Skip to content

EasyBuild.ShipIt

EasyBuild.ShipIt

Partas.Build.EasyBuild.ShipIt wraps EasyBuild.ShipIt as reusable operations, inputs, stages and commands. ShipIt calculates release versions from conventional commits, updates changelogs and configured project files, and can open release pull requests.

The extension supports net10.0, net8.0 and netstandard2.0. The default ShipIt tool version, 3.1.0, requires .NET 10. Add the extension as a project/package reference using the installation guide.

Add the commands to your build

open Partas.Build
open Partas.Build.EasyBuild.ShipIt

let root = Command.root {
    workingDir __SOURCE_DIRECTORY__
    addCommand Commands.shipit
    addCommand (command "bump" {
        Command.pipeline { Stages.bump }
    })
}

let build args = Command.invoke args root

Commands.shipit exposes generate, github, bump, version, conventions, setup, and init changelog|workflows|github|project. Each command registers the inputs its stages read. Help, schema and explain inspect the workflow without running setup or release operations.

For a build project, invoke it as dotnet run --project Build.fsproj -- shipit .... For a script, use dotnet fsi build.fsx -- shipit ... after your usual root invocation. The following examples use the build-project form.

Set up the local tool

dotnet run --project Build.fsproj -- shipit setup

Setup creates the Git repository's .config/dotnet-tools.json if absent, installs EasyBuild.ShipIt 3.1.0 only if unregistered, and restores the tools. Existing registrations retain their pinned version. --tool-version selects the version for a new registration. There is no global installation.

From a subdirectory, setup still uses the closest Git repository's manifest. Competing nested manifests or an alternate root dotnet-tools.json are rejected; invoke from the repository root or remove the competing manifest. Normal ShipIt prefab stages apply the same boundary check.

Setup is explicit: bumping does not install the tool or change GitHub settings.

Keep package versions and changelogs together

dotnet run --project Build.fsproj -- shipit init project \
  --changelog src/MyLibrary/CHANGELOG.md \
  --project src/MyLibrary/MyLibrary.fsproj

Use a single line in PowerShell. This creates the changelog if missing and registers a ShipIt XML updater. Project/changelog input paths are relative to the stage's working directory; updater paths are relative to the changelog:

updaters:
  - xml:
      file: MyLibrary.fsproj
      selector: /Project/PropertyGroup/Version

Configuration preserves existing front matter, comments, changelog body, line endings and UTF-8 BOM. Repeated setup does not duplicate equivalent XML updaters. Projects must contain exactly one unconditional literal <Version> under <Project><PropertyGroup>. Conditional, computed or externally defined versions require manual updater configuration. Existing updaters must use a nonempty block sequence; remove an empty key before initialization.

For independently versioned packages, use a changelog for each package. For a shared version, register multiple projects against one changelog using --project. When adopting an existing package, seed its changelog with its last released version and set last_commit_released to the correct commit. ShipIt calculates from the changelog's release history, rather than reading the .fsproj version as its baseline.

AssemblyVersion remains under your compatibility policy. This setup only registers updates for the package Version.

Use the ShipIt-backed bump

dotnet run --project Build.fsproj -- shipit bump --allow-branch master --dry-run
dotnet run --project Build.fsproj -- shipit bump --allow-branch master

Stages.bump, Stages.bumpWith and shipit bump always use local mode: ShipIt calculates the version and updates the changelog and configured project files without pushing or creating a PR. Even consumer-supplied options with another mode are forced to local. The bump command has no --mode input.

Do not follow this with the agnostic Partas.Build.Baked.SemVer bump. ShipIt owns the release version; a second independent increment could make the changelog and package disagree. Review the local changes, commit them, then compose your normal build, pack and publish stages.

Consumer-defined inputs can supply the configuration directly:

let bump = Stages.bumpWith (InputSpec.ret {
    ReleaseOptions.defaults with
        AllowedBranches = [ "master" ]
        PreRelease = Some "beta"
})

let bumpCommand = command "bump" {
    Command.pipeline { bump }
}

Omit PreRelease for a stable CLI request, or supply a prefix such as beta. A prerelease configured in changelog front matter still applies when the CLI prefix is omitted.

Release and initialize GitHub explicitly

shipit generate supports --mode local|pull-request|push, defaulting to pull-request. shipit github selects the GitHub provider explicitly and accepts a sensitive --token; it falls back to GITHUB_TOKEN or upstream gh authentication. Token values are masked in command labels, schema and explain; upstream tool output remains upstream's responsibility.

Release inputs also include --allow-branch (default main, multiple values), --pre-release PREFIX, remote hostname/owner/repository overrides, --skip-invalid-commit, --skip-merge-commit, and --dry-run. Use --allow-branch master for repositories using master.

shipit init changelog and shipit init workflows delegate upstream scaffolding, which refuses to overwrite existing files. shipit init github applies GitHub merge and workflow-permission settings using authenticated gh; preview them with --dry-run. --org additionally changes organization settings and requires the appropriate administrative access.

CI needs full Git history, conventional commits and suitable GitHub permissions/authentication. ShipIt generates release changes; it does not publish NuGet packages. See upstream's configuration and CI recipes for changelog include/exclude rules and release automation.

Choose the composition level

  • Operations: pure Cmd builders for upstream operations. Low-level callers supply their own working directory/tool resolution.
  • Inputs: reusable typed CLI inputs, including token defaults evaluated per invocation.
  • Stages: ready-made stages and *With variants for consumer-supplied InputSpec values. They inherit normal execution settings.
  • Commands.shipit: the complete command tree for a build root.

The extension is also included in the API reference.

Edit this page