Skip to content

Commit 5f9e96e

Browse files
thomhurstclaude
andcommitted
fix: make ThrowOnPipelineFailure configurable via PipelineOptions
Add ThrowOnPipelineFailure option (default true) to control whether PipelineFailedException is thrown when pipeline fails. This ensures: - Production/CI: Throws by default for non-zero exit codes - Tests: Can disable to inspect PipelineSummary without catching exceptions Test helper now sets ThrowOnPipelineFailure = false by default so existing tests continue to work as expected. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 2958103 commit 5f9e96e

3 files changed

Lines changed: 24 additions & 1 deletion

File tree

src/ModularPipelines/Engine/Executors/ExecutionOrchestrator.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
using System.Diagnostics;
22
using Microsoft.Extensions.Logging;
3+
using Microsoft.Extensions.Options;
34
using ModularPipelines.Enums;
45
using ModularPipelines.Exceptions;
56
using ModularPipelines.Helpers;
67
using ModularPipelines.Models;
78
using ModularPipelines.Modules;
9+
using ModularPipelines.Options;
810

911
namespace ModularPipelines.Engine.Executors;
1012

@@ -34,6 +36,7 @@ internal class ExecutionOrchestrator : IExecutionOrchestrator
3436
private readonly EngineCancellationToken _engineCancellationToken;
3537
private readonly IThreadPoolConfigurator _threadPoolConfigurator;
3638
private readonly IExceptionRethrowService _exceptionRethrowService;
39+
private readonly IOptions<PipelineOptions> _options;
3740
private readonly ILogger<ExecutionOrchestrator> _logger;
3841

3942
private readonly object _lock = new();
@@ -50,6 +53,7 @@ public ExecutionOrchestrator(
5053
EngineCancellationToken engineCancellationToken,
5154
IThreadPoolConfigurator threadPoolConfigurator,
5255
IExceptionRethrowService exceptionRethrowService,
56+
IOptions<PipelineOptions> options,
5357
ILogger<ExecutionOrchestrator> logger)
5458
{
5559
_pipelineInitializer = pipelineInitializer;
@@ -61,6 +65,7 @@ public ExecutionOrchestrator(
6165
_engineCancellationToken = engineCancellationToken;
6266
_threadPoolConfigurator = threadPoolConfigurator;
6367
_exceptionRethrowService = exceptionRethrowService;
68+
_options = options;
6469
_logger = logger;
6570
}
6671

@@ -149,7 +154,7 @@ private async Task<PipelineSummary> OnEnd(OrganizedModules organizedModules, Sto
149154
}
150155

151156
// Throw exception if pipeline failed - this ensures non-zero exit code in CI
152-
if (pipelineSummary.Status == Status.Failed)
157+
if (pipelineSummary.Status == Status.Failed && _options.Value.ThrowOnPipelineFailure)
153158
{
154159
var failedModules = pipelineSummary.GetFailedModuleResults()
155160
.Select(r => r.ModuleName)

src/ModularPipelines/Options/PipelineOptions.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,4 +205,21 @@ public bool ShowProgressInConsole
205205
/// </para>
206206
/// </remarks>
207207
public CommandExecutionOptions? DefaultExecutionOptions { get; set; }
208+
209+
/// <summary>
210+
/// Gets or sets a value indicating whether to throw a <see cref="Exceptions.PipelineFailedException"/>
211+
/// when the pipeline completes with one or more failed modules.
212+
/// </summary>
213+
/// <remarks>
214+
/// <para>
215+
/// Default is <c>true</c> to ensure non-zero exit codes in CI/CD environments.
216+
/// When a pipeline fails, the exception is thrown after the summary has been printed,
217+
/// ensuring users see the full output before the process exits.
218+
/// </para>
219+
/// <para>
220+
/// Set to <c>false</c> for scenarios where you want to inspect the <see cref="Models.PipelineSummary"/>
221+
/// programmatically without catching exceptions (e.g., in tests or when implementing custom failure handling).
222+
/// </para>
223+
/// </remarks>
224+
public bool ThrowOnPipelineFailure { get; set; } = true;
208225
}

test/ModularPipelines.TestHelpers/TestPipelineHostBuilder.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ public static PipelineBuilder Create(TestHostSettings testHostSettings, TimeProv
2929
builder.Options.PrintResults = false;
3030
builder.Options.PrintLogo = false;
3131
builder.Options.PrintDependencyChains = false;
32+
builder.Options.ThrowOnPipelineFailure = false; // Tests handle failures explicitly
3233

3334
if (testHostSettings.ClearLogProviders)
3435
{

0 commit comments

Comments
 (0)