bun checks are a minimum, not an exact match; every setup-bun pin follows devEngines

Merged
TE
12d ago
+210-60

Leo, 2026-10-24: "surely we can just update bun on everything? they're usually p good ab breaking/nonbreaking changes"

A fleet build on cmux16 (bun 1.4.4) failed at the web bundles step because reload.sh's path required bun 1.4.2 exactly. This is PR A of two. It changes the bun checks from an exact match to a minimum and makes every pin follow one source. The declared version stays 1.4.2, so a fleet worker that already has 1.4.4 passes. PR B moves the version to 1.4.4 once the cmuxterm-hq fleet-tools pins land.

What changed

  • One version, one source. webviews/package.json devEngines.packageManager.version stays 1.4.2. It stays an exact string because hq's build recipe and testbox read it to build download URLs. bun does not enforce devEngines.
  • All 103 oven-sh/setup-bun steps now use bun-version: "1.4.2". 28 jobs move up to it: 25 were on 1.3.14 and 3 on 1.3.6.
  • Tests enforce the copies. tests/test_ci_change_areas.py::test_every_setup_bun_step_declares_a_version requires every setup-bun step in every workflow to match devEngines; before, only ci-web.yml was tied to it. tests/test_cmux_next_fast_gates.py and tests/test_docs_deploy_auth_guard.py read devEngines instead of hard-coding versions.
  • One minimum check. scripts/check-webviews-bun-version.sh is the only place that compares bun versions:
    • The compare is plain sh/awk and numeric, so 1.4.10 counts as newer than 1.4.4.
    • A newer patch or minor of the same major passes.
    • An older bun fails, and so does a prerelease of the pin. Both print curl -fsSL https://bun.sh/install | bash -s bun-v<pin>.
    • A different major fails.
    • --quiet [BUN] gives an exit status only, for callers that print their own message.
    • New test scripts/cmux-next/tests/check-webviews-bun-version.test.sh uses fake binaries and runs in cmux-next.yml.
  • Every builder calls the check. build-web-bundles.sh need_bun (the CMUX_WEB_BUNDLES_TOOLS_OPTIONAL branch), build-pages-web.sh and build-palette-ranker.sh call it, alongside the builders that already did.
  • scripts/ci/ensure-web-bundles.sh still installs the exact pin next to its cache. The change is under CMUX_WEB_BUNDLES_NO_INSTALL=1 (nx-remote): a newer bun now builds instead of failing, into a cache entry keyed <source key>-bun<version>, so a pinned job never installs bundles that another bun built.
  • ci-web.yml react-apps-base-check runs the base's scripts/cmux-next/private-bun.sh, so the base replay builds with the bun the base declares. A PR that moves the pin hit this: the base's exact check refused the head's bun.
  • Left as exact provisioning, since none of these fail on a newer bun: private-bun.sh (for #18124 determinism; the header comment says so), run-webviews-tests.sh and scripts/measure/*.
  • Not touched: images/cmux-vm/inputs.lock.json bun 1.3.14, web/scripts/run-tests.sh's existing minimum, @types/bun, test fixtures and the unpinned installs.

Risk

  • The 28 jobs that were on 1.3.6 or 1.3.14 now run 1.4.2. The only behaviour change for everything else: a newer bun now passes where it used to fail.
  • The web bundles' source key changes, because check-webviews-bun-version.sh is one of its inputs, so the bundles rebuild once.

Agent session: cosmic-gray

šŸ¤– Generated with Claude Code