Repository navigation
ci: the routing table fails a macOS job pinned to one fixed label - #28600
Merged
Merged
Conversation
cmux-next-ios-kit.yml's kit-tests ran on `... || vars.CI_PAID_MACOS_OVERFLOW == '1' && vars.MACOS_RUNNER_26 || 'blacksmith-6vcpu-macos-26'` and no runs-on check caught it. test_ci_runs_on_fallback.py only refuses single-host labels (a glaeda-runner-*, a mini's name) and the 12 vCPU Blacksmith Mac. runs_on_values.py only refuses runner-name variables. runner_routing_table.py counted only a bare vars.CI_SIDE_LANE_RUNNER / CI_LIGHT_LANE_RUNNER as bypassing placement. A Blacksmith 6 vCPU macOS literal is none of those, so moving a job off the owned pool onto a fixed Blacksmith label passed every check. runner_routing_table.check() now also fails a macOS job whose runs-on (with its matrix, when it reads one) reads no picker output: no needs.<job>.outputs.<x> other than the static capability map, and no caller's inputs.*. The 42 macOS jobs pinned this way today get a picker_followup entry in .github/runners.json. Like linux_followup and placement_followup, a followup that no longer applies fails, so the list only shrinks. Release-signing jobs are marked as needing a signing picker (per-job keychain, exclusive claim). kit-tests gets no entry: the test stays red until #28145 routes it through ios_runner_pool.py. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-cabecb079fe356666905
Contributor
|
cmux status (one comment, edited in place; each line is updated by the job that owns it) Review App of this head (app.zip, kept 1 day)
Shipped in:
|
|
Found 5 test failures on Blacksmith runners: Failures
|
The check catches kit-tests' fixed Blacksmith label, which is the point of this change. Until #28145 moves the job onto ios_runner_pool.py, it carries a followup like the other 42 pinned jobs, so the guard can land now and refuse new pins. When #28145 lands, the stale-followup rule makes it drop this line. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-cabecb079fe356666905
teamleaderleo
temporarily deployed
to
ci-routing-agent
October 31, 2026 00:19 — with
GitHub Actions
Inactive
Review round 2: matching a picker output anywhere in runs-on or the whole strategy let a fixed label pass. An unrelated matrix field that read an output was enough, and so was an output used only as a condition. Now only value positions count: the last && operand of each || alternative, read through groups and fromJSON(...). For matrix.<key>, only that key's axis and include values count. The tighter read catches one more pin, cmux-next-perf-budgets.yml#blacksmith-mac. It compares inputs.runner_class and then always names a Blacksmith label, so it gets a picker_followup. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-cabecb079fe356666905
teamleaderleo
temporarily deployed
to
ci-routing-agent
October 31, 2026 00:27 — with
GitHub Actions
Inactive
Review round 3: an expression-valued include could vouch for a fixed runner axis. GitHub keeps the axis's own legs whatever an include adds, so each leg's value now has to come from a picker: the axis items, and the include rows that set the key. An opaque include counts only when nothing else gives the key a value. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-cabecb079fe356666905
teamleaderleo
temporarily deployed
to
ci-routing-agent
October 31, 2026 00:31 — with
GitHub Actions
Inactive
Review round 4: the every-leg rule also asked a picker of the Linux and Windows legs in a mixed matrix. A literal leg that names a Linux or Windows runner and no macOS hint is left out. The macOS legs must still all be picked. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-cabecb079fe356666905
teamleaderleo
temporarily deployed
to
ci-routing-agent
October 31, 2026 00:34 — with
GitHub Actions
Inactive
Review round 5: `fromJSON(needs.pick.outputs.runners)['label']` was taken for a literal. A value term now counts as picked when it reads a picker output anywhere outside a quoted string, unless it is a boolean: a negation, a comparison, or contains/startsWith/endsWith. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-cabecb079fe356666905
teamleaderleo
temporarily deployed
to
ci-routing-agent
October 31, 2026 00:46 — with
GitHub Actions
Inactive
Collaborator
Author
|
Follow-ups from the independent review (Codex gpt-6-astra high, SHIP at eda4401). Neither one blocks:
No workflow in the tree uses either shape today. |
This branch was previously deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
![Fix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/fix-with-codesmith-light-3x.png)
Leo, 2026-10-28: "Bro, I thought we already had logic to automatically route stuff. How can we still have pins like this? I hate pins. Like, just pin the set of the stuff that isn't hilariously slow."
cmux-next-ios-kit.yml'skit-testsruns on... || vars.CI_PAID_MACOS_OVERFLOW == '1' && vars.MACOS_RUNNER_26 || 'blacksmith-6vcpu-macos-26': one fixed Blacksmith macOS label, with no owned Mac first and no stall-aware failover. None of the runs-on checks caught it:tests/test_ci_runs_on_fallback.pyrefuses only single-host labels (aglaeda-runner-*label or a mini's name) and the 12 vCPU Blacksmith Mac as a last resort.scripts/ci/runs_on_values.pyrefuses only runner-name variables that are read bare.scripts/ci/runner_routing_table.pycounted only a barevars.CI_SIDE_LANE_RUNNER/CI_LIGHT_LANE_RUNNERas bypassing placement.A Blacksmith 6 vCPU macOS literal is none of those, so a job that moved off the owned pool onto a fixed Blacksmith label passed every check.
Change.
runner_routing_table.check()now also fails a macOS job whose runs-on (plus its matrix, when it reads one) reads no picker output. A picker output is aneeds.<job>.outputs.<x>other than the static capability map, or a caller'sinputs.*. Each failure names the pickers to use:ios_runner_pool.py,simple_pool_picker.pyorside_lane_placement.py.The 42 macOS jobs pinned this way today each get a
picker_followupin.github/runners.json. Likelinux_followupandplacement_followup, a followup that no longer applies fails, so the list only shrinks. The release-signing jobs are marked as needing a signing picker (per-job keychain, exclusive claim). A placement bypass already has itsplacement_followupand is not counted twice.Red/green.
test_a_macos_job_on_a_fixed_label_failsfails on the exactkit-testsexpression.kit-testsgot its followup, the tree testtest_the_tree_classifies_every_macos_jobfailed and namedcmux-next-ios-kit.yml#kit-tests runs on macOS from a fixed label.kit-testsnow carries apicker_followupthat points at ci: route iOS kit tests through the runner pool #28145, so this guard can land now and refuse new pins. ci: route iOS kit tests through the runner pool #28145 routes the job throughios_runner_pool.py: owned simulator Macs first, Blacksmith on retry, with the owned-pool rescue watch, whose main-side half ci: rescue iOS kit runs from main pool watcher #28431 has merged. With ci: route iOS kit tests through the runner pool #28145's workflow overlaid on this tree, the check reportskit-tests no longer runs on a fixed label; remove its picker_followup, so ci: route iOS kit tests through the runner pool #28145 drops that one line when it lands.New fixture tests cover:
kit-testsexpression;Validation:
tests/test_runner_routing_table.py,test_ci_runner_capability_resolver.py,test_runs_on_labels.py,test_ci_no_github_hosted_macos.pyandtest_feat_ci_guard_group.pywere run locally.test_ci_change_areas.pyhas one failure (test_repository_helpers_route_by_where_they_run), which is the same on base. No workflow file changes.No capture: CI routing check only.
Agent session: agent session
🤖 Generated with Claude Code