Builds & Tests¶
How artifacts are produced and gated: container images, binaries, and container-run
commands (docs generators, static-site builds), the cache that speeds them up, and the tests
that gate them. Builds are referenced by targets via build:.
Every build has a unique id that targets reference, and a kind that decides how
it is produced:
kind |
Produces |
|---|---|
docker |
A container image via docker buildx (single- or multi-platform). |
binary |
A compiled binary via a language builder (e.g. go). |
command |
Whatever a command emits in a container — a generated docs tree, a built static site — captured as a declared output. |
builds:
- id: myapp
kind: docker
platforms: [linux/amd64, linux/arm64]
dockerfile: "Dockerfile"
context: "."
build_args:
GO_VERSION: "1.25"
Crucible mode¶
build_mode: crucible performs a self-proving rebuild — the image is built twice and its
layers are compared to verify reproducibility.
Build cache¶
The cache: block controls incremental-build invalidation. With auto_detect on (the
default), StageFreight watches lockfiles and invalidates the dependent layers when they
change; watch lets you declare additional path→layer rules.
builds:
- id: myapp
kind: docker
cache:
auto_detect: true
watch:
- paths: ["go.sum"]
invalidates: ["COPY go.* ./", "RUN go mod download"]
Build strategy selection¶
For docker builds, the strategy is chosen automatically from the platforms and the
targets that consume the build:
| Condition | Strategy | Behavior |
|---|---|---|
--local flag |
local | --load into the daemon, no push |
| Single platform + registries | load + push | --load, then docker push each tag |
| Multi-platform + registries | multi-platform push | --push directly (buildx can't --load multi-arch) |
| No registries | local | --load, default tag stagefreight:dev |
This is why single-platform images exist both locally and remotely (so local and remote retention work), while multi-platform images are push-only.
Reference¶
The blocks below are generated per kind (docker, binary, command) — exactly the
fields each accepts.
builds¶
Named build artifacts. Each build has a unique ID referenced by targets. Currently supports kind: docker.
kind: docker¶
builds:
- id: <string> # ID is the unique identifier for this build, referenced by targets. · required
kind: docker # Kind is the build type. Determines which fields are valid. Supported: "docker", "binary"… · one of: binary, command, docker · required
dockerfile: <string> # Dockerfile is the path to the Dockerfile. Default: auto-detect.
context: <string> # Context is the Docker build context path. Default: "." (repo root).
target: <string> # Target is the --target stage name for multi-stage builds.
platforms: [<string>] # Platforms lists the target platforms. Default: [linux/{current_arch}].
build_args: {} # BuildArgs are key-value pairs passed as --build-arg. Supports templates.
kind: binary¶
builds:
- id: <string> # ID is the unique identifier for this build, referenced by targets. · required
kind: binary # Kind is the build type. Determines which fields are valid. Supported: "docker", "binary"… · one of: binary, command, docker · required
builder: <string> # Builder is the toolchain that interprets the build. Supported: "go". Future: "rust", "zig", "cargo". · one of: android, c, dotnet, elixir, go, jvm, node, python, rust
from: <string> # From is the source/input root or entry point. e.g., "./src/cli" (Go package), "./src/main.rs"…
output: <string> # Output is the artifact name. Windows platforms auto-append ".exe". Default: basename of From.
args: [<string>] # Args are ordered raw arguments passed directly to the selected builder. For Go: raw args to "go…
env: {} # Env are build environment variables. e.g., {"CGO_ENABLED": "0"}
platforms: [<string>] # Platforms lists the target platforms. Default: [linux/{current_arch}].
kind: command¶
builds:
- id: <string> # ID is the unique identifier for this build, referenced by targets. · required
kind: command # Kind is the build type. Determines which fields are valid. Supported: "docker", "binary"… · one of: binary, command, docker · required
image: <string> # Image is the container image a containerized build (builder: node, elixir) runs inside (with the…
command: <string> # Command is the builder subcommand (binary: e.g. "build") or the full command (kind: command).…
env: {} # Env are build environment variables. e.g., {"CGO_ENABLED": "0"}
stage: # Stage recycles a binary build's output into this docker build's context before buildx, so a…
from: <string> # required
as: <string> # required
outputs: # Outputs declares what the command produced and each output's artifact class.
- type: <string> # one of: binary, file, tree · required
source: <string> # required
worktree: {}
Build IDs must be unique across all builds. Targets reference builds by name via the
build:field.
build_cache¶
BuildCache defines the build cache subsystem (local, shared, hybrid).
build_cache:
preset: <string>
mode: <string> # Mode selects which cache planes are active. "": inactive — no cache flags emitted, no cleanup…
builder: # Builder configures the buildx builder lifecycle. The engine owns creation, bootstrap, and narration…
backend: <string> # Backend pins the build backend. Default: "" (auto-detect). "buildkitd" → prefer persistent…
name: <string> # Name is the buildx builder name. Default: "sf-builder".
driver: <string> # Driver is the buildx driver. Default: "docker-container".
context: <string> # Context is the Docker context name for the builder endpoint. Default: "sf-context".
local: # Local configures the bounded local buildkit cache.
path: <string> # override local cache root (default: /stagefreight/cache/buildkit)
retention:
max_age: <string> # e.g. "7d"
max_size: <string> # e.g. "15GB"
external: # External configures registry-backed shared cache.
target: <string> # Target references a targets[].id with kind: registry.
path: <string> # Path is appended to the target URL: <target-url>/<path>/<repo>/<branch>.
fallback: <string> # Fallback is the read-only fallback branch ref (e.g. "default", "main"). Never written to unless…
mode: <string> # Mode is the BuildKit cache mode (e.g. "max", "min"). Default: "max".
retention: # Retention defines when stale external cache refs are pruned.
max_refs: <int> # max branch cache refs per repo
stale_age: <string> # prune refs for dead/merged branches
cleanup: # Cleanup is governance-owned host-hygiene policy — see HostCleanupConfig.
enabled: false # Enabled controls whether cleanup runs. Independent of cache mode.
enforcement: <string> # Enforcement controls what happens when cleanup cannot execute. best_effort: continue + structured…
protect: # Protect defines what is never pruned.
images:
refs: [<string>] # glob patterns
volumes:
named: false # protect all named volumes
prune: # Prune defines what is eligible for removal.
images:
dangling:
older_than: <string> # e.g. "72h"
unreferenced:
older_than: <string> # e.g. "72h"
build_cache:
older_than: <string> # e.g. "72h"
keep_storage: <string> # e.g. "20GB"
containers:
exited:
older_than: <string> # e.g. "72h"
networks:
unused: false
test¶
test:
preset: <string>
enabled: false # required
auto: false # nil ⇒ true
suites:
- id: <string> # required
tool: <string> # required
gate: <string> # default: perform
from: <string> # module/crate dir when not at repo root (e.g. dd-ui's api/)
args: [<string>] # raw passthrough escape hatch
command: <string>
packages: [<string>] # ── Go (native `go test` flag projections)…
tags: [<string>] # -tags a,b
run: <string> # -run <regex>
timeout: <string> # -timeout <d>
race: false # -race
coverage: false # -coverprofile
coverage_min: <value> # gate: fail the suite if statement coverage < this %
workspace: false # ── Rust (native `cargo test` flag projections)…
features: [<string>] # --features a,b
tests: [<string>] # --test <name>
release: false # --release
nextest: false # cargo nextest run