From 046456849df61536b6d15ec7de5602cf3984f084 Mon Sep 17 00:00:00 2001 From: Matthias Koch Date: Sun, 13 Oct 2024 01:01:07 +0200 Subject: [PATCH 1/6] fix(execution): exclude skipped target from lookup for skippable dependencies --- source/Nuke.Build.Tests/BuildExecutorTest.cs | 13 +++++++++++++ source/Nuke.Build/Execution/BuildExecutor.cs | 6 +++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/source/Nuke.Build.Tests/BuildExecutorTest.cs b/source/Nuke.Build.Tests/BuildExecutorTest.cs index 8c156e26c..035e380c6 100644 --- a/source/Nuke.Build.Tests/BuildExecutorTest.cs +++ b/source/Nuke.Build.Tests/BuildExecutorTest.cs @@ -105,6 +105,19 @@ public void TestStaticCondition_DependencyBehavior_Skip() B.OnlyWhen.Should().Be("false"); } + [Fact] + public void TestStaticCondition_DependencyBehavior_Skip_Invoked() + { + C.Invoked = true; + C.StaticConditions.Add(("() => false", () => false)); + B.DependencyBehavior = DependencyBehavior.Skip; + ExecuteBuild(); + AssertSkipped(A, B, C); + A.Skipped.Should().Be("because of B"); + B.Skipped.Should().Be("because of C"); + C.OnlyWhen.Should().Be("false"); + } + [Fact] public void TestStaticCondition_Multiple() { diff --git a/source/Nuke.Build/Execution/BuildExecutor.cs b/source/Nuke.Build/Execution/BuildExecutor.cs index 56f6b0fda..16fe5ba2a 100644 --- a/source/Nuke.Build/Execution/BuildExecutor.cs +++ b/source/Nuke.Build/Execution/BuildExecutor.cs @@ -195,12 +195,12 @@ private static void MarkTargetSkipped(INukeBuild build, ExecutableTarget target, bool HasOtherDependencies(ExecutableTarget dependentTarget) => build.ExecutionPlan - .Where(x => x.Status == ExecutionStatus.Scheduled) + .Where(x => x != target && x.Status == ExecutionStatus.Scheduled) .Any(x => x.ExecutionDependencies.Contains(dependentTarget) || x.Triggers.Contains(dependentTarget)); - var skippableTargets = target.ExecutionDependencies.Concat(target.Triggers) + var skippableDependencies = target.ExecutionDependencies.Concat(target.Triggers) .Where(x => !HasOtherDependencies(x)).ToList(); - skippableTargets.ForEach(x => MarkTargetSkipped(build, x, $"because of {target.Name}")); + skippableDependencies.ForEach(x => MarkTargetSkipped(build, x, $"because of {target.Name}")); } private static void AppendToBuildAttemptFile(string value) From b3891131dde20d9af05c894dc4306742112a3158 Mon Sep 17 00:00:00 2001 From: Matthias Koch Date: Sun, 13 Oct 2024 01:02:14 +0200 Subject: [PATCH 2/6] fix(execution): prefer logger from settings in parallel execution --- source/Nuke.Tooling/Configure.cs | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/source/Nuke.Tooling/Configure.cs b/source/Nuke.Tooling/Configure.cs index 20a11bf51..7c4a5ea69 100644 --- a/source/Nuke.Tooling/Configure.cs +++ b/source/Nuke.Tooling/Configure.cs @@ -29,7 +29,7 @@ public static T InvokeSafe([CanBeNull] this Configure configurator, T obj) public static IReadOnlyCollection<(TSettings Settings, IReadOnlyCollection Output)> Invoke( this CombinatorialConfigure configurator, Func> executor, - Action logger, + Action defaultLogger, int degreeOfParallelism, bool completeOnFailure) where TSettings : ToolSettings, new() @@ -38,7 +38,7 @@ public static T InvokeSafe([CanBeNull] this Configure configurator, T obj) configurator, x => (Settings: x, Output: executor(x)), x => x.Output, - logger, + defaultLogger, degreeOfParallelism, completeOnFailure); } @@ -46,16 +46,16 @@ public static T InvokeSafe([CanBeNull] this Configure configurator, T obj) public static IReadOnlyCollection<(TSettings Settings, TResult Result, IReadOnlyCollection Output)> Invoke( this CombinatorialConfigure configurator, Func Output)> executor, - Action logger, + Action defaultLogger, int degreeOfParallelism, bool completeOnFailure) where TSettings : ToolSettings, new() { return Invoke( configurator, - x => (Settings: x, ReturnValue: executor(x)), - x => x.ReturnValue.Output, - logger, + executor: x => (Settings: x, ReturnValue: executor(x)), + outputSelector: x => x.ReturnValue.Output, + defaultLogger, degreeOfParallelism, completeOnFailure) .Select(x => (x.Settings, x.ReturnValue.Result, x.ReturnValue.Output)).ToList(); @@ -65,12 +65,12 @@ private static IReadOnlyCollection Invoke( CombinatorialConfigure configurator, Func executor, Func> outputSelector, - Action logger, + Action defaultLogger, int degreeOfParallelism, bool completeOnFailure) where TSettings : ToolSettings, new() { - var invocations = new ConcurrentBag<(TSettings Settings, TResult Result, Exception Exception)>(); + var invocations = new ConcurrentBag<(TSettings Settings, Action logger, TResult Result, Exception Exception)>(); try { @@ -79,13 +79,15 @@ private static IReadOnlyCollection Invoke( .WithDegreeOfParallelism(degreeOfParallelism) .ForAll(x => { + var logger = x.ProcessLogger ?? defaultLogger; try { - invocations.Add((x, executor(x.DisableProcessLogOutput()), default)); + var result = executor(x.DisableProcessLogOutput()); + invocations.Add((x, logger, result, default)); } catch (Exception exception) { - invocations.Add((x, default, exception)); + invocations.Add((x, logger, default, exception)); if (!completeOnFailure) throw; @@ -103,14 +105,14 @@ private static IReadOnlyCollection Invoke( .Where(x => x.Settings.ProcessLogOutput ?? ProcessTasks.DefaultLogOutput) .SelectMany(x => { - var (settings, result, exception) = x; + var (_, logger, result, exception) = x; var output = exception switch { ProcessException processException => processException.Process.Output, _ => outputSelector(result), }; - return output.Select(x => (Logger: logger ?? settings.ProcessLogger, Line: x)); + return output.Select(x => (Logger: logger, Line: x)); }) .ForEach(x => x.Logger(x.Line.Type, x.Line.Text)); } From 6895f4cbe2ab266b7087ddcc1cd1ec229c238174 Mon Sep 17 00:00:00 2001 From: Matthias Koch Date: Sun, 13 Oct 2024 01:14:24 +0200 Subject: [PATCH 3/6] build: update dependencies --- Directory.Packages.props | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index e571d0ad7..2fa67976d 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -5,23 +5,23 @@ - + - + - + - + - + - + @@ -29,8 +29,8 @@ - - + + From 1b0de60107c957eaab9f4561243d6611c2bae118 Mon Sep 17 00:00:00 2001 From: Matthias Koch Date: Sun, 13 Oct 2024 02:05:33 +0200 Subject: [PATCH 4/6] fix(utilities): mandatory boolean default for conversion from string values --- source/Nuke.Build.Tests/ParameterServiceTest.cs | 7 +++++++ source/Nuke.Build/Execution/ParameterService.cs | 2 +- .../Reflection/ReflectionUtilityTest.cs | 6 +++--- source/Nuke.Utilities/ArgumentParser.cs | 2 +- source/Nuke.Utilities/EnvironmentInfo.Variables.cs | 2 +- .../Reflection/ReflectionUtility.Conversion.cs | 8 ++++---- 6 files changed, 17 insertions(+), 10 deletions(-) diff --git a/source/Nuke.Build.Tests/ParameterServiceTest.cs b/source/Nuke.Build.Tests/ParameterServiceTest.cs index 546db9700..4106ea9ee 100644 --- a/source/Nuke.Build.Tests/ParameterServiceTest.cs +++ b/source/Nuke.Build.Tests/ParameterServiceTest.cs @@ -41,8 +41,12 @@ public void TestNotSupplied(Type destinationType, object expectedValue) [Theory] [InlineData("arg1", typeof(string), "value1")] [InlineData("arg2", typeof(string), "value3")] + [InlineData("arg3", typeof(string), "value4")] + [InlineData("switch1", typeof(bool), true)] [InlineData("switch2", typeof(bool), true)] [InlineData("switch3", typeof(bool), false)] + [InlineData("switch4", typeof(bool), false)] + [InlineData("switch5", typeof(bool), true)] [InlineData("array1", typeof(string[]), new[] { "element1", "element2" })] [InlineData("array2", typeof(string[]), new string[0])] [InlineData("array3", typeof(string[]), null)] @@ -60,8 +64,11 @@ public void TestEnvironmentVariables(string parameter, Type destinationType, obj { { "arg1", "value2" }, { "arg2", "value3" }, + { "nuke_arg_3", "value4" }, { "switch2", "true" }, { "switch3", "false" }, + { "switch4", "" }, + { "nuke_switch_5", "true" }, { "array1", "element1+element2" }, { "array2", "" }, }); diff --git a/source/Nuke.Build/Execution/ParameterService.cs b/source/Nuke.Build/Execution/ParameterService.cs index f293f6a6e..271578075 100644 --- a/source/Nuke.Build/Execution/ParameterService.cs +++ b/source/Nuke.Build/Execution/ParameterService.cs @@ -214,7 +214,7 @@ static string GetTrimmedName(string name) try { - return Convert(value, destinationType, separator); + return Convert(value, destinationType, separator, booleanDefault: false); } catch (Exception ex) { diff --git a/source/Nuke.Utilities.Tests/Reflection/ReflectionUtilityTest.cs b/source/Nuke.Utilities.Tests/Reflection/ReflectionUtilityTest.cs index b40e835ff..975f21cc7 100644 --- a/source/Nuke.Utilities.Tests/Reflection/ReflectionUtilityTest.cs +++ b/source/Nuke.Utilities.Tests/Reflection/ReflectionUtilityTest.cs @@ -86,15 +86,15 @@ public void TestConversionCollections() .Should().BeOfType().Which .Should().BeEmpty(); - ReflectionUtility.Convert(string.Empty, typeof(string[]), separator: '+') + ReflectionUtility.Convert(string.Empty, typeof(string[]), separator: '+', booleanDefault: true) .Should().BeOfType().Which .Should().BeEmpty(); - ReflectionUtility.Convert("A+B+C", typeof(string[]), separator: '+') + ReflectionUtility.Convert("A+B+C", typeof(string[]), separator: '+', booleanDefault: true) .Should().BeOfType().Which .Should().Equal("A", "B", "C"); - ReflectionUtility.Convert("1 2 3", typeof(int[]), separator: ' ') + ReflectionUtility.Convert("1 2 3", typeof(int[]), separator: ' ', booleanDefault: true) .Should().BeOfType().Which .Should().Equal(1, 2, 3); } diff --git a/source/Nuke.Utilities/ArgumentParser.cs b/source/Nuke.Utilities/ArgumentParser.cs index dc1d78db1..9beff5833 100644 --- a/source/Nuke.Utilities/ArgumentParser.cs +++ b/source/Nuke.Utilities/ArgumentParser.cs @@ -151,7 +151,7 @@ private object ConvertValues(string argumentName, IReadOnlyCollection va { try { - return ReflectionUtility.Convert(values, destinationType); + return ReflectionUtility.Convert(values, destinationType, booleanDefault: true); } catch (Exception ex) { diff --git a/source/Nuke.Utilities/EnvironmentInfo.Variables.cs b/source/Nuke.Utilities/EnvironmentInfo.Variables.cs index 9416b9428..0e8fde613 100644 --- a/source/Nuke.Utilities/EnvironmentInfo.Variables.cs +++ b/source/Nuke.Utilities/EnvironmentInfo.Variables.cs @@ -62,7 +62,7 @@ public static T GetVariable(string name, char? separator = null) if (value == null) return default; - return (T)ReflectionUtility.Convert(value, typeof(T), separator); + return (T)ReflectionUtility.Convert(value, typeof(T), separator, booleanDefault: false); } /// diff --git a/source/Nuke.Utilities/Reflection/ReflectionUtility.Conversion.cs b/source/Nuke.Utilities/Reflection/ReflectionUtility.Conversion.cs index 07c1a9dfb..1076719a4 100644 --- a/source/Nuke.Utilities/Reflection/ReflectionUtility.Conversion.cs +++ b/source/Nuke.Utilities/Reflection/ReflectionUtility.Conversion.cs @@ -42,15 +42,15 @@ public static object Convert(object value, Type destinationType) // TODO: rename overloads? [CanBeNull] - public static object Convert(string value, Type destinationType, char? separator) + public static object Convert(string value, Type destinationType, char? separator, bool booleanDefault) { var values = (separator.HasValue ? value.Split(separator.Value) : new[] { value }) .Where(x => !x.IsNullOrWhiteSpace()).ToArray(); - return Convert(values, destinationType); + return Convert(values, destinationType, booleanDefault); } [CanBeNull] - public static object Convert(IReadOnlyCollection values, Type destinationType) + public static object Convert(IReadOnlyCollection values, Type destinationType, bool booleanDefault) { Assert.True(!destinationType.IsArray || destinationType.GetArrayRank() == 1, "Arrays must have a rank of 1"); var elementType = (destinationType.IsArray ? destinationType.GetElementType() : destinationType).NotNull(); @@ -62,7 +62,7 @@ public static object Convert(IReadOnlyCollection values, Type destinatio return Array.CreateInstance(elementType, length: 0); if (destinationType == typeof(bool) || destinationType == typeof(bool?)) - return true; + return booleanDefault; return null; } From 0cc02f38fb4868dda88e0df2677622e8a42fac7b Mon Sep 17 00:00:00 2001 From: Matthias Koch Date: Sun, 13 Oct 2024 02:12:25 +0200 Subject: [PATCH 5/6] chore: update CHANGELOG.md --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 11b713efc..61be199c9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,9 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). ## [vNext] +- Fixed exclusion of skipped target from lookup for skippable dependencies +- Fixed resolution of empty environment variables to false +- Fixed parallel execution to prefer logger from settings ## [8.1.1] / 2024-10-05 - Fixed nested solution folders in `StronglyTypedSolutionGenerator` From d3ef1b09c71a53fa98b42c9116d67f6b35e10642 Mon Sep 17 00:00:00 2001 From: Matthias Koch Date: Sun, 13 Oct 2024 02:13:19 +0200 Subject: [PATCH 6/6] chore: CHANGELOG.md for 8.1.2 --- CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 61be199c9..cbd4ff4c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). ## [vNext] + +## [8.1.2] / 2024-10-13 - Fixed exclusion of skipped target from lookup for skippable dependencies - Fixed resolution of empty environment variables to false - Fixed parallel execution to prefer logger from settings @@ -1160,7 +1162,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Added CLT tasks for Git - Fixed background color in console output -[vNext]: https://github.com/nuke-build/nuke/compare/8.1.1...HEAD +[vNext]: https://github.com/nuke-build/nuke/compare/8.1.2...HEAD +[8.1.2]: https://github.com/nuke-build/nuke/compare/8.1.1...8.1.2 [8.1.1]: https://github.com/nuke-build/nuke/compare/8.1.0...8.1.1 [8.1.0]: https://github.com/nuke-build/nuke/compare/8.0.0...8.1.0 [8.0.0]: https://github.com/nuke-build/nuke/compare/7.0.6...8.0.0