From 4da313098fcc9aa3bd9095ff9794193022defe8b Mon Sep 17 00:00:00 2001 From: CodeWhale Bot Date: Wed, 23 Sep 2026 17:37:29 -0700 Subject: [PATCH] ci: run macOS budget/eval beside Test whenever the Mac leg is hosted The RSS budget and offline eval ran inside Test for every trusted event, assuming the warm self-hosted Mac. With CW_SELF_HOSTED_MAC off, a trusted PR's macOS leg is a cold GitHub-hosted Mac, where Test alone took 77-80 minutes on 2026-09-23 (#6431, #6417) and the two extra steps would pass the 90-minute limit. Route both steps by runner, not trust: inside Test only on the self-hosted Mac, otherwise in the parallel macos-budget job. Raise Test's timeout to 120 minutes for cold hosted Macs. This makes the existing kill switch safe to use: the single self-hosted runner had 14 queued runs and dropped jobs with "lost communication". Verification: actionlint with CI's flags (-ignore SC2129/SC2221/SC2222) clean. No tests run; workflow-only change, CI is the proof. Co-Authored-By: Claude Opus 5.5 (1M context) --- .github/workflows/ci.yml | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 74452ea4e7..0909632066 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -632,7 +632,9 @@ jobs: # non-PR release/main pushes use CNB for Linux. # The ternary is safe: matrix.os is always a non-empty literal, so # runs-on can never evaluate to empty. - timeout-minutes: 90 + # A cold GitHub-hosted Mac spent 77-80 minutes in Test on 2026-09-23 + # (fork PRs #6431, #6417), too close to the old 90-minute limit. + timeout-minutes: 120 # macOS legs go to the self-hosted Mac ONLY when all three hold: the # change is heavy, the event is trusted (not a fork PR), and the # CW_SELF_HOSTED_MAC repo variable is 'true'. That variable is the kill @@ -761,11 +763,12 @@ jobs: # The Ubuntu lint lane validates non-RSS backlog fields. Run the same # source-bound measurement on macOS so loss or growth of RSS evidence # fails closed instead of becoming an unsupported-field skip. - # Trusted events only: here it reuses the warm self-hosted build. Fork - # PRs run it in the separate `macos-budget` job with its own timeout, - # because on a cold hosted Mac it pushed Test past 90 minutes. + # Only on the self-hosted Mac: there it reuses the warm build. Every + # hosted Mac leg (fork PRs, or any PR with CW_SELF_HOSTED_MAC off) runs + # it in the separate `macos-budget` job with its own timeout, because + # on a cold hosted Mac it pushed Test past 90 minutes. - name: Check persistence-backlog RSS budget - if: needs.changes.outputs.heavy == 'true' && matrix.os == 'macos-latest' && needs.changes.outputs.trusted == 'true' + if: needs.changes.outputs.heavy == 'true' && matrix.os == 'macos-latest' && needs.changes.outputs.trusted == 'true' && vars.CW_SELF_HOSTED_MAC == 'true' run: python3 scripts/check-persistence-backlog-budget.py - name: Lockfile drift guard if: needs.changes.outputs.heavy == 'true' && (matrix.os != 'ubuntu-latest' || github.event_name == 'workflow_dispatch' || github.event_name == 'pull_request') @@ -774,9 +777,9 @@ jobs: # The eval harness is OS-independent prompt/composition checking; # running it once (on the faster macOS leg, warm from the test build) # instead of once per desktop OS keeps the coverage while taking - # ~2min off the Windows critical path. Trusted events only; fork PRs - # run it in `macos-budget` (see the RSS step above). - if: needs.changes.outputs.heavy == 'true' && matrix.os == 'macos-latest' && needs.changes.outputs.trusted == 'true' + # ~2min off the Windows critical path. Self-hosted Mac only; hosted + # Mac legs run it in `macos-budget` (see the RSS step above). + if: needs.changes.outputs.heavy == 'true' && matrix.os == 'macos-latest' && needs.changes.outputs.trusted == 'true' && vars.CW_SELF_HOSTED_MAC == 'true' run: cargo run -p codewhale-tui --all-features -- eval - name: sccache stats if: needs.changes.outputs.heavy == 'true' && (matrix.os != 'ubuntu-latest' || github.event_name == 'workflow_dispatch' || github.event_name == 'pull_request') && steps.sccache.outcome == 'success' @@ -793,11 +796,13 @@ jobs: # cancelled fork PRs at the 90-minute limit (jobs 106749104684 and # 106235312282) before Test could report. Running both here, in parallel # with Test and under their own timeout, keeps the coverage without - # holding the required Test (macos-latest) context hostage. Trusted - # events run the same two steps inside Test on the warm build instead. + # holding the required Test (macos-latest) context hostage. When Test's + # macOS leg runs on the self-hosted Mac (trusted event and + # CW_SELF_HOSTED_MAC == 'true'), it runs these two steps on the warm + # build instead. The name keeps "(fork PR)" so check contexts stay stable. name: macOS budget and eval (fork PR) needs: changes - if: needs.changes.outputs.heavy == 'true' && needs.changes.outputs.trusted != 'true' + if: needs.changes.outputs.heavy == 'true' && !(needs.changes.outputs.trusted == 'true' && vars.CW_SELF_HOSTED_MAC == 'true') timeout-minutes: 75 runs-on: macos-latest steps: