diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index c28383f..53a2966 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -23,6 +23,6 @@ jobs: with: dotnet-version: 8.0.x - name: Pack - run: ./build.sh "pack --version=$RELEASE_VERSION" + run: ./build.sh pack -rv $RELEASE_VERSION - name: Push run: dotnet nuget push ./artifacts/*.nupkg -s https://api.nuget.org/v3/index.json -k ${{ secrets.NUGET }} diff --git a/build/Program.cs b/build/Program.cs index d834548..7e78bc2 100644 --- a/build/Program.cs +++ b/build/Program.cs @@ -1,241 +1,184 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading.Tasks; +using Bullseye; + +using McMaster.Extensions.CommandLineUtils; using static Bullseye.Targets; using static SimpleExec.Command; -namespace targets; +const string Solution = "microwf.sln"; +IList packableProjects = new List{ + "microwf.Core", + "microwf.Domain", + "microwf.Infrastructure", + "microwf.AspNetCoreEngine" +}; -internal static class Program +var app = new CommandLineApplication { - private const string solution = "microwf.sln"; - private const string packOutput = "./artifacts"; - private const string nugetSource = "https://api.nuget.org/v3/index.json"; - private const string envVarMissing = " environment variable is missing. Aborting."; - - private static IList packableProjects = new List{ - "microwf.Core", - "microwf.Domain", - "microwf.Infrastructure", - "microwf.AspNetCoreEngine" - }; - - private static class Targets - { - public const string RestoreTools = "restore-tools"; - public const string AddChangelog = "add-changelog"; - public const string CleanBuildOutput = "clean-build-output"; - public const string CleanPackOutput = "clean-pack-output"; - public const string Build = "build"; - public const string Test = "test"; - public const string UpdateChangelog = "update-changelog"; - public const string Release = "release"; - public const string Pack = "pack"; - public const string Deploy = "deploy"; - public const string DeployWebClient = "deploy-webclient"; - } - - static async Task Main(string[] args) - { - // TODO: encapsulate with sth. like McMaster.Extensions.CommandLineUtils - var version = string.Empty; - var key = string.Empty; - - if (args[0].Contains("--")) - { - var firstArg = args[0].Split("--")[0].Trim(); - var customArgs = args[0].Split("--")[1].Trim().Split("&"); + UsePagerForHelpText = false +}; +app.HelpOption(); - if (customArgs.Any(x => x.Contains("version"))) - { - var versionArgs = customArgs.First(x => x.Contains("version")); - version = versionArgs.Split('=')[1].Trim(); - } +// 1. define custom options +var versionOption = app.Option("-rv|--release-version", "Release version that should be applied to the released artifacts.", CommandOptionType.SingleValue); - if (customArgs.Any(x => x.Contains("key"))) - { - var keyArgs = customArgs.First(x => x.Contains("key")); - key = keyArgs.Split('=')[1].Trim(); - } +// 2. translate from Bullseye to McMaster.Extensions.CommandLineUtils +app.Argument("targets", "A list of targets to run or list. If not specified, the \"default\" target will be run, or all targets will be listed.", true); +foreach (var (aliases, description) in Options.Definitions) +{ + _ = app.Option(string.Join("|", aliases), description, CommandOptionType.NoValue); +} - args[0] = firstArg; - } +app.OnExecuteAsync(async _ => +{ + // translate from McMaster.Extensions.CommandLineUtils to Bullseye + var targets = app.Arguments[0].Values.OfType(); + var options = new Options(Options.Definitions + .Select(d => (d.Aliases[0], app.Options + .Single(o => d.Aliases.Contains($"--{o.LongName}")).HasValue()) + )); + + #region Tooling targets + const string RestoreTools = "restore-tools"; + const string AddChangelog = "add-changelog"; + + Target(RestoreTools, () => + { + Run("dotnet", "tool restore"); + }); - if (!string.IsNullOrWhiteSpace(version)) - { - Console.WriteLine($"Using version: '{version}'" + Environment.NewLine); - } + Target(AddChangelog, () => + { + Run("dotnet", "tool run releasy add-changelog", "changelogs"); + }); + #endregion - #region Local build targets - Target(Targets.RestoreTools, () => - { - Run("dotnet", "tool restore"); - }); + #region Build targets + const string Clean = "clean"; + const string Build = "build"; + const string Test = "test"; + const string Release = "release"; - Target(Targets.AddChangelog, () => - { - Run("dotnet", "tool run releasy add-changelog", "changelogs"); - }); + Target(Clean, () => + { + Run("dotnet", $"clean {Solution} -c Release -v m --nologo"); + }); - Target(Targets.CleanBuildOutput, () => - { - Run("dotnet", $"clean {solution} -c Release -v m --nologo"); - }); + Target(Build, DependsOn(Clean), () => + { + Run("dotnet", $"build {Solution} -c Release --nologo"); + }); - Target(Targets.Build, DependsOn(Targets.CleanBuildOutput), () => - { - Run("dotnet", $"build {solution} -c Release --nologo"); - }); + Target(Test, DependsOn(Build), () => + { + Run("dotnet", $"test {Solution} -c Release --no-build --nologo"); + }); - Target(Targets.Test, DependsOn(Targets.Build), () => + Target(Release, DependsOn(Test), () => + { + if (string.IsNullOrWhiteSpace(versionOption.Value())) { - Run("dotnet", $"test {solution} -c Release --no-build --nologo"); - }); + throw new TargetFailedException("Version for updating changelog is missing!"); + } - Target(Targets.UpdateChangelog, () => - { - if (string.IsNullOrWhiteSpace(version)) - { - throw new Bullseye.TargetFailedException("Version for updating changelog is missing!"); - } + var version = versionOption.Value(); + Console.WriteLine($"Releasing version: '{version}'"); - // updating the changelog - Run("dotnet", $"tool run releasy update-changelog -v {version} -p https://github.com/thomasduft/microwf/issues/"); + // updating the changelog + Run("dotnet", $"tool run releasy update-changelog -v {version} -p https://github.com/thomasduft/microwf/issues/"); - // committing the changelog changes - Run("git", $"commit -am \"Committing changelog changes for v'{version}'\""); - }); + // committing the changelog changes + Run("git", $"commit -am \"Committing changelog changes for v{version}\""); - Target(Targets.Release, DependsOn(Targets.RestoreTools, Targets.Test, Targets.UpdateChangelog), () => - { - if (string.IsNullOrWhiteSpace(version)) - { - throw new Bullseye.TargetFailedException("Version for updating changelog is missing!"); - } + // applying the tag + Run("git", $"tag -a v{version} -m \"version '{version}'\""); - // applying the tag - Run("git", $"tag -a v{version} -m \"version '{version}'\""); + // pushing + Run("git", $"push origin v{version}"); + }); + #endregion - // pushing - Run("git", $"push origin v{version}"); - }); - #endregion + #region Deployment targets + const string ArtifactsDirectory = "./artifacts"; + const string CleanArtifacts = "clean-artifacts"; + const string Pack = "pack"; - #region Deployment targets - Target(Targets.CleanPackOutput, () => + Target(CleanArtifacts, () => + { + if (Directory.Exists(ArtifactsDirectory)) { - if (Directory.Exists(packOutput)) - { - Directory.Delete(packOutput, true); - } - }); + Directory.Delete(ArtifactsDirectory, true); + } + }); - Target(Targets.Pack, DependsOn(Targets.Build, Targets.CleanPackOutput), () => + Target(Pack, DependsOn(Build, CleanArtifacts), () => + { + if (string.IsNullOrWhiteSpace(versionOption.Value())) { - if (string.IsNullOrWhiteSpace(version)) - { - throw new Bullseye.TargetFailedException("Version for packaging is missing!"); - } - - // pack packages - var directory = Directory.CreateDirectory(packOutput).FullName; - var projects = GetFiles("src", $"*.csproj"); - foreach (var project in projects) - { - if (project.Contains(".Tests")) - continue; + throw new TargetFailedException("Version for packaging is missing!"); + } - if (packableProjects.Any(m => project.Contains(m))) - { - Run("dotnet", $"pack {project} -c Release -p:PackageVersion={version} -p:Version={version} -o {directory} --no-build --nologo"); - } - } - }); + var version = versionOption.Value(); + Console.WriteLine($"Pack for version: '{version}'"); - Target(Targets.Deploy, DependsOn(Targets.RestoreTools, Targets.Test, Targets.Pack), () => + // pack packages + var directory = Directory.CreateDirectory(ArtifactsDirectory).FullName; + var projects = GetFiles("src", $"*.csproj"); + foreach (var project in projects) { - if (string.IsNullOrWhiteSpace(key)) - { - throw new Bullseye.TargetFailedException("Key for deploying is missing!"); - } + if (project.Contains(".Tests")) + continue; - // push packages - var directory = Directory.CreateDirectory(packOutput).FullName; - var packages = GetFiles(directory, $"*.nupkg"); - foreach (var package in packages) + if (packableProjects.Any(m => project.Contains(m))) { - Run("dotnet", $"nuget push {package} -s {nugetSource} -k {key}"); + Run("dotnet", $"pack {project} -c Release -p:PackageVersion={version} -p:Version={version} -o {directory} --no-build --nologo"); } - }); - #endregion - - #region Make life easier targets - Target(Targets.DeployWebClient, () => - { - Run("npm", "install", "samples/WebClient"); - Run("npm", "run publish", "samples/WebClient"); + } + }); + #endregion - // delete all files, not directories in samples/WebApi/wwwroot - var files = Directory.GetFiles("samples/WebApi/wwwroot"); - foreach (var file in files) - { - File.Delete(file); - } + await RunTargetsAndExitAsync(targets, options); +}); - // copy files of samples/WebClient/dist to samples/WebApi/wwwroot - CopyDirectory("samples/WebClient/dist", "samples/WebApi/wwwroot"); +return await app.ExecuteAsync(args); - // care about special assets - CopyDirectory("samples/WebClient/dist/assets/js", "samples/WebApi/wwwroot/assets/js"); - }); - #endregion +#region Helpers +static IEnumerable GetFiles( + string directoryToScan, + string filter +) +{ + List files = new(); - await RunTargetsAndExitAsync( - args, - ex => ex is SimpleExec.ExitCodeException - || ex.Message.EndsWith(envVarMissing, StringComparison.InvariantCultureIgnoreCase) - ); - } + files.AddRange(Directory.GetFiles( + directoryToScan, + filter, + SearchOption.AllDirectories + )); - private static IEnumerable GetFiles( - string directoryToScan, - string filter - ) - { - List files = new List(); + return files; +} - files.AddRange(Directory.GetFiles( - directoryToScan, - filter, - SearchOption.AllDirectories - )); +static void CopyDirectory(string sourceDir, string destinationDir, bool recursive = false) +{ + var dir = new DirectoryInfo(sourceDir); + if (!dir.Exists) + throw new DirectoryNotFoundException($"Source directory not found: {dir.FullName}"); - return files; + foreach (FileInfo file in dir.GetFiles()) + { + Directory.CreateDirectory(destinationDir); + string targetFilePath = Path.Combine(destinationDir, file.Name); + file.CopyTo(targetFilePath, true); } - static void CopyDirectory(string sourceDir, string destinationDir, bool recursive = false) + if (recursive) { - var dir = new DirectoryInfo(sourceDir); - if (!dir.Exists) - throw new DirectoryNotFoundException($"Source directory not found: {dir.FullName}"); - - foreach (FileInfo file in dir.GetFiles()) + foreach (DirectoryInfo subDir in dir.GetDirectories()) { - Directory.CreateDirectory(destinationDir); - string targetFilePath = Path.Combine(destinationDir, file.Name); - file.CopyTo(targetFilePath, true); - } - - if (recursive) - { - foreach (DirectoryInfo subDir in dir.GetDirectories()) - { - string newDestinationDir = Path.Combine(destinationDir, subDir.Name); - CopyDirectory(subDir.FullName, newDestinationDir, true); - } + string newDestinationDir = Path.Combine(destinationDir, subDir.Name); + CopyDirectory(subDir.FullName, newDestinationDir, true); } } -} \ No newline at end of file +} +#endregion diff --git a/build/targets.csproj b/build/targets.csproj index 8c3a2f8..b63dc12 100644 --- a/build/targets.csproj +++ b/build/targets.csproj @@ -3,10 +3,13 @@ net8.0 Exe + + enable + \ No newline at end of file