Repository navigation
🤖 ci: upgrade Bun from 1.3.12 to 1.4.3 - #6319
Conversation
|
Preview deployment for your docs. Learn more about Mintlify Previews.
💡 Tip: Enable Automations to automatically generate PRs for you. |
…read socket, sort order, ALS disable)
6f4b6d7 to
0928afb
Compare
|
@codex review |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
Codex Review: Didn't find any major issues. Delightful! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
🛡️ Codex Security Review · Automatically triggeredSecurity review completed. No security issues were found in this pull request. Reviewed commit: Only the user who started this review can view the report in Codex. ℹ️ About Codex security reviews in GitHubThis is an experimental Codex feature. Security reviews are triggered when:
Once complete, Codex will leave suggestions, or a comment if no findings are found. |
Summary
Upgrade the pinned Bun from 1.3.12 to 1.4.3. With 6 small fixes (3 in tests, 1 in dev dependencies, 2 in production code), the full PR CI run is green on Bun 1.4.3, and CI time does not change measurably. The main gain: the Bun 1.3.12 coverage bug that hides lines after a
usingdeclaration is gone, so the CRAP gate scores those functions correctly again.resumeStream(workspaceService.ts) goes from 5% to 99% line coverage andexecuteBashfrom 9% to 96.5% on the same tree.Background
Bun 1.3.12 loses line coverage when a method is followed directly by an async or generator method that no test calls. With a
usingdeclaration in the method, every line after theusingreads as never run. The CRAP gate scores functions from Bun coverage, so these methods read about 0%.#4958 (
AbortSignal.timeoutnever fires after its last listener is removed, Bun 1.3.13 and 1.3.14) blocked every bump past 1.3.12. Its repro passes on Bun 1.4.2 and 1.4.3 on this host (abort event aborted= true).Implementation
Pins changed to 1.4.3:
.tool-versions,package.json,packages/chat-components/package.json,vscode/package.json(packageManager),.github/actions/setup-xum/action.yml,.github/workflows/{auto-cleanup-fixup,auto-cleanup,pr,update-models}.yml,Dockerfile,benchmarks/terminal_bench/mux_setup.sh.j2,docs/guides/github-actions.mdx,docs/AGENTS.md(host requirement) and the regeneratedbuiltInSkillContent.generated.ts. Three test comments that name the pinned runtime now name 1.4.3.flake.nixtakes Bun from nixpkgs, so it has no pin.Not changed:
tests/bugbash/sandbox/Dockerfile(oven/bun:1.3.12-slim) and its published image inimage.json, and.github/workflows/perf-profiles.yml(pins Bun 1.3.5, not 1.3.12. I did not check why).Fixes for what 1.4.3 breaks
bun installon 1.4.3 hoistedplaywright-core@1.63.0(from@e2e-dev/web) to the root.@coder/pixel-storybookthen loaded 1.63, whose Chromium CI does not install (Test / Storybook failed), andtests/bugbash/sandbox/build.shfound no@e2e-dev/web/playwright-coreentry (Test / Bug-bash sandbox failed). Fix: a root devDependency"playwright-core": "1.57.0"(the versionplaywright@1.57.0pins), which restores the 1.3.12 tree. The newbun.lockalso drops two optional peer entries that nothing installs or imports (@opentelemetry/api,esbuild-register).tests/bugbash/sandbox/runner.test.ts:process.env.TMPDIR = undefinednow stores the string"undefined"(Node does the same), andos.tmpdir()returned it. The test now deletes the variable when it was unset.tests/bugbash/sandbox/inContainer.test.tsandsrc/node/services/browser/agentBrowserCommandClient.test.ts: a fake server that callssocket.end()without reading never sees the peer's FIN, soserver.close()waits forever. Node does the same; Bun 1.3.12 closed it anyway. The fake servers now callsocket.resume()first.src/node/orpc/replayOwnership.test.ts: on Bun 1.4.2 and 1.4.3,AsyncLocalStorage.disable()does not hide the store from a continuation that resumes after it. Node and Bun 1.3.12 do. The product runs on Node (#!/usr/bin/env node, the DockerENTRYPOINT, Electron), so the test now asserts the release only when a probe shows that the runtime implements it. The rest of the test runs everywhere.computePriorHistoryFingerprintand its async twin: their sort comparator was inconsistent for a non-finite persistedhistorySequence(NaN || tiebreak). On 1.4.3 the reference sorted such rows differently once the DFG JIT optimized it (BUN_JSC_useDFGJIT=0makes the test pass), so the twin test failed. Fix: a shared total-order comparator (comparePriorHistoryOrder) that puts non-finite sequences after finite ones, then orders by id. The order of finite sequences does not change. It changes the fingerprint only for histories with a malformed sequence, and a fingerprint mismatch falls back to a full replay.LocalBaseRuntime(childstdout/stderrandreadFile) now usesnodeReadableToWeb(src/node/utils/nodeReadableToWeb.ts) instead ofReadable.toWeb. On Bun 1.4.3,Readable.toWebcan get adataevent from a child's pipe after the web stream was cancelled. Its listener then callsenqueueon the closed controller and throwsTypeError: Invalid state: Controller is already closedoutside any caller. The bash tool hits this when it cancels its readers on output overflow. In tests it fails the test. In the CLI (terminal-bench runs it on Bun,mux-run.sh) the uncaught exception ends the run. The adapter follows Node's adapter (pull resumes the source, byte-sized queue at the source's highWaterMark, chunks copied out of the pool, cancel destroys the source, a premature close is an AbortError), and it dropsdatathat arrives after cancel or end. A repro harness that spawns a fast-exiting writer and cancels at 1 MB threw in 15 of 300 runs on 1.4.3 withReadable.toWeb, 0 of 600 with the adapter, and 0 of 300 on 1.3.12.Validation
CI
4efc81977a(pins only)d19fec9773agentBrowserCommandClient(fix 3, second file).f7e1fb5fea6f4b6d727a(fix 6)562063cf36was cancelled by the newer push.0928afbff0(rebased ontob01fe77f6b)Flake (fix 6):
bash tool > should reject overlong line at boundary (IPC mode)failed once in run 1 withController is already closed. Failure counts insrc/node/services/tools/bash.test.ts, each test alone 40 times and the whole file 15 times:overflow_policy: 'truncate')All 6 "before" failures were
Controller is already closed. The one "after" failure is a second, older race in the truncate test: the tool cancels at 1 MB whileperlstill writes 1.5 MB, and when the pipe closes first,perlexits 1 and the tool reportssuccess: false. It happens with and without fix 6 (1.4.3: 1 of 150 runs before, 1 of 300 after, 1.3.12: 0 of 150), so it is not caused by the fix (follow-up below).PR CI runs (the first three predate the rebase onto current main):
Local (
make static-check,make test)make static-checkpasses on 1.4.3 and on 1.3.12.make test(onebun test srcprocess, 25,321 tests) has 12 failures on 1.4.3 and 14 on 1.3.12. Both sharetaskGitPatchEngine(hostinit.templateDir) and oneBackupRepoCachetimeout. The other failures are 5 s timeouts that differ between runs. Every 1.4.3-only failure passes when its file runs alone on both versions, except the 3 that fixes 3–5 address.Coverage (CRAP gate)
Main moved during the measurement and #6307 added coverage from isolated unit files, so the CI comparison uses only each shard's shared
lcov.infoand counts only functions in files that are the same in both trees.workspaceService.ts(9 files)resumeStream(workspaceService.ts, cc 83): coverage, CRAP (9 files)executeBash(cc 38): coverage, CRAP (9 files)resumeStream, unit onlyexecuteBash, unit onlyBefore: unit lcov from run 38372261688 (a browser-only PR, a Checkbox component and CSS, merged into
32364fb956, the same base), integration lcov from run 38374718068 (the closest green run that ran the backend integration tests, merged into a newer main). Main push runs upload nocrap-lcov-*artifacts. After: run 38382892697, scored on its merge tree (f83f8e1182+ this branch). Integration coverage comes from Jest, so Bun does not change it.Same-tree A/B (the 9
workspaceService*.test.tsfiles that call these methods, run with coverage under each Bun on one tree):resumeStream5.1% to 99.0%,executeBash9.2% to 96.5%,fork2% to 77%,getFileCompletions20% to 98%. No function lost 10 points or more.CI time
make test-unit-cistepRuns 1 and 2 were slower to set up (unit setup 54 s vs 30 s) because the
node_modulescache key includes the Bun version. This PR runs 2 jobs more than the baselines (Nix Build, Lint Actions), because it changesbun.lockand the workflows.Bun 1.3.12 workarounds: status on 1.4.3
AbortSignal.timeouttests/bunEachTableGcWorkaround.ts,tests/bunEachTableGc.test.ts(#6020)scripts/test-unit-ci.shisolation ofbunEachTableGc.test.tsscripts/perf/desktopColdStart.ts:8(runs under Node)_electron.launchfrom Bun hangs on 1.3.12 and works on 1.4.3scripts/crap/crapper_report.py:163(a loaded but never-run function lists every line at 0)scripts/crap/crapper_report.py:201(an uncalled arrow counts a later line as hit)tests/bugbash/sandbox/proxy.ts:280(node:httpmisses a client disconnect)Risks
Low for the product. The product runs on Node, and the production changes are the comparator (fix 5) and the stream adapter (fix 6), which follows Node's
Readable.toWebbehavior. The remaining Bun-only risk is in tests:AsyncLocalStorage.disable()semantics that differ from Node, and the truncate test's pipe race.Follow-ups
Not done in this PR:
tests/bunEachTableGcWorkaround.ts, itsbunfig.tomlpreload,tests/bunEachTableGc*.ts, and thejest.config.jsandscripts/test-unit-ci.shentries. Then close 🤖 bug: Bun 1.3.13+ AbortSignal.timeout never fires after its last listener is removed (blocks Bun > 1.3.12) #4958.oven/bun:1.4.3(tests/bugbash/sandbox/Dockerfile, rebuild and publishimage.json), and make the "a client that goes away" test inproxy.test.tsstrict again (theproxy.ts:280removal trigger).AsyncLocalStorage.disable()gate inreplayOwnership.test.tsa removal trigger.playwright-coretogether withplaywrightand@playwright/test: the root pin from fix 1 must move with them.Generated with
xum• Model:anthropic:claude-opus-5-5• Thinking:high• Cost:$16.55