Files
rdbms-playground/docs/handoff/20260615-handoff-70.md
T
claude@clouddev1 984bc30256 docs: record CI branch work — D1/D2 done, TT5 partial, handoff 70
requirements.md: D1 (all six cross-platform binaries) and D2 (no-runtime-
deps, per-platform) done; D3 noted (binaries shipped, package managers
pending); TT5 partial (gate + macOS test live; Windows build-only; Tier-4
unwired). CLAUDE.md: add the CI/release decision (-> docs/ci/adr) + update
the deferred list. Adds handoff 70 summarising the pipeline + follow-ups
(incl. the versioning gap).
2026-06-15 16:31:58 +00:00

5.8 KiB

Session handoff — 2026-06-15 (70)

Seventieth handover. A dedicated infrastructure session, run on a separate ci branch (in a worktree), that built the project's entire CI/CD pipeline on the self-hosted Gitea Actions runner — from nothing to a live gate plus a six-target cross-platform release. Net: the CI / requirements.md TT5 item and D1/D2 are now done; D3 and a couple of TT5 tails remain. Decisions are recorded in a new ADR namespace, docs/ci/adr/ (ADR-ci-001/002/003), kept separate from the main integer ADR sequence to avoid cross-branch number collisions (the same split the website branch uses — and it paid off: main independently took ADR-0049 this period, which would have collided).

§1. State at handoff

Branch: ci (worktree). main has been merged into ci (commit 138e766, clean — ci and main touched disjoint files) so the gate runs against current main before CI lands there. Working tree clean except the in-progress doc updates from this handoff. Pushes/promotion are the user's step.

Gate verified locally on the merged code: clippy -D warnings clean; cargo test 2488 passing / 0 failing / 1 ignored (the long-standing friendly doctest). main's features came in with their tests (2424 → 2488).

Pipeline (.gitea/workflows/):

  • build-ci-image.yaml — builds + pushes the CI image (node:22-bookworm-slim
    • single-user nix + the flake's devShell pre-warmed) to the Gitea registry. Triggers only on image-input changes (Dockerfile / flake / toolchain).
  • ci.yaml — the gate: clippy -D warnings + cargo test, branch pushes + PRs (docs-only changes skipped).
  • release.yaml — on a v* tag: testbuild matrix over the four non-macOS targets via cargo-zigbuild, upload to the Gitea release.
  • release-macos.yamlworkflow_dispatch (tag input) on the Tart Apple-Silicon runner (runs-on: macos): test → build both *-apple-darwin → de-nix libiconv + ad-hoc re-sign → upload.

Verified live this session: the 4-target release published 8 assets (binary + .sha256 each) for tag v.0.0.0-citest3; the macOS build was proven portable (system-only deps) + signed + launches on the runner.

§2. What was built (and the non-obvious bits)

  • Nix flake (ADR-ci-002, relocated from a would-be main ADR-0049): one pinned toolchain (1.95.0) for dev and CI; cargo-zigbuild + zig (Linux only) for the cross targets; apple-sdk on darwin.
  • Runner facts (ADR-ci-001): jobs run inside a container (ci-publiccatthehacker/ubuntu), so host nix is unreachable — hence the baked image. The Mac runner is host execution; its label is macos (:host in the registration is the act_runner backend, not part of the label).
  • Cross-compile (ADR-ci-003): cargo-zigbuild for the 4 non-macOS targets. Windows needs an empty libsynchronization.a stub (ci/winstub/, wired via .cargo/config.toml) — std links -lsynchronization, absent from rust-overlay's toolchain + zig's mingw, but forwarded by kernel32.
  • macOS (ADR-ci-003 amendment): built on real Apple hardware (Tart), so the SDK is fully licensed — no osxcross grey area. The darwin stdenv bakes a /nix/store libiconv path into the binary; the build rewrites it to /usr/lib/libiconv.2.dylib (install_name_tool) and re-signs ad-hoc (codesign -f -s -; install_name_tool invalidates the signature, arm64 refuses unsigned). A guard fails the build on any remaining /nix/store dep.
  • Cache hygiene (Mac): the runner wipes the workspace each run, so cargo target/ never accumulates; the persistent nix store is bounded by generation (record the devShell in a persistent profile, keep the 2 newest via nix-env --delete-generations +2, GC the rest). First sweep reclaimed a ~3.8 GB one-time backlog of build scaffolding (source + build-only deps, not re-installed toolchains).

§3. Immediate next steps (user)

  1. Push ci → the gate re-runs in CI (should be green; no image rebuild — the merge didn't touch the flake/Dockerfile).
  2. Promote: git checkout main && git merge ci — a fast-forward (ci already contains main) — then push main. CI goes live; release-macos becomes dispatchable (workflow_dispatch needs the default branch).
  3. First real release: tag v0.1.0 (auto-builds the 4 Linux/Windows assets), then dispatch release-macos for v0.1.0 with the Mac up (adds the 2 macOS assets) → a full 6-binary release.
  4. Cleanup: delete the v.0.0.0-citest* test tags + their releases.
  5. Runner-side: add min-free/max-free to the Mac's /etc/nix/nix.conf as a hands-off nix-store backstop.

§4. Known gaps / follow-ups

  • Versioning is not wired into the binary (flagged by the user). The release git tag is nowhere in the produced binary — there is no --version flag, no CARGO_PKG_VERSION use anywhere in src/, and the release workflows use the tag only for the release name + asset filenames (rdbms-playground-<tag>-<target>). Cargo.toml is a static version = "0.1.0", decoupled from the tag. So a v0.5.0 tag yields a …-v0.5.0-… asset whose binary knows nothing of "0.5.0". To fix later: add a --version flag, and inject the tag at build time (e.g. a build.rs reading a CI-provided env, or bumping Cargo.toml as part of tagging) so the binary and the release agree.
  • D3 packaging — Homebrew / Scoop / winget / cargo binstall manifests (asset naming is already binstall-friendly).
  • TT5 tails — Windows is build-only (no execution runner); Tier-4 PTY (TT4) is unwired in CI.
  • fmt gate — deliberately off (tree isn't stock-rustfmt-clean); revisit on main.
  • Website → Cloudflare deploy — the separate, simpler workflow, still to do.