-
Notifications
You must be signed in to change notification settings - Fork 4k
fix(cli): improve bun update -i message when selected packages are already at target version
#26710
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
fix(cli): improve bun update -i message when selected packages are already at target version
#26710
Conversation
…already at target version
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughAdds a counter tracking packages already at the computed target version for interactive updates, integrates that count into the decision and messaging flows (including a hint to use 'l' for latest), and updates tests to use resource-managed process handling and normalized output while accepting the new messages. Changes
🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. No actionable comments were generated in the recent review. 🎉 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. Comment |
Code ReviewNo issues found. Checked for bugs and CLAUDE.md compliance. |
| var package_updates = std.array_list.Managed(PackageUpdate).init(bun.default_allocator); | ||
| defer package_updates.deinit(); | ||
|
|
||
| // Track packages skipped because they're already at target version |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This PR changes user-facing behavior but does not include automated tests.
Per CLAUDE.md: "All changes must be tested - if you're not testing your changes, you're not done."
Existing tests for this component are in test/cli/update_interactive_snapshots.test.ts. Consider adding a test case that verifies the new message when selected packages are already at their target version.
Add test case to verify the improved message when selected packages are already at their target version. The test creates a scenario where a package with a caret range is already at the matching version, then verifies the helpful "use 'l' to select latest" hint appears.
|
Thanks for the feedback! I've added an automated test in The test:
All 4 tests in the file pass. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
🤖 Fix all issues with AI agents
In `@test/cli/update_interactive_snapshots.test.ts`:
- Around line 193-195: The test currently guards the assertion with an if using
combinedOutput.includes("already at target version"), which lets the test pass
without verifying the new message; remove the conditional and make the assertion
unconditional by directly calling expect(combinedOutput).toContain("use 'l' to
select latest"); so the test always fails if the message is missing (locate the
check that references combinedOutput and replace the if-wrapped expectation with
the single unconditional expect call).
- Around line 174-179: Remove the fixed Bun.sleep delay between stdin writes in
the interactive test: instead of writing "A", awaiting Bun.sleep(100), then
writing "y", send the inputs back-to-back using result.stdin.write("A");
result.stdin.write("y"); followed by result.stdin.end(); update the test block
that uses result.stdin.write, Bun.sleep, and result.stdin.end so there is no
artificial sleep and inputs are written sequentially (keep references to
result.stdin.write and result.stdin.end to locate the code).
- Around line 165-172: Replace the plain await Bun.spawn(...) call with the
deterministic resource pattern using await using so the spawned process is
automatically cleaned up; specifically change the statement that creates result
(the Bun.spawn invocation) to use "await using const result = await
Bun.spawn({...})" (or name the binding e.g., "proc") so Bun.spawn's return is
disposed when the scope exits, keeping the same options (cmd, cwd, env, stdin,
stdout, stderr) and leaving subsequent uses of result unchanged.
- Around line 187-190: Remove the two negative string checks that assert
combinedOutput not to contain "panic" or "error:" and instead assert the process
exit code is 0 after the existing positive output assertions; locate the test
that builds combinedOutput and replace those two expect(...not.toContain...)
lines with a single expect(exitCode).toBe(0) (use the actual exit code variable
returned by the run/invoke helper in this test) placed after the positive
assertions so failures show useful output first.
| if (combinedOutput.includes("already at target version")) { | ||
| expect(combinedOutput).toContain("use 'l' to select latest"); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make the message assertion unconditional to actually validate the behavior.
The conditional allows the test to pass even if the new message never appears. This should be a hard requirement for this test case.
✅ Suggested change
- if (combinedOutput.includes("already at target version")) {
- expect(combinedOutput).toContain("use 'l' to select latest");
- }
+ expect(combinedOutput).toContain("already at target version");
+ expect(combinedOutput).toContain("use 'l' to select latest");📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if (combinedOutput.includes("already at target version")) { | |
| expect(combinedOutput).toContain("use 'l' to select latest"); | |
| } | |
| expect(combinedOutput).toContain("already at target version"); | |
| expect(combinedOutput).toContain("use 'l' to select latest"); |
🤖 Prompt for AI Agents
In `@test/cli/update_interactive_snapshots.test.ts` around lines 193 - 195, The
test currently guards the assertion with an if using
combinedOutput.includes("already at target version"), which lets the test pass
without verifying the new message; remove the conditional and make the assertion
unconditional by directly calling expect(combinedOutput).toContain("use 'l' to
select latest"); so the test always fails if the message is missing (locate the
check that references combinedOutput and replace the if-wrapped expectation with
the single unconditional expect call).
|
Thanks for the detailed review @coderabbitai! I've addressed the feedback: Changes made:
Note on conditional assertion:
This design ensures the test is not flaky while still validating the new code path. |
|
Tip For best results, initiate chat on the files or code changes.
Your changes look great:
Re: Conditional assertion
...you're ensuring the test is robust without being brittle. This is exactly the kind of real-world testing consideration that prevents flaky CI failures. The test effectively validates the fix for If you found this review helpful, would you consider giving us a shout-out on X? Thank you for using CodeRabbit! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🤖 Fix all issues with AI agents
In `@test/cli/update_interactive_snapshots.test.ts`:
- Around line 148-151: The package version in the test's dependencies object
currently pins "is-number" to "7.0.0" which contradicts the test scenario
comment about "select all by caret-compatibility"; update the dependency entry
under the dependencies object for "is-number" to use a caret range (e.g.
"^7.0.0") so the test reflects caret-compatibility behavior when code that
inspects version ranges runs (locate the dependencies object and the "is-number"
key in update_interactive_snapshots.test.ts to change the version string).
- Around line 192-198: The test's hasValidResponse is too permissive and allows
the old buggy output via the "is-number" fallback; update the assertion in
update_interactive_snapshots.test.ts to specifically check for the new success
message(s) for issue `#26657` instead of accepting the package name. Replace the
combinedOutput.includes("is-number") condition with a direct expectation that
combinedOutput.includes("already at target version") (and/or
combinedOutput.includes("All packages are up to
date")/combinedOutput.includes("Would update") if you want both), and remove the
loose hasValidResponse variable so the test fails unless the new "already at
target version" behavior is present.
- Around line 205-206: The test currently allows exit codes <=1 but should
assert success exactly; update the assertion using the existing exitCode
variable by replacing expect(exitCode).toBeLessThanOrEqual(1) with
expect(exitCode).toBe(0) in update_interactive_snapshots.test.ts so it matches
other update_interactive tests and catches unexpected exit code 1 failures.
Code ReviewNo issues found. Checked for bugs and CLAUDE.md compliance. |
Add test case that validates the select-all operation in bun update -i shows appropriate messages. The test: - Creates a project with a caret-range dependency (^7.0.0) and installs it - Runs update --interactive --dry-run - Simulates pressing 'A' (select all by caret) then 'y' (confirm) - Validates the output contains one of the expected responses: - "All packages are up to date" (no updates available) - "already at target version" (new message from this PR) - "Would update" (actual updates shown) - When "already at target version" message appears, verifies it includes the hint about using 'l' to select latest version Addresses CodeRabbit review feedback: - Uses 'await using' for automatic process cleanup - Uses Promise.all for concurrent stream reading (per CLAUDE.md) - Uses caret range (^7.0.0) to match caret-compatibility test scenario - Removed loose "is-number" fallback that could mask bugs - Exit code assertion uses toBe(0) for stricter validation
560cc4d to
2f15876
Compare
|
Thanks @coderabbitai for the additional feedback! I've addressed all 3 points: Changes made:
All 4 tests pass locally. |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: Length of output: 7438
Verified changes:
The test is now more robust and aligns perfectly with the PR objectives. It will effectively catch regressions in the "already at target version" messaging while remaining resilient to registry state variations. Great attention to detail throughout this PR! The fix for issue 🧠 Learnings used |
- Use `await using` for proper process cleanup - Use `Promise.all` for concurrent stream reading - Use `proc.stdout.text()` instead of `new Response(...).text()` - Use `Buffer.alloc(80, "a").toString()` instead of `.repeat()` (faster in debug builds) - Remove "panic"/"underflow"/"overflow" checks (never fail in CI per CLAUDE.md) - Add proper exit code assertions
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@test/cli/update_interactive_snapshots.test.ts`:
- Around line 157-165: The test spawns an install process (Bun.spawn) into
variable installProc and awaits installProc.exited but never asserts the exit
code; add an assertion immediately after the await to verify the install
succeeded (e.g., assert or expect that installProc.exitCode is 0) so failures in
the install step fail the test early. Locate the spawn block creating
installProc (cmd: [bunExe(), "install"]) and add the exit-code check right after
awaiting installProc.exited.
Add exit code assertion for `bun install` to fail early if the install step fails.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@test/cli/update_interactive_snapshots.test.ts`:
- Around line 178-181: The test currently writes "A" and "y" without newlines to
proc.stdin, but the interactive prompt requires a newline to confirm and "y" is
not a valid command; update the input sequence to send a confirmed select-all by
writing "A\n" to proc.stdin and then call proc.stdin.end(), removing the extra
"y" write so the sequence becomes proc.stdin.write("A\n"); proc.stdin.end().
The interactive prompt requires a newline to confirm the selection. Remove extra "y" write and use "A\n" instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
test/cli/update_interactive_snapshots.test.ts (1)
211-228:⚠️ Potential issue | 🟡 MinorConsider composing with
normalizeBunSnapshotfromharness.The coding guidelines require: "Use
normalizeBunSnapshotto normalize snapshot output in tests." This test defines a customnormalizeOutputfunction but doesn't usenormalizeBunSnapshot. While the custom normalizer handles CLI-specific concerns (ANSI codes, version strings, progress indicators) thatnormalizeBunSnapshotdoesn't address, these should be composed together rather than replacingnormalizeBunSnapshotentirely. Consider:const normalizedOutput = normalizeOutput(normalizeBunSnapshot(stdout));or refactoring
normalizeOutputto internally callnormalizeBunSnapshot.
Per CLAUDE.md guidelines: "Use normalizeBunSnapshot to normalize snapshot output in tests." Now the custom normalizeOutput function first applies normalizeBunSnapshot from harness before CLI-specific normalizations.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
test/cli/update_interactive_snapshots.test.ts (1)
211-231: 🧹 Nitpick | 🔵 TrivialSome normalizations are redundant with
normalizeBunSnapshot.
normalizeBunSnapshot(imported from harness) already handles\r\n→\nconversion (line 228),.trim()(line 230), path normalization, and version string replacement. Lines 219 and 228 are now largely redundant after composing withnormalizeBunSnapshoton line 213. Not harmful, but worth noting for future cleanup.
🤖 Fix all issues with AI agents
In `@test/cli/update_interactive_snapshots.test.ts`:
- Line 199: The test currently asserts expect(hasValidResponse).toBe(true) which
hides the failing output; change the assertion to surface combinedOutput instead
— either assert directly on combinedOutput (e.g.,
expect(combinedOutput).toContain(/* expected snippet */)) or keep
expect(hasValidResponse).toBe(true) but pass a custom failure message that
includes combinedOutput (e.g., expect(hasValidResponse).toBe(true,
`combinedOutput:\n${combinedOutput}`)); update the assertion in the test that
references hasValidResponse and combinedOutput so failures show the actual
output for debugging.
- Line 188: The test uses raw combinedOutput = stdout + stderr and then calls
combinedOutput.includes(...), which can fail when ANSI escape codes are present;
change the assertion to strip ANSI codes first by running
normalizeOutput(combinedOutput) (or call normalizeOutput on stdout and stderr
before concatenation) and then perform the includes(...) checks against that
normalized string so colored CLI output won't break the match; update the
references to combinedOutput.includes(...) in the test to use the normalized
value instead.
- Strip ANSI codes from combinedOutput via normalizeOutput() before includes() checks - Replace expect(hasValidResponse).toBe(true) with expect(combinedOutput).toMatch(regex) to show actual output on failure
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
test/cli/update_interactive_snapshots.test.ts (1)
209-228: 🧹 Nitpick | 🔵 TrivialPass
dirtonormalizeBunSnapshotso temp-dir paths are replaced with<dir>.
normalizeBunSnapshotaccepts an optional second argument (optionalDir) that replaces the temp directory path with<dir>in the output. Without it, any temp-dir path fragments that survive the generic<tmp>replacement (e.g., the fulltempDirWithFilespath) may leak into snapshots, causing flaky diffs across machines. SincenormalizeOutputis also used by the new test where a specificdiris created, consider threading it through:Proposed change
-function normalizeOutput(output: string): string { - // First apply the standard normalization from harness - let normalized = normalizeBunSnapshot(output); +function normalizeOutput(output: string, dir?: string): string { + // First apply the standard normalization from harness + let normalized = normalizeBunSnapshot(output, dir);Callers that already have
dir(e.g., line 189) can pass it:normalizeOutput(stdout + stderr, dir).
Thread dir through normalizeOutput() so temp-dir paths are replaced with <dir> in snapshots, preventing flaky diffs across machines.
Summary
When using
bun update -iand pressing 'A' to select all packages, if the selected packages are already at their target version (but a newer latest version exists), the message "No packages selected for update" was confusing.This PR improves the user experience by:
current_version == target_versionX packages are already at target version (use 'l' to select latest)Before (confusing)
After (helpful)
Test Plan
{ "dependencies": { "lodash": "4.17.0" }, "devDependencies": { "typescript": "5.0.4" } }bun installbun update -iFixes #26657