-
-Command line and build pipelines in F#. Composable, hints of elderberry, thick in tannins, a glorious vintage.
-
-A pipeline DSL based on [Fun.Build](https://github.com/slaveOftime/Fun.Build), scaffolded over
-[FSharp.SystemCommandLine](https://github.com/jordanmarr/FSharp.SystemCommandLine), for no-nonsense CLIs. CLI
-inputs are declared where used and lifted into the command line help of the commands that run them, with
-automatic validation and help.
-
-## Layers
-
-| Layer | CE | Produces |
-|---|---|---|
-| Step | `run`, `echo`, … | one action inside a stage |
-| Stage | `stage "name" { }` | `StageContext` |
-| Inputs | `input { }` | `InputSpec<'T>` |
-| Pipeline | `pipeline "name" { }` | `PipelineContext` or `InputSpec
-
-## API reference
-
-The [API reference](https://shayanhabibi.github.io/Partas.Build/reference/) is generated from the XML
-documentation on each custom operation.
-*)
diff --git a/docs/content/Build/index.md b/docs/content/Build/index.md
new file mode 100644
index 0000000..22beebd
--- /dev/null
+++ b/docs/content/Build/index.md
@@ -0,0 +1,46 @@
+---
+title: Overview
+description: The building blocks of a Partas.Build command.
+category: Build
+order: 0
+---
+
+Partas.Build turns F# workflow definitions into command-line tools. A stage declares the inputs it reads; each command derives its options, validation, and help from those stages.
+
+## Start with a command
+
+[Install the packages](installation.md), then [create your first build](getting-started.md).
+
+```fsharp
+open Partas.Build
+
+let root = Command.root {
+ command "build" {
+ stage "compile" { run "dotnet build" }
+ }
+}
+
+let build args = Command.invoke args root
+```
+
+Construction runs nothing. `Command.invoke [ "build" ] root` parses the arguments and runs the selected workflow.
+
+## The building blocks
+
+- **Step**: one process or F# function inside a stage.
+- **Stage**: named steps, conditions, and execution settings.
+- **Input**: an option or argument bound where the workflow needs it.
+- **Pipeline**: an ordered workflow of stages.
+- **Command**: a CLI entry point containing stages or pipelines.
+- **Root**: the command tree, invoked once or reused by a host.
+
+## Choose your next task
+
+- [Inputs and help](inputs.md): bind options with `let!` and `and!`.
+- [Processes and secrets](steps.md): preserve argument boundaries and mask sensitive values.
+- [Composition](composition.md): reuse stages and commands.
+- [Execution](execution.md): conditions, parallelism, timeouts, and failure handling.
+- [Baked stages](baked.md): common .NET build operations.
+- [Agents and JSON](agents.md): inspect and run a build with structured output.
+
+[Capabilities](CAPABILITIES.md) lists the operations. [Workflow reference](workflow-reference.md) retains the detailed examples, and the [API reference](https://shayanhabibi.github.io/Partas.Build/reference/) supplies full signatures.
diff --git a/docs/content/Build/inputs.md b/docs/content/Build/inputs.md
new file mode 100644
index 0000000..cc375ba
--- /dev/null
+++ b/docs/content/Build/inputs.md
@@ -0,0 +1,57 @@
+---
+title: Inputs and help
+description: Bind CLI options and arguments where they are used.
+category: Build
+order: 3
+---
+
+Declare an input once. Bind it in an `input` block that returns a stage or pipeline.
+
+```fsharp
+open Partas.Build
+
+let quick =
+ Input.option
-
-Command line and build pipelines in F#. Composable, hints of elderberry, thick in tannins, a glorious vintage.
-
-A pipeline DSL based on [Fun.Build](https://github.com/slaveOftime/Fun.Build), scaffolded over
-[FSharp.SystemCommandLine](https://github.com/jordanmarr/FSharp.SystemCommandLine), for no-nonsense CLIs. CLI
-inputs are declared where used and lifted into the command line help of the commands that run them, with
-automatic validation and help.
+Detailed examples complement the [task-focused guides](index.md).
## Layers
@@ -81,7 +20,9 @@ automatic validation and help.
| Hosted root | `Command.root { }` | `RootCommandDefinition` — runs on each `Command.invoke args` |
## A first pipeline
-*)
+
+```fsharp
+open Partas.Build
let hello =
pipeline "hello" {
@@ -92,8 +33,7 @@ let hello =
run "dotnet --version"
}
}
-
-(**
+```
`step` -> `stage` -> `stage` -> ... -> `pipeline` -> `command` -> `rootCommand`. Nothing runs until the root
command does.
@@ -101,8 +41,8 @@ command does.
## Steps
A step is anything yielded inside a `stage`. `run` is heavily overloaded; three overloads matter:
-*)
+```fsharp
let steps =
stage "steps" {
// a whole command line, split on whitespace honouring quotes
@@ -114,77 +54,77 @@ let steps =
// an F# function; also Async<_>, Task<_>, StageContext -> _ and Result-returning variants
run (fun (ctx: StageContext) -> printfn "%s" ctx.Name)
}
+```
-(**
### Interpolation: use `cmd`
`run $"..."` binds the **`string`** overload, which flattens the holes and re-splits the result on whitespace.
A path containing a space becomes two arguments. Route interpolation through `cmd` instead: it keeps each hole
as exactly one argument and lets the platform do the escaping:
-*)
- // v------- will break if directly passed verbatim
+```fsharp
+// v------- will break if directly passed verbatim
let project = "src/My Project/My Project.fsproj"
let interpolated =
stage "build" {
run (cmd $"dotnet build {project}") // one argument, space and all
}
+```
-(**
`runSensitive` takes a `FormattableString` directly, needs no `cmd`, and masks every hole as `***` in the log
while passing the real value to the process:
-*)
+```fsharp
let password = "drowssap"
let login =
stage "login" {
runSensitive $"docker login -u me -p {password}"
}
+```
-(**
It masks *every* hole. Build a `Cmd` by hand when only one argument is secret. `Secrets` is a set of argument
indices:
-*)
+```fsharp
let pushArgs = [ "nuget"; "push"; "bin/x.nupkg"; "--api-key"; password ]
let push =
stage "push" {
run { Cmd.ofList "dotnet" pushArgs with Secrets = Set.singleton 4 }
}
+```
-(**
*New in >0.2.2*: wrap sensitive strings with `Cmd.secret` or `Cmd.sensitive`. Every command runner picks them
up and quotes any string containing spaces.
-*)
+```fsharp
let pushSecret =
stage "push" {
run $"dotnet nuget push bin/x.nupkg --api-key {Cmd.secret password}"
}
+```
-(**
## Conditions
`when'` and its friends set whether a stage runs. They **conjoin**. A second condition narrows the first
rather than replacing it:
-*)
+```fsharp
let conditional =
stage "release only" {
whenBranch "master"
whenNot { envVar "CI" } // master AND not CI
run "dotnet pack"
}
+```
-(**
`whenAll`, `whenAny` and `whenNot` are CEs that combine leaf conditions (`branch`, `branches`, `envVar`,
`platformWindows`, `platformLinux`, `platformOSX`, and a literal `when'`). An empty `whenAll { }` is active,
the identity of `forall`. An empty `whenAny { }` is not.
-*)
+```fsharp
let combined =
stage "publish" {
whenAny {
@@ -193,8 +133,8 @@ let combined =
}
run "dotnet nuget push"
}
+```
-(**
`when'` also accepts a whole `StageContext`. It runs for real, side effects and console output included, and
its success is the answer.
@@ -205,8 +145,8 @@ argument, `when' (not quick) "--quick is set"`, and `--explain` prints `(skipped
A stage that needs a CLI flag binds it in an `input` CE. It is then lifted into any command that asks for it,
with no further wiring:
-*)
+```fsharp
module Options =
let quick =
Input.option
+
## API reference
The [API reference](https://shayanhabibi.github.io/Partas.Build/reference/) is generated from the XML
documentation on each custom operation.
-*)
diff --git a/docs/content/extensions/shipit.md b/docs/content/extensions/shipit.md
index be1fa08..e12b0d6 100644
--- a/docs/content/extensions/shipit.md
+++ b/docs/content/extensions/shipit.md
@@ -1,5 +1,6 @@
---
title: EasyBuild.ShipIt
+description: Conventional-commit releases with changelogs and synchronized package versions.
category: Extensions
order: 1
---
@@ -8,7 +9,7 @@ order: 1
`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/).
+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](../Build/installation.md).
## Add the commands to your build
diff --git a/docs/content/external-annotations/external-annotations-api.fsx b/docs/content/external-annotations/external-annotations-api.md
similarity index 71%
rename from docs/content/external-annotations/external-annotations-api.fsx
rename to docs/content/external-annotations/external-annotations-api.md
index c4e4ba3..2ad59a0 100644
--- a/docs/content/external-annotations/external-annotations-api.fsx
+++ b/docs/content/external-annotations/external-annotations-api.md
@@ -1,64 +1,9 @@
-(**
---
title: F# surface
category: ExternalAnnotations
index: 2
---
-*)
-(*** hide ***)
-// Sources are #load-ed rather than #r-ing built DLLs so the guide type-checks against the code as written,
-// and so nothing holds a file lock while the site watcher is running. Keep this list in the same order
-// as the Define stages once. Compose them into commands. The inputs each stage reads become your CLI options, validation, and help.
+ +let build = input {
+ let! config = Input.option<string> "--configuration"
+ |> Input.def "Release"
+ return stage "compile" {
+ run (cmd $"dotnet build -c {config}")
+ }
+}
+
+let root = Command.root {
+ command "build" { build }
+}
+