Artifact 87871fcbdf76a8ece6d1128f2f2bd6a31e29ff0f41ef5ac7c83575f3f005e330:
- File
.github/workflows/ci.yml
— part of check-in
[c8cccb2723]
at
2026-07-19 00:29:49
on branch trunk
— CI: target the self-hosted macOS runner instead of a hosted Linux one
GitHub-hosted runners are unavailable to this repository: it is private, and private-repo Actions minutes are billed, so the first hosted run never started — 'recent account payments have failed or your spending limit needs to be increased', zero steps executed. The gate now runs on the self-hosted mac-mini-zit (macOS/ARM64), which is online and already carries the toolchain.
- runs-on names the specific machine ([self-hosted, mac-mini-zit]) rather than bare self-hosted, so a second runner joining the account cannot silently pick this job up on a different OS or architecture. - The Zig tarball is the aarch64-macos build with its published digest from ziglang.org/download/index.json. macOS ships shasum rather than GNU sha256sum, so the digest is compared explicitly; a swapped tarball still fails the job rather than building silently. - fossil is verified rather than apt-installed — the runner is a developer machine carrying 2.28, newer than what apt ships. The step hard-fails when fossil is absent, because a skipped smoke step would silently stop exercising the conformance claim the release rests on.
src/ci_test.zig moves in lockstep: the runs-on line, the digest constant, the digest-check form, and the fossil-guard pin all now assert the macOS shape. Pins and workflow must change together or zig build test goes red, which is the point of having them. (user: dmestas, size: 5542) [annotate] [blame] [check-ins using]
name: ci # Every push on every branch, plus pull requests. Deliberately unfiltered: the # 0.1.0 release is developed on `release-0.1`, and a default-branch-only gate # would leave the entire release unverified until the merge that is supposed to # be the safe part. on: push: pull_request: # Least privilege: the battery only reads the checkout. Without an explicit # block the job inherits whatever the repo/org default grants, which is # read/write on many configurations. permissions: contents: read # Unfiltered `push:` plus `pull_request:` means a PR branch runs the whole # battery twice per push. Superseded runs are cancelled rather than left to # finish against a commit nobody is waiting on. concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true # One gating job. A macOS leg is 0.2 material; splitting the battery across # several jobs would read as broader coverage than it is. jobs: battery: # Self-hosted (mac-mini-zit, macOS/ARM64). GitHub-hosted runners are not # available to this repository: it is private, and private-repo Actions # minutes are billed, so the first hosted run never started ("recent account # payments have failed or your spending limit needs to be increased"). The # label set is narrowed to the specific machine rather than bare # `self-hosted` so a second runner joining the account cannot silently pick # up this job on a different OS or architecture. runs-on: [self-hosted, mac-mini-zit] # An explicit ceiling, per the bounded-waits rule: every wait needs an # interval and a timeout. Without this the job inherits GitHub's 360-minute # default, so a hang — most plausibly smoke's spawned server never exiting — # turns a red gate into a six-hour silent stall instead of a failure. timeout-minutes: 20 env: # Kept in lockstep with src/ci_test.zig's `pinned_zig_version` and # `pinned_zig_shasum`, which fail `zig build test` if this file drifts. # The digest is the published one from ziglang.org/download/index.json, # so a swapped tarball is a build failure rather than a silent event. ZIG_VERSION: 0.16.0 # aarch64-macos, matching the self-hosted runner. Published digest from # ziglang.org/download/index.json. ZIG_SHASUM: b23d70deaa879b5c2d486ed3316f7eaa53e84acf6fc9cc747de152450d401489 steps: - uses: actions/checkout@v4 # smoke drives the real fossil binary — it is the only step that proves # the conformance claim against the reference implementation rather than # against our own reading of the RFCs. The runner's fossil is whatever # apt ships and will lag the local 2.28, so print it: the release notes # must name the exact version smoke passed against (readiness item S7). - name: Verify fossil run: | set -euo pipefail command -v fossil >/dev/null 2>&1 || { echo "fossil is not installed on this runner; smoke cannot run." >&2 echo "install it with: brew install fossil" >&2 exit 1 } fossil version # Installed by hand rather than through a setup action: the toolchain is # one tarball, the URL is stable, and verifying the published digest here # is both simpler and stronger than trusting a third-party action to pin # the same thing. - name: Install Zig ${{ env.ZIG_VERSION }} run: | set -euo pipefail tarball="zig-aarch64-macos-${ZIG_VERSION}.tar.xz" curl -fsSL -o "$tarball" "https://ziglang.org/download/${ZIG_VERSION}/${tarball}" # macOS ships `shasum`, not GNU `sha256sum`, so the digest is compared # explicitly rather than through `--check --strict`. Same guarantee: # a swapped tarball fails the job instead of building silently. actual="$(shasum -a 256 "$tarball" | awk '{print $1}')" if [ "$actual" != "${ZIG_SHASUM}" ]; then echo "zig tarball digest mismatch: expected ${ZIG_SHASUM}, got ${actual}" >&2 exit 1 fi tar -xf "$tarball" echo "${GITHUB_WORKSPACE}/zig-aarch64-macos-${ZIG_VERSION}" >> "$GITHUB_PATH" - name: Zig version run: zig version # `--check build.zig src` rather than `--check .`: the bare dot walks # .zig-cache/ and zig-out/, whose generated sources are not ours to # format. Naming the source roots keeps the check meaning the same thing # on a cold runner and in a warm local tree. - name: Format check run: zig fmt --check build.zig src - name: Build run: zig build # The battery runs each step explicitly. Local semantics are deliberately # unchanged: e2e staying compile-only under `zig build test` is a good # inner-loop design, so CI names the steps rather than the build graph # being rewired to fold them in. - name: Unit tests run: zig build test - name: End-to-end tests run: zig build e2e - name: Deterministic simulation run: zig build dst # The tightest per-step bound in the battery, and deliberately so: smoke # spawns a server, which is the one step that can hang without producing # output. The job ceiling would eventually catch it; this catches it while # the log still reads as a failed step rather than a dead run. - name: Fossil interop smoke timeout-minutes: 5 run: zig build smoke