diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6a5ab1991..fcd0b26c5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -14,19 +14,22 @@ on: - dev - preview - v* + paths: + - "src/**" + - ".github/workflows/**" -env: - NugetApiKey: ${{secrets.NUGETAPIKEY}} - TwitterConsumerKey: ${{secrets.TWITTER_CONSUMER_KEY}} - TwitterConsumerSecret: ${{secrets.TWITTER_CONSUMER_SECRET}} - TwitterAccessToken: ${{secrets.TWITTER_ACCESS_TOKEN}} - TwitterAccessTokenSecret: ${{secrets.TWITTER_ACCESS_TOKEN_SECRET}} - DiscordToken: ${{secrets.DISCORD_TOKEN}} - DiscordGuildId: '679761126598115336' - DiscordChannelId: '803717285986566174' - MastodonClientId: ${{secrets.MASTODON_CLIENT_ID}} - MastodonClientSecret: ${{secrets.MASTODON_CLIENT_SECRET}} - MastodonInstance: 'dotnet.social' +#env: +# NugetApiKey: ${{secrets.NUGETAPIKEY}} +# TwitterConsumerKey: ${{secrets.TWITTER_CONSUMER_KEY}} +# TwitterConsumerSecret: ${{secrets.TWITTER_CONSUMER_SECRET}} +# TwitterAccessToken: ${{secrets.TWITTER_ACCESS_TOKEN}} +# TwitterAccessTokenSecret: ${{secrets.TWITTER_ACCESS_TOKEN_SECRET}} +# DiscordToken: ${{secrets.DISCORD_TOKEN}} +# DiscordGuildId: '679761126598115336' +# DiscordChannelId: '803717285986566174' +# MastodonClientId: ${{secrets.MASTODON_CLIENT_ID}} +# MastodonClientSecret: ${{secrets.MASTODON_CLIENT_SECRET}} +# MastodonInstance: 'dotnet.social' jobs: build: @@ -50,10 +53,16 @@ jobs: architecture: x64 - name: Add .NET Workloads - run: dotnet workload install maui-ios maui-android maui-maccatalyst maui-windows + run: dotnet workload install maui - name: Build - run: dotnet run --project build/ShinyBuild.csproj + run: dotnet build Build.slnf /restore -m -property:Configuration=Release -property:PublicRelease=true + + - name: Post NuGet Artifacts + uses: actions/upload-artifact@v2 + with: + name: nuget-artifacts + path: '**/*.nupkg' - name: Publish Artifacts uses: actions/upload-artifact@v3 @@ -61,3 +70,33 @@ jobs: name: nugets path: ${{ github.workspace }}/artifacts retention-days: 5 + + - name: Publish NuGets + if: ${{ github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/v') }} + run: dotnet nuget push **\*.nupkg --source https://api.nuget.org/v3/index.json --api-key ${{ secrets.NUGETAPIKEY }} --skip-duplicate + + - name: Install NerdBank.GitVersioning CLI + if: ${{ github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/v') }} + run: dotnet tool install -g nbgv + + - name: Get Nuget Version from Nerdbank + run: nbgv get-version + + #https://shinylib.net/release-notes/mobile/ + #this.GitVersioningGetVersion().NuGetPackageVersion - Nerdbank versioning in cake + - name: Announce to Mastodon + if: ${{ github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/v') }} + uses: cbrgm/mastodon-github-action@v2 + with: + access-token: ${{ secrets.MASTODON_ACCESS_TOKEN }} # access token + url: ${{ secrets.MASTODON_URL }} + message: "Hello from GitHub Actions!" + + - name: 'Announce to X/Twitter' + uses: ethomson/send-tweet-action@v1 + with: + status: "Hi, this is a test!" + consumer-key: ${{ secrets.TWITTER_CONSUMER_API_KEY }} + consumer-secret: ${{ secrets.TWITTER_CONSUMER_API_SECRET }} + access-token: ${{ secrets.TWITTER_ACCESS_TOKEN }} + access-token-secret: ${{ secrets.TWITTER_ACCESS_TOKEN_SECRET }} \ No newline at end of file diff --git a/Shiny.sln b/Shiny.sln index 53e43db32..b7e589803 100644 --- a/Shiny.sln +++ b/Shiny.sln @@ -82,8 +82,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Shiny.Push.AzureNotificatio EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shiny.Net.Http", "src\Shiny.Net.Http\Shiny.Net.Http.csproj", "{DA452A0B-08F8-4809-95F4-9CD583F30FEA}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ShinyBuild", "build\ShinyBuild.csproj", "{452F676E-22B7-49A6-9603-D39689F0EAAD}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Shiny.Support.Repositories", "src\Shiny.Support.Repositories\Shiny.Support.Repositories.csproj", "{47A57CFE-A1A8-407A-86FA-FA003D562C58}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shiny.Tests", "tests\Shiny.Tests\Shiny.Tests.csproj", "{B145321D-8E33-4A33-B5CF-37A162C0E261}" @@ -192,10 +190,6 @@ Global {DA452A0B-08F8-4809-95F4-9CD583F30FEA}.Debug|Any CPU.Build.0 = Debug|Any CPU {DA452A0B-08F8-4809-95F4-9CD583F30FEA}.Release|Any CPU.ActiveCfg = Release|Any CPU {DA452A0B-08F8-4809-95F4-9CD583F30FEA}.Release|Any CPU.Build.0 = Release|Any CPU - {452F676E-22B7-49A6-9603-D39689F0EAAD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {452F676E-22B7-49A6-9603-D39689F0EAAD}.Debug|Any CPU.Build.0 = Debug|Any CPU - {452F676E-22B7-49A6-9603-D39689F0EAAD}.Release|Any CPU.ActiveCfg = Release|Any CPU - {452F676E-22B7-49A6-9603-D39689F0EAAD}.Release|Any CPU.Build.0 = Release|Any CPU {47A57CFE-A1A8-407A-86FA-FA003D562C58}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {47A57CFE-A1A8-407A-86FA-FA003D562C58}.Debug|Any CPU.Build.0 = Debug|Any CPU {47A57CFE-A1A8-407A-86FA-FA003D562C58}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -371,7 +365,6 @@ Global {F80BF383-347B-492D-87D2-D566D80AFFC7} = {6374E4D9-1BD8-4880-B603-AFDEA8345D7E} {A4FAACE2-CE11-415C-8886-97A9A52FB35C} = {6374E4D9-1BD8-4880-B603-AFDEA8345D7E} {DA452A0B-08F8-4809-95F4-9CD583F30FEA} = {6374E4D9-1BD8-4880-B603-AFDEA8345D7E} - {452F676E-22B7-49A6-9603-D39689F0EAAD} = {3A15354E-BAD2-4195-BE6B-49ED2B4E56E6} {47A57CFE-A1A8-407A-86FA-FA003D562C58} = {6374E4D9-1BD8-4880-B603-AFDEA8345D7E} {B145321D-8E33-4A33-B5CF-37A162C0E261} = {7C114E37-36C8-4971-91C6-E2557DDCB4E8} {2E4505D4-B9B3-4836-A0F8-37BA72025D3D} = {6374E4D9-1BD8-4880-B603-AFDEA8345D7E} diff --git a/build/BuildContext.cs b/build/BuildContext.cs deleted file mode 100644 index f1cb3eee7..000000000 --- a/build/BuildContext.cs +++ /dev/null @@ -1,86 +0,0 @@ -using Cake.Frosting; -using Cake.Git; -using Cake.Common; -using Cake.Common.Build; -using Cake.Core; -using Cake.Core.IO; -using Cake.Core.Diagnostics; -using Cake.GitVersioning; - -namespace ShinyBuild; - - -public class BuildContext : FrostingContext -{ - public BuildContext(ICakeContext context) : base(context) - { -#if DEBUG - //walk backwards until git directory found -that's root - if (!context.GitIsValidRepository(context.Environment.WorkingDirectory)) - { - var dir = new DirectoryPath("."); - while (!context.GitIsValidRepository(dir)) - dir = new DirectoryPath(Directory.GetParent(dir.FullPath).FullName); - - context.Environment.WorkingDirectory = dir; - } -#endif - this.Branch = context.GitBranchCurrent("."); - - this.ReleaseVersion = this.GitVersioningGetVersion().NuGetPackageVersion; - this.Log.Information("NUGET PACKAGE VERSION: " + this.ReleaseVersion); - } - - - public string ReleaseVersion { get; } - //public bool UseXamarinPreview => this.HasArgumentOrEnvironment("UseXamarinPreview"); - public string GitHubSecretToken => this.ArgumentOrEnvironment("GITHUB_TOKEN"); - public string OperatingSystemString => this.Environment.Platform.Family == PlatformFamily.Windows ? "WINDOWS_NT" : "MAC"; - public string MsBuildConfiguration => this.ArgumentOrEnvironment("configuration", Constants.DefaultBuildConfiguration); - public string NugetApiKey => this.ArgumentOrEnvironment("NugetApiKey"); - public bool AllowNugetUploadFailures => this.ArgumentOrEnvironment("AllowNugetUploadFailures", false); - public GitBranch Branch { get; } - - public T ArgumentOrEnvironment(string name, T defaultValue = default) - => this.HasArgument(name) ? this.Argument(name) : this.EnvironmentVariable(name, defaultValue); - - public bool HasArgumentOrEnvironment(string name) - => this.HasArgument(name) || this.HasEnvironmentVariable(name); - - public string ArtifactDirectory - { - get - { - if (this.IsRunningInCI) - return this.GitHubActions().Environment.Workflow.Workspace + "/artifacts"; - - return System.IO.Path.Combine(this.Environment.WorkingDirectory.FullPath, "artifacts"); - } - } - - public bool IsReleaseBranch => this.Branch.FriendlyName.ToLower().StartsWith("v"); - - - public bool IsPullRequest => - this.IsRunningInCI && - this.GitHubActions().Environment.PullRequest.IsPullRequest; - - public bool IsRunningInCI - => this.GitHubActions()?.IsRunningOnGitHubActions ?? false; - - - public bool IsNugetDeployBranch - { - get - { - if (this.IsPullRequest) - return false; - - var bn = this.Branch.FriendlyName.ToLower(); - return bn.Equals("main") || bn.Equals("master") || bn.Equals("preview") || bn.StartsWith("v"); - } - } - - - public bool IsDocsDeployBranch => this.IsNugetDeployBranch && !this.IsPullRequest; -} \ No newline at end of file diff --git a/build/Constants.cs b/build/Constants.cs deleted file mode 100644 index d625ff4c0..000000000 --- a/build/Constants.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace ShinyBuild; - -public static class Constants -{ - public const string DefaultBuildConfiguration = "Release"; -} diff --git a/build/Extensions.cs b/build/Extensions.cs deleted file mode 100644 index ba55aeafa..000000000 --- a/build/Extensions.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Cake.Core; -using Cake.Core.IO; - -namespace ShinyBuild; - -public static class Extensions -{ - public static IProcess Execute(this ICakeContext context, FilePath exe, string args) => - context.ProcessRunner.Start( - exe, - new ProcessSettings - { - Arguments = ProcessArgumentBuilder.FromString(args) - } - ); -} \ No newline at end of file diff --git a/build/Program.cs b/build/Program.cs deleted file mode 100644 index 26d0d02e4..000000000 --- a/build/Program.cs +++ /dev/null @@ -1,15 +0,0 @@ -using Cake.Frosting; - -namespace ShinyBuild; - - -class Program -{ - //https://cakebuild.net/docs/running-builds/runners/cake-frosting#bootstrapping-for-cake-frosting - public static int Main(string[] args) - => new CakeHost() - .UseContext() - //.UseLifetime() - //.InstallTool(new Uri("dotnet:n?package=GitVersion.Tool&version=5.6.9")) - .Run(args); -} diff --git a/build/Properties/launchSettings.json b/build/Properties/launchSettings.json deleted file mode 100644 index 33504c948..000000000 --- a/build/Properties/launchSettings.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "profiles": { - "WSL": { - "commandName": "WSL2", - "distributionName": "" - } - } -} \ No newline at end of file diff --git a/build/ShinyBuild.csproj b/build/ShinyBuild.csproj deleted file mode 100644 index 83cb0ca70..000000000 --- a/build/ShinyBuild.csproj +++ /dev/null @@ -1,22 +0,0 @@ - - - - Exe - net7.0 - latest - enable - enable - - - - - - - - - - - - - - \ No newline at end of file diff --git a/build/Tasks/DefaultTask.cs b/build/Tasks/DefaultTask.cs deleted file mode 100644 index eabc39192..000000000 --- a/build/Tasks/DefaultTask.cs +++ /dev/null @@ -1,12 +0,0 @@ -using Cake.Frosting; -using ShinyBuild.Tasks.Library; - -namespace ShinyBuild.Tasks; - - -[TaskName("Default")] -[IsDependentOn(typeof(CopyArtifactsTask))] -[IsDependentOn(typeof(NugetDeployTask))] -[IsDependentOn(typeof(ReleaseAnnouncementTask))] -//[IsDependentOn(typeof(GitHubReleaseTask))] -public sealed class DefaultTarget : FrostingTask { } diff --git a/build/Tasks/Library/BuildTask.cs b/build/Tasks/Library/BuildTask.cs deleted file mode 100644 index 00f37df2c..000000000 --- a/build/Tasks/Library/BuildTask.cs +++ /dev/null @@ -1,35 +0,0 @@ -using Cake.Common; -using Cake.Common.IO; -using Cake.Common.Tools.MSBuild; -using Cake.Frosting; - -namespace ShinyBuild.Tasks.Library; - - -[TaskName("Build")] -public sealed class BuildTask : FrostingTask -{ - // needs to be windows build for UWP - public override bool ShouldRun(BuildContext context) => context.IsRunningOnWindows(); - - - public override void Run(BuildContext context) - { - context.CleanDirectories($"./src/**/obj/"); - context.CleanDirectories($"./src/**/bin/{context.MsBuildConfiguration}"); - - //context.MSBuild("Shiny.sln", x => x - context.MSBuild("Build.slnf", x => x - .WithRestore() - //.SetMSBuildPlatform(MSBuildPlatform.Automatic) - //.UseToolVersion(MSBuildToolVersion.VS2022) - //.UseToolVersion("17.7") - .WithTarget("Clean") - .WithTarget("Build") - .WithProperty("PublicRelease", "true") - .WithProperty("CI", context.IsRunningInCI.ToString()) - .WithProperty("OS", context.OperatingSystemString) - .SetConfiguration(context.MsBuildConfiguration) - ); - } -} \ No newline at end of file diff --git a/build/Tasks/Library/CopyArtifactsTask.cs b/build/Tasks/Library/CopyArtifactsTask.cs deleted file mode 100644 index 1d83f69fd..000000000 --- a/build/Tasks/Library/CopyArtifactsTask.cs +++ /dev/null @@ -1,21 +0,0 @@ -using Cake.Common.IO; -using Cake.Frosting; - -namespace ShinyBuild.Tasks.Library; - - -[IsDependentOn(typeof(BuildTask))] -public class CopyArtifactsTask : FrostingTask -{ - public override void Run(BuildContext context) - { - var directory = context.Directory(context.ArtifactDirectory); - if (Directory.Exists(directory.Path.FullPath)) - context.CleanDirectory(directory); - else - Directory.CreateDirectory(directory.Path.FullPath); - - context.CopyFiles("src/**/*.nupkg", directory); - context.CopyFiles("src/**/*.snupkg", directory); - } -} diff --git a/build/Tasks/Library/GitHubReleaseTask.cs b/build/Tasks/Library/GitHubReleaseTask.cs deleted file mode 100644 index a0385af43..000000000 --- a/build/Tasks/Library/GitHubReleaseTask.cs +++ /dev/null @@ -1,41 +0,0 @@ -//using Cake.Frosting; -//using Cake.GitVersioning; -//using Octokit; - -//namespace ShinyBuild.Tasks.Library; - - -//[IsDependentOn(typeof(NugetDeployTask))] -//public class GitHubReleaseTask : AsyncFrostingTask -//{ -// public override bool ShouldRun(BuildContext context) => context.IsReleaseBranch && context.IsRunningInCI; - - -// public override async Task RunAsync(BuildContext context) -// { -// var client = new GitHubClient(new ProductHeaderValue("ShinyRelease")) -// { -// Credentials = new Credentials(context.GitHubSecretToken) -// }; - -// //https://octokitnet.readthedocs.io/en/latest/releases/#upload-assets -// var release = new NewRelease("v" + context.ReleaseVersion); -// release.Name = "v" + context.ReleaseVersion; -// release.Body = this.GetReleaseNotes(context); -// release.Draft = false; -// release.Prerelease = false; -// var result = await client.Repository.Release.Create("shinyorg", "shiny", release); -// } - - -// string GetReleaseNotes(BuildContext context) -// { -// var v = context.GitVersioningGetVersion(); -// var path = $"./docs/Input/release-notes/v{v.VersionMajor}.{v.VersionMinor}.{v.VersionRevision}.md"; -// if (!File.Exists(path)) -// { -// // TODO: exception? -// } -// return File.ReadAllText(path); -// } -//} diff --git a/build/Tasks/Library/NugetDeployTask.cs b/build/Tasks/Library/NugetDeployTask.cs deleted file mode 100644 index 66ec96d43..000000000 --- a/build/Tasks/Library/NugetDeployTask.cs +++ /dev/null @@ -1,51 +0,0 @@ -using Cake.Common.IO; -using Cake.Common.Tools.DotNet; -using Cake.Common.Tools.DotNet.NuGet.Push; -using Cake.Frosting; - -namespace ShinyBuild.Tasks.Library; - - -[TaskName("NugetDeploy")] -[IsDependentOn(typeof(BuildTask))] -//[IsDependeeOf(typeof(BasicTestsTask))] -public sealed class NugetDeployTask : FrostingTask -{ - const string MainNuget = "https://api.nuget.org/v3/index.json"; - - public override bool ShouldRun(BuildContext context) - { - var result = context.IsNugetDeployBranch && context.IsRunningInCI; - if (result && String.IsNullOrWhiteSpace(context.NugetApiKey)) - throw new ArgumentException("NugetApiKey is missing"); - - return result; - } - - - public override void Run(BuildContext context) - { - var settings = new DotNetNuGetPushSettings - { - ApiKey = context.NugetApiKey, - Source = MainNuget, - SkipDuplicate = true - }; - - var packages = context.GetFiles("src/**/*.nupkg"); - foreach (var package in packages) - { - //try - //{ - context.DotNetNuGetPush(package.FullPath, settings); - //} - //catch (Exception ex) - //{ - // if (context.AllowNugetUploadFailures) - // context.Error($"Error Upload: {package.FullPath} - Exception: {ex}"); - // else - // throw; // break build - //} - } - } -} diff --git a/build/Tasks/Library/ReleaseAnnouncementTask.cs b/build/Tasks/Library/ReleaseAnnouncementTask.cs deleted file mode 100644 index 213f0df2f..000000000 --- a/build/Tasks/Library/ReleaseAnnouncementTask.cs +++ /dev/null @@ -1,144 +0,0 @@ -using Cake.Core.Diagnostics; -using Cake.Frosting; -using Discord; -using Discord.WebSocket; -using Mastonet; -using Mastonet.Entities; -using Tweetinvi; - -namespace ShinyBuild.Tasks.Library; - - -[IsDependentOn(typeof(NugetDeployTask))] -public class ReleaseAnnouncementTask : AsyncFrostingTask -{ - // const string DocLink = "https://shinylib.net/release-notes/mobile/"; - - public override bool ShouldRun(BuildContext context) - => context.IsRunningInCI && context.Branch.FriendlyName.Contains("v3"); - - - public override Task RunAsync(BuildContext context) - { - //var link = GetLink(context); - //var message = $"Shiny {context.ReleaseVersion} released! Check out the latest release notes here - {link}"; - var message = $"Shiny {context.ReleaseVersion} released! Check out the latest info @ https://shinylib.net"; - - return Task.WhenAll( - this.Twitter(context, message), - this.Discord(context, message), - this.Mastodon(context, message) - ); - } - - - //static string GetLink(BuildContext context) - //{ - // if (!context.IsReleaseBranch) - // return $"{DocLink}vnext.html"; - - // var ver = context.ReleaseVersion.Replace(".", String.Empty); - // if (!ver.StartsWith("v")) - // ver = "v" + ver; - - // return $"{DocLink}{ver}.html"; - //} - - - async Task Twitter(BuildContext context, string message) - { - try - { - context.Log.Information("Attempting to publish to Twitter"); - - var consumerKey = context.ArgumentOrEnvironment("TwitterConsumerKey"); - var consumerSecret = context.ArgumentOrEnvironment("TwitterConsumerSecret"); - var accessToken = context.ArgumentOrEnvironment("TwitterAccessToken"); - var accessTokenSecret = context.ArgumentOrEnvironment("TwitterAccessTokenSecret"); - var client = new TwitterClient( - consumerKey, - consumerSecret, - accessToken, - accessTokenSecret - ); - - await client.Tweets.PublishTweetAsync(message); - - context.Log.Information("Tweet Published - " + message); - } - catch (Exception ex) - { - // don't fail the build because of a failed tweet - context.Log.Error($"Error publishing release Tweet - {ex}"); - } - } - - - async Task Mastodon(BuildContext context, string message) - { - try - { - context.Log.Information("Attempting to publish to Mastodon"); - - var clientId = context.ArgumentOrEnvironment("MastodonClientId"); - var clientSecret = context.ArgumentOrEnvironment("MastodonClientSecret"); - var instance = context.ArgumentOrEnvironment("MastodonClientSecret") ?? "dotnet.social"; - - var appReg = new AppRegistration - { - Instance = instance, - ClientId = clientId, - ClientSecret = clientSecret - }; - var authClient = new AuthenticationClient(appReg); - var auth = await authClient.CreateApp("ShinyBot", Scope.Write); - - var client = new MastodonClient(auth.Instance, authClient.AccessToken); - await client.PublishStatus(message, Visibility.Public); - - context.Log.Information("Toot Published - " + message); - } - catch (Exception ex) - { - context.Log.Error($"Error publishing release Toot - {ex}"); - } - } - - - async Task Discord(BuildContext context, string message) - { - try - { - context.Log.Information("Attempting to publish Discord message"); - - var discordToken = context.ArgumentOrEnvironment("DiscordToken"); - var discordGuildId = context.ArgumentOrEnvironment("DiscordGuildId"); - var discordChannel = context.ArgumentOrEnvironment("DiscordChannelId"); // 803717285986566174 - #shinylib on sponsorconnect - - var client = new DiscordSocketClient(); - await client.LoginAsync(TokenType.Bot, discordToken, true); - await client.StartAsync(); - SocketGuild? guild = null; - var count = 0; - while (guild == null) - { - guild = client.GetGuild(discordGuildId); - await Task.Delay(2000); - count++; - if (count == 5) - throw new ArgumentException("Could not retrieve guild"); - } - - await guild - .TextChannels - .First(x => x.Id == discordChannel) - .SendMessageAsync(message); - - context.Log.Information("Discord Message Published"); - } - catch (Exception ex) - { - context.Log.Error($"Error publishing release message to Discord - {ex}"); - } - } -}