ci: single arm64 debian-13 build host; ThinLTO everywhere; baseline-only x64; rust+link merge; sysroots; WebKit a36c188; rust 2026-07-20 - #34782
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughChangesThis PR consolidates x64 baseline handling, updates CI release gating and artifact aliases, adds Linux glibc and macOS SDK bootstrap support, pins Rust nightly toolchains, removes AVX2-based platform selection, and applies Rust fixed-size chunk and expression-based refactors. Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
Comment |
f72bd40 to
710f3fb
Compare
710f3fb to
84ca491
Compare
|
Added unit tests in Note on the fail-before gate: the |
10907c1 to
d4d4c5e
Compare
There was a problem hiding this comment.
Additional findings (outside current diff — PR may have been updated during review):
-
🟡
.buildkite/ci.mjs:1626-1633— The comment says "enforce only on main or [lto] PRs", but the code issizeRecordOnly = isMainBranch() || !options.forceLto— on main,recordOnlyis true so--no-failis passed and the size threshold is not enforced (it only records the baseline, matching pre-PR behavior and your own verification table). Enforcement happens only on[lto]PRs; consider rewording to something like "enforce only on [lto] PRs; main records the baseline; non-LTO PRs annotate only."Extended reasoning...
What the comment says vs. what the code does
The newly-added comment at
.buildkite/ci.mjs:1626-1628reads:Binary-size tracking. Non-LTO PR binaries are larger than the LTO main canary they compare against, so enforce only on main or [lto] PRs; other PRs still annotate.
The code immediately below it is:
const sizeRecordOnly = isMainBranch() || !options.forceLto; steps.push(getBinarySizeStep(strippedPlatforms, options, { recordOnly: sizeRecordOnly }));
getBinarySizeStep()translatesrecordOnly: trueinto the--no-failflag, which makesscripts/binary-size.tsannotate without failing the build. So "enforce" ↔recordOnly === false, and "annotate only" ↔recordOnly === true.Step-by-step proof
Scenario isMainBranch()options.forceLtosizeRecordOnly--no-failpassed?Enforced? main true(irrelevant — short-circuit) trueyes no PR without [lto]falsefalsetrueyes no PR with [lto]falsetrue(truthy string)falseno yes So enforcement happens only on
[lto]PRs. Main is record-only — it never enforces the threshold.The code is intentional; the comment is wrong
Three independent sources confirm main is meant to be record-only:
- Pre-PR behavior: the old line was
recordOnly: isMainBranch()— main was already record-only before this PR touched it. getBinarySizeStep()'s own docstring (unchanged in this PR): "Runs on PR builds (comparison) and main (record-only, to produce the baseline artifact)."- The PR description's verification table: the
mainrow showsbinary-size --no-failcount = 1, i.e. main gets--no-fail.
So the logic is deliberate and correct; only the comment's phrase "enforce only on main or [lto] PRs" contradicts it.
Impact
No runtime effect — this is purely a documentation inaccuracy. But per REVIEW.md, comments must "carry only durable non-obvious content" and be accurate. A future reader of this comment would reasonably conclude that main hard-fails on binary-size regressions, when in fact main only records the baseline artifact and never fails on size. That could lead to confusion when debugging why a size regression on main didn't block the canary, or when someone later revisits this gating.
Suggested fix
Reword the comment to match the code, e.g.:
// Binary-size tracking. Non-LTO PR binaries are larger than the LTO main // canary they compare against, so enforce only on [lto] PRs; main records // the baseline; non-LTO PRs annotate only.
- Pre-PR behavior: the old line was
|
Good catch on the binary-size comment wording: |
d4d4c5e to
00ea037
Compare
There was a problem hiding this comment.
Additional findings (outside current diff — PR may have been updated during review):
-
🔴
.buildkite/scripts/upload-release.sh:340-349—alias_baseline_artifact()copies the zip verbatim (cp "$artifact" "$alias"), so the inner directory is stillbun-linux-x64-baseline/. On AVX2-capable machinesinstall.shcomputestarget=linux-x64(no-baselinesuffix), downloads the aliasedbun-linux-x64.zip, and thenmv "$bin_dir/bun-linux-x64/bun" ...fails with "Failed to move extracted bun to destination" — same forinstall.ps1(line 191/200 → "Download is corrupt or intercepted Antivirus?") andbun upgradefrom every already-installed haswell x64 build (EXE_SUBPATHusesVersion::FOLDER_NAMEwithEnvironment::BASELINE = false). The alias needs to repack: unzip → rename the inner directory to the aliased stem → re-zip.Extended reasoning...
What the bug is
upload-release.shnow aliases each*-baseline*.zipto its historical non-baseline name so "existing download URLs keep resolving" (per the code comment and the PR description). But the alias is created with a barerun_command cp "$artifact" "$alias", which renames only the zip file — the top-level directory inside the zip is unchanged.The zip layout is
${bunTriplet}.zip → ${bunTriplet}/bun[.exe]wherebunTriplet = bun-${os}-${arch}[-musl][-baseline](scripts/build/ci.ts:330–339,computeBunTriplet()/makeZip()). Sobun-linux-x64-baseline.zipcontainsbun-linux-x64-baseline/bun, and after thecpthe aliasedbun-linux-x64.zipalso containsbun-linux-x64-baseline/bun.Every consumer of these zips relies on the invariant that the inner directory name matches the zip filename stem — that convention is exactly what the alias exists to preserve.
Code paths that break
src/runtime/cli/install.sh(thecurl -fsSL https://bun.sh/install | bashpath):- Line 83:
Linux x86_64→target=linux-x64 - Line 117: appends
-baselineonly whengrep avx2 /proc/cpuinfois empty — on the vast majority of modern x64 machines AVX2 is present, sotargetstayslinux-x64(orlinux-x64-muslon Alpine) - Line 132: downloads
.../bun-linux-x64.zip→ gets the alias - Line 152:
unzip -oqd "$bin_dir" "$exe.zip"→ creates$bin_dir/bun-linux-x64-baseline/ - Line 155:
mv "$bin_dir/bun-linux-x64/bun" "$exe"→ No such file or directory →error 'Failed to move extracted bun to destination'
src/runtime/cli/install.ps1:- Line 143:
$Target = "bun-windows-$BunArch"(no-baselineunless$IsBaseline, which is CPU-feature-gated) - Line 148: downloads
.../bun-windows-x64.zip→ gets the alias - Line 191:
Test-Path "${BunBin}\bun-windows-x64\bun.exe"→ false (actual path is${BunBin}\bun-windows-x64-baseline\bun.exe) - Line 192: throws
"Download is corrupt or intercepted Antivirus?"
src/runtime/cli/upgrade_command.rs(bun upgrade):EXE_SUBPATH = Version::FOLDER_NAME + "/bun"(line 503–508), whereFOLDER_NAMEincludes-baselineonly ifEnvironment::BASELINEis true (line 116–123)- Every x64 binary already installed on user machines was built as haswell (non-baseline), so
Environment::BASELINE = falsein those binaries → they downloadbun-linux-x64.zip/bun-windows-x64.zip(the alias) and look forbun-linux-x64/buninside → extraction fails
Why nothing prevents it
The PR description says "the install scripts keep resolving." The URLs resolve — GitHub/S3 serve the aliased asset — but resolving the URL is only half the contract. The install scripts, install.ps1, and
bun upgradeall hard-code the inner-directory-matches-zip-stem convention, andcpdoesn't rewrite zip contents.Impact
On the first canary shipped from
mainafter this merges:curl -fsSL https://bun.sh/install | bashfails for essentially every Linux x64 glibc and musl user with a post-2013 CPU.irm bun.sh/install.ps1 | iexfails for essentially every Windows x64 user with an AVX2-capable CPU.bun upgradefails for every existing x64 install.
Users on non-AVX2 CPUs (who get
target=…-baselineand download the real-baseline.zip) are unaffected, as are aarch64 users.Step-by-step proof
- CI builds
bun-linux-x64-baseline.zipcontainingbun-linux-x64-baseline/bun(ci.tsmakeZip(cfg, bunTriplet, [...])stages files underresolve(buildDir, bunTriplet)). upload-release.shrunsalias_baseline_artifact "bun-linux-x64-baseline.zip"→ echoesbun-linux-x64.zip.run_command cp "bun-linux-x64-baseline.zip" "bun-linux-x64.zip"— byte-identical copy, inner dir stillbun-linux-x64-baseline/.- Both are uploaded to S3 + the GitHub release.
- A user on an AVX2-capable Ubuntu box runs
curl -fsSL https://bun.sh/install | bash. target=linux-x64(line 83);/proc/cpuinfocontainsavx2so line 117 does not append-baseline.bun_uri=.../releases/latest/download/bun-linux-x64.zip— downloads the alias.unzip -oqd "$HOME/.bun/bin" bun.zip→ creates$HOME/.bun/bin/bun-linux-x64-baseline/bun.mv "$HOME/.bun/bin/bun-linux-x64/bun" "$HOME/.bun/bin/bun"→mv: cannot stat …: No such file or directory.- Script exits with
error: Failed to move extracted bun to destination.
Fix
Repack the alias so the inner directory matches the aliased stem, e.g.:
local alias="$(alias_baseline_artifact "$artifact")" if [ -n "$alias" ]; then local src_dir="${artifact%.zip}" local dst_dir="${alias%.zip}" rm -rf "$src_dir" "$dst_dir" run_command unzip -q "$artifact" run_command mv "$src_dir" "$dst_dir" run_command zip -qr "$alias" "$dst_dir" rm -rf "$dst_dir" upload_one "$alias" fi
(
unzip/zipare already available on the release agent —install_aws_linuxinstallsunzip, and Amazon Linux 2023 shipszip; add acommand -v zip || package_manager_install zipguard if desired.) - Line 83:
00ea037 to
a903927
Compare
a903927 to
0b859d1
Compare
There was a problem hiding this comment.
Actionable comments posted: 7
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/runtime/cli/install.ps1 (1)
133-135: 📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy liftAdd one hermetic regression suite for baseline-free artifact resolution. The installer and upgrader now share unsuffixed x64 artifact naming, but the supplied tests only exercise build configuration.
src/runtime/cli/install.ps1#L133-L135: test plain Windows x64 archive selection for current and legacy requested versions.src/runtime/cli/install.sh#L108-L110: test Unix x64 resolution through fixture-backed redirect behavior, without public-network access.src/runtime/cli/upgrade_command.rs#L116-L124: test normal and profile ZIP/folder names selected by upgrade metadata parsing.As per coding guidelines, every behavioral change must include an automated regression test in the same change.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/runtime/cli/install.ps1` around lines 133 - 135, Add a hermetic regression suite covering baseline-free artifact resolution: in src/runtime/cli/install.ps1 lines 133-135, test plain Windows x64 archive selection for both current and legacy requested versions; in src/runtime/cli/install.sh lines 108-110, test Unix x64 resolution using fixture-backed redirects without network access; and in src/runtime/cli/upgrade_command.rs lines 116-124, test normal and profile ZIP/folder names produced by upgrade metadata parsing. Use the existing test conventions and keep all cases automated within this change.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.buildkite/ci.mjs:
- Around line 158-162: Condense the Windows LTO rationale comment in
.buildkite/ci.mjs lines 158-162 to three lines or fewer while retaining the key
constraint and reference to ltoDefault. Also condense the baseline-alias
compatibility rationale comment in .buildkite/scripts/upload-release.sh lines
317-320 to three lines or fewer, preserving its essential meaning.
In @.buildkite/scripts/upload-release.sh:
- Around line 340-346: Update the archive repacking flow around src_zip and
dst_zip to derive absolute workspace paths for all rm, unzip, mv, and zip file
operations, while passing relative paths to zip as needed to preserve archive
entry names. Ensure cleanup and repacking remain anchored to the intended
workspace regardless of the caller’s current directory.
In `@scripts/bootstrap.sh`:
- Around line 1408-1474: Require checksum verification in
install_linux_glibc_sysroot before any tar extraction by populating
linux_sysroot_sha256_x86_64 and linux_sysroot_sha256_aarch64 with the matching
published digests and removing the empty-checksum fallback. Ensure each
architecture uses download_and_verify_file and aborts rather than extracting
when its checksum is missing or invalid.
In `@scripts/build/config.ts`:
- Around line 564-583: Update detectLinuxGlibcSysroot so the aarch64 candidates
cannot include the generic /opt/linux-sysroot-glibc path used for x86_64; retain
only the arm64-specific path for aarch64 and preserve the existing x86_64
candidate behavior. Keep the environment override and undefined result
unchanged.
In `@src/js_parser/parse/parse_typescript.rs`:
- Around line 637-638: Update the comment in the TypeScript parsing code to
remove the temporary reference to duplicated slice8 implementations and retain
only the durable invariant that to_utf8_e_string guarantees is_utf16 == false,
explaining why accessing .data directly is safe.
In `@src/js_printer/lib.rs`:
- Around line 7926-7932: Compress the comment immediately above module_scope
into no more than three lines, preserving both points: Scope is not Copy, and
compute_reserved_names_for_scope only traverses members/generated/children, so
referencing the in-place tree.module_scope preserves the required lifetime.
In `@test/internal/macos-cross-config.test.ts`:
- Line 76: Remove the redundant “explicit override still wins” comment from the
regression test, leaving the adjacent assertion unchanged; retain only an issue
URL comment if one is required by the project guidelines.
---
Outside diff comments:
In `@src/runtime/cli/install.ps1`:
- Around line 133-135: Add a hermetic regression suite covering baseline-free
artifact resolution: in src/runtime/cli/install.ps1 lines 133-135, test plain
Windows x64 archive selection for both current and legacy requested versions; in
src/runtime/cli/install.sh lines 108-110, test Unix x64 resolution using
fixture-backed redirects without network access; and in
src/runtime/cli/upgrade_command.rs lines 116-124, test normal and profile
ZIP/folder names produced by upgrade metadata parsing. Use the existing test
conventions and keep all cases automated within this change.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 2ec5289a-54b3-44cf-a26a-9793a1f92fd9
📒 Files selected for processing (48)
.buildkite/ci.mjs.buildkite/scripts/upload-release.sh.github/workflows/clippy.yml.github/workflows/format.yml.github/workflows/miri.ymlrust-toolchain.tomlscripts/bootstrap.shscripts/build/buildOptionsRs.tsscripts/build/ci.tsscripts/build/config.tsscripts/build/deps/webkit.tsscripts/build/flags.tsscripts/build/rust.tsscripts/build/source.tsscripts/build/tools.tssrc/ast/char_freq.rssrc/boringssl/lib.rssrc/bun_alloc/lib.rssrc/bun_bin/lib.rssrc/bun_core/Global.rssrc/bun_core/build.rssrc/bun_core/env.rssrc/bun_core/lib.rssrc/collections/bit_set.rssrc/collections/multi_array_list.rssrc/crash_handler/lib.rssrc/css/values/color.rssrc/http_jsc/websocket_client/WebSocketUpgradeClient.rssrc/install/PackageManager/CommandLineArguments.rssrc/install/resolvers/folder_resolver.rssrc/js_parser/parse/parse_typescript.rssrc/js_printer/lib.rssrc/jsc/bindings/ANSIHelpers.hsrc/jsc/bindings/c-bindings.cppsrc/jsc/bindings/xxhash3.cppsrc/options_types/compile_target.rssrc/react_compiler/ssa/enter_ssa.rssrc/router/lib.rssrc/runtime/cli/install.ps1src/runtime/cli/install.shsrc/runtime/cli/upgrade_command.rssrc/runtime/image/codecs.rssrc/runtime/node/path.rssrc/runtime/socket/udp_socket.rssrc/runtime/valkey_jsc/valkey.rssrc/runtime/webcore/encoding.rssrc/sql_jsc/mysql/MySQLValue.rstest/internal/macos-cross-config.test.ts
💤 Files with no reviewable changes (2)
- scripts/build/buildOptionsRs.ts
- src/jsc/bindings/c-bindings.cpp
0b859d1 to
40bcd4d
Compare
9045f7b to
2039218
Compare
2039218 to
ec0ca0f
Compare
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@scripts/bootstrap.sh`:
- Around line 1604-1640: Harden install_macos_sdk by eliminating execution of an
implicitly mutable xmac.mjs ref: default BUN_BOOTSTRAP_REPO_REF to the pinned
commit or tag associated with this bootstrap.sh, and add checksum verification
for the downloaded xmac_mjs before invoking it via bun. Reuse the existing
trusted-reference or sha256 validation patterns in the script, and abort before
execution when validation fails.
In `@src/jsc/bindings/ANSIHelpers.h`:
- Around line 50-53: Condense the comments at ANSIHelpers.h lines 50-53 and
77-82, and xxhash3.cpp lines 4-8, to no more than three lines each while
preserving their explanations of Highway runtime dispatch, the long-scan fast
path, and file-level dispatch rationale.
In `@src/runtime/cli/install.sh`:
- Around line 108-112: Restore the Darwin x64 branch in the target-selection
case handling so pinned Haswell releases on non-AVX2 macOS hosts probe AVX2 and
fall back to the baseline artifact. Keep the current behavior for newer releases
unchanged, and condense the associated comment to no more than three lines so it
accurately describes the preserved fallback.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 1a52bebf-9a65-4677-967c-66b842860c72
📒 Files selected for processing (50)
.buildkite/ci.mjs.buildkite/scripts/upload-release.sh.github/workflows/clippy.yml.github/workflows/format.yml.github/workflows/miri.ymlpackages/bun-release/src/platform.tsrust-toolchain.tomlscripts/bootstrap.shscripts/build/buildOptionsRs.tsscripts/build/ci.tsscripts/build/config.tsscripts/build/deps/webkit.tsscripts/build/flags.tsscripts/build/rust.tsscripts/build/source.tsscripts/build/tools.tssrc/ast/char_freq.rssrc/boringssl/lib.rssrc/bun_alloc/lib.rssrc/bun_bin/lib.rssrc/bun_core/Global.rssrc/bun_core/build.rssrc/bun_core/env.rssrc/bun_core/lib.rssrc/bun_core/string/immutable/unicode.rssrc/collections/bit_set.rssrc/collections/multi_array_list.rssrc/crash_handler/lib.rssrc/css/values/color.rssrc/http_jsc/websocket_client/WebSocketUpgradeClient.rssrc/install/PackageManager/CommandLineArguments.rssrc/install/resolvers/folder_resolver.rssrc/js_parser/parse/parse_typescript.rssrc/js_printer/lib.rssrc/jsc/bindings/ANSIHelpers.hsrc/jsc/bindings/c-bindings.cppsrc/jsc/bindings/xxhash3.cppsrc/options_types/compile_target.rssrc/react_compiler/ssa/enter_ssa.rssrc/router/lib.rssrc/runtime/cli/install.ps1src/runtime/cli/install.shsrc/runtime/cli/upgrade_command.rssrc/runtime/image/codecs.rssrc/runtime/node/path.rssrc/runtime/socket/udp_socket.rssrc/runtime/valkey_jsc/valkey.rssrc/runtime/webcore/encoding.rssrc/sql_jsc/mysql/MySQLValue.rstest/internal/source-lints/windows-cross-config.test.ts
💤 Files with no reviewable changes (3)
- scripts/build/buildOptionsRs.ts
- src/jsc/bindings/c-bindings.cpp
- src/bun_core/env.rs
ec0ca0f to
890c0cd
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.buildkite/ci.mjs:
- Around line 1592-1613: Remove the unused forceTests destructuring and simplify
the test-step condition in the relevant pipeline setup to rely only on
skipTests, since getPipelineOptions does not populate forceTests. Preserve the
existing behavior of running tests when tests are not skipped and omitting them
when skipTests is enabled.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 2fbfdef8-8008-438e-bfaf-99bb9668f498
📒 Files selected for processing (51)
.buildkite/ci.mjs.buildkite/scripts/upload-release.sh.github/workflows/clippy.yml.github/workflows/format.yml.github/workflows/miri.ymlpackages/bun-release/src/platform.tsrust-toolchain.tomlscripts/bootstrap.shscripts/build/buildOptionsRs.tsscripts/build/ci.tsscripts/build/config.tsscripts/build/deps/webkit.tsscripts/build/flags.tsscripts/build/rust.tsscripts/build/source.tsscripts/build/tools.tssrc/ast/char_freq.rssrc/boringssl/lib.rssrc/bun_alloc/lib.rssrc/bun_bin/lib.rssrc/bun_core/Global.rssrc/bun_core/build.rssrc/bun_core/env.rssrc/bun_core/lib.rssrc/bun_core/string/immutable/unicode.rssrc/collections/bit_set.rssrc/collections/multi_array_list.rssrc/crash_handler/lib.rssrc/css/values/color.rssrc/http_jsc/websocket_client/WebSocketUpgradeClient.rssrc/install/PackageManager/CommandLineArguments.rssrc/install/resolvers/folder_resolver.rssrc/js_parser/parse/parse_typescript.rssrc/js_printer/lib.rssrc/jsc/bindings/ANSIHelpers.hsrc/jsc/bindings/c-bindings.cppsrc/jsc/bindings/xxhash3.cppsrc/options_types/compile_target.rssrc/react_compiler/ssa/enter_ssa.rssrc/router/lib.rssrc/runtime/cli/install.ps1src/runtime/cli/install.shsrc/runtime/cli/upgrade_command.rssrc/runtime/image/codecs.rssrc/runtime/node/path.rssrc/runtime/socket/udp_socket.rssrc/runtime/valkey_jsc/valkey.rssrc/runtime/webcore/encoding.rssrc/sql_jsc/mysql/MySQLValue.rstest/internal/source-lints/webkit-prebuilt-url.test.tstest/internal/source-lints/windows-cross-config.test.ts
💤 Files with no reviewable changes (3)
- src/jsc/bindings/c-bindings.cpp
- src/bun_core/env.rs
- scripts/build/buildOptionsRs.ts
890c0cd to
bcae883
Compare
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.buildkite/ci.mjs:
- Around line 1592-1621: Add automated pipeline-generation regression tests
covering the relevantTestPlatforms filtering for main without ASAN, release test
dependency wiring through testStepKeys, and getBinarySizeStep behavior for main
versus non-LTO and LTO builds. Keep the assertions focused on generated steps
and dependencies, and place the coverage alongside the existing
.buildkite/ci.mjs pipeline-generation tests.
- Line 1643: Filter ASAN platforms out of the buildPlatforms list before passing
it to getReleaseStep in the steps.push release-step construction, while
preserving all other platform dependencies and existing release options.
In `@packages/bun-release/src/platform.ts`:
- Around line 133-136: Add automated postinstall platform-selection coverage for
supportedPlatforms, using the x64 Linux-musl scenario to assert that the plain
package is selected, the compatibility alias is excluded, and the Linux-musl
match remains included. Place the regression test alongside the existing
platform-selection tests and preserve the current filtering behavior.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: edb90c0a-02db-498d-9986-c2a654e275ac
📒 Files selected for processing (52)
.buildkite/ci.mjs.buildkite/scripts/upload-release.sh.github/workflows/clippy.yml.github/workflows/format.yml.github/workflows/miri.ymlpackages/bun-release/src/platform.tsrust-toolchain.tomlscripts/bootstrap.shscripts/build/buildOptionsRs.tsscripts/build/ci.tsscripts/build/config.tsscripts/build/deps/brotli.tsscripts/build/deps/webkit.tsscripts/build/flags.tsscripts/build/rust.tsscripts/build/source.tsscripts/build/tools.tssrc/ast/char_freq.rssrc/boringssl/lib.rssrc/bun_alloc/lib.rssrc/bun_bin/lib.rssrc/bun_core/Global.rssrc/bun_core/build.rssrc/bun_core/env.rssrc/bun_core/lib.rssrc/bun_core/string/immutable/unicode.rssrc/collections/bit_set.rssrc/collections/multi_array_list.rssrc/crash_handler/lib.rssrc/css/values/color.rssrc/http_jsc/websocket_client/WebSocketUpgradeClient.rssrc/install/PackageManager/CommandLineArguments.rssrc/install/resolvers/folder_resolver.rssrc/js_parser/parse/parse_typescript.rssrc/js_printer/lib.rssrc/jsc/bindings/ANSIHelpers.hsrc/jsc/bindings/c-bindings.cppsrc/jsc/bindings/xxhash3.cppsrc/options_types/compile_target.rssrc/react_compiler/ssa/enter_ssa.rssrc/router/lib.rssrc/runtime/cli/install.ps1src/runtime/cli/install.shsrc/runtime/cli/upgrade_command.rssrc/runtime/image/codecs.rssrc/runtime/node/path.rssrc/runtime/socket/udp_socket.rssrc/runtime/valkey_jsc/valkey.rssrc/runtime/webcore/encoding.rssrc/sql_jsc/mysql/MySQLValue.rstest/internal/source-lints/webkit-prebuilt-url.test.tstest/internal/source-lints/windows-cross-config.test.ts
💤 Files with no reviewable changes (4)
- scripts/build/deps/brotli.ts
- scripts/build/buildOptionsRs.ts
- src/jsc/bindings/c-bindings.cpp
- src/bun_core/env.rs
|
The debian-13 x64-asan lane surfaced a latent 200ms guard-timer flake in |
…#35132) Fixes `test/js/third_party/socket.io/socket.io-connection-state-recovery.test.ts` going red on the debian-13 x64-asan lane. ## Failure ``` error: timeout at <anonymous> (test/js/third_party/socket.io/socket.io-connection-state-recovery.test.ts:46:26) ✗ connection state recovery > should restore session and missed packets [219.96ms] ``` Seen on builds [77055](https://buildkite.com/bun/bun/builds/77055) (219.84ms) and [77789](https://buildkite.com/bun/bun/builds/77789) (219.96ms), both debian-13 x64-asan. ## Cause Each test in this file carries a `setTimeout(() => fail(...), 200)` guard that was added when the suite was ported from upstream socket.io in fe74c94. The [upstream test](https://github.com/socketio/socket.io/blob/main/packages/socket.io/test/connection-state-recovery.ts) has no such timers. These tests drive the Engine.IO long-polling transport by hand via supertest: the first test performs 8 sequential HTTP round trips. On release that is ~50ms; on release+ASAN it is ~220ms. #34782 moved the x64-asan build lane from amazonlinux-2023 to debian-13 on Jul 21, and the failures started immediately after, with the work landing just past the 200ms guard every time. The guard is not a behavioral assertion. It races real work against a wall clock and turns a slow-but-correct run into a failure. The test runner already applies its own per-test timeout (90s, tripled under ASAN in CI). ## Fix Drop the guard timers and align with the upstream structure: plain `async` tests that await the protocol events, with `io.close()` in a `finally` block so the server is always released. Every assertion is preserved; the same code paths are exercised. ## Verification ``` # before, bun bd (debug+asan), 5 runs: 0 pass / 7 fail every time # after, bun bd (debug+asan), 5 runs: 7 pass / 0 fail (×5) # release bun, 3 runs: 7 pass / 0 fail (×3) ``` <!-- robobun:evidence:begin --> --- **[stamp-90s]** gate passed · iteration 0 · 1 files touched <details><summary>passes on PR (with fix)</summary> ```console Test-only change. Debug/ASAN (expected pass): $ bun bd test 'test/js/third_party/socket.io/socket.io-connection-state-recovery.test.ts' $ BUN_DEBUG_QUIET_LOGS=1 bun scripts/build.ts --profile=debug --quiet test test/js/third_party/socket.io/socket.io-connection-state-recovery.test.ts bun test v1.4.0 (70a1c05) test/js/third_party/socket.io/socket.io-connection-state-recovery.test.ts: (pass) connection state recovery > should restore session and missed packets [2559.28ms] (pass) connection state recovery > should restore rooms and data attributes [1087.52ms] (pass) connection state recovery > should not run middlewares upon recovery by default [1125.18ms] (pass) connection state recovery > should run middlewares even upon recovery [1000.73ms] (pass) connection state recovery > should fail to restore an unknown session [421.80ms] (pass) connection state recovery > should be disabled by default [434.45ms] (pass) connection state recovery > should not call adapter#persistSession or adapter#restoreSession if disabled [405.80ms] 7 pass 0 fail 43 expect() calls Ran 7 tests across 1 file. [14.50s] Exit: 0 ``` </details> <details><summary>diff hotspot</summary> ``` .../socket.io-connection-state-recovery.test.ts | 318 +++++++++------------ 1 file changed, 134 insertions(+), 184 deletions(-) ``` </details> **gate history** · 1 passed · 0 rejected · iteration 0 <details><summary>evidence per changed file</summary> ``` file reads edits tests …y/socket.io/socket.io-connection-state-recovery.test.ts 2 3 0 ``` </details> **self-review** · no surviving concerns 25 concerns were raised and did not survive verification. **root cause** · written by the author bot The test wrapped its async work in a hardcoded 200ms setTimeout guard that was not a behavioral assertion, and on slow ASAN builds the real protocol steps outran that window, so the guard fired and failed the test even though the code under test behaved correctly. The fix removes the wall-clock guards entirely and converts each test to a plain async function that awaits the protocol steps directly, with server cleanup moved into a try/finally block. Hangs are now bounded by the test runner's per-test timeout rather than an arbitrary 200ms race, and all original assertions are preserved. <!-- robobun:evidence:end -->
|
Heads up: under queue backlog the rust-and-link poll in |
…ailure (#37915) ### Problem - Build lanes die in a dep fetch: `error: Failed to download after 5 attempts: https://github.com/oven-sh/lol-html/archive/725ce499....tar.gz`, `cause: fetch failed`. Build 93382 lost linux x64-asan on lolhtml. Build 93392 (a one-file PR) lost four lanes: x64-musl and x64-android on cares, mimalloc and the WebKit tarball, freebsd aarch64 on lolhtml, windows aarch64 on cares, libuv, mimalloc and WebKit. - Those are the downloads that miss the image's prefetch cache (everything else in the same logs says `using prefetch cache`): the deps whose pins moved after the images were baked in #34782 (lolhtml #36733, mimalloc #36431, c-ares #34007, libuv #36839, WebKit several times a week), plus WebKit on every lane other than linux arm64, because `prefetch-deps.ts` only enumerates the bake host's own target (handed off separately). Each build makes on the order of a hundred live github.com downloads. - `downloadWithRetry` (`scripts/build/download.ts:156`) made 5 attempts with 2+4+8+16s of backoff, about 30s in total. The logs show agent-wide outages longer than that: on the x64-musl lane three downloads that started together failed on all five attempts over roughly two minutes, after lolhtml had succeeded on the same agent seconds earlier; on the freebsd lane lolhtml failed five times in a row while cares and mimalloc went through and WebKit succeeded on its second try. - `BuildError.format()` (`scripts/build/error.ts:33`) prints one level of cause. node's fetch throws `TypeError: fetch failed` and keeps the real error (DNS, connect timeout, reset) in `.cause`, so every one of these logs says only `cause: fetch failed`, and the retry lines say nothing about what failed. ### Fix - `downloadRetry`: 10 attempts, backoff doubling from 2s and capped at 30s, 180s of backoff in total instead of 30s. Exported as a `RetryPolicy` (optional last parameter of `downloadWithRetry`) so the test can run the production attempt count with the backoff zeroed. - 408 and 429 are retried along with 5xx and network errors. Other 4xx still fail on the first attempt and are still thrown unwrapped, which `prefetch-deps.ts` relies on to tell a 404 (variant not published) from a transient failure. - Each retry line names the failure it is retrying, e.g. `retry 2/10 in 2000ms (fetch failed: other side closed)`, and `format()` prints the whole cause chain through the new `describeError()`, so the next one of these says what the network did. - Why here: the prefetch cache goes stale by design as soon as a pin moves, and WebKit moves faster than images get rebaked (the images were rebaked on July 21 and this came back within two weeks; #30095 was an earlier rebake for the same symptom), so the live path is permanently on every build's critical path and has to outlast the outages CI actually sees. The wider window only costs time while github.com is actually down, when the lane would otherwise have failed; build-bun's step timeout is 60 minutes. - Verified with `test/internal/build-download-retry.test.ts` (`bun bd test`, 7 pass). It drives the real `downloadWithRetry` against a local server that drops connections or returns scripted statuses, checks the retry lines and `format()` output, and pins the schedule's total backoff at two minutes or more. Against the previous `download.ts`/`error.ts` the file fails at import (`downloadRetry` and `describeError` did not exist); each behavioral case is something the old loop did not do (10 attempts, 429 retried, reason on the retry line, cause chain in `format()`). - Also ran the loop under node, the runtime CI builds with, against a dropping server: retry lines read `(fetch failed: other side closed)` and the final report prints `cause: fetch failed: other side closed`. `bunx tsc -p scripts/build/tsconfig.json` reports nothing for these files. ### Background - Dep fetching: configure emits one ninja `dep_fetch` edge per vendored dep, which runs `scripts/build/fetch-cli.ts`; that calls `downloadWithRetry` on `https://github.com/<repo>/archive/<commit>.tar.gz`, and `fetchPrebuilt` uses the same function for release tarballs such as WebKit. Both URL kinds start with a 302 from github.com (to codeload.github.com and objects.githubusercontent.com respectively), which is why one github.com problem takes out both kinds at once. - Prefetch cache: CI images run `scripts/prefetch-deps.ts` at bake time, storing each tarball under `/opt/bun-prefetch/by-url/<sha256(url)>`. `downloadWithRetry` looks there before touching the network, so a dep is served from the image only while its pinned URL is the one that was current at bake time; anything bumped later downloads live until the next `[publish images]` rebake. - `BuildError` is the build system's error type; `fetch-cli.ts` and `build.ts` print failures through its `format()`, which produces the `error:` / `hint:` / `cause:` lines seen in the build log.
One image bake covering a set of coupled CI/build changes. Commit subject carries
[build images]so the v40 images bake on this PR.What
Single arm64 debian-12 build host
Every build lane (all 13 targets: linux x64/aarch64 gnu/musl/android/asan, darwin x64/aarch64, freebsd x64/aarch64, windows x64/aarch64) now runs on one
linux-aarch64-12-debianhost image and cross-compiles to its target via--target+--sysroot.buildHostPlatformin.buildkite/ci.mjsis the single source of truth;getCppAgent()/getLinkBunAgent()always pickc8g.4xlarge/r8g.2xlarge.getBuildArgs()always emits--os/--arch/--abisoresolveConfig()never infers target from the host.scripts/build/config.tsgains a Linux cross-arch/cross-abi block: when targetarchorabidiffers from the host's,crossTargetis set to<arch>-unknown-linux-<gnu|musl>andsysrootto the matching/opt/linux-sysroot-{glibc,musl}{,-arm64}.scripts/build/flags.tsadds the matching--target/--sysrootlinkerFlags entry.scripts/build/shims.tspoints the musl CRT-print-file-nameprobe at the sysroot when cross-compiling.bootstrap.sh v40
install_linux_glibc_sysroot(): extracts glibc 2.17 headers/libs + devtoolset libstdc++ fromquay.io/pypa/manylinux2014_<arch>:latestviaskopeo copy dir:+ manifest-ordered layer unpack into/opt/linux-sysroot-glibc{,-arm64}. Best-effort during bake (prints a warning, does not abort); the build throws a clearBuildErrorif missing when cross-compiling.install_linux_musl_sysroot(): extracts<triple>/+lib/gcc/frommusl.cc/<arch>-linux-musl-cross.tgzinto/opt/linux-sysroot-musl{,-arm64}.install_macos_sdk(): fetchesscripts/build/xmac.mjsatBUN_BOOTSTRAP_REPO_REFand splats the pinned SDK into/opt/macos-sdk, so the per-job Apple CDN fetch in configure goes away.install_cross_compiler_rt(): best-effortdpkg --add-architecture amd64+libclang-rt-<v>-dev:amd64on arm64 debian so x64 asan cross can link. If apt.llvm.org lacks the amd64 packages on arm64 repos, the asan lane is the one candidate for an x64-host exception.install_rust(): adds{x86_64,aarch64}-unknown-linux-{gnu,musl}rustup targets.clean_system():apt-get clean/dnf clean all/apkcache purge,rm -rf /tmp/*, andfstrim -avbefore snapshot to shrink the EBS snapshot.install_osxcrosspath and--osxcrossflag removed;lsb-releaseandqemu-useradded to apt installs.rust-and-link merged step
getBuildRustStep()andgetLinkBunStep()collapse into onegetBuildBunStep()(key*-build-bun,timeout_in_minutes: 60) that runsci-rust-and-link:ninja bun-rust, pollbuildkite-agent step get outcome --step <target>-build-cpp(60m deadline), download the cpp archive, link, package. build-cpp runs in parallel with nodepends_onbetween them.test/release/verify-baseline/binary-sizedepends_onstay on*-build-bun.PR builds skip LTO
getBuildArgs()passes--lto=offon non-main branches.[lto]in the commit subject opts back in.binary-sizeis annotate-only on non-LTO PRs.mainkeeps LTO.Tests on
main, canary gated on greenThe
!isMainBranch()guard around test steps is dropped (asan stays PR-only).getReleaseStep()depends_onevery*-test-bunkey.Test shards in their own groups
Test groups are keyed on
getPlatformKey/getPlatformLabel(distro + release) instead ofgetTargetKey/getTargetLabel, so they no longer merge into the build groups by label. Build groups depend only on thebuildHostPlatformimage; test groups depend on their own native image.verify-baseline stays arch-matched
getVerifyBaselineHost()picks a per-target-arch native host (debian-13 / windows-2019) so the pinned qemu/SDE binaries keep working.scripts/verify-baseline.tsaccepts--archinstead of inferring fromprocess.arch.x64 is baseline-only
scripts/build/config.tsdefaultsbaseline = trueon x64,scripts/build/flags.tsdrops-march=haswell. Non-baseline x64 lanes removed fromci.mjs.upload-release.shgainsalias_baseline_artifact()+rezip_as()which rezips each x64 artifact under its old non-baseline name so existing download URLs keep resolving.ENABLE_SIMDandBASELINEenv constants removed fromsrc/bun_core/env.rs;bun_warn_avx_missingremoved fromc-bindings.cppandlib.rs.Rust nightly-2026-07-20
Folds #34452.
#[allow(suspicious_runtime_symbol_definitions)]on thesafe fnlibc extern blocks insrc/bun_core/Global.rsandsrc/sys/lib.rsfor the new lint.scripts/packer/build-image.pkr.hcl
New Packer template with
docker+amazon-ebssources both runningscripts/bootstrap.sh, so localdocker runand CI AMIs share one provisioner. Not yet wired intomachine.mjs.Verification
Generated
.buildkite/ci.ymlunder[build images]/[publish images]/[build linux images]/ plain-PR: all YAML-valid, 0 danglingdepends_on, 0 duplicate keys. Bake set is 9 images (1 build host + 8 test-platform).sh -n/bash -nonbootstrap.shandupload-release.sh.bunx tsc --noEmit -p scripts/build/tsconfig.jsonintroduces no new errors.cargo check --workspace --target {x86_64,aarch64}-unknown-linux-{gnu,musl}and{aarch64-apple-darwin, x86_64-unknown-freebsd, aarch64-pc-windows-msvc}all pass.bun bdbuilds;bun bd teston the four config/flags/shims-touching internal tests passes.The actual cross-link of x64/musl binaries from an arm64 host is not exercisable locally (needs the baked sysroots); the
[build images]run on this PR is the first end-to-end exercise.no test proof · iteration 32 · Platform-specific test(s) that do not run on this machine. Deferring to CI, which covers all platforms: test/cli/run/require-cache.test.ts test/internal/macos-cross-config.test.ts test/internal/source-lints/windows-cross-config.test.ts test/js/bun/perf/linker-order.test.ts test/napi/napi.test.ts