ci(signing): owned Macs first for the release, repair and DEV signing jobs, with a stall-aware fallback
Leo, 2026-10-28, on letting the release signing jobs run on our own Macs while Blacksmith is starved: "ok. idk what the "risk" was before but like.. we can just read the code and stuff." The routing order is Linux first, then owned Macs, then Blacksmith macOS last.
What changed
release.ymlbuild-sign-notarize,repair-v0-64-25-helper-rpaths.ymlrepair andcmux-next-dev-daily.ymlsign each get apick-sign-runnerjob, like the nightly signing picker:- Linux Blacksmith, the routing environment,
actions: readandcontents: read,continue-on-error. - It runs
scripts/ci/signing_runner.py: a drained owned Mac on attempt 1 whilevars.CI_SIGN_OWNEDis1, else the Blacksmith macOS 26 label whose queue moves, and the other size for a re-run (stall-aware fallback). - The routing token is minted only on the refs the release environment allows (main,
rc/**,v*tags).
- Linux Blacksmith, the routing environment,
- Each signing job takes the pick:
github.run_attempt == 1 && <owned> && fromJSON(<owned>), then the Blacksmith pick, then a literal Blacksmith label. No raw repository variable names the signing runner. - Each signing job starts with the claim gate (before the checkout's token) and runs the claim script before any secret; its existing
if: always()keychain delete stays. tests/test_ci_signing_owned_mac.pyreads which picker output is the owned one, and fails a picker of an owned-routed job that could hold a secret on any ref.tests/test_ci_release_sdk_lane.shexpects the release job's new runs-on.
Before / after
- Before: the three keyed signing jobs sat on the literal
blacksmith-12vcpu-macos-26label, whatever its queue. - After: an idle owned Mac first (once
CI_SIGN_OWNED=1), else whichever Blacksmith macOS 26 size is moving; a re-run takes the other size.
Tests
Local: test_ci_signing_owned_mac.py, test_ci_blacksmith_linux_failover.py, test_ci_runs_on_fallback.py, test_ci_runs_on_values.py, test_runs_on_labels.py, test_supplychain_security.py, test_ci_check_repo_variables.py, test_cmux_next_dev_daily_dispatch.py, test_ci_release_sdk_lane.sh, test_repair_v06425_workflow.sh, actionlint.
Risk: medium. It changes where release signing runs. Owned Macs stay off until the variable is set; without it the jobs only move between Blacksmith sizes.
Agent session: agent session
š¤ Generated with Claude Code