Skip to content

Commit b13071a

Browse files
committed
feat(bun): support native binary lockfile patching
1 parent 4b61c96 commit b13071a

111 files changed

Lines changed: 6198 additions & 2361 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.github/workflows/bun-compatibility.yml‎

Lines changed: 57 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@ on:
1616
paths:
1717
- '.github/actions/upload-artifact/**'
1818
- '.github/workflows/bun-compatibility.yml'
19-
- 'scripts/backtest-bun.py'
19+
- 'scripts/backtest-bun*.py'
20+
- 'scripts/bun-historical-shas.json'
21+
- 'crates/socket-patch-cli/tests/e2e_bun_lockb.rs'
22+
- 'crates/socket-patch-core/tests/fixtures/bun-lockb/**'
2023
- 'docs/testing/bun-compatibility.md'
2124
- 'Cargo.lock'
2225
- 'crates/socket-patch-core/src/vendor/**'
@@ -45,12 +48,13 @@ on:
4548
branches: [main]
4649
paths:
4750
- '.github/workflows/bun-compatibility.yml'
48-
- 'scripts/backtest-bun.py'
51+
- 'scripts/backtest-bun*.py'
52+
- 'scripts/bun-historical-shas.json'
53+
- 'crates/socket-patch-cli/tests/e2e_bun_lockb.rs'
54+
- 'crates/socket-patch-core/tests/fixtures/bun-lockb/**'
4955
- 'Cargo.lock'
5056
- 'crates/socket-patch-core/src/vendor/**'
51-
- 'crates/socket-patch-core/src/patch/redirect/mod.rs'
52-
- 'crates/socket-patch-core/src/patch/redirect/replay.rs'
53-
- 'crates/socket-patch-core/src/patch/redirect/takeover.rs'
57+
- 'crates/socket-patch-core/src/patch/redirect/**'
5458
- 'crates/socket-patch-cli/src/commands/get.rs'
5559
- 'crates/socket-patch-cli/src/commands/scan/**'
5660
- 'crates/socket-patch-cli/src/commands/rollback.rs'
@@ -130,7 +134,7 @@ jobs:
130134
# Every lock-format and behaviour boundary the CLI has to survive:
131135
# 0.8.1 / 1.0.0 / 1.0.36 / 1.1.0 / 1.1.38 binary bun.lockb only
132136
# 1.1.39 first text lock (lockfileVersion 0, opt-in)
133-
# 1.1.43 first `--lockfile-only` (the lockb migration recipe)
137+
# 1.1.43 first `--lockfile-only`
134138
# 1.1.45 last v0 writer
135139
# 1.2.0 / 1.2.23 / 1.3.0 text default, lockfileVersion 1
136140
# 1.3.9 / 1.3.10 URL/local tarball sha512 enforcement boundary
@@ -327,3 +331,50 @@ jobs:
327331
native-bun/captures/**/tree/**
328332
native-bun/captures/**/*.log
329333
retention-days: 14
334+
335+
336+
binary:
337+
strategy:
338+
fail-fast: false
339+
matrix:
340+
os: [ubuntu-latest, macos-latest, windows-latest]
341+
runs-on: ${{ matrix.os }}
342+
timeout-minutes: 30
343+
steps:
344+
- name: Checkout
345+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
346+
with:
347+
persist-credentials: false
348+
349+
- name: Cache cargo
350+
uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
351+
with:
352+
key: bun-native-binary
353+
save-if: ${{ github.ref == 'refs/heads/main' }}
354+
355+
- name: Setup Python
356+
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
357+
with:
358+
python-version: '3.12'
359+
360+
- name: Native binary writer and reader acceptance
361+
shell: bash
362+
run: |
363+
versions=()
364+
# Windows releases begin at 1.1.0. Unix exercises all binary
365+
# schema boundaries, including the earliest format-1 writer.
366+
if [ "$RUNNER_OS" = "Windows" ]; then
367+
versions=(--versions 1.1.0 1.1.38 1.1.45 1.2.0 1.2.23 1.3.0 1.3.14 1.4.2)
368+
fi
369+
python3 scripts/backtest-bun-lockb.py \
370+
--tools native-binary/tools \
371+
--output native-binary/results \
372+
--jobs 2 "${versions[@]}"
373+
374+
- name: Upload binary acceptance results
375+
if: always()
376+
uses: ./.github/actions/upload-artifact
377+
with:
378+
name: bun-binary-results-${{ matrix.os }}
379+
path: native-binary/results
380+
retention-days: 14

‎README.md‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,15 @@ Mode support varies by ecosystem — e.g. Go can't do hosted, Rush monorepos can
254254
vendored. See the full **[mode × ecosystem matrix](docs/ecosystems.md#mode--ecosystem-matrix)**
255255
for details and per-ecosystem caveats.
256256
257+
### Bun compatibility
258+
259+
Both text `bun.lock` and binary `bun.lockb` support hosted and vendored
260+
patches, mode switching, repair, and rollback. Binary locks are read and
261+
patched natively: Socket Patch does not need Bun installed to discover or
262+
rewrite them, and does not convert them to text. If both filenames exist,
263+
`bun.lock` takes precedence. See [Bun compatibility](docs/testing/bun-compatibility.md)
264+
for the tested versions, workspace behavior, and installer integrity limits.
265+
257266
### Pipenv compatibility
258267
259268
Hosted mode rewrites every `Pipfile.lock` category that pins the patched

‎crates/socket-patch-cli/CLI_CONTRACT.md‎

Lines changed: 19 additions & 20 deletions
Large diffs are not rendered by default.

‎crates/socket-patch-cli/src/commands/bun_preflight.rs‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
//!
88
//! One read-only [`preflight_vendor`] per run, evaluated before any
99
//! `/patches/view/` fetch and before any write, so an incompatible Bun
10-
//! project (binary `bun.lockb` without a text lock, an unreadable lock, an
10+
//! project (malformed binary `bun.lockb`, an unreadable lock, an
1111
//! unsupported `lockfileVersion`, a pre-version-2 `workspace:` lock) never
1212
//! has a patch downloaded on its behalf — let alone recorded in the
1313
//! manifest, or its live hosted redirect stripped — and every entry point
@@ -50,7 +50,7 @@ pub(crate) type LedgerLoad<'a> = Result<&'a HashMap<String, VendorEntry>, &'a st
5050
///
5151
/// [`wired_instances_all_ours`]: socket_patch_core::vendor::bun_lock::wired_instances_all_ours
5252
pub(crate) struct BunVendorRefusal {
53-
/// The stable vendor error code (`vendor_bun_lockb_unsupported`,
53+
/// The stable vendor error code (`vendor_bun_lockb_invalid`,
5454
/// `vendor_lockfile_missing`, `vendor_lockfile_version_unsupported`,
5555
/// `vendor_bun_workspace_unsupported`) — the same string the vendor
5656
/// engine would have emitted as a `failed` event — or
@@ -283,15 +283,15 @@ mod tests {
283283
let npm = vec![sel(UUID, PURL)];
284284
let refusal = bun_vendor_preflight(tmp.path(), &npm)
285285
.await
286-
.expect("lockb-only project is refused");
287-
assert_eq!(refusal.code, "vendor_bun_lockb_unsupported");
286+
.expect("malformed lockb project is refused");
287+
assert_eq!(refusal.code, "vendor_bun_lockb_invalid");
288288
assert!(refusal.applies_to(PURL));
289289
assert!(!refusal.applies_to("pkg:pypi/only@1.0.0"));
290290

291-
// A ledger at this UUID cannot make a binary lock vendorable.
291+
// A ledger at this UUID cannot make a malformed binary lock vendorable.
292292
seed_bun_vendor_entry(tmp.path(), PURL, UUID);
293293
let refusal = bun_vendor_preflight(tmp.path(), &npm).await.unwrap();
294-
assert_eq!(refusal.code, "vendor_bun_lockb_unsupported");
294+
assert_eq!(refusal.code, "vendor_bun_lockb_invalid");
295295
assert!(refusal.applies_to(PURL), "the live lock must be compatible");
296296

297297
// …but a corrupt ledger exempts nothing and names itself.

‎crates/socket-patch-cli/src/commands/get.rs‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5198,7 +5198,7 @@ mod tests {
51985198

51995199
#[tokio::test]
52005200
#[serial_test::serial]
5201-
async fn download_patch_records_bun_lockb_refuses_before_fetch() {
5201+
async fn download_patch_records_malformed_bun_lockb_refuses_before_fetch() {
52025202
use wiremock::matchers::{method, path as wm_path};
52035203
use wiremock::{Mock, MockServer, ResponseTemplate};
52045204

@@ -5234,7 +5234,7 @@ mod tests {
52345234
assert_eq!(json["failed"], 1, "json={json}");
52355235
assert_eq!(json["patches"][0]["action"], "failed", "json={json}");
52365236
assert_eq!(
5237-
json["patches"][0]["errorCode"], "vendor_bun_lockb_unsupported",
5237+
json["patches"][0]["errorCode"], "vendor_bun_lockb_invalid",
52385238
"json={json}"
52395239
);
52405240
assert!(

0 commit comments

Comments
 (0)