From e45e076ed0d1bbe1143c416ea5853698ef4ad38e Mon Sep 17 00:00:00 2001 From: Tom Longhurst <30480171+thomhurst@users.noreply.github.com> Date: Fri, 16 Jan 2026 13:11:42 +0000 Subject: [PATCH 1/8] chore: migrate ModularPipelines to v3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update TUnit.Pipeline to use ModularPipelines v3 APIs: - Entry point: `builder.BuildPipeline()` → `builder.Build()` - `IPipelineContext` → `IModuleContext` - `context.GetModule()` instead of direct GetModule - `context.SubModule()` instead of SubModule() - `ModuleResult.Value` → `ValueOrDefault` - `result.SkipDecision.ShouldSkip` → `result.IsSkipped` - `result.HasValue` → `result.IsSuccess` - `CommandLogging` → `CommandLoggingOptions` with boolean properties - Tool options separated from `CommandExecutionOptions` - Tool options use property initializers (no constructors) - Git commands use `Arguments` property for non-typed values - `Shell.Bash.Command(new BashCommandOptions(cmd), token)` - `DotNet().New.Execute()` for template operations Co-Authored-By: Claude Opus 4.5 --- Directory.Packages.props | 8 +-- .../Modules/Abstract/TestBaseModule.cs | 47 +++++++-------- .../Modules/AddLocalNuGetRepositoryModule.cs | 23 ++++++-- TUnit.Pipeline/Modules/CommitFilesModule.cs | 53 +++++++++-------- .../Modules/CopyToLocalNuGetModule.cs | 6 +- TUnit.Pipeline/Modules/CreateReleaseModule.cs | 27 +++++---- .../Modules/GenerateReadMeModule.cs | 8 ++- .../Modules/GenerateVersionModule.cs | 8 +-- .../Modules/GetPackageProjectsModule.cs | 2 +- .../Modules/PackTUnitFilesModule.cs | 27 ++++++--- .../Modules/ProcessorParallelLimit.cs | 2 +- .../Modules/PublishNugetTesterAOTModule.cs | 39 ++++++++----- .../Modules/PushVersionTagModule.cs | 24 ++++---- .../Modules/RunAnalyzersTestsModule.cs | 18 ++++-- .../RunAspNetCoreAnalyzersTestsModule.cs | 18 ++++-- .../Modules/RunAspNetTestsModule.cs | 18 ++++-- .../RunAssertionsAnalyzersTestsModule.cs | 18 ++++-- .../RunAssertionsCodeFixersTestsModule.cs | 18 ++++-- .../Modules/RunAssertionsTestsModule.cs | 26 +++++---- .../Modules/RunEngineTestsModule.cs | 18 ++++-- .../Modules/RunPlaywrightTestsModule.cs | 24 +++++--- .../Modules/RunPublicAPITestsModule.cs | 28 +++++---- TUnit.Pipeline/Modules/RunRpcTestsModule.cs | 28 +++++---- .../Modules/RunSourceGeneratorTestsModule.cs | 26 +++++---- .../Modules/RunTemplateTestsModule.cs | 18 ++++-- TUnit.Pipeline/Modules/RunUnitTestsModule.cs | 26 +++++---- .../TestAspNetCoreNugetPackageModule.cs | 45 ++++++++------ .../Modules/TestNugetPackageModule.cs | 46 +++++++++------ .../Modules/TestTemplatePackageModule.cs | 58 ++++++++++++++----- TUnit.Pipeline/Modules/UploadToNuGetModule.cs | 42 +++++++++----- TUnit.Pipeline/Program.cs | 29 ++++------ TUnit.Pipeline/TUnit.Pipeline.csproj | 1 + 32 files changed, 480 insertions(+), 299 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 277167c660..38b4438e4f 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -47,9 +47,9 @@ - - - + + + @@ -101,4 +101,4 @@ - + \ No newline at end of file diff --git a/TUnit.Pipeline/Modules/Abstract/TestBaseModule.cs b/TUnit.Pipeline/Modules/Abstract/TestBaseModule.cs index 481e4167a3..6a02fa1f91 100644 --- a/TUnit.Pipeline/Modules/Abstract/TestBaseModule.cs +++ b/TUnit.Pipeline/Modules/Abstract/TestBaseModule.cs @@ -2,9 +2,9 @@ using ModularPipelines.Context; using ModularPipelines.DotNet.Extensions; using ModularPipelines.DotNet.Options; -using ModularPipelines.Enums; using ModularPipelines.Models; using ModularPipelines.Modules; +using ModularPipelines.Options; namespace TUnit.Pipeline.Modules.Abstract; @@ -24,17 +24,19 @@ protected virtual IEnumerable TestableFrameworks } } - protected sealed override async Task?> ExecuteAsync(IPipelineContext context, CancellationToken cancellationToken) + protected sealed override async Task?> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken) { var results = new List(); foreach (var framework in TestableFrameworks) { - var testResult = await SubModule(framework, async () => + var testResult = await context.SubModule(framework, async () => { - var testOptions = SetDefaults(await GetTestOptions(context, framework, cancellationToken)); + var (testOptions, executionOptions) = await GetTestOptions(context, framework, cancellationToken); - return await context.DotNet().Run(testOptions, cancellationToken); + var finalExecutionOptions = SetDefaults(testOptions, executionOptions ?? new CommandExecutionOptions(), framework); + + return await context.DotNet().Run(testOptions, finalExecutionOptions, cancellationToken); }); results.Add(testResult); @@ -43,35 +45,30 @@ protected virtual IEnumerable TestableFrameworks return results; } - private DotNetRunOptions SetDefaults(DotNetRunOptions testOptions) + private CommandExecutionOptions SetDefaults(DotNetRunOptions testOptions, CommandExecutionOptions executionOptions, string framework) { - if (testOptions.EnvironmentVariables?.Any(x => x.Key == "NET_VERSION") != true) + var envVars = executionOptions.EnvironmentVariables ?? new Dictionary(); + if (!envVars.ContainsKey("NET_VERSION")) { - testOptions = testOptions with + envVars = new Dictionary(envVars) { - EnvironmentVariables = new Dictionary - { - ["NET_VERSION"] = testOptions.Framework, - } + ["NET_VERSION"] = framework }; } - // Add hangdump flags with 20 minute timeout - var arguments = testOptions.Arguments?.ToList() ?? new List(); - if (!arguments.Contains("--hangdump")) - { - arguments.AddRange(["--hangdump", "--hangdump-filename", $"hangdump.{Environment.OSVersion.Platform}.{GetType().Name}.dmp", "--hangdump-timeout", "5m"]); - } - // Suppress output for successful operations, but show errors and basic info - testOptions = testOptions with + return executionOptions with { - Arguments = arguments, - CommandLogging = CommandLogging.Input | CommandLogging.Error | CommandLogging.Duration | CommandLogging.ExitCode + EnvironmentVariables = envVars, + LogSettings = new CommandLoggingOptions + { + ShowCommandArguments = true, + ShowStandardError = true, + ShowExecutionTime = true, + ShowExitCode = true + } }; - - return testOptions; } - protected abstract Task GetTestOptions(IPipelineContext context, string framework, CancellationToken cancellationToken); + protected abstract Task<(DotNetRunOptions Options, CommandExecutionOptions? ExecutionOptions)> GetTestOptions(IModuleContext context, string framework, CancellationToken cancellationToken); } diff --git a/TUnit.Pipeline/Modules/AddLocalNuGetRepositoryModule.cs b/TUnit.Pipeline/Modules/AddLocalNuGetRepositoryModule.cs index f37d3b3b40..33cf74c7c6 100644 --- a/TUnit.Pipeline/Modules/AddLocalNuGetRepositoryModule.cs +++ b/TUnit.Pipeline/Modules/AddLocalNuGetRepositoryModule.cs @@ -1,20 +1,33 @@ using ModularPipelines.Context; using ModularPipelines.DotNet.Extensions; using ModularPipelines.DotNet.Options; -using ModularPipelines.Enums; using ModularPipelines.FileSystem; using ModularPipelines.Modules; +using ModularPipelines.Options; namespace TUnit.Pipeline.Modules; public class AddLocalNuGetRepositoryModule : Module { - protected override async Task ExecuteAsync(IPipelineContext context, CancellationToken cancellationToken) + protected override async Task ExecuteAsync(IModuleContext context, CancellationToken cancellationToken) { - var folder = context.FileSystem.GetFolder(Environment.SpecialFolder.LocalApplicationData).GetFolder("LocalNuget").Create(); - await context.DotNet().Nuget.Add.Source(new DotNetNugetAddSourceOptions(folder) + var localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); + var folder = new Folder(Path.Combine(localAppData, "LocalNuget")); + folder.Create(); + + await context.DotNet().Nuget.Add.Source(new DotNetNugetAddSourceOptions + { + Name = "LocalNuget", + Packagesourcepath = folder.Path, + }, new CommandExecutionOptions { - CommandLogging = CommandLogging.Input | CommandLogging.Error | CommandLogging.Duration | CommandLogging.ExitCode + LogSettings = new CommandLoggingOptions + { + ShowCommandArguments = true, + ShowStandardError = true, + ShowExecutionTime = true, + ShowExitCode = true + } }, cancellationToken); return folder; } diff --git a/TUnit.Pipeline/Modules/CommitFilesModule.cs b/TUnit.Pipeline/Modules/CommitFilesModule.cs index c8feb2a2e9..854479a4f5 100644 --- a/TUnit.Pipeline/Modules/CommitFilesModule.cs +++ b/TUnit.Pipeline/Modules/CommitFilesModule.cs @@ -1,4 +1,5 @@ using ModularPipelines.Attributes; +using ModularPipelines.Configuration; using ModularPipelines.Context; using ModularPipelines.Extensions; using ModularPipelines.Git.Attributes; @@ -24,21 +25,25 @@ namespace TUnit.Pipeline.Modules; [ModuleCategory("ReadMe")] public class CommitFilesModule : Module { - protected override async Task ShouldSkip(IPipelineContext context) - { - var generateReadMeModule = GetModuleIfRegistered(); - - if (generateReadMeModule is null) + protected override ModuleConfiguration Configure() => ModuleConfiguration.Create() + .WithSkipWhen(async ctx => { - return "Nothing to commit"; - } + var generateReadMeModule = ctx.GetModuleIfRegistered(); + + if (generateReadMeModule is null) + { + return SkipDecision.Skip("Nothing to commit"); + } - var result = await generateReadMeModule; + var result = await generateReadMeModule; - return result.SkipDecision.ShouldSkip || !result.HasValue; - } + return result.IsSkipped || !result.IsSuccess + ? SkipDecision.Skip("GenerateReadMeModule was skipped or has no value") + : SkipDecision.DoNotSkip; + }) + .Build(); - protected override async Task ExecuteAsync(IPipelineContext context, CancellationToken cancellationToken) + protected override async Task ExecuteAsync(IModuleContext context, CancellationToken cancellationToken) { var repositoryId = long.Parse(context.GitHub().EnvironmentVariables.RepositoryId!); @@ -46,33 +51,36 @@ await context.Git().Commands.Config(new GitConfigOptions { Global = true, Arguments = ["user.name", context.GitHub().EnvironmentVariables.Actor!] - }, cancellationToken); + }, token: cancellationToken); await context.Git().Commands.Config(new GitConfigOptions { Global = true, Arguments = ["user.email", $"{context.GitHub().EnvironmentVariables.ActorId!}_{context.GitHub().EnvironmentVariables.Actor!}@users.noreply.github.com"] - }, cancellationToken); + }, token: cancellationToken); var newBranchName = $"feature/readme-{Guid.NewGuid():N}"; - await context.Git().Commands.Checkout(new GitCheckoutOptions(newBranchName, true), cancellationToken); + await context.Git().Commands.Checkout(new GitCheckoutOptions(newBranchName, true), token: cancellationToken); await context.Git().Commands.Add(new GitAddOptions { Arguments = ["README.md"], - WorkingDirectory = context.Git().RootDirectory.AssertExists() + }, new CommandExecutionOptions + { + WorkingDirectory = context.Git().RootDirectory.AssertExists().Path }, cancellationToken); await context.Git().Commands.Commit(new GitCommitOptions { Message = "Update README.md" - }, cancellationToken); + }, token: cancellationToken); await context.Git().Commands.Push(new GitPushOptions { - Arguments = ["--set-upstream", "origin", newBranchName] - }, cancellationToken); + SetUpstream = true, + Arguments = ["origin", newBranchName] + }, token: cancellationToken); await context.Git().Commands.Push(token: cancellationToken); @@ -85,12 +93,7 @@ await context.Git().Commands.Push(new GitPushOptions await context.GitHub().Client.Issue.Update(repositoryId, pr.Number, issueUpdate); - return await context.Command.ExecuteCommandLineTool(new CommandLineToolOptions("gh", "pr", "merge", "--admin", "--squash", pr.Number.ToString()) - { - EnvironmentVariables = new Dictionary - { - ["GH_TOKEN"] = Environment.GetEnvironmentVariable("ADMIN_TOKEN") - } - }, cancellationToken); + var adminToken = Environment.GetEnvironmentVariable("ADMIN_TOKEN"); + return await context.Shell.Bash.Command(new BashCommandOptions($"GH_TOKEN={adminToken} gh pr merge --admin --squash {pr.Number}"), cancellationToken); } } diff --git a/TUnit.Pipeline/Modules/CopyToLocalNuGetModule.cs b/TUnit.Pipeline/Modules/CopyToLocalNuGetModule.cs index 36787c5ecf..7baa2a2db2 100644 --- a/TUnit.Pipeline/Modules/CopyToLocalNuGetModule.cs +++ b/TUnit.Pipeline/Modules/CopyToLocalNuGetModule.cs @@ -9,11 +9,11 @@ namespace TUnit.Pipeline.Modules; [DependsOn] public class CopyToLocalNuGetModule : Module> { - protected override async Task?> ExecuteAsync(IPipelineContext context, CancellationToken cancellationToken) + protected override async Task?> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken) { - var folder = await GetModule(); + var folder = await context.GetModule(); return context.Git().RootDirectory.GetFiles(x => x.Name.StartsWith("TUnit", StringComparison.InvariantCultureIgnoreCase) && x.Extension.EndsWith("nupkg")) - .Select(x => x.CopyTo(folder.Value!)) + .Select(x => x.CopyTo(folder.ValueOrDefault!)) .ToList(); } } diff --git a/TUnit.Pipeline/Modules/CreateReleaseModule.cs b/TUnit.Pipeline/Modules/CreateReleaseModule.cs index afae921c5d..860bc4029c 100644 --- a/TUnit.Pipeline/Modules/CreateReleaseModule.cs +++ b/TUnit.Pipeline/Modules/CreateReleaseModule.cs @@ -1,4 +1,5 @@ using ModularPipelines.Attributes; +using ModularPipelines.Configuration; using ModularPipelines.Context; using ModularPipelines.Git.Attributes; using ModularPipelines.GitHub.Extensions; @@ -14,23 +15,27 @@ namespace TUnit.Pipeline.Modules; [DependsOn] public class CreateReleaseModule : Module { - protected override async Task ShouldSkip(IPipelineContext context) - { - if (GetModuleIfRegistered() is not { } uploadToNuGetModule) + protected override ModuleConfiguration Configure() => ModuleConfiguration.Create() + .WithSkipWhen(async ctx => { - return true; - } + if (ctx.GetModuleIfRegistered() is not { } uploadToNuGetModule) + { + return SkipDecision.Skip("UploadToNuGetModule not registered"); + } - var result = await uploadToNuGetModule; + var result = await uploadToNuGetModule; - return result.SkipDecision.ShouldSkip; - } + return result.IsSkipped + ? SkipDecision.Skip("UploadToNuGetModule was skipped") + : SkipDecision.DoNotSkip; + }) + .Build(); - protected override async Task ExecuteAsync(IPipelineContext context, CancellationToken cancellationToken) + protected override async Task ExecuteAsync(IModuleContext context, CancellationToken cancellationToken) { - var versionModule = await GetModule(); + var versionModule = await context.GetModule(); - var version = versionModule.Value!.SemVer; + var version = versionModule.ValueOrDefault!.SemVer; var repositoryId = long.Parse(context.GitHub().EnvironmentVariables.RepositoryId!); diff --git a/TUnit.Pipeline/Modules/GenerateReadMeModule.cs b/TUnit.Pipeline/Modules/GenerateReadMeModule.cs index 45b8f5f4fb..f31be6dc7c 100644 --- a/TUnit.Pipeline/Modules/GenerateReadMeModule.cs +++ b/TUnit.Pipeline/Modules/GenerateReadMeModule.cs @@ -1,4 +1,5 @@ -using System.Text; +using System.IO.Compression; +using System.Text; using Microsoft.Extensions.Logging; using ModularPipelines.Attributes; using ModularPipelines.Context; @@ -20,7 +21,7 @@ namespace TUnit.Pipeline.Modules; [ModuleCategory("ReadMe")] public class GenerateReadMeModule : Module { - protected override async Task ExecuteAsync(IPipelineContext context, CancellationToken cancellationToken) + protected override async Task ExecuteAsync(IModuleContext context, CancellationToken cancellationToken) { var template = await context.Git() .RootDirectory @@ -90,7 +91,8 @@ public class GenerateReadMeModule : Module var downloadedZip = File.GetNewTemporaryFilePath(); await downloadedZip.WriteAsync(stream, cancellationToken); - var unzippedDirectory = context.Zip.UnZipToFolder(downloadedZip, Folder.CreateTemporaryFolder()); + var unzippedDirectory = Folder.CreateTemporaryFolder(); + ZipFile.ExtractToDirectory(downloadedZip.Path, unzippedDirectory.Path); var markdownFile = unzippedDirectory.FindFile(x => x.Extension == ".md").AssertExists(); diff --git a/TUnit.Pipeline/Modules/GenerateVersionModule.cs b/TUnit.Pipeline/Modules/GenerateVersionModule.cs index 4f8699fc9d..5ffe70d796 100644 --- a/TUnit.Pipeline/Modules/GenerateVersionModule.cs +++ b/TUnit.Pipeline/Modules/GenerateVersionModule.cs @@ -1,5 +1,5 @@ -using ModularPipelines.Context; -using ModularPipelines.Extensions; +using Microsoft.Extensions.Logging; +using ModularPipelines.Context; using ModularPipelines.Git.Extensions; using ModularPipelines.Git.Models; using ModularPipelines.Modules; @@ -8,11 +8,11 @@ namespace TUnit.Pipeline.Modules; public class GenerateVersionModule : Module { - protected override async Task ExecuteAsync(IPipelineContext context, CancellationToken cancellationToken) + protected override async Task ExecuteAsync(IModuleContext context, CancellationToken cancellationToken) { var versionInformation = await context.Git().Versioning.GetGitVersioningInformation(); - context.LogOnPipelineEnd($"NuGet Version is: {versionInformation.SemVer}"); + context.Logger.LogInformation("NuGet Version is: {SemVer}", versionInformation.SemVer); return versionInformation; } diff --git a/TUnit.Pipeline/Modules/GetPackageProjectsModule.cs b/TUnit.Pipeline/Modules/GetPackageProjectsModule.cs index fa83ebc66a..d7ba373019 100644 --- a/TUnit.Pipeline/Modules/GetPackageProjectsModule.cs +++ b/TUnit.Pipeline/Modules/GetPackageProjectsModule.cs @@ -6,7 +6,7 @@ namespace TUnit.Pipeline.Modules; public class GetPackageProjectsModule : Module> { - protected override async Task?> ExecuteAsync(IPipelineContext context, CancellationToken cancellationToken) + protected override async Task?> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken) { await Task.CompletedTask; diff --git a/TUnit.Pipeline/Modules/PackTUnitFilesModule.cs b/TUnit.Pipeline/Modules/PackTUnitFilesModule.cs index 5b671c1ee3..c477ffd418 100644 --- a/TUnit.Pipeline/Modules/PackTUnitFilesModule.cs +++ b/TUnit.Pipeline/Modules/PackTUnitFilesModule.cs @@ -2,9 +2,9 @@ using ModularPipelines.Context; using ModularPipelines.DotNet.Extensions; using ModularPipelines.DotNet.Options; -using ModularPipelines.Enums; using ModularPipelines.Models; using ModularPipelines.Modules; +using ModularPipelines.Options; namespace TUnit.Pipeline.Modules; @@ -13,24 +13,25 @@ namespace TUnit.Pipeline.Modules; [DependsOn] public class PackTUnitFilesModule : Module> { - protected override async Task?> ExecuteAsync(IPipelineContext context, + protected override async Task?> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken) { - var projects = await GetModule(); - var versionResult = await GetModule(); + var projects = await context.GetModule(); + var versionResult = await context.GetModule(); - var version = versionResult.Value!; + var version = versionResult.ValueOrDefault!; var packageVersion = version.SemVer!; var packedProjects = new List(); - foreach (var project in projects.Value!) + foreach (var project in projects.ValueOrDefault!) { await context.DotNet() .Pack( - new DotNetPackOptions(project) + new DotNetPackOptions { + ProjectSolution = project.Path, Properties = [ new KeyValue("Version", version.SemVer!), @@ -39,8 +40,16 @@ await context.DotNet() new KeyValue("IsPackTarget", "true") ], IncludeSource = project == Sourcy.DotNet.Projects.TUnit_Templates ? false : true, - Configuration = Configuration.Release, - CommandLogging = CommandLogging.Input | CommandLogging.Error | CommandLogging.Duration | CommandLogging.ExitCode + Configuration = "Release", + }, new CommandExecutionOptions + { + LogSettings = new CommandLoggingOptions + { + ShowCommandArguments = true, + ShowStandardError = true, + ShowExecutionTime = true, + ShowExitCode = true + } }, cancellationToken); packedProjects.Add(new PackedProject(project.NameWithoutExtension, version.SemVer!)); diff --git a/TUnit.Pipeline/Modules/ProcessorParallelLimit.cs b/TUnit.Pipeline/Modules/ProcessorParallelLimit.cs index 6d9728539a..28fd7dbb40 100644 --- a/TUnit.Pipeline/Modules/ProcessorParallelLimit.cs +++ b/TUnit.Pipeline/Modules/ProcessorParallelLimit.cs @@ -4,5 +4,5 @@ namespace TUnit.Pipeline.Modules; public class ProcessorParallelLimit : IParallelLimit { - public int Limit { get; } = Environment.ProcessorCount * 4; + public static int Limit { get; } = Environment.ProcessorCount * 4; } diff --git a/TUnit.Pipeline/Modules/PublishNugetTesterAOTModule.cs b/TUnit.Pipeline/Modules/PublishNugetTesterAOTModule.cs index b15f0e8a03..d9a19126b6 100644 --- a/TUnit.Pipeline/Modules/PublishNugetTesterAOTModule.cs +++ b/TUnit.Pipeline/Modules/PublishNugetTesterAOTModule.cs @@ -1,13 +1,14 @@ using System.Runtime.InteropServices; using ModularPipelines.Attributes; +using ModularPipelines.Configuration; using ModularPipelines.Context; using ModularPipelines.DotNet.Extensions; using ModularPipelines.DotNet.Options; -using ModularPipelines.Enums; using ModularPipelines.Extensions; using ModularPipelines.Git.Extensions; using ModularPipelines.Models; using ModularPipelines.Modules; +using ModularPipelines.Options; namespace TUnit.Pipeline.Modules; @@ -16,15 +17,16 @@ namespace TUnit.Pipeline.Modules; [DependsOn] public class PublishNugetTesterAOTModule : Module> { - protected override Task ShouldSkip(IPipelineContext context) - { - return Task.FromResult(EnvironmentVariables.IsNetFramework); - } + protected override ModuleConfiguration Configure() => ModuleConfiguration.Create() + .WithSkipWhen(_ => EnvironmentVariables.IsNetFramework + ? SkipDecision.Skip("Running on .NET Framework") + : SkipDecision.DoNotSkip) + .Build(); - protected override async Task?> ExecuteAsync(IPipelineContext context, CancellationToken cancellationToken) + protected override async Task?> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken) { var results = new List(); - var version = await GetModule(); + var version = await context.GetModule(); var testProject = context.Git() .RootDirectory @@ -35,20 +37,29 @@ protected override Task ShouldSkip(IPipelineContext context) // Test AOT publishing foreach (var framework in new[] { "net8.0", "net9.0", "net10.0" }) { - var result = await SubModule($"AOT-{framework}", async () => + var result = await context.SubModule($"AOT-{framework}", async () => { - return await context.DotNet().Publish(new DotNetPublishOptions(testProject) + return await context.DotNet().Publish(new DotNetPublishOptions { - RuntimeIdentifier = GetRuntimeIdentifier(), - Configuration = Configuration.Release, - OutputDirectory = $"NUGETTESTER_AOT_{framework}", + ProjectSolution = testProject.Path, + Runtime = GetRuntimeIdentifier(), + Configuration = "Release", + Output = $"NUGETTESTER_AOT_{framework}", Properties = [ new KeyValue("Aot", "true"), - new KeyValue("TUnitVersion", version.Value!.SemVer!) + new KeyValue("TUnitVersion", version.ValueOrDefault!.SemVer!) ], Framework = framework, - CommandLogging = CommandLogging.Input | CommandLogging.Error | CommandLogging.Duration | CommandLogging.ExitCode + }, new CommandExecutionOptions + { + LogSettings = new CommandLoggingOptions + { + ShowCommandArguments = true, + ShowStandardError = true, + ShowExecutionTime = true, + ShowExitCode = true + } }, cancellationToken); }); diff --git a/TUnit.Pipeline/Modules/PushVersionTagModule.cs b/TUnit.Pipeline/Modules/PushVersionTagModule.cs index fb958a4ff9..a72a8173e8 100644 --- a/TUnit.Pipeline/Modules/PushVersionTagModule.cs +++ b/TUnit.Pipeline/Modules/PushVersionTagModule.cs @@ -1,4 +1,5 @@ using ModularPipelines.Attributes; +using ModularPipelines.Configuration; using ModularPipelines.Context; using ModularPipelines.Git.Attributes; using ModularPipelines.Git.Extensions; @@ -13,25 +14,26 @@ namespace TUnit.Pipeline.Modules; [DependsOn] public class PushVersionTagModule : Module { - protected override async Task ShouldIgnoreFailures(IPipelineContext context, Exception exception) - { - var versionInformation = await GetModule(); - - return exception.Message.Contains($"tag 'v{versionInformation.Value!.SemVer}' already exists"); - } + protected override ModuleConfiguration Configure() => ModuleConfiguration.Create() + .WithIgnoreFailuresWhen(async (ctx, ex) => + { + var versionInformation = await ctx.GetModule(); + return ex.Message.Contains($"tag 'v{versionInformation.ValueOrDefault!.SemVer}' already exists"); + }) + .Build(); - protected override async Task ExecuteAsync(IPipelineContext context, CancellationToken cancellationToken) + protected override async Task ExecuteAsync(IModuleContext context, CancellationToken cancellationToken) { - var versionInformation = await GetModule(); + var versionInformation = await context.GetModule(); await context.Git().Commands.Tag(new GitTagOptions { - Arguments = [$"v{versionInformation.Value!.SemVer}"], - }, cancellationToken); + TagName = $"v{versionInformation.ValueOrDefault!.SemVer}", + }, token: cancellationToken); return await context.Git().Commands.Push(new GitPushOptions { Tags = true - }, cancellationToken); + }, token: cancellationToken); } } diff --git a/TUnit.Pipeline/Modules/RunAnalyzersTestsModule.cs b/TUnit.Pipeline/Modules/RunAnalyzersTestsModule.cs index 796c740b68..fa97dabd05 100644 --- a/TUnit.Pipeline/Modules/RunAnalyzersTestsModule.cs +++ b/TUnit.Pipeline/Modules/RunAnalyzersTestsModule.cs @@ -2,33 +2,41 @@ using ModularPipelines.Context; using ModularPipelines.DotNet.Extensions; using ModularPipelines.DotNet.Options; -using ModularPipelines.Enums; using ModularPipelines.Extensions; using ModularPipelines.Git.Extensions; using ModularPipelines.Models; using ModularPipelines.Modules; +using ModularPipelines.Options; namespace TUnit.Pipeline.Modules; [NotInParallel("DotNetTests")] public class RunAnalyzersTestsModule : Module { - protected override async Task ExecuteAsync(IPipelineContext context, CancellationToken cancellationToken) + protected override async Task ExecuteAsync(IModuleContext context, CancellationToken cancellationToken) { var project = context.Git().RootDirectory.FindFile(x => x.Name == "TUnit.Analyzers.Tests.csproj").AssertExists(); return await context.DotNet().Test(new DotNetTestOptions { - WorkingDirectory = project.Folder!, NoBuild = true, - Configuration = Configuration.Release, + Configuration = "Release", Framework = "net8.0", Arguments = ["--", "--hangdump", "--hangdump-filename", "hangdump.analyzers-tests.dmp", "--hangdump-timeout", "5m"], + }, new CommandExecutionOptions + { + WorkingDirectory = project.Folder!.Path, EnvironmentVariables = new Dictionary { ["DISABLE_GITHUB_REPORTER"] = "true", }, - CommandLogging = CommandLogging.Input | CommandLogging.Error | CommandLogging.Duration | CommandLogging.ExitCode + LogSettings = new CommandLoggingOptions + { + ShowCommandArguments = true, + ShowStandardError = true, + ShowExecutionTime = true, + ShowExitCode = true + } }, cancellationToken); } } diff --git a/TUnit.Pipeline/Modules/RunAspNetCoreAnalyzersTestsModule.cs b/TUnit.Pipeline/Modules/RunAspNetCoreAnalyzersTestsModule.cs index 921b8b8a51..85755e0d0b 100644 --- a/TUnit.Pipeline/Modules/RunAspNetCoreAnalyzersTestsModule.cs +++ b/TUnit.Pipeline/Modules/RunAspNetCoreAnalyzersTestsModule.cs @@ -2,33 +2,41 @@ using ModularPipelines.Context; using ModularPipelines.DotNet.Extensions; using ModularPipelines.DotNet.Options; -using ModularPipelines.Enums; using ModularPipelines.Extensions; using ModularPipelines.Git.Extensions; using ModularPipelines.Models; using ModularPipelines.Modules; +using ModularPipelines.Options; namespace TUnit.Pipeline.Modules; [NotInParallel("DotNetTests")] public class RunAspNetCoreAnalyzersTestsModule : Module { - protected override async Task ExecuteAsync(IPipelineContext context, CancellationToken cancellationToken) + protected override async Task ExecuteAsync(IModuleContext context, CancellationToken cancellationToken) { var project = context.Git().RootDirectory.FindFile(x => x.Name == "TUnit.AspNetCore.Analyzers.Tests.csproj").AssertExists(); return await context.DotNet().Test(new DotNetTestOptions { - WorkingDirectory = project.Folder!, NoBuild = true, - Configuration = Configuration.Release, + Configuration = "Release", Framework = "net9.0", Arguments = ["--", "--hangdump", "--hangdump-filename", "hangdump.aspnetcore-analyzers-tests.dmp", "--hangdump-timeout", "5m"], + }, new CommandExecutionOptions + { + WorkingDirectory = project.Folder!.Path, EnvironmentVariables = new Dictionary { ["DISABLE_GITHUB_REPORTER"] = "true", }, - CommandLogging = CommandLogging.Input | CommandLogging.Error | CommandLogging.Duration | CommandLogging.ExitCode + LogSettings = new CommandLoggingOptions + { + ShowCommandArguments = true, + ShowStandardError = true, + ShowExecutionTime = true, + ShowExitCode = true + } }, cancellationToken); } } diff --git a/TUnit.Pipeline/Modules/RunAspNetTestsModule.cs b/TUnit.Pipeline/Modules/RunAspNetTestsModule.cs index 19affa0735..8c55dcffe3 100644 --- a/TUnit.Pipeline/Modules/RunAspNetTestsModule.cs +++ b/TUnit.Pipeline/Modules/RunAspNetTestsModule.cs @@ -2,18 +2,18 @@ using ModularPipelines.Context; using ModularPipelines.DotNet.Extensions; using ModularPipelines.DotNet.Options; -using ModularPipelines.Enums; using ModularPipelines.Extensions; using ModularPipelines.Git.Extensions; using ModularPipelines.Models; using ModularPipelines.Modules; +using ModularPipelines.Options; namespace TUnit.Pipeline.Modules; [NotInParallel("DotNetTests"), RunOnLinuxOnly, RunOnWindowsOnly] public class RunAspNetTestsModule : Module { - protected override async Task ExecuteAsync(IPipelineContext context, CancellationToken cancellationToken) + protected override async Task ExecuteAsync(IModuleContext context, CancellationToken cancellationToken) { var project = context.Git().RootDirectory.FindFile(x => x.Name == "TUnit.Example.Asp.Net.TestProject.csproj").AssertExists(); @@ -21,15 +21,23 @@ public class RunAspNetTestsModule : Module { Project = project.Name, NoBuild = true, - Configuration = Configuration.Release, + Configuration = "Release", Framework = "net10.0", - WorkingDirectory = project.Folder!, Arguments = ["--hangdump", "--hangdump-filename", "hangdump.aspnet-tests.dmp", "--hangdump-timeout", "5m"], + }, new CommandExecutionOptions + { + WorkingDirectory = project.Folder!.Path, EnvironmentVariables = new Dictionary { ["DISABLE_GITHUB_REPORTER"] = "true", }, - CommandLogging = CommandLogging.Input | CommandLogging.Error | CommandLogging.Duration | CommandLogging.ExitCode + LogSettings = new CommandLoggingOptions + { + ShowCommandArguments = true, + ShowStandardError = true, + ShowExecutionTime = true, + ShowExitCode = true + } }, cancellationToken); } } diff --git a/TUnit.Pipeline/Modules/RunAssertionsAnalyzersTestsModule.cs b/TUnit.Pipeline/Modules/RunAssertionsAnalyzersTestsModule.cs index 01458e50f1..524fc25b0f 100644 --- a/TUnit.Pipeline/Modules/RunAssertionsAnalyzersTestsModule.cs +++ b/TUnit.Pipeline/Modules/RunAssertionsAnalyzersTestsModule.cs @@ -2,33 +2,41 @@ using ModularPipelines.Context; using ModularPipelines.DotNet.Extensions; using ModularPipelines.DotNet.Options; -using ModularPipelines.Enums; using ModularPipelines.Extensions; using ModularPipelines.Git.Extensions; using ModularPipelines.Models; using ModularPipelines.Modules; +using ModularPipelines.Options; namespace TUnit.Pipeline.Modules; [NotInParallel("DotNetTests")] public class RunAssertionsAnalyzersTestsModule : Module { - protected override async Task ExecuteAsync(IPipelineContext context, CancellationToken cancellationToken) + protected override async Task ExecuteAsync(IModuleContext context, CancellationToken cancellationToken) { var project = context.Git().RootDirectory.FindFile(x => x.Name == "TUnit.Assertions.Analyzers.Tests.csproj").AssertExists(); return await context.DotNet().Test(new DotNetTestOptions { - WorkingDirectory = project.Folder!, NoBuild = true, - Configuration = Configuration.Release, + Configuration = "Release", Framework = "net8.0", Arguments = ["--", "--hangdump", "--hangdump-filename", "hangdump.assertions-analyzers-tests.dmp", "--hangdump-timeout", "5m"], + }, new CommandExecutionOptions + { + WorkingDirectory = project.Folder!.Path, EnvironmentVariables = new Dictionary { ["DISABLE_GITHUB_REPORTER"] = "true", }, - CommandLogging = CommandLogging.Input | CommandLogging.Error | CommandLogging.Duration | CommandLogging.ExitCode + LogSettings = new CommandLoggingOptions + { + ShowCommandArguments = true, + ShowStandardError = true, + ShowExecutionTime = true, + ShowExitCode = true + } }, cancellationToken); } } diff --git a/TUnit.Pipeline/Modules/RunAssertionsCodeFixersTestsModule.cs b/TUnit.Pipeline/Modules/RunAssertionsCodeFixersTestsModule.cs index ac7e4af46e..92b3776861 100644 --- a/TUnit.Pipeline/Modules/RunAssertionsCodeFixersTestsModule.cs +++ b/TUnit.Pipeline/Modules/RunAssertionsCodeFixersTestsModule.cs @@ -2,33 +2,41 @@ using ModularPipelines.Context; using ModularPipelines.DotNet.Extensions; using ModularPipelines.DotNet.Options; -using ModularPipelines.Enums; using ModularPipelines.Extensions; using ModularPipelines.Git.Extensions; using ModularPipelines.Models; using ModularPipelines.Modules; +using ModularPipelines.Options; namespace TUnit.Pipeline.Modules; [NotInParallel("DotNetTests")] public class RunAssertionsCodeFixersTestsModule : Module { - protected override async Task ExecuteAsync(IPipelineContext context, CancellationToken cancellationToken) + protected override async Task ExecuteAsync(IModuleContext context, CancellationToken cancellationToken) { var project = context.Git().RootDirectory.FindFile(x => x.Name == "TUnit.Assertions.Analyzers.CodeFixers.Tests.csproj").AssertExists(); return await context.DotNet().Test(new DotNetTestOptions { - WorkingDirectory = project.Folder!, NoBuild = true, - Configuration = Configuration.Release, + Configuration = "Release", Framework = "net8.0", Arguments = ["--", "--hangdump", "--hangdump-filename", "hangdump.assertions-codefixers-tests.dmp", "--hangdump-timeout", "5m"], + }, new CommandExecutionOptions + { + WorkingDirectory = project.Folder!.Path, EnvironmentVariables = new Dictionary { ["DISABLE_GITHUB_REPORTER"] = "true", }, - CommandLogging = CommandLogging.Input | CommandLogging.Error | CommandLogging.Duration | CommandLogging.ExitCode + LogSettings = new CommandLoggingOptions + { + ShowCommandArguments = true, + ShowStandardError = true, + ShowExecutionTime = true, + ShowExitCode = true + } }, cancellationToken); } } diff --git a/TUnit.Pipeline/Modules/RunAssertionsTestsModule.cs b/TUnit.Pipeline/Modules/RunAssertionsTestsModule.cs index 72c504be62..bdb42203ff 100644 --- a/TUnit.Pipeline/Modules/RunAssertionsTestsModule.cs +++ b/TUnit.Pipeline/Modules/RunAssertionsTestsModule.cs @@ -3,6 +3,7 @@ using ModularPipelines.DotNet.Options; using ModularPipelines.Extensions; using ModularPipelines.Git.Extensions; +using ModularPipelines.Options; using TUnit.Pipeline.Modules.Abstract; namespace TUnit.Pipeline.Modules; @@ -10,20 +11,25 @@ namespace TUnit.Pipeline.Modules; [NotInParallel("DotNetTests")] public class RunAssertionsTestsModule : TestBaseModule { - protected override Task GetTestOptions(IPipelineContext context, string framework, CancellationToken cancellationToken) + protected override Task<(DotNetRunOptions Options, CommandExecutionOptions? ExecutionOptions)> GetTestOptions(IModuleContext context, string framework, CancellationToken cancellationToken) { var project = context.Git().RootDirectory.FindFile(x => x.Name == "TUnit.Assertions.Tests.csproj").AssertExists(); - return Task.FromResult(new DotNetRunOptions - { - WorkingDirectory = project.Folder!, - NoBuild = true, - Configuration = Configuration.Release, - Framework = framework, - EnvironmentVariables = new Dictionary + return Task.FromResult<(DotNetRunOptions, CommandExecutionOptions?)>(( + new DotNetRunOptions { - ["TUNIT_DISABLE_GITHUB_REPORTER"] = "true", + NoBuild = true, + Configuration = "Release", + Framework = framework, + }, + new CommandExecutionOptions + { + WorkingDirectory = project.Folder!.Path, + EnvironmentVariables = new Dictionary + { + ["TUNIT_DISABLE_GITHUB_REPORTER"] = "true", + } } - }); + )); } } diff --git a/TUnit.Pipeline/Modules/RunEngineTestsModule.cs b/TUnit.Pipeline/Modules/RunEngineTestsModule.cs index 49a70177aa..b8e07e0df9 100644 --- a/TUnit.Pipeline/Modules/RunEngineTestsModule.cs +++ b/TUnit.Pipeline/Modules/RunEngineTestsModule.cs @@ -2,11 +2,11 @@ using ModularPipelines.Context; using ModularPipelines.DotNet.Extensions; using ModularPipelines.DotNet.Options; -using ModularPipelines.Enums; using ModularPipelines.Extensions; using ModularPipelines.Git.Extensions; using ModularPipelines.Models; using ModularPipelines.Modules; +using ModularPipelines.Options; namespace TUnit.Pipeline.Modules; @@ -24,7 +24,7 @@ namespace TUnit.Pipeline.Modules; [DependsOn] public class RunEngineTestsModule : Module { - protected override async Task ExecuteAsync(IPipelineContext context, CancellationToken cancellationToken) + protected override async Task ExecuteAsync(IModuleContext context, CancellationToken cancellationToken) { var project = context.Git().RootDirectory.FindFile(x => x.Name == "TUnit.Engine.Tests.csproj").AssertExists(); @@ -32,18 +32,26 @@ public class RunEngineTestsModule : Module { Project = project.Name, NoBuild = true, - Configuration = Configuration.Release, + Configuration = "Release", Framework = "net10.0", - WorkingDirectory = project.Folder!, Arguments = [ "--hangdump", "--hangdump-filename", $"hangdump.{Environment.OSVersion.Platform}.engine-tests.dmp", "--hangdump-timeout", "30m", "--timeout", "35m", ], + }, new CommandExecutionOptions + { + WorkingDirectory = project.Folder!.Path, EnvironmentVariables = new Dictionary { ["TUNIT_DISABLE_GITHUB_REPORTER"] = "true", }, - CommandLogging = CommandLogging.Input | CommandLogging.Error | CommandLogging.Duration | CommandLogging.ExitCode + LogSettings = new CommandLoggingOptions + { + ShowCommandArguments = true, + ShowStandardError = true, + ShowExecutionTime = true, + ShowExitCode = true + } }, cancellationToken); } } diff --git a/TUnit.Pipeline/Modules/RunPlaywrightTestsModule.cs b/TUnit.Pipeline/Modules/RunPlaywrightTestsModule.cs index 478a0223d1..1acecd34e9 100644 --- a/TUnit.Pipeline/Modules/RunPlaywrightTestsModule.cs +++ b/TUnit.Pipeline/Modules/RunPlaywrightTestsModule.cs @@ -1,6 +1,7 @@ using ModularPipelines.Attributes; using ModularPipelines.Context; using ModularPipelines.DotNet.Options; +using ModularPipelines.Options; using TUnit.Pipeline.Modules.Abstract; namespace TUnit.Pipeline.Modules; @@ -8,19 +9,24 @@ namespace TUnit.Pipeline.Modules; [NotInParallel("DotNetTests"), RunOnLinuxOnly, RunOnWindowsOnly] public class RunPlaywrightTestsModule : TestBaseModule { - protected override Task GetTestOptions(IPipelineContext context, string framework, CancellationToken cancellationToken) + protected override Task<(DotNetRunOptions Options, CommandExecutionOptions? ExecutionOptions)> GetTestOptions(IModuleContext context, string framework, CancellationToken cancellationToken) { var project = Sourcy.DotNet.Projects.TUnit_Templates__content__TUnit_Playwright__TestProject; - return Task.FromResult(new DotNetRunOptions - { - Project = project.FullName, - NoBuild = true, - Configuration = Configuration.Release, - EnvironmentVariables = new Dictionary + return Task.FromResult<(DotNetRunOptions, CommandExecutionOptions?)>(( + new DotNetRunOptions { - ["DISABLE_GITHUB_REPORTER"] = "true", + Project = project.FullName, + NoBuild = true, + Configuration = "Release", + }, + new CommandExecutionOptions + { + EnvironmentVariables = new Dictionary + { + ["DISABLE_GITHUB_REPORTER"] = "true", + } } - }); + )); } } diff --git a/TUnit.Pipeline/Modules/RunPublicAPITestsModule.cs b/TUnit.Pipeline/Modules/RunPublicAPITestsModule.cs index 683be1a71c..554866d3f6 100644 --- a/TUnit.Pipeline/Modules/RunPublicAPITestsModule.cs +++ b/TUnit.Pipeline/Modules/RunPublicAPITestsModule.cs @@ -3,6 +3,7 @@ using ModularPipelines.DotNet.Options; using ModularPipelines.Extensions; using ModularPipelines.Git.Extensions; +using ModularPipelines.Options; using TUnit.Pipeline.Modules.Abstract; namespace TUnit.Pipeline.Modules; @@ -10,21 +11,26 @@ namespace TUnit.Pipeline.Modules; [NotInParallel("DotNetTests")] public class RunPublicAPITestsModule : TestBaseModule { - protected override Task GetTestOptions(IPipelineContext context, string framework, CancellationToken cancellationToken) + protected override Task<(DotNetRunOptions Options, CommandExecutionOptions? ExecutionOptions)> GetTestOptions(IModuleContext context, string framework, CancellationToken cancellationToken) { var project = context.Git().RootDirectory.FindFile(x => x.Name == "TUnit.PublicAPI.csproj").AssertExists(); - return Task.FromResult(new DotNetRunOptions - { - WorkingDirectory = project.Folder!, - NoBuild = true, - Configuration = Configuration.Release, - Framework = framework, - EnvironmentVariables = new Dictionary + return Task.FromResult<(DotNetRunOptions, CommandExecutionOptions?)>(( + new DotNetRunOptions { - ["DISABLE_GITHUB_REPORTER"] = "true", - ["GITHUB_ACTIONS"] = "false", + NoBuild = true, + Configuration = "Release", + Framework = framework, }, - }); + new CommandExecutionOptions + { + WorkingDirectory = project.Folder!.Path, + EnvironmentVariables = new Dictionary + { + ["DISABLE_GITHUB_REPORTER"] = "true", + ["GITHUB_ACTIONS"] = "false", + } + } + )); } } diff --git a/TUnit.Pipeline/Modules/RunRpcTestsModule.cs b/TUnit.Pipeline/Modules/RunRpcTestsModule.cs index a85724add0..d7fadbee8b 100644 --- a/TUnit.Pipeline/Modules/RunRpcTestsModule.cs +++ b/TUnit.Pipeline/Modules/RunRpcTestsModule.cs @@ -3,6 +3,7 @@ using ModularPipelines.DotNet.Options; using ModularPipelines.Extensions; using ModularPipelines.Git.Extensions; +using ModularPipelines.Options; using TUnit.Pipeline.Modules.Abstract; namespace TUnit.Pipeline.Modules; @@ -16,21 +17,26 @@ public class RunRpcTestsModule : TestBaseModule "net8.0" ]; - protected override Task GetTestOptions(IPipelineContext context, string framework, CancellationToken cancellationToken) + protected override Task<(DotNetRunOptions Options, CommandExecutionOptions? ExecutionOptions)> GetTestOptions(IModuleContext context, string framework, CancellationToken cancellationToken) { var project = context.Git().RootDirectory.FindFile(x => x.Name == "TUnit.RpcTests.csproj").AssertExists(); - return Task.FromResult(new DotNetRunOptions - { - WorkingDirectory = project.Folder!, - NoBuild = true, - Configuration = Configuration.Release, - Framework = framework, - EnvironmentVariables = new Dictionary + return Task.FromResult<(DotNetRunOptions, CommandExecutionOptions?)>(( + new DotNetRunOptions { - ["DISABLE_GITHUB_REPORTER"] = "true", + NoBuild = true, + Configuration = "Release", + Framework = framework, + Arguments = ["--ignore-exit-code", "8"], }, - Arguments = ["--ignore-exit-code", "8"], - }); + new CommandExecutionOptions + { + WorkingDirectory = project.Folder!.Path, + EnvironmentVariables = new Dictionary + { + ["DISABLE_GITHUB_REPORTER"] = "true", + } + } + )); } } diff --git a/TUnit.Pipeline/Modules/RunSourceGeneratorTestsModule.cs b/TUnit.Pipeline/Modules/RunSourceGeneratorTestsModule.cs index 5eb29f0e14..cfd2596ef3 100644 --- a/TUnit.Pipeline/Modules/RunSourceGeneratorTestsModule.cs +++ b/TUnit.Pipeline/Modules/RunSourceGeneratorTestsModule.cs @@ -3,6 +3,7 @@ using ModularPipelines.DotNet.Options; using ModularPipelines.Extensions; using ModularPipelines.Git.Extensions; +using ModularPipelines.Options; using TUnit.Pipeline.Modules.Abstract; namespace TUnit.Pipeline.Modules; @@ -10,20 +11,25 @@ namespace TUnit.Pipeline.Modules; [NotInParallel("DotNetTests")] public class RunSourceGeneratorTestsModule : TestBaseModule { - protected override Task GetTestOptions(IPipelineContext context, string framework, CancellationToken cancellationToken) + protected override Task<(DotNetRunOptions Options, CommandExecutionOptions? ExecutionOptions)> GetTestOptions(IModuleContext context, string framework, CancellationToken cancellationToken) { var project = context.Git().RootDirectory.FindFile(x => x.Name == "TUnit.Core.SourceGenerator.Tests.csproj").AssertExists(); - return Task.FromResult(new DotNetRunOptions - { - WorkingDirectory = project.Folder!, - NoBuild = true, - Configuration = Configuration.Release, - Framework = framework, - EnvironmentVariables = new Dictionary + return Task.FromResult<(DotNetRunOptions, CommandExecutionOptions?)>(( + new DotNetRunOptions { - ["DISABLE_GITHUB_REPORTER"] = "true", + NoBuild = true, + Configuration = "Release", + Framework = framework, }, - }); + new CommandExecutionOptions + { + WorkingDirectory = project.Folder!.Path, + EnvironmentVariables = new Dictionary + { + ["DISABLE_GITHUB_REPORTER"] = "true", + } + } + )); } } diff --git a/TUnit.Pipeline/Modules/RunTemplateTestsModule.cs b/TUnit.Pipeline/Modules/RunTemplateTestsModule.cs index 6199c64f72..85fc93293d 100644 --- a/TUnit.Pipeline/Modules/RunTemplateTestsModule.cs +++ b/TUnit.Pipeline/Modules/RunTemplateTestsModule.cs @@ -2,33 +2,41 @@ using ModularPipelines.Context; using ModularPipelines.DotNet.Extensions; using ModularPipelines.DotNet.Options; -using ModularPipelines.Enums; using ModularPipelines.Extensions; using ModularPipelines.Git.Extensions; using ModularPipelines.Models; using ModularPipelines.Modules; +using ModularPipelines.Options; namespace TUnit.Pipeline.Modules; [NotInParallel("DotNetTests")] public class RunTemplateTestsModule : Module { - protected override async Task ExecuteAsync(IPipelineContext context, CancellationToken cancellationToken) + protected override async Task ExecuteAsync(IModuleContext context, CancellationToken cancellationToken) { var project = context.Git().RootDirectory.FindFile(x => x.Name == "TUnit.Templates.Tests.csproj").AssertExists(); return await context.DotNet().Test(new DotNetTestOptions { - WorkingDirectory = project.Folder!, NoBuild = true, - Configuration = Configuration.Release, + Configuration = "Release", Framework = "net10.0", Arguments = ["--", "--hangdump", "--hangdump-filename", "hangdump.template-tests.dmp", "--hangdump-timeout", "5m"], + }, new CommandExecutionOptions + { + WorkingDirectory = project.Folder!.Path, EnvironmentVariables = new Dictionary { ["DISABLE_GITHUB_REPORTER"] = "true", }, - CommandLogging = CommandLogging.Input | CommandLogging.Error | CommandLogging.Duration | CommandLogging.ExitCode + LogSettings = new CommandLoggingOptions + { + ShowCommandArguments = true, + ShowStandardError = true, + ShowExecutionTime = true, + ShowExitCode = true + } }, cancellationToken); } } diff --git a/TUnit.Pipeline/Modules/RunUnitTestsModule.cs b/TUnit.Pipeline/Modules/RunUnitTestsModule.cs index e24e0e9627..cb1d7afe6b 100644 --- a/TUnit.Pipeline/Modules/RunUnitTestsModule.cs +++ b/TUnit.Pipeline/Modules/RunUnitTestsModule.cs @@ -3,6 +3,7 @@ using ModularPipelines.DotNet.Options; using ModularPipelines.Extensions; using ModularPipelines.Git.Extensions; +using ModularPipelines.Options; using TUnit.Pipeline.Modules.Abstract; namespace TUnit.Pipeline.Modules; @@ -10,20 +11,25 @@ namespace TUnit.Pipeline.Modules; [NotInParallel("DotNetTests")] public class RunUnitTestsModule : TestBaseModule { - protected override Task GetTestOptions(IPipelineContext context, string framework, CancellationToken cancellationToken) + protected override Task<(DotNetRunOptions Options, CommandExecutionOptions? ExecutionOptions)> GetTestOptions(IModuleContext context, string framework, CancellationToken cancellationToken) { var project = context.Git().RootDirectory.FindFile(x => x.Name == "TUnit.UnitTests.csproj").AssertExists(); - return Task.FromResult(new DotNetRunOptions - { - WorkingDirectory = project.Folder!, - NoBuild = true, - Configuration = Configuration.Release, - Framework = framework, - EnvironmentVariables = new Dictionary + return Task.FromResult<(DotNetRunOptions, CommandExecutionOptions?)>(( + new DotNetRunOptions { - ["TUNIT_DISABLE_GITHUB_REPORTER"] = "true", + NoBuild = true, + Configuration = "Release", + Framework = framework, + }, + new CommandExecutionOptions + { + WorkingDirectory = project.Folder!.Path, + EnvironmentVariables = new Dictionary + { + ["TUNIT_DISABLE_GITHUB_REPORTER"] = "true", + } } - }); + )); } } diff --git a/TUnit.Pipeline/Modules/TestAspNetCoreNugetPackageModule.cs b/TUnit.Pipeline/Modules/TestAspNetCoreNugetPackageModule.cs index 718826f48b..1ea45872fb 100644 --- a/TUnit.Pipeline/Modules/TestAspNetCoreNugetPackageModule.cs +++ b/TUnit.Pipeline/Modules/TestAspNetCoreNugetPackageModule.cs @@ -1,10 +1,11 @@ using ModularPipelines.Attributes; +using ModularPipelines.Configuration; using ModularPipelines.Context; using ModularPipelines.DotNet.Options; using ModularPipelines.Extensions; using ModularPipelines.Git.Extensions; using ModularPipelines.Models; -using Polly.Retry; +using ModularPipelines.Options; using TUnit.Pipeline.Modules.Abstract; namespace TUnit.Pipeline.Modules; @@ -13,8 +14,9 @@ namespace TUnit.Pipeline.Modules; [DependsOn] public class TestAspNetCoreNugetPackageModule : TestBaseModule { - protected override AsyncRetryPolicy?> RetryPolicy - => CreateRetryPolicy(3); + protected override ModuleConfiguration Configure() => ModuleConfiguration.Create() + .WithRetryCount(3) + .Build(); // ASP.NET Core only supports .NET Core frameworks, not .NET Framework protected override IEnumerable TestableFrameworks @@ -27,10 +29,10 @@ protected override IEnumerable TestableFrameworks } } - protected override async Task GetTestOptions(IPipelineContext context, string framework, + protected override async Task<(DotNetRunOptions Options, CommandExecutionOptions? ExecutionOptions)> GetTestOptions(IModuleContext context, string framework, CancellationToken cancellationToken) { - var version = await GetModule(); + var version = await context.GetModule(); var project = context.Git() .RootDirectory @@ -38,19 +40,24 @@ protected override async Task GetTestOptions(IPipelineContext .FindFile(x => x.Name == "TUnit.AspNetCore.NugetTester.csproj") .AssertExists(); - return new DotNetRunOptions - { - WorkingDirectory = project.Folder!, - Framework = framework, - Properties = - [ - new KeyValue("TUnitVersion", version.Value!.SemVer!) - ], - Arguments = - [ - "--coverage", - "--report-trx" - ] - }; + return ( + new DotNetRunOptions + { + Framework = framework, + Properties = + [ + new KeyValue("TUnitVersion", version.ValueOrDefault!.SemVer!) + ], + Arguments = + [ + "--coverage", + "--report-trx" + ] + }, + new CommandExecutionOptions + { + WorkingDirectory = project.Folder!.Path, + } + ); } } diff --git a/TUnit.Pipeline/Modules/TestNugetPackageModule.cs b/TUnit.Pipeline/Modules/TestNugetPackageModule.cs index d10bc1702d..537ce328fc 100644 --- a/TUnit.Pipeline/Modules/TestNugetPackageModule.cs +++ b/TUnit.Pipeline/Modules/TestNugetPackageModule.cs @@ -1,11 +1,12 @@ using System.Runtime.InteropServices; using ModularPipelines.Attributes; +using ModularPipelines.Configuration; using ModularPipelines.Context; using ModularPipelines.DotNet.Options; using ModularPipelines.Extensions; using ModularPipelines.Git.Extensions; using ModularPipelines.Models; -using Polly.Retry; +using ModularPipelines.Options; using TUnit.Pipeline.Modules.Abstract; namespace TUnit.Pipeline.Modules; @@ -31,8 +32,10 @@ public class TestVBNugetPackageModule : AbstractTestNugetPackageModule [DependsOn] public abstract class AbstractTestNugetPackageModule : TestBaseModule { - protected override AsyncRetryPolicy?> RetryPolicy - => CreateRetryPolicy(3); + protected override ModuleConfiguration Configure() => ModuleConfiguration.Create() + .WithRetryCount(3) + .Build(); + protected override IEnumerable TestableFrameworks { get @@ -50,10 +53,10 @@ protected override IEnumerable TestableFrameworks } } - protected override async Task GetTestOptions(IPipelineContext context, string framework, + protected override async Task<(DotNetRunOptions Options, CommandExecutionOptions? ExecutionOptions)> GetTestOptions(IModuleContext context, string framework, CancellationToken cancellationToken) { - var version = await GetModule(); + var version = await context.GetModule(); var project = context.Git() .RootDirectory @@ -61,20 +64,25 @@ protected override async Task GetTestOptions(IPipelineContext .FindFile(x => x.Name == ProjectName) .AssertExists(); - return new DotNetRunOptions - { - WorkingDirectory = project.Folder!, - Framework = framework, - Properties = - [ - new KeyValue("TUnitVersion", version.Value!.SemVer!) - ], - Arguments = - [ - "--coverage", - "--report-trx" - ] - }; + return ( + new DotNetRunOptions + { + Framework = framework, + Properties = + [ + new KeyValue("TUnitVersion", version.ValueOrDefault!.SemVer!) + ], + Arguments = + [ + "--coverage", + "--report-trx" + ] + }, + new CommandExecutionOptions + { + WorkingDirectory = project.Folder!.Path, + } + ); } public abstract string ProjectName { get; } diff --git a/TUnit.Pipeline/Modules/TestTemplatePackageModule.cs b/TUnit.Pipeline/Modules/TestTemplatePackageModule.cs index 774a2107c5..f01500888e 100644 --- a/TUnit.Pipeline/Modules/TestTemplatePackageModule.cs +++ b/TUnit.Pipeline/Modules/TestTemplatePackageModule.cs @@ -2,9 +2,9 @@ using ModularPipelines.Context; using ModularPipelines.DotNet.Extensions; using ModularPipelines.DotNet.Options; -using ModularPipelines.Enums; using ModularPipelines.Models; using ModularPipelines.Modules; +using ModularPipelines.Options; namespace TUnit.Pipeline.Modules; @@ -12,40 +12,68 @@ namespace TUnit.Pipeline.Modules; [DependsOn] public class TestTemplatePackageModule : Module { - protected override async Task ExecuteAsync(IPipelineContext context, + protected override async Task ExecuteAsync(IModuleContext context, CancellationToken cancellationToken) { - var version = await GetModule(); + var version = await context.GetModule(); - await context.DotNet().New(new DotNetNewOptions("uninstall") + var logSettings = new CommandLoggingOptions + { + ShowCommandArguments = true, + ShowStandardError = true, + ShowExecutionTime = true, + ShowExitCode = true + }; + + // Uninstall existing template + await context.DotNet().New.Execute(new DotNetNewOptions + { + TemplateShortName = "uninstall", + TemplateArgs = "TUnit.Templates", + }, new CommandExecutionOptions { - Arguments = ["TUnit.Templates"], ThrowOnNonZeroExitCode = false, - CommandLogging = CommandLogging.Input | CommandLogging.Error | CommandLogging.Duration | CommandLogging.ExitCode + LogSettings = logSettings }, cancellationToken); - await context.DotNet().New(new DotNetNewOptions("install") + // Install template with specific version + await context.DotNet().New.Execute(new DotNetNewOptions + { + TemplateShortName = "install", + TemplateArgs = $"TUnit.Templates::{version.ValueOrDefault!.SemVer}", + }, new CommandExecutionOptions { - Arguments = [$"TUnit.Templates::{version.Value!.SemVer}"], - CommandLogging = CommandLogging.Input | CommandLogging.Error | CommandLogging.Duration | CommandLogging.ExitCode + LogSettings = logSettings }, cancellationToken); - await context.DotNet().New(new DotNetNewOptions("TUnit") + // Create TUnit project + await context.DotNet().New.Execute(new DotNetNewOptions { + TemplateShortName = "TUnit", Name = "MyTestProject", - CommandLogging = CommandLogging.Input | CommandLogging.Error | CommandLogging.Duration | CommandLogging.ExitCode + }, new CommandExecutionOptions + { + LogSettings = logSettings }, cancellationToken); - await context.DotNet().New(new DotNetNewOptions("TUnit.AspNet") + // Create TUnit.AspNet project + await context.DotNet().New.Execute(new DotNetNewOptions { + TemplateShortName = "TUnit.AspNet", Name = "MyTestProject2", - CommandLogging = CommandLogging.Input | CommandLogging.Error | CommandLogging.Duration | CommandLogging.ExitCode + }, new CommandExecutionOptions + { + LogSettings = logSettings }, cancellationToken); - return await context.DotNet().New(new DotNetNewOptions("TUnit.Playwright") + // Create TUnit.Playwright project + return await context.DotNet().New.Execute(new DotNetNewOptions { + TemplateShortName = "TUnit.Playwright", Name = "MyTestProject3", - CommandLogging = CommandLogging.Input | CommandLogging.Error | CommandLogging.Duration | CommandLogging.ExitCode + }, new CommandExecutionOptions + { + LogSettings = logSettings }, cancellationToken); } } diff --git a/TUnit.Pipeline/Modules/UploadToNuGetModule.cs b/TUnit.Pipeline/Modules/UploadToNuGetModule.cs index 76144cdb4a..2a9db11038 100644 --- a/TUnit.Pipeline/Modules/UploadToNuGetModule.cs +++ b/TUnit.Pipeline/Modules/UploadToNuGetModule.cs @@ -1,14 +1,15 @@ using EnumerableAsyncProcessor.Extensions; using Microsoft.Extensions.Options; using ModularPipelines.Attributes; +using ModularPipelines.Configuration; using ModularPipelines.Context; using ModularPipelines.DotNet.Extensions; using ModularPipelines.DotNet.Options; -using ModularPipelines.Enums; using ModularPipelines.Git.Attributes; using ModularPipelines.Git.Extensions; using ModularPipelines.Models; using ModularPipelines.Modules; +using ModularPipelines.Options; namespace TUnit.Pipeline.Modules; @@ -20,32 +21,43 @@ namespace TUnit.Pipeline.Modules; [DependsOn] public class UploadToNuGetModule(IOptions options) : Module { - protected override Task ShouldSkip(IPipelineContext context) - { - if (!options.Value.ShouldPublish) + protected override ModuleConfiguration Configure() => ModuleConfiguration.Create() + .WithSkipWhen(_ => { - return Task.FromResult("Should Publish is false"); - } + if (!options.Value.ShouldPublish) + { + return SkipDecision.Skip("Should Publish is false"); + } - if (string.IsNullOrEmpty(options.Value.ApiKey)) - { - return Task.FromResult("No API key found"); - } + if (string.IsNullOrEmpty(options.Value.ApiKey)) + { + return SkipDecision.Skip("No API key found"); + } - return Task.FromResult(false); - } + return SkipDecision.DoNotSkip; + }) + .Build(); - protected override async Task ExecuteAsync(IPipelineContext context, CancellationToken cancellationToken) + protected override async Task ExecuteAsync(IModuleContext context, CancellationToken cancellationToken) { var nupkgs = context.Git().RootDirectory .GetFiles(x => x.NameWithoutExtension.Contains("TUnit") && x.Extension is ".nupkg"); return await nupkgs.SelectAsync(file => - context.DotNet().Nuget.Push(new DotNetNugetPushOptions(file) + context.DotNet().Nuget.Push(new DotNetNugetPushOptions { + Path = file.Path, Source = "https://api.nuget.org/v3/index.json", ApiKey = options.Value.ApiKey, - CommandLogging = CommandLogging.Input | CommandLogging.Error | CommandLogging.Duration | CommandLogging.ExitCode + }, new CommandExecutionOptions + { + LogSettings = new CommandLoggingOptions + { + ShowCommandArguments = true, + ShowStandardError = true, + ShowExecutionTime = true, + ShowExitCode = true + } }, cancellationToken), cancellationToken: cancellationToken) .ProcessOneAtATime(); } diff --git a/TUnit.Pipeline/Program.cs b/TUnit.Pipeline/Program.cs index 7d9881253a..88098bebd5 100644 --- a/TUnit.Pipeline/Program.cs +++ b/TUnit.Pipeline/Program.cs @@ -1,8 +1,8 @@ using System.CommandLine; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; +using ModularPipelines; using ModularPipelines.Extensions; -using ModularPipelines.Host; using ModularPipelines.Options; using TUnit.Pipeline; @@ -17,35 +17,26 @@ var rootCommand = new RootCommand("The pipeline for building, testing and packaging TUnit"); rootCommand.Add(categoryOption); -rootCommand.SetAction(parseResult => +rootCommand.SetAction(async parseResult => { var categories = parseResult.GetValue(categoryOption)!; - var pipelineHostBuilder = PipelineHostBuilder.Create() - .ConfigureAppConfiguration((_, builder) => - { - builder.AddEnvironmentVariables(); - }) - .ConfigureServices((context, collection) => - { - collection.Configure(context.Configuration.GetSection("NuGet")); - collection.AddModulesFromAssembly(typeof(Program).Assembly); - }) - .ConfigurePipelineOptions((_, options) => options.ExecutionMode = ExecutionMode.WaitForAllModules); + var builder = Pipeline.CreateBuilder(); + builder.Configuration.AddEnvironmentVariables(); + builder.Services.Configure(builder.Configuration.GetSection("NuGet")); + builder.Services.AddModulesFromAssembly(typeof(Program).Assembly); + builder.Options.ExecutionMode = ExecutionMode.WaitForAllModules; if (categories.Length > 0) { - pipelineHostBuilder.RunCategories(categories); + builder.RunCategories(categories); } else { - pipelineHostBuilder.IgnoreCategories("ReadMe"); + builder.IgnoreCategories("ReadMe"); } - pipelineHostBuilder - .ExecutePipelineAsync() - .GetAwaiter() - .GetResult(); + await builder.Build().RunAsync(); }); return await rootCommand.Parse(args).InvokeAsync(); diff --git a/TUnit.Pipeline/TUnit.Pipeline.csproj b/TUnit.Pipeline/TUnit.Pipeline.csproj index 396086de73..1bfe6325f3 100644 --- a/TUnit.Pipeline/TUnit.Pipeline.csproj +++ b/TUnit.Pipeline/TUnit.Pipeline.csproj @@ -1,6 +1,7 @@ net10.0 + net10.0 false false From aab156b91ba2b5463cef9fde10c8e829336d1571 Mon Sep 17 00:00:00 2001 From: Tom Longhurst <30480171+thomhurst@users.noreply.github.com> Date: Fri, 16 Jan 2026 20:54:45 +0000 Subject: [PATCH 2/8] chore(deps): update ModularPipelines packages to v2.48.528-alpha0001 --- Directory.Packages.props | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 38b4438e4f..ca0ab9873a 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -47,9 +47,9 @@ - - - + + + From 614824d87298324de7e59329bff809b1b17f2cf3 Mon Sep 17 00:00:00 2001 From: Tom Longhurst <30480171+thomhurst@users.noreply.github.com> Date: Fri, 16 Jan 2026 13:11:42 +0000 Subject: [PATCH 3/8] chore: migrate ModularPipelines to v3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update TUnit.Pipeline to use ModularPipelines v3 APIs: - Entry point: `builder.BuildPipeline()` → `builder.Build()` - `IPipelineContext` → `IModuleContext` - `context.GetModule()` instead of direct GetModule - `context.SubModule()` instead of SubModule() - `ModuleResult.Value` → `ValueOrDefault` - `result.SkipDecision.ShouldSkip` → `result.IsSkipped` - `result.HasValue` → `result.IsSuccess` - `CommandLogging` → `CommandLoggingOptions` with boolean properties - Tool options separated from `CommandExecutionOptions` - Tool options use property initializers (no constructors) - Git commands use `Arguments` property for non-typed values - `Shell.Bash.Command(new BashCommandOptions(cmd), token)` - `DotNet().New.Execute()` for template operations Co-Authored-By: Claude Opus 4.5 --- Directory.Packages.props | 8 +-- .../Modules/Abstract/TestBaseModule.cs | 47 +++++++-------- .../Modules/AddLocalNuGetRepositoryModule.cs | 23 ++++++-- TUnit.Pipeline/Modules/CommitFilesModule.cs | 53 +++++++++-------- .../Modules/CopyToLocalNuGetModule.cs | 6 +- TUnit.Pipeline/Modules/CreateReleaseModule.cs | 27 +++++---- .../Modules/GenerateReadMeModule.cs | 8 ++- .../Modules/GenerateVersionModule.cs | 8 +-- .../Modules/GetPackageProjectsModule.cs | 2 +- .../Modules/PackTUnitFilesModule.cs | 27 ++++++--- .../Modules/ProcessorParallelLimit.cs | 2 +- .../Modules/PublishNugetTesterAOTModule.cs | 39 ++++++++----- .../Modules/PushVersionTagModule.cs | 24 ++++---- .../Modules/RunAnalyzersTestsModule.cs | 18 ++++-- .../RunAspNetCoreAnalyzersTestsModule.cs | 18 ++++-- .../Modules/RunAspNetTestsModule.cs | 18 ++++-- .../RunAssertionsAnalyzersTestsModule.cs | 18 ++++-- .../RunAssertionsCodeFixersTestsModule.cs | 18 ++++-- .../Modules/RunAssertionsTestsModule.cs | 26 +++++---- .../Modules/RunEngineTestsModule.cs | 18 ++++-- .../Modules/RunPlaywrightTestsModule.cs | 24 +++++--- .../Modules/RunPublicAPITestsModule.cs | 28 +++++---- TUnit.Pipeline/Modules/RunRpcTestsModule.cs | 28 +++++---- .../Modules/RunSourceGeneratorTestsModule.cs | 26 +++++---- .../Modules/RunTemplateTestsModule.cs | 18 ++++-- TUnit.Pipeline/Modules/RunUnitTestsModule.cs | 26 +++++---- .../TestAspNetCoreNugetPackageModule.cs | 45 ++++++++------ .../Modules/TestNugetPackageModule.cs | 46 +++++++++------ .../Modules/TestTemplatePackageModule.cs | 58 ++++++++++++++----- TUnit.Pipeline/Modules/UploadToNuGetModule.cs | 42 +++++++++----- TUnit.Pipeline/Program.cs | 29 ++++------ TUnit.Pipeline/TUnit.Pipeline.csproj | 1 + 32 files changed, 480 insertions(+), 299 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 3c212fca7f..5fc28b5da4 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -47,9 +47,9 @@ - - - + + + @@ -101,4 +101,4 @@ - + \ No newline at end of file diff --git a/TUnit.Pipeline/Modules/Abstract/TestBaseModule.cs b/TUnit.Pipeline/Modules/Abstract/TestBaseModule.cs index 481e4167a3..6a02fa1f91 100644 --- a/TUnit.Pipeline/Modules/Abstract/TestBaseModule.cs +++ b/TUnit.Pipeline/Modules/Abstract/TestBaseModule.cs @@ -2,9 +2,9 @@ using ModularPipelines.Context; using ModularPipelines.DotNet.Extensions; using ModularPipelines.DotNet.Options; -using ModularPipelines.Enums; using ModularPipelines.Models; using ModularPipelines.Modules; +using ModularPipelines.Options; namespace TUnit.Pipeline.Modules.Abstract; @@ -24,17 +24,19 @@ protected virtual IEnumerable TestableFrameworks } } - protected sealed override async Task?> ExecuteAsync(IPipelineContext context, CancellationToken cancellationToken) + protected sealed override async Task?> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken) { var results = new List(); foreach (var framework in TestableFrameworks) { - var testResult = await SubModule(framework, async () => + var testResult = await context.SubModule(framework, async () => { - var testOptions = SetDefaults(await GetTestOptions(context, framework, cancellationToken)); + var (testOptions, executionOptions) = await GetTestOptions(context, framework, cancellationToken); - return await context.DotNet().Run(testOptions, cancellationToken); + var finalExecutionOptions = SetDefaults(testOptions, executionOptions ?? new CommandExecutionOptions(), framework); + + return await context.DotNet().Run(testOptions, finalExecutionOptions, cancellationToken); }); results.Add(testResult); @@ -43,35 +45,30 @@ protected virtual IEnumerable TestableFrameworks return results; } - private DotNetRunOptions SetDefaults(DotNetRunOptions testOptions) + private CommandExecutionOptions SetDefaults(DotNetRunOptions testOptions, CommandExecutionOptions executionOptions, string framework) { - if (testOptions.EnvironmentVariables?.Any(x => x.Key == "NET_VERSION") != true) + var envVars = executionOptions.EnvironmentVariables ?? new Dictionary(); + if (!envVars.ContainsKey("NET_VERSION")) { - testOptions = testOptions with + envVars = new Dictionary(envVars) { - EnvironmentVariables = new Dictionary - { - ["NET_VERSION"] = testOptions.Framework, - } + ["NET_VERSION"] = framework }; } - // Add hangdump flags with 20 minute timeout - var arguments = testOptions.Arguments?.ToList() ?? new List(); - if (!arguments.Contains("--hangdump")) - { - arguments.AddRange(["--hangdump", "--hangdump-filename", $"hangdump.{Environment.OSVersion.Platform}.{GetType().Name}.dmp", "--hangdump-timeout", "5m"]); - } - // Suppress output for successful operations, but show errors and basic info - testOptions = testOptions with + return executionOptions with { - Arguments = arguments, - CommandLogging = CommandLogging.Input | CommandLogging.Error | CommandLogging.Duration | CommandLogging.ExitCode + EnvironmentVariables = envVars, + LogSettings = new CommandLoggingOptions + { + ShowCommandArguments = true, + ShowStandardError = true, + ShowExecutionTime = true, + ShowExitCode = true + } }; - - return testOptions; } - protected abstract Task GetTestOptions(IPipelineContext context, string framework, CancellationToken cancellationToken); + protected abstract Task<(DotNetRunOptions Options, CommandExecutionOptions? ExecutionOptions)> GetTestOptions(IModuleContext context, string framework, CancellationToken cancellationToken); } diff --git a/TUnit.Pipeline/Modules/AddLocalNuGetRepositoryModule.cs b/TUnit.Pipeline/Modules/AddLocalNuGetRepositoryModule.cs index f37d3b3b40..33cf74c7c6 100644 --- a/TUnit.Pipeline/Modules/AddLocalNuGetRepositoryModule.cs +++ b/TUnit.Pipeline/Modules/AddLocalNuGetRepositoryModule.cs @@ -1,20 +1,33 @@ using ModularPipelines.Context; using ModularPipelines.DotNet.Extensions; using ModularPipelines.DotNet.Options; -using ModularPipelines.Enums; using ModularPipelines.FileSystem; using ModularPipelines.Modules; +using ModularPipelines.Options; namespace TUnit.Pipeline.Modules; public class AddLocalNuGetRepositoryModule : Module { - protected override async Task ExecuteAsync(IPipelineContext context, CancellationToken cancellationToken) + protected override async Task ExecuteAsync(IModuleContext context, CancellationToken cancellationToken) { - var folder = context.FileSystem.GetFolder(Environment.SpecialFolder.LocalApplicationData).GetFolder("LocalNuget").Create(); - await context.DotNet().Nuget.Add.Source(new DotNetNugetAddSourceOptions(folder) + var localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); + var folder = new Folder(Path.Combine(localAppData, "LocalNuget")); + folder.Create(); + + await context.DotNet().Nuget.Add.Source(new DotNetNugetAddSourceOptions + { + Name = "LocalNuget", + Packagesourcepath = folder.Path, + }, new CommandExecutionOptions { - CommandLogging = CommandLogging.Input | CommandLogging.Error | CommandLogging.Duration | CommandLogging.ExitCode + LogSettings = new CommandLoggingOptions + { + ShowCommandArguments = true, + ShowStandardError = true, + ShowExecutionTime = true, + ShowExitCode = true + } }, cancellationToken); return folder; } diff --git a/TUnit.Pipeline/Modules/CommitFilesModule.cs b/TUnit.Pipeline/Modules/CommitFilesModule.cs index c8feb2a2e9..854479a4f5 100644 --- a/TUnit.Pipeline/Modules/CommitFilesModule.cs +++ b/TUnit.Pipeline/Modules/CommitFilesModule.cs @@ -1,4 +1,5 @@ using ModularPipelines.Attributes; +using ModularPipelines.Configuration; using ModularPipelines.Context; using ModularPipelines.Extensions; using ModularPipelines.Git.Attributes; @@ -24,21 +25,25 @@ namespace TUnit.Pipeline.Modules; [ModuleCategory("ReadMe")] public class CommitFilesModule : Module { - protected override async Task ShouldSkip(IPipelineContext context) - { - var generateReadMeModule = GetModuleIfRegistered(); - - if (generateReadMeModule is null) + protected override ModuleConfiguration Configure() => ModuleConfiguration.Create() + .WithSkipWhen(async ctx => { - return "Nothing to commit"; - } + var generateReadMeModule = ctx.GetModuleIfRegistered(); + + if (generateReadMeModule is null) + { + return SkipDecision.Skip("Nothing to commit"); + } - var result = await generateReadMeModule; + var result = await generateReadMeModule; - return result.SkipDecision.ShouldSkip || !result.HasValue; - } + return result.IsSkipped || !result.IsSuccess + ? SkipDecision.Skip("GenerateReadMeModule was skipped or has no value") + : SkipDecision.DoNotSkip; + }) + .Build(); - protected override async Task ExecuteAsync(IPipelineContext context, CancellationToken cancellationToken) + protected override async Task ExecuteAsync(IModuleContext context, CancellationToken cancellationToken) { var repositoryId = long.Parse(context.GitHub().EnvironmentVariables.RepositoryId!); @@ -46,33 +51,36 @@ await context.Git().Commands.Config(new GitConfigOptions { Global = true, Arguments = ["user.name", context.GitHub().EnvironmentVariables.Actor!] - }, cancellationToken); + }, token: cancellationToken); await context.Git().Commands.Config(new GitConfigOptions { Global = true, Arguments = ["user.email", $"{context.GitHub().EnvironmentVariables.ActorId!}_{context.GitHub().EnvironmentVariables.Actor!}@users.noreply.github.com"] - }, cancellationToken); + }, token: cancellationToken); var newBranchName = $"feature/readme-{Guid.NewGuid():N}"; - await context.Git().Commands.Checkout(new GitCheckoutOptions(newBranchName, true), cancellationToken); + await context.Git().Commands.Checkout(new GitCheckoutOptions(newBranchName, true), token: cancellationToken); await context.Git().Commands.Add(new GitAddOptions { Arguments = ["README.md"], - WorkingDirectory = context.Git().RootDirectory.AssertExists() + }, new CommandExecutionOptions + { + WorkingDirectory = context.Git().RootDirectory.AssertExists().Path }, cancellationToken); await context.Git().Commands.Commit(new GitCommitOptions { Message = "Update README.md" - }, cancellationToken); + }, token: cancellationToken); await context.Git().Commands.Push(new GitPushOptions { - Arguments = ["--set-upstream", "origin", newBranchName] - }, cancellationToken); + SetUpstream = true, + Arguments = ["origin", newBranchName] + }, token: cancellationToken); await context.Git().Commands.Push(token: cancellationToken); @@ -85,12 +93,7 @@ await context.Git().Commands.Push(new GitPushOptions await context.GitHub().Client.Issue.Update(repositoryId, pr.Number, issueUpdate); - return await context.Command.ExecuteCommandLineTool(new CommandLineToolOptions("gh", "pr", "merge", "--admin", "--squash", pr.Number.ToString()) - { - EnvironmentVariables = new Dictionary - { - ["GH_TOKEN"] = Environment.GetEnvironmentVariable("ADMIN_TOKEN") - } - }, cancellationToken); + var adminToken = Environment.GetEnvironmentVariable("ADMIN_TOKEN"); + return await context.Shell.Bash.Command(new BashCommandOptions($"GH_TOKEN={adminToken} gh pr merge --admin --squash {pr.Number}"), cancellationToken); } } diff --git a/TUnit.Pipeline/Modules/CopyToLocalNuGetModule.cs b/TUnit.Pipeline/Modules/CopyToLocalNuGetModule.cs index 36787c5ecf..7baa2a2db2 100644 --- a/TUnit.Pipeline/Modules/CopyToLocalNuGetModule.cs +++ b/TUnit.Pipeline/Modules/CopyToLocalNuGetModule.cs @@ -9,11 +9,11 @@ namespace TUnit.Pipeline.Modules; [DependsOn] public class CopyToLocalNuGetModule : Module> { - protected override async Task?> ExecuteAsync(IPipelineContext context, CancellationToken cancellationToken) + protected override async Task?> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken) { - var folder = await GetModule(); + var folder = await context.GetModule(); return context.Git().RootDirectory.GetFiles(x => x.Name.StartsWith("TUnit", StringComparison.InvariantCultureIgnoreCase) && x.Extension.EndsWith("nupkg")) - .Select(x => x.CopyTo(folder.Value!)) + .Select(x => x.CopyTo(folder.ValueOrDefault!)) .ToList(); } } diff --git a/TUnit.Pipeline/Modules/CreateReleaseModule.cs b/TUnit.Pipeline/Modules/CreateReleaseModule.cs index afae921c5d..860bc4029c 100644 --- a/TUnit.Pipeline/Modules/CreateReleaseModule.cs +++ b/TUnit.Pipeline/Modules/CreateReleaseModule.cs @@ -1,4 +1,5 @@ using ModularPipelines.Attributes; +using ModularPipelines.Configuration; using ModularPipelines.Context; using ModularPipelines.Git.Attributes; using ModularPipelines.GitHub.Extensions; @@ -14,23 +15,27 @@ namespace TUnit.Pipeline.Modules; [DependsOn] public class CreateReleaseModule : Module { - protected override async Task ShouldSkip(IPipelineContext context) - { - if (GetModuleIfRegistered() is not { } uploadToNuGetModule) + protected override ModuleConfiguration Configure() => ModuleConfiguration.Create() + .WithSkipWhen(async ctx => { - return true; - } + if (ctx.GetModuleIfRegistered() is not { } uploadToNuGetModule) + { + return SkipDecision.Skip("UploadToNuGetModule not registered"); + } - var result = await uploadToNuGetModule; + var result = await uploadToNuGetModule; - return result.SkipDecision.ShouldSkip; - } + return result.IsSkipped + ? SkipDecision.Skip("UploadToNuGetModule was skipped") + : SkipDecision.DoNotSkip; + }) + .Build(); - protected override async Task ExecuteAsync(IPipelineContext context, CancellationToken cancellationToken) + protected override async Task ExecuteAsync(IModuleContext context, CancellationToken cancellationToken) { - var versionModule = await GetModule(); + var versionModule = await context.GetModule(); - var version = versionModule.Value!.SemVer; + var version = versionModule.ValueOrDefault!.SemVer; var repositoryId = long.Parse(context.GitHub().EnvironmentVariables.RepositoryId!); diff --git a/TUnit.Pipeline/Modules/GenerateReadMeModule.cs b/TUnit.Pipeline/Modules/GenerateReadMeModule.cs index 45b8f5f4fb..f31be6dc7c 100644 --- a/TUnit.Pipeline/Modules/GenerateReadMeModule.cs +++ b/TUnit.Pipeline/Modules/GenerateReadMeModule.cs @@ -1,4 +1,5 @@ -using System.Text; +using System.IO.Compression; +using System.Text; using Microsoft.Extensions.Logging; using ModularPipelines.Attributes; using ModularPipelines.Context; @@ -20,7 +21,7 @@ namespace TUnit.Pipeline.Modules; [ModuleCategory("ReadMe")] public class GenerateReadMeModule : Module { - protected override async Task ExecuteAsync(IPipelineContext context, CancellationToken cancellationToken) + protected override async Task ExecuteAsync(IModuleContext context, CancellationToken cancellationToken) { var template = await context.Git() .RootDirectory @@ -90,7 +91,8 @@ public class GenerateReadMeModule : Module var downloadedZip = File.GetNewTemporaryFilePath(); await downloadedZip.WriteAsync(stream, cancellationToken); - var unzippedDirectory = context.Zip.UnZipToFolder(downloadedZip, Folder.CreateTemporaryFolder()); + var unzippedDirectory = Folder.CreateTemporaryFolder(); + ZipFile.ExtractToDirectory(downloadedZip.Path, unzippedDirectory.Path); var markdownFile = unzippedDirectory.FindFile(x => x.Extension == ".md").AssertExists(); diff --git a/TUnit.Pipeline/Modules/GenerateVersionModule.cs b/TUnit.Pipeline/Modules/GenerateVersionModule.cs index 4f8699fc9d..5ffe70d796 100644 --- a/TUnit.Pipeline/Modules/GenerateVersionModule.cs +++ b/TUnit.Pipeline/Modules/GenerateVersionModule.cs @@ -1,5 +1,5 @@ -using ModularPipelines.Context; -using ModularPipelines.Extensions; +using Microsoft.Extensions.Logging; +using ModularPipelines.Context; using ModularPipelines.Git.Extensions; using ModularPipelines.Git.Models; using ModularPipelines.Modules; @@ -8,11 +8,11 @@ namespace TUnit.Pipeline.Modules; public class GenerateVersionModule : Module { - protected override async Task ExecuteAsync(IPipelineContext context, CancellationToken cancellationToken) + protected override async Task ExecuteAsync(IModuleContext context, CancellationToken cancellationToken) { var versionInformation = await context.Git().Versioning.GetGitVersioningInformation(); - context.LogOnPipelineEnd($"NuGet Version is: {versionInformation.SemVer}"); + context.Logger.LogInformation("NuGet Version is: {SemVer}", versionInformation.SemVer); return versionInformation; } diff --git a/TUnit.Pipeline/Modules/GetPackageProjectsModule.cs b/TUnit.Pipeline/Modules/GetPackageProjectsModule.cs index fa83ebc66a..d7ba373019 100644 --- a/TUnit.Pipeline/Modules/GetPackageProjectsModule.cs +++ b/TUnit.Pipeline/Modules/GetPackageProjectsModule.cs @@ -6,7 +6,7 @@ namespace TUnit.Pipeline.Modules; public class GetPackageProjectsModule : Module> { - protected override async Task?> ExecuteAsync(IPipelineContext context, CancellationToken cancellationToken) + protected override async Task?> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken) { await Task.CompletedTask; diff --git a/TUnit.Pipeline/Modules/PackTUnitFilesModule.cs b/TUnit.Pipeline/Modules/PackTUnitFilesModule.cs index 5b671c1ee3..c477ffd418 100644 --- a/TUnit.Pipeline/Modules/PackTUnitFilesModule.cs +++ b/TUnit.Pipeline/Modules/PackTUnitFilesModule.cs @@ -2,9 +2,9 @@ using ModularPipelines.Context; using ModularPipelines.DotNet.Extensions; using ModularPipelines.DotNet.Options; -using ModularPipelines.Enums; using ModularPipelines.Models; using ModularPipelines.Modules; +using ModularPipelines.Options; namespace TUnit.Pipeline.Modules; @@ -13,24 +13,25 @@ namespace TUnit.Pipeline.Modules; [DependsOn] public class PackTUnitFilesModule : Module> { - protected override async Task?> ExecuteAsync(IPipelineContext context, + protected override async Task?> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken) { - var projects = await GetModule(); - var versionResult = await GetModule(); + var projects = await context.GetModule(); + var versionResult = await context.GetModule(); - var version = versionResult.Value!; + var version = versionResult.ValueOrDefault!; var packageVersion = version.SemVer!; var packedProjects = new List(); - foreach (var project in projects.Value!) + foreach (var project in projects.ValueOrDefault!) { await context.DotNet() .Pack( - new DotNetPackOptions(project) + new DotNetPackOptions { + ProjectSolution = project.Path, Properties = [ new KeyValue("Version", version.SemVer!), @@ -39,8 +40,16 @@ await context.DotNet() new KeyValue("IsPackTarget", "true") ], IncludeSource = project == Sourcy.DotNet.Projects.TUnit_Templates ? false : true, - Configuration = Configuration.Release, - CommandLogging = CommandLogging.Input | CommandLogging.Error | CommandLogging.Duration | CommandLogging.ExitCode + Configuration = "Release", + }, new CommandExecutionOptions + { + LogSettings = new CommandLoggingOptions + { + ShowCommandArguments = true, + ShowStandardError = true, + ShowExecutionTime = true, + ShowExitCode = true + } }, cancellationToken); packedProjects.Add(new PackedProject(project.NameWithoutExtension, version.SemVer!)); diff --git a/TUnit.Pipeline/Modules/ProcessorParallelLimit.cs b/TUnit.Pipeline/Modules/ProcessorParallelLimit.cs index 6d9728539a..28fd7dbb40 100644 --- a/TUnit.Pipeline/Modules/ProcessorParallelLimit.cs +++ b/TUnit.Pipeline/Modules/ProcessorParallelLimit.cs @@ -4,5 +4,5 @@ namespace TUnit.Pipeline.Modules; public class ProcessorParallelLimit : IParallelLimit { - public int Limit { get; } = Environment.ProcessorCount * 4; + public static int Limit { get; } = Environment.ProcessorCount * 4; } diff --git a/TUnit.Pipeline/Modules/PublishNugetTesterAOTModule.cs b/TUnit.Pipeline/Modules/PublishNugetTesterAOTModule.cs index b15f0e8a03..d9a19126b6 100644 --- a/TUnit.Pipeline/Modules/PublishNugetTesterAOTModule.cs +++ b/TUnit.Pipeline/Modules/PublishNugetTesterAOTModule.cs @@ -1,13 +1,14 @@ using System.Runtime.InteropServices; using ModularPipelines.Attributes; +using ModularPipelines.Configuration; using ModularPipelines.Context; using ModularPipelines.DotNet.Extensions; using ModularPipelines.DotNet.Options; -using ModularPipelines.Enums; using ModularPipelines.Extensions; using ModularPipelines.Git.Extensions; using ModularPipelines.Models; using ModularPipelines.Modules; +using ModularPipelines.Options; namespace TUnit.Pipeline.Modules; @@ -16,15 +17,16 @@ namespace TUnit.Pipeline.Modules; [DependsOn] public class PublishNugetTesterAOTModule : Module> { - protected override Task ShouldSkip(IPipelineContext context) - { - return Task.FromResult(EnvironmentVariables.IsNetFramework); - } + protected override ModuleConfiguration Configure() => ModuleConfiguration.Create() + .WithSkipWhen(_ => EnvironmentVariables.IsNetFramework + ? SkipDecision.Skip("Running on .NET Framework") + : SkipDecision.DoNotSkip) + .Build(); - protected override async Task?> ExecuteAsync(IPipelineContext context, CancellationToken cancellationToken) + protected override async Task?> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken) { var results = new List(); - var version = await GetModule(); + var version = await context.GetModule(); var testProject = context.Git() .RootDirectory @@ -35,20 +37,29 @@ protected override Task ShouldSkip(IPipelineContext context) // Test AOT publishing foreach (var framework in new[] { "net8.0", "net9.0", "net10.0" }) { - var result = await SubModule($"AOT-{framework}", async () => + var result = await context.SubModule($"AOT-{framework}", async () => { - return await context.DotNet().Publish(new DotNetPublishOptions(testProject) + return await context.DotNet().Publish(new DotNetPublishOptions { - RuntimeIdentifier = GetRuntimeIdentifier(), - Configuration = Configuration.Release, - OutputDirectory = $"NUGETTESTER_AOT_{framework}", + ProjectSolution = testProject.Path, + Runtime = GetRuntimeIdentifier(), + Configuration = "Release", + Output = $"NUGETTESTER_AOT_{framework}", Properties = [ new KeyValue("Aot", "true"), - new KeyValue("TUnitVersion", version.Value!.SemVer!) + new KeyValue("TUnitVersion", version.ValueOrDefault!.SemVer!) ], Framework = framework, - CommandLogging = CommandLogging.Input | CommandLogging.Error | CommandLogging.Duration | CommandLogging.ExitCode + }, new CommandExecutionOptions + { + LogSettings = new CommandLoggingOptions + { + ShowCommandArguments = true, + ShowStandardError = true, + ShowExecutionTime = true, + ShowExitCode = true + } }, cancellationToken); }); diff --git a/TUnit.Pipeline/Modules/PushVersionTagModule.cs b/TUnit.Pipeline/Modules/PushVersionTagModule.cs index fb958a4ff9..a72a8173e8 100644 --- a/TUnit.Pipeline/Modules/PushVersionTagModule.cs +++ b/TUnit.Pipeline/Modules/PushVersionTagModule.cs @@ -1,4 +1,5 @@ using ModularPipelines.Attributes; +using ModularPipelines.Configuration; using ModularPipelines.Context; using ModularPipelines.Git.Attributes; using ModularPipelines.Git.Extensions; @@ -13,25 +14,26 @@ namespace TUnit.Pipeline.Modules; [DependsOn] public class PushVersionTagModule : Module { - protected override async Task ShouldIgnoreFailures(IPipelineContext context, Exception exception) - { - var versionInformation = await GetModule(); - - return exception.Message.Contains($"tag 'v{versionInformation.Value!.SemVer}' already exists"); - } + protected override ModuleConfiguration Configure() => ModuleConfiguration.Create() + .WithIgnoreFailuresWhen(async (ctx, ex) => + { + var versionInformation = await ctx.GetModule(); + return ex.Message.Contains($"tag 'v{versionInformation.ValueOrDefault!.SemVer}' already exists"); + }) + .Build(); - protected override async Task ExecuteAsync(IPipelineContext context, CancellationToken cancellationToken) + protected override async Task ExecuteAsync(IModuleContext context, CancellationToken cancellationToken) { - var versionInformation = await GetModule(); + var versionInformation = await context.GetModule(); await context.Git().Commands.Tag(new GitTagOptions { - Arguments = [$"v{versionInformation.Value!.SemVer}"], - }, cancellationToken); + TagName = $"v{versionInformation.ValueOrDefault!.SemVer}", + }, token: cancellationToken); return await context.Git().Commands.Push(new GitPushOptions { Tags = true - }, cancellationToken); + }, token: cancellationToken); } } diff --git a/TUnit.Pipeline/Modules/RunAnalyzersTestsModule.cs b/TUnit.Pipeline/Modules/RunAnalyzersTestsModule.cs index 796c740b68..fa97dabd05 100644 --- a/TUnit.Pipeline/Modules/RunAnalyzersTestsModule.cs +++ b/TUnit.Pipeline/Modules/RunAnalyzersTestsModule.cs @@ -2,33 +2,41 @@ using ModularPipelines.Context; using ModularPipelines.DotNet.Extensions; using ModularPipelines.DotNet.Options; -using ModularPipelines.Enums; using ModularPipelines.Extensions; using ModularPipelines.Git.Extensions; using ModularPipelines.Models; using ModularPipelines.Modules; +using ModularPipelines.Options; namespace TUnit.Pipeline.Modules; [NotInParallel("DotNetTests")] public class RunAnalyzersTestsModule : Module { - protected override async Task ExecuteAsync(IPipelineContext context, CancellationToken cancellationToken) + protected override async Task ExecuteAsync(IModuleContext context, CancellationToken cancellationToken) { var project = context.Git().RootDirectory.FindFile(x => x.Name == "TUnit.Analyzers.Tests.csproj").AssertExists(); return await context.DotNet().Test(new DotNetTestOptions { - WorkingDirectory = project.Folder!, NoBuild = true, - Configuration = Configuration.Release, + Configuration = "Release", Framework = "net8.0", Arguments = ["--", "--hangdump", "--hangdump-filename", "hangdump.analyzers-tests.dmp", "--hangdump-timeout", "5m"], + }, new CommandExecutionOptions + { + WorkingDirectory = project.Folder!.Path, EnvironmentVariables = new Dictionary { ["DISABLE_GITHUB_REPORTER"] = "true", }, - CommandLogging = CommandLogging.Input | CommandLogging.Error | CommandLogging.Duration | CommandLogging.ExitCode + LogSettings = new CommandLoggingOptions + { + ShowCommandArguments = true, + ShowStandardError = true, + ShowExecutionTime = true, + ShowExitCode = true + } }, cancellationToken); } } diff --git a/TUnit.Pipeline/Modules/RunAspNetCoreAnalyzersTestsModule.cs b/TUnit.Pipeline/Modules/RunAspNetCoreAnalyzersTestsModule.cs index 921b8b8a51..85755e0d0b 100644 --- a/TUnit.Pipeline/Modules/RunAspNetCoreAnalyzersTestsModule.cs +++ b/TUnit.Pipeline/Modules/RunAspNetCoreAnalyzersTestsModule.cs @@ -2,33 +2,41 @@ using ModularPipelines.Context; using ModularPipelines.DotNet.Extensions; using ModularPipelines.DotNet.Options; -using ModularPipelines.Enums; using ModularPipelines.Extensions; using ModularPipelines.Git.Extensions; using ModularPipelines.Models; using ModularPipelines.Modules; +using ModularPipelines.Options; namespace TUnit.Pipeline.Modules; [NotInParallel("DotNetTests")] public class RunAspNetCoreAnalyzersTestsModule : Module { - protected override async Task ExecuteAsync(IPipelineContext context, CancellationToken cancellationToken) + protected override async Task ExecuteAsync(IModuleContext context, CancellationToken cancellationToken) { var project = context.Git().RootDirectory.FindFile(x => x.Name == "TUnit.AspNetCore.Analyzers.Tests.csproj").AssertExists(); return await context.DotNet().Test(new DotNetTestOptions { - WorkingDirectory = project.Folder!, NoBuild = true, - Configuration = Configuration.Release, + Configuration = "Release", Framework = "net9.0", Arguments = ["--", "--hangdump", "--hangdump-filename", "hangdump.aspnetcore-analyzers-tests.dmp", "--hangdump-timeout", "5m"], + }, new CommandExecutionOptions + { + WorkingDirectory = project.Folder!.Path, EnvironmentVariables = new Dictionary { ["DISABLE_GITHUB_REPORTER"] = "true", }, - CommandLogging = CommandLogging.Input | CommandLogging.Error | CommandLogging.Duration | CommandLogging.ExitCode + LogSettings = new CommandLoggingOptions + { + ShowCommandArguments = true, + ShowStandardError = true, + ShowExecutionTime = true, + ShowExitCode = true + } }, cancellationToken); } } diff --git a/TUnit.Pipeline/Modules/RunAspNetTestsModule.cs b/TUnit.Pipeline/Modules/RunAspNetTestsModule.cs index 19affa0735..8c55dcffe3 100644 --- a/TUnit.Pipeline/Modules/RunAspNetTestsModule.cs +++ b/TUnit.Pipeline/Modules/RunAspNetTestsModule.cs @@ -2,18 +2,18 @@ using ModularPipelines.Context; using ModularPipelines.DotNet.Extensions; using ModularPipelines.DotNet.Options; -using ModularPipelines.Enums; using ModularPipelines.Extensions; using ModularPipelines.Git.Extensions; using ModularPipelines.Models; using ModularPipelines.Modules; +using ModularPipelines.Options; namespace TUnit.Pipeline.Modules; [NotInParallel("DotNetTests"), RunOnLinuxOnly, RunOnWindowsOnly] public class RunAspNetTestsModule : Module { - protected override async Task ExecuteAsync(IPipelineContext context, CancellationToken cancellationToken) + protected override async Task ExecuteAsync(IModuleContext context, CancellationToken cancellationToken) { var project = context.Git().RootDirectory.FindFile(x => x.Name == "TUnit.Example.Asp.Net.TestProject.csproj").AssertExists(); @@ -21,15 +21,23 @@ public class RunAspNetTestsModule : Module { Project = project.Name, NoBuild = true, - Configuration = Configuration.Release, + Configuration = "Release", Framework = "net10.0", - WorkingDirectory = project.Folder!, Arguments = ["--hangdump", "--hangdump-filename", "hangdump.aspnet-tests.dmp", "--hangdump-timeout", "5m"], + }, new CommandExecutionOptions + { + WorkingDirectory = project.Folder!.Path, EnvironmentVariables = new Dictionary { ["DISABLE_GITHUB_REPORTER"] = "true", }, - CommandLogging = CommandLogging.Input | CommandLogging.Error | CommandLogging.Duration | CommandLogging.ExitCode + LogSettings = new CommandLoggingOptions + { + ShowCommandArguments = true, + ShowStandardError = true, + ShowExecutionTime = true, + ShowExitCode = true + } }, cancellationToken); } } diff --git a/TUnit.Pipeline/Modules/RunAssertionsAnalyzersTestsModule.cs b/TUnit.Pipeline/Modules/RunAssertionsAnalyzersTestsModule.cs index 01458e50f1..524fc25b0f 100644 --- a/TUnit.Pipeline/Modules/RunAssertionsAnalyzersTestsModule.cs +++ b/TUnit.Pipeline/Modules/RunAssertionsAnalyzersTestsModule.cs @@ -2,33 +2,41 @@ using ModularPipelines.Context; using ModularPipelines.DotNet.Extensions; using ModularPipelines.DotNet.Options; -using ModularPipelines.Enums; using ModularPipelines.Extensions; using ModularPipelines.Git.Extensions; using ModularPipelines.Models; using ModularPipelines.Modules; +using ModularPipelines.Options; namespace TUnit.Pipeline.Modules; [NotInParallel("DotNetTests")] public class RunAssertionsAnalyzersTestsModule : Module { - protected override async Task ExecuteAsync(IPipelineContext context, CancellationToken cancellationToken) + protected override async Task ExecuteAsync(IModuleContext context, CancellationToken cancellationToken) { var project = context.Git().RootDirectory.FindFile(x => x.Name == "TUnit.Assertions.Analyzers.Tests.csproj").AssertExists(); return await context.DotNet().Test(new DotNetTestOptions { - WorkingDirectory = project.Folder!, NoBuild = true, - Configuration = Configuration.Release, + Configuration = "Release", Framework = "net8.0", Arguments = ["--", "--hangdump", "--hangdump-filename", "hangdump.assertions-analyzers-tests.dmp", "--hangdump-timeout", "5m"], + }, new CommandExecutionOptions + { + WorkingDirectory = project.Folder!.Path, EnvironmentVariables = new Dictionary { ["DISABLE_GITHUB_REPORTER"] = "true", }, - CommandLogging = CommandLogging.Input | CommandLogging.Error | CommandLogging.Duration | CommandLogging.ExitCode + LogSettings = new CommandLoggingOptions + { + ShowCommandArguments = true, + ShowStandardError = true, + ShowExecutionTime = true, + ShowExitCode = true + } }, cancellationToken); } } diff --git a/TUnit.Pipeline/Modules/RunAssertionsCodeFixersTestsModule.cs b/TUnit.Pipeline/Modules/RunAssertionsCodeFixersTestsModule.cs index ac7e4af46e..92b3776861 100644 --- a/TUnit.Pipeline/Modules/RunAssertionsCodeFixersTestsModule.cs +++ b/TUnit.Pipeline/Modules/RunAssertionsCodeFixersTestsModule.cs @@ -2,33 +2,41 @@ using ModularPipelines.Context; using ModularPipelines.DotNet.Extensions; using ModularPipelines.DotNet.Options; -using ModularPipelines.Enums; using ModularPipelines.Extensions; using ModularPipelines.Git.Extensions; using ModularPipelines.Models; using ModularPipelines.Modules; +using ModularPipelines.Options; namespace TUnit.Pipeline.Modules; [NotInParallel("DotNetTests")] public class RunAssertionsCodeFixersTestsModule : Module { - protected override async Task ExecuteAsync(IPipelineContext context, CancellationToken cancellationToken) + protected override async Task ExecuteAsync(IModuleContext context, CancellationToken cancellationToken) { var project = context.Git().RootDirectory.FindFile(x => x.Name == "TUnit.Assertions.Analyzers.CodeFixers.Tests.csproj").AssertExists(); return await context.DotNet().Test(new DotNetTestOptions { - WorkingDirectory = project.Folder!, NoBuild = true, - Configuration = Configuration.Release, + Configuration = "Release", Framework = "net8.0", Arguments = ["--", "--hangdump", "--hangdump-filename", "hangdump.assertions-codefixers-tests.dmp", "--hangdump-timeout", "5m"], + }, new CommandExecutionOptions + { + WorkingDirectory = project.Folder!.Path, EnvironmentVariables = new Dictionary { ["DISABLE_GITHUB_REPORTER"] = "true", }, - CommandLogging = CommandLogging.Input | CommandLogging.Error | CommandLogging.Duration | CommandLogging.ExitCode + LogSettings = new CommandLoggingOptions + { + ShowCommandArguments = true, + ShowStandardError = true, + ShowExecutionTime = true, + ShowExitCode = true + } }, cancellationToken); } } diff --git a/TUnit.Pipeline/Modules/RunAssertionsTestsModule.cs b/TUnit.Pipeline/Modules/RunAssertionsTestsModule.cs index 72c504be62..bdb42203ff 100644 --- a/TUnit.Pipeline/Modules/RunAssertionsTestsModule.cs +++ b/TUnit.Pipeline/Modules/RunAssertionsTestsModule.cs @@ -3,6 +3,7 @@ using ModularPipelines.DotNet.Options; using ModularPipelines.Extensions; using ModularPipelines.Git.Extensions; +using ModularPipelines.Options; using TUnit.Pipeline.Modules.Abstract; namespace TUnit.Pipeline.Modules; @@ -10,20 +11,25 @@ namespace TUnit.Pipeline.Modules; [NotInParallel("DotNetTests")] public class RunAssertionsTestsModule : TestBaseModule { - protected override Task GetTestOptions(IPipelineContext context, string framework, CancellationToken cancellationToken) + protected override Task<(DotNetRunOptions Options, CommandExecutionOptions? ExecutionOptions)> GetTestOptions(IModuleContext context, string framework, CancellationToken cancellationToken) { var project = context.Git().RootDirectory.FindFile(x => x.Name == "TUnit.Assertions.Tests.csproj").AssertExists(); - return Task.FromResult(new DotNetRunOptions - { - WorkingDirectory = project.Folder!, - NoBuild = true, - Configuration = Configuration.Release, - Framework = framework, - EnvironmentVariables = new Dictionary + return Task.FromResult<(DotNetRunOptions, CommandExecutionOptions?)>(( + new DotNetRunOptions { - ["TUNIT_DISABLE_GITHUB_REPORTER"] = "true", + NoBuild = true, + Configuration = "Release", + Framework = framework, + }, + new CommandExecutionOptions + { + WorkingDirectory = project.Folder!.Path, + EnvironmentVariables = new Dictionary + { + ["TUNIT_DISABLE_GITHUB_REPORTER"] = "true", + } } - }); + )); } } diff --git a/TUnit.Pipeline/Modules/RunEngineTestsModule.cs b/TUnit.Pipeline/Modules/RunEngineTestsModule.cs index 49a70177aa..b8e07e0df9 100644 --- a/TUnit.Pipeline/Modules/RunEngineTestsModule.cs +++ b/TUnit.Pipeline/Modules/RunEngineTestsModule.cs @@ -2,11 +2,11 @@ using ModularPipelines.Context; using ModularPipelines.DotNet.Extensions; using ModularPipelines.DotNet.Options; -using ModularPipelines.Enums; using ModularPipelines.Extensions; using ModularPipelines.Git.Extensions; using ModularPipelines.Models; using ModularPipelines.Modules; +using ModularPipelines.Options; namespace TUnit.Pipeline.Modules; @@ -24,7 +24,7 @@ namespace TUnit.Pipeline.Modules; [DependsOn] public class RunEngineTestsModule : Module { - protected override async Task ExecuteAsync(IPipelineContext context, CancellationToken cancellationToken) + protected override async Task ExecuteAsync(IModuleContext context, CancellationToken cancellationToken) { var project = context.Git().RootDirectory.FindFile(x => x.Name == "TUnit.Engine.Tests.csproj").AssertExists(); @@ -32,18 +32,26 @@ public class RunEngineTestsModule : Module { Project = project.Name, NoBuild = true, - Configuration = Configuration.Release, + Configuration = "Release", Framework = "net10.0", - WorkingDirectory = project.Folder!, Arguments = [ "--hangdump", "--hangdump-filename", $"hangdump.{Environment.OSVersion.Platform}.engine-tests.dmp", "--hangdump-timeout", "30m", "--timeout", "35m", ], + }, new CommandExecutionOptions + { + WorkingDirectory = project.Folder!.Path, EnvironmentVariables = new Dictionary { ["TUNIT_DISABLE_GITHUB_REPORTER"] = "true", }, - CommandLogging = CommandLogging.Input | CommandLogging.Error | CommandLogging.Duration | CommandLogging.ExitCode + LogSettings = new CommandLoggingOptions + { + ShowCommandArguments = true, + ShowStandardError = true, + ShowExecutionTime = true, + ShowExitCode = true + } }, cancellationToken); } } diff --git a/TUnit.Pipeline/Modules/RunPlaywrightTestsModule.cs b/TUnit.Pipeline/Modules/RunPlaywrightTestsModule.cs index 478a0223d1..1acecd34e9 100644 --- a/TUnit.Pipeline/Modules/RunPlaywrightTestsModule.cs +++ b/TUnit.Pipeline/Modules/RunPlaywrightTestsModule.cs @@ -1,6 +1,7 @@ using ModularPipelines.Attributes; using ModularPipelines.Context; using ModularPipelines.DotNet.Options; +using ModularPipelines.Options; using TUnit.Pipeline.Modules.Abstract; namespace TUnit.Pipeline.Modules; @@ -8,19 +9,24 @@ namespace TUnit.Pipeline.Modules; [NotInParallel("DotNetTests"), RunOnLinuxOnly, RunOnWindowsOnly] public class RunPlaywrightTestsModule : TestBaseModule { - protected override Task GetTestOptions(IPipelineContext context, string framework, CancellationToken cancellationToken) + protected override Task<(DotNetRunOptions Options, CommandExecutionOptions? ExecutionOptions)> GetTestOptions(IModuleContext context, string framework, CancellationToken cancellationToken) { var project = Sourcy.DotNet.Projects.TUnit_Templates__content__TUnit_Playwright__TestProject; - return Task.FromResult(new DotNetRunOptions - { - Project = project.FullName, - NoBuild = true, - Configuration = Configuration.Release, - EnvironmentVariables = new Dictionary + return Task.FromResult<(DotNetRunOptions, CommandExecutionOptions?)>(( + new DotNetRunOptions { - ["DISABLE_GITHUB_REPORTER"] = "true", + Project = project.FullName, + NoBuild = true, + Configuration = "Release", + }, + new CommandExecutionOptions + { + EnvironmentVariables = new Dictionary + { + ["DISABLE_GITHUB_REPORTER"] = "true", + } } - }); + )); } } diff --git a/TUnit.Pipeline/Modules/RunPublicAPITestsModule.cs b/TUnit.Pipeline/Modules/RunPublicAPITestsModule.cs index 683be1a71c..554866d3f6 100644 --- a/TUnit.Pipeline/Modules/RunPublicAPITestsModule.cs +++ b/TUnit.Pipeline/Modules/RunPublicAPITestsModule.cs @@ -3,6 +3,7 @@ using ModularPipelines.DotNet.Options; using ModularPipelines.Extensions; using ModularPipelines.Git.Extensions; +using ModularPipelines.Options; using TUnit.Pipeline.Modules.Abstract; namespace TUnit.Pipeline.Modules; @@ -10,21 +11,26 @@ namespace TUnit.Pipeline.Modules; [NotInParallel("DotNetTests")] public class RunPublicAPITestsModule : TestBaseModule { - protected override Task GetTestOptions(IPipelineContext context, string framework, CancellationToken cancellationToken) + protected override Task<(DotNetRunOptions Options, CommandExecutionOptions? ExecutionOptions)> GetTestOptions(IModuleContext context, string framework, CancellationToken cancellationToken) { var project = context.Git().RootDirectory.FindFile(x => x.Name == "TUnit.PublicAPI.csproj").AssertExists(); - return Task.FromResult(new DotNetRunOptions - { - WorkingDirectory = project.Folder!, - NoBuild = true, - Configuration = Configuration.Release, - Framework = framework, - EnvironmentVariables = new Dictionary + return Task.FromResult<(DotNetRunOptions, CommandExecutionOptions?)>(( + new DotNetRunOptions { - ["DISABLE_GITHUB_REPORTER"] = "true", - ["GITHUB_ACTIONS"] = "false", + NoBuild = true, + Configuration = "Release", + Framework = framework, }, - }); + new CommandExecutionOptions + { + WorkingDirectory = project.Folder!.Path, + EnvironmentVariables = new Dictionary + { + ["DISABLE_GITHUB_REPORTER"] = "true", + ["GITHUB_ACTIONS"] = "false", + } + } + )); } } diff --git a/TUnit.Pipeline/Modules/RunRpcTestsModule.cs b/TUnit.Pipeline/Modules/RunRpcTestsModule.cs index a85724add0..d7fadbee8b 100644 --- a/TUnit.Pipeline/Modules/RunRpcTestsModule.cs +++ b/TUnit.Pipeline/Modules/RunRpcTestsModule.cs @@ -3,6 +3,7 @@ using ModularPipelines.DotNet.Options; using ModularPipelines.Extensions; using ModularPipelines.Git.Extensions; +using ModularPipelines.Options; using TUnit.Pipeline.Modules.Abstract; namespace TUnit.Pipeline.Modules; @@ -16,21 +17,26 @@ public class RunRpcTestsModule : TestBaseModule "net8.0" ]; - protected override Task GetTestOptions(IPipelineContext context, string framework, CancellationToken cancellationToken) + protected override Task<(DotNetRunOptions Options, CommandExecutionOptions? ExecutionOptions)> GetTestOptions(IModuleContext context, string framework, CancellationToken cancellationToken) { var project = context.Git().RootDirectory.FindFile(x => x.Name == "TUnit.RpcTests.csproj").AssertExists(); - return Task.FromResult(new DotNetRunOptions - { - WorkingDirectory = project.Folder!, - NoBuild = true, - Configuration = Configuration.Release, - Framework = framework, - EnvironmentVariables = new Dictionary + return Task.FromResult<(DotNetRunOptions, CommandExecutionOptions?)>(( + new DotNetRunOptions { - ["DISABLE_GITHUB_REPORTER"] = "true", + NoBuild = true, + Configuration = "Release", + Framework = framework, + Arguments = ["--ignore-exit-code", "8"], }, - Arguments = ["--ignore-exit-code", "8"], - }); + new CommandExecutionOptions + { + WorkingDirectory = project.Folder!.Path, + EnvironmentVariables = new Dictionary + { + ["DISABLE_GITHUB_REPORTER"] = "true", + } + } + )); } } diff --git a/TUnit.Pipeline/Modules/RunSourceGeneratorTestsModule.cs b/TUnit.Pipeline/Modules/RunSourceGeneratorTestsModule.cs index 5eb29f0e14..cfd2596ef3 100644 --- a/TUnit.Pipeline/Modules/RunSourceGeneratorTestsModule.cs +++ b/TUnit.Pipeline/Modules/RunSourceGeneratorTestsModule.cs @@ -3,6 +3,7 @@ using ModularPipelines.DotNet.Options; using ModularPipelines.Extensions; using ModularPipelines.Git.Extensions; +using ModularPipelines.Options; using TUnit.Pipeline.Modules.Abstract; namespace TUnit.Pipeline.Modules; @@ -10,20 +11,25 @@ namespace TUnit.Pipeline.Modules; [NotInParallel("DotNetTests")] public class RunSourceGeneratorTestsModule : TestBaseModule { - protected override Task GetTestOptions(IPipelineContext context, string framework, CancellationToken cancellationToken) + protected override Task<(DotNetRunOptions Options, CommandExecutionOptions? ExecutionOptions)> GetTestOptions(IModuleContext context, string framework, CancellationToken cancellationToken) { var project = context.Git().RootDirectory.FindFile(x => x.Name == "TUnit.Core.SourceGenerator.Tests.csproj").AssertExists(); - return Task.FromResult(new DotNetRunOptions - { - WorkingDirectory = project.Folder!, - NoBuild = true, - Configuration = Configuration.Release, - Framework = framework, - EnvironmentVariables = new Dictionary + return Task.FromResult<(DotNetRunOptions, CommandExecutionOptions?)>(( + new DotNetRunOptions { - ["DISABLE_GITHUB_REPORTER"] = "true", + NoBuild = true, + Configuration = "Release", + Framework = framework, }, - }); + new CommandExecutionOptions + { + WorkingDirectory = project.Folder!.Path, + EnvironmentVariables = new Dictionary + { + ["DISABLE_GITHUB_REPORTER"] = "true", + } + } + )); } } diff --git a/TUnit.Pipeline/Modules/RunTemplateTestsModule.cs b/TUnit.Pipeline/Modules/RunTemplateTestsModule.cs index 6199c64f72..85fc93293d 100644 --- a/TUnit.Pipeline/Modules/RunTemplateTestsModule.cs +++ b/TUnit.Pipeline/Modules/RunTemplateTestsModule.cs @@ -2,33 +2,41 @@ using ModularPipelines.Context; using ModularPipelines.DotNet.Extensions; using ModularPipelines.DotNet.Options; -using ModularPipelines.Enums; using ModularPipelines.Extensions; using ModularPipelines.Git.Extensions; using ModularPipelines.Models; using ModularPipelines.Modules; +using ModularPipelines.Options; namespace TUnit.Pipeline.Modules; [NotInParallel("DotNetTests")] public class RunTemplateTestsModule : Module { - protected override async Task ExecuteAsync(IPipelineContext context, CancellationToken cancellationToken) + protected override async Task ExecuteAsync(IModuleContext context, CancellationToken cancellationToken) { var project = context.Git().RootDirectory.FindFile(x => x.Name == "TUnit.Templates.Tests.csproj").AssertExists(); return await context.DotNet().Test(new DotNetTestOptions { - WorkingDirectory = project.Folder!, NoBuild = true, - Configuration = Configuration.Release, + Configuration = "Release", Framework = "net10.0", Arguments = ["--", "--hangdump", "--hangdump-filename", "hangdump.template-tests.dmp", "--hangdump-timeout", "5m"], + }, new CommandExecutionOptions + { + WorkingDirectory = project.Folder!.Path, EnvironmentVariables = new Dictionary { ["DISABLE_GITHUB_REPORTER"] = "true", }, - CommandLogging = CommandLogging.Input | CommandLogging.Error | CommandLogging.Duration | CommandLogging.ExitCode + LogSettings = new CommandLoggingOptions + { + ShowCommandArguments = true, + ShowStandardError = true, + ShowExecutionTime = true, + ShowExitCode = true + } }, cancellationToken); } } diff --git a/TUnit.Pipeline/Modules/RunUnitTestsModule.cs b/TUnit.Pipeline/Modules/RunUnitTestsModule.cs index e24e0e9627..cb1d7afe6b 100644 --- a/TUnit.Pipeline/Modules/RunUnitTestsModule.cs +++ b/TUnit.Pipeline/Modules/RunUnitTestsModule.cs @@ -3,6 +3,7 @@ using ModularPipelines.DotNet.Options; using ModularPipelines.Extensions; using ModularPipelines.Git.Extensions; +using ModularPipelines.Options; using TUnit.Pipeline.Modules.Abstract; namespace TUnit.Pipeline.Modules; @@ -10,20 +11,25 @@ namespace TUnit.Pipeline.Modules; [NotInParallel("DotNetTests")] public class RunUnitTestsModule : TestBaseModule { - protected override Task GetTestOptions(IPipelineContext context, string framework, CancellationToken cancellationToken) + protected override Task<(DotNetRunOptions Options, CommandExecutionOptions? ExecutionOptions)> GetTestOptions(IModuleContext context, string framework, CancellationToken cancellationToken) { var project = context.Git().RootDirectory.FindFile(x => x.Name == "TUnit.UnitTests.csproj").AssertExists(); - return Task.FromResult(new DotNetRunOptions - { - WorkingDirectory = project.Folder!, - NoBuild = true, - Configuration = Configuration.Release, - Framework = framework, - EnvironmentVariables = new Dictionary + return Task.FromResult<(DotNetRunOptions, CommandExecutionOptions?)>(( + new DotNetRunOptions { - ["TUNIT_DISABLE_GITHUB_REPORTER"] = "true", + NoBuild = true, + Configuration = "Release", + Framework = framework, + }, + new CommandExecutionOptions + { + WorkingDirectory = project.Folder!.Path, + EnvironmentVariables = new Dictionary + { + ["TUNIT_DISABLE_GITHUB_REPORTER"] = "true", + } } - }); + )); } } diff --git a/TUnit.Pipeline/Modules/TestAspNetCoreNugetPackageModule.cs b/TUnit.Pipeline/Modules/TestAspNetCoreNugetPackageModule.cs index 718826f48b..1ea45872fb 100644 --- a/TUnit.Pipeline/Modules/TestAspNetCoreNugetPackageModule.cs +++ b/TUnit.Pipeline/Modules/TestAspNetCoreNugetPackageModule.cs @@ -1,10 +1,11 @@ using ModularPipelines.Attributes; +using ModularPipelines.Configuration; using ModularPipelines.Context; using ModularPipelines.DotNet.Options; using ModularPipelines.Extensions; using ModularPipelines.Git.Extensions; using ModularPipelines.Models; -using Polly.Retry; +using ModularPipelines.Options; using TUnit.Pipeline.Modules.Abstract; namespace TUnit.Pipeline.Modules; @@ -13,8 +14,9 @@ namespace TUnit.Pipeline.Modules; [DependsOn] public class TestAspNetCoreNugetPackageModule : TestBaseModule { - protected override AsyncRetryPolicy?> RetryPolicy - => CreateRetryPolicy(3); + protected override ModuleConfiguration Configure() => ModuleConfiguration.Create() + .WithRetryCount(3) + .Build(); // ASP.NET Core only supports .NET Core frameworks, not .NET Framework protected override IEnumerable TestableFrameworks @@ -27,10 +29,10 @@ protected override IEnumerable TestableFrameworks } } - protected override async Task GetTestOptions(IPipelineContext context, string framework, + protected override async Task<(DotNetRunOptions Options, CommandExecutionOptions? ExecutionOptions)> GetTestOptions(IModuleContext context, string framework, CancellationToken cancellationToken) { - var version = await GetModule(); + var version = await context.GetModule(); var project = context.Git() .RootDirectory @@ -38,19 +40,24 @@ protected override async Task GetTestOptions(IPipelineContext .FindFile(x => x.Name == "TUnit.AspNetCore.NugetTester.csproj") .AssertExists(); - return new DotNetRunOptions - { - WorkingDirectory = project.Folder!, - Framework = framework, - Properties = - [ - new KeyValue("TUnitVersion", version.Value!.SemVer!) - ], - Arguments = - [ - "--coverage", - "--report-trx" - ] - }; + return ( + new DotNetRunOptions + { + Framework = framework, + Properties = + [ + new KeyValue("TUnitVersion", version.ValueOrDefault!.SemVer!) + ], + Arguments = + [ + "--coverage", + "--report-trx" + ] + }, + new CommandExecutionOptions + { + WorkingDirectory = project.Folder!.Path, + } + ); } } diff --git a/TUnit.Pipeline/Modules/TestNugetPackageModule.cs b/TUnit.Pipeline/Modules/TestNugetPackageModule.cs index d10bc1702d..537ce328fc 100644 --- a/TUnit.Pipeline/Modules/TestNugetPackageModule.cs +++ b/TUnit.Pipeline/Modules/TestNugetPackageModule.cs @@ -1,11 +1,12 @@ using System.Runtime.InteropServices; using ModularPipelines.Attributes; +using ModularPipelines.Configuration; using ModularPipelines.Context; using ModularPipelines.DotNet.Options; using ModularPipelines.Extensions; using ModularPipelines.Git.Extensions; using ModularPipelines.Models; -using Polly.Retry; +using ModularPipelines.Options; using TUnit.Pipeline.Modules.Abstract; namespace TUnit.Pipeline.Modules; @@ -31,8 +32,10 @@ public class TestVBNugetPackageModule : AbstractTestNugetPackageModule [DependsOn] public abstract class AbstractTestNugetPackageModule : TestBaseModule { - protected override AsyncRetryPolicy?> RetryPolicy - => CreateRetryPolicy(3); + protected override ModuleConfiguration Configure() => ModuleConfiguration.Create() + .WithRetryCount(3) + .Build(); + protected override IEnumerable TestableFrameworks { get @@ -50,10 +53,10 @@ protected override IEnumerable TestableFrameworks } } - protected override async Task GetTestOptions(IPipelineContext context, string framework, + protected override async Task<(DotNetRunOptions Options, CommandExecutionOptions? ExecutionOptions)> GetTestOptions(IModuleContext context, string framework, CancellationToken cancellationToken) { - var version = await GetModule(); + var version = await context.GetModule(); var project = context.Git() .RootDirectory @@ -61,20 +64,25 @@ protected override async Task GetTestOptions(IPipelineContext .FindFile(x => x.Name == ProjectName) .AssertExists(); - return new DotNetRunOptions - { - WorkingDirectory = project.Folder!, - Framework = framework, - Properties = - [ - new KeyValue("TUnitVersion", version.Value!.SemVer!) - ], - Arguments = - [ - "--coverage", - "--report-trx" - ] - }; + return ( + new DotNetRunOptions + { + Framework = framework, + Properties = + [ + new KeyValue("TUnitVersion", version.ValueOrDefault!.SemVer!) + ], + Arguments = + [ + "--coverage", + "--report-trx" + ] + }, + new CommandExecutionOptions + { + WorkingDirectory = project.Folder!.Path, + } + ); } public abstract string ProjectName { get; } diff --git a/TUnit.Pipeline/Modules/TestTemplatePackageModule.cs b/TUnit.Pipeline/Modules/TestTemplatePackageModule.cs index 774a2107c5..f01500888e 100644 --- a/TUnit.Pipeline/Modules/TestTemplatePackageModule.cs +++ b/TUnit.Pipeline/Modules/TestTemplatePackageModule.cs @@ -2,9 +2,9 @@ using ModularPipelines.Context; using ModularPipelines.DotNet.Extensions; using ModularPipelines.DotNet.Options; -using ModularPipelines.Enums; using ModularPipelines.Models; using ModularPipelines.Modules; +using ModularPipelines.Options; namespace TUnit.Pipeline.Modules; @@ -12,40 +12,68 @@ namespace TUnit.Pipeline.Modules; [DependsOn] public class TestTemplatePackageModule : Module { - protected override async Task ExecuteAsync(IPipelineContext context, + protected override async Task ExecuteAsync(IModuleContext context, CancellationToken cancellationToken) { - var version = await GetModule(); + var version = await context.GetModule(); - await context.DotNet().New(new DotNetNewOptions("uninstall") + var logSettings = new CommandLoggingOptions + { + ShowCommandArguments = true, + ShowStandardError = true, + ShowExecutionTime = true, + ShowExitCode = true + }; + + // Uninstall existing template + await context.DotNet().New.Execute(new DotNetNewOptions + { + TemplateShortName = "uninstall", + TemplateArgs = "TUnit.Templates", + }, new CommandExecutionOptions { - Arguments = ["TUnit.Templates"], ThrowOnNonZeroExitCode = false, - CommandLogging = CommandLogging.Input | CommandLogging.Error | CommandLogging.Duration | CommandLogging.ExitCode + LogSettings = logSettings }, cancellationToken); - await context.DotNet().New(new DotNetNewOptions("install") + // Install template with specific version + await context.DotNet().New.Execute(new DotNetNewOptions + { + TemplateShortName = "install", + TemplateArgs = $"TUnit.Templates::{version.ValueOrDefault!.SemVer}", + }, new CommandExecutionOptions { - Arguments = [$"TUnit.Templates::{version.Value!.SemVer}"], - CommandLogging = CommandLogging.Input | CommandLogging.Error | CommandLogging.Duration | CommandLogging.ExitCode + LogSettings = logSettings }, cancellationToken); - await context.DotNet().New(new DotNetNewOptions("TUnit") + // Create TUnit project + await context.DotNet().New.Execute(new DotNetNewOptions { + TemplateShortName = "TUnit", Name = "MyTestProject", - CommandLogging = CommandLogging.Input | CommandLogging.Error | CommandLogging.Duration | CommandLogging.ExitCode + }, new CommandExecutionOptions + { + LogSettings = logSettings }, cancellationToken); - await context.DotNet().New(new DotNetNewOptions("TUnit.AspNet") + // Create TUnit.AspNet project + await context.DotNet().New.Execute(new DotNetNewOptions { + TemplateShortName = "TUnit.AspNet", Name = "MyTestProject2", - CommandLogging = CommandLogging.Input | CommandLogging.Error | CommandLogging.Duration | CommandLogging.ExitCode + }, new CommandExecutionOptions + { + LogSettings = logSettings }, cancellationToken); - return await context.DotNet().New(new DotNetNewOptions("TUnit.Playwright") + // Create TUnit.Playwright project + return await context.DotNet().New.Execute(new DotNetNewOptions { + TemplateShortName = "TUnit.Playwright", Name = "MyTestProject3", - CommandLogging = CommandLogging.Input | CommandLogging.Error | CommandLogging.Duration | CommandLogging.ExitCode + }, new CommandExecutionOptions + { + LogSettings = logSettings }, cancellationToken); } } diff --git a/TUnit.Pipeline/Modules/UploadToNuGetModule.cs b/TUnit.Pipeline/Modules/UploadToNuGetModule.cs index 76144cdb4a..2a9db11038 100644 --- a/TUnit.Pipeline/Modules/UploadToNuGetModule.cs +++ b/TUnit.Pipeline/Modules/UploadToNuGetModule.cs @@ -1,14 +1,15 @@ using EnumerableAsyncProcessor.Extensions; using Microsoft.Extensions.Options; using ModularPipelines.Attributes; +using ModularPipelines.Configuration; using ModularPipelines.Context; using ModularPipelines.DotNet.Extensions; using ModularPipelines.DotNet.Options; -using ModularPipelines.Enums; using ModularPipelines.Git.Attributes; using ModularPipelines.Git.Extensions; using ModularPipelines.Models; using ModularPipelines.Modules; +using ModularPipelines.Options; namespace TUnit.Pipeline.Modules; @@ -20,32 +21,43 @@ namespace TUnit.Pipeline.Modules; [DependsOn] public class UploadToNuGetModule(IOptions options) : Module { - protected override Task ShouldSkip(IPipelineContext context) - { - if (!options.Value.ShouldPublish) + protected override ModuleConfiguration Configure() => ModuleConfiguration.Create() + .WithSkipWhen(_ => { - return Task.FromResult("Should Publish is false"); - } + if (!options.Value.ShouldPublish) + { + return SkipDecision.Skip("Should Publish is false"); + } - if (string.IsNullOrEmpty(options.Value.ApiKey)) - { - return Task.FromResult("No API key found"); - } + if (string.IsNullOrEmpty(options.Value.ApiKey)) + { + return SkipDecision.Skip("No API key found"); + } - return Task.FromResult(false); - } + return SkipDecision.DoNotSkip; + }) + .Build(); - protected override async Task ExecuteAsync(IPipelineContext context, CancellationToken cancellationToken) + protected override async Task ExecuteAsync(IModuleContext context, CancellationToken cancellationToken) { var nupkgs = context.Git().RootDirectory .GetFiles(x => x.NameWithoutExtension.Contains("TUnit") && x.Extension is ".nupkg"); return await nupkgs.SelectAsync(file => - context.DotNet().Nuget.Push(new DotNetNugetPushOptions(file) + context.DotNet().Nuget.Push(new DotNetNugetPushOptions { + Path = file.Path, Source = "https://api.nuget.org/v3/index.json", ApiKey = options.Value.ApiKey, - CommandLogging = CommandLogging.Input | CommandLogging.Error | CommandLogging.Duration | CommandLogging.ExitCode + }, new CommandExecutionOptions + { + LogSettings = new CommandLoggingOptions + { + ShowCommandArguments = true, + ShowStandardError = true, + ShowExecutionTime = true, + ShowExitCode = true + } }, cancellationToken), cancellationToken: cancellationToken) .ProcessOneAtATime(); } diff --git a/TUnit.Pipeline/Program.cs b/TUnit.Pipeline/Program.cs index 7d9881253a..88098bebd5 100644 --- a/TUnit.Pipeline/Program.cs +++ b/TUnit.Pipeline/Program.cs @@ -1,8 +1,8 @@ using System.CommandLine; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; +using ModularPipelines; using ModularPipelines.Extensions; -using ModularPipelines.Host; using ModularPipelines.Options; using TUnit.Pipeline; @@ -17,35 +17,26 @@ var rootCommand = new RootCommand("The pipeline for building, testing and packaging TUnit"); rootCommand.Add(categoryOption); -rootCommand.SetAction(parseResult => +rootCommand.SetAction(async parseResult => { var categories = parseResult.GetValue(categoryOption)!; - var pipelineHostBuilder = PipelineHostBuilder.Create() - .ConfigureAppConfiguration((_, builder) => - { - builder.AddEnvironmentVariables(); - }) - .ConfigureServices((context, collection) => - { - collection.Configure(context.Configuration.GetSection("NuGet")); - collection.AddModulesFromAssembly(typeof(Program).Assembly); - }) - .ConfigurePipelineOptions((_, options) => options.ExecutionMode = ExecutionMode.WaitForAllModules); + var builder = Pipeline.CreateBuilder(); + builder.Configuration.AddEnvironmentVariables(); + builder.Services.Configure(builder.Configuration.GetSection("NuGet")); + builder.Services.AddModulesFromAssembly(typeof(Program).Assembly); + builder.Options.ExecutionMode = ExecutionMode.WaitForAllModules; if (categories.Length > 0) { - pipelineHostBuilder.RunCategories(categories); + builder.RunCategories(categories); } else { - pipelineHostBuilder.IgnoreCategories("ReadMe"); + builder.IgnoreCategories("ReadMe"); } - pipelineHostBuilder - .ExecutePipelineAsync() - .GetAwaiter() - .GetResult(); + await builder.Build().RunAsync(); }); return await rootCommand.Parse(args).InvokeAsync(); diff --git a/TUnit.Pipeline/TUnit.Pipeline.csproj b/TUnit.Pipeline/TUnit.Pipeline.csproj index 396086de73..1bfe6325f3 100644 --- a/TUnit.Pipeline/TUnit.Pipeline.csproj +++ b/TUnit.Pipeline/TUnit.Pipeline.csproj @@ -1,6 +1,7 @@ net10.0 + net10.0 false false From 2cb78ff9acc513d6e88480c45abf368589efe955 Mon Sep 17 00:00:00 2001 From: Tom Longhurst <30480171+thomhurst@users.noreply.github.com> Date: Fri, 16 Jan 2026 20:54:45 +0000 Subject: [PATCH 4/8] chore(deps): update ModularPipelines packages to v2.48.528-alpha0001 --- Directory.Packages.props | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 5fc28b5da4..7075f768ea 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -47,9 +47,9 @@ - - - + + + From 96c1678d1c354b5519595235615b2a8130bf075e Mon Sep 17 00:00:00 2001 From: Tom Longhurst <30480171+thomhurst@users.noreply.github.com> Date: Fri, 16 Jan 2026 21:28:00 +0000 Subject: [PATCH 5/8] fix: mark optional module dependencies as IgnoreIfNotRegistered In ModularPipelines v3, DependsOn now throws if the dependency isn't registered. Mark platform-filtered test modules as optional dependencies. Co-Authored-By: Claude Opus 4.5 --- TUnit.Pipeline/Modules/RunEngineTestsModule.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/TUnit.Pipeline/Modules/RunEngineTestsModule.cs b/TUnit.Pipeline/Modules/RunEngineTestsModule.cs index b8e07e0df9..85aa8abc8b 100644 --- a/TUnit.Pipeline/Modules/RunEngineTestsModule.cs +++ b/TUnit.Pipeline/Modules/RunEngineTestsModule.cs @@ -14,10 +14,10 @@ namespace TUnit.Pipeline.Modules; [DependsOn] [DependsOn] [DependsOn] -[DependsOn] +[DependsOn(IgnoreIfNotRegistered = true)] [DependsOn] -[DependsOn] -[DependsOn] +[DependsOn(IgnoreIfNotRegistered = true)] +[DependsOn(IgnoreIfNotRegistered = true)] [DependsOn] [DependsOn] [DependsOn] From 630f41f3c9d6f96097905edbf14c3a9e9980c2cf Mon Sep 17 00:00:00 2001 From: Tom Longhurst <30480171+thomhurst@users.noreply.github.com> Date: Sat, 17 Jan 2026 00:00:09 +0000 Subject: [PATCH 6/8] perf: parallelize pipeline test modules for faster CI - Remove [NotInParallel("DotNetTests")] from 6 safe modules: - RunAnalyzersTestsModule (in-memory Roslyn testing) - RunAspNetCoreAnalyzersTestsModule (in-memory Roslyn testing) - RunAssertionsAnalyzersTestsModule (in-memory Roslyn testing) - RunAssertionsCodeFixersTestsModule (in-memory Roslyn testing) - RunUnitTestsModule (no shared resources) - RunAssertionsTestsModule (GUID-based temp directories) - Add [NotInParallel("SnapshotTests")] for snapshot testing modules: - RunSourceGeneratorTestsModule (350+ snapshot files) - RunPublicAPITestsModule (12+ snapshot files) - RunTemplateTestsModule (global DiffRunner state) - Change [NotInParallel("NetworkTests")] for network-bound modules: - RunAspNetTestsModule (web server ports) - RunRpcTestsModule (RPC ports) - RunPlaywrightTestsModule (browser resources) - RunEngineTestsModule (runs after all tests anyway) Expected ~50% reduction in pipeline time by running test groups in parallel while maintaining safety constraints. Co-Authored-By: Claude Opus 4.5 --- TUnit.Pipeline/Modules/RunAnalyzersTestsModule.cs | 1 - TUnit.Pipeline/Modules/RunAspNetCoreAnalyzersTestsModule.cs | 1 - TUnit.Pipeline/Modules/RunAspNetTestsModule.cs | 2 +- TUnit.Pipeline/Modules/RunAssertionsAnalyzersTestsModule.cs | 1 - TUnit.Pipeline/Modules/RunAssertionsCodeFixersTestsModule.cs | 1 - TUnit.Pipeline/Modules/RunAssertionsTestsModule.cs | 1 - TUnit.Pipeline/Modules/RunEngineTestsModule.cs | 2 +- TUnit.Pipeline/Modules/RunPlaywrightTestsModule.cs | 2 +- TUnit.Pipeline/Modules/RunPublicAPITestsModule.cs | 2 +- TUnit.Pipeline/Modules/RunRpcTestsModule.cs | 2 +- TUnit.Pipeline/Modules/RunSourceGeneratorTestsModule.cs | 2 +- TUnit.Pipeline/Modules/RunTemplateTestsModule.cs | 2 +- TUnit.Pipeline/Modules/RunUnitTestsModule.cs | 1 - 13 files changed, 7 insertions(+), 13 deletions(-) diff --git a/TUnit.Pipeline/Modules/RunAnalyzersTestsModule.cs b/TUnit.Pipeline/Modules/RunAnalyzersTestsModule.cs index fa97dabd05..d487d0e7db 100644 --- a/TUnit.Pipeline/Modules/RunAnalyzersTestsModule.cs +++ b/TUnit.Pipeline/Modules/RunAnalyzersTestsModule.cs @@ -10,7 +10,6 @@ namespace TUnit.Pipeline.Modules; -[NotInParallel("DotNetTests")] public class RunAnalyzersTestsModule : Module { protected override async Task ExecuteAsync(IModuleContext context, CancellationToken cancellationToken) diff --git a/TUnit.Pipeline/Modules/RunAspNetCoreAnalyzersTestsModule.cs b/TUnit.Pipeline/Modules/RunAspNetCoreAnalyzersTestsModule.cs index 85755e0d0b..b1e399ab4d 100644 --- a/TUnit.Pipeline/Modules/RunAspNetCoreAnalyzersTestsModule.cs +++ b/TUnit.Pipeline/Modules/RunAspNetCoreAnalyzersTestsModule.cs @@ -10,7 +10,6 @@ namespace TUnit.Pipeline.Modules; -[NotInParallel("DotNetTests")] public class RunAspNetCoreAnalyzersTestsModule : Module { protected override async Task ExecuteAsync(IModuleContext context, CancellationToken cancellationToken) diff --git a/TUnit.Pipeline/Modules/RunAspNetTestsModule.cs b/TUnit.Pipeline/Modules/RunAspNetTestsModule.cs index 8c55dcffe3..83900fb664 100644 --- a/TUnit.Pipeline/Modules/RunAspNetTestsModule.cs +++ b/TUnit.Pipeline/Modules/RunAspNetTestsModule.cs @@ -10,7 +10,7 @@ namespace TUnit.Pipeline.Modules; -[NotInParallel("DotNetTests"), RunOnLinuxOnly, RunOnWindowsOnly] +[NotInParallel("NetworkTests"), RunOnLinuxOnly, RunOnWindowsOnly] public class RunAspNetTestsModule : Module { protected override async Task ExecuteAsync(IModuleContext context, CancellationToken cancellationToken) diff --git a/TUnit.Pipeline/Modules/RunAssertionsAnalyzersTestsModule.cs b/TUnit.Pipeline/Modules/RunAssertionsAnalyzersTestsModule.cs index 524fc25b0f..bd51ada274 100644 --- a/TUnit.Pipeline/Modules/RunAssertionsAnalyzersTestsModule.cs +++ b/TUnit.Pipeline/Modules/RunAssertionsAnalyzersTestsModule.cs @@ -10,7 +10,6 @@ namespace TUnit.Pipeline.Modules; -[NotInParallel("DotNetTests")] public class RunAssertionsAnalyzersTestsModule : Module { protected override async Task ExecuteAsync(IModuleContext context, CancellationToken cancellationToken) diff --git a/TUnit.Pipeline/Modules/RunAssertionsCodeFixersTestsModule.cs b/TUnit.Pipeline/Modules/RunAssertionsCodeFixersTestsModule.cs index 92b3776861..5507628467 100644 --- a/TUnit.Pipeline/Modules/RunAssertionsCodeFixersTestsModule.cs +++ b/TUnit.Pipeline/Modules/RunAssertionsCodeFixersTestsModule.cs @@ -10,7 +10,6 @@ namespace TUnit.Pipeline.Modules; -[NotInParallel("DotNetTests")] public class RunAssertionsCodeFixersTestsModule : Module { protected override async Task ExecuteAsync(IModuleContext context, CancellationToken cancellationToken) diff --git a/TUnit.Pipeline/Modules/RunAssertionsTestsModule.cs b/TUnit.Pipeline/Modules/RunAssertionsTestsModule.cs index bdb42203ff..3ade3231f5 100644 --- a/TUnit.Pipeline/Modules/RunAssertionsTestsModule.cs +++ b/TUnit.Pipeline/Modules/RunAssertionsTestsModule.cs @@ -8,7 +8,6 @@ namespace TUnit.Pipeline.Modules; -[NotInParallel("DotNetTests")] public class RunAssertionsTestsModule : TestBaseModule { protected override Task<(DotNetRunOptions Options, CommandExecutionOptions? ExecutionOptions)> GetTestOptions(IModuleContext context, string framework, CancellationToken cancellationToken) diff --git a/TUnit.Pipeline/Modules/RunEngineTestsModule.cs b/TUnit.Pipeline/Modules/RunEngineTestsModule.cs index 85aa8abc8b..94a8f9e679 100644 --- a/TUnit.Pipeline/Modules/RunEngineTestsModule.cs +++ b/TUnit.Pipeline/Modules/RunEngineTestsModule.cs @@ -10,7 +10,7 @@ namespace TUnit.Pipeline.Modules; -[NotInParallel("DotNetTests")] +[NotInParallel("NetworkTests")] [DependsOn] [DependsOn] [DependsOn] diff --git a/TUnit.Pipeline/Modules/RunPlaywrightTestsModule.cs b/TUnit.Pipeline/Modules/RunPlaywrightTestsModule.cs index 1acecd34e9..37cc00c82c 100644 --- a/TUnit.Pipeline/Modules/RunPlaywrightTestsModule.cs +++ b/TUnit.Pipeline/Modules/RunPlaywrightTestsModule.cs @@ -6,7 +6,7 @@ namespace TUnit.Pipeline.Modules; -[NotInParallel("DotNetTests"), RunOnLinuxOnly, RunOnWindowsOnly] +[NotInParallel("NetworkTests"), RunOnLinuxOnly, RunOnWindowsOnly] public class RunPlaywrightTestsModule : TestBaseModule { protected override Task<(DotNetRunOptions Options, CommandExecutionOptions? ExecutionOptions)> GetTestOptions(IModuleContext context, string framework, CancellationToken cancellationToken) diff --git a/TUnit.Pipeline/Modules/RunPublicAPITestsModule.cs b/TUnit.Pipeline/Modules/RunPublicAPITestsModule.cs index 554866d3f6..47c1b363ca 100644 --- a/TUnit.Pipeline/Modules/RunPublicAPITestsModule.cs +++ b/TUnit.Pipeline/Modules/RunPublicAPITestsModule.cs @@ -8,7 +8,7 @@ namespace TUnit.Pipeline.Modules; -[NotInParallel("DotNetTests")] +[NotInParallel("SnapshotTests")] public class RunPublicAPITestsModule : TestBaseModule { protected override Task<(DotNetRunOptions Options, CommandExecutionOptions? ExecutionOptions)> GetTestOptions(IModuleContext context, string framework, CancellationToken cancellationToken) diff --git a/TUnit.Pipeline/Modules/RunRpcTestsModule.cs b/TUnit.Pipeline/Modules/RunRpcTestsModule.cs index d7fadbee8b..a2bcf58b7c 100644 --- a/TUnit.Pipeline/Modules/RunRpcTestsModule.cs +++ b/TUnit.Pipeline/Modules/RunRpcTestsModule.cs @@ -8,7 +8,7 @@ namespace TUnit.Pipeline.Modules; -[NotInParallel("DotNetTests")] +[NotInParallel("NetworkTests")] [RunOnLinuxOnly, RunOnWindowsOnly] public class RunRpcTestsModule : TestBaseModule { diff --git a/TUnit.Pipeline/Modules/RunSourceGeneratorTestsModule.cs b/TUnit.Pipeline/Modules/RunSourceGeneratorTestsModule.cs index cfd2596ef3..959bdd7ce1 100644 --- a/TUnit.Pipeline/Modules/RunSourceGeneratorTestsModule.cs +++ b/TUnit.Pipeline/Modules/RunSourceGeneratorTestsModule.cs @@ -8,7 +8,7 @@ namespace TUnit.Pipeline.Modules; -[NotInParallel("DotNetTests")] +[NotInParallel("SnapshotTests")] public class RunSourceGeneratorTestsModule : TestBaseModule { protected override Task<(DotNetRunOptions Options, CommandExecutionOptions? ExecutionOptions)> GetTestOptions(IModuleContext context, string framework, CancellationToken cancellationToken) diff --git a/TUnit.Pipeline/Modules/RunTemplateTestsModule.cs b/TUnit.Pipeline/Modules/RunTemplateTestsModule.cs index 85fc93293d..8ac3dad9ae 100644 --- a/TUnit.Pipeline/Modules/RunTemplateTestsModule.cs +++ b/TUnit.Pipeline/Modules/RunTemplateTestsModule.cs @@ -10,7 +10,7 @@ namespace TUnit.Pipeline.Modules; -[NotInParallel("DotNetTests")] +[NotInParallel("SnapshotTests")] public class RunTemplateTestsModule : Module { protected override async Task ExecuteAsync(IModuleContext context, CancellationToken cancellationToken) diff --git a/TUnit.Pipeline/Modules/RunUnitTestsModule.cs b/TUnit.Pipeline/Modules/RunUnitTestsModule.cs index cb1d7afe6b..1d7ed32cde 100644 --- a/TUnit.Pipeline/Modules/RunUnitTestsModule.cs +++ b/TUnit.Pipeline/Modules/RunUnitTestsModule.cs @@ -8,7 +8,6 @@ namespace TUnit.Pipeline.Modules; -[NotInParallel("DotNetTests")] public class RunUnitTestsModule : TestBaseModule { protected override Task<(DotNetRunOptions Options, CommandExecutionOptions? ExecutionOptions)> GetTestOptions(IModuleContext context, string framework, CancellationToken cancellationToken) From add7be89684b4b7c798ecd7ce5555768bff920f8 Mon Sep 17 00:00:00 2001 From: Tom Longhurst <30480171+thomhurst@users.noreply.github.com> Date: Sat, 17 Jan 2026 01:17:29 +0000 Subject: [PATCH 7/8] chore(deps): update ModularPipelines packages to v3.0.1 --- Directory.Packages.props | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 7075f768ea..5ee98308fb 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -47,9 +47,9 @@ - - - + + + From 76840e25a1b5eb5c2709fdc6c274f87b75219bcb Mon Sep 17 00:00:00 2001 From: Tom Longhurst <30480171+thomhurst@users.noreply.github.com> Date: Sat, 17 Jan 2026 11:09:14 +0000 Subject: [PATCH 8/8] fix: restrict TUnit.Pipeline to net10.0 for ModularPipelines v3 compatibility ModularPipelines v3.0.1 only supports net10.0, so the pipeline project must be excluded from the default multi-targeting (net8.0;net9.0;net10.0). Co-Authored-By: Claude Opus 4.5 --- Directory.Build.props | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Directory.Build.props b/Directory.Build.props index 1691a1d4eb..174a023dc6 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -4,6 +4,10 @@ net8.0;net9.0;net10.0 + + net10.0 + + netstandard2.0 $(TargetFramework)