Skip to content

feat(install): add dry-run resolution preview - #927

Merged
jdx merged 6 commits into
mainfrom
codex/install-dry-run
Jun 23, 2026
Merged

jdx merged 6 commits into
mainfrom
codex/install-dry-run

Conversation

@jdx

@jdx jdx commented Jun 22, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

  • Add aube install --dry-run as a no-write resolution preview
  • Reuse the lockfile-only resolver path with lockfile writes disabled
  • Skip install fast-path mutation, force state reset, branch-lockfile merge, lifecycle hooks, fetch, link, and finalize work in dry-run mode

Validation

  • cargo build
  • cargo fmt --check
  • mise run test:bats test/install.bats

Note

Medium Risk
Changes the central install command path and frozen/CI interaction semantics, but dry-run is explicitly no-write and is covered by new integration tests.

Overview
Adds aube install --dry-run to resolve dependencies and print what would happen without writing the lockfile, linking node_modules, or running install side effects. The flag conflicts with --lockfile-only and is documented in CLI usage and install docs.

Dry-run threads through InstallOptions.dry_run and reuses the existing lockfile-only resolve path with write_lockfile: false. The main install flow skips force/state reset, the install fast path, Node runtime ensure, branch-lockfile merge, and root preinstall hooks when dry-run is set.

Behavior differs from --lockfile-only in a few ways: explicit --frozen-lockfile still fails when no lockfile exists (and validates drift before resolve), while CI-style dry-run can resolve without a lockfile or when the lockfile is drifted. When the lockfile is already fresh, output uses dry-run-specific messages instead of the lockfile-only “resolution step is skipped” line.

ci and deploy continue to pass dry_run: false. Bats coverage asserts no aube-lock.yaml / node_modules and checks frozen/CI/fresh-lockfile cases, including lockfile=false projects that can dry-run without the lockfile-only conflict.

Reviewed by Cursor Bugbot for commit 9427906. Bugbot is set up for automated code reviews on this repo. Configure here.

Summary by CodeRabbit

  • New Features
    • Added --dry-run to aube install to resolve and report planned changes without writing the lockfile, creating node_modules, or running lifecycle scripts.
  • Behavior Changes
    • --dry-run is incompatible with --lockfile-only.
    • In frozen scenarios, dry-run validates lockfile constraints and fails with clear errors when a lockfile is required but missing; otherwise it reports an “up to date” outcome without applying changes.
  • Documentation
    • Updated CLI help and install docs for --dry-run.
  • Tests
    • Added Bats coverage to confirm no aube-lock.yaml or node_modules are created.

@coderabbitai

coderabbitai Bot commented Jun 22, 2026 •

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds a --dry-run flag to aube install (conflicting with --lockfile-only). When set, dependency resolution runs but all side-effectful phases are skipped: fast-path install, runtime setup, branch lockfile merge, root preinstall hook, and lockfile/node_modules writes. CI and deploy callers explicitly set dry_run: false. Five Bats tests validate behavior across basic, frozen-lockfile, CI-mode, drifted-manifest, and config scenarios.

Changes

--dry-run install flag

Layer / File(s) Summary
InstallOptions.dry_run field and CLI arg
crates/aube/src/commands/install/args.rs
InstallArgs gains --dry-run (conflicts with --lockfile-only); InstallOptions gains a dry_run: bool field defaulting to false; into_options wires the parsed value through.
Install orchestration dry-run gating
crates/aube/src/commands/install/mod.rs
Fast-path reset/install, runtime setup, branch lockfile merge, and root preinstall hook are each guarded by !opts.dry_run. The lockfile-only short-circuit now runs on opts.dry_run with frozen-mode validation and passes write_lockfile: !opts.dry_run to run_lockfile_only.
Lockfile-only dry-run path
crates/aube/src/commands/install/resolve.rs
LockfileOnlyInput gains write_lockfile: bool; run_lockfile_only adds early-return branches that report completion, print resolved-package counts, and skip all disk output when write_lockfile is false.
CLI documentation and usage
aube.usage.kdl, docs/cli/commands.json, docs/cli/install.md
Adds --dry-run flag documentation to usage, command reference, and install guide, describing it resolves and reports without writing lockfiles or linking node_modules.
CI/deploy callers and integration tests
crates/aube/src/commands/ci.rs, crates/aube/src/commands/deploy/mod.rs, test/install.bats, test/lockfile_settings.bats
CI and deploy callers add dry_run: false to their InstallOptions structs. Five new Bats test cases assert aube install --dry-run succeeds with "Dry run: resolved" or "Dry run: lockfile is up to date" messages and no aube-lock.yaml or node_modules created, across basic, frozen-lockfile, CI-mode, drifted-manifest, and lockfile=false scenarios.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • jdx/aube#843: Both PRs modify LockfileOnlyInput and the early-exit branching in run_lockfile_only, extending the same struct and path that this PR reuses for dry-run control.
  • jdx/aube#882: Both PRs extend LockfileOnlyInput in install/resolve.rs to control lockfile-writing scope; this PR adds write_lockfile for dry-run gating, while the retrieved PR extends per-project lockfile writing.
  • jdx/aube#893: Both PRs modify the run_lockfile_only path in crates/aube/src/commands/install/resolve.rs; this PR adds a write_lockfile-driven dry-run early return, while the retrieved PR adds resolver passes immediately before writing.

Poem

🐰 Hop, hop, no files to drop!
--dry-run peeks without a stop,
Resolves the packages, counts them all,
No lockfile written, no modules to install.
The bunny checks, then springs away—
"All looks good! But not today." 🌿

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(install): add dry-run resolution preview' directly and clearly describes the main change: adding a dry-run flag to the install command for previewing resolution without side effects.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Comment thread crates/aube/src/commands/install/mod.rs Resolved
@greptile-apps

greptile-apps Bot commented Jun 22, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds --dry-run to aube install, letting users preview what resolution would produce without writing the lockfile, creating node_modules, or running lifecycle hooks. The flag is wired through InstallOptions, set to false in the ci and deploy callers, and conflicts with --lockfile-only.

  • Dry-run reuses the run_lockfile_only resolve path with a new write_lockfile: false switch, emitting a distinct "Dry run: resolved N package(s)" or "Dry run: lockfile is up to date; fetch/link steps were not run" message instead of writing files.
  • Mutating steps in the main install pipeline — force state reset, install fast-path, Node runtime ensure, branch-lockfile merge, root preinstall hooks — are all guarded by !opts.dry_run.
  • Six new bats tests cover the core scenarios: basic dry-run, --frozen-lockfile without a lockfile, CI auto-frozen with no lockfile, CI with a drifted lockfile, the fresh-lockfile message variant, and the lockfile=false interaction.

Confidence Score: 5/5

Safe to merge — dry-run exits before any disk write, so worst-case a user sees an unexpected message or count but nothing is mutated.

The orchestration changes are narrow and well-guarded: every mutating step in the main pipeline is individually gated on !opts.dry_run, the lockfile-only resolve path is cleanly reused with write_lockfile: false, and the frozen-lockfile validation logic correctly distinguishes explicit --frozen-lockfile from CI auto-frozen. The six new bats tests cover the key code paths including the CI-drifted-lockfile scenario and the lockfile=false interaction that surfaced in prior review threads. No untested paths that could produce incorrect behavior were found.

No files require special attention.

Important Files Changed

Filename Overview
crates/aube/src/commands/install/mod.rs Core orchestration: mutating steps correctly gated by !opts.dry_run; dry-run routes to run_lockfile_only with write_lockfile: false; explicit --frozen-lockfile drift validation preserved via opts.strict_no_lockfile guard; CI auto-frozen path correctly skips the strict guard and resolves freely.
crates/aube/src/commands/install/resolve.rs Adds write_lockfile field to LockfileOnlyInput; emits distinct dry-run messages for both the fresh-lockfile and post-resolution branches; no disk writes occur when write_lockfile=false.
crates/aube/src/commands/install/args.rs Adds dry_run: bool to InstallArgs with conflicts_with = "lockfile_only" and threads it through InstallOptions; callers (ci, deploy) correctly default to false.
test/install.bats Five well-targeted tests cover: basic dry-run resolution, --frozen-lockfile without lockfile, CI no-lockfile, CI drifted-lockfile, and fresh-lockfile message; all assert absence of aube-lock.yaml and node_modules where relevant.
test/lockfile_settings.bats Adds regression test for lockfile=false + --dry-run confirming no --lockfile-only conflict message and no lockfile/node_modules are created.

Reviews (6): Last reviewed commit: "fix(install): let CI dry-run resolve dri..." | Re-trigger Greptile

Comment thread crates/aube/src/commands/install/mod.rs Resolved

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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 `@crates/aube/src/commands/install/mod.rs`:
- Around line 168-173: The dry-run flag check happens too late in the execution
flow, allowing filesystem mutations through crate::runtime::ensure before the
dry-run no-write path is reached. Move the opts.dry_run check earlier in the
command execution flow, before calling crate::runtime::ensure and other
functions that can download and pin runtimes. This ensures that when dry-run is
enabled, all operations that would mutate filesystem state are skipped entirely,
with the lockfile-only flow at line 239 becoming the only path taken for dry-run
mode.
🪄 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: Central YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: 171646e9-e6d6-46a3-8ebf-248712533a2f

📥 Commits

Reviewing files that changed from the base of the PR and between 7f8c98f and 3b750ae.

📒 Files selected for processing (6)
  • crates/aube/src/commands/ci.rs
  • crates/aube/src/commands/deploy/mod.rs
  • crates/aube/src/commands/install/args.rs
  • crates/aube/src/commands/install/mod.rs
  • crates/aube/src/commands/install/resolve.rs
  • test/install.bats

Comment thread crates/aube/src/commands/install/mod.rs Resolved
Comment thread crates/aube/src/commands/install/mod.rs Resolved

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit c59ae55. Configure here.

Comment thread crates/aube/src/commands/install/mod.rs Resolved

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
test/install.bats (2)

947-960: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider verifying lockfile preservation in this drift scenario.

The test modifies package.json after _setup_basic_fixture creates a lockfile, then runs dry-run. Since dry-run explicitly disables lockfile writes (per write_lockfile: !opts.dry_run), consider adding an assertion to verify the existing lockfile wasn't modified.

For example, capture the lockfile timestamp or content hash before dry-run and verify it remains unchanged, or at minimum add:

assert [ -e aube-lock.yaml ]

to confirm the lockfile still exists and wasn't removed/recreated.

🤖 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 `@test/install.bats` around lines 947 - 960, The test "aube install --dry-run
in CI resolves drifted lockfile" does not verify that the existing lockfile is
preserved after running the dry-run command with a drifted package.json. Add an
assertion to confirm the lockfile (aube-lock.yaml) still exists and was not
modified by the dry-run operation. You can do this by adding an assert statement
checking that the lockfile file exists after the run command completes.
Optionally, capture the lockfile content or timestamp before running the dry-run
command and verify it matches afterwards to ensure the file was not rewritten.

962-971: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider adding lockfile preservation check for the fresh scenario.

This test verifies the "up-to-date lockfile" dry-run path correctly skips fetch/link and reports appropriately. Since _setup_basic_fixture creates a lockfile and this scenario explicitly tests that resolution is skipped when the lockfile is fresh, consider adding:

assert [ -e aube-lock.yaml ]

after line 970 to confirm the lockfile still exists and dry-run didn't remove or modify it.

🤖 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 `@test/install.bats` around lines 962 - 971, The test function "aube install
--dry-run with fresh lockfile still reports skipped fetch and link" does not
verify that the lockfile is preserved after the dry-run operation. Add an
assertion after the assert_output checks to confirm the aube-lock.yaml file
still exists following the dry-run, ensuring the lockfile was neither removed
nor modified during the operation.
🤖 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.

Nitpick comments:
In `@test/install.bats`:
- Around line 947-960: The test "aube install --dry-run in CI resolves drifted
lockfile" does not verify that the existing lockfile is preserved after running
the dry-run command with a drifted package.json. Add an assertion to confirm the
lockfile (aube-lock.yaml) still exists and was not modified by the dry-run
operation. You can do this by adding an assert statement checking that the
lockfile file exists after the run command completes. Optionally, capture the
lockfile content or timestamp before running the dry-run command and verify it
matches afterwards to ensure the file was not rewritten.
- Around line 962-971: The test function "aube install --dry-run with fresh
lockfile still reports skipped fetch and link" does not verify that the lockfile
is preserved after the dry-run operation. Add an assertion after the
assert_output checks to confirm the aube-lock.yaml file still exists following
the dry-run, ensuring the lockfile was neither removed nor modified during the
operation.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Central YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: 5e58612b-bfce-48de-b7d7-74cf715f1c1f

📥 Commits

Reviewing files that changed from the base of the PR and between 3391af8 and 9427906.

📒 Files selected for processing (6)
  • aube.usage.kdl
  • crates/aube/src/commands/install/mod.rs
  • crates/aube/src/commands/install/resolve.rs
  • docs/cli/commands.json
  • docs/cli/install.md
  • test/install.bats
✅ Files skipped from review due to trivial changes (1)
  • docs/cli/install.md
🚧 Files skipped from review as they are similar to previous changes (2)
  • crates/aube/src/commands/install/mod.rs
  • crates/aube/src/commands/install/resolve.rs

@jdx
jdx merged commit fb07186 into main Jun 23, 2026
18 checks passed
@jdx
jdx deleted the codex/install-dry-run branch June 23, 2026 17:46
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