ci(runner pools): one pool per Blacksmith Linux size, so a stalled size moves by declaration

Merged
TE
4d ago
+54-1

Leo-ask: ask-973a915bea

Leo, 2026-10-28: "Where the f***ing are the generalized solution to all these problems that these incessant pins?"

475 runs-on lines on feat-cmux-next end in a literal single-size Blacksmith label (265 at 4 vCPU, 61 at macOS 26, 57 at 8 vCPU, 42 at 2 vCPU, 29 at 32 vCPU, 9 at 16 vCPU and others). A re-run cannot move a literal label, so a stalled size strands every job that names it. On 2026-10-28 that happened to blacksmith-4vcpu-ubuntu-2404 in nightly.yml.

This PR is step 1. It declares one pool per Blacksmith Linux size, plus macos_latest, in .github/runners.json pools:

PoolMembers
linux_22 vCPU, then 4 vCPU
linux_88 vCPU, then 16 vCPU
linux_1616 vCPU, then 32 vCPU
linux_3232 vCPU, then 16 vCPU
macos_latestblacksmith-6vcpu-macos-latest

runner_pools.py is unchanged. On its next pass it writes each new key into RUNNER_POOLS, and it moves a key off a member the probe or the janitor marks dead. The follow-up PRs on feat-cmux-next replace each literal last resort with fromJSON(vars.RUNNER_POOLS).<size pool>. A fork pull request keeps its literal fork branch, because a fork's run gets no repository variables. Those PRs land only after this one has merged and the variable carries the keys.

Changed:

  • .github/runners.json adds the five pools.
  • docs/ci-runners.md updates the pool table and fixes the linux row, which now lists 4 vCPU first.
  • tests/test_ci_runner_pools.py checks that each Linux size has its own pool with a member to fail over to.

Tests: tests/test_ci_runner_pools.py (42 OK), test_ci_runner_set, test_ci_queue_janitor, test_ci_simple_pool_picker and test_ci_starved_labels all pass.

Performance

metricbeforeafterdeltaharness
Blacksmith minutes per dayunchangedunchanged0declaration only; each pool's first member is the size jobs already name, so no job moves until a size stalls

Agent session: agent session

šŸ¤– Generated with Claude Code


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.


Summary by cubic

Declares one pool per Blacksmith Linux size plus macos_latest in .github/runners.json, so a stalled size moves its jobs by declaration instead of stranding them on a literal label.

Hundreds of runs-on lines end in a literal single-size Blacksmith label; a re-run cannot move a literal label, so when a size stops starting jobs every job that names it is stuck. This adds linux_2, linux_4, linux_8, linux_16, linux_32, and macos_latest, each with a first (preferred) member and a fail-over member. macos_latest fails over to the macOS 26 image. linux_4 is ephemeral-only: it serves secret-bearing and write-token jobs that must not ride the shared linux pool. runner_pools.py is unchanged — it writes the new keys into RUNNER_POOLS on its next pass, and follow-up PRs replace literal labels with fromJSON(vars.RUNNER_POOLS) lookups.

  • Adds a test asserting each Linux size has its own pool with a fail-over member, and adjusts the dead-mark fixture so every pool holds a live member when linux_4 shares the 4 vCPU first slot.
  • The docs/ci-runners.md pool table update moves to the same follow-up change that starts reading the pools.

Summary by CodeRabbit

  • New Features
    • CI jobs can use Linux runner pools sized from 2 to 32 vCPUs, with alternate runner options available for each size.
    • Added a macOS latest runner option with a macOS 26 fallback.
  • Documentation
    • Updated CI runner guidance to describe size-matched Linux pools and the available macOS options.