Skipping Modules
Using ModuleConfiguration
The recommended way to configure module skipping is through the Configure(ModuleConfigurationBuilder) method with the fluent builder API:
Attribute conditions ([SkipIf<T>], [RunIf<T>], [RunIfAll<T1, ..., T4>], and
[RunIfAny<T1, ..., T4>]) remain supported; the grouped forms accept two to four conditions.
Attribute and fluent conditions run in the same execution pipeline after dependency waiting, so
both invoke skipped hooks and lifecycle notifications.
PlanAsync() and --dry-run also evaluate these conditions before execution. Conditions must be
side-effect-free and must not rely on being evaluated exactly once.
If a fluent condition reads an awaited module result, that result does not exist during planning;
the plan reports the module's skip decision as unknown and continues without executing modules.
Simple Condition
public class MyModule : Module<CommandResult>
{
protected override void Configure(ModuleConfigurationBuilder module) => module
.WithSkipWhen(
_ => Environment.GetEnvironmentVariable("SKIP_MODULE") == "true",
"SKIP_MODULE is true");
protected override async Task<CommandResult> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken)
{
// Module logic here
}
}
Using Pipeline Context
When you need access to the pipeline context for your skip condition:
public class MyModule : Module<CommandResult>
{
protected override void Configure(ModuleConfigurationBuilder module) => module
.WithSkipWhen(
async (ctx, _) => (await ctx.Tools.Git.Information.GetInfoAsync())?.BranchName != "main",
"This should only run on the main branch");
protected override async Task<CommandResult> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken)
{
// This only runs on the main branch
}
}
With Skip Reason
For better reporting, pass the reason alongside the boolean condition:
public class MyModule : Module<CommandResult>
{
protected override void Configure(ModuleConfigurationBuilder module) => module
.WithSkipWhen(async (ctx, _) =>
{
var repositoryInfo = await ctx.Tools.Git.Information.GetInfoAsync();
return repositoryInfo?.BranchName != "main";
}, "This should only run on the main branch");
protected override async Task<CommandResult> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken)
{
// Module logic here
}
}
Async Skip Conditions
For conditions that require async operations:
public class MyModule : Module<CommandResult>
{
protected override void Configure(ModuleConfigurationBuilder module) => module
.WithSkipWhen(async (_, cancellationToken) =>
{
var response = await HttpClient.GetAsync(
"https://api.example.com/should-run",
cancellationToken);
return !response.IsSuccessStatusCode;
}, "The remote service is unavailable");
}
Combining with Other Behaviors
Repeated WithSkipWhen conditions use OR-to-skip semantics, matching repeated [SkipIf<T>]
attributes. They run in registration order, and evaluation stops when any condition returns
SkipDecision.Skip.
For example, this module skips cleanup for either CI builds or non-main branches:
public class CleanupModule : Module<CommandResult>
{
protected override void Configure(ModuleConfigurationBuilder module) => module
.WithSkipWhen(_ => Environment.GetEnvironmentVariable("CI") == "true", "Running in CI")
.WithSkipWhen(
async (ctx, _) => (await ctx.Tools.Git.Information.GetInfoAsync())?.BranchName != "main",
"Not on the main branch")
.WithAlwaysRun() // Run even if dependencies fail (when not skipped)
.WithTimeout(TimeSpan.FromMinutes(5));
}
When every condition must match before the module is skipped, group them explicitly with
WithSkipWhenAll:
protected override void Configure(ModuleConfigurationBuilder module) => module
.WithSkipWhenAll(
_ => Environment.GetEnvironmentVariable("CI") == "true"
? SkipDecision.Skip("Running in CI")
: SkipDecision.DoNotSkip,
_ => Environment.GetEnvironmentVariable("DEPLOY_ENV") != "production"
? SkipDecision.Skip("Not deploying to production")
: SkipDecision.DoNotSkip);
Conditions inside a WithSkipWhenAll group use AND-to-skip semantics and combine their reasons.
The group composes with other skip conditions using OR-to-skip semantics.
History
If a module was skipped, you can attempt to find its history from a previous run. See History
Run Conditions
See Run Conditions
Categories
See Categories