Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Build/Program.fs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ module Project =
"build", Repo.Project.``Partas.Build``.Path
"baked", Repo.Project.``Partas.Build.Baked``.Path
"cmd", Repo.Project.``Partas.Build.Cmd``.Path
"shipit", Repo.Project.``Partas.Build.EasyBuild.ShipIt``.Path
"external-annotations", Repo.Project.``Partas.ExternalAnnotations``.Path
"external-annotations-tool", Repo.Project.``Partas.ExternalAnnotations.Tool``.Path
"build-external-annotations", Repo.Project.``Partas.Build.ExternalAnnotations``.Path
Expand Down
3 changes: 3 additions & 0 deletions Partas.Build.slnx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
<Project Path="src/Partas.Build.Cmd/Partas.Build.Cmd.fsproj" />
<Project Path="src/Partas.Build/Partas.Build.fsproj" />
</Folder>
<Folder Name="/src/extensions/">
<Project Path="src/extensions/Partas.Build.EasyBuild.ShipIt/Partas.Build.EasyBuild.ShipIt.fsproj" />
</Folder>
<Folder Name="/src/external-annotations/">
<Project Path="Partas.Build.ExternalAnnotations/Partas.Build.ExternalAnnotations.fsproj" />
<Project Path="Partas.ExternalAnnotations.Tool/Partas.ExternalAnnotations.Tool.fsproj" />
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,7 @@ Build/
src/Partas.Build/ the library
src/Partas.Build.Cmd/ the command value and the process runner
src/Partas.Build.Baked/ ready-made options, stages and semver helpers
src/extensions/Partas.Build.EasyBuild.ShipIt/ ShipIt-backed bump, release inputs, commands and explicit setup
docs/ the Nacara site (Site.fs, docs.fsproj, content/, blog/, static/)
tests/ the Expecto suites
```
Expand Down
6 changes: 5 additions & 1 deletion docs/Site.fs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ let theme =
Theme.defaults
|> Theme.navbar [
NavbarSection("Build", "build", "/build/")
NavbarSection("Extensions", "extensions", "/extensions/")
NavbarSection("External Annotations", "external-annotations", "/external-annotations/")
NavbarSection("Reference", "reference", "/reference/")
NavbarDivider
Expand All @@ -32,7 +33,10 @@ let theme =
let apiOptions = {
FSharpApi.defaults with
Root = "reference"
Sources = [ FSharpApiSource.create "../src/Partas.Build/bin/Release/net10.0/Partas.Build.dll" ]
Sources = [
FSharpApiSource.create "../src/Partas.Build/bin/Release/net10.0/Partas.Build.dll"
FSharpApiSource.create "../src/extensions/Partas.Build.EasyBuild.ShipIt/bin/Release/net10.0/Partas.Build.EasyBuild.ShipIt.dll"
]
Exclude = [ "Partas.Build.Internal" ]
}

Expand Down
13 changes: 13 additions & 0 deletions docs/content/extensions/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
title: Extensions
category: Extensions
order: 0
---

# Extensions

Extensions package workflows for specific tools as composable Partas.Build operations, inputs, stages and commands.

- [EasyBuild.ShipIt](shipit.md): conventional-commit versioning, synchronized changelog/project updates, release commands and explicit setup.

Use `Partas.Build.Baked` for general build operations. Use an extension when its tool should own a workflow, such as calculating package versions from commit history.
113 changes: 113 additions & 0 deletions docs/content/extensions/shipit.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
---
title: EasyBuild.ShipIt
category: Extensions
order: 1
---

# EasyBuild.ShipIt

`Partas.Build.EasyBuild.ShipIt` wraps [EasyBuild.ShipIt](https://github.com/easybuild-org/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; script consumers can use the [package feed described on the home page](https://shayanhabibi.github.io/Partas.Build/).

## Add the commands to your build

```fsharp
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

```shell
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

```shell
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:

```yaml
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

```shell
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:

```fsharp
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](https://github.com/easybuild-org/EasyBuild.ShipIt#configuration) 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](https://shayanhabibi.github.io/Partas.Build/reference/).
1 change: 1 addition & 0 deletions docs/static/llms.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
- [Index](https://shayanhabibi.github.io/Partas.Build/build/): the layers, and a first pipeline
- [Composition](https://shayanhabibi.github.io/Partas.Build/build/composition/): nesting stages, and reusing commands across files
- [Hosting](https://shayanhabibi.github.io/Partas.Build/build/hosting/): running a build from a long-lived F# session (SageFs) through `Command.invoke`
- [ShipIt extension](https://shayanhabibi.github.io/Partas.Build/extensions/shipit/): ShipIt-backed package bumps, release commands and explicit setup

## Ask the script rather than reading it

Expand Down
Loading