Pipeline Modules
Pipeline Modules
Section titled “Pipeline Modules”The pipeline is a Modular Pipelines orchestration. Modules are registered in BuildPipeline.cs (Program.cs handles the CLI: informational options, the version banner, and failure reporting); explicit [DependsOn] edges define ordering, while ModuleConfiguration skip conditions gate opt-in behavior. Module categories are Build and Release.
Each module logs a line when it starts (Running BuildModule...) before its command output, so long runs report progress in CI logs where the live progress display is disabled.
CleanArtifacts → { Version, Restore → Build → Test, Restore → Lint } → Pack → ValidatePack → Publish → GitHub releaseCleanArtifactsModule
Section titled “CleanArtifactsModule”Deletes Build:ArtifactsFolder (when it exists) and recreates it empty, before any other module runs. The folder is shared output: pack writes it, validation inspects every package in it, publishing moves packages out of it, and the release step can upload its contents — so a leftover package from an earlier (or differently configured) run would otherwise be validated, published, or uploaded as if it belonged to this run.
VersionModule and RestoreModule depend on this module, so the reset completes before any other module starts. Skip conditions: skipped when Build:CleanArtifacts is false, or when Build:RunPack is false (nothing will be packed, so existing artifacts — for example a folder being inspected ahead of a manual publish — are left untouched).
VersionModule
Section titled “VersionModule”Reads the SemVer version field from the repository root package.json and produces a NuGetVersion. Fails when the file is missing, the field is missing/empty, or the value is not valid SemVer. The version feeds PackModule (via Version/PackageVersion) and CreateGitHubReleaseModule (via the v{version} tag).
RestoreModule
Section titled “RestoreModule”Runs Build:WebInstallCommand (default bun install) when Build:ProjectType is Web, otherwise dotnet restore against Build:Solution.
BuildModule
Section titled “BuildModule”Depends on RestoreModule.
- DotNet: runs
dotnet buildagainstBuild:SolutionwithBuild:Configurationand--no-restore. - Web: when
Build:WebBuildCommandis left at the default (bun run build) and the repository declares adata:syncscript, first runsbun run data:sync(so a fresh checkout can build offline), then runs the build command. OverridingWebBuildCommandtakes full control of the build (for example a chain of validation scripts); the automatic data sync is then skipped.
LintModule
Section titled “LintModule”Depends on RestoreModule (Web lint invokes tooling installed by the restore step, so it must wait for bun install; dotnet lint is unaffected beyond running after restore). Skip condition: skipped when Build:RunLint is false.
- DotNet: restores the repository’s local tools (
dotnet tool restoreagainst.config/dotnet-tools.json, retried up to 3 times with a 2-second backoff on failure) and then runsdotnet tool run csharpier check <repository root>. The repository root is resolved by walking up to the nearestpackage.json. - Web: runs
Build:WebFormatCheckCommand(defaultbun run format:check) thenBuild:WebLintCommand(defaultbun run lint). Each step is skipped when the corresponding script is not declared in the rootpackage.json.
RunTestsModule
Section titled “RunTestsModule”Depends on BuildModule. Skip condition: skipped when Build:RunTests is false.
- DotNet: discovers test projects by enumerating
*.csprojrecursively underBuild:TestRoot, matching file names againstBuild:TestPatterns(comma-separated glob/name patterns, case-insensitive), then restricting the run list withBuild:TestProjects(default*). If no projects match, it logs a warning and returns an empty result. Runs each test project withdotnet test --no-build --no-restorein parallel, usingBuild:Configuration:- TUnit (default): passes
--ignore-exit-code 8(Microsoft.Testing.Platform exits with code 8 when no tests are selected; treated as success) and, whenBuild:TestFilteris non-empty,--treenode-filter <filter>. - xUnit: when
Build:TestFilteris non-empty, passes--filter <filter>.
- TUnit (default): passes
- Web: runs
Build:WebTestCommand(defaultbun run test) from the repository root.
Per-project timings are logged, ordered by elapsed time.
PackModule
Section titled “PackModule”Depends on RunTestsModule and VersionModule. Skip condition: skipped when Build:RunPack is false.
CleanArtifactsModule resets Build:ArtifactsFolder before the run produces anything, so the folder only contains packages from the current run.
- DotNet: creates
Build:ArtifactsFolderand runsdotnet packagainstBuild:SolutionwithBuild:Configuration,--output <ArtifactsFolder>, and-p:PackageVersion=<version> -p:Version=<version>where the version comes fromVersionModule. - Web: creates
Build:ArtifactsFolderand zipsBuild:WebBuildOutput(defaultsrc/dist) into<package-name>-<version>.zip(name from the rootpackage.jsonnamefield, version fromVersionModule). Logs a warning and produces no artifact when the build output directory does not exist.
ValidatePackModule
Section titled “ValidatePackModule”Depends on PackModule. Skip condition: skipped when Build:ValidatePack is false or Build:ProjectType is Web (Web projects produce no .nupkg).
Inspects every .nupkg/.snupkg in Build:ArtifactsFolder. Because CleanArtifactsModule cleared the folder at the start of the run, the packages inspected are exactly those the current run packed. Fails the run if any package has errors. Produces a summary of valid/invalid package counts. See Pack Validation for the full rule set.
PublishNuGetModule
Section titled “PublishNuGetModule”Category Release. Depends on PackModule, ValidatePackModule, and RunTestsModule. Skip condition: skipped when Build:ProjectType is Web or Release:Mode is not NuGet or (NuGet:TrustedPublishing is false and no API key resolves via NuGet:GetNuGetAPIKey()).
Pushes every *.nupkg in Build:ArtifactsFolder to NuGet:FeedUrl with --skip-duplicate. When NuGet:TrustedPublishing is true, pushes without an API key (NuGet Trusted Publishing / OIDC federation).
PublishLocalNuGetModule
Section titled “PublishLocalNuGetModule”Depends on PackModule and ValidatePackModule. Skip condition: skipped when Build:ProjectType is Web or the tool is not running locally (ctx.IsRunningLocally()) or Release:Mode is not LocalNuGet. This mode is intentionally ignored in CI.
Validates PublishLocalNuGet:LocalFeedPath (resolved via GetLocalFeedPath(), falling back to PublishLocalNuGet__LOCAL_NUGET_FEED_PATH and then process env LOCAL_NUGET_FEED_PATH). The path must be absolute; drive-relative paths such as p:foo (backslashes stripped by a sh-style shell) are rejected with a remediation message. See Local Development.
Moves the .nupkg/.snupkg files from Build:ArtifactsFolder into the local feed (skipping existing files unless OverwriteExistingPackages is true), optionally clears the NuGet global-packages and HTTP caches for the published packages (ClearPackageCache), and optionally shuts down the dotnet build server (ShutdownDotnetBuilderServer).
CreateGitHubReleaseModule
Section titled “CreateGitHubReleaseModule”Category Release. Depends on PublishNuGetModule, ValidatePackModule, and VersionModule. Skip condition: skipped unless Release:Mode is NuGet or GitHubRelease and a GitHub token resolves via GitHub:GetGitHubToken().
Creates a GitHub release with tag v{version} and GenerateReleaseNotes = true. Releases whose version is a prerelease (for example 2.0.0-prerelease.25) are created as GitHub prereleases unless Release:MarkPrerelease is false, so prerelease builds are not presented as the latest stable release. This changes GitHub release metadata only: prerelease versions are still published to the NuGet feed — PublishNuGetModule is unaffected. When Release:UploadArtifacts is true, uploads every file in Build:ArtifactsFolder as a release asset — for Web projects this is the <package-name>-<version>.zip produced by PackModule. The tag must not already exist; callers gate release eligibility (the tool does not skip an existing tag itself).