base red: nightly.yml under its 490,000-byte budget (30 run blocks move to scripts/ci/nightly-steps/)

Merged
LA
5d ago
+511-404

tests/test_workflow_file_size.py (ci-guards preflight) caps nightly.yml at 490,000 bytes. nightly.yml was 505,604 bytes (508,735 before #30824), so this check was red on every PR. Lead decision, 17:37Z: move run blocks, as #25879 did.

Nightly owners (#30284, #30249, #30471, #30278, #30113): nightly.yml now calls 30 more step scripts in scripts/ci/nightly-steps/. To change one of these steps, edit its script. tests/nightly_workflow_text.py shows the workflow with the scripts written back inline.

What changes

  • 30 run: | blocks move verbatim into scripts/ci/nightly-steps/<name>.sh. Each step now runs bash scripts/ci/nightly-steps/<name>.sh, with the same env:, if:, id:, shell and working directory.
  • nightly.yml goes from 505,604 to 486,014 bytes.
  • yaml.safe_load of head and base give the same top level, the same jobs and the same steps, except those 30 run strings.
  • tests/nightly_workflow_text.py expands head to exactly the base's expansion, byte for byte.

How the blocks were chosen (so behavior does not change)

  • Shell options: each block starts with set -euo pipefail and uses no ${{ }}. bash script.sh does not inherit GitHub's bash -e, so the script sets the same options the inline block did.
  • Excluded: steps with a working directory, a run block that performs a checkout, and the "Hold the whole Mac before any credential" security gate, whose text test_ci_signing_owned_mac.py pins.
  • The script exists in the tree the step runs on:
    • refresh-compilation-cache, refresh-test-compilation-cache and resolve-nightly-cmux-tui-client check out the workflow commit (decide's head_sha is context.sha).
    • build-nightly-app, build-nightly-ghostty-cli-helper and build-nightly-remote-daemon check out build_sha. All three are skipped by an unsigned resume, which is the run that builds an older saved tree.
    • The 20+ scripts these jobs already call (chief-*, inputs-web-bundles, visual-gate-*) work the same way.

Remaining exposure

build_sha always has this PR's nightly.yml, so it also has its scripts. The resolver runs with CMUX_TUI_TREE_SAME_PATHS: .github/workflows/nightly.yml ... (nightly.yml:3028). scripts/cmux-next/pin-cmux-tui.sh then skips any candidate whose nightly.yml differs from the tip's. The tree-pending, fast and build-only paths build the tip.

Three edge cases are left:

  • "Bound the kept Rust target directories" runs under always(). If the warm checkout fails before it reaches build_sha on a builder whose kept tree is older than this PR, the step fails and does not trim. The job has already failed in that case.
  • The script now comes from the build_sha tree, not from the tip's workflow. This is the same as for the 20+ scripts that were already moved.
  • Tests that read nightly.yml without expanding it (for example test_ci_self_hosted_guard.sh) no longer see the moved bodies. Nothing violates those checks today.

Tests

The tests that read the raw nightly.yml text of a moved block now read it through nightly_workflow_text.expand, the helper #25879 added for this. Only the loading changed, not the checks. The 8 files: test_ci_fleet_compilation_cache.py, test_ci_nightly_off_blacksmith.py (only the reads of moved blocks; the ensure-gh test still reads raw), test_ci_nightly_push_throttle.py, test_ci_test_compilation_cache_seed.sh, test_nightly_cmux_tui_resolve.py, test_nightly_ghostty_helper_cache.py, test_nightly_next_source_archive.py and test_nightly_trusted_routing.py.

No new CI job, step or gate. Risk tier: high (nightly.yml). This PR needs a SHIP receipt at the exact head and a green compile.

Red and green

  • python3 tests/test_workflow_file_size.py:
    • Red at 623850468f1 (#30824 head) and at the feat tip: "505604 not less than 490000".
    • Green at this head.
  • All 124 tests that read nightly.yml give the same results as at base, except test_workflow_file_size.py, which turns green.
  • shellcheck -S warning on the 30 new scripts: clean. This is the level the repo's actionlint step gives shellcheck.
  • actionlint 1.7.12-manaflow.1 (the repo's pin) on nightly.yml: the same 5 findings as at base, all unused anchors that already exist there.

Observed / Not run

  • Observed: everything above, plus prepush-gate.py.
  • Not run: no nightly run. That needs the nightly-next push path; the fleet compile on this PR is the compile gate.

Changelog

none