Release runner policy
Release binary runner labels are data, not workflow control flow. The source of
truth is .github/release-runner-policy.json; scripts/release_runner_matrix.sh
validates that document and resolves the matrix consumed by
build-release-binaries.yml.
Each target declares five labels:
warm: routine default-branch cache refreshes.primary: tag-push release builds on the product critical path.recovery: manual tag recovery when no override is requested.standard: an explicit standard-capacity recovery or benchmark override.fast: an explicit latency-prioritized recovery or benchmark override.
Primary and warm builds always use policy. Recovery accepts policy,
standard, or fast; the default is policy. The non-publishing benchmark
mode requires an explicit target subset and either standard or fast. It
compiles and runs the binary-size gate, but cannot sign, notarize, package,
upload, finalize a release, publish a container, or save a cache.
gh workflow run build-release-binaries.yml \
--ref <branch> \
-f benchmark_only=true \
-f runner_profile=fast \
-f targets=x86_64-apple-darwin
The policy is also the source of truth for metered runner rates, source URLs, and their effective date; the approximate costs below are projections from that data. GitHub rounds each job to a whole minute. See Actions runner pricing, the larger runner reference, and Blacksmith pricing.
Current decision#
Use macos-15-intel for policy-selected x86_64-apple-darwin builds and
macos-latest for native workspace certification by default. Keep the proven
Blacksmith M4 and GitHub xlarge profiles available only for explicit incident
or benchmark dispatches. Routine main pushes, scheduled cache refreshes,
certification, and shipping therefore stay on the public repository's free
standard capacity unless an owner opts into a paid profile.
The public repository uses GitHub-hosted release capacity by default. Set the
repository Actions variable HARN_RELEASE_ENABLE_BLACKSMITH_MACOS=true to opt
policy-selected primary and recovery Intel builds into Blacksmith. Explicit
standard and fast recovery or benchmark profiles still honor the operator's
selected profile. Set HARN_RELEASE_ENABLE_BLACKSMITH_LINUX=true to opt release
and benchmark CLI AOT preparation into Blacksmith; warm-cache runs use
ubuntu-latest regardless. Leave both variables unset unless a reviewed
release incident justifies paid capacity.
The primary and recovery choice is based on a same-source cold-cache pair.
Both runs used Harn source commit
34e00360c1f310b364b92dd2e4aeabeddde46528, the same target, AOT payload,
thin-LTO profile, and 16 codegen units. The branches differed only in runner
policy, and both reported Swatinem cache hit: false.
| Receipt | Runner | Cargo duration | Job duration | Cost |
|---|---|---|---|---|
| GitHub M2 benchmark | macos-15-xlarge | 10m01s | 10m25s | about $1.12 before credits |
| Blacksmith M4 benchmark | blacksmith-12vcpu-macos-15 | 5m30s | 5m53s | about $0.96 |
Blacksmith saved 4m31s of Cargo time, or 45.1%, and 4m32s of job wall time over the credit-eligible GitHub M2 recovery. More importantly, it cut 18m39s from the previously selected cache-hit Intel Large job. Harn published 60 v0.10.x releases in the 30 days ending 2026-08-09. At that unusually high cadence, the measured Blacksmith macOS job projects to about $58 per month. The 16-vCPU Blacksmith AOT job adds about $6 per month at the same cadence.
A second Blacksmith validation run
identified the cross-compiled output as an x86_64 Mach-O and executed
harn --version under Rosetta. The downloaded artifact independently passed
the same execution check, then passed ad-hoc signing, strict signature
verification, and another x86_64 execution on an Apple Silicon host.
CLI AOT preparation used to take 4m57s on standard Linux in the same benchmark cohort. A controlled 16-vCPU Blacksmith run finished that job in 2m26s. A GitHub 16-core trial was abandoned after five minutes without runner assignment, so it is not a production fallback. The measured AOT plus primary macOS job is about 8m19s before the sub-minute signing and notarization tail; this is a component-path estimate, not a completed release SLO claim.
Cache availability remains the larger lever. The v0.10.67 release missed its cache and spent 79m05s in Cargo on standard Intel. A warm standard runner cut that to 36m38s without paid capacity. The ARM runners complete cold builds faster than that warm Intel path, so primary release latency no longer depends on an x86 cache hit. Intel cache warms remain useful for the emergency standard fallback and retain the repository's existing storage budgets and pruning.
Compiler-cache backends#
Each target also declares sccache_backend next to use_sccache:
| Backend | Meaning |
|---|---|
sticky | Blacksmith sticky-disk SCCACHE_DIR. Hosted runners for the same target fall back to the bounded local blob cache. |
local | Bounded local SCCACHE_DIR restored/saved as one Actions cache blob. SCCACHE_GHA_ENABLED=false. |
install | Historical Linux install path through .github/actions/sccache-install. |
none | Explicit skip with a job-summary reason. |
The per-object GHA sccache backend stays off. Windows previously failed mid
harn-vm compile with os error 10054 (#2114), and the hosted per-object trial
spent 5.35 GiB for negligible hits (v0.10.39). Local blob persistence is the
next-best reusable boundary on hosted macOS ARM and Windows: restore once
before compile, save once after, never talk to the cache API during rustc.
Every Build job records cache mode, hit/miss statistics (or an explicit skip
reason), and Build-step wall time in the job summary. Warm and candidate modes
compare that Build-step duration to
.github/release-warm-build-budget.json, which ratchets from the measured
v0.10.65 fanout (run 31288092986).
Queue time and skipped targets do not count.
An earlier cold-cache benchmark saved only 55 seconds on Large. That result correctly blocked adoption at the time, but cold dependency compilation is not the intended steady-state Intel release path. The later cache-hit pair showed a 36.1% Intel Large advantage and justified the first paid default; the controlled ARM pair above supersedes it with a faster and cheaper primary.
Update this table and any primary label change only from an observed
workflow/job receipt. Force standard capacity if Blacksmith has two consecutive
runner/platform failures, if the primary job p95 exceeds 10 minutes over five
releases, or if projected release-runner spend exceeds $150 per month without a
matching release cadence. Do not infer a capacity win from runner
specifications alone.