From 3f706820a461685dbf619492952049e243b863e6 Mon Sep 17 00:00:00 2001 From: Declan Smith Date: Sat, 4 Jan 2025 23:46:05 +1000 Subject: [PATCH 1/6] feat(cli): add interactive mode support for user input during builds Introduced `InteractiveArg` for enabling interactive mode in the CLI. Added `HasInteractive` property in `CommandLineArgs` to detect the `-i/--interactive` argument. Extended `ParamService` to prompt users for parameter inputs when in interactive mode. Adjusted `BuildExecutor` to handle execution flow for interactive and non-interactive modes. Unit tests updated to include support for `IAnsiConsole`. --- .../ClassTests/Params/ParamServiceTests.cs | 33 +++++++------ DecSm.Atom/Args/CommandLineArgs.cs | 6 +++ DecSm.Atom/Args/CommandLineArgsParser.cs | 1 + DecSm.Atom/Args/IArg.cs | 7 +++ DecSm.Atom/Build/BuildExecutor.cs | 49 +++++++++++++------ DecSm.Atom/Params/ParamService.cs | 24 ++++++++- 6 files changed, 90 insertions(+), 30 deletions(-) diff --git a/DecSm.Atom.Tests/ClassTests/Params/ParamServiceTests.cs b/DecSm.Atom.Tests/ClassTests/Params/ParamServiceTests.cs index ea3abeb1..955e9bc5 100644 --- a/DecSm.Atom.Tests/ClassTests/Params/ParamServiceTests.cs +++ b/DecSm.Atom.Tests/ClassTests/Params/ParamServiceTests.cs @@ -10,13 +10,14 @@ public void Setup() _buildDefinition = A.Fake(); _args = new(true, Array.Empty()); _config = A.Fake(); + _console = A.Fake(); _vaultProviders = new List { A.Fake(), }; - _paramService = new(_buildDefinition, _args, _config, _vaultProviders); + _paramService = new(_buildDefinition, _args, _console, _config, _vaultProviders); } [TearDown] @@ -26,6 +27,7 @@ public void TearDown() => private IBuildDefinition _buildDefinition; private CommandLineArgs _args; private IConfiguration _config; + private IAnsiConsole _console; private IEnumerable _vaultProviders; private ParamService _paramService; @@ -51,7 +53,7 @@ public void GetParam_WithExpression_ReturnsExpectedValue() }) .Build(); - _paramService = new(_buildDefinition, _args, _config, _vaultProviders); + _paramService = new(_buildDefinition, _args, _console, _config, _vaultProviders); A .CallTo(() => _buildDefinition.ParamDefinitions) @@ -87,7 +89,7 @@ public void GetParam_WithString_ReturnsExpectedValue() }) .Build(); - _paramService = new(_buildDefinition, _args, _config, _vaultProviders); + _paramService = new(_buildDefinition, _args, _console, _config, _vaultProviders); A .CallTo(() => _buildDefinition.ParamDefinitions) @@ -123,7 +125,7 @@ public void GetParam_WithEnvironmentVariable_ReturnsExpectedValue() }) .Build(); - _paramService = new(_buildDefinition, _args, _config, _vaultProviders); + _paramService = new(_buildDefinition, _args, _console, _config, _vaultProviders); A .CallTo(() => _buildDefinition.ParamDefinitions) @@ -156,7 +158,7 @@ public void GetParam_WithVaultValue_ReturnsExpectedValue() var vaultProvider = A.Fake(); _config = new ConfigurationBuilder().Build(); - _paramService = new(_buildDefinition, _args, _config, [vaultProvider]); + _paramService = new(_buildDefinition, _args, _console, _config, [vaultProvider]); A .CallTo(() => _buildDefinition.ParamDefinitions) @@ -191,7 +193,7 @@ public void GetParam_WithVaultValueButNotSecret_ReturnsDefaultValue() var vaultProvider = A.Fake(); _config = new ConfigurationBuilder().Build(); - _paramService = new(_buildDefinition, _args, _config, [vaultProvider]); + _paramService = new(_buildDefinition, _args, _console, _config, [vaultProvider]); A .CallTo(() => _buildDefinition.ParamDefinitions) @@ -225,7 +227,7 @@ public void MaskSecrets_WithSecretsInText_MasksSecrets() }; _config = new ConfigurationBuilder().Build(); - _paramService = new(_buildDefinition, _args, _config, _vaultProviders); + _paramService = new(_buildDefinition, _args, _console, _config, _vaultProviders); A .CallTo(() => _buildDefinition.ParamDefinitions) @@ -261,8 +263,9 @@ public void MaskSecrets_WithSecretsInTextButNotSecretAttribute_DoesNotMaskSecret Sources = ParamSource.All, IsSecret = false, }; + _config = new ConfigurationBuilder().Build(); - _paramService = new(_buildDefinition, _args, _config, _vaultProviders); + _paramService = new(_buildDefinition, _args, _console, _config, _vaultProviders); A .CallTo(() => _buildDefinition.ParamDefinitions) @@ -301,7 +304,7 @@ public void GetParam_WithNoCacheScope_DoesNotCacheValue() _config = new ConfigurationBuilder().Build(); - _paramService = new(_buildDefinition, _args, _config, _vaultProviders); + _paramService = new(_buildDefinition, _args, _console, _config, _vaultProviders); A .CallTo(() => _buildDefinition.ParamDefinitions) @@ -356,7 +359,7 @@ public void GetParam_WithNoneFilter_IncludesNone() _vaultProviders = [new TestSecretsProvider()]; - _paramService = new(_buildDefinition, _args, _config, _vaultProviders); + _paramService = new(_buildDefinition, _args, _console, _config, _vaultProviders); A .CallTo(() => _buildDefinition.ParamDefinitions) @@ -397,7 +400,7 @@ public void GetParam_WithCommandLineArgsFilter_IncludesCommandLineArgs() _vaultProviders = [new TestSecretsProvider()]; - _paramService = new(_buildDefinition, _args, _config, _vaultProviders); + _paramService = new(_buildDefinition, _args, _console, _config, _vaultProviders); A .CallTo(() => _buildDefinition.ParamDefinitions) @@ -438,7 +441,7 @@ public void GetParam_WithEnvironmentVariablesFilter_IncludesEnvironmentVariables _vaultProviders = [new TestSecretsProvider()]; - _paramService = new(_buildDefinition, _args, _config, _vaultProviders); + _paramService = new(_buildDefinition, _args, _console, _config, _vaultProviders); A .CallTo(() => _buildDefinition.ParamDefinitions) @@ -479,7 +482,7 @@ public void GetParam_WithConfigurationFilter_IncludesConfiguration() _vaultProviders = [new TestSecretsProvider()]; - _paramService = new(_buildDefinition, _args, _config, _vaultProviders); + _paramService = new(_buildDefinition, _args, _console, _config, _vaultProviders); A .CallTo(() => _buildDefinition.ParamDefinitions) @@ -520,7 +523,7 @@ public void GetParam_WithVaultFilter_IncludesVault() _vaultProviders = [new TestSecretsProvider()]; - _paramService = new(_buildDefinition, _args, _config, _vaultProviders); + _paramService = new(_buildDefinition, _args, _console, _config, _vaultProviders); A .CallTo(() => _buildDefinition.ParamDefinitions) @@ -561,7 +564,7 @@ public void GetParam_WithSecretsFilter_IncludesVault() _vaultProviders = [new TestSecretsProvider()]; - _paramService = new(_buildDefinition, _args, _config, _vaultProviders); + _paramService = new(_buildDefinition, _args, _console, _config, _vaultProviders); A .CallTo(() => _buildDefinition.ParamDefinitions) diff --git a/DecSm.Atom/Args/CommandLineArgs.cs b/DecSm.Atom/Args/CommandLineArgs.cs index 52cd80da..5bc31b54 100644 --- a/DecSm.Atom/Args/CommandLineArgs.cs +++ b/DecSm.Atom/Args/CommandLineArgs.cs @@ -50,6 +50,12 @@ public sealed record CommandLineArgs(bool Valid, IReadOnlyList Args) /// public bool HasProject => Args.Any(arg => arg is ProjectArg); + /// + /// Whether the -i / --interactive argument was provided. + /// + /// + public bool HasInteractive => Args.Any(arg => arg is InteractiveArg); + /// /// The list of parameter arguments provided. /// diff --git a/DecSm.Atom/Args/CommandLineArgsParser.cs b/DecSm.Atom/Args/CommandLineArgsParser.cs index 663ace6c..1e56f41d 100644 --- a/DecSm.Atom/Args/CommandLineArgsParser.cs +++ b/DecSm.Atom/Args/CommandLineArgsParser.cs @@ -116,6 +116,7 @@ public CommandLineArgs Parse(IReadOnlyList rawArgs) "-hl" or "--headless" => new HeadlessArg(), "-v" or "--verbose" => new VerboseArg(), "-p" or "--project" => new ProjectArg(string.Empty), + "-i" or "--interactive" => new InteractiveArg(), _ => null, }; diff --git a/DecSm.Atom/Args/IArg.cs b/DecSm.Atom/Args/IArg.cs index 57437cda..15493546 100644 --- a/DecSm.Atom/Args/IArg.cs +++ b/DecSm.Atom/Args/IArg.cs @@ -64,3 +64,10 @@ public sealed record VerboseArg : IArg; /// The name of the project. [PublicAPI] public sealed record ProjectArg(string ProjectName) : IArg; + +/// +/// Instructs the build to run in interactive mode. +/// Typically used to allow user input during the build. +/// +[PublicAPI] +public sealed record InteractiveArg : IArg; diff --git a/DecSm.Atom/Build/BuildExecutor.cs b/DecSm.Atom/Build/BuildExecutor.cs index 5a7e2207..4c0ab8a8 100644 --- a/DecSm.Atom/Build/BuildExecutor.cs +++ b/DecSm.Atom/Build/BuildExecutor.cs @@ -24,17 +24,28 @@ public async Task Execute() logger.LogInformation("Executing build"); - await console - .Status() - .StartAsync("Executing build...", - async context => - { - foreach (var command in commands) - ValidateTargetParameters(buildModel.GetTarget(command.Name)); + if (args.HasInteractive) + { + foreach (var command in commands) + ValidateTargetParameters(buildModel.GetTarget(command.Name)); - foreach (var command in commands) - await ExecuteTarget(buildModel.GetTarget(command.Name), context); - }); + foreach (var command in commands) + await ExecuteTarget(buildModel.GetTarget(command.Name), null); + } + else + { + await console + .Status() + .StartAsync("Executing build...", + async context => + { + foreach (var command in commands) + ValidateTargetParameters(buildModel.GetTarget(command.Name)); + + foreach (var command in commands) + await ExecuteTarget(buildModel.GetTarget(command.Name), context); + }); + } foreach (var outcomeReporter in outcomeReporters) try @@ -81,7 +92,7 @@ private void ValidateTargetParameters(TargetModel target) } } - private async Task ExecuteTarget(TargetModel target, StatusContext context) + private async Task ExecuteTarget(TargetModel target, StatusContext? context) { if (buildModel.TargetStates[target].Status is TargetRunState.NotRun or TargetRunState.Skipped @@ -129,9 +140,19 @@ or TargetRunState.Succeeded buildModel.TargetStates[target].Status = TargetRunState.Running; var startTime = Stopwatch.GetTimestamp(); - context.Status($"Executing [bold]{target.Name}[/]..."); - context.Spinner(Spinner.Known.Star); - context.SpinnerStyle(Style.Parse("green")); + + if (context is not null) + { + context.Status($"Executing [bold]{target.Name}[/]..."); + context.Spinner(Spinner.Known.Star); + context.SpinnerStyle(Style.Parse("green")); + } + else + { + console.WriteLine(); + console.Write(new Markup($"Executing target [bold]{target.Name}[/]...\n")); + console.WriteLine(); + } using (logger.BeginScope(new Dictionary { diff --git a/DecSm.Atom/Params/ParamService.cs b/DecSm.Atom/Params/ParamService.cs index 3378143f..9b4c2b90 100644 --- a/DecSm.Atom/Params/ParamService.cs +++ b/DecSm.Atom/Params/ParamService.cs @@ -21,6 +21,7 @@ public interface IParamService internal sealed class ParamService( IBuildDefinition buildDefinition, CommandLineArgs args, + IAnsiConsole console, IConfiguration config, IEnumerable vaultProviders ) : IParamService @@ -96,6 +97,9 @@ public string MaskSecrets(string text) => paramDefinition.IsSecret && TryGetParamFromVault(paramDefinition, converter) is (true, { } vaultValue)) result = vaultValue; + else if (args is { HasHeadless: false, HasInteractive: true, HasHelp: false } && + TryGetParamFromUser(paramDefinition, converter) is (true, { } userValue)) + result = userValue; else result = defaultValue; @@ -139,7 +143,6 @@ public string MaskSecrets(string text) => if (string.IsNullOrEmpty(envVar)) envVar = Environment.GetEnvironmentVariable(paramDefinition - .ArgName .ToUpperInvariant() .Replace('-', '_')); @@ -185,4 +188,23 @@ public string MaskSecrets(string text) => return (false, default); } + + private (bool HasValue, T? Value) TryGetParamFromUser(ParamDefinition paramDefinition, Func? converter) + { + var result = console.Prompt(new TextPrompt($"Enter value for parameter '{paramDefinition.ArgName}': ") + { + IsSecret = paramDefinition.IsSecret, + Mask = '*', + ShowDefaultValue = paramDefinition.DefaultValue is { Length: > 0 }, + AllowEmpty = paramDefinition.DefaultValue is { Length: > 0 }, + }); + + if (result is not { Length: > 0 }) + return (false, default); + + // Force cache as it is a user input + _cache[paramDefinition] = result; + + return (true, TypeUtil.Convert(result, converter)); + } } From d67a5441c8159c139309a6069481eb5cb6c13859 Mon Sep 17 00:00:00 2001 From: Declan Smith Date: Sun, 5 Jan 2025 00:00:41 +1000 Subject: [PATCH 2/6] chore(dependencies): bump analyzer and associated packages versions Updated multiple projects to use newer versions of the following packages: - Roslynator (4.12.9 -> 4.12.10) - NUnit (4.2.2 -> 4.3.2) - Microsoft.CodeAnalysis.CSharp.Workspaces (4.11.0 -> 4.12.0) - TestableIO.System.IO.Abstractions.TestingHelpers (21.1.7 -> 21.2.1) - Verify.NUnit (28.4.0 -> 28.7.0) - NUnit.Analyzers (4.4.0 -> 4.5.0) - Coverlet.Collector (6.0.2 -> 6.0.3) --- .../DecSm.Atom.Module.AzureKeyVault.csproj | 4 +-- .../DecSm.Atom.Module.AzureStorage.csproj | 4 +-- .../DecSm.Atom.Module.DevopsWorkflows.csproj | 4 +-- .../DecSm.Atom.Module.Dotnet.csproj | 4 +-- .../DecSm.Atom.Module.GitVersion.csproj | 4 +-- ...m.Atom.Module.GithubWorkflows.Tests.csproj | 16 +++++----- .../DecSm.Atom.Module.GithubWorkflows.csproj | 4 +-- .../DecSm.Atom.SourceGenerators.Tests.csproj | 31 +++++++++---------- .../DecSm.Atom.SourceGenerators.csproj | 8 ++--- .../DecSm.Atom.TestUtils.csproj | 8 ++--- DecSm.Atom.Tests/DecSm.Atom.Tests.csproj | 16 +++++----- DecSm.Atom.Tool/DecSm.Atom.Tool.csproj | 6 ++-- DecSm.Atom/DecSm.Atom.csproj | 6 ++-- DecSm.Atom/Paths/AtomFileSystem.cs | 2 ++ _atom/_atom.csproj | 4 +-- 15 files changed, 61 insertions(+), 60 deletions(-) diff --git a/DecSm.Atom.Module.AzureKeyVault/DecSm.Atom.Module.AzureKeyVault.csproj b/DecSm.Atom.Module.AzureKeyVault/DecSm.Atom.Module.AzureKeyVault.csproj index 6f6f30a0..6f2a7adf 100644 --- a/DecSm.Atom.Module.AzureKeyVault/DecSm.Atom.Module.AzureKeyVault.csproj +++ b/DecSm.Atom.Module.AzureKeyVault/DecSm.Atom.Module.AzureKeyVault.csproj @@ -10,11 +10,11 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/DecSm.Atom.Module.AzureStorage/DecSm.Atom.Module.AzureStorage.csproj b/DecSm.Atom.Module.AzureStorage/DecSm.Atom.Module.AzureStorage.csproj index bf162f3e..d2f0d04e 100644 --- a/DecSm.Atom.Module.AzureStorage/DecSm.Atom.Module.AzureStorage.csproj +++ b/DecSm.Atom.Module.AzureStorage/DecSm.Atom.Module.AzureStorage.csproj @@ -14,11 +14,11 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/DecSm.Atom.Module.DevopsWorkflows/DecSm.Atom.Module.DevopsWorkflows.csproj b/DecSm.Atom.Module.DevopsWorkflows/DecSm.Atom.Module.DevopsWorkflows.csproj index 6df2d3f8..5849102b 100644 --- a/DecSm.Atom.Module.DevopsWorkflows/DecSm.Atom.Module.DevopsWorkflows.csproj +++ b/DecSm.Atom.Module.DevopsWorkflows/DecSm.Atom.Module.DevopsWorkflows.csproj @@ -5,11 +5,11 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/DecSm.Atom.Module.Dotnet/DecSm.Atom.Module.Dotnet.csproj b/DecSm.Atom.Module.Dotnet/DecSm.Atom.Module.Dotnet.csproj index 6df2d3f8..5849102b 100644 --- a/DecSm.Atom.Module.Dotnet/DecSm.Atom.Module.Dotnet.csproj +++ b/DecSm.Atom.Module.Dotnet/DecSm.Atom.Module.Dotnet.csproj @@ -5,11 +5,11 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/DecSm.Atom.Module.GitVersion/DecSm.Atom.Module.GitVersion.csproj b/DecSm.Atom.Module.GitVersion/DecSm.Atom.Module.GitVersion.csproj index 83fbb8f7..5dcbbb86 100644 --- a/DecSm.Atom.Module.GitVersion/DecSm.Atom.Module.GitVersion.csproj +++ b/DecSm.Atom.Module.GitVersion/DecSm.Atom.Module.GitVersion.csproj @@ -5,11 +5,11 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/DecSm.Atom.Module.GithubWorkflows.Tests/DecSm.Atom.Module.GithubWorkflows.Tests.csproj b/DecSm.Atom.Module.GithubWorkflows.Tests/DecSm.Atom.Module.GithubWorkflows.Tests.csproj index 1d9b0905..de0be8bb 100644 --- a/DecSm.Atom.Module.GithubWorkflows.Tests/DecSm.Atom.Module.GithubWorkflows.Tests.csproj +++ b/DecSm.Atom.Module.GithubWorkflows.Tests/DecSm.Atom.Module.GithubWorkflows.Tests.csproj @@ -7,19 +7,19 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + - - + + @@ -27,19 +27,19 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/DecSm.Atom.Module.GithubWorkflows/DecSm.Atom.Module.GithubWorkflows.csproj b/DecSm.Atom.Module.GithubWorkflows/DecSm.Atom.Module.GithubWorkflows.csproj index 6df2d3f8..5849102b 100644 --- a/DecSm.Atom.Module.GithubWorkflows/DecSm.Atom.Module.GithubWorkflows.csproj +++ b/DecSm.Atom.Module.GithubWorkflows/DecSm.Atom.Module.GithubWorkflows.csproj @@ -5,11 +5,11 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/DecSm.Atom.SourceGenerators.Tests/DecSm.Atom.SourceGenerators.Tests.csproj b/DecSm.Atom.SourceGenerators.Tests/DecSm.Atom.SourceGenerators.Tests.csproj index cc72a5c0..46a6ddde 100644 --- a/DecSm.Atom.SourceGenerators.Tests/DecSm.Atom.SourceGenerators.Tests.csproj +++ b/DecSm.Atom.SourceGenerators.Tests/DecSm.Atom.SourceGenerators.Tests.csproj @@ -7,43 +7,42 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - + + + + + + + - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive - - + + diff --git a/DecSm.Atom.SourceGenerators/DecSm.Atom.SourceGenerators.csproj b/DecSm.Atom.SourceGenerators/DecSm.Atom.SourceGenerators.csproj index 39711270..96373324 100644 --- a/DecSm.Atom.SourceGenerators/DecSm.Atom.SourceGenerators.csproj +++ b/DecSm.Atom.SourceGenerators/DecSm.Atom.SourceGenerators.csproj @@ -13,16 +13,16 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/DecSm.Atom.TestUtils/DecSm.Atom.TestUtils.csproj b/DecSm.Atom.TestUtils/DecSm.Atom.TestUtils.csproj index 66746db3..0b1c5a75 100644 --- a/DecSm.Atom.TestUtils/DecSm.Atom.TestUtils.csproj +++ b/DecSm.Atom.TestUtils/DecSm.Atom.TestUtils.csproj @@ -6,20 +6,20 @@ - + - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/DecSm.Atom.Tests/DecSm.Atom.Tests.csproj b/DecSm.Atom.Tests/DecSm.Atom.Tests.csproj index 2737527c..0b80525c 100644 --- a/DecSm.Atom.Tests/DecSm.Atom.Tests.csproj +++ b/DecSm.Atom.Tests/DecSm.Atom.Tests.csproj @@ -7,19 +7,19 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + - - + + @@ -27,19 +27,19 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/DecSm.Atom.Tool/DecSm.Atom.Tool.csproj b/DecSm.Atom.Tool/DecSm.Atom.Tool.csproj index c92f9461..73d7237e 100644 --- a/DecSm.Atom.Tool/DecSm.Atom.Tool.csproj +++ b/DecSm.Atom.Tool/DecSm.Atom.Tool.csproj @@ -8,15 +8,15 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/DecSm.Atom/DecSm.Atom.csproj b/DecSm.Atom/DecSm.Atom.csproj index 44cac685..ba50450a 100644 --- a/DecSm.Atom/DecSm.Atom.csproj +++ b/DecSm.Atom/DecSm.Atom.csproj @@ -8,16 +8,16 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/DecSm.Atom/Paths/AtomFileSystem.cs b/DecSm.Atom/Paths/AtomFileSystem.cs index 6fc4add0..4dc98251 100644 --- a/DecSm.Atom/Paths/AtomFileSystem.cs +++ b/DecSm.Atom/Paths/AtomFileSystem.cs @@ -33,6 +33,8 @@ public interface IAtomFileSystem : IFileSystem IPath IFileSystem.Path => FileSystem.Path; + IFileVersionInfoFactory IFileSystem.FileVersionInfo => FileSystem.FileVersionInfo; + RootedPath GetPath(string key); RootedPath CreateRootedPath(string path) => diff --git a/_atom/_atom.csproj b/_atom/_atom.csproj index 869dbc08..255b0c41 100644 --- a/_atom/_atom.csproj +++ b/_atom/_atom.csproj @@ -7,11 +7,11 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive From 699cbc83a30029d2f9ca9c77bcd28647ef62dd99 Mon Sep 17 00:00:00 2001 From: Declan Smith Date: Sun, 5 Jan 2025 00:04:47 +1000 Subject: [PATCH 3/6] fix(reporter): resolve bug in log message splitting logic Refactored log message splitting to use a pre-defined array for delimiters. Resolves ambiguous call error. --- DecSm.Atom/Reports/ConsoleOutcomeReporter.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/DecSm.Atom/Reports/ConsoleOutcomeReporter.cs b/DecSm.Atom/Reports/ConsoleOutcomeReporter.cs index 9e81d9da..27c8bbcc 100644 --- a/DecSm.Atom/Reports/ConsoleOutcomeReporter.cs +++ b/DecSm.Atom/Reports/ConsoleOutcomeReporter.cs @@ -129,7 +129,8 @@ private void Write(List reportData, string header, string styleTa foreach (var log in reportData) { - var messageLines = log.Message.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries); + var splitPattern = new[] { '\r', '\n' }; + var messageLines = log.Message.Split(splitPattern, StringSplitOptions.RemoveEmptyEntries); var rows = new List { From 541b964174901aab56494005f03ac12b48c2e81e Mon Sep 17 00:00:00 2001 From: Declan Smith Date: Sun, 5 Jan 2025 00:08:25 +1000 Subject: [PATCH 4/6] fix(dotnet-tools): replace 'install' with 'update' for dotnet tools Updated commands in multiple locations to use 'dotnet tool update' instead of 'dotnet tool install' for already installed tools. This ensures correct behavior and avoids potential errors when re-installing existing tools. Affected files: - DotnetToolService.cs - DevopsWorkflowWriter.cs - GithubWorkflowWriter.cs --- .../Generation/DevopsWorkflowWriter.cs | 2 +- DecSm.Atom.Module.Dotnet/DotnetToolService.cs | 4 ++-- .../Generation/GithubWorkflowWriter.cs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/DecSm.Atom.Module.DevopsWorkflows/Generation/DevopsWorkflowWriter.cs b/DecSm.Atom.Module.DevopsWorkflows/Generation/DevopsWorkflowWriter.cs index ec9163c9..efb72fab 100644 --- a/DecSm.Atom.Module.DevopsWorkflows/Generation/DevopsWorkflowWriter.cs +++ b/DecSm.Atom.Module.DevopsWorkflows/Generation/DevopsWorkflowWriter.cs @@ -361,7 +361,7 @@ private void WriteStep(WorkflowModel workflow, IWorkflowTargetModel step, Workfl .ToList(); // TODO: Remove preview flag once v1.0.0 is released - using (WriteSection("- script: dotnet tool install --global DecSm.Atom.Tool --prerelease")) + using (WriteSection("- script: dotnet tool update --global DecSm.Atom.Tool --prerelease")) WriteLine("displayName: 'Install atom tool'"); WriteLine(); diff --git a/DecSm.Atom.Module.Dotnet/DotnetToolService.cs b/DecSm.Atom.Module.Dotnet/DotnetToolService.cs index 14059896..48419e0b 100644 --- a/DecSm.Atom.Module.Dotnet/DotnetToolService.cs +++ b/DecSm.Atom.Module.Dotnet/DotnetToolService.cs @@ -47,7 +47,7 @@ void InstallTool(string toolName, string? version = null, bool global = true, bo : string.Empty; GetService() - .Run(new("dotnet", $"tool install {toolName} {versionFlag} {globalFlag}") + .Run(new("dotnet", $"tool update {toolName} {versionFlag} {globalFlag}") { InvocationLogLevel = LogLevel.Debug, }); @@ -97,7 +97,7 @@ await GetService() : string.Empty; await GetService() - .RunAsync(new("dotnet", $"tool install {toolName} {versionFlag} {globalFlag}") + .RunAsync(new("dotnet", $"tool update {toolName} {versionFlag} {globalFlag}") { InvocationLogLevel = LogLevel.Debug, }); diff --git a/DecSm.Atom.Module.GithubWorkflows/Generation/GithubWorkflowWriter.cs b/DecSm.Atom.Module.GithubWorkflows/Generation/GithubWorkflowWriter.cs index d91f0030..34619f91 100644 --- a/DecSm.Atom.Module.GithubWorkflows/Generation/GithubWorkflowWriter.cs +++ b/DecSm.Atom.Module.GithubWorkflows/Generation/GithubWorkflowWriter.cs @@ -283,7 +283,7 @@ private void WriteStep(WorkflowModel workflow, IWorkflowTargetModel step, Workfl // TODO: Remove preview flag once v1.0.0 is released using (WriteSection("- name: Install atom tool")) { - WriteLine("run: dotnet tool install --global DecSm.Atom.Tool --prerelease"); + WriteLine("run: dotnet tool update --global DecSm.Atom.Tool --prerelease"); WriteLine("shell: bash"); } From 9b0220bb0cc6214661d549020c151116c2f5a7ea Mon Sep 17 00:00:00 2001 From: Declan Smith Date: Sun, 5 Jan 2025 00:10:01 +1000 Subject: [PATCH 5/6] chore: rebuild workflows --- .devops/workflows/Test_BuildPrivateNugetFeed.yml | 2 +- .devops/workflows/Test_ValidatePrivateNugetFeed.yml | 2 +- .github/workflows/Test_BuildPrivateNugetFeed.yml | 2 +- .github/workflows/Test_ValidatePrivateNugetFeed.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.devops/workflows/Test_BuildPrivateNugetFeed.yml b/.devops/workflows/Test_BuildPrivateNugetFeed.yml index 6e9d4632..e22bb38d 100644 --- a/.devops/workflows/Test_BuildPrivateNugetFeed.yml +++ b/.devops/workflows/Test_BuildPrivateNugetFeed.yml @@ -27,7 +27,7 @@ jobs: - checkout: self fetchDepth: 0 - - script: dotnet tool install --global DecSm.Atom.Tool --prerelease + - script: dotnet tool update --global DecSm.Atom.Tool --prerelease displayName: 'Install atom tool' - script: | diff --git a/.devops/workflows/Test_ValidatePrivateNugetFeed.yml b/.devops/workflows/Test_ValidatePrivateNugetFeed.yml index ee185067..de81448f 100644 --- a/.devops/workflows/Test_ValidatePrivateNugetFeed.yml +++ b/.devops/workflows/Test_ValidatePrivateNugetFeed.yml @@ -43,7 +43,7 @@ jobs: - checkout: self fetchDepth: 0 - - script: dotnet tool install --global DecSm.Atom.Tool --prerelease + - script: dotnet tool update --global DecSm.Atom.Tool --prerelease displayName: 'Install atom tool' - script: | diff --git a/.github/workflows/Test_BuildPrivateNugetFeed.yml b/.github/workflows/Test_BuildPrivateNugetFeed.yml index c74cf20e..66210ef0 100644 --- a/.github/workflows/Test_BuildPrivateNugetFeed.yml +++ b/.github/workflows/Test_BuildPrivateNugetFeed.yml @@ -35,7 +35,7 @@ jobs: with: fetch-depth: 0 - name: Install atom tool - run: dotnet tool install --global DecSm.Atom.Tool --prerelease + run: dotnet tool update --global DecSm.Atom.Tool --prerelease shell: bash - name: Setup NuGet diff --git a/.github/workflows/Test_ValidatePrivateNugetFeed.yml b/.github/workflows/Test_ValidatePrivateNugetFeed.yml index cb8de4f9..b80c4b66 100644 --- a/.github/workflows/Test_ValidatePrivateNugetFeed.yml +++ b/.github/workflows/Test_ValidatePrivateNugetFeed.yml @@ -52,7 +52,7 @@ jobs: with: fetch-depth: 0 - name: Install atom tool - run: dotnet tool install --global DecSm.Atom.Tool --prerelease + run: dotnet tool update --global DecSm.Atom.Tool --prerelease shell: bash - name: Setup NuGet From d7e3639e716108fa8f8c9750b8f16d5dd3cf17a4 Mon Sep 17 00:00:00 2001 From: Declan Smith Date: Sun, 5 Jan 2025 00:36:41 +1000 Subject: [PATCH 6/6] fix(params): ensure cached value uses converted result Previously, the raw result was being cached instead of the converted value. This could lead to unexpected behavior when retrieved from the cache. The fix ensures the converted result is both cached and returned. --- DecSm.Atom/Params/ParamService.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/DecSm.Atom/Params/ParamService.cs b/DecSm.Atom/Params/ParamService.cs index 9b4c2b90..cb8c09ea 100644 --- a/DecSm.Atom/Params/ParamService.cs +++ b/DecSm.Atom/Params/ParamService.cs @@ -202,9 +202,11 @@ public string MaskSecrets(string text) => if (result is not { Length: > 0 }) return (false, default); + var convertedResult = TypeUtil.Convert(result, converter); + // Force cache as it is a user input - _cache[paramDefinition] = result; + _cache[paramDefinition] = convertedResult; - return (true, TypeUtil.Convert(result, converter)); + return (true, convertedResult); } }