docs: 0.10.0 release build runbook (Sam & Claude)
Step-by-step for cutting the release-channel operator image on the FreeBSD build host: sync clean merged heads (the gate requires it), build colibri + zot artifacts, run BUILD_CHANNEL=release ISO_VERSION=0.10.0, verify provenance in build-manifest.json, boot-proof via the acceptance runbook, and publish .xz. Version-parameterized so future cuts just bump ISO_VERSION. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
9a12702b4f
commit
e471988a6c
1 changed files with 210 additions and 0 deletions
210
docs/RELEASE-BUILD-RUNBOOK.md
Normal file
210
docs/RELEASE-BUILD-RUNBOOK.md
Normal file
|
|
@ -0,0 +1,210 @@
|
|||
# Release Build Runbook
|
||||
|
||||
**Current target:** `0.10.0` ("Operator Image") · **Channel:** `release`
|
||||
|
||||
How to cut a reproducible, publishable operator image from merged sources. This
|
||||
is the `BUILD_CHANNEL=release` path — distinct from the everyday
|
||||
`BUILD_CHANNEL=dev` integration build. Run it on the **FreeBSD 15 build host**;
|
||||
Linux can't produce the FreeBSD binaries.
|
||||
|
||||
For a throwaway integration image (current `main`, no clean-tree requirement),
|
||||
use `BUILD_CHANNEL=dev` and skip the pinning discipline below.
|
||||
|
||||
---
|
||||
|
||||
## 0. What a release build guarantees
|
||||
|
||||
- **Reproducible by record.** The release gate refuses to build unless every
|
||||
staged source repo (`clawdie-iso`, `clawdie-ai`, `colibri`, `zot`) is a clean,
|
||||
committed tree (`git status --porcelain` — untracked files count). The exact
|
||||
commits are then written to `build-manifest.json`, so the image can be rebuilt
|
||||
from that record.
|
||||
- **Own product version.** `ISO_VERSION` is an explicit product number
|
||||
(`0.10.0`), not a component's. Component versions are provenance, not identity.
|
||||
- **Fits the stick.** The build aborts before shipping if the live filesystem
|
||||
has less than `IMAGE_MIN_FREE_MB` (default 1024) free.
|
||||
|
||||
Output: `tmp/output/clawdie-quindecim-0.10.0.img` (`quindecim` = FreeBSD 15).
|
||||
|
||||
---
|
||||
|
||||
## 1. Host prerequisites
|
||||
|
||||
- FreeBSD 15 build host (root for the build; it mounts/loops the image).
|
||||
- Toolchains: **Rust** (`cargo`, `rustc`) for Colibri, **Go** for zot. See
|
||||
`REQUIREMENTS.md`.
|
||||
- Repos checked out **side by side** (the defaults assume `../colibri`, `../zot`,
|
||||
`../clawdie-ai` relative to `clawdie-iso`, or `/home/clawdie/ai/<repo>`):
|
||||
|
||||
```text
|
||||
<work>/clawdie-iso
|
||||
<work>/colibri
|
||||
<work>/zot
|
||||
<work>/clawdie-ai
|
||||
```
|
||||
|
||||
Report host evidence in the release notes:
|
||||
|
||||
```sh
|
||||
freebsd-version ; uname -a ; rustc --version ; cargo --version ; go version
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. Sync clean, merged heads
|
||||
|
||||
The gate requires every repo clean and on its intended commit. Do this for
|
||||
**all four** repos:
|
||||
|
||||
```sh
|
||||
for r in clawdie-iso colibri zot clawdie-ai; do
|
||||
git -C "../$r" fetch --prune origin
|
||||
git -C "../$r" switch main && git -C "../$r" pull --ff-only # or checkout the release ref
|
||||
git -C "../$r" status --porcelain # MUST be empty
|
||||
done
|
||||
```
|
||||
|
||||
Any output from `status --porcelain` (modified *or* untracked) will fail the
|
||||
release gate. Clean it before continuing — do not `.gitignore` your way past it.
|
||||
|
||||
> `zot` ships at a pinned tag. Check out the tag you intend to release
|
||||
> (`ZOT_VERSION`, default `v0.2.29`) so the recorded commit is the tag's commit.
|
||||
|
||||
---
|
||||
|
||||
## 3. Build the artifacts (the ISO stages, never compiles)
|
||||
|
||||
```sh
|
||||
# Colibri release binaries
|
||||
cd ../colibri
|
||||
cargo build --workspace --release
|
||||
cargo test --workspace # green before release
|
||||
cargo clippy --workspace --all-targets -- -D warnings
|
||||
|
||||
# zot agent binary (native FreeBSD build)
|
||||
cd ../zot
|
||||
git checkout v0.2.29 # the release tag
|
||||
go build -trimpath -o bin/zot ./cmd/zot
|
||||
|
||||
cd ../clawdie-iso
|
||||
```
|
||||
|
||||
`build.sh` preflight will hard-fail if any of these are missing:
|
||||
|
||||
```sh
|
||||
ls -l ../colibri/target/release/colibri-daemon \
|
||||
../colibri/target/release/colibri \
|
||||
../colibri/target/release/colibri-test-agent \
|
||||
../colibri/target/release/colibri-mcp \
|
||||
../zot/bin/zot
|
||||
# colibri-tui is optional (staged if present)
|
||||
```
|
||||
|
||||
> Building binaries does **not** dirty the repos (`target/` and `bin/zot` are
|
||||
> gitignored). If `git status --porcelain` is non-empty after building, something
|
||||
> else changed — investigate, don't suppress.
|
||||
|
||||
---
|
||||
|
||||
## 4. Run the release build
|
||||
|
||||
```sh
|
||||
cd ../clawdie-iso
|
||||
sudo env BUILD_CHANNEL=release ISO_VERSION=0.10.0 \
|
||||
./build.sh --clawdie-ref main
|
||||
```
|
||||
|
||||
- `ISO_VERSION=0.10.0` — also the `build.cfg` default; an empty/`auto` value
|
||||
fails fast.
|
||||
- `--clawdie-ref main` bundles current `clawdie-ai` main (its commit is recorded
|
||||
as provenance). Use `--clawdie-version X.Y.Z` instead to pin a clawdie-ai tag.
|
||||
The gate does **not** require a tag — a recorded commit is enough.
|
||||
- Defaults that matter: `FEATURE_COLIBRI=YES`, `COLIBRI_STAGE_AGENT=YES`,
|
||||
`COLIBRI_COST_MODE=smart`. Override only with reason.
|
||||
|
||||
What you should see, in order:
|
||||
|
||||
1. **Banner** — `ISO : 0.10.0-release (zot v0.2.29)`.
|
||||
2. **Release gate** — silent on success; on failure it lists each modified repo
|
||||
and exits. (Fix the tree; don't switch to `dev` for a real release.)
|
||||
3. **Preflight** — confirms the colibri binaries and `zot/bin/zot` exist.
|
||||
4. **Image space report** — `df`/`du` of the live filesystem, then
|
||||
`Free space OK (… MB, floor 1024 MB)` — or an abort if it won't fit.
|
||||
5. **Output** — `Done : tmp/output/clawdie-quindecim-0.10.0.img`.
|
||||
|
||||
---
|
||||
|
||||
## 5. Verify provenance
|
||||
|
||||
```sh
|
||||
cat tmp/output/build-manifest.json # or USB_SHARE copy
|
||||
```
|
||||
|
||||
Confirm:
|
||||
|
||||
- `"iso_version": "0.10.0"`, `"version_scheme": "product"`,
|
||||
`"build_channel": "release"`.
|
||||
- `zot_commit`, `colibri_commit`, `clawdie_ai_commit`, `iso_repo_commit` are all
|
||||
real SHAs (not `unknown`).
|
||||
- **Every** `*_modified` flag is `false` (`zot_modified`, `colibri_modified`,
|
||||
`clawdie_ai_modified`, `iso_repo_modified`). A `true` here on a release means a
|
||||
tree was modified — the gate should have caught it; investigate.
|
||||
|
||||
---
|
||||
|
||||
## 6. Boot proof (the actual acceptance)
|
||||
|
||||
Boot the image in bhyve or on hardware and run `docs/ISO-ACCEPTANCE-RUNBOOK.md`.
|
||||
Minimum pass set for the milestone:
|
||||
|
||||
```sh
|
||||
id colibri
|
||||
service colibri_daemon status # running, socket ready
|
||||
colibri status # paths, cost.mode=smart, scheduler
|
||||
colibri create-task --title "rc check"
|
||||
colibri list-tasks --status queued # contains "rc check"
|
||||
service colibri_daemon stop # socket + pidfiles cleaned up (SIGTERM path)
|
||||
service colibri_daemon start # restart works; no stale-socket clobber
|
||||
```
|
||||
|
||||
XFCE: confirm the desktop comes up and is usable (the milestone's headline).
|
||||
|
||||
If anything fails out of the box, this is not the cut — fix, rebuild, and the
|
||||
`rc1`→`rc2` style iteration is the version number doing its job.
|
||||
|
||||
---
|
||||
|
||||
## 7. Publish
|
||||
|
||||
Follow `skills/iso-publish/SKILL.md`: compress to `.xz`, write the `.sha256`, and
|
||||
the publish manifest, then `scripts/publish.sh` to the CMS downloads jail.
|
||||
`FLASHING.md` is the operator-facing flashing guide (already references the
|
||||
`0.10.0` artifact name).
|
||||
|
||||
---
|
||||
|
||||
## Acceptance checklist
|
||||
|
||||
- [ ] All four repos clean (`git status --porcelain` empty) and on the release ref.
|
||||
- [ ] `cargo test --workspace` + `cargo clippy -D warnings` green on colibri.
|
||||
- [ ] `BUILD_CHANNEL=release ISO_VERSION=0.10.0 ./build.sh` completes; gate passed,
|
||||
preflight passed, free-space check passed.
|
||||
- [ ] `build-manifest.json`: channel `release`, all commits real, all
|
||||
`*_modified` `false`.
|
||||
- [ ] Booted image: `colibri_daemon` start/status/task/stop/restart clean; XFCE usable.
|
||||
- [ ] Published `.xz` + `.sha256` + manifest; `FLASHING.md` accurate.
|
||||
|
||||
---
|
||||
|
||||
## Notes / gotchas
|
||||
|
||||
- **Future cuts:** bump `ISO_VERSION` in `build.cfg` (e.g. `0.10.1`, `1.0.0`).
|
||||
Everything else here is unchanged.
|
||||
- **`dev` vs `release`:** `dev` skips the clean-tree gate — fine for proving a
|
||||
change, never for a published artifact.
|
||||
- **Live field repair:** to rebuild Colibri on an already-booted USB without a
|
||||
full image rebuild, use `colibri-live-rebuild` (see `docs/LIVE-COLIBRI-REBUILD.md`).
|
||||
That is for validation, not release artifacts.
|
||||
- **`BUILD_CHANNEL` is not the package channel.** It marks artifact provenance;
|
||||
the future poudriere pkg repo's channel (latest/quarterly/signed) is a separate
|
||||
axis — don't conflate them.
|
||||
Loading…
Add table
Reference in a new issue