Skip to content

pm: honour --dry-run in link, unlink, pm version, pm cache rm, pm trust, pm pkg, and pm migrate - #41690

Open
robobun wants to merge 5 commits into
mainfrom
robobun/0e7c9450/pm-dry-run
Open

robobun wants to merge 5 commits into
mainfrom
robobun/0e7c9450/pm-dry-run

Conversation

@robobun

@robobun robobun commented Sep 6, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

  • --dry-run is parsed by every bun pm command and by bun link / bun unlink (their --help lists it as "Perform a dry run without making changes"), but none of them read it. bun link --dry-run creates the global symlink, bun unlink --dry-run deletes it, bun pm version <bump> --dry-run writes package.json, runs preversion / version / postversion, and commits and tags, bun pm cache rm --dry-run deletes the whole cache, bun pm trust <pkg> --dry-run runs the blocked scripts and writes package.json and bun.lock, bun pm pkg set|delete|fix --dry-run writes package.json, and bun pm migrate --dry-run writes bun.lock.
  • Cause: CommandLineArguments::parse sets cli.dry_run for every subcommand and Options::load copies it to options.dry_run (src/install/PackageManager/PackageManagerOptions.rs:746), but only the install path consults it. The commands above live in src/runtime/cli/ and go straight to their write.

Fix

  • Each command checks options.dry_run right before its first write and stops there: link / unlink print the symlink path that would be created or removed, pm version prints the new version only (no scripts, no write, no git), pm cache rm prints the cache directory and each bunx-* temp directory it would delete, pm trust prints the scripts that would run and the names it would add to trustedDependencies, pm pkg prints the resulting package.json to stdout, and pm migrate prints the lockfile it would save (bun.lock or bun.lockb, from LoadResult::save_format, which becomes pub with LockfileFormat::filename).
  • Read-only steps before the write still run, so a dry run reports the same errors the real run would: pm version still checks for a dirty git tree, pm trust still loads the lockfile and resolves the untrusted scripts, pm migrate still parses the foreign lockfile.
  • Correct because --dry-run is documented for these commands as "without making changes" and bun install --dry-run already means no node_modules, no lockfile, and no package.json writes.
  • Verified: new cases in test/cli/install/bun-link.test.ts, bun-pm-version.test.ts, bun-pm-pkg.test.ts, bun-pm.test.ts, migration/migrate.test.ts, and bun-install-lifecycle-scripts.test.ts (all fail on the released binary, pass with the fix). Also ran each of those files in full.

Background

  • bun pm <cmd>, bun link, and bun unlink share the install CommandLineArguments parser and PackageManager::Options. --dry-run is one of the shared params, so every one of these commands accepts it.
  • The global link directory is $BUN_INSTALL/install/global/node_modules. bun link symlinks the current package into it, and bun link <name> in another project resolves through it.
  • bun pm trust runs the lifecycle scripts of dependencies that were blocked at install time and records their names in trustedDependencies in both package.json and bun.lock.
Notes

no test proof · iteration 0 · platform-specific test(s) that do not run on this machine, deferring to CI, which covers all platforms: test/cli/install/migration/migrate.test.ts, test/cli/install/bun-link.test.ts, test/cli/install/bun-install-lifecycle-scripts.test.ts

…st, pm pkg, and pm migrate

--dry-run was parsed by each of these commands but never read. link
created the global symlink, unlink deleted it, pm version wrote
package.json and ran the version scripts and git commit/tag, pm cache rm
deleted the cache, pm trust ran the blocked scripts and wrote
package.json and bun.lock, pm pkg set/delete/fix wrote package.json, and
pm migrate wrote bun.lock.

Each command now stops before its first write and prints what it would
have done.
@coderabbitai

coderabbitai Bot commented Sep 6, 2026 •

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

  • Run on-demand review

On-demand reviews are free for the next 13 days. After that, they cost $0.25 per reviewed file.

Or wait 57 minutes for your next included review.

Check out review usage here.

View limit details

Limit details: You’ve used all 10 included reviews currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Essentials

Run ID: f48907bf-db95-411f-abd7-9ce435a7003a

📥 Commits

Reviewing files that changed from the base of the PR and between 62838e1 and 25744a2.

📒 Files selected for processing (14)
  • docs/pm/cli/pm.mdx
  • src/install/lockfile.rs
  • src/runtime/cli/link_command.rs
  • src/runtime/cli/package_manager_command.rs
  • src/runtime/cli/pm_pkg_command.rs
  • src/runtime/cli/pm_trusted_command.rs
  • src/runtime/cli/pm_version_command.rs
  • src/runtime/cli/unlink_command.rs
  • test/cli/install/bun-install-lifecycle-scripts.test.ts
  • test/cli/install/bun-link.test.ts
  • test/cli/install/bun-pm-pkg.test.ts
  • test/cli/install/bun-pm-version.test.ts
  • test/cli/install/bun-pm.test.ts
  • test/cli/install/migration/migrate.test.ts

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added the claude label Sep 6, 2026
@robobun

robobun commented Sep 6, 2026 •

Copy link
Copy Markdown
Collaborator Author
Updated 6:07 PM PT - Sep 7th, 2026

❌ @Jarred-Sumner, your commit 25744a2 has 7 failures in Build #112216 (All Failures):


🧪   To try this PR locally:

bunx bun-pr 41690

That installs a local version of the PR into your bun-41690 executable, so you can run:

bun-41690 --bun

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I reviewed this PR and didn't find any bugs. Because it adds new user-facing output text across seven subcommands (which REVIEW.md treats as reviewed word-for-word) and the description flags a known test conflict with #38804, a human look at the output wording and cross-PR coordination would still be worthwhile.

What was reviewed:

  • Each subcommand's dry-run guard is placed after validation and before the first write; error paths and exit codes are preserved.
  • pm cache rm counter still increments in dry-run so the "Would clear N" total is correct; had_err stays false so exit is 0.
  • unlink reuses link_path after lstat (borrow, not move) and still runs the existence check so dry-run reports the same "not globally linked" message the real run would.
  • Tests assert the negative contract (package.json/bun.lock/symlink unchanged) and are added to existing files per test/CLAUDE.md.
Extended reasoning...

Overview

This PR wires the already-parsed --dry-run flag through seven package-manager subcommands that previously ignored it: bun link, bun unlink, bun pm cache rm, bun pm migrate, bun pm pkg set|delete|fix, bun pm version, and bun pm trust. Each command now checks options.dry_run immediately before its first filesystem/git mutation, prints a dry run: would … line describing the action, and exits (or returns) without side effects. Read-only validation (lockfile load, git dirty check, lstat of the existing link) still runs so a dry run surfaces the same errors the real run would. Docs (docs/pm/cli/pm.mdx) and the pm version help text are updated, and tests are added to six existing test files asserting both the dry-run output and that no files are written.

Security risks

None. The change is purely additive gating that short-circuits write paths earlier; no new input parsing, no new filesystem reads of untrusted data, no network, no auth/crypto. The one new unsafe block in pm_trusted_command.rs reads (*pm_raw).options.dry_run through the same singleton raw pointer already dereferenced on the surrounding lines for options.log_level.show_progress(), with a matching SAFETY comment.

Level of scrutiny

Moderate. The mechanics are straightforward and the bug hunter ran to dry_streak with no findings, but this PR introduces roughly ten new user-facing output strings, and REVIEW.md explicitly calls out that "error messages are reviewed word-for-word as code" — a maintainer may have preferences on the dry run: prefix convention, whether pm pkg --dry-run should print the full resulting JSON to stdout, or whether link --dry-run should still create the global link parent directory (as noted in the PR description). These are design/wording judgments rather than correctness issues.

Other factors

The PR description explicitly notes a conflict with #38804, which pins bun pm migrate --dry-run as writing bun.lock — "whichever lands second needs a one-line test update." That coordination is a human decision. Test coverage is good: each subcommand's dry-run path has a test asserting output before exit code and verifying the negative contract (files unchanged, scripts not run, git untouched), placed in the existing test files per repo convention. Given the breadth (seven subcommands), the new output surface, and the known cross-PR interaction, deferring for a quick human sign-off on wording and landing order is the right call over auto-approving.

…ng the scripts

`bun pm trust <names> --ignore-scripts` adds the names to
trustedDependencies in package.json and skips the lifecycle scripts. The
lockfile is left alone, so the next `bun install` sees a package that
package.json trusts and the lockfile does not, runs its scripts, and
saves the lockfile.

Only the flag skips the scripts. `ignoreScripts` in bunfig.toml or
.npmrc does not, because `bun pm trust <names>` is the explicit request
to run those scripts.

pm migrate --dry-run now names the lockfile it would write from
LoadResult::save_format, so it prints bun.lockb when saveTextLockfile is
false. LockfileFormat::filename and LoadResult::save_format become pub
for that.

pm pkg --dry-run ends its output with a newline when the package.json
has no trailing newline.

Folds the part of #41686 that #41690 did not cover.
Comment thread src/runtime/cli/pm_trusted_command.rs Outdated
Comment thread src/runtime/cli/pm_trusted_command.rs Outdated
@robobun robobun changed the title pm: honour --dry-run in link, unlink, pm version, pm cache rm, pm trust, pm pkg, and pm migrate pm: honour --dry-run in link, unlink, pm version, pm cache rm, pm trust, pm pkg and pm migrate, and add --ignore-scripts to pm trust Sep 6, 2026

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nothing blocking. The comments below are optional suggestions. There is no need to push a fix for them before merging.

Comment thread test/cli/install/bun-pm.test.ts Outdated
Comment thread test/cli/install/bun-pm-pkg.test.ts
Comment thread src/runtime/cli/pm_trusted_command.rs Outdated

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code review found no issues

No high-confidence issues detected in this change.

@robobun

robobun commented Sep 7, 2026 •

Copy link
Copy Markdown
Collaborator Author

Status: ready for review.

Reproduced on 1.4.2, 1.4.3-canary (d316760) and 1.3.14 in a temp dir with a private BUN_INSTALL and no network: bun link --dry-run created the global symlink and bun unlink --dry-run removed it, bun pm version minor --dry-run --no-git-tag-version wrote package.json and ran preversion/postversion, bun pm pkg set foo=bar --dry-run wrote package.json, bun pm cache rm --dry-run deleted the cache, bun pm trust <dep> --dry-run ran the blocked script and wrote package.json and bun.lock, and bun pm migrate --dry-run wrote bun.lock. The new tests fail on the release binary and pass on this branch.

Scope is --dry-run only. #41686 overlapped on pm cache rm, migrate, pkg and trust; the --dry-run work is consolidated here. Its bun pm trust --ignore-scripts piece was folded in and backed out again (see the Notes in the PR body), so it is not part of this change, and #41686 is reopened to carry only that piece.

CI on the current head 05a3a29 (build 112076): the lanes that run the touched install tests are green. The one red job is debian 13 x64-asan test-bun, on three files this PR does not touch: test/js/node/vm/sourcetextmodule-leak.test.ts and test/cli/run/require-cache.test.ts (leak tests timing out) and vendor/elysia/test/response/stream.test.ts. The previous head was green on that lane apart from test-crypto-dh-leak.js, which fails on main.

The record-only --ignore-scripts mode relied on the next `bun install`
running the scripts of a package that package.json newly trusts. That
holds under the hoisted linker (PackageInstaller.rs checks
summary.added_trusted_dependencies for already-installed packages), but
not under the isolated linker: an entry that is already in
node_modules/.bun takes the relink path, and Installer::next_step goes
from SymlinkDependencyBinaries straight to Done when relinking, so
RunPreinstall never runs. The install then saves the trust to bun.lock
and the scripts never run until a forced or clean install. The same
happens when trustedDependencies is edited by hand, so it is a separate
isolated-linker bug, and --ignore-scripts on pm trust stays with #41686
until that is sorted out.

Kept from the fold: pm migrate --dry-run names the lockfile from
LoadResult::save_format, pm pkg --dry-run ends with a newline, the
--dry-run line under trust in bun pm --help, and the pm pkg fix
--dry-run test.
@robobun robobun changed the title pm: honour --dry-run in link, unlink, pm version, pm cache rm, pm trust, pm pkg and pm migrate, and add --ignore-scripts to pm trust pm: honour --dry-run in link, unlink, pm version, pm cache rm, pm trust, pm pkg, and pm migrate Sep 7, 2026

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code review found no issues

No high-confidence issues detected in this change.

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code review found no issues

No high-confidence issues detected in this change.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants