From 87b0662aa52ed9179ddca32ba6502fa52ff2f827 Mon Sep 17 00:00:00 2001 From: teamleaderleo Date: Sat, 26 Sep 2026 00:39:53 -0400 Subject: [PATCH 1/2] ci: place release-build and main's side lanes on the owned minis - pr_runner_pool.py: release-build is a side lane of a full suite with release_build (exactly when swift-package-tests builds the SDK 15 helper on Blacksmith, so a run still has at most three side lanes). Its priority follows cli-product, ahead of the light lanes, since it saves the most Blacksmith time (a 15-minute universal compile). - Main's full-suite dispatch keeps its side lanes in the plan instead of dropping them, and claude-wrapper, remote-daemon, swift-package-tests and release-build read the pick for main's dispatch the way admission does. - ci-macos.yml release-build (and its CMUX_PRODUCT_RUNNER mirror) takes the side label when owned_jobs names ' release-build ', else MACOS_RUNNER_26. - The self-hosted guard pins the new expressions and route branches. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/ci-macos.yml | 15 ++++--- .github/workflows/ci.yml | 2 +- .github/workflows/remote-daemon.yml | 2 +- docs/ci-runners.md | 4 +- scripts/ci/pr_runner_pool.py | 31 +++++++++----- tests/test_ci_pr_runner_pool.py | 63 +++++++++++++++++++++++++---- tests/test_ci_self_hosted_guard.sh | 15 +++++-- 7 files changed, 100 insertions(+), 32 deletions(-) diff --git a/.github/workflows/ci-macos.yml b/.github/workflows/ci-macos.yml index 894086cc9a57..30ec36494a0c 100644 --- a/.github/workflows/ci-macos.yml +++ b/.github/workflows/ci-macos.yml @@ -2949,12 +2949,12 @@ jobs: ghostty_helper_toolchain_sha256: ${{ steps.ghostty-helper-identity.outputs.toolchain_sha256 }} ghostty_helper_sdk: ${{ steps.ghostty-helper-identity.outputs.sdk }} # Build the release helper with SDK 15, then run package tests with SDK 26. - runs-on: ${{ github.repository_owner != 'manaflow-ai' && 'macos-15' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository && 'blacksmith-6vcpu-macos-15' || github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository && contains(inputs.pr_owned_jobs, ' swift-package ') && (github.run_attempt == 1 && (inputs.pr_side_runner || inputs.pr_runner) || github.run_attempt == 2 && (inputs.pr_side_runner || inputs.pr_refused_retry_runner)) || vars.CI_PAID_MACOS_OVERFLOW == '1' && vars.MACOS_RUNNER_DUAL_XCODE || 'blacksmith-6vcpu-macos-15') }} + runs-on: ${{ github.repository_owner != 'manaflow-ai' && 'macos-15' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository && 'blacksmith-6vcpu-macos-15' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main') && contains(inputs.pr_owned_jobs, ' swift-package ') && (github.run_attempt == 1 && (inputs.pr_side_runner || inputs.pr_runner) || github.run_attempt == 2 && (inputs.pr_side_runner || inputs.pr_refused_retry_runner)) || vars.CI_PAID_MACOS_OVERFLOW == '1' && vars.MACOS_RUNNER_DUAL_XCODE || 'blacksmith-6vcpu-macos-15') }} timeout-minutes: 60 env: # The owned label's Xcode (the lane pin) exactly when runs-on took it; # the pool picker's Wiring tests keep the two conditions equal. - CMUX_CI_XCODE_APP: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository && contains(inputs.pr_owned_jobs, ' swift-package ') && (github.run_attempt == 1 && (inputs.pr_side_runner || inputs.pr_runner) || github.run_attempt == 2 && (inputs.pr_side_runner || inputs.pr_refused_retry_runner)) && (inputs.pr_xcode_app || vars.CMUX_CI_XCODE_APP_PR) || vars.CMUX_CI_XCODE_APP_MACOS_15 }} + CMUX_CI_XCODE_APP: ${{ (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main') && contains(inputs.pr_owned_jobs, ' swift-package ') && (github.run_attempt == 1 && (inputs.pr_side_runner || inputs.pr_runner) || github.run_attempt == 2 && (inputs.pr_side_runner || inputs.pr_refused_retry_runner)) && (inputs.pr_xcode_app || vars.CMUX_CI_XCODE_APP_PR) || vars.CMUX_CI_XCODE_APP_MACOS_15 }} CMUX_CI_HELPER_XCODE_APP: ${{ vars.CMUX_CI_HELPER_XCODE_APP_MACOS_15 }} CMUX_CI_REQUIRED_MACOS_SDK_MAJOR: "26" steps: @@ -3930,8 +3930,13 @@ jobs: # compiles into the same artifact shape as nightly and stable releases. # Release builds need enough disk for a universal Release build plus the # restored SwiftPM cache, which the macOS 26 image already carries. The - # variable names that image, not this lane. - runs-on: ${{ github.repository_owner != 'manaflow-ai' && 'macos-26' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository && 'blacksmith-6vcpu-macos-26' || vars.MACOS_RUNNER_26 || 'blacksmith-6vcpu-macos-26') }} + # variable names that image, not this lane. A same-repository pull request + # or main's full-suite dispatch takes the owned side label when the picker + # placed ' release-build ' in pr_owned_jobs (pr_runner_pool.RELEASE_BUILD_JOB): + # same Xcode 26.6, and glaeda's hook classes the job isolated. Attempt 2 of a + # refused job tries the owned pool once more; any other retry takes the + # macOS 26 variable. + runs-on: ${{ github.repository_owner != 'manaflow-ai' && 'macos-26' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository && 'blacksmith-6vcpu-macos-26' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main') && contains(inputs.pr_owned_jobs, ' release-build ') && (github.run_attempt == 1 && (inputs.pr_side_runner || inputs.pr_runner) || github.run_attempt == 2 && (inputs.pr_side_runner || inputs.pr_refused_retry_runner)) || vars.MACOS_RUNNER_26 || 'blacksmith-6vcpu-macos-26') }} timeout-minutes: 60 permissions: actions: read @@ -3941,7 +3946,7 @@ jobs: CMUX_CI_XCODE_APP: ${{ vars.CMUX_CI_XCODE_APP_MACOS_26 }} CMUX_CI_REQUIRED_MACOS_SDK_MAJOR: "26" CMUX_SKIP_ZIG_BUILD: "1" - CMUX_PRODUCT_RUNNER: ${{ github.repository_owner != 'manaflow-ai' && 'macos-26' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository && 'blacksmith-6vcpu-macos-26' || vars.MACOS_RUNNER_26 || 'blacksmith-6vcpu-macos-26') }} + CMUX_PRODUCT_RUNNER: ${{ github.repository_owner != 'manaflow-ai' && 'macos-26' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository && 'blacksmith-6vcpu-macos-26' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main') && contains(inputs.pr_owned_jobs, ' release-build ') && (github.run_attempt == 1 && (inputs.pr_side_runner || inputs.pr_runner) || github.run_attempt == 2 && (inputs.pr_side_runner || inputs.pr_refused_retry_runner)) || vars.MACOS_RUNNER_26 || 'blacksmith-6vcpu-macos-26') }} CMUX_RELEASE_SOURCE_REVISION: ${{ github.event.pull_request.head.sha || github.sha }} steps: - name: Clear stale git locks (self-hosted reused workspace) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 17a6058fabee..d5177c78afac 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1176,7 +1176,7 @@ jobs: name: Claude wrapper regressions needs: [changes, static-preflight] if: ${{ !cancelled() && needs.changes.result == 'success' && needs.static-preflight.result == 'success' && (needs.changes.outputs.claude_wrapper == 'true' || (needs.changes.outputs.macos == 'true' && needs.changes.outputs.full_suite == 'true')) }} - runs-on: ${{ github.repository_owner != 'manaflow-ai' && 'macos-26' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository && (startsWith(needs.changes.outputs.macos_pr_runner, 'blacksmith-') && needs.changes.outputs.macos_pr_runner || 'blacksmith-6vcpu-macos-15') || github.event_name == 'pull_request' && github.run_attempt == 2 && contains(needs.changes.outputs.macos_pr_owned_jobs, ' claude-wrapper ') && (needs.changes.outputs.macos_pr_side_runner || needs.changes.outputs.macos_pr_refused_retry_runner) || github.event_name == 'pull_request' && (github.run_attempt > 1 || !contains(needs.changes.outputs.macos_pr_owned_jobs, ' claude-wrapper ')) && needs.changes.outputs.macos_pr_retry_runner || github.event_name == 'pull_request' && (needs.changes.outputs.macos_pr_side_runner || needs.changes.outputs.macos_pr_runner || vars.MACOS_RUNNER_PR || 'blacksmith-6vcpu-macos-15') || vars.CI_PAID_MACOS_OVERFLOW == '1' && vars.MACOS_RUNNER_15 || 'blacksmith-6vcpu-macos-15') }} + runs-on: ${{ github.repository_owner != 'manaflow-ai' && 'macos-26' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository && (startsWith(needs.changes.outputs.macos_pr_runner, 'blacksmith-') && needs.changes.outputs.macos_pr_runner || 'blacksmith-6vcpu-macos-15') || (github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main') && github.run_attempt == 2 && contains(needs.changes.outputs.macos_pr_owned_jobs, ' claude-wrapper ') && (needs.changes.outputs.macos_pr_side_runner || needs.changes.outputs.macos_pr_refused_retry_runner) || (github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main') && (github.run_attempt > 1 || !contains(needs.changes.outputs.macos_pr_owned_jobs, ' claude-wrapper ')) && needs.changes.outputs.macos_pr_retry_runner || github.event_name == 'pull_request' && (needs.changes.outputs.macos_pr_side_runner || needs.changes.outputs.macos_pr_runner || vars.MACOS_RUNNER_PR || 'blacksmith-6vcpu-macos-15') || github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main' && contains(needs.changes.outputs.macos_pr_owned_jobs, ' claude-wrapper ') && (needs.changes.outputs.macos_pr_side_runner || needs.changes.outputs.macos_pr_runner) || vars.CI_PAID_MACOS_OVERFLOW == '1' && vars.MACOS_RUNNER_15 || 'blacksmith-6vcpu-macos-15') }} # Normally 1-2 minutes, but it spawns hundreds of short bash, perl and node # processes, so a mini saturated by a compile beside it stretches it: # 120-527 s at a mean load of 36-100 on 14 cores (glaeda-cmux-jobs.jsonl, diff --git a/.github/workflows/remote-daemon.yml b/.github/workflows/remote-daemon.yml index 093e9bddeb08..96e47a5995f3 100644 --- a/.github/workflows/remote-daemon.yml +++ b/.github/workflows/remote-daemon.yml @@ -121,7 +121,7 @@ jobs: # Plain `go test` with no Xcode or GUI: any Mac will do. Follow the same # lanes as the other pull-request macOS jobs instead of pinning the # contended macOS 26 pool. - runs-on: ${{ github.repository_owner != 'manaflow-ai' && 'macos-26' || github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository && (startsWith(inputs.pr_runner, 'blacksmith-') && inputs.pr_runner || 'blacksmith-6vcpu-macos-15') || github.event_name == 'pull_request' && (github.run_attempt == 2 && contains(inputs.pr_owned_jobs, ' remote-daemon ') && (inputs.pr_side_runner || inputs.pr_refused_retry_runner) || (github.run_attempt > 1 || !contains(inputs.pr_owned_jobs, ' remote-daemon ')) && inputs.pr_retry_runner || inputs.pr_side_runner || inputs.pr_runner || vars.MACOS_RUNNER_PR || 'blacksmith-6vcpu-macos-15') || vars.CI_PAID_MACOS_OVERFLOW == '1' && vars.MACOS_RUNNER_15 || 'blacksmith-6vcpu-macos-15' }} + runs-on: ${{ github.repository_owner != 'manaflow-ai' && 'macos-26' || github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository && (startsWith(inputs.pr_runner, 'blacksmith-') && inputs.pr_runner || 'blacksmith-6vcpu-macos-15') || (github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main') && (github.run_attempt == 2 && contains(inputs.pr_owned_jobs, ' remote-daemon ') && (inputs.pr_side_runner || inputs.pr_refused_retry_runner) || (github.run_attempt > 1 || !contains(inputs.pr_owned_jobs, ' remote-daemon ')) && inputs.pr_retry_runner || inputs.pr_side_runner || inputs.pr_runner || vars.MACOS_RUNNER_PR || 'blacksmith-6vcpu-macos-15') || vars.CI_PAID_MACOS_OVERFLOW == '1' && vars.MACOS_RUNNER_15 || 'blacksmith-6vcpu-macos-15' }} timeout-minutes: 15 steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 diff --git a/docs/ci-runners.md b/docs/ci-runners.md index 668befcde8c0..09c12572c6ec 100644 --- a/docs/ci-runners.md +++ b/docs/ci-runners.md @@ -653,14 +653,14 @@ overflow and ci-owned-pool-rescue.yml as the way off a busy or refusing mini. | Jobs | Route | Why | | --- | --- | --- | | `ci-macos.yml` compile admission, app-host shards, `tests-build-and-lag`, `cli-product-tests` | owned via `pr_runner_pool.py` (root label), pull requests and main's full-suite dispatch | canonical-root jobs | -| `ci.yml` `claude-wrapper`, `remote-daemon.yml` macOS tests | owned side lane via the picker (the side label) | light | +| `ci.yml` `claude-wrapper`, `remote-daemon.yml` macOS tests | owned side lane via the picker (the side label), pull requests and main's full-suite dispatch | light | | `ci-macos.yml` `swift-package-tests` | owned side lane via the picker (the side label) when the run builds no Release helper; else Blacksmith macOS 15 | the helper needs an SDK 15 Xcode | | the seven side-lane workflows above | `CI_SIDE_LANE_RUNNER` on attempt 1 of a pull request | light; other events stay on Blacksmith | | `test-e2e.yml` (and `dispatch-focused-test.py`) | owned via `e2e_runner_pool.py`; UI runs with `CI_E2E_OWNED_UI=1` | root jobs; Blacksmith when no root runner is free | | `test-ios.yml`, `ios-screenshots.yml` | owned via `ios_runner_pool.py` behind `CI_IOS_OWNED=1` | needs the `glaeda-ios-sim` label (an iOS 26.x simulator runtime) | | `app-host-test-rerun.yml` `rerun` | Blacksmith | restores a product into a fixed canonical root; needs a root route and a glaeda class first | | `cmux-tui.yml` macOS `lint`, `test`, `cdp-browser-smoke` | Blacksmith | could move; glaeda classes unknown ids as compile (root), and these ids are generic | -| `ci-macos.yml` `release-build` | `MACOS_RUNNER_26` | could move; needs a picker key and a glaeda class | +| `ci-macos.yml` `release-build` | owned side lane via the picker (`release-build`, the side label), pull requests and main's full-suite dispatch; else `MACOS_RUNNER_26` | isolated: an unsigned universal Release into its own DerivedData, Xcode 26.6 | | low-volume dispatches: `test-macos-suite`, `tmux-corpus`, `perf-activation`, command palette benchmarks, `iroh-release-gate` version skew | Blacksmith or the caller's runner input | a few runs a week; benchmarks want a quiet machine | | `relay-tls` `system-keychain` | Blacksmith | edits the System keychain trust store | | `plain-paste-worker`, `ci-macos-compat`, `seed-swiftpm-manifests`, release and nightly Ghostty helpers | Blacksmith macOS 15 / 14 | an OS or SDK the minis lack | diff --git a/scripts/ci/pr_runner_pool.py b/scripts/ci/pr_runner_pool.py index dac9e9712249..c471fc020eb5 100644 --- a/scripts/ci/pr_runner_pool.py +++ b/scripts/ci/pr_runner_pool.py @@ -248,9 +248,9 @@ wait up to the queue rounds and the bound (owned_room()). CI_OWNED_MAIN_RESERVE (0 when unset) holds that many machines and root runners back for pull requests; with a reserve it takes an owned pool only whole, and only while its peak is free now (no queue -allowance). Its side lanes (the Claude wrapper and -remote daemon) route only for pull requests, so they are not in its plan. -Main's CI concurrency group holds one run at a time, so main holds at most +allowance). Its side lanes (the Claude wrapper, the remote daemon and the +universal Release build) are in its plan like a pull request's, and read the +pick through the same inputs. Main's CI concurrency group holds one run at a time, so main holds at most one run's machines. ci-owned-pool-rescue.yml watches it like a pull request. Anything uncertain keeps today's route: an event other than pull_request or @@ -359,7 +359,10 @@ # suite with release_build false, which then peaks at all three side lanes # beside admission and its nine follow-on jobs. MAX_RUN_JOBS counts all three; # the replay charge leaves out the package lane, which a compile-only run -# carries only on a package change. +# carries only on a package change. release-build (RELEASE_BUILD_JOB) is the +# package lane's alternative: it runs only on a full suite with release_build, +# exactly when swift-package-tests builds the SDK 15 helper on Blacksmith, so a +# run still has at most three side lanes. APP_HOST_SHARDS = 7 SIDE_LANES = 3 MAX_RUN_JOBS = SIDE_LANES + APP_HOST_SHARDS + 2 @@ -591,13 +594,16 @@ def run_plan(*, macos: str | None, full_suite: str | None, unit_suite: str | Non that does not know) counts one shard, as before. swift-package-tests is a side lane only when package_lane_owned() says it may take the pool; `swift_packages` None (a caller that does not pass it) leaves it out. + release-build is a side lane on a full suite with `release_build` true; + None leaves it out. """ full = flag(macos) and flag(full_suite) side = tuple(key for key, on in (("claude-wrapper", flag(claude_wrapper) or full), ("remote-daemon", flag(remote_daemon)), (SWIFT_PACKAGE_JOB, package_lane_owned( full=full, full_suite=full_suite, swift_packages=swift_packages, - release_build=release_build))) if on) + release_build=release_build)), + (RELEASE_BUILD_JOB, full and flag(release_build))) if on) if not (flag(macos) or flag(cli)): return RunJobs(False, (), side) unit = flag(macos) and flag(unit_suite) and not flag(unit_in_admission) @@ -619,6 +625,11 @@ def run_plan(*, macos: str | None, full_suite: str | None, unit_suite: str | Non # Blacksmith macOS 15 image carries (the minis have Xcode 26.6 alone), so only # a run without that helper build places it on an owned pool. SWIFT_PACKAGE_JOB = "swift-package" +# ci-macos.yml release-build: the unsigned universal Release app nightly signs, +# into its own workspace DerivedData with the lane's Xcode 26.6 (glaeda's hook +# classes it isolated: no GUI, product, canonical root or secrets). It runs +# after admission and swift-package-tests on its own machine. +RELEASE_BUILD_JOB = "release-build" def package_lane_owned(*, full: bool, full_suite: str | None, swift_packages: str | None, @@ -641,12 +652,14 @@ def run_jobs(**routing: str | None) -> int: # Owned placement priority: the heavy compile, then GUI jobs (the longest # Blacksmith queues), then light jobs. GUI jobs need the mini's console # session; CI_PR_POOL_OWNED_GUI=0 keeps them off. -LIGHT_JOBS = ("cli-product", "remote-daemon", "claude-wrapper", SWIFT_PACKAGE_JOB) +# release-build is not light (a 15-minute universal compile), but it follows +# cli-product: it is the side lane that saves the most Blacksmith time. +LIGHT_JOBS = ("cli-product", RELEASE_BUILD_JOB, "remote-daemon", "claude-wrapper", SWIFT_PACKAGE_JOB) # glaeda's canonical-root jobs: admission and every job after it (RunJobs.after: # the shards, tests-build-and-lag, cli-product-tests). The side lanes are not. ROOT_JOBS = "admission, shards, lag, cli-product" # The side lanes (RunJobs.side): light, no canonical root; they take side_runner() on a pool with a root count. -SIDE_LANE_JOBS = ("claude-wrapper", "remote-daemon", SWIFT_PACKAGE_JOB) +SIDE_LANE_JOBS = ("claude-wrapper", "remote-daemon", SWIFT_PACKAGE_JOB, RELEASE_BUILD_JOB) def gui_job(key: str) -> bool: @@ -2022,10 +2035,6 @@ def count_routed(since: str) -> int: cli=env.get("RUN_CLI"), remote_daemon=env.get("RUN_REMOTE_DAEMON"), unit_selectors=env.get("RUN_UNIT_SELECTORS"), swift_packages=env.get("RUN_SWIFT_PACKAGES"), release_build=env.get("RUN_RELEASE_BUILD")) - if on_main: - # The side lanes read the pick only on a pull request (ci.yml's - # claude-wrapper, remote-daemon.yml); main's keep their own route. - plan = dataclasses.replace(plan, side=()) # What an owned pool must have free for the whole run: its owned-eligible # jobs at their peak. gui = (env.get("POOL_OWNED_GUI") or "").strip() != "0" diff --git a/tests/test_ci_pr_runner_pool.py b/tests/test_ci_pr_runner_pool.py index 7ce70f69fad1..7f30128db5a4 100644 --- a/tests/test_ci_pr_runner_pool.py +++ b/tests/test_ci_pr_runner_pool.py @@ -2181,12 +2181,18 @@ def test_a_rerun_of_failed_shards_leaves_the_owned_pool(self): "format(' shard-{0} ', matrix.shard))) && inputs.pr_retry_runner " "|| inputs.pr_shard_runner || needs.macos-compile-admission.outputs.runner }}") wrapper = self.workflow("ci.yml")["jobs"]["claude-wrapper"]["runs-on"] - self.assertIn("github.event_name == 'pull_request' && github.run_attempt == 2 && contains(" + routed = "(github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main')" + self.assertIn(f"{routed} && github.run_attempt == 2 && contains(" "needs.changes.outputs.macos_pr_owned_jobs, ' claude-wrapper ') && " "(needs.changes.outputs.macos_pr_side_runner || needs.changes.outputs.macos_pr_refused_retry_runner) " - "|| github.event_name == 'pull_request' && " + f"|| {routed} && " "(github.run_attempt > 1 || !contains(needs.changes.outputs.macos_pr_owned_jobs, " "' claude-wrapper ')) && needs.changes.outputs.macos_pr_retry_runner", wrapper) + # Main's dispatch takes the side label only where the picker placed the wrapper. + self.assertIn("|| github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main' && " + "contains(needs.changes.outputs.macos_pr_owned_jobs, ' claude-wrapper ') && " + "(needs.changes.outputs.macos_pr_side_runner || needs.changes.outputs.macos_pr_runner) " + "|| vars.CI_PAID_MACOS_OVERFLOW == '1'", wrapper) def test_callers_pass_the_choice(self): jobs = self.workflow("ci.yml")["jobs"] @@ -2205,10 +2211,11 @@ def test_callers_pass_the_choice(self): self.assertEqual(jobs["remote-daemon"]["with"]["pr_side_runner"], "${{ needs.changes.outputs.macos_pr_side_runner }}") self.assertEqual(jobs["macos"]["with"]["pr_side_runner"], "${{ needs.changes.outputs.macos_pr_side_runner }}") - # In ci-macos.yml only swift-package-tests reads it; its root jobs never do. + # In ci-macos.yml only the side lanes read it (swift-package-tests and + # release-build); its root jobs never do. macos_jobs = self.workflow("ci-macos.yml")["jobs"] readers = sorted(name for name, job in macos_jobs.items() if "pr_side_runner" in yaml.safe_dump(job)) - self.assertEqual(readers, ["swift-package-tests"]) + self.assertEqual(readers, ["release-build", "swift-package-tests"]) self.assertEqual(self.workflow("ci.yml")["jobs"]["changes"]["outputs"]["macos_pr_side_runner"], "${{ steps.macos-pool.outputs.side_runner }}") self.assertEqual(jobs["macos"]["with"]["pr_admission_runner"], @@ -2307,7 +2314,8 @@ def test_package_tests_take_an_owned_mac_only_where_the_picker_placed_them(self) # (MACOS_RUNNER_PR) or the retry pool; only the owned label, on the # attempts that read it, when owned_jobs names ' swift-package '. job = self.workflow("ci-macos.yml")["jobs"]["swift-package-tests"] - owned = ("github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository && " + owned = ("(github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository || " + "github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main') && " "contains(inputs.pr_owned_jobs, ' swift-package ') && " "(github.run_attempt == 1 && (inputs.pr_side_runner || inputs.pr_runner) || github.run_attempt == 2 && " "(inputs.pr_side_runner || inputs.pr_refused_retry_runner))") @@ -2333,6 +2341,44 @@ def test_package_tests_take_an_owned_mac_only_where_the_picker_placed_them(self) self.assertIn("inputs.full_suite == 'true' && inputs.release_build == 'true'", step.get("if", ""), step.get("name")) + def test_release_build_takes_an_owned_mac_only_where_the_picker_placed_them(self): + # The universal Release build: the side label when owned_jobs names + # ' release-build ' (same repository or main's dispatch), else the + # macOS 26 variable, and its product-contract mirror says the same. + job = self.workflow("ci-macos.yml")["jobs"]["release-build"] + owned = ("(github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository || " + "github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main') && " + "contains(inputs.pr_owned_jobs, ' release-build ') && " + "(github.run_attempt == 1 && (inputs.pr_side_runner || inputs.pr_runner) || github.run_attempt == 2 && " + "(inputs.pr_side_runner || inputs.pr_refused_retry_runner))") + expected = ("${{ github.repository_owner != 'manaflow-ai' && 'macos-26' || (github.event_name == 'pull_request' && " + "github.event.pull_request.head.repo.full_name != github.repository && 'blacksmith-6vcpu-macos-26' || " + f"{owned} || vars.MACOS_RUNNER_26 || 'blacksmith-6vcpu-macos-26') }}}}") + self.assertEqual(job["runs-on"], expected) + self.assertEqual(job["env"]["CMUX_PRODUCT_RUNNER"], expected) + self.assertEqual(pool.RELEASE_BUILD_JOB, "release-build") + + def test_release_build_is_a_side_lane_of_a_full_suite_with_release_build(self): + full = dict(macos="true", full_suite="true", unit_suite="false", unit_in_admission="false", + claude_wrapper="true", cli="true", remote_daemon="false") + plan = pool.run_plan(**full, swift_packages="true", release_build="true") + # The helper build keeps swift-package-tests on Blacksmith; release-build takes its place. + self.assertEqual(plan.side, ("claude-wrapper", "release-build")) + self.assertNotIn("release-build", pool.run_plan(**full, swift_packages="true", release_build="false").side) + self.assertNotIn("release-build", pool.run_plan(**full, swift_packages="true").side) + self.assertNotIn("release-build", pool.run_plan(**{**full, "full_suite": "false"}, + release_build="true").side) + # Still at most three side lanes, so the most machines a run holds is unchanged. + self.assertLessEqual(pool.run_plan(**{**full, "remote_daemon": "true"}, swift_packages="true", + release_build="true").peak, pool.MAX_RUN_JOBS) + keys, held = pool.place(plan, plan.peak) + self.assertIn("release-build", keys) + self.assertEqual(held, plan.peak) + # Behind the root jobs and cli-product, ahead of the light side lanes. + order = sorted(("claude-wrapper", "remote-daemon", "release-build", "cli-product", "lag"), key=pool.priority) + self.assertEqual(order, ["lag", "cli-product", "release-build", "remote-daemon", "claude-wrapper"]) + self.assertIn("release-build", pool.SIDE_LANE_JOBS) + def test_the_picker_reads_the_package_lane_routing(self): env = next(step for step in self.workflow("ci.yml")["jobs"]["changes"]["steps"] if step.get("id") == "macos-pool")["env"] @@ -2465,7 +2511,7 @@ def test_anything_else_keeps_its_route(self): choice = self.main_choice(self.snap(), **kwargs) self.assertEqual((choice.runner, choice.root_runner), ("", ""), kwargs) - def test_main_routes_the_full_suite_without_its_side_lanes(self): + def test_main_routes_the_full_suite_with_its_side_lanes(self): with tempfile.TemporaryDirectory() as tmp: snapshot = Path(tmp, "snap.json") fresh = self.snap() @@ -2482,10 +2528,11 @@ def test_main_routes_the_full_suite_without_its_side_lanes(self): with unittest.mock.patch("sys.stdout", io.StringIO()): self.assertEqual(pool.main(["--snapshot", str(snapshot)], env), 0) values = dict(line.split("=", 1) for line in out.read_text().splitlines()) + # The nine root jobs at their peak, plus the Claude wrapper and the remote daemon beside them. self.assertEqual((values["runner"], values["persistent"], values["root_runner"], values["jobs"]), - (MINI, "true", ROOT_MINI, "9")) + (MINI, "true", ROOT_MINI, "11")) self.assertEqual(values["owned_jobs"], " admission " + " ".join(f"shard-{index}" for index in range(1, 8)) - + " lag cli-product ") + + " lag cli-product remote-daemon claude-wrapper ") self.assertTrue(values["retry_runner"].startswith("blacksmith-")) # A dispatch on another branch writes the default route. env.update(GITHUB_REF="refs/heads/topic") diff --git a/tests/test_ci_self_hosted_guard.sh b/tests/test_ci_self_hosted_guard.sh index cffc063c031b..e2959b41d154 100755 --- a/tests/test_ci_self_hosted_guard.sh +++ b/tests/test_ci_self_hosted_guard.sh @@ -93,7 +93,7 @@ check_release_build_runner_disk_capacity() { # paid-overflow gate appearing here, which does not belong: MACOS_RUNNER_26 # is the free macOS 26 pool and is read ungated everywhere. See # docs/ci-runners.md for why the gate must not grow to cover it. - if ! awk -v release_runner="runs-on: \${{ github.repository_owner != 'manaflow-ai' && 'macos-26' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository && 'blacksmith-6vcpu-macos-26' || vars.MACOS_RUNNER_26 || 'blacksmith-6vcpu-macos-26') }}" ' + if ! awk -v release_runner="runs-on: \${{ github.repository_owner != 'manaflow-ai' && 'macos-26' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository && 'blacksmith-6vcpu-macos-26' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main') && contains(inputs.pr_owned_jobs, ' release-build ') && (github.run_attempt == 1 && (inputs.pr_side_runner || inputs.pr_runner) || github.run_attempt == 2 && (inputs.pr_side_runner || inputs.pr_refused_retry_runner)) || vars.MACOS_RUNNER_26 || 'blacksmith-6vcpu-macos-26') }}" ' /^ release-build:/ { in_job=1; next } in_job && /^ [^[:space:]#][^:]*:[[:space:]]*(#.*)?$/ { in_job=0 } in_job && index($0, release_runner) { saw_release_runner=1 } @@ -298,7 +298,7 @@ check_release_helper_artifact_from_package_lane() { # The one arm besides the dual-Xcode pool: the side label, else the owned # label, only when the picker placed ' swift-package ' in pr_owned_jobs, # which it does only for a run that skips the SDK 15 helper steps (pr_runner_pool.package_lane_owned()). - if ! awk -v dual_runner="runs-on: \${{ github.repository_owner != 'manaflow-ai' && 'macos-15' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository && 'blacksmith-6vcpu-macos-15' || github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository && contains(inputs.pr_owned_jobs, ' swift-package ') && (github.run_attempt == 1 && (inputs.pr_side_runner || inputs.pr_runner) || github.run_attempt == 2 && (inputs.pr_side_runner || inputs.pr_refused_retry_runner)) || vars.CI_PAID_MACOS_OVERFLOW == '1' && vars.MACOS_RUNNER_DUAL_XCODE || 'blacksmith-6vcpu-macos-15') }}" ' + if ! awk -v dual_runner="runs-on: \${{ github.repository_owner != 'manaflow-ai' && 'macos-15' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository && 'blacksmith-6vcpu-macos-15' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main') && contains(inputs.pr_owned_jobs, ' swift-package ') && (github.run_attempt == 1 && (inputs.pr_side_runner || inputs.pr_runner) || github.run_attempt == 2 && (inputs.pr_side_runner || inputs.pr_refused_retry_runner)) || vars.CI_PAID_MACOS_OVERFLOW == '1' && vars.MACOS_RUNNER_DUAL_XCODE || 'blacksmith-6vcpu-macos-15') }}" ' /^ swift-package-tests:/ { in_job=1; next } in_job && /^ [^[:space:]#][^:]*:[[:space:]]*(#.*)?$/ { in_job=0 } @@ -1349,13 +1349,20 @@ GUARDED = ( "github.event_name == 'pull_request' && (needs.changes.outputs.macos_pr_side_runner" " || needs.changes.outputs.macos_pr_runner || vars.MACOS_RUNNER_PR || 'blacksmith-6vcpu-macos-15')", # Attempt 2 of a refused owned job: the owned pool once more. - "github.event_name == 'pull_request' && github.run_attempt == 2 && contains(needs.changes.outputs.macos_pr_owned_jobs," + "(github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main')" + " && github.run_attempt == 2 && contains(needs.changes.outputs.macos_pr_owned_jobs," " ' claude-wrapper ') && (needs.changes.outputs.macos_pr_side_runner" " || needs.changes.outputs.macos_pr_refused_retry_runner)", # A re-run of failed jobs on an owned-pool run, or a job the picker did not # place on the owned pool: the Blacksmith pool the picker named for it. - "github.event_name == 'pull_request' && (github.run_attempt > 1 || !contains(needs.changes.outputs.macos_pr_owned_jobs," + "(github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main')" + " && (github.run_attempt > 1 || !contains(needs.changes.outputs.macos_pr_owned_jobs," " ' claude-wrapper ')) && needs.changes.outputs.macos_pr_retry_runner", + # The full-suite dispatch on main (code already on main, which + # pr_runner_pool.py places like a pull request): only the job it placed. + "github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main' && contains(" + "needs.changes.outputs.macos_pr_owned_jobs, ' claude-wrapper ') && (needs.changes.outputs.macos_pr_side_runner" + " || needs.changes.outputs.macos_pr_runner)", ) From 3a6d7cb777e1f74f29388a34e59c9265b12b93ae Mon Sep 17 00:00:00 2001 From: teamleaderleo Date: Mon, 28 Sep 2026 00:08:32 -0400 Subject: [PATCH 2/2] ci: keep main re-runs and the light pool off release-build's owned route - Main's dispatch reads the pick on attempt 1 only for the side lanes (claude-wrapper, remote-daemon, swift-package-tests, release-build), like its root jobs: the queue janitor charges no owned machine to a re-run of main, so a manual re-run there must not take one. - The light pool's own pick drops release-build from its placement, so the universal Release compile never lands on a light side runner. - release-build's CMUX_CI_XCODE_APP follows its runs-on: the lane pin on the owned label, the macOS 26 pin elsewhere. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/ci-macos.yml | 19 +++++++++++-------- .github/workflows/ci.yml | 2 +- .github/workflows/remote-daemon.yml | 2 +- docs/ci-runners.md | 2 +- scripts/ci/pr_runner_pool.py | 3 +++ tests/test_ci_change_areas.py | 14 ++++++++------ tests/test_ci_pr_runner_pool.py | 28 ++++++++++++++++++---------- tests/test_ci_release_sdk_lane.sh | 4 ++-- tests/test_ci_self_hosted_guard.sh | 9 ++++----- 9 files changed, 49 insertions(+), 34 deletions(-) diff --git a/.github/workflows/ci-macos.yml b/.github/workflows/ci-macos.yml index 94710114f2b0..ab439486f0ff 100644 --- a/.github/workflows/ci-macos.yml +++ b/.github/workflows/ci-macos.yml @@ -3045,12 +3045,12 @@ jobs: # capacity ledger fits the light class; that mini checks out the commit # itself and streams the log and exit code back. PACKAGE_TESTS_VIA_STEP # below restates the runs-on branch for the steps. - runs-on: ${{ github.repository_owner != 'manaflow-ai' && 'macos-15' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository && 'blacksmith-6vcpu-macos-15' || github.event_name == 'pull_request' && !(inputs.full_suite == 'true' && inputs.release_build == 'true') && vars.CI_SWIFT_PACKAGE_TESTS_STEP_GATEWAY || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main') && contains(inputs.pr_owned_jobs, ' swift-package ') && ((github.run_attempt == 1 || github.triggering_actor != 'github-actions[bot]') && (inputs.pr_side_runner || inputs.pr_runner)) || vars.CI_PAID_MACOS_OVERFLOW == '1' && vars.MACOS_RUNNER_DUAL_XCODE || 'blacksmith-6vcpu-macos-15') }} + runs-on: ${{ github.repository_owner != 'manaflow-ai' && 'macos-15' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository && 'blacksmith-6vcpu-macos-15' || github.event_name == 'pull_request' && !(inputs.full_suite == 'true' && inputs.release_build == 'true') && vars.CI_SWIFT_PACKAGE_TESTS_STEP_GATEWAY || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository && (github.run_attempt == 1 || github.triggering_actor != 'github-actions[bot]') || github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main' && github.run_attempt == 1) && contains(inputs.pr_owned_jobs, ' swift-package ') && (inputs.pr_side_runner || inputs.pr_runner) || vars.CI_PAID_MACOS_OVERFLOW == '1' && vars.MACOS_RUNNER_DUAL_XCODE || 'blacksmith-6vcpu-macos-15') }} timeout-minutes: 60 env: # The owned label's Xcode (the lane pin) exactly when runs-on took it; # the pool picker's Wiring tests keep the two conditions equal. - CMUX_CI_XCODE_APP: ${{ (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main') && contains(inputs.pr_owned_jobs, ' swift-package ') && ((github.run_attempt == 1 || github.triggering_actor != 'github-actions[bot]') && (inputs.pr_side_runner || inputs.pr_runner)) && (inputs.pr_xcode_app || vars.CMUX_CI_XCODE_APP_PR) || vars.CMUX_CI_XCODE_APP_MACOS_15 }} + CMUX_CI_XCODE_APP: ${{ (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository && (github.run_attempt == 1 || github.triggering_actor != 'github-actions[bot]') || github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main' && github.run_attempt == 1) && contains(inputs.pr_owned_jobs, ' swift-package ') && (inputs.pr_side_runner || inputs.pr_runner) && (inputs.pr_xcode_app || vars.CMUX_CI_XCODE_APP_PR) || vars.CMUX_CI_XCODE_APP_MACOS_15 }} CMUX_CI_HELPER_XCODE_APP: ${{ vars.CMUX_CI_HELPER_XCODE_APP_MACOS_15 }} CMUX_CI_REQUIRED_MACOS_SDK_MAJOR: "26" PACKAGE_TESTS_VIA_STEP: ${{ github.repository_owner == 'manaflow-ai' && github.event.pull_request.head.repo.full_name == github.repository && vars.CI_SWIFT_PACKAGE_TESTS_STEP_GATEWAY != '' && github.event_name == 'pull_request' && !(inputs.full_suite == 'true' && inputs.release_build == 'true') && '1' || '0' }} @@ -3824,22 +3824,25 @@ jobs: # variable names that image, not this lane. A same-repository pull request # or main's full-suite dispatch takes the owned side label when the picker # placed ' release-build ' in pr_owned_jobs (pr_runner_pool.RELEASE_BUILD_JOB) - # on attempt 1 or a manual re-run: the same Xcode 26.6, and glaeda's hook - # classes the job isolated. A bot re-run (ci-owned-pool-rescue.yml) takes - # the macOS 26 variable. The picker never gives it the light side runners, + # on attempt 1 or a manual re-run of a pull request (attempt 1 only on + # main, whose re-runs the janitor charges no owned machine), with the + # lane's Xcode; glaeda's hook classes the job isolated. A bot re-run + # (ci-owned-pool-rescue.yml) takes the macOS 26 variable. The picker never + # gives it the light pool's side runners, # and swift-package-tests (the only lane ci.yml hands the light label # through pr_side_runner) never shares a run with it. - runs-on: ${{ github.repository_owner != 'manaflow-ai' && 'macos-26' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository && 'blacksmith-6vcpu-macos-26' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main') && contains(inputs.pr_owned_jobs, ' release-build ') && ((github.run_attempt == 1 || github.triggering_actor != 'github-actions[bot]') && (inputs.pr_side_runner || inputs.pr_runner)) || vars.MACOS_RUNNER_26 || 'blacksmith-6vcpu-macos-26') }} + runs-on: ${{ github.repository_owner != 'manaflow-ai' && 'macos-26' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository && 'blacksmith-6vcpu-macos-26' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository && (github.run_attempt == 1 || github.triggering_actor != 'github-actions[bot]') || github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main' && github.run_attempt == 1) && contains(inputs.pr_owned_jobs, ' release-build ') && (inputs.pr_side_runner || inputs.pr_runner) || vars.MACOS_RUNNER_26 || 'blacksmith-6vcpu-macos-26') }} timeout-minutes: 60 permissions: actions: read attestations: read contents: read env: - CMUX_CI_XCODE_APP: ${{ vars.CMUX_CI_XCODE_APP_MACOS_26 }} + # The owned label's Xcode exactly when runs-on took it, as swift-package-tests. + CMUX_CI_XCODE_APP: ${{ (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository && (github.run_attempt == 1 || github.triggering_actor != 'github-actions[bot]') || github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main' && github.run_attempt == 1) && contains(inputs.pr_owned_jobs, ' release-build ') && (inputs.pr_side_runner || inputs.pr_runner) && (inputs.pr_xcode_app || vars.CMUX_CI_XCODE_APP_PR) || vars.CMUX_CI_XCODE_APP_MACOS_26 }} CMUX_CI_REQUIRED_MACOS_SDK_MAJOR: "26" CMUX_SKIP_ZIG_BUILD: "1" - CMUX_PRODUCT_RUNNER: ${{ github.repository_owner != 'manaflow-ai' && 'macos-26' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository && 'blacksmith-6vcpu-macos-26' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main') && contains(inputs.pr_owned_jobs, ' release-build ') && ((github.run_attempt == 1 || github.triggering_actor != 'github-actions[bot]') && (inputs.pr_side_runner || inputs.pr_runner)) || vars.MACOS_RUNNER_26 || 'blacksmith-6vcpu-macos-26') }} + CMUX_PRODUCT_RUNNER: ${{ github.repository_owner != 'manaflow-ai' && 'macos-26' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository && 'blacksmith-6vcpu-macos-26' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository && (github.run_attempt == 1 || github.triggering_actor != 'github-actions[bot]') || github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main' && github.run_attempt == 1) && contains(inputs.pr_owned_jobs, ' release-build ') && (inputs.pr_side_runner || inputs.pr_runner) || vars.MACOS_RUNNER_26 || 'blacksmith-6vcpu-macos-26') }} CMUX_RELEASE_SOURCE_REVISION: ${{ github.event.pull_request.head.sha || github.sha }} steps: - name: Clear stale git locks (self-hosted reused workspace) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d3964af4b0ff..da7003c33062 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1190,7 +1190,7 @@ jobs: name: Claude wrapper regressions needs: [changes, static-preflight] if: ${{ !cancelled() && needs.changes.result == 'success' && needs.static-preflight.result == 'success' && (needs.changes.outputs.claude_wrapper == 'true' || (needs.changes.outputs.macos == 'true' && needs.changes.outputs.full_suite == 'true')) }} - runs-on: ${{ github.repository_owner != 'manaflow-ai' && 'macos-26' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository && (startsWith(needs.changes.outputs.macos_pr_runner, 'blacksmith-') && needs.changes.outputs.macos_pr_runner || 'blacksmith-6vcpu-macos-15') || github.event_name == 'pull_request' && (github.run_attempt > 1 && github.triggering_actor == 'github-actions[bot]' || !contains(needs.changes.outputs.macos_pr_owned_jobs, ' claude-wrapper ')) && needs.changes.outputs.macos_pr_retry_runner || github.event_name == 'pull_request' && ((contains(needs.changes.outputs.macos_pr_light_side_jobs, ' claude-wrapper ') && needs.changes.outputs.macos_pr_light_side_runner || needs.changes.outputs.macos_pr_side_runner) || needs.changes.outputs.macos_pr_runner || vars.MACOS_RUNNER_PR || 'blacksmith-6vcpu-macos-15') || github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main' && contains(needs.changes.outputs.macos_pr_owned_jobs, ' claude-wrapper ') && (github.run_attempt == 1 || github.triggering_actor != 'github-actions[bot]') && (needs.changes.outputs.macos_pr_side_runner || needs.changes.outputs.macos_pr_runner) || vars.CI_PAID_MACOS_OVERFLOW == '1' && vars.MACOS_RUNNER_15 || 'blacksmith-6vcpu-macos-15') }} + runs-on: ${{ github.repository_owner != 'manaflow-ai' && 'macos-26' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository && (startsWith(needs.changes.outputs.macos_pr_runner, 'blacksmith-') && needs.changes.outputs.macos_pr_runner || 'blacksmith-6vcpu-macos-15') || github.event_name == 'pull_request' && (github.run_attempt > 1 && github.triggering_actor == 'github-actions[bot]' || !contains(needs.changes.outputs.macos_pr_owned_jobs, ' claude-wrapper ')) && needs.changes.outputs.macos_pr_retry_runner || github.event_name == 'pull_request' && ((contains(needs.changes.outputs.macos_pr_light_side_jobs, ' claude-wrapper ') && needs.changes.outputs.macos_pr_light_side_runner || needs.changes.outputs.macos_pr_side_runner) || needs.changes.outputs.macos_pr_runner || vars.MACOS_RUNNER_PR || 'blacksmith-6vcpu-macos-15') || github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main' && github.run_attempt == 1 && contains(needs.changes.outputs.macos_pr_owned_jobs, ' claude-wrapper ') && (needs.changes.outputs.macos_pr_side_runner || needs.changes.outputs.macos_pr_runner) || vars.CI_PAID_MACOS_OVERFLOW == '1' && vars.MACOS_RUNNER_15 || 'blacksmith-6vcpu-macos-15') }} # Normally 1-2 minutes, but it spawns hundreds of short bash, perl and node # processes, so a mini saturated by a compile beside it stretches it: # 120-527 s at a mean load of 36-100 on 14 cores (glaeda-cmux-jobs.jsonl, diff --git a/.github/workflows/remote-daemon.yml b/.github/workflows/remote-daemon.yml index 0eb19f97a20f..8512de9be7d0 100644 --- a/.github/workflows/remote-daemon.yml +++ b/.github/workflows/remote-daemon.yml @@ -114,7 +114,7 @@ jobs: # contended macOS 26 pool. A direct push or dispatch of this workflow (not # ci.yml's call) is a side lane: the minis on attempt 1, Blacksmith on # any retry. - runs-on: ${{ github.repository_owner != 'manaflow-ai' && 'macos-26' || github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository && (startsWith(inputs.pr_runner, 'blacksmith-') && inputs.pr_runner || 'blacksmith-6vcpu-macos-15') || github.event_name == 'pull_request' && ((github.run_attempt > 1 && github.triggering_actor == 'github-actions[bot]' || !contains(inputs.pr_owned_jobs, ' remote-daemon ')) && inputs.pr_retry_runner || inputs.pr_side_runner || inputs.pr_runner || vars.MACOS_RUNNER_PR || 'blacksmith-6vcpu-macos-15') || github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main' && contains(inputs.pr_owned_jobs, ' remote-daemon ') && (github.run_attempt == 1 || github.triggering_actor != 'github-actions[bot]') && (inputs.pr_side_runner || inputs.pr_runner) || contains(github.workflow_ref, '/.github/workflows/remote-daemon.yml@') && vars.CI_PR_POOL_OWNED == '1' && contains(fromJSON('["pull_request","push","schedule","workflow_dispatch"]'), github.event_name) && (github.run_attempt == 1 && (vars.CI_LIGHT_LANE_RUNNER || vars.CI_SIDE_LANE_RUNNER)) || vars.CI_PAID_MACOS_OVERFLOW == '1' && vars.MACOS_RUNNER_15 || 'blacksmith-6vcpu-macos-15' }} + runs-on: ${{ github.repository_owner != 'manaflow-ai' && 'macos-26' || github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository && (startsWith(inputs.pr_runner, 'blacksmith-') && inputs.pr_runner || 'blacksmith-6vcpu-macos-15') || github.event_name == 'pull_request' && ((github.run_attempt > 1 && github.triggering_actor == 'github-actions[bot]' || !contains(inputs.pr_owned_jobs, ' remote-daemon ')) && inputs.pr_retry_runner || inputs.pr_side_runner || inputs.pr_runner || vars.MACOS_RUNNER_PR || 'blacksmith-6vcpu-macos-15') || github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main' && github.run_attempt == 1 && contains(inputs.pr_owned_jobs, ' remote-daemon ') && (inputs.pr_side_runner || inputs.pr_runner) || contains(github.workflow_ref, '/.github/workflows/remote-daemon.yml@') && vars.CI_PR_POOL_OWNED == '1' && contains(fromJSON('["pull_request","push","schedule","workflow_dispatch"]'), github.event_name) && (github.run_attempt == 1 && (vars.CI_LIGHT_LANE_RUNNER || vars.CI_SIDE_LANE_RUNNER)) || vars.CI_PAID_MACOS_OVERFLOW == '1' && vars.MACOS_RUNNER_15 || 'blacksmith-6vcpu-macos-15' }} timeout-minutes: 15 steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 diff --git a/docs/ci-runners.md b/docs/ci-runners.md index ad519f0eea6d..c3f80eeef2a1 100644 --- a/docs/ci-runners.md +++ b/docs/ci-runners.md @@ -762,7 +762,7 @@ and the retired self-hosted fleet failed `codesign` with | `app-host-test-rerun.yml` `rerun` | `CI_SIDE_LANE_RUNNER` for macOS 26 products, attempt 1 only; macOS 15 products on Blacksmith macOS 15 | gui; it takes the product's root itself (`glaeda-canonical-root take`) | | `cmux-tui.yml` macOS `lint`, `test`, `cdp-browser-smoke` | `CI_SIDE_LANE_RUNNER`, attempt 1 only | isolated (glaeda classes them by workflow and id) | | `cmux-tui.yml` release-path dogfood `build` (`cmux-tui-build-package.yml`) | Blacksmith macOS 15 | the release packaging build, shared with the release and nightly callers; its matrix is planned once, so a re-run could not leave the minis | -| `ci-macos.yml` `release-build` | owned side lane via the picker (`release-build`, the picked pool's side label; the light side runners ahead of the pick never take it), pull requests and main's full-suite dispatch, attempt 1 or a manual re-run; else `MACOS_RUNNER_26` | isolated: an unsigned universal Release into its own DerivedData, Xcode 26.6 | +| `ci-macos.yml` `release-build` | owned side lane via the picker (`release-build`, the picked std pool's side label, never the light pool), pull requests (attempt 1 or a manual re-run) and main's full-suite dispatch (attempt 1); else `MACOS_RUNNER_26` | isolated: an unsigned universal Release into its own DerivedData, Xcode 26.6 | | `reload-build.yml` `build` | `CI_SIDE_LANE_RUNNER` for a macOS build when the runner input is `auto` or `blacksmith-6vcpu-macos-26`, attempt 1 only (iOS builds take Blacksmith); any other label as given | isolated: a Debug build into the workspace | | low-volume GUI dispatches: `test-macos-suite`, `tmux-corpus`, `perf-activation`, command palette benchmarks | Blacksmith or the caller's runner input | 0 to 1 runs a week; they drive the app in the runner's own session, which a mini's runner lacks (E2E and the rerun use its console session) | | `iroh-release-gate` version skew | Blacksmith macOS 15 | pins the macOS 15 pool's Xcode 26.3 | diff --git a/scripts/ci/pr_runner_pool.py b/scripts/ci/pr_runner_pool.py index 2291690b4e37..0a6c72ac823e 100644 --- a/scripts/ci/pr_runner_pool.py +++ b/scripts/ci/pr_runner_pool.py @@ -2307,6 +2307,9 @@ def count_routed(since: str) -> int: # run takes retry_runner. The marker's jobs are the owned machines held. owned_slots = slots(env.get("OWNED_SLOTS"), pr_xcode_app) gui_label_out = gui_runner(choice, owned_slots) + if choice.runner.startswith(f"glaeda-{LIGHT_CLASS}-"): + # The light pool's own pick places no universal Release compile; it keeps MACOS_RUNNER_26. + plan = dataclasses.replace(plan, side=tuple(key for key in plan.side if key != RELEASE_BUILD_JOB)) owned_jobs, held = (place(plan, choice.owned_budget, gui, choice.root_budget if choice.root_runner else None, bool(gui_label_out)) if persistent(choice.runner) else ((), plan.peak)) diff --git a/tests/test_ci_change_areas.py b/tests/test_ci_change_areas.py index 61ca50d29011..045802758787 100755 --- a/tests/test_ci_change_areas.py +++ b/tests/test_ci_change_areas.py @@ -6247,11 +6247,10 @@ def test_macos_jobs_use_lane_specific_xcode_pin_vars() -> None: package_block = workflow_job_block("swift-package-tests", MACOS_WORKFLOW) assert "vars.MACOS_RUNNER_PR" not in package_block assert ( - "CMUX_CI_XCODE_APP: ${{ (github.event_name == 'pull_request' && " - "github.event.pull_request.head.repo.full_name == github.repository || " - "github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main') && " - "contains(inputs.pr_owned_jobs, ' swift-package ') && " - "((github.run_attempt == 1 || github.triggering_actor != 'github-actions[bot]') && (inputs.pr_side_runner || inputs.pr_runner)) && " + "CMUX_CI_XCODE_APP: ${{ (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository && " + "(github.run_attempt == 1 || github.triggering_actor != 'github-actions[bot]') || " + "github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main' && github.run_attempt == 1) && " + "contains(inputs.pr_owned_jobs, ' swift-package ') && (inputs.pr_side_runner || inputs.pr_runner) && " "(inputs.pr_xcode_app || vars.CMUX_CI_XCODE_APP_PR) || vars.CMUX_CI_XCODE_APP_MACOS_15 }}" ) in package_block assert ( @@ -6261,7 +6260,10 @@ def test_macos_jobs_use_lane_specific_xcode_pin_vars() -> None: assert 'CMUX_CI_REQUIRED_MACOS_SDK_MAJOR: "26"' in package_block release_block = workflow_job_block("release-build", MACOS_WORKFLOW) - assert "CMUX_CI_XCODE_APP: ${{ vars.CMUX_CI_XCODE_APP_MACOS_26 }}" in release_block + assert ( + "CMUX_CI_XCODE_APP: ${{ (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository && (github.run_attempt == 1 || github.triggering_actor != 'github-actions[bot]') || github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main' && github.run_attempt == 1) && contains(inputs.pr_owned_jobs, ' release-build ') && (inputs.pr_side_runner || inputs.pr_runner) " + "&& (inputs.pr_xcode_app || vars.CMUX_CI_XCODE_APP_PR) || vars.CMUX_CI_XCODE_APP_MACOS_26 }}" + ) in release_block assert 'CMUX_CI_REQUIRED_MACOS_SDK_MAJOR: "26"' in release_block diff --git a/tests/test_ci_pr_runner_pool.py b/tests/test_ci_pr_runner_pool.py index 0ba74595af20..8d58ae3abf37 100644 --- a/tests/test_ci_pr_runner_pool.py +++ b/tests/test_ci_pr_runner_pool.py @@ -2078,6 +2078,10 @@ def test_release_build_stays_with_the_picked_pool(self): self.assertIn(" release-build ", values["owned_jobs"]) self.assertEqual(pool.light_side_lanes(pool.RunJobs(False, (), ("release-build",)), idle, {LIGHT: 4, light_root: 2}, PR_XCODE), ("", ())) + # The light pool's own pick leaves it to MACOS_RUNNER_26 too. + values = self.outputs(idle, slots=slots, extra={**lanes, "POOL_ORDER": LIGHT}) + self.assertEqual(values["runner"], LIGHT) + self.assertNotIn(" release-build ", values["owned_jobs"]) def test_light_side_lanes_on_the_light_pick_count_in_its_peak(self): # The janitor takes the side lanes off the marker's peak for the root share, so the peak holds them. @@ -2420,9 +2424,10 @@ def test_a_rerun_of_failed_shards_leaves_the_owned_pool(self): "(github.run_attempt > 1 && github.triggering_actor == 'github-actions[bot]' || !contains(needs.changes.outputs.macos_pr_owned_jobs, " "' claude-wrapper ')) && needs.changes.outputs.macos_pr_retry_runner", wrapper) # Main's dispatch takes the side label only where the picker placed the wrapper. + # Attempt 1 only: a re-run of main's dispatch takes no owned machine (the janitor charges none). self.assertIn("|| github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main' && " + "github.run_attempt == 1 && " "contains(needs.changes.outputs.macos_pr_owned_jobs, ' claude-wrapper ') && " - "(github.run_attempt == 1 || github.triggering_actor != 'github-actions[bot]') && " "(needs.changes.outputs.macos_pr_side_runner || needs.changes.outputs.macos_pr_runner) " "|| vars.CI_PAID_MACOS_OVERFLOW == '1'", wrapper) @@ -2561,10 +2566,10 @@ def test_package_tests_take_an_owned_mac_only_where_the_picker_placed_them(self) # (MACOS_RUNNER_PR) or the retry pool; only the owned label, on the # attempts that read it, when owned_jobs names ' swift-package '. job = self.workflow("ci-macos.yml")["jobs"]["swift-package-tests"] - owned = ("(github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository || " - "github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main') && " - "contains(inputs.pr_owned_jobs, ' swift-package ') && " - "((github.run_attempt == 1 || github.triggering_actor != 'github-actions[bot]') && (inputs.pr_side_runner || inputs.pr_runner))") + owned = ("(github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository && " + "(github.run_attempt == 1 || github.triggering_actor != 'github-actions[bot]') || " + "github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main' && github.run_attempt == 1) && " + "contains(inputs.pr_owned_jobs, ' swift-package ') && (inputs.pr_side_runner || inputs.pr_runner)") self.assertEqual(job["runs-on"], ( "${{ github.repository_owner != 'manaflow-ai' && 'macos-15' || (github.event_name == 'pull_request' && " "github.event.pull_request.head.repo.full_name != github.repository && 'blacksmith-6vcpu-macos-15' || " @@ -2595,16 +2600,19 @@ def test_release_build_takes_an_owned_mac_only_where_the_picker_placed_them(self # ' release-build ' (same repository or main's dispatch), else the # macOS 26 variable, and its product-contract mirror says the same. job = self.workflow("ci-macos.yml")["jobs"]["release-build"] - owned = ("(github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository || " - "github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main') && " - "contains(inputs.pr_owned_jobs, ' release-build ') && " - "((github.run_attempt == 1 || github.triggering_actor != 'github-actions[bot]') && " - "(inputs.pr_side_runner || inputs.pr_runner))") + owned = ("(github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository && " + "(github.run_attempt == 1 || github.triggering_actor != 'github-actions[bot]') || " + "github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main' && github.run_attempt == 1) && " + "contains(inputs.pr_owned_jobs, ' release-build ') && (inputs.pr_side_runner || inputs.pr_runner)") expected = ("${{ github.repository_owner != 'manaflow-ai' && 'macos-26' || (github.event_name == 'pull_request' && " "github.event.pull_request.head.repo.full_name != github.repository && 'blacksmith-6vcpu-macos-26' || " f"{owned} || vars.MACOS_RUNNER_26 || 'blacksmith-6vcpu-macos-26') }}}}") self.assertEqual(job["runs-on"], expected) self.assertEqual(job["env"]["CMUX_PRODUCT_RUNNER"], expected) + # The Xcode follows the same condition: the lane pin on the owned label. + self.assertEqual(job["env"]["CMUX_CI_XCODE_APP"], + f"${{{{ {owned} && (inputs.pr_xcode_app || vars.CMUX_CI_XCODE_APP_PR) " + "|| vars.CMUX_CI_XCODE_APP_MACOS_26 }}") self.assertEqual(pool.RELEASE_BUILD_JOB, "release-build") def test_release_build_is_a_side_lane_of_a_full_suite_with_release_build(self): diff --git a/tests/test_ci_release_sdk_lane.sh b/tests/test_ci_release_sdk_lane.sh index 643227747f98..fd0e1248df9b 100755 --- a/tests/test_ci_release_sdk_lane.sh +++ b/tests/test_ci_release_sdk_lane.sh @@ -44,7 +44,7 @@ require_job_contains \ require_job_contains \ "$CI_FILE" \ "release-build" \ - 'runs-on: ${{ github.repository_owner != '\''manaflow-ai'\'' && '\''macos-26'\'' || (github.event_name == '\''pull_request'\'' && github.event.pull_request.head.repo.full_name != github.repository && '\''blacksmith-6vcpu-macos-26'\'' || (github.event_name == '\''pull_request'\'' && github.event.pull_request.head.repo.full_name == github.repository || github.event_name == '\''workflow_dispatch'\'' && github.ref == '\''refs/heads/main'\'') && contains(inputs.pr_owned_jobs, '\'' release-build '\'') && ((github.run_attempt == 1 || github.triggering_actor != '\''github-actions[bot]'\'') && (inputs.pr_side_runner || inputs.pr_runner)) || vars.MACOS_RUNNER_26 || '\''blacksmith-6vcpu-macos-26'\'') }}' \ + 'runs-on: ${{ github.repository_owner != '\''manaflow-ai'\'' && '\''macos-26'\'' || (github.event_name == '\''pull_request'\'' && github.event.pull_request.head.repo.full_name != github.repository && '\''blacksmith-6vcpu-macos-26'\'' || (github.event_name == '\''pull_request'\'' && github.event.pull_request.head.repo.full_name == github.repository && (github.run_attempt == 1 || github.triggering_actor != '\''github-actions[bot]'\'') || github.event_name == '\''workflow_dispatch'\'' && github.ref == '\''refs/heads/main'\'' && github.run_attempt == 1) && contains(inputs.pr_owned_jobs, '\'' release-build '\'') && (inputs.pr_side_runner || inputs.pr_runner) || vars.MACOS_RUNNER_26 || '\''blacksmith-6vcpu-macos-26'\'') }}' \ "CI release-build must use GitHub-hosted macOS on forks, the picked owned side lane where placed, and the macOS 26 runner variable upstream" for workflow in "$CI_FILE" "$RELEASE_FILE"; do @@ -78,7 +78,7 @@ swift_package_section="$(job_section "$CI_FILE" "swift-package-tests")" # ' swift-package ' on an owned Mac, which the # picker does only for a run that builds no helper (package_lane_owned()), # and the opt-in build-fleet gateway (hq#794), also only without the helper. -expected_runs_on='runs-on: ${{ github.repository_owner != '\''manaflow-ai'\'' && '\''macos-15'\'' || (github.event_name == '\''pull_request'\'' && github.event.pull_request.head.repo.full_name != github.repository && '\''blacksmith-6vcpu-macos-15'\'' || github.event_name == '\''pull_request'\'' && !(inputs.full_suite == '\''true'\'' && inputs.release_build == '\''true'\'') && vars.CI_SWIFT_PACKAGE_TESTS_STEP_GATEWAY || (github.event_name == '\''pull_request'\'' && github.event.pull_request.head.repo.full_name == github.repository || github.event_name == '\''workflow_dispatch'\'' && github.ref == '\''refs/heads/main'\'') && contains(inputs.pr_owned_jobs, '\'' swift-package '\'') && ((github.run_attempt == 1 || github.triggering_actor != '\''github-actions[bot]'\'') && (inputs.pr_side_runner || inputs.pr_runner)) || vars.CI_PAID_MACOS_OVERFLOW == '\''1'\'' && vars.MACOS_RUNNER_DUAL_XCODE || '\''blacksmith-6vcpu-macos-15'\'') }}' +expected_runs_on='runs-on: ${{ github.repository_owner != '\''manaflow-ai'\'' && '\''macos-15'\'' || (github.event_name == '\''pull_request'\'' && github.event.pull_request.head.repo.full_name != github.repository && '\''blacksmith-6vcpu-macos-15'\'' || github.event_name == '\''pull_request'\'' && !(inputs.full_suite == '\''true'\'' && inputs.release_build == '\''true'\'') && vars.CI_SWIFT_PACKAGE_TESTS_STEP_GATEWAY || (github.event_name == '\''pull_request'\'' && github.event.pull_request.head.repo.full_name == github.repository && (github.run_attempt == 1 || github.triggering_actor != '\''github-actions[bot]'\'') || github.event_name == '\''workflow_dispatch'\'' && github.ref == '\''refs/heads/main'\'' && github.run_attempt == 1) && contains(inputs.pr_owned_jobs, '\'' swift-package '\'') && (inputs.pr_side_runner || inputs.pr_runner) || vars.CI_PAID_MACOS_OVERFLOW == '\''1'\'' && vars.MACOS_RUNNER_DUAL_XCODE || '\''blacksmith-6vcpu-macos-15'\'') }}' if [[ "$swift_package_section" != *"$expected_runs_on"* ]]; then echo "FAIL: CI swift-package-tests must use the dual-Xcode runner lane on every event" >&2 exit 1 diff --git a/tests/test_ci_self_hosted_guard.sh b/tests/test_ci_self_hosted_guard.sh index 4e3cb9c3e866..c849bcc0aaac 100755 --- a/tests/test_ci_self_hosted_guard.sh +++ b/tests/test_ci_self_hosted_guard.sh @@ -94,7 +94,7 @@ check_release_build_runner_disk_capacity() { # paid-overflow gate appearing here, which does not belong: MACOS_RUNNER_26 # is the free macOS 26 pool and is read ungated everywhere. See # docs/ci-runners.md for why the gate must not grow to cover it. - if ! awk -v release_runner="runs-on: \${{ github.repository_owner != 'manaflow-ai' && 'macos-26' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository && 'blacksmith-6vcpu-macos-26' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main') && contains(inputs.pr_owned_jobs, ' release-build ') && ((github.run_attempt == 1 || github.triggering_actor != 'github-actions[bot]') && (inputs.pr_side_runner || inputs.pr_runner)) || vars.MACOS_RUNNER_26 || 'blacksmith-6vcpu-macos-26') }}" ' + if ! awk -v release_runner="runs-on: \${{ github.repository_owner != 'manaflow-ai' && 'macos-26' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository && 'blacksmith-6vcpu-macos-26' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository && (github.run_attempt == 1 || github.triggering_actor != 'github-actions[bot]') || github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main' && github.run_attempt == 1) && contains(inputs.pr_owned_jobs, ' release-build ') && (inputs.pr_side_runner || inputs.pr_runner) || vars.MACOS_RUNNER_26 || 'blacksmith-6vcpu-macos-26') }}" ' /^ release-build:/ { in_job=1; next } in_job && /^ [^[:space:]#][^:]*:[[:space:]]*(#.*)?$/ { in_job=0 } in_job && index($0, release_runner) { saw_release_runner=1 } @@ -300,7 +300,7 @@ check_release_helper_artifact_from_package_lane() { # label, only when the picker placed ' swift-package ' in pr_owned_jobs, # which it does only for a run that skips the SDK 15 helper steps (pr_runner_pool.package_lane_owned()). # The opt-in build-fleet gateway (hq#794) likewise takes only a run without the helper. - if ! awk -v dual_runner="runs-on: \${{ github.repository_owner != 'manaflow-ai' && 'macos-15' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository && 'blacksmith-6vcpu-macos-15' || github.event_name == 'pull_request' && !(inputs.full_suite == 'true' && inputs.release_build == 'true') && vars.CI_SWIFT_PACKAGE_TESTS_STEP_GATEWAY || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main') && contains(inputs.pr_owned_jobs, ' swift-package ') && ((github.run_attempt == 1 || github.triggering_actor != 'github-actions[bot]') && (inputs.pr_side_runner || inputs.pr_runner)) || vars.CI_PAID_MACOS_OVERFLOW == '1' && vars.MACOS_RUNNER_DUAL_XCODE || 'blacksmith-6vcpu-macos-15') }}" ' + if ! awk -v dual_runner="runs-on: \${{ github.repository_owner != 'manaflow-ai' && 'macos-15' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository && 'blacksmith-6vcpu-macos-15' || github.event_name == 'pull_request' && !(inputs.full_suite == 'true' && inputs.release_build == 'true') && vars.CI_SWIFT_PACKAGE_TESTS_STEP_GATEWAY || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository && (github.run_attempt == 1 || github.triggering_actor != 'github-actions[bot]') || github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main' && github.run_attempt == 1) && contains(inputs.pr_owned_jobs, ' swift-package ') && (inputs.pr_side_runner || inputs.pr_runner) || vars.CI_PAID_MACOS_OVERFLOW == '1' && vars.MACOS_RUNNER_DUAL_XCODE || 'blacksmith-6vcpu-macos-15') }}" ' /^ swift-package-tests:/ { in_job=1; next } in_job && /^ [^[:space:]#][^:]*:[[:space:]]*(#.*)?$/ { in_job=0 } @@ -1365,9 +1365,8 @@ GUARDED = ( " ' claude-wrapper ')) && needs.changes.outputs.macos_pr_retry_runner", # The full-suite dispatch on main (code already on main, which # pr_runner_pool.py places like a pull request): only the job it placed. - "github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main' && contains(" - "needs.changes.outputs.macos_pr_owned_jobs, ' claude-wrapper ') && (github.run_attempt == 1" - " || github.triggering_actor != 'github-actions[bot]') && (needs.changes.outputs.macos_pr_side_runner" + "github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main' && github.run_attempt == 1" + " && contains(needs.changes.outputs.macos_pr_owned_jobs, ' claude-wrapper ') && (needs.changes.outputs.macos_pr_side_runner" " || needs.changes.outputs.macos_pr_runner)", )