### Complete Pipeline Configuration Example Source: https://github.com/thomhurst/modularpipelines/blob/main/docs/docs/how-to/pipeline-host.md Demonstrates a full pipeline setup including configuration, options, service registration, and conditional module loading. Use this as a starting point for your pipeline host. ```csharp using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using ModularPipelines; using ModularPipelines.Extensions; using ModularPipelines.Options; var builder = Pipeline.CreateBuilder(args); // Configuration builder.Configuration .AddJsonFile("appsettings.json") .AddUserSecrets() .AddEnvironmentVariables(); // Options builder.Options.ExecutionMode = ExecutionMode.StopOnFirstException; builder.Options.IgnoreCategories = ["Experimental"]; // Services builder.Services.Configure(builder.Configuration.GetSection("NuGet")); builder.Services.Configure(builder.Configuration.GetSection("Publish")); // Conditional modules if (builder.Environment.IsDevelopment()) { builder.Services .AddModule() .AddModule(); } else { builder.Services .AddModule() .AddModule() .AddModule(); } // Always-registered modules builder.Services .AddModule() .AddModule(); // Run await builder.Build().RunAsync(); ``` -------------------------------- ### V3 Program.cs - Pipeline Setup Source: https://github.com/thomhurst/modularpipelines/blob/main/docs/docs/migrating-to-v3.md Example of setting up a pipeline using Pipeline.CreateBuilder in V3, including configuration and module registration. ```csharp // Program.cs var builder = Pipeline.CreateBuilder(args); builder.Configuration.AddJsonFile("appsettings.json"); builder.Services .AddModule() .AddModule() .AddModule(); await builder.Build().RunAsync(); ``` -------------------------------- ### V2 Program.cs - Pipeline Setup Source: https://github.com/thomhurst/modularpipelines/blob/main/docs/docs/migrating-to-v3.md Example of setting up a pipeline using PipelineHostBuilder in V2, including configuration and service registration. ```csharp // Program.cs await PipelineHostBuilder.Create() .ConfigureAppConfiguration((ctx, builder) => { builder.AddJsonFile("appsettings.json"); }) .ConfigureServices((ctx, services) => { services.AddModule() .AddModule() .AddModule(); }) .ExecutePipelineAsync(); ``` -------------------------------- ### Create and Run a Basic Pipeline Source: https://github.com/thomhurst/modularpipelines/blob/main/docs/docs/how-to/pipeline-host.md Use Pipeline.CreateBuilder() to start building a pipeline and then run it asynchronously. This is the fundamental setup for most pipelines. ```csharp var builder = Pipeline.CreateBuilder(args); builder.Services .AddModule() .AddModule() .AddModule(); await builder.Build().RunAsync(); ``` -------------------------------- ### V3 BuildModule Example Source: https://github.com/thomhurst/modularpipelines/blob/main/docs/docs/migrating-to-v3.md A sample BuildModule in V3, demonstrating configuration using ModuleConfiguration.Create() for timeout and execution. ```csharp // BuildModule.cs public class BuildModule : Module { protected override ModuleConfiguration Configure() => ModuleConfiguration.Create() .WithTimeout(TimeSpan.FromMinutes(10)) .Build(); protected override async Task ExecuteAsync( IModuleContext context, CancellationToken cancellationToken) { var result = await context.DotNet().Build(new DotNetBuildOptions()); return new BuildOutput(result.StandardOutput); } } ``` -------------------------------- ### V2 BuildModule Example Source: https://github.com/thomhurst/modularpipelines/blob/main/docs/docs/migrating-to-v3.md A sample BuildModule in V2, demonstrating how to define a timeout and execute a .NET build command. ```csharp // BuildModule.cs public class BuildModule : Module { protected internal override TimeSpan Timeout => TimeSpan.FromMinutes(10); protected override async Task ExecuteAsync( IPipelineContext context, CancellationToken cancellationToken) { var result = await context.DotNet().Build(new DotNetBuildOptions()); return new BuildOutput(result.StandardOutput); } } ``` -------------------------------- ### Single File C# Pipeline Example Source: https://github.com/thomhurst/modularpipelines/blob/main/docs/docs/examples/single-file-csharp.md A complete single-file C# application using ModularPipelines to update .NET workloads and check the SDK. This example requires the .NET SDK to be installed and in the PATH. ```csharp #!/usr/bin/dotnet run #:package ModularPipelines.DotNet@3.* using ModularPipelines; using ModularPipelines.Attributes; using ModularPipelines.Context; using ModularPipelines.DotNet.Extensions; using ModularPipelines.Extensions; using ModularPipelines.Models; using ModularPipelines.Modules; var builder = Pipeline.CreateBuilder(args); builder.Services .AddModule() .AddModule(); await builder.Build().RunAsync(); public class UpdateDotnetWorkloads : Module { protected override async Task ExecuteAsync(IModuleContext context, CancellationToken cancellationToken) { return await context.DotNet().DotNetWorkload.Update(token: cancellationToken); } } [DependsOn] public class CheckDotnetSdkModule : Module { protected override async Task ExecuteAsync(IModuleContext context, CancellationToken cancellationToken) { return await context.DotNet().Sdk.Check(token: cancellationToken); } } ``` -------------------------------- ### Build Specific Solutions Source: https://github.com/thomhurst/modularpipelines/blob/main/CLAUDE.md Builds specific parts of the solution, such as examples or analyzers. Use the Release configuration. ```bash # Build specific solution (examples, analyzers, etc.) dotnet build ModularPipelines.Examples.sln -c Release dotnet build ModularPipelines.Analyzers.sln -c Release ``` -------------------------------- ### V3 Module Templates Source: https://github.com/thomhurst/modularpipelines/blob/main/docs/docs/migrating-to-v3.md Examples of creating asynchronous modules with and without return values, and synchronous modules. ```csharp // Async module WITH return value public class MyModule : Module { protected override ModuleConfiguration Configure() => ModuleConfiguration.Create() .WithTimeout(TimeSpan.FromMinutes(5)) // Add other configuration as needed .Build(); protected override async Task ExecuteAsync( IModuleContext context, CancellationToken cancellationToken) { // Implementation return new MyResult(); } } // Async module WITHOUT return value public class MyActionModule : Module { protected override async Task ExecuteModuleAsync( IModuleContext context, CancellationToken cancellationToken) { // Implementation - no return needed } } // Sync module WITHOUT return value public class MySyncModule : SyncModule { protected override void ExecuteModule( IModuleContext context, CancellationToken cancellationToken) { // Implementation - no return needed } } ``` -------------------------------- ### Pipeline Creation and Configuration in V3 Source: https://github.com/thomhurst/modularpipelines/blob/main/docs/docs/migrating-to-v3.md Use `Pipeline.CreateBuilder(args)` to start. Configuration, services, and options are added directly to the builder properties. ```csharp var builder = Pipeline.CreateBuilder(args); // Direct property access instead of callbacks builder.Configuration .AddJsonFile("appsettings.json") .AddUserSecrets() .AddEnvironmentVariables(); // Configure services directly builder.Services.Configure(builder.Configuration.GetSection("MySettings")); if (builder.Environment.IsDevelopment()) { builder.Services.AddModule(); } builder.Services .AddModule() .AddModule() .AddModule(); // Configure options directly builder.Options.ExecutionMode = ExecutionMode.StopOnFirstException; // Two-step build and run await builder.Build().RunAsync(); ``` -------------------------------- ### V2 DeployModule Example Source: https://github.com/thomhurst/modularpipelines/blob/main/docs/docs/migrating-to-v3.md A sample DeployModule in V2, showing dependency declaration and conditional skipping based on the branch name. ```csharp // DeployModule.cs [DependsOn] [DependsOn] public class DeployModule : Module { protected internal override Task ShouldSkip(IPipelineContext context) { if (context.Git().Information.BranchName != "main") return Task.FromResult(SkipDecision.Skip("Not main branch")); return Task.FromResult(SkipDecision.DoNotSkip); } protected override async Task ExecuteAsync( IPipelineContext context, CancellationToken cancellationToken) { var buildResult = await GetModule(); if (buildResult.ModuleResultType != ModuleResultType.Success) return false; // Deploy using buildResult.Value return true; } } ``` -------------------------------- ### V3 DeployModule Example Source: https://github.com/thomhurst/modularpipelines/blob/main/docs/docs/migrating-to-v3.md A sample DeployModule in V3, showing configuration using ModuleConfiguration.Create() for conditional skipping and module result handling. ```csharp // DeployModule.cs [DependsOn] [DependsOn] public class DeployModule : Module { protected override ModuleConfiguration Configure() => ModuleConfiguration.Create() .WithSkipWhen(ctx => ctx.Git().Information.BranchName != "main" ? SkipDecision.Skip("Not main branch") : SkipDecision.DoNotSkip) .Build(); protected override async Task ExecuteAsync( IModuleContext context, CancellationToken cancellationToken) { var buildResult = await context.GetModule(); if (buildResult is not ModuleResult.Success { Value: var output }) return false; // Deploy using output return true; } } ``` -------------------------------- ### Implement Docker Requirement Check Source: https://github.com/thomhurst/modularpipelines/blob/main/docs/architecture/interface-hierarchy.md Implement IPipelineRequirement to define conditions that must be met before pipeline execution. This example checks if Docker is installed. ```csharp public class DockerRequirement : IPipelineRequirement { public int Order => 100; public async Task MustAsync(IPipelineHookContext context) { var result = await context.Command.ExecuteCommandLineTool( new("docker", "version")); return result.ExitCode == 0 ? RequirementDecision.Met : RequirementDecision.NotMet("Docker is not installed"); } } ``` -------------------------------- ### Register Modules on Services Source: https://github.com/thomhurst/modularpipelines/blob/main/docs/docs/how-to/pipeline-host.md Register individual modules or multiple modules at once using the Services collection. This example shows both methods. ```csharp var builder = Pipeline.CreateBuilder(args); // Register modules builder.Services .AddModule() .AddModule() .AddModule(); // Or register multiple at once builder.AddModules(); ``` -------------------------------- ### Publish Module Example in C# Source: https://github.com/thomhurst/modularpipelines/blob/main/README_Template.md Demonstrates a C# module for publishing an application. It depends on the BuildModule and TestModule and uses the DotNet publish command. Set breakpoints and debug locally. ```csharp using ModularPipelines; using ModularPipelines.DotNet.Options; using ModularPipelines.Models; using System.Threading; using System.Threading.Tasks; [DependsOn] [DependsOn] public class PublishModule : Module { protected override async Task ExecuteAsync(IPipelineContext context, CancellationToken cancellationToken) { // This is real C#. Set a breakpoint. Inspect variables. Debug locally. return await context.DotNet().Publish(new DotNetPublishOptions { Project = "src/MyApp/MyApp.csproj", Configuration = Configuration.Release, Output = "publish/" }, cancellationToken); } } ``` -------------------------------- ### Example JSON Output for ModuleResult Source: https://github.com/thomhurst/modularpipelines/blob/main/docs/plans/2026-01-07-module-result-discriminated-union.md An example of the JSON output for a successful ModuleResult, including type information and specific value. ```json { "$type": "Success", "Value": "build output", "ModuleName": "BuildModule", "ModuleDuration": "00:01:23" } ``` -------------------------------- ### Create Pipeline Builder and Add Modules Source: https://github.com/thomhurst/modularpipelines/blob/main/docs/docs/how-to/storing-and-retrieving-results.md Configure a pipeline builder, add modules, and specify a custom results repository. This setup is necessary before running the pipeline. ```csharp var builder = Pipeline.CreateBuilder(args); builder.Services .AddModule() .AddModule() .AddModule(); builder.AddResultsRepository(); await builder.Build().RunAsync(); ``` -------------------------------- ### Migrate from IPipelineContext to IModuleContext Source: https://github.com/thomhurst/modularpipelines/blob/main/docs/architecture/interface-hierarchy.md Example demonstrating the migration from the deprecated IPipelineContext to the recommended IModuleContext for module implementations. ```csharp // Before protected override async Task ExecuteAsync( IPipelineContext context, // DEPRECATED CancellationToken ct) { } // After protected override async Task ExecuteAsync( IModuleContext context, // RECOMMENDED CancellationToken ct) { } ``` -------------------------------- ### Async and Sync Non-Generic Module Classes Source: https://github.com/thomhurst/modularpipelines/blob/main/RELEASE_NOTES_V3.md Provides examples of new `Module` and `SyncModule` base classes for modules that do not return data. ```csharp // Async module - no return value needed public class DeployModule : Module { protected override async Task ExecuteModuleAsync( IModuleContext context, CancellationToken cancellationToken) { await context.Command.ExecuteCommandLineTool(...); } } ``` ```csharp // Sync module - no return value needed public class LoggingModule : SyncModule { protected override void ExecuteModule( IModuleContext context, CancellationToken cancellationToken) { context.Logger.LogInformation("Done!"); } } ``` -------------------------------- ### Optional Dependency Example Source: https://github.com/thomhurst/modularpipelines/blob/main/docs/docs/how-to/execution-and-dependencies.md Mark dependencies with Optional = true if they might not be present. Use GetModuleIfRegistered() to check for their existence and access results safely. ```csharp // Optional dependency - won't be auto-registered [DependsOn(Optional = true)] public class Module2 : Module { protected override async Task ExecuteAsync(IModuleContext context, CancellationToken cancellationToken) { // Use GetModuleIfRegistered for optional dependencies var module1 = context.GetModuleIfRegistered(); if (module1 != null) { var result = await module1; return $"Got result: {result.Value}"; } return "Module1 not available"; } } ``` -------------------------------- ### Command Logging Configuration in V3 Source: https://github.com/thomhurst/modularpipelines/blob/main/docs/docs/migrating-to-v3.md V3 introduces `CommandLoggingOptions` for richer logging control, replacing the limited options previously found on tool configurations. This example contrasts V2's logging settings with V3's detailed configuration. ```csharp // Logging settings were on tool options with limited control await context.DotNet().Build(new DotNetBuildOptions { LogInput = true, LogOutput = false, // Limited options available }); ``` ```csharp // Rich logging configuration via CommandLoggingOptions await context.DotNet().Build( new DotNetBuildOptions { Configuration = "Release" }, new CommandExecutionOptions { LogSettings = new CommandLoggingOptions { Verbosity = CommandLogVerbosity.Detailed, ShowCommandArguments = true, ShowStandardOutput = true, ShowStandardError = true, ShowExitCode = true, ShowExecutionTime = true } }); ``` -------------------------------- ### Create Pipeline Builder Source: https://github.com/thomhurst/modularpipelines/blob/main/docs/docs/fundamentals.md Initialize a new pipeline builder using `Pipeline.CreateBuilder()`. This setup is similar to ASP.NET Core minimal APIs, providing access to configuration, services, and options. ```csharp var builder = Pipeline.CreateBuilder(args); builder.Services.AddModule(); await builder.Build().RunAsync(); ``` -------------------------------- ### Module Data Sharing Example in C# Source: https://github.com/thomhurst/modularpipelines/blob/main/README_Template.md Illustrates how modules can share data. The BuildModule returns build information, which is then consumed by the PublishModule. This ensures strongly-typed, compile-time checked data flow. ```csharp // BuildModule returns version info public class BuildModule : Module { protected override async Task ExecuteAsync(IModuleContext context, CancellationToken cancellationToken) { await context.DotNet().Build(new DotNetBuildOptions { Project = "MyApp.csproj" }, cancellationToken); return new BuildInfo { Version = "1.0.0", OutputPath = "bin/Release" }; } } // PublishModule retrieves and uses it [DependsOn] public class PublishModule : Module { protected override async Task ExecuteAsync(IModuleContext context, CancellationToken cancellationToken) { var buildResult = await GetModule(); var outputPath = buildResult.Value!.OutputPath; // Strongly-typed, compile-time checked // Publish using the build output... } } ``` -------------------------------- ### Pipeline Setup with Time Estimator Source: https://github.com/thomhurst/modularpipelines/blob/main/docs/docs/how-to/time-estimator.md Configure your pipeline to use a custom time provider for estimating module durations. This is done by adding the estimated time provider to the service collection before building the pipeline. ```csharp var builder = Pipeline.CreateBuilder(args); builder.Services .AddModule() .AddModule() .AddModule(); builder.AddModuleEstimatedTimeProvider(); await builder.Build().RunAsync(); ``` -------------------------------- ### Implement a Pipeline Requirement Source: https://github.com/thomhurst/modularpipelines/blob/main/docs/docs/how-to/requirements.md Implement the `IPipelineRequirement` interface to define custom startup checks. The `MustAsync` method should return a Task that resolves to true if the requirement is met, and false otherwise. This example checks if the operating system is Windows. ```csharp public class WindowsRequirement : IPipelineRequirement { public Task MustAsync(IPipelineHookContext context) { return (context.Environment.OperatingSystem == OSPlatform.Windows).AsTask(); } } ``` -------------------------------- ### V2 Pipeline Entry Point Source: https://github.com/thomhurst/modularpipelines/blob/main/docs/docs/migrating-to-v3.md Illustrates the V2 approach to building and configuring a pipeline using PipelineHostBuilder.Create(). ```csharp await PipelineHostBuilder.Create() .ConfigureAppConfiguration((context, builder) => { builder.AddJsonFile("appsettings.json") .AddUserSecrets() .AddEnvironmentVariables(); }) .ConfigureServices((context, collection) => { collection.Configure(context.Configuration.GetSection("MySettings")); if (context.HostingEnvironment.IsDevelopment()) { collection.AddModule(); } collection.AddModule(); }) .ConfigurePipelineOptions((context, options) => { options.ExecutionMode = ExecutionMode.StopOnFirstException; }) .AddModule() .AddModule() .ExecutePipelineAsync(); ``` -------------------------------- ### Build Entire Solution Source: https://github.com/thomhurst/modularpipelines/blob/main/CLAUDE.md Builds the entire solution. Use the Release configuration for production builds. ```bash # Build the entire solution dotnet build ModularPipelines.sln -c Release ``` -------------------------------- ### Define a Synchronous Module Source: https://context7.com/thomhurst/modularpipelines/llms.txt For synchronous operations, inherit from `SyncModule` and override `ExecuteModule`. This example logs the pipeline start time using `context.Logger.LogInformation()`. ```csharp // Synchronous module public class TimestampLogModule : SyncModule { protected override void ExecuteModule( IModuleContext context, CancellationToken cancellationToken) { context.Logger.LogInformation("Pipeline started at {Time}", DateTime.UtcNow); } } ``` -------------------------------- ### Add ModularPipelines Package Source: https://github.com/thomhurst/modularpipelines/blob/main/README_Template.md Install the ModularPipelines NuGet package to your console application. ```bash dotnet new console -n MyPipeline cd MyPipeline dotnet add package ModularPipelines ``` -------------------------------- ### Create and Configure Pipeline Builder Source: https://context7.com/thomhurst/modularpipelines/llms.txt Use `Pipeline.CreateBuilder()` as the entry point for defining pipelines. Configure sources, pipeline-level options, register services, and conditionally add modules based on the environment. Build and run the pipeline, exiting with an error code if it fails. ```csharp using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using ModularPipelines; using ModularPipelines.Options; var builder = Pipeline.CreateBuilder(args); // Configuration sources builder.Configuration .AddJsonFile("appsettings.json") .AddUserSecrets() .AddEnvironmentVariables(); // Pipeline-level options builder.Options.ExecutionMode = ExecutionMode.StopOnFirstException; builder.Options.RunOnlyCategories = ["Build", "Test"]; builder.Options.IgnoreCategories = ["Experimental"]; builder.Options.DefaultRetryCount = 3; builder.Options.DefaultLoggingOptions = CommandLoggingOptions.Diagnostic; // Register custom services and settings builder.Services.Configure(builder.Configuration.GetSection("NuGet")); // Conditional module registration if (builder.Environment.IsDevelopment()) builder.Services.AddModule(); else builder.Services.AddModule() .AddModule() .AddModule(); // Always-on modules builder.Services .AddModule() .AddModule(); // Build and run var summary = await builder.Build().RunAsync(); if (summary.Status == PipelineStatus.Failed) Environment.Exit(1); ``` -------------------------------- ### Plugin System Implementation Source: https://github.com/thomhurst/modularpipelines/blob/main/RELEASE_NOTES_V3.md Illustrates how to create a reusable pipeline extension by implementing the `IModularPipelinesPlugin` interface. ```csharp public class MyPlugin : IModularPipelinesPlugin { public string Name => "MyPlugin"; public void ConfigureServices(IServiceCollection services) { services.AddSingleton(); } public void ConfigurePipeline(PipelineBuilder builder) { builder.Services.AddModule(); } } [assembly: ModularPipelinesPlugin(typeof(MyPlugin))] ``` -------------------------------- ### Configure and Execute Pipeline Source: https://github.com/thomhurst/modularpipelines/blob/main/src/ModularPipelines.Development.Analyzers/Readme.md Sets up application configuration, registers services, and adds modules to execute a pipeline. ```csharp await PipelineHostBuilder.Create() .ConfigureAppConfiguration((context, builder) => { builder.AddJsonFile("appsettings.json") .AddUserSecrets() .AddEnvironmentVariables(); }) .ConfigureServices((context, collection) => { collection.Configure(context.Configuration.GetSection("NuGet")); collection.Configure(context.Configuration.GetSection("Publish")); collection.AddSingleton(); collection.AddTransient(); }) .AddModule() .AddModule() .ExecutePipelineAsync(); ``` -------------------------------- ### Required Dependency Example Source: https://github.com/thomhurst/modularpipelines/blob/main/docs/docs/how-to/execution-and-dependencies.md Required dependencies are automatically registered and validated. Use GetModule() to safely access their results. ```csharp // Required dependency (default) // Module1 will be auto-registered if not explicitly added [DependsOn] public class Module2 : Module { protected override async Task ExecuteAsync(IModuleContext context, CancellationToken cancellationToken) { // Safe to call - Module1 is guaranteed to be registered var result = await context.GetModule(); return result.Value; } } ``` -------------------------------- ### Register Global Hooks Source: https://github.com/thomhurst/modularpipelines/blob/main/docs/docs/how-to/hooks.md Register a custom class that implements `IPipelineGlobalHooks` to execute actions before the pipeline starts and after it ends. ```csharp collection.AddPipelineGlobalHooks(); ``` -------------------------------- ### Tool Options Class Initialization in v2 (Deprecated) Source: https://github.com/thomhurst/modularpipelines/blob/main/docs/docs/migrating-to-v3.md Demonstrates the old way of initializing tool options classes using constructor arguments, which is no longer supported in v3. ```csharp // Constructor arguments - NO LONGER WORKS var newOptions = new DotNetNewOptions("console"); var packOptions = new DotNetPackOptions(projectPath); var pushOptions = new DotNetNugetPushOptions(packagePath); ``` -------------------------------- ### Register Module Hooks Source: https://github.com/thomhurst/modularpipelines/blob/main/docs/docs/how-to/hooks.md Register a custom class that implements `IPipelineModuleHooks` to execute actions before and after each module starts and ends. ```csharp collection.AddPipelineModuleHooks(); ``` -------------------------------- ### Tool Options Class Initialization in v3 Source: https://github.com/thomhurst/modularpipelines/blob/main/docs/docs/migrating-to-v3.md Shows the required way to initialize tool options classes in v3 using property initializers, as constructors are no longer provided. ```csharp // Use property initializers instead var newOptions = new DotNetNewOptions { TemplateShortName = "console" }; var packOptions = new DotNetPackOptions { TargetPath = projectPath }; var pushOptions = new DotNetNugetPushOptions { PackagePath = packagePath }; ``` -------------------------------- ### Conditional Execution Attributes Source: https://github.com/thomhurst/modularpipelines/blob/main/RELEASE_NOTES_V3.md Provides examples of attributes used to control module execution based on platform or specific conditions. ```csharp [RunOnLinux] public class LinuxModule : Module { } ``` ```csharp [RunOnWindowsOnly] // Skips on other platforms public class WindowsOnlyModule : Module { } ``` ```csharp [SkipIf(typeof(IsNotMainBranchCondition))] public class MainBranchModule : Module { } ``` ```csharp [RunIfAll(typeof(IsCI), typeof(IsMainBranch))] public class CIMainModule : Module { } ``` -------------------------------- ### Fluent Module Configuration: V2 vs V3 Source: https://github.com/thomhurst/modularpipelines/blob/main/RELEASE_NOTES_V3.md Illustrates the shift from scattered property overrides in V2 to a centralized, fluent configuration API in V3 for module behavior. ```csharp // Before (V2) - properties scattered across the class protected internal override TimeSpan Timeout => TimeSpan.FromMinutes(5); protected override AsyncRetryPolicy RetryPolicy => ...; protected internal override Task ShouldSkip(...) => ...; ``` ```csharp // After (V3) - everything in one place protected override ModuleConfiguration Configure() => ModuleConfiguration.Create() .WithTimeout(TimeSpan.FromMinutes(5)) .WithRetryCount(3) .WithSkipWhen(ctx => ctx.Git().Information.BranchName != "main" ? SkipDecision.Skip("Only runs on main") : SkipDecision.DoNotSkip) .Build(); ``` -------------------------------- ### Module Configuration: Before/After Execute Source: https://github.com/thomhurst/modularpipelines/blob/main/docs/docs/migrating-to-v3.md For executing logic before or after a module runs in v3, use `Configure().WithBeforeExecute(...)` or `Configure().WithAfterExecute(...)`, or the `OnBeforeExecuteAsync(...)` and `OnAfterExecuteAsync(...)` methods. ```yaml - old: "protected internal override Task OnBeforeExecute(IPipelineContext context)" new: "Configure().WithBeforeExecute(...) or OnBeforeExecuteAsync(...)" ``` ```yaml - old: "protected internal override Task OnAfterExecute(IPipelineContext context)" new: "Configure().WithAfterExecute(...) or OnAfterExecuteAsync(...)" ``` -------------------------------- ### Auto-Registering Dependencies Source: https://github.com/thomhurst/modularpipelines/blob/main/docs/docs/how-to/execution-and-dependencies.md When a required dependency is declared, ModularPipelines automatically registers it, simplifying pipeline setup. This includes transitive dependencies. ```csharp await PipelineHostBuilder.Create() .AddModule() // Module1 is auto-registered because Module2 depends on it .ExecutePipelineAsync(); ``` -------------------------------- ### Pipeline Program Configuration Source: https://context7.com/thomhurst/modularpipelines/llms.txt Sets up the pipeline builder, configures settings from various sources (JSON, user secrets, environment variables), and registers the pipeline modules. This is the entry point for the pipeline execution. ```csharp // Program.cs var builder = Pipeline.CreateBuilder(args); builder.Configuration .AddJsonFile("appsettings.json") .AddUserSecrets() .AddEnvironmentVariables(); builder.Services.Configure(builder.Configuration.GetSection("NuGet")); builder.Services .AddModule() .AddModule() .AddModule() .AddModule(); await builder.Build().RunAsync(); ``` -------------------------------- ### Implement IPipelineModuleHooks for Module Events Source: https://github.com/thomhurst/modularpipelines/blob/main/docs/architecture/interface-hierarchy.md Implement IPipelineModuleHooks to receive callbacks before a module starts and after it ends, utilizing IPipelineHookContext for context and logging. ```csharp public class MyModuleHooks : IPipelineModuleHooks { public Task OnBeforeModuleStartAsync(IPipelineHookContext context, IModule module) { context.Logger.LogInformation("Module {ModuleName} starting...", module.GetType().Name); return Task.CompletedTask; } public Task OnAfterModuleEndAsync(IPipelineHookContext context, IModule module) { context.Logger.LogInformation("Module {ModuleName} finished", module.GetType().Name); return Task.CompletedTask; } } ``` -------------------------------- ### Build and Run Pipeline Source: https://github.com/thomhurst/modularpipelines/blob/main/docs/docs/how-to/pipeline-host.md The standard two-step process to build the pipeline configuration and then execute it asynchronously. Includes basic error handling for failed runs. ```csharp var builder = Pipeline.CreateBuilder(args); builder.Services.AddModule(); // Step 1: Build the pipeline var pipeline = builder.Build(); // Step 2: Run it var summary = await pipeline.RunAsync(); // Check results if (summary.Status == PipelineStatus.Failed) { Environment.Exit(1); } ``` -------------------------------- ### Run Build Pipeline Source: https://github.com/thomhurst/modularpipelines/blob/main/CLAUDE.md Executes the build pipeline from the src/ModularPipelines.Build directory. Use the Release configuration and net10.0 framework. ```bash # Run the build pipeline (from src/ModularPipelines.Build) cd src/ModularPipelines.Build dotnet run -c Release --framework net10.0 ``` -------------------------------- ### V3 Command Execution Pattern Source: https://github.com/thomhurst/modularpipelines/blob/main/docs/docs/migrating-to-v3.md Shows how to execute commands with tool-specific options separated from general command execution options. ```csharp // Tool-specific options separate from execution options await context.DotNet().Build( new DotNetBuildOptions { ProjectSolution = "MySolution.sln", Configuration = "Release", }, new CommandExecutionOptions { WorkingDirectory = "/path/to/project", EnvironmentVariables = new Dictionary { ["CI"] = "true" }, ThrowOnNonZeroExitCode = false, ExecutionTimeout = TimeSpan.FromMinutes(10) }); ``` -------------------------------- ### Implement Module Hooks Source: https://github.com/thomhurst/modularpipelines/blob/main/docs/docs/how-to/hooks.md Define a class implementing `IPipelineModuleHooks` to log module start and end events, including module name and duration. ```csharp public class MyModuleHooks : IPipelineModuleHooks { public Task OnBeforeModuleStartAsync(IPipelineHookContext context, IModule module) { context.Logger.LogInformation("{Module} is starting", module.GetType().Name); return Task.CompletedTask; } public Task OnBeforeModuleEndAsync(IPipelineHookContext context, IModule module) { context.Logger.LogInformation("{Module} finished after {Elapsed}", module.GetType().Name, module.Duration); return Task.CompletedTask; } } ``` -------------------------------- ### Alternative Result Access Patterns in v3 Source: https://github.com/thomhurst/modularpipelines/blob/main/docs/docs/migrating-to-v3.md Demonstrates various ways to access results from module execution in v3, including pattern matching, helper methods, safe accessors, and status checks. Pattern matching is recommended for handling all result cases. ```csharp var buildResult = await context.GetModule(); // Option 1: Pattern matching (recommended - handles all cases) return buildResult switch { ModuleResult.Success { Value: var output } => Process(output), ModuleResult.Skipped => null, ModuleResult.Failure { Exception: var ex } => throw ex, _ => null }; // Option 2: Match helper method (functional style) return buildResult.Match( onSuccess: output => Process(output), onFailure: ex => throw new InvalidOperationException("Failed", ex), onSkipped: skip => null ); // Option 3: Safe accessor (simplest migration path) var artifact = buildResult.ValueOrDefault?.ArtifactPath; if (artifact == null) return null; return await Deploy(artifact); // Option 4: Quick status checks if (buildResult.IsSuccess) { var value = buildResult.ValueOrDefault; } if (buildResult.IsFailure) { var ex = buildResult.ExceptionOrDefault; } if (buildResult.IsSkipped) { var reason = buildResult.SkipDecisionOrDefault?.Reason; } ``` -------------------------------- ### IHookable + ISkippable Interaction Example Source: https://github.com/thomhurst/modularpipelines/blob/main/docs/docs/architecture/module-execution-lifecycle.md Demonstrates how `OnBeforeExecute` and `OnAfterExecute` are not called when a module implementing `IHookable` and `ISkippable` is skipped. The `ShouldSkip` method is evaluated first. ```csharp public class MyModule : Module, IHookable, ISkippable { public Task ShouldSkip(IPipelineContext context) { // This runs FIRST return SkipDecision.Skip("Not needed").AsTask(); } public Task OnBeforeExecute(IPipelineContext context) { // This does NOT run when skipped return Task.CompletedTask; } public Task OnAfterExecute(IPipelineContext context) { // This does NOT run when skipped return Task.CompletedTask; } } ``` -------------------------------- ### Implement Custom Pipeline Validation Source: https://github.com/thomhurst/modularpipelines/blob/main/docs/architecture/interface-hierarchy.md Implement IPipelineValidator to add custom validation logic during pipeline initialization. This example checks for the registration of a required service. ```csharp public class MyValidator : IPipelineValidator { public int Order => 100; public ValidationResult Validate(IServiceProvider services) { var errors = new List(); // Check for required services if (services.GetService() == null) { errors.Add("IMyRequiredService is not registered"); } return new ValidationResult(errors); } } ``` -------------------------------- ### Implement Global Hooks Source: https://github.com/thomhurst/modularpipelines/blob/main/docs/docs/how-to/hooks.md Define a class implementing `IPipelineGlobalHooks` to log pipeline start and end events. The end hook also provides access to `PipelineSummary`. ```csharp public class MyGlobalHooks : IPipelineGlobalHooks { public Task OnStartAsync(IPipelineHookContext pipelineContext) { pipelineContext.Logger.LogInformation("Pipeline is starting"); return Task.CompletedTask; } public Task OnEndAsync(IPipelineHookContext pipelineContext, PipelineSummary pipelineSummary) { pipelineContext.Logger.LogInformation("Pipeline is ending"); return Task.CompletedTask; } } ``` -------------------------------- ### Implement IPipelineGlobalHooks for Pipeline Lifecycle Events Source: https://github.com/thomhurst/modularpipelines/blob/main/docs/architecture/interface-hierarchy.md Implement IPipelineGlobalHooks to receive callbacks for pipeline start and end events, using IPipelineHookContext for accessing pipeline capabilities. ```csharp public class MyHooks : IPipelineGlobalHooks { public Task OnStartAsync(IPipelineHookContext context) { context.Logger.LogInformation("Pipeline starting..."); return Task.CompletedTask; } public Task OnEndAsync(IPipelineHookContext context, PipelineSummary summary) { context.Logger.LogInformation("Pipeline finished: {TotalModules} modules", summary.TotalModules); return Task.CompletedTask; } } ``` -------------------------------- ### Pipeline Creation: v2 vs v3 Source: https://github.com/thomhurst/modularpipelines/blob/main/docs/docs/migrating-to-v3.md Use `Pipeline.CreateBuilder(args)` in v3, passing command-line arguments. The v2 `PipelineHostBuilder.Create()` is replaced. ```yaml - old: "PipelineHostBuilder.Create()" new: "Pipeline.CreateBuilder(args)" ```