Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 78 additions & 6 deletions .github/workflows/bun-compatibility.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@ on:
paths:
- '.github/actions/upload-artifact/**'
- '.github/workflows/bun-compatibility.yml'
- 'scripts/backtest-bun.py'
- 'scripts/backtest-bun*.py'
- 'scripts/probe-bun-historical-linux.py'
- 'scripts/bun-historical-shas.json'
- 'crates/socket-patch-cli/tests/e2e_bun_lockb.rs'
- 'crates/socket-patch-core/tests/fixtures/bun-lockb/**'
- 'docs/testing/bun-compatibility.md'
- 'Cargo.lock'
- 'crates/socket-patch-core/src/vendor/**'
Expand Down Expand Up @@ -45,12 +49,14 @@ on:
branches: [main]
paths:
- '.github/workflows/bun-compatibility.yml'
- 'scripts/backtest-bun.py'
- 'scripts/backtest-bun*.py'
- 'scripts/probe-bun-historical-linux.py'
- 'scripts/bun-historical-shas.json'
- 'crates/socket-patch-cli/tests/e2e_bun_lockb.rs'
- 'crates/socket-patch-core/tests/fixtures/bun-lockb/**'
- 'Cargo.lock'
- 'crates/socket-patch-core/src/vendor/**'
- 'crates/socket-patch-core/src/patch/redirect/mod.rs'
- 'crates/socket-patch-core/src/patch/redirect/replay.rs'
- 'crates/socket-patch-core/src/patch/redirect/takeover.rs'
- 'crates/socket-patch-core/src/patch/redirect/**'
- 'crates/socket-patch-cli/src/commands/get.rs'
- 'crates/socket-patch-cli/src/commands/scan/**'
- 'crates/socket-patch-cli/src/commands/rollback.rs'
Expand Down Expand Up @@ -125,12 +131,15 @@ jobs:
needs: build
strategy:
fail-fast: false
# Each job runs three cells against the public patch service. Bound
# concurrent jobs so the full release matrix does not flood that API.
max-parallel: 6
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
# Every lock-format and behaviour boundary the CLI has to survive:
# 0.8.1 / 1.0.0 / 1.0.36 / 1.1.0 / 1.1.38 binary bun.lockb only
# 1.1.39 first text lock (lockfileVersion 0, opt-in)
# 1.1.43 first `--lockfile-only` (the lockb migration recipe)
# 1.1.43 first `--lockfile-only`
# 1.1.45 last v0 writer
# 1.2.0 / 1.2.23 / 1.3.0 text default, lockfileVersion 1
# 1.3.9 / 1.3.10 URL/local tarball sha512 enforcement boundary
Expand Down Expand Up @@ -326,4 +335,67 @@ jobs:
native-bun/captures/**/cli-output.json
native-bun/captures/**/tree/**
native-bun/captures/**/*.log
native-bun/attempts/**
retention-days: 14


binary:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, ubuntu-22.04, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
timeout-minutes: 30
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false

- name: Cache cargo
uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
with:
# Keep binaries linked against different glibc versions separate.
key: bun-native-binary-${{ matrix.os }}
save-if: ${{ github.ref == 'refs/heads/main' }}

- name: Setup Python
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
with:
python-version: '3.12'

- name: Native binary writer and reader acceptance
shell: bash
env:
MATRIX_OS: ${{ matrix.os }}
run: |
versions=()
# Windows releases begin at 1.1.0. Ubuntu 22.04 and macOS exercise
# every schema boundary, including the earliest format-1 writer.
if [ "$RUNNER_OS" = "Windows" ]; then
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)
elif [ "$MATRIX_OS" = "ubuntu-latest" ]; then
# Bun 0.5.9/0.6.x segfault during pristine HTTP initialization
# on the Ubuntu 24.04 runner; the complete matrix remains
# required on Ubuntu 22.04, with modern releases on both hosts.
versions=(--versions 0.8.1 1.0.0 1.0.36 1.1.0 1.1.38 1.1.45 1.2.0 1.2.23 1.3.0 1.3.14 1.4.2)
fi
python3 scripts/backtest-bun-lockb.py \
--tools native-binary/tools \
--output native-binary/results \
--jobs 2 "${versions[@]}"

- name: Diagnose historical Linux runtime failures
if: failure() && runner.os == 'Linux'
run: >-
python3 scripts/probe-bun-historical-linux.py
--tools native-binary/tools
--output native-binary/results/linux-diagnostics

- name: Upload binary acceptance results
if: always()
uses: ./.github/actions/upload-artifact
with:
name: bun-binary-results-${{ matrix.os }}
path: native-binary/results
retention-days: 14
48 changes: 16 additions & 32 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ into the new version's section — see docs/releasing.md.

### Changed (BREAKING)

- **Binary Bun lockfiles are patched natively in place.** Hosted and vendored
modes read and rewrite `bun.lockb` formats 1–3 directly, including mode
changes, repair, and scoped rollback. Binary-to-text conversion, migration
ledger replay, and their warning codes and tests have been removed.
- **`rollback` is now the full-state dual of `scan`.** `scan` and `rollback`
are the batch primaries (`get`↔`remove` stay the single-patch duals): a
bare `rollback` restores the SYSTEM to unpatched across all three modes —
Expand Down Expand Up @@ -248,12 +252,8 @@ into the new version's section — see docs/releasing.md.
table, staged all-or-nothing per ecosystem group, covering gem, golang,
pypi, composer, bun, and the non-package rideshare edits (pnpm
`trustLockfile` auto-config — pristine scaffold deleted, modified
scaffold keeps the file and loses only the owned line). The bun.lockb
migration marker restores the binary lock from the bytes the ledger
captured (`redirect_bun_lockb_restored`; the generated `bun.lock` is kept)
and warns `redirect_bun_lockb_unrestorable` naming git history only when
the ledger holds no bytes and the file is absent, or a different
`bun.lockb` has appeared since;
scaffold keeps the file and loses only the owned line). Native `bun.lockb`
package snapshots restore binary resolutions directly;
maven and nuget fail closed with `hosted_revert_unsupported` guidance
(their structured-metadata edits keep their ledger records; re-run
`scan --mode hosted` or restore from VCS). Refused groups keep their
Expand All @@ -272,7 +272,7 @@ into the new version's section — see docs/releasing.md.
an existing vendored patch, including during dry-run. Vendored preflight
exemptions require live local lock tuples; a ledger retained by
`rollback --preserve-state` cannot bypass a refusal or hide it in a preview.
Symlinked `bun.lockb` files are refused before migration so their links
Symlinked `bun.lockb` files are refused before patching so their links
survive, and `vendor --silent` keeps refusal diagnostics on stderr.

- **Bun projects: every text-lock generation is accepted, vendored refusals
Expand Down Expand Up @@ -301,7 +301,7 @@ into the new version's section — see docs/releasing.md.
`.socket/vendor/state.json` met by that preflight is reported as
`vendor_state_unreadable` rather than a Bun lock code. `scan --mode vendored`,
`get --mode vendored` (search and uuid paths) and `--detached` runs now
preflight the Bun lock BEFORE any download: a binary-only, unreadable,
preflight the Bun lock BEFORE any download: a malformed binary, unreadable,
unsupported-version or pre-version-2 workspace lock marks the npm patches
`failed` with the vendor refusal code and detail, fetches nothing and
records no patch — the `scan` / `get <purl>` path still writes an unchanged
Expand All @@ -312,15 +312,10 @@ into the new version's section — see docs/releasing.md.
`package_not_installed`). The refusals stay visible under `--silent`
(code-tagged stderr line), `--dry-run` previews them as the additive
`would_refuse` action (the human `scan` and `get` previews both print the
`[would-refuse]` lines), the `bun.lockb` refusal carries one remedy on every
path (`bun install --save-text-lockfile`, Bun ≥ 1.1.39), and a `scan` on a
`bun.lockb`-only project warns `bun_lockb_unsupported` instead of reporting
a clean empty inventory — the detail names a shadowed sibling
`package-lock.json` / `yarn.lock` / `pnpm-lock.yaml` and the
delete-the-stale-lockb remedy when one exists, and the warning is kept in
hosted mode too (beside the driver's own `redirect_bun_lockb_*` outcome on
the run that migrates) instead of being dropped on every non-empty hosted
run. Hosted → vendored
`[would-refuse]` lines). Valid binary locks are inventoried and patched
directly without a Bun runtime; malformed binary locks report
`bun_lockb_invalid`, `redirect_bun_lockb_invalid`, or
`vendor_bun_lockb_invalid` at the corresponding entry point. Hosted → vendored
takeover now works for bun —
`scan`/`get --mode vendored` and `vendor` over a hosted-redirected `bun.lock`
claim and replay that purl's hosted edit instead of refusing
Expand All @@ -329,21 +324,10 @@ into the new version's section — see docs/releasing.md.
several hosted bun records; on a lock the vendored backend refuses (a
pre-version-2 workspace lock) `vendor` and its dry run report the refusal
BEFORE the hosted revert, leaving the purl hosted-patched instead of
un-hosting it and then refusing. The hosted `bun.lockb` migration is truthful:
`bun` is resolved on absolute `PATH` entries (Windows `bun.cmd` shims
included, spawned directly — the standard library quotes batch-shim paths
with spaces and metacharacters correctly), a stale `bun.lockb` beside a
live npm / yarn / pnpm lock is left alone (`redirect_bun_lockb_sibling_lock`;
the redirect follows the sibling lock) instead of converting the project to
`bun.lock`, a `bun.lockb` that is not a regular file is refused before
`bun` is spawned, a `bun.lockb` that Bun 1.1.43–1.1.45 keep beside the new text
lock is removed by the CLI so the ledger's `removed` edit is true, the
pre-migration bytes ride the ledger and `rollback` restores `bun.lockb`
(`redirect_bun_lockb_restored`; the generated `bun.lock` is kept), Bun
1.1.39–1.1.42 — which accept the flags but write nothing — get
`redirect_bun_lockb_manual_migration` instead of a false "unavailable", and
a failed spawn's `redirect_bun_lockb_unsupported` carries bun's output tail.
The hosted rewrite keeps CRLF on the rewritten `bun.lock` line. Real-Bun
un-hosting it and then refusing. Native `bun.lockb` edits preserve the
dependency graph and unrelated package metadata while updating binary
pointers, tarball integrity, and the package metadata hash. The hosted text
rewrite keeps CRLF on the rewritten `bun.lock` line. Real-Bun
coverage now runs in CI: the hermetic hosted and vendored suites on Linux,
macOS and Windows (Bun 1.4.2, plus 1.1.45 and 1.2.23 lock-era legs), and
the production native matrix — 16 releases from 0.8.1 to 1.4.2 in hosted,
Expand Down
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,15 @@ Mode support varies by ecosystem — e.g. Go can't do hosted, Rush monorepos can
vendored. See the full **[mode × ecosystem matrix](docs/ecosystems.md#mode--ecosystem-matrix)**
for details and per-ecosystem caveats.

### Bun compatibility

Both text `bun.lock` and binary `bun.lockb` support hosted and vendored
patches, mode switching, repair, and rollback. Binary locks are read and
patched natively: Socket Patch does not need Bun installed to discover or
rewrite them, and does not convert them to text. If both filenames exist,
`bun.lock` takes precedence. See [Bun compatibility](docs/testing/bun-compatibility.md)
for the tested versions, workspace behavior, and installer integrity limits.

### Pipenv compatibility

Hosted mode rewrites every `Pipfile.lock` category that pins the patched
Expand Down
Loading
Loading