From 63e8f17789b0fc2ce62411066f1004ddb497ca10 Mon Sep 17 00:00:00 2001 From: lawrencecchen <54008264+lawrencecchen@users.noreply.github.com> Date: Sat, 30 May 2026 03:15:56 -0700 Subject: [PATCH 1/4] Use Blacksmith as macOS CI default --- .github/actionlint.yaml | 2 -- .github/workflows/build-ghosttykit.yml | 2 +- .github/workflows/ci-macos-compat.yml | 4 ++-- .github/workflows/ci.yml | 8 ++++---- .github/workflows/nightly.yml | 2 +- .github/workflows/perf-activation.yml | 10 ++++------ .github/workflows/release.yml | 2 +- .github/workflows/test-depot.yml | 2 +- .github/workflows/test-e2e.yml | 18 ++++++++---------- .github/workflows/tmux-corpus.yml | 2 +- docs/macos-ci-runners.md | 16 +++++++--------- tests/test_ci_self_hosted_guard.sh | 12 ++++++------ 12 files changed, 36 insertions(+), 44 deletions(-) diff --git a/.github/actionlint.yaml b/.github/actionlint.yaml index 173d405a72..6cf888054f 100644 --- a/.github/actionlint.yaml +++ b/.github/actionlint.yaml @@ -6,7 +6,5 @@ self-hosted-runner: - blacksmith-6vcpu-macos-15 - blacksmith-6vcpu-macos-26 - blacksmith-6vcpu-macos-latest - - warp-macos-15-arm64-6x - - warp-macos-26-arm64-6x - depot-macos-latest - depot-macos-14 diff --git a/.github/workflows/build-ghosttykit.yml b/.github/workflows/build-ghosttykit.yml index 1140c63d97..5b8450bef7 100644 --- a/.github/workflows/build-ghosttykit.yml +++ b/.github/workflows/build-ghosttykit.yml @@ -9,7 +9,7 @@ concurrency: jobs: build-ghosttykit: - runs-on: ${{ vars.MACOS_RUNNER_15 || 'warp-macos-15-arm64-6x' }} + runs-on: ${{ vars.MACOS_RUNNER_15 || 'blacksmith-6vcpu-macos-15' }} timeout-minutes: 20 env: GHOSTTYKIT_CRASH_REPORT_SUBDIR: cmux/crash diff --git a/.github/workflows/ci-macos-compat.yml b/.github/workflows/ci-macos-compat.yml index 1045f02f63..226f8b9bf9 100644 --- a/.github/workflows/ci-macos-compat.yml +++ b/.github/workflows/ci-macos-compat.yml @@ -9,12 +9,12 @@ jobs: fail-fast: false matrix: include: - - os: ${{ vars.MACOS_RUNNER_15 || 'warp-macos-15-arm64-6x' }} + - os: ${{ vars.MACOS_RUNNER_15 || 'blacksmith-6vcpu-macos-15' }} timeout: 30 startup_smoke: true virtual_display: true skip_zig: false - - os: ${{ vars.MACOS_RUNNER_26 || 'warp-macos-26-arm64-6x' }} + - os: ${{ vars.MACOS_RUNNER_26 || 'blacksmith-6vcpu-macos-26' }} timeout: 30 startup_smoke: true virtual_display: false diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5ee48bf4c7..4c34e6b15e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -167,7 +167,7 @@ jobs: bun test tests/vm-db-read-model.test.ts tests: - runs-on: ${{ vars.MACOS_RUNNER_15 || 'warp-macos-15-arm64-6x' }} + runs-on: ${{ vars.MACOS_RUNNER_15 || 'blacksmith-6vcpu-macos-15' }} timeout-minutes: 75 env: CMUX_SKIP_ZIG_BUILD: "1" @@ -395,7 +395,7 @@ jobs: # Keep lag validation separate from UI regressions so functional UI failures # and performance regressions stay isolated. Broader interactive UI suites # still run via test-e2e.yml on GitHub-hosted runners. - runs-on: ${{ vars.MACOS_RUNNER_15 || 'warp-macos-15-arm64-6x' }} + runs-on: ${{ vars.MACOS_RUNNER_15 || 'blacksmith-6vcpu-macos-15' }} # A cold DerivedData cache (any project.pbxproj or Package.resolved change # mints a new cache key with no restore-keys fallback) forces a full # cmux build whose Swift codegen alone runs ~18-20 min, so 20 was right at @@ -599,7 +599,7 @@ jobs: # Keep this on macOS 15 until Zig can link the real universal Ghostty # CLI helper on macOS 26 runners. The macOS 26 compatibility job still # covers the app build path with CMUX_SKIP_ZIG_BUILD=1. - runs-on: ${{ vars.MACOS_RUNNER_15 || 'warp-macos-15-arm64-6x' }} + runs-on: ${{ vars.MACOS_RUNNER_15 || 'blacksmith-6vcpu-macos-15' }} timeout-minutes: 20 steps: - name: Checkout @@ -703,7 +703,7 @@ jobs: lipo "$HELPER_BINARY" -verify_arch arm64 x86_64 ui-regressions: - runs-on: ${{ vars.MACOS_RUNNER_15 || 'warp-macos-15-arm64-6x' }} + runs-on: ${{ vars.MACOS_RUNNER_15 || 'blacksmith-6vcpu-macos-15' }} # Cold builds after project/package changes can spend more than 25 minutes # in build-for-testing before the UI regression script starts. timeout-minutes: 45 diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index ec931143cb..34fd8aff6c 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -100,7 +100,7 @@ jobs: build-sign-notarize-nightly: needs: decide if: needs.decide.outputs.should_build == 'true' - runs-on: ${{ vars.MACOS_RUNNER_26 || 'warp-macos-26-arm64-6x' }} + runs-on: ${{ vars.MACOS_RUNNER_26 || 'blacksmith-6vcpu-macos-26' }} timeout-minutes: 20 steps: - name: Checkout build ref diff --git a/.github/workflows/perf-activation.yml b/.github/workflows/perf-activation.yml index ee42c9c899..2adb753bb0 100644 --- a/.github/workflows/perf-activation.yml +++ b/.github/workflows/perf-activation.yml @@ -9,7 +9,7 @@ on: required: false default: "" runner: - description: macOS runner (auto follows the MACOS_RUNNER_15 repo variable, then warp) + description: macOS runner (auto follows the MACOS_RUNNER_15 repo variable, then Blacksmith) required: false default: auto type: choice @@ -18,8 +18,6 @@ on: - blacksmith-6vcpu-macos-15 - blacksmith-6vcpu-macos-26 - blacksmith-6vcpu-macos-latest - - warp-macos-15-arm64-6x - - warp-macos-26-arm64-6x workspace_count: description: Fixture workspace count required: false @@ -39,7 +37,7 @@ concurrency: jobs: activation-session: - runs-on: ${{ (!inputs.runner || inputs.runner == 'auto') && (vars.MACOS_RUNNER_15 || 'warp-macos-15-arm64-6x') || inputs.runner }} + runs-on: ${{ (!inputs.runner || inputs.runner == 'auto') && (vars.MACOS_RUNNER_15 || 'blacksmith-6vcpu-macos-15') || inputs.runner }} timeout-minutes: 45 env: PERF_TAG: perfci @@ -94,8 +92,8 @@ jobs: uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: path: .ci-source-packages - key: spm-${{ (!inputs.runner || inputs.runner == 'auto') && (vars.MACOS_RUNNER_15 || 'warp-macos-15-arm64-6x') || inputs.runner }}-${{ hashFiles('cmux.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved') }} - restore-keys: spm-${{ (!inputs.runner || inputs.runner == 'auto') && (vars.MACOS_RUNNER_15 || 'warp-macos-15-arm64-6x') || inputs.runner }}- + key: spm-${{ (!inputs.runner || inputs.runner == 'auto') && (vars.MACOS_RUNNER_15 || 'blacksmith-6vcpu-macos-15') || inputs.runner }}-${{ hashFiles('cmux.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved') }} + restore-keys: spm-${{ (!inputs.runner || inputs.runner == 'auto') && (vars.MACOS_RUNNER_15 || 'blacksmith-6vcpu-macos-15') || inputs.runner }}- - name: Resolve Swift packages run: | diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 56acd94f0b..0edb2edcda 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -16,7 +16,7 @@ env: jobs: build-sign-notarize: - runs-on: ${{ vars.MACOS_RUNNER_26 || 'warp-macos-26-arm64-6x' }} + runs-on: ${{ vars.MACOS_RUNNER_26 || 'blacksmith-6vcpu-macos-26' }} timeout-minutes: 20 steps: - name: Checkout diff --git a/.github/workflows/test-depot.yml b/.github/workflows/test-depot.yml index c3b1740d32..7094762807 100644 --- a/.github/workflows/test-depot.yml +++ b/.github/workflows/test-depot.yml @@ -28,7 +28,7 @@ on: jobs: tests: - runs-on: ${{ vars.MACOS_RUNNER_15 || 'warp-macos-15-arm64-6x' }} + runs-on: ${{ vars.MACOS_RUNNER_15 || 'blacksmith-6vcpu-macos-15' }} timeout-minutes: 20 steps: - name: Checkout diff --git a/.github/workflows/test-e2e.yml b/.github/workflows/test-e2e.yml index 5974dcfda6..61f32d5a62 100644 --- a/.github/workflows/test-e2e.yml +++ b/.github/workflows/test-e2e.yml @@ -1,5 +1,5 @@ name: E2E test with video recording -run-name: ${{ inputs.test_filter }} on ${{ (!inputs.runner || inputs.runner == 'auto') && (vars.MACOS_RUNNER_15 || 'warp-macos-15-arm64-6x') || inputs.runner }} @ ${{ inputs.ref || github.ref_name }} +run-name: ${{ inputs.test_filter }} on ${{ (!inputs.runner || inputs.runner == 'auto') && (vars.MACOS_RUNNER_15 || 'blacksmith-6vcpu-macos-15') || inputs.runner }} @ ${{ inputs.ref || github.ref_name }} on: workflow_dispatch: @@ -21,7 +21,7 @@ on: default: true type: boolean runner: - description: "Runner OS (auto follows the MACOS_RUNNER_15 repo variable, then warp; pick depot-macos-* for GUI activation)" + description: "Runner OS (auto follows the MACOS_RUNNER_15 repo variable, then Blacksmith; pick depot-macos-* for GUI activation)" required: false default: "auto" type: choice @@ -30,26 +30,24 @@ on: - blacksmith-6vcpu-macos-15 - blacksmith-6vcpu-macos-26 - blacksmith-6vcpu-macos-latest - - warp-macos-15-arm64-6x - - warp-macos-26-arm64-6x - depot-macos-latest - depot-macos-14 concurrency: - group: e2e-${{ (!inputs.runner || inputs.runner == 'auto') && (vars.MACOS_RUNNER_15 || 'warp-macos-15-arm64-6x') || inputs.runner }}-${{ inputs.ref || github.ref_name }}-${{ inputs.test_filter }} + group: e2e-${{ (!inputs.runner || inputs.runner == 'auto') && (vars.MACOS_RUNNER_15 || 'blacksmith-6vcpu-macos-15') || inputs.runner }}-${{ inputs.ref || github.ref_name }}-${{ inputs.test_filter }} cancel-in-progress: true jobs: e2e: - runs-on: ${{ (!inputs.runner || inputs.runner == 'auto') && (vars.MACOS_RUNNER_15 || 'warp-macos-15-arm64-6x') || inputs.runner }} + runs-on: ${{ (!inputs.runner || inputs.runner == 'auto') && (vars.MACOS_RUNNER_15 || 'blacksmith-6vcpu-macos-15') || inputs.runner }} timeout-minutes: 20 env: TEST_REF: ${{ inputs.ref || github.ref }} steps: - name: Validate Depot runner identity - if: ${{ startsWith((!inputs.runner || inputs.runner == 'auto') && (vars.MACOS_RUNNER_15 || 'warp-macos-15-arm64-6x') || inputs.runner, 'depot-macos-') }} + if: ${{ startsWith((!inputs.runner || inputs.runner == 'auto') && (vars.MACOS_RUNNER_15 || 'blacksmith-6vcpu-macos-15') || inputs.runner, 'depot-macos-') }} env: - REQUESTED_RUNNER: ${{ (!inputs.runner || inputs.runner == 'auto') && (vars.MACOS_RUNNER_15 || 'warp-macos-15-arm64-6x') || inputs.runner }} + REQUESTED_RUNNER: ${{ (!inputs.runner || inputs.runner == 'auto') && (vars.MACOS_RUNNER_15 || 'blacksmith-6vcpu-macos-15') || inputs.runner }} RUNNER_CONTEXT_NAME: ${{ runner.name }} run: | set -euo pipefail @@ -232,8 +230,8 @@ jobs: uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: path: .ci-source-packages - key: spm-${{ (!inputs.runner || inputs.runner == 'auto') && (vars.MACOS_RUNNER_15 || 'warp-macos-15-arm64-6x') || inputs.runner }}-${{ hashFiles('cmux.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved') }} - restore-keys: spm-${{ (!inputs.runner || inputs.runner == 'auto') && (vars.MACOS_RUNNER_15 || 'warp-macos-15-arm64-6x') || inputs.runner }}- + key: spm-${{ (!inputs.runner || inputs.runner == 'auto') && (vars.MACOS_RUNNER_15 || 'blacksmith-6vcpu-macos-15') || inputs.runner }}-${{ hashFiles('cmux.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved') }} + restore-keys: spm-${{ (!inputs.runner || inputs.runner == 'auto') && (vars.MACOS_RUNNER_15 || 'blacksmith-6vcpu-macos-15') || inputs.runner }}- - name: Resolve Swift packages run: | diff --git a/.github/workflows/tmux-corpus.yml b/.github/workflows/tmux-corpus.yml index 736efa583b..7d67466110 100644 --- a/.github/workflows/tmux-corpus.yml +++ b/.github/workflows/tmux-corpus.yml @@ -57,7 +57,7 @@ jobs: terminal-nightly: if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' - runs-on: ${{ vars.MACOS_RUNNER_15 || 'warp-macos-15-arm64-6x' }} + runs-on: ${{ vars.MACOS_RUNNER_15 || 'blacksmith-6vcpu-macos-15' }} timeout-minutes: 30 steps: - name: Checkout diff --git a/docs/macos-ci-runners.md b/docs/macos-ci-runners.md index b219e5124f..c13e69fddd 100644 --- a/docs/macos-ci-runners.md +++ b/docs/macos-ci-runners.md @@ -3,13 +3,13 @@ All paid macOS CI/CD jobs pick their runner from two repository variables instead of a hardcoded label: - `MACOS_RUNNER_15` for macOS 15 jobs (most jobs, plus the e2e/perf defaults) -- `MACOS_RUNNER_26` for macOS 26 jobs (release, nightly, the `release-build` job, compat) +- `MACOS_RUNNER_26` for macOS 26 jobs (release, nightly, compat) -Workflows reference them as `runs-on: ${{ vars.MACOS_RUNNER_15 || 'warp-macos-15-arm64-6x' }}`. If a variable is unset, the job falls back to WarpBuild, so CI is never broken by a missing variable. +Workflows reference them as `runs-on: ${{ vars.MACOS_RUNNER_15 || 'blacksmith-6vcpu-macos-15' }}`. If a variable is unset, the job still uses Blacksmith. -## Switch Blacksmith <-> WarpBuild +## Blacksmith defaults -The switch is a repo-variable change. It takes effect on the next workflow run, with no PR or commit. +The defaults are checked into the workflows. The repo variables are an override layer and take effect on the next workflow run, with no PR or commit. Use Blacksmith (default): @@ -18,15 +18,13 @@ gh variable set MACOS_RUNNER_15 --repo manaflow-ai/cmux -b blacksmith-6vcpu-maco gh variable set MACOS_RUNNER_26 --repo manaflow-ai/cmux -b blacksmith-6vcpu-macos-26 ``` -Fall back to WarpBuild (e.g. Blacksmith macOS capacity is queuing, as happened in https://github.com/manaflow-ai/cmux/pull/4926): +Remove the override and use the checked-in Blacksmith defaults: ```bash gh variable delete MACOS_RUNNER_15 --repo manaflow-ai/cmux gh variable delete MACOS_RUNNER_26 --repo manaflow-ai/cmux ``` -Deleting the variables reverts to the WarpBuild fallback baked into the workflows. You can also set them explicitly to `warp-macos-15-arm64-6x` / `warp-macos-26-arm64-6x`. - Check current values: ```bash @@ -35,8 +33,8 @@ gh variable list --repo manaflow-ai/cmux ## Manual runs -`perf-activation.yml` and `test-e2e.yml` keep a `runner` choice input that defaults to `auto`. `auto` (and the empty `pull_request` case for perf) follows `MACOS_RUNNER_15` then the Warp fallback, so flipping the repo variable also redirects these workflows. An explicit choice wins over the variable; both dropdowns expose `warp-macos-15-arm64-6x` / `warp-macos-26-arm64-6x` so an operator can pick Warp directly during a Blacksmith outage. `test-e2e.yml` also keeps `depot-macos-*` choices and a Depot identity guard for GUI-activation runs. +`perf-activation.yml` and `test-e2e.yml` keep a `runner` choice input that defaults to `auto`. `auto` (and the empty `pull_request` case for perf) follows `MACOS_RUNNER_15` then the checked-in Blacksmith default, so flipping the repo variable also redirects these workflows. An explicit choice wins over the variable. `test-e2e.yml` also keeps `depot-macos-*` choices and a Depot identity guard for GUI-activation runs. ## Guard -`tests/test_ci_self_hosted_guard.sh` (run by the `workflow-guard-tests` job) asserts every paid macOS job references `vars.MACOS_RUNNER_*` or a Blacksmith/Warp label, so a job can never silently fall back to a free GitHub-hosted runner. Keep new labels in `.github/actionlint.yaml`. +`tests/test_ci_self_hosted_guard.sh` (run by the `workflow-guard-tests` job) asserts every paid macOS job references `vars.MACOS_RUNNER_*` or a Blacksmith label, so a job can never silently fall back to a free GitHub-hosted runner. Keep new labels in `.github/actionlint.yaml`. diff --git a/tests/test_ci_self_hosted_guard.sh b/tests/test_ci_self_hosted_guard.sh index be15cc229d..0191846504 100755 --- a/tests/test_ci_self_hosted_guard.sh +++ b/tests/test_ci_self_hosted_guard.sh @@ -1,8 +1,8 @@ #!/usr/bin/env bash # Regression test for https://github.com/manaflow-ai/cmux/issues/385. -# Ensures paid CI jobs use a paid macOS runner (Blacksmith or WarpBuild, routed +# Ensures paid CI jobs use a paid macOS runner (Blacksmith, routed # through the MACOS_RUNNER_15 / MACOS_RUNNER_26 repo variables), never a free -# GitHub-hosted runner. Flip Blacksmith<->Warp by editing those repo variables; +# GitHub-hosted runner. Override Blacksmith by editing those repo variables; # see docs/macos-ci-runners.md. # Fork PRs are gated by GitHub's built-in "Require approval for outside # collaborators" setting, so workflow-level fork guards are not needed. @@ -19,11 +19,11 @@ check_macos_runner() { if ! awk -v job="$job" ' $0 ~ "^ "job":" { in_job=1; next } in_job && /^ [^[:space:]#][^:]*:[[:space:]]*(#.*)?$/ { in_job=0 } - in_job && /runs-on:.*(vars\.MACOS_RUNNER|blacksmith-[0-9]+vcpu-macos-|warp-macos-[0-9]+-arm64)/ { saw=1 } - in_job && /os:.*(vars\.MACOS_RUNNER|blacksmith-[0-9]+vcpu-macos-|warp-macos-[0-9]+-arm64)/ { saw=1 } + in_job && /runs-on:.*(vars\.MACOS_RUNNER|blacksmith-[0-9]+vcpu-macos-)/ { saw=1 } + in_job && /os:.*(vars\.MACOS_RUNNER|blacksmith-[0-9]+vcpu-macos-)/ { saw=1 } END { exit !(saw) } ' "$file"; then - echo "FAIL: $job in $(basename "$file") must run on a paid macOS runner (vars.MACOS_RUNNER_* or a Blacksmith/Warp label), not a GitHub-hosted runner" + echo "FAIL: $job in $(basename "$file") must run on a paid macOS runner (vars.MACOS_RUNNER_* or a Blacksmith label), not a GitHub-hosted runner" exit 1 fi echo "PASS: $job in $(basename "$file") uses a paid macOS runner" @@ -61,7 +61,7 @@ check_e2e_runner_fallbacks() { exit 1 fi - if ! grep -Fq "startsWith((!inputs.runner || inputs.runner == 'auto') && (vars.MACOS_RUNNER_15 || 'warp-macos-15-arm64-6x') || inputs.runner, 'depot-macos-')" "$E2E_FILE"; then + if ! grep -Fq "startsWith((!inputs.runner || inputs.runner == 'auto') && (vars.MACOS_RUNNER_15 || 'blacksmith-6vcpu-macos-15') || inputs.runner, 'depot-macos-')" "$E2E_FILE"; then echo "FAIL: test-e2e.yml must validate all Depot macOS runner choices" exit 1 fi From 56156bd9d6e8602ee6fda3216965d5009b08431d Mon Sep 17 00:00:00 2001 From: lawrencecchen <54008264+lawrencecchen@users.noreply.github.com> Date: Sat, 30 May 2026 04:00:03 -0700 Subject: [PATCH 2/4] Document macOS runner capacity override --- docs/macos-ci-runners.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/macos-ci-runners.md b/docs/macos-ci-runners.md index c13e69fddd..4c60221858 100644 --- a/docs/macos-ci-runners.md +++ b/docs/macos-ci-runners.md @@ -31,6 +31,10 @@ Check current values: gh variable list --repo manaflow-ai/cmux ``` +## Capacity events + +If Blacksmith queues spike, temporarily point `MACOS_RUNNER_15` and `MACOS_RUNNER_26` at another paid macOS runner label with `gh variable set`, then restore the Blacksmith values after the incident. Do not change checked-in workflow defaults for a temporary capacity event. + ## Manual runs `perf-activation.yml` and `test-e2e.yml` keep a `runner` choice input that defaults to `auto`. `auto` (and the empty `pull_request` case for perf) follows `MACOS_RUNNER_15` then the checked-in Blacksmith default, so flipping the repo variable also redirects these workflows. An explicit choice wins over the variable. `test-e2e.yml` also keeps `depot-macos-*` choices and a Depot identity guard for GUI-activation runs. From 1071f648409223445df056defc6f90809d4b8e97 Mon Sep 17 00:00:00 2001 From: lawrencecchen <54008264+lawrencecchen@users.noreply.github.com> Date: Mon, 1 Jun 2026 22:17:58 -0700 Subject: [PATCH 3/4] Update release SDK-lane test for Blacksmith default runners --- tests/test_ci_release_sdk_lane.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/test_ci_release_sdk_lane.sh b/tests/test_ci_release_sdk_lane.sh index 8f4925e866..faf9f5968b 100755 --- a/tests/test_ci_release_sdk_lane.sh +++ b/tests/test_ci_release_sdk_lane.sh @@ -32,25 +32,25 @@ require_job_contains() { require_job_contains \ "$RELEASE_FILE" \ "build-ghostty-cli-helper" \ - 'runs-on: ${{ vars.MACOS_RUNNER_15 || '\''warp-macos-15-arm64-6x'\'' }}' \ + 'runs-on: ${{ vars.MACOS_RUNNER_15 || '\''blacksmith-6vcpu-macos-15'\'' }}' \ "release must build the real Ghostty CLI helper on macOS 15" require_job_contains \ "$RELEASE_FILE" \ "build-sign-notarize" \ - 'runs-on: ${{ vars.MACOS_RUNNER_26 || '\''warp-macos-26-arm64-6x'\'' }}' \ + 'runs-on: ${{ vars.MACOS_RUNNER_26 || '\''blacksmith-6vcpu-macos-26'\'' }}' \ "release must build the app on macOS 26" require_job_contains \ "$CI_FILE" \ "release-ghostty-cli-helper" \ - 'runs-on: ${{ vars.MACOS_RUNNER_15 || '\''warp-macos-15-arm64-6x'\'' }}' \ + 'runs-on: ${{ vars.MACOS_RUNNER_15 || '\''blacksmith-6vcpu-macos-15'\'' }}' \ "CI must build the real Ghostty CLI helper on macOS 15" require_job_contains \ "$CI_FILE" \ "release-build" \ - 'runs-on: ${{ vars.MACOS_RUNNER_26 || '\''warp-macos-26-arm64-6x'\'' }}' \ + 'runs-on: ${{ vars.MACOS_RUNNER_26 || '\''blacksmith-6vcpu-macos-26'\'' }}' \ "CI release-build must compile the app on macOS 26" for workflow in "$CI_FILE" "$RELEASE_FILE"; do From 638a8c0db0a19dce947e10f3a6e29c6dcf5aa46a Mon Sep 17 00:00:00 2001 From: lawrencecchen <54008264+lawrencecchen@users.noreply.github.com> Date: Mon, 1 Jun 2026 22:29:34 -0700 Subject: [PATCH 4/4] Hardcode Blacksmith runners; drop MACOS_RUNNER_* override variable --- .github/actionlint.yaml | 6 ++-- .github/workflows/build-ghosttykit.yml | 2 +- .github/workflows/ci-macos-compat.yml | 4 +-- .github/workflows/ci.yml | 20 ++++++------ .github/workflows/nightly.yml | 2 +- .github/workflows/perf-activation.yml | 8 ++--- .github/workflows/release.yml | 4 +-- .github/workflows/test-depot.yml | 2 +- .github/workflows/test-e2e.yml | 16 +++++----- .github/workflows/tmux-corpus.yml | 2 +- docs/macos-ci-runners.md | 42 ++++++-------------------- tests/test_ci_release_sdk_lane.sh | 8 ++--- tests/test_ci_self_hosted_guard.sh | 17 +++++------ 13 files changed, 55 insertions(+), 78 deletions(-) diff --git a/.github/actionlint.yaml b/.github/actionlint.yaml index 6cf888054f..408c79ec0c 100644 --- a/.github/actionlint.yaml +++ b/.github/actionlint.yaml @@ -1,8 +1,8 @@ self-hosted-runner: labels: - # Active default lives in the MACOS_RUNNER_15 / MACOS_RUNNER_26 repo - # variables; these are the literal labels referenced as fallbacks or as - # manual workflow_dispatch choices. See docs/macos-ci-runners.md. + # macOS jobs run on Blacksmith (hardcoded in the workflows). These are the + # labels referenced directly or offered as manual workflow_dispatch choices. + # See docs/macos-ci-runners.md. - blacksmith-6vcpu-macos-15 - blacksmith-6vcpu-macos-26 - blacksmith-6vcpu-macos-latest diff --git a/.github/workflows/build-ghosttykit.yml b/.github/workflows/build-ghosttykit.yml index 5b8450bef7..e5ff6d670b 100644 --- a/.github/workflows/build-ghosttykit.yml +++ b/.github/workflows/build-ghosttykit.yml @@ -9,7 +9,7 @@ concurrency: jobs: build-ghosttykit: - runs-on: ${{ vars.MACOS_RUNNER_15 || 'blacksmith-6vcpu-macos-15' }} + runs-on: blacksmith-6vcpu-macos-15 timeout-minutes: 20 env: GHOSTTYKIT_CRASH_REPORT_SUBDIR: cmux/crash diff --git a/.github/workflows/ci-macos-compat.yml b/.github/workflows/ci-macos-compat.yml index 226f8b9bf9..33702dd153 100644 --- a/.github/workflows/ci-macos-compat.yml +++ b/.github/workflows/ci-macos-compat.yml @@ -9,12 +9,12 @@ jobs: fail-fast: false matrix: include: - - os: ${{ vars.MACOS_RUNNER_15 || 'blacksmith-6vcpu-macos-15' }} + - os: blacksmith-6vcpu-macos-15 timeout: 30 startup_smoke: true virtual_display: true skip_zig: false - - os: ${{ vars.MACOS_RUNNER_26 || 'blacksmith-6vcpu-macos-26' }} + - os: blacksmith-6vcpu-macos-26 timeout: 30 startup_smoke: true virtual_display: false diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ec3729d6bd..d50d89ac90 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -170,11 +170,13 @@ jobs: bun test tests/vm-db-read-model.test.ts tests: - # macOS CI runs on Blacksmith by default (checked in, git-tracked). The - # vars.MACOS_RUNNER_15 / MACOS_RUNNER_26 repo variables are an emergency - # override only and are normally unset: set them to a warp-macos-* label to - # revert every macOS job to Warp without a PR. See docs/macos-ci-runners.md. - runs-on: ${{ vars.MACOS_RUNNER_15 || 'blacksmith-6vcpu-macos-15' }} + # macOS CI runs on Blacksmith (hardcoded, git-tracked; no override variable). + # To change provider or roll back to Warp, edit the runs-on labels in a PR. + # macos-15 vs macos-26: helper / GhosttyKit / nightly jobs build on macos-15 + # because zig can only cross-link the universal Ghostty CLI helper against a + # pre-26 SDK; the app and SDK-validation builds use macos-26 (Liquid Glass). + # See docs/macos-ci-runners.md. + runs-on: blacksmith-6vcpu-macos-15 timeout-minutes: 75 env: CMUX_SKIP_ZIG_BUILD: "1" @@ -431,7 +433,7 @@ jobs: # Keep lag validation separate from UI regressions so functional UI failures # and performance regressions stay isolated. Broader interactive UI suites # still run via test-e2e.yml on GitHub-hosted runners. - runs-on: ${{ vars.MACOS_RUNNER_15 || 'blacksmith-6vcpu-macos-15' }} + runs-on: blacksmith-6vcpu-macos-15 # A cold DerivedData cache (any project.pbxproj or Package.resolved change # mints a new cache key with no restore-keys fallback) forces a full # cmux build whose Swift codegen alone can run 20+ min. Project/package @@ -626,7 +628,7 @@ jobs: rm -f /tmp/create-virtual-display release-ghostty-cli-helper: - runs-on: ${{ vars.MACOS_RUNNER_15 || 'blacksmith-6vcpu-macos-15' }} + runs-on: blacksmith-6vcpu-macos-15 timeout-minutes: 20 steps: - name: Checkout @@ -665,7 +667,7 @@ jobs: # mistakes before they reach main. # Keep the app build on macOS 26 so SDK-gated SwiftUI Liquid Glass code # compiles into the same artifact shape as nightly and stable releases. - runs-on: ${{ vars.MACOS_RUNNER_26 || 'blacksmith-6vcpu-macos-26' }} + runs-on: blacksmith-6vcpu-macos-26 timeout-minutes: 20 steps: - name: Checkout @@ -774,7 +776,7 @@ jobs: [[ "$SDK_VERSION" == 26.* ]] ui-regressions: - runs-on: ${{ vars.MACOS_RUNNER_15 || 'blacksmith-6vcpu-macos-15' }} + runs-on: blacksmith-6vcpu-macos-15 # Cold builds after project/package changes can spend more than 25 minutes # in build-for-testing before the UI regression script starts. timeout-minutes: 45 diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index cef587ca34..c46273aaf5 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -107,7 +107,7 @@ jobs: # and injected before signing (see Select Xcode + the helper build/inject # steps). Building the whole app with Xcode 16 (#5022) shipped a macOS 15 SDK # binary that Tahoe forced into the legacy non-Liquid-Glass appearance. - runs-on: ${{ vars.MACOS_RUNNER_15 || 'blacksmith-6vcpu-macos-15' }} + runs-on: blacksmith-6vcpu-macos-15 timeout-minutes: 30 steps: - name: Checkout build ref diff --git a/.github/workflows/perf-activation.yml b/.github/workflows/perf-activation.yml index 2adb753bb0..5e1aef59c8 100644 --- a/.github/workflows/perf-activation.yml +++ b/.github/workflows/perf-activation.yml @@ -9,7 +9,7 @@ on: required: false default: "" runner: - description: macOS runner (auto follows the MACOS_RUNNER_15 repo variable, then Blacksmith) + description: macOS runner (auto uses the Blacksmith default) required: false default: auto type: choice @@ -37,7 +37,7 @@ concurrency: jobs: activation-session: - runs-on: ${{ (!inputs.runner || inputs.runner == 'auto') && (vars.MACOS_RUNNER_15 || 'blacksmith-6vcpu-macos-15') || inputs.runner }} + runs-on: ${{ (!inputs.runner || inputs.runner == 'auto') && 'blacksmith-6vcpu-macos-15' || inputs.runner }} timeout-minutes: 45 env: PERF_TAG: perfci @@ -92,8 +92,8 @@ jobs: uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: path: .ci-source-packages - key: spm-${{ (!inputs.runner || inputs.runner == 'auto') && (vars.MACOS_RUNNER_15 || 'blacksmith-6vcpu-macos-15') || inputs.runner }}-${{ hashFiles('cmux.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved') }} - restore-keys: spm-${{ (!inputs.runner || inputs.runner == 'auto') && (vars.MACOS_RUNNER_15 || 'blacksmith-6vcpu-macos-15') || inputs.runner }}- + key: spm-${{ (!inputs.runner || inputs.runner == 'auto') && 'blacksmith-6vcpu-macos-15' || inputs.runner }}-${{ hashFiles('cmux.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved') }} + restore-keys: spm-${{ (!inputs.runner || inputs.runner == 'auto') && 'blacksmith-6vcpu-macos-15' || inputs.runner }}- - name: Resolve Swift packages run: | diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 713ee6e01b..e05ffe4c3a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -16,7 +16,7 @@ env: jobs: build-ghostty-cli-helper: - runs-on: ${{ vars.MACOS_RUNNER_15 || 'blacksmith-6vcpu-macos-15' }} + runs-on: blacksmith-6vcpu-macos-15 timeout-minutes: 20 steps: - name: Checkout @@ -53,7 +53,7 @@ jobs: # Build the app on macOS 26 so SDK-gated SwiftUI Liquid Glass code compiles # into stable releases. The real universal Ghostty CLI helper is built on # macOS 15 above because Zig 0.15.2 cannot link it on macOS 26. - runs-on: ${{ vars.MACOS_RUNNER_26 || 'blacksmith-6vcpu-macos-26' }} + runs-on: blacksmith-6vcpu-macos-26 timeout-minutes: 20 steps: - name: Checkout diff --git a/.github/workflows/test-depot.yml b/.github/workflows/test-depot.yml index 7094762807..f59acbb408 100644 --- a/.github/workflows/test-depot.yml +++ b/.github/workflows/test-depot.yml @@ -28,7 +28,7 @@ on: jobs: tests: - runs-on: ${{ vars.MACOS_RUNNER_15 || 'blacksmith-6vcpu-macos-15' }} + runs-on: blacksmith-6vcpu-macos-15 timeout-minutes: 20 steps: - name: Checkout diff --git a/.github/workflows/test-e2e.yml b/.github/workflows/test-e2e.yml index 61f32d5a62..35adb51562 100644 --- a/.github/workflows/test-e2e.yml +++ b/.github/workflows/test-e2e.yml @@ -1,5 +1,5 @@ name: E2E test with video recording -run-name: ${{ inputs.test_filter }} on ${{ (!inputs.runner || inputs.runner == 'auto') && (vars.MACOS_RUNNER_15 || 'blacksmith-6vcpu-macos-15') || inputs.runner }} @ ${{ inputs.ref || github.ref_name }} +run-name: ${{ inputs.test_filter }} on ${{ (!inputs.runner || inputs.runner == 'auto') && 'blacksmith-6vcpu-macos-15' || inputs.runner }} @ ${{ inputs.ref || github.ref_name }} on: workflow_dispatch: @@ -21,7 +21,7 @@ on: default: true type: boolean runner: - description: "Runner OS (auto follows the MACOS_RUNNER_15 repo variable, then Blacksmith; pick depot-macos-* for GUI activation)" + description: "Runner OS (auto uses the Blacksmith default; pick depot-macos-* for GUI activation)" required: false default: "auto" type: choice @@ -34,20 +34,20 @@ on: - depot-macos-14 concurrency: - group: e2e-${{ (!inputs.runner || inputs.runner == 'auto') && (vars.MACOS_RUNNER_15 || 'blacksmith-6vcpu-macos-15') || inputs.runner }}-${{ inputs.ref || github.ref_name }}-${{ inputs.test_filter }} + group: e2e-${{ (!inputs.runner || inputs.runner == 'auto') && 'blacksmith-6vcpu-macos-15' || inputs.runner }}-${{ inputs.ref || github.ref_name }}-${{ inputs.test_filter }} cancel-in-progress: true jobs: e2e: - runs-on: ${{ (!inputs.runner || inputs.runner == 'auto') && (vars.MACOS_RUNNER_15 || 'blacksmith-6vcpu-macos-15') || inputs.runner }} + runs-on: ${{ (!inputs.runner || inputs.runner == 'auto') && 'blacksmith-6vcpu-macos-15' || inputs.runner }} timeout-minutes: 20 env: TEST_REF: ${{ inputs.ref || github.ref }} steps: - name: Validate Depot runner identity - if: ${{ startsWith((!inputs.runner || inputs.runner == 'auto') && (vars.MACOS_RUNNER_15 || 'blacksmith-6vcpu-macos-15') || inputs.runner, 'depot-macos-') }} + if: ${{ startsWith((!inputs.runner || inputs.runner == 'auto') && 'blacksmith-6vcpu-macos-15' || inputs.runner, 'depot-macos-') }} env: - REQUESTED_RUNNER: ${{ (!inputs.runner || inputs.runner == 'auto') && (vars.MACOS_RUNNER_15 || 'blacksmith-6vcpu-macos-15') || inputs.runner }} + REQUESTED_RUNNER: ${{ (!inputs.runner || inputs.runner == 'auto') && 'blacksmith-6vcpu-macos-15' || inputs.runner }} RUNNER_CONTEXT_NAME: ${{ runner.name }} run: | set -euo pipefail @@ -230,8 +230,8 @@ jobs: uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: path: .ci-source-packages - key: spm-${{ (!inputs.runner || inputs.runner == 'auto') && (vars.MACOS_RUNNER_15 || 'blacksmith-6vcpu-macos-15') || inputs.runner }}-${{ hashFiles('cmux.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved') }} - restore-keys: spm-${{ (!inputs.runner || inputs.runner == 'auto') && (vars.MACOS_RUNNER_15 || 'blacksmith-6vcpu-macos-15') || inputs.runner }}- + key: spm-${{ (!inputs.runner || inputs.runner == 'auto') && 'blacksmith-6vcpu-macos-15' || inputs.runner }}-${{ hashFiles('cmux.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved') }} + restore-keys: spm-${{ (!inputs.runner || inputs.runner == 'auto') && 'blacksmith-6vcpu-macos-15' || inputs.runner }}- - name: Resolve Swift packages run: | diff --git a/.github/workflows/tmux-corpus.yml b/.github/workflows/tmux-corpus.yml index de3d9fdd75..c090ba4539 100644 --- a/.github/workflows/tmux-corpus.yml +++ b/.github/workflows/tmux-corpus.yml @@ -61,7 +61,7 @@ jobs: terminal-nightly: if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' - runs-on: ${{ vars.MACOS_RUNNER_15 || 'blacksmith-6vcpu-macos-15' }} + runs-on: blacksmith-6vcpu-macos-15 timeout-minutes: 30 steps: - name: Checkout diff --git a/docs/macos-ci-runners.md b/docs/macos-ci-runners.md index 7234fd98c5..ffc649d860 100644 --- a/docs/macos-ci-runners.md +++ b/docs/macos-ci-runners.md @@ -1,46 +1,22 @@ # macOS CI runners -All paid macOS CI/CD jobs pick their runner from two repository variables instead of a hardcoded label: +All paid macOS CI/CD jobs run on Blacksmith. The runner labels are hardcoded in the workflows (git-tracked); there is no repo-variable override. -- `MACOS_RUNNER_15` for jobs that build the real universal Release app, including nightly, stable release, `release-build`, and the e2e/perf defaults. -- `MACOS_RUNNER_26` for macOS 26 compatibility coverage and jobs that do not need Zig to build the real universal Ghostty CLI helper. +- `blacksmith-6vcpu-macos-15` for jobs that build the universal Ghostty CLI helper (zig 0.15.2 can only cross-link the x86_64 slice against a pre-26 SDK), for the GhosttyKit framework build, for unit/UI tests, and for the nightly app build (which uses Xcode 26 on the macOS 15 host). +- `blacksmith-6vcpu-macos-26` for the app builds that must link the macOS 26 SDK so SDK-gated SwiftUI Liquid Glass code compiles in: stable `release` `build-sign-notarize` and the CI `release-build` SDK-validation lane. `ci-macos-compat.yml` also exercises macOS 26 with `CMUX_SKIP_ZIG_BUILD=1`. -Workflows reference them as `runs-on: ${{ vars.MACOS_RUNNER_15 || 'blacksmith-6vcpu-macos-15' }}`. If a variable is unset, the job still uses Blacksmith. +Workflows reference these labels directly, e.g. `runs-on: blacksmith-6vcpu-macos-15`. -## Blacksmith defaults +## Changing the runner -Nightly and stable release stay on macOS 15 until Zig can link the real universal Ghostty CLI helper on macOS 26. `ci-macos-compat.yml` still covers macOS 26 by setting `CMUX_SKIP_ZIG_BUILD=1`, but publishing workflows cannot use that stub because the signed artifacts must include the real helper. +To switch providers or roll back to Warp, edit the `runs-on` labels in `.github/workflows/*.yml` and open a PR. There is no variable to flip; the runner choice lives in git so every change is reviewed and recorded. -The defaults are checked into the workflows. The repo variables are an override layer and take effect on the next workflow run, with no PR or commit. - -Use Blacksmith (default): - -```bash -gh variable set MACOS_RUNNER_15 --repo manaflow-ai/cmux -b blacksmith-6vcpu-macos-15 -gh variable set MACOS_RUNNER_26 --repo manaflow-ai/cmux -b blacksmith-6vcpu-macos-26 -``` - -Remove the override and use the checked-in Blacksmith defaults: - -```bash -gh variable delete MACOS_RUNNER_15 --repo manaflow-ai/cmux -gh variable delete MACOS_RUNNER_26 --repo manaflow-ai/cmux -``` - -Check current values: - -```bash -gh variable list --repo manaflow-ai/cmux -``` - -## Capacity events - -If Blacksmith queues spike, temporarily point `MACOS_RUNNER_15` and `MACOS_RUNNER_26` at another paid macOS runner label with `gh variable set`, then restore the Blacksmith values after the incident. Do not change checked-in workflow defaults for a temporary capacity event. +If a new runner label is introduced, add it to `.github/actionlint.yaml` so `actionlint` recognizes it. ## Manual runs -`perf-activation.yml` and `test-e2e.yml` keep a `runner` choice input that defaults to `auto`. `auto` (and the empty `pull_request` case for perf) follows `MACOS_RUNNER_15` then the checked-in Blacksmith default, so flipping the repo variable also redirects these workflows. An explicit choice wins over the variable. `test-e2e.yml` also keeps `depot-macos-*` choices and a Depot identity guard for GUI-activation runs. +`perf-activation.yml` and `test-e2e.yml` keep a `runner` choice input that defaults to `auto`. `auto` (and the empty `pull_request` case for perf) resolves to the hardcoded Blacksmith default; an explicit choice wins. `test-e2e.yml` also keeps `depot-macos-*` choices and a Depot identity guard for GUI-activation runs. ## Guard -`tests/test_ci_self_hosted_guard.sh` (run by the `workflow-guard-tests` job) asserts every paid macOS job references `vars.MACOS_RUNNER_*` or a Blacksmith label, so a job can never silently fall back to a free GitHub-hosted runner. Keep new labels in `.github/actionlint.yaml`. +`tests/test_ci_self_hosted_guard.sh` (run by the `workflow-guard-tests` job) asserts every paid macOS job references a Blacksmith label, so a job can never silently fall back to a free GitHub-hosted runner. `tests/test_ci_release_sdk_lane.sh` asserts the release/CI app builds use macOS 26 with a macOS-15-built helper. diff --git a/tests/test_ci_release_sdk_lane.sh b/tests/test_ci_release_sdk_lane.sh index faf9f5968b..c5fa7c001c 100755 --- a/tests/test_ci_release_sdk_lane.sh +++ b/tests/test_ci_release_sdk_lane.sh @@ -32,25 +32,25 @@ require_job_contains() { require_job_contains \ "$RELEASE_FILE" \ "build-ghostty-cli-helper" \ - 'runs-on: ${{ vars.MACOS_RUNNER_15 || '\''blacksmith-6vcpu-macos-15'\'' }}' \ + 'runs-on: blacksmith-6vcpu-macos-15' \ "release must build the real Ghostty CLI helper on macOS 15" require_job_contains \ "$RELEASE_FILE" \ "build-sign-notarize" \ - 'runs-on: ${{ vars.MACOS_RUNNER_26 || '\''blacksmith-6vcpu-macos-26'\'' }}' \ + 'runs-on: blacksmith-6vcpu-macos-26' \ "release must build the app on macOS 26" require_job_contains \ "$CI_FILE" \ "release-ghostty-cli-helper" \ - 'runs-on: ${{ vars.MACOS_RUNNER_15 || '\''blacksmith-6vcpu-macos-15'\'' }}' \ + 'runs-on: blacksmith-6vcpu-macos-15' \ "CI must build the real Ghostty CLI helper on macOS 15" require_job_contains \ "$CI_FILE" \ "release-build" \ - 'runs-on: ${{ vars.MACOS_RUNNER_26 || '\''blacksmith-6vcpu-macos-26'\'' }}' \ + 'runs-on: blacksmith-6vcpu-macos-26' \ "CI release-build must compile the app on macOS 26" for workflow in "$CI_FILE" "$RELEASE_FILE"; do diff --git a/tests/test_ci_self_hosted_guard.sh b/tests/test_ci_self_hosted_guard.sh index b9c500c540..b990972ff7 100755 --- a/tests/test_ci_self_hosted_guard.sh +++ b/tests/test_ci_self_hosted_guard.sh @@ -1,9 +1,8 @@ #!/usr/bin/env bash # Regression test for https://github.com/manaflow-ai/cmux/issues/385. -# Ensures paid CI jobs use a paid macOS runner (Blacksmith, routed -# through the MACOS_RUNNER_15 / MACOS_RUNNER_26 repo variables), never a free -# GitHub-hosted runner. Override Blacksmith by editing those repo variables; -# see docs/macos-ci-runners.md. +# Ensures paid CI jobs use a paid macOS runner (a Blacksmith label), never a +# free GitHub-hosted runner. Runners are hardcoded in the workflows; see +# docs/macos-ci-runners.md. # Fork PRs are gated by GitHub's built-in "Require approval for outside # collaborators" setting, so workflow-level fork guards are not needed. set -euo pipefail @@ -19,11 +18,11 @@ check_macos_runner() { if ! awk -v job="$job" ' $0 ~ "^ "job":" { in_job=1; next } in_job && /^ [^[:space:]#][^:]*:[[:space:]]*(#.*)?$/ { in_job=0 } - in_job && /runs-on:.*(vars\.MACOS_RUNNER|blacksmith-[0-9]+vcpu-macos-)/ { saw=1 } - in_job && /os:.*(vars\.MACOS_RUNNER|blacksmith-[0-9]+vcpu-macos-)/ { saw=1 } + in_job && /runs-on:.*blacksmith-[0-9]+vcpu-macos-/ { saw=1 } + in_job && /os:.*blacksmith-[0-9]+vcpu-macos-/ { saw=1 } END { exit !(saw) } ' "$file"; then - echo "FAIL: $job in $(basename "$file") must run on a paid macOS runner (vars.MACOS_RUNNER_* or a Blacksmith label), not a GitHub-hosted runner" + echo "FAIL: $job in $(basename "$file") must run on a paid macOS runner (a Blacksmith label), not a GitHub-hosted runner" exit 1 fi echo "PASS: $job in $(basename "$file") uses a paid macOS runner" @@ -61,7 +60,7 @@ check_e2e_runner_fallbacks() { exit 1 fi - if ! grep -Fq "startsWith((!inputs.runner || inputs.runner == 'auto') && (vars.MACOS_RUNNER_15 || 'blacksmith-6vcpu-macos-15') || inputs.runner, 'depot-macos-')" "$E2E_FILE"; then + if ! grep -Fq "startsWith((!inputs.runner || inputs.runner == 'auto') && 'blacksmith-6vcpu-macos-15' || inputs.runner, 'depot-macos-')" "$E2E_FILE"; then echo "FAIL: test-e2e.yml must validate all Depot macOS runner choices" exit 1 fi @@ -133,7 +132,7 @@ check_macos_runner "$CI_FILE" "ui-regressions" # build-ghosttykit.yml check_macos_runner "$GHOSTTYKIT_FILE" "build-ghosttykit" -# ci-macos-compat.yml (matrix.os routed through the MACOS_RUNNER_* repo vars) +# ci-macos-compat.yml (matrix.os uses hardcoded Blacksmith labels) check_macos_runner "$COMPAT_FILE" "compat-tests" # test-e2e.yml is manual, so keep the Depot GUI runner choices but cancel