Skip to content
zit Artifact [87871fcbdf]
Login

Artifact [87871fcbdf]

Artifact 87871fcbdf76a8ece6d1128f2f2bd6a31e29ff0f41ef5ac7c83575f3f005e330:


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