Skip to content

chore(bindings): migrate pnpm→bun package management; Bun 1.4.0; deps latest stable - #27

Merged
andrescera merged 4 commits into
mainfrom
chore/bun-first-toolchain-upgrade
Aug 21, 2026
Merged

chore(bindings): migrate pnpm→bun package management; Bun 1.4.0; deps latest stable#27
andrescera merged 4 commits into
mainfrom
chore/bun-first-toolchain-upgrade

Conversation

@andrescera

Copy link
Copy Markdown
Member

What

Migrates bindings package management from pnpm to Bun (bun@1.4.0), rewrites the package-manager policy contract to enforce Bun-only, moves the two contract-verification scripts into the Bun-only bindings CI job, and replaces an undocumented ambient-Node dependency with an explicit, falsifiable Bun-shim proof. Also sweeps dependencies to the latest stable versions, including Biome 2.5.9 and @ceralive/biome-config 2026.8.1.

Why

Completes the workspace-wide Bun 1.4.0 migration and reverses the deliberate pnpm exception for this package per the plan decision. This is the sibling PR to merged root policy PR #81.

How to verify

cd bindings/typescript && bun install --frozen-lockfile && bun run lint && bun run typecheck && bun test && bun run build
bash scripts/bindings_package_manager_contract_test.sh
bash scripts/bindings_release_ref_contract_test.sh
uv run scripts/release_workflow_contract_test.py
uv run scripts/rust_cache_contract_test.py

Risks

Low — Rust workspace and workflows are untouched, golden fixtures remain byte-identical, and the dependency update uses published stable packages with no pre-releases.

…cy contract; Bun 1.4.0

The binding package/tests were already Bun-native while pnpm managed the
dependencies. This makes the package manager match the runtime: packageManager
is bun@1.4.0, bun.lock replaces pnpm-lock.yaml, and both binding CI lanes install
and run through Bun.

bindings_package_manager_contract_test.sh is inverted rather than deleted — the
old policy required pnpm and forbade bun.lock, the new one requires bun.lock and
forbids pnpm-lock.yaml/package-lock.json/yarn.lock plus any pnpm invocation in a
workflow. A second lockfile resolves a different dependency graph than the one CI
installs, and it does so silently, which is the failure this guards against.

The ci.yml bindings job now installs no Node: the root CI/CD STANDARD's Node 26
baseline exempts binding gates that execute under Bun. Node 26 + npm 11.18.0 stay
in publish-bindings.yml for the npm pack tarball guard, and the OIDC publish job
is untouched.

Biome is deliberately held at the 2.5.8 canon (via @ceralive/biome-config
2026.8.0) instead of floating to the newly published 2.5.9, so biome.json's
$schema stays truthful; the caret range is unchanged.
Todo 8 was dispatched before the root canon bump landed, so it deliberately
held Biome at 2.5.8. That hold is now skew. Bumps @biomejs/biome to ^2.5.9 and
the biome.json $schema URL to match.

@ceralive/biome-config stays at ^2026.8.0: 2026.8.1 is not published yet (it is
an unreleased source bump in the root worktree), and the caret range already
admits it, so this consumer picks it up automatically on the first install after
the root publish.
…b; replace node -p with bun -e (F1/F2/F4 review fix)

bindings_release_ref_contract_test.sh and bindings_package_manager_contract_test.sh
both evaluate JavaScript, but ran in ci.yml's Rust `test` job, which declares no JS
runtime at all — only setup-rust-toolchain and setup-uv. They worked purely on the
Node the ubuntu-latest image happens to preinstall. Masking `node` from PATH
reproduces exit 127 on both.

They now run in the `bindings` job, right after setup-bun, with working-directory: .
because they are repo-root scripts under a job whose default is bindings/typescript.
Their own `node -p` calls become `bun -e` + console.log, which produces byte-identical
output (verified with od -c for both the version and packageManager reads). No
setup-node was added anywhere: the Rust gate stays Rust/uv-only.

ci/verify-bindings-release-ref.sh is untouched. It is the sanctioned Node island —
publish-bindings.yml's Node-26 OIDC publish job runs it, and that is where its `node`
call is correct. But the release-ref contract test IS that island's test, so it
reaches the island's node from a Bun-only job. Rather than change the island, the
wrapper provisions a Bun-backed `node` shim and prepends it to PATH.

That prepend is UNCONDITIONAL, deliberately. A GitHub runner ships an ambient Node, so
an `if ! command -v node` guard would never fire where it matters: the island's node -p
would resolve to an unpinned ambient runtime and the test would report OK while proving
nothing about the Bun-only job it now lives in. Prepending always means every run
exercises the Bun path, and the script then asserts the result rather than assuming it —
`command -v node` must be the shim AND process.versions.bun must be set, a behavioral
check no real Node can pass, so a shim that exec'd node would also be caught. The
resolved runtime is echoed on the success line (node-runtime=bun@<version>) so every CI
log carries the proof. The export is scoped to the process; the production publish job
resolves its own real Node 26 and is untouched.

Note the wrapper's positive case runs before every expect_rejection, so a broken runtime
aborts under set -e instead of making the rejection assertions pass for the wrong reason;
do not reorder those lines.

release_workflow_contract_test.py drops the two now-stale job("test") assertions and
gains test_binding_contracts_run_under_bun_never_on_an_ambient_node, which requires
both scripts absent from the Rust gate, present in `bindings` after setup-bun, carrying
working-directory: ".", and no setup-node in either job. It fails on the pre-fix ci.yml.
workflow_contract.py's Step model gains working-directory so that override — without
which the repo-root paths do not resolve — is assertable rather than invisible.

Docs: AGENTS.md's Biome prose said 2.5.8 while package.json, bun.lock, and biome.json's
$schema are all 2.5.9 since the previous commit; its files.includes list was also
missing !dist. Both corrected, along with the job-location prose for the contract
scripts in AGENTS.md and README.md.
@andrescera
andrescera merged commit eb39636 into main Aug 21, 2026
10 checks passed
@andrescera
andrescera deleted the chore/bun-first-toolchain-upgrade branch August 21, 2026 16:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant