From ba8eb909193cfdf529a8e119c5c3bcfe7650fe7d Mon Sep 17 00:00:00 2001 From: Leo Li Date: Wed, 23 Sep 2026 18:53:38 -0700 Subject: [PATCH 1/2] ci: remove the Tart VM runner choices Nobody runs the Tart VM pool any more, yet test-e2e.yml still offered tart-canary, tart-dual and tart-small, and test-ios.yml offered tart-ios. Picking one queued for a runner that never comes. A tart-canary run was also mistaken for evidence about the default pool: its Xcode and paths differ, so it could never adopt main's DerivedData. Remove the choices, their identity-check steps, the actionlint label and the dispatcher's allowlist entries. The self-hosted guard stops requiring the choices and stops exempting them, so any tart-* label in a runner position now fails it. The runner docs drop the Tart pool and its restore recipe. Co-Authored-By: Claude Opus 5.5 --- .github/actionlint.yaml | 2 - .github/workflows/cmux-tui-artifacts.yml | 4 +- .github/workflows/test-e2e.yml | 43 +-------- .github/workflows/test-ios.yml | 48 +--------- docs/ci-runners.md | 62 ++----------- docs/ci/mac-fleet.md | 11 +-- scripts/ci/dispatch-focused-test.py | 3 - tests/test_ci_e2e_compilation_cache.py | 2 +- tests/test_ci_self_hosted_guard.sh | 112 ++--------------------- tests/test_run_e2e.py | 2 +- 10 files changed, 25 insertions(+), 264 deletions(-) diff --git a/.github/actionlint.yaml b/.github/actionlint.yaml index df4f46dc183d..0d0a22d21623 100644 --- a/.github/actionlint.yaml +++ b/.github/actionlint.yaml @@ -12,8 +12,6 @@ self-hosted-runner: # macOS 26 needs route to Blacksmith cloud, not warp-macos-26-arm64-6x: our # self-hosted minis carry that label, and GitHub prefers a matching # self-hosted runner. See check_no_self_hosted_fleet_runners. - # Manual E2E canary only. Required CI remains routed through repo variables. - - tart-canary # Dispatch-only compile-admission producer; guarded separately from required jobs. - cmux-persistent-macos-compile # Linux: Blacksmith primary (LINUX_RUNNER), WarpBuild overflow fallback. diff --git a/.github/workflows/cmux-tui-artifacts.yml b/.github/workflows/cmux-tui-artifacts.yml index 91654050cef2..b8dd19897245 100644 --- a/.github/workflows/cmux-tui-artifacts.yml +++ b/.github/workflows/cmux-tui-artifacts.yml @@ -42,8 +42,8 @@ on: inputs: macos_runner: # A branch dogfood publish only needs its commit-addressed objects; let - # it build the macOS targets on an idle self-hosted label (for example - # tart-macos-15) instead of waiting behind the shared hosted queue. + # it build the macOS targets on an idle cloud label (for example + # blacksmith-6vcpu-macos-15) instead of waiting behind the hosted queue. description: "Optional macOS runner label override for this publish" required: false default: "" diff --git a/.github/workflows/test-e2e.yml b/.github/workflows/test-e2e.yml index 47285584a906..3708e953df47 100644 --- a/.github/workflows/test-e2e.yml +++ b/.github/workflows/test-e2e.yml @@ -29,7 +29,7 @@ on: default: true type: boolean runner: - description: "Runner OS (auto follows MACOS_RUNNER_TESTS; tart-* choices use isolated VMs)" + description: "Runner OS (auto follows MACOS_RUNNER_TESTS)" required: false default: "auto" type: choice @@ -39,9 +39,6 @@ on: - blacksmith-6vcpu-macos-26 - blacksmith-12vcpu-macos-26 - blacksmith-6vcpu-macos-latest - - tart-canary - - tart-dual - - tart-small concurrency: group: e2e-${{ (!inputs.runner || inputs.runner == 'auto') && (vars.MACOS_RUNNER_TESTS || 'blacksmith-6vcpu-macos-26') || inputs.runner }}-${{ inputs.ref || github.ref_name }}-${{ inputs.test_filter }} @@ -217,25 +214,6 @@ jobs: CMUX_PRODUCT_RUNNER: ${{ (!inputs.runner || inputs.runner == 'auto') && (vars.MACOS_RUNNER_TESTS || 'blacksmith-6vcpu-macos-26') || inputs.runner }} steps: - - name: Validate Tart canary identity - if: ${{ startsWith((!inputs.runner || inputs.runner == 'auto') && (vars.MACOS_RUNNER_TESTS || 'blacksmith-6vcpu-macos-26') || inputs.runner, 'tart-') }} - env: - REQUESTED_RUNNER: ${{ (!inputs.runner || inputs.runner == 'auto') && (vars.MACOS_RUNNER_TESTS || 'blacksmith-6vcpu-macos-26') || inputs.runner }} - RUNNER_CONTEXT_NAME: ${{ runner.name }} - run: | - set -euo pipefail - case "$RUNNER_CONTEXT_NAME" in - tart-cmux-*) ;; - *) - echo "::error::$REQUESTED_RUNNER resolved to unexpected runner $RUNNER_CONTEXT_NAME" - exit 1 - ;; - esac - test -f /etc/cmux-tart-ci || { - echo "::error::$REQUESTED_RUNNER runner is missing the immutable VM identity marker" - exit 1 - } - - name: Clear stale git locks (self-hosted reused workspace) shell: bash run: | @@ -641,25 +619,6 @@ jobs: CMUX_APP_HOST_CAPTURE_XCRESULTS: "1" steps: - - name: Validate Tart canary identity - if: ${{ startsWith((!inputs.runner || inputs.runner == 'auto') && (vars.MACOS_RUNNER_TESTS || 'blacksmith-6vcpu-macos-26') || inputs.runner, 'tart-') }} - env: - REQUESTED_RUNNER: ${{ (!inputs.runner || inputs.runner == 'auto') && (vars.MACOS_RUNNER_TESTS || 'blacksmith-6vcpu-macos-26') || inputs.runner }} - RUNNER_CONTEXT_NAME: ${{ runner.name }} - run: | - set -euo pipefail - case "$RUNNER_CONTEXT_NAME" in - tart-cmux-*) ;; - *) - echo "::error::$REQUESTED_RUNNER resolved to unexpected runner $RUNNER_CONTEXT_NAME" - exit 1 - ;; - esac - test -f /etc/cmux-tart-ci || { - echo "::error::$REQUESTED_RUNNER runner is missing the immutable VM identity marker" - exit 1 - } - - name: Clear stale git locks (self-hosted reused workspace) shell: bash run: | diff --git a/.github/workflows/test-ios.yml b/.github/workflows/test-ios.yml index cba6ccb4db43..073df174dd5c 100644 --- a/.github/workflows/test-ios.yml +++ b/.github/workflows/test-ios.yml @@ -43,14 +43,13 @@ on: - iphone - ipad runner: - description: "macOS runner (auto follows MACOS_RUNNER_IOS; tart-ios uses the isolated VM fleet)" + description: "macOS runner (auto follows MACOS_RUNNER_IOS)" required: false default: "auto" type: choice options: - auto - blacksmith-6vcpu-macos-26 - - tart-ios cache_backend: description: "Cache store for this run. default follows CI_CACHE_BACKEND." required: false @@ -225,21 +224,6 @@ jobs: *) echo "::error::Unsupported Swift package: $SELECTED_PACKAGE"; exit 1 ;; esac - - name: Validate Tart runner identity - if: ${{ startsWith((!inputs.runner || inputs.runner == 'auto') && (vars.MACOS_RUNNER_IOS || 'blacksmith-6vcpu-macos-26') || inputs.runner, 'tart-') }} - env: - RUNNER_CONTEXT_NAME: ${{ runner.name }} - run: | - set -euo pipefail - [[ "$RUNNER_CONTEXT_NAME" == tart-cmux-* ]] || { - echo "::error::tart-ios resolved to unexpected runner $RUNNER_CONTEXT_NAME" - exit 1 - } - test -f /etc/cmux-tart-ci || { - echo "::error::tart-ios runner is missing the immutable VM identity marker" - exit 1 - } - - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: @@ -387,21 +371,6 @@ jobs: package_seconds: ${{ steps.package-product.outputs.seconds }} upload_seconds: ${{ steps.upload-metrics.outputs.seconds }} steps: - - name: Validate Tart runner identity - if: ${{ startsWith((!inputs.runner || inputs.runner == 'auto') && (vars.MACOS_RUNNER_IOS || 'blacksmith-6vcpu-macos-26') || inputs.runner, 'tart-') }} - env: - RUNNER_CONTEXT_NAME: ${{ runner.name }} - run: | - set -euo pipefail - [[ "$RUNNER_CONTEXT_NAME" == tart-cmux-* ]] || { - echo "::error::tart-ios resolved to unexpected runner $RUNNER_CONTEXT_NAME" - exit 1 - } - test -f /etc/cmux-tart-ci || { - echo "::error::tart-ios runner is missing the immutable VM identity marker" - exit 1 - } - - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: @@ -693,21 +662,6 @@ jobs: matrix: family: ${{ fromJSON(needs.detect-ios-changes.outputs.device_families) }} steps: - - name: Validate Tart runner identity - if: ${{ startsWith((!inputs.runner || inputs.runner == 'auto') && (vars.MACOS_RUNNER_IOS || 'blacksmith-6vcpu-macos-26') || inputs.runner, 'tart-') }} - env: - RUNNER_CONTEXT_NAME: ${{ runner.name }} - run: | - set -euo pipefail - [[ "$RUNNER_CONTEXT_NAME" == tart-cmux-* ]] || { - echo "::error::tart-ios resolved to unexpected runner $RUNNER_CONTEXT_NAME" - exit 1 - } - test -f /etc/cmux-tart-ci || { - echo "::error::tart-ios runner is missing the immutable VM identity marker" - exit 1 - } - - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: diff --git a/docs/ci-runners.md b/docs/ci-runners.md index a427af026cc3..b74dc85e17d1 100644 --- a/docs/ci-runners.md +++ b/docs/ci-runners.md @@ -4,9 +4,7 @@ Every CI/CD job picks its runner from a repository variable instead of a hardcoded label. Changing a runner type is a single repository-variable update that takes effect on the next workflow run. -Linux uses Blacksmith. macOS uses Blacksmith cloud runners, with the -self-hosted Tart fleet described below carrying specific lanes as they are -qualified. WarpBuild is paid overflow and is not a steady state for any lane. +Linux uses Blacksmith. macOS uses Blacksmith cloud runners. WarpBuild is paid overflow and is not a steady state for any lane. Non-urgent macOS work runs on free GitHub-hosted runners through the background lane described below. @@ -268,29 +266,9 @@ compile, warning validation, product publication, total wall time, runner time, and the `hot` / `partially-warm` / `cold-reset` / `hosted fallback` classification. -## Tart isolation and capacity - -Each GitHub runner identity is sealed into a Tart template. A job runs in a -fresh clone with an Aqua login session, then the host deletes the clone. This -provides the GUI session required by macOS XCTest and prevents DerivedData, -simulators, credentials, and workspaces from leaking into later jobs. - -The fleet has 18 Sequoia slots: two each on the seven 48 GB or larger hosts and -one each on the two 16 GB hosts. The 16 large-host slots accept GUI and iOS -jobs; all 18 accept ordinary macOS 15 jobs. macOS 26 and release builds stay on -Blacksmith until a Tahoe VM image passes the same runner and GUI canaries. Hosts -reject new jobs below their free-space threshold, delete every job VM after -use, and reap stale clones. - -Do not route jobs to the physical mini runner records. The supported -self-hosted labels are the `tart-*` labels, and each Tart-aware canary checks -that the resolved runner name starts with `tart-cmux-` and that the guest has -the immutable `/etc/cmux-tart-ci` marker. - ## Shared physical-host interoperability -The current required-CI policy continues to use isolated Tart guests or hosted -providers. Any future path that executes directly on shared CMUX-owned hardware +The current required-CI policy uses hosted providers. Any future path that executes directly on shared CMUX-owned hardware must preserve a separate caller identity, semantic workload request, and machine-local physical lease. @@ -321,9 +299,8 @@ admission or is draining, pressured, or unavailable. ## Break-glass: switch a runner type to a paid provider -There is no automatic overflow. If the Tart pool is unavailable or its queue is -too long, set the affected variable to a paid provider. Restore Tart after the -fleet recovers. +There is no automatic overflow. If the Blacksmith queue is too long, set the +affected variable to a paid provider, and restore it once the queue recovers. Four runner variables exist to name **metered WarpBuild capacity**, so they are read through a second switch that lives in this repository rather than in @@ -371,26 +348,6 @@ Leave `MACOS_RUNNER_PR` and `MACOS_RUNNER_TESTS` unset in either recipe. They exist to hold the pull-request and manual test lanes on Blacksmith independently of whatever the pool above is set to. -Restore the self-hosted pool with explicit labels. The gate above applies -here too: `MACOS_RUNNER_15`, `MACOS_RUNNER_DISPLAY` and the other gated -variables are read only when `CI_PAID_MACOS_OVERFLOW=1`, so Tart needs that -flag set even though Tart is free. Without it, these values are ignored and -every lane stays on its Blacksmith fallback, with no error. `MACOS_RUNNER_26` -is ungated, so repointing the ordinary macOS 26 pool does not require the paid -overflow switch. - -```bash -gh variable set MACOS_RUNNER_15 --repo manaflow-ai/cmux -b tart-macos-15 -gh variable set MACOS_RUNNER_DUAL_XCODE --repo manaflow-ai/cmux -b blacksmith-6vcpu-macos-15 -gh variable set MACOS_RUNNER_26 --repo manaflow-ai/cmux -b blacksmith-6vcpu-macos-26 -gh variable set MACOS_RUNNER_26_LARGE --repo manaflow-ai/cmux -b blacksmith-12vcpu-macos-26 -gh variable set MACOS_RUNNER_DISPLAY --repo manaflow-ai/cmux -b tart-gui -gh variable set MACOS_RUNNER_IOS --repo manaflow-ai/cmux -b tart-ios -``` - -`MACOS_RUNNER_DUAL_XCODE` remains on Blacksmith because the Tart macOS 15 -image currently carries Xcode 26 only and cannot build the SDK 15 helper. - Check current values: ```bash @@ -404,9 +361,7 @@ defaults to `auto`. Manual `auto` runs follow `MACOS_RUNNER_15` then the Blacksm fallback, so flipping the repo variable redirects those workflows. An explicit manual choice wins over the variable; both dropdowns expose Blacksmith, Warp, and `depot-macos-*` choices, with a Depot identity guard for GUI-activation -runs. `test-e2e.yml` also exposes `tart-canary`, `tart-dual`, and `tart-small` -for targeted fleet validation. These choices are available only through -`workflow_dispatch`. +runs. These choices are available only through `workflow_dispatch`. ## Guard @@ -426,8 +381,8 @@ repository per minute, since Blacksmith is sponsored for this organization. The CI health report counts those two. Keep new labels in `.github/actionlint.yaml`. -The fleet-label guard allows Tart labels only as exact manual canary choices. -Required jobs continue to reference repository variables, so cutover and +The fleet-label guard rejects `tart-*` labels everywhere; the Tart VM pool no +longer exists. Required jobs continue to reference repository variables, so cutover and break-glass remain configuration changes instead of workflow edits. ## CMUX-owned machine enrollment @@ -459,5 +414,4 @@ carries no repository secrets, and grants its hot state zero result authority. Every required macOS fallback still routes to the paid hosted path. `check_no_self_hosted_fleet_runners` in `tests/test_ci_self_hosted_guard.sh` enforces that exact exception and rejects -any second required-job or generic fleet route. Repository variables may keep -pointing at the isolated `tart-*` pool for their existing jobs. +any second required-job or generic fleet route. diff --git a/docs/ci/mac-fleet.md b/docs/ci/mac-fleet.md index 6e127b763ba5..cbe233ae2b08 100644 --- a/docs/ci/mac-fleet.md +++ b/docs/ci/mac-fleet.md @@ -8,7 +8,7 @@ This document is the capacity and operations layer. It does not restate the routing contract, which already exists: - [`ci-runners.md`](../ci-runners.md) owns the runner-variable table, the - persistent compile-admission pilot contract, the Tart pool, and the + persistent compile-admission pilot contract and the direct-physical-host boundary. - [`fleet-enrollment.md`](../fleet-enrollment.md) owns machine onboarding. - [`workload-profiles.md`](../workload-profiles.md) owns workload identity. @@ -197,9 +197,9 @@ them (section 5). owned-Mac lane is a deliberate guard edit, not an accident. 3. **`app-host unit tests`** - do **not** move to minis, despite being 55% of the minutes. It needs a foreground GUI session, it is six shards of - XCTest, and it is a required check. Its home is the isolated Tart pool - (18 slots, `ci-runners.md`), where each job gets a fresh VM clone and an - Aqua login session. A shared mini cannot give it either. + XCTest, and it is a required check. Its home is the cloud macOS pool, where each + job gets a fresh machine and an Aqua login session. A shared mini cannot + give it either. 4. **`release-build`, signing, notarization, nightly, TestFlight** - never. Unchanged from `ci-runners.md`. @@ -514,8 +514,7 @@ There is no macOS ephemeral-runner primitive anywhere in either repository. The honest statement of this design is: **the macOS fleet is a persistent, credential-minimized, artifact-producing machine whose output carries no authority, not an ephemeral runner.** If per-job macOS isolation is ever -required, the existing Tart pool provides it (fresh VM clone per job, deleted -after) and is where that requirement belongs. +required, the cloud macOS pools provide it (a fresh machine per job). ## 5. Rollout diff --git a/scripts/ci/dispatch-focused-test.py b/scripts/ci/dispatch-focused-test.py index 301b0267b0b8..dded4d963f67 100644 --- a/scripts/ci/dispatch-focused-test.py +++ b/scripts/ci/dispatch-focused-test.py @@ -31,9 +31,6 @@ "blacksmith-6vcpu-macos-26", "blacksmith-12vcpu-macos-26", "blacksmith-6vcpu-macos-latest", - "tart-canary", - "tart-dual", - "tart-small", ) # Half of all commits compile on the large macOS 26 SKU, so the two sizes are # compared on real focused-run traffic rather than one benchmark. The split is diff --git a/tests/test_ci_e2e_compilation_cache.py b/tests/test_ci_e2e_compilation_cache.py index 00edb21d08c1..25800a384c47 100644 --- a/tests/test_ci_e2e_compilation_cache.py +++ b/tests/test_ci_e2e_compilation_cache.py @@ -319,7 +319,7 @@ def test_failed_restore_discards_partial_cache_without_removing_products(self): def test_failure_guard_only_allows_optional_compilation_cache_steps(self): guard = (ROOT / 'tests/test_ci_self_hosted_guard.sh').read_text() start = guard.index('check_e2e_runner_fallbacks() {') - end = guard.index('\ncheck_ios_tart_canary()', start) + end = guard.index('\ncheck_xcode_selection()', start) invoke = guard[start:end] + '\ncheck_e2e_runner_fallbacks\n' workflow = (ROOT / '.github/workflows/test-e2e.yml').read_text() candidate = self.root / 'workflow.yml' diff --git a/tests/test_ci_self_hosted_guard.sh b/tests/test_ci_self_hosted_guard.sh index 2c8b8e64fa27..57b267dd53d6 100755 --- a/tests/test_ci_self_hosted_guard.sh +++ b/tests/test_ci_self_hosted_guard.sh @@ -130,7 +130,7 @@ check_e2e_runner_fallbacks() { in_on && /^ [A-Za-z0-9_-]+:/ { saw_other_trigger=1 } END { exit !(saw_dispatch && !saw_other_trigger) } ' "$E2E_FILE"; then - echo "FAIL: test-e2e.yml must remain workflow_dispatch-only before it may expose the self-hosted Tart canary" + echo "FAIL: test-e2e.yml must remain workflow_dispatch-only" exit 1 fi @@ -153,41 +153,6 @@ check_e2e_runner_fallbacks() { exit 1 fi - if ! awk ' - /^ runner:$/ { in_runner=1; next } - in_runner && /^ [A-Za-z0-9_-]+:/ { in_runner=0; in_options=0 } - in_runner && /^ options:$/ { in_options=1; next } - in_options && /^ [A-Za-z0-9_-]+:/ { in_options=0 } - in_options && /^ - tart-canary$/ { canary_options++ } - in_options && /^ - tart-dual$/ { dual_options++ } - in_options && /^ - tart-small$/ { small_options++ } - END { exit !(canary_options == 1 && dual_options == 1 && small_options == 1) } - ' "$E2E_FILE"; then - echo "FAIL: test-e2e.yml must expose tart-canary, tart-dual, and tart-small exactly once under workflow_dispatch.inputs.runner.options" - exit 1 - fi - - if ! awk ' - /^[[:space:]]*- name: Validate Tart canary identity$/ { in_tart_step=1; next } - in_tart_step && /^ - / { in_tart_step=0; in_runner_reject=0; in_marker_reject=0 } - in_tart_step && /startsWith\(\(!inputs\.runner \|\| inputs\.runner == '\''auto'\''\) && \(vars\.MACOS_RUNNER_[A-Z0-9_]+ \|\| '\''blacksmith-6vcpu-macos-[0-9]+'\''\) \|\| inputs\.runner, '\''tart-'\''\)/ { saw_effective_runner=1 } - in_tart_step && /REQUESTED_RUNNER:.*inputs\.runner/ { saw_requested_runner=1 } - in_tart_step && /RUNNER_CONTEXT_NAME: \$\{\{ runner\.name \}\}/ { saw_runner_context=1 } - in_tart_step && /tart-cmux-\*/ { saw_runner_pattern=1 } - in_tart_step && /^[[:space:]]*\*\)$/ { in_runner_reject=1 } - in_runner_reject && /::error::\$REQUESTED_RUNNER resolved to unexpected runner/ { saw_runner_reject=1 } - in_runner_reject && /^[[:space:]]*exit 1$/ { saw_runner_exit=1 } - in_runner_reject && /^[[:space:]]*;;$/ { in_runner_reject=0 } - in_tart_step && /test -f \/etc\/cmux-tart-ci \|\| \{/ { saw_vm_marker=1; in_marker_reject=1 } - in_marker_reject && /::error::\$REQUESTED_RUNNER runner is missing the immutable VM identity marker/ { saw_marker_reject=1 } - in_marker_reject && /^[[:space:]]*exit 1$/ { saw_marker_exit=1 } - in_marker_reject && /^[[:space:]]*}$/ { in_marker_reject=0 } - END { exit !(saw_effective_runner && saw_requested_runner && saw_runner_context && saw_runner_pattern && saw_runner_reject && saw_runner_exit && saw_vm_marker && saw_marker_reject && saw_marker_exit) } - ' "$E2E_FILE"; then - echo "FAIL: test-e2e.yml must validate the effective Tart runner name and immutable VM marker, failing closed for either mismatch" - exit 1 - fi - # Compilation caching is an optional optimization. Its failure must not # suppress setup/test failures or make successful tests depend on the cache # service. Keep the exception confined to these cache operations. @@ -221,10 +186,9 @@ for job_id, job in document["jobs"].items(): raise SystemExit(f"FAIL: {step.get('name')} must not mask E2E setup or test failures") PYTHON - # The Tart identity gate, the run name and the SwiftPM cache key all decide + # The run name, the concurrency group and the SwiftPM cache key all decide # things about "the runner this job uses". If any of them reads a different - # repository variable than runs-on, the gate can be skipped on a Tart VM, or - # demanded on a runner that is not one. + # repository variable than runs-on, they describe a runner the job is not on. runner_vars="$(grep -oE "vars\.MACOS_RUNNER_[A-Z0-9_]+" "$E2E_FILE" | sort -u)" if [ "$(printf '%s\n' "$runner_vars" | grep -c .)" -ne 1 ]; then echo "FAIL: test-e2e.yml must select its runner from one variable, found:" @@ -232,28 +196,7 @@ PYTHON exit 1 fi - echo "PASS: test-e2e.yml exposes supported Tart runner choices and duplicate-queue cancellation" -} - -check_ios_tart_canary() { - if ! grep -Eq '^[[:space:]]+- tart-ios$' "$IOS_FILE"; then - echo "FAIL: test-ios.yml must expose the Tart iOS canary runner" - exit 1 - fi - if [[ "$(grep -c 'tart-ios resolved to unexpected runner' "$IOS_FILE")" -ne 3 ]] || - [[ "$(grep -c 'tart-ios runner is missing the immutable VM identity marker' "$IOS_FILE")" -ne 3 ]]; then - echo "FAIL: all macOS iOS test jobs must fail closed on Tart identity mismatch" - exit 1 - fi - if [[ "$(grep -Fc "runs-on: \${{ (!inputs.runner || inputs.runner == 'auto') && (vars.MACOS_RUNNER_IOS || 'blacksmith-6vcpu-macos-26') || inputs.runner }}" "$IOS_FILE")" -ne 3 ]]; then - echo "FAIL: all macOS iOS test jobs must honor the dispatch runner override" - exit 1 - fi - if [[ "$(grep -Fc "startsWith((!inputs.runner || inputs.runner == 'auto') && (vars.MACOS_RUNNER_IOS || 'blacksmith-6vcpu-macos-26') || inputs.runner, 'tart-')" "$IOS_FILE")" -ne 3 ]]; then - echo "FAIL: all macOS iOS test jobs must validate Tart identity for explicit and repo-variable routing" - exit 1 - fi - echo "PASS: test-ios.yml exposes the guarded Tart iOS canary" + echo "PASS: test-e2e.yml runs dispatch-only and cancels duplicate queued jobs" } check_xcode_selection() { @@ -1163,8 +1106,8 @@ check_no_bare_github_hosted_runners() { check_no_self_hosted_fleet_runners() { # Required jobs route through repository variables. Forbid hardcoded fleet - # labels so Tart cutover and paid-provider fallback remain configuration - # changes and a physical host label cannot bypass the isolated VM pool. + # labels so paid-provider fallback remains a configuration change and a + # physical host label cannot reach a required job. # Allowed macOS labels (none carried by any fleet runner): # blacksmith-{6,12}vcpu-macos-{15,26,latest}, warp-macos-15-arm64-6x, # NOTE: reload-build.yml is the dev-build offload path (workflow_dispatch, @@ -1211,36 +1154,6 @@ check_no_self_hosted_fleet_runners() { exit 1 fi - local e2e_tart_option_line e2e_tart_dual_option_line e2e_tart_small_option_line e2e_tart_tahoe_option_line ios_tart_option_line - e2e_tart_option_line="$(awk ' - /^ runner:$/ { in_runner=1; next } - in_runner && /^ [A-Za-z0-9_-]+:/ { in_runner=0; in_options=0 } - in_runner && /^ options:$/ { in_options=1; next } - in_options && /^ [A-Za-z0-9_-]+:/ { in_options=0 } - in_options && /^ - tart-canary$/ { print FNR } - ' "$E2E_FILE")" - e2e_tart_dual_option_line="$(awk ' - /^ runner:$/ { in_runner=1; next } - in_runner && /^ [A-Za-z0-9_-]+:/ { in_runner=0; in_options=0 } - in_runner && /^ options:$/ { in_options=1; next } - in_options && /^ [A-Za-z0-9_-]+:/ { in_options=0 } - in_options && /^ - tart-dual$/ { print FNR } - ' "$E2E_FILE")" - e2e_tart_small_option_line="$(awk ' - /^ runner:$/ { in_runner=1; next } - in_runner && /^ [A-Za-z0-9_-]+:/ { in_runner=0; in_options=0 } - in_runner && /^ options:$/ { in_options=1; next } - in_options && /^ [A-Za-z0-9_-]+:/ { in_options=0 } - in_options && /^ - tart-small$/ { print FNR } - ' "$E2E_FILE")" - ios_tart_option_line="$(awk ' - /^ runner:$/ { in_runner=1; next } - in_runner && /^ [A-Za-z0-9_-]+:/ { in_runner=0; in_options=0 } - in_runner && /^ options:$/ { in_options=1; next } - in_options && /^ [A-Za-z0-9_-]+:/ { in_options=0 } - in_options && /^ - tart-ios$/ { print FNR } - ' "$IOS_FILE")" - local hits="" line content content_without_allowed # Inspect runner-selection lines only: runs-on:, matrix `os:`, and scalar list # items (` -