Skip to content

v6.0.11: Fix Bun global install deduplication#1

Merged
tyl3r-ch merged 2 commits intomainfrom
feature-2026-04-10
Apr 9, 2026
Merged

v6.0.11: Fix Bun global install deduplication#1
tyl3r-ch merged 2 commits intomainfrom
feature-2026-04-10

Conversation

@tyl3r-ch
Copy link
Copy Markdown
Contributor

@tyl3r-ch tyl3r-ch commented Apr 9, 2026

Summary by CodeRabbit

  • Bug Fixes

    • Installer now cleans stale global entries and removes problematic lockfiles to prevent duplicate manifest keys during repeated upgrades.
  • Chores

    • Release version bumped to 6.0.11.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 9, 2026

📝 Walkthrough

Walkthrough

Release 6.0.11: bump version and changelog; installer scripts now normalize Bun’s global manifest by removing stale app entries and optionally deleting a problematic bun.lock before performing a global install to avoid duplicate package.json keys.

Changes

Cohort / File(s) Summary
Release metadata
CHANGELOG.md, package.json, src/lib/constants.ts
Version bumped to 6.0.11 and changelog entry added documenting the Bun installer idempotency fix.
Unix Bun installer cleanup
install.sh
Read package name/version from script-relative package.json; added prepare_bun_global_install() to locate Bun global path, remove the app entry from install/global/package.json, normalize JSON, and delete bun.lock when necessary before bun add -g file:....
Windows Bun installer cleanup & script init
install.bat
Set script directory and cd there, initialize APP_NAME from package.json, detect Bun global bin, inline bun --eval to remove/normalize the global manifest, delete bun.lock if needed, then proceed with bun add -g (npm fallback remains).

Sequence Diagram(s)

sequenceDiagram
    participant Installer as Installer Script
    participant BunCLI as Bun CLI
    participant Manifest as Bun Global Manifest
    participant Lock as bun.lock File
    Installer->>BunCLI: bun pm bin -g (get global path)
    BunCLI-->>Installer: Bun root path
    Installer->>Manifest: Read install/global/package.json
    Manifest-->>Installer: manifest contents
    Installer->>BunCLI: bun --eval (remove app dep / normalize JSON)
    BunCLI->>Manifest: modify & rewrite package.json
    BunCLI-->>Installer: status (clean/removed/normalized)
    alt Manifest was changed / stale entry removed
        Installer->>Lock: delete bun.lock
        Lock-->>Installer: deletion confirmed
    end
    Installer->>BunCLI: bun add -g file:$(pwd)
    BunCLI-->>Installer: install result
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐇 I hopped to the manifest, tidy and spry,
I nudged out the old key with a twinkle in my eye.
Cleaned the lock, then installed with care,
No duplicates now — tidy as a hare! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically summarizes the main change: fixing Bun global install deduplication issues through cleanup logic added to both install scripts.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature-2026-04-10

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

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a 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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@CHANGELOG.md`:
- Around line 3-6: The release date for the CHANGELOG entry "## [6.0.11] -
2026-04-10" is future-dated; update the header in CHANGELOG.md for the "6.0.11"
entry to either the actual release date (e.g., 2026-04-09 if releasing today) or
mark it as unreleased (e.g., "## [6.0.11] - Unreleased") so the changelog
accurately reflects the release timing.

In `@install.bat`:
- Around line 80-85: The script can proceed with cleanup even when the inline
bun command failed (stderr was suppressed) because BUN_CLEANUP_STATUS can be
empty; change the logic so you only delete BUN_GLOBAL_LOCKFILE and echo the
cleanup message when BUN_CLEANUP_STATUS explicitly equals expected success
values (e.g., "removed" or "normalized") and not when it's empty or when bun
failed; implement this by (a) removing or not suppressing bun stderr so failures
are visible or by capturing bun's exit status, and (b) replacing the
unconditional if /i not "!BUN_CLEANUP_STATUS!"=="clean" check with an explicit
check like if /i "!BUN_CLEANUP_STATUS!"=="removed" ( ... ) else if /i
"!BUN_CLEANUP_STATUS!"=="normalized" ( ... ) to only run the deletion of
%BUN_GLOBAL_LOCKFILE% and the echo for %APP_NAME% when the bun command actually
reported work done.
- Around line 7-10: The script reads package.json from the current working
directory instead of the batch file directory, so change both PowerShell calls
that set APP_VERSION and APP_NAME to read package.json via the install.bat
location (use %~dp0). Update the two for /f lines that call PowerShell (the ones
that set APP_VERSION and APP_NAME) to reference "%~dp0package.json" (ensuring
proper quoting) instead of 'package.json' so the metadata is always resolved
from the script's folder.

In `@install.sh`:
- Around line 17-25: The script currently reads package.json from the caller's
cwd causing package_name (and version) to be taken from the wrong project;
change the package.json read to reference the script's directory (use a
script_dir computed from "${BASH_SOURCE[0]}" or "$0") and run sed against
"$script_dir/package.json" when setting package_name and version so
prepare_bun_global_install() and other logic always use this script's
package.json; keep the same fallback defaults for package_name ("ttdash") and
version ("unbekannt").
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3684a35e-f5bc-4f7e-b84c-227351ad8a26

📥 Commits

Reviewing files that changed from the base of the PR and between 387e2df and ceeb4ca.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (5)
  • CHANGELOG.md
  • install.bat
  • install.sh
  • package.json
  • src/lib/constants.ts

Comment thread CHANGELOG.md
Comment thread install.bat
Comment thread install.bat
Comment thread install.sh Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

♻️ Duplicate comments (1)
install.bat (1)

83-87: ⚠️ Potential issue | 🟠 Major

Only treat explicit Bun cleanup outcomes as success.

Line 84 still treats an empty/failed BUN_CLEANUP_STATUS as non-clean, so the script can delete bun.lock and print a cleanup success message even when bun --eval failed silently.

Proposed fix
-        for /f "usebackq delims=" %%s in (`bun --eval "const fs = require('fs'); const file = process.env.BUN_GLOBAL_PACKAGE_JSON; const name = process.env.APP_NAME; if (!file || !fs.existsSync(file)) { console.log('clean'); process.exit(0); } const raw = fs.readFileSync(file, 'utf8'); const parsed = JSON.parse(raw); const deps = { ...(parsed.dependencies || {}) }; const hadEntry = Object.prototype.hasOwnProperty.call(deps, name); if (hadEntry) { delete deps[name]; } const next = { ...parsed }; if (Object.keys(deps).length > 0) { next.dependencies = deps; } else { delete next.dependencies; } const normalized = JSON.stringify(next, null, 2) + '\n'; const normalizedChanged = raw !== normalized; if (normalizedChanged || hadEntry) { fs.writeFileSync(file, normalized); } if (hadEntry) { console.log('removed'); } else if (normalizedChanged) { console.log('normalized'); } else { console.log('clean'); }" 2^>nul`) do set "BUN_CLEANUP_STATUS=%%s"
-        if /i not "!BUN_CLEANUP_STATUS!"=="clean" (
-            if exist "%BUN_GLOBAL_LOCKFILE%" del /f /q "%BUN_GLOBAL_LOCKFILE%" >nul 2>&1
-            echo    - Vorhandenen Bun-Globaleintrag fuer %APP_NAME% bereinigt
-        )
+        for /f "usebackq delims=" %%s in (`bun --eval "const fs = require('fs'); const file = process.env.BUN_GLOBAL_PACKAGE_JSON; const name = process.env.APP_NAME; if (!file || !fs.existsSync(file)) { console.log('clean'); process.exit(0); } const raw = fs.readFileSync(file, 'utf8'); const parsed = JSON.parse(raw); const deps = { ...(parsed.dependencies || {}) }; const hadEntry = Object.prototype.hasOwnProperty.call(deps, name); if (hadEntry) { delete deps[name]; } const next = { ...parsed }; if (Object.keys(deps).length > 0) { next.dependencies = deps; } else { delete next.dependencies; } const normalized = JSON.stringify(next, null, 2) + '\n'; const normalizedChanged = raw !== normalized; if (normalizedChanged || hadEntry) { fs.writeFileSync(file, normalized); } if (hadEntry) { console.log('removed'); } else if (normalizedChanged) { console.log('normalized'); } else { console.log('clean'); }"`) do set "BUN_CLEANUP_STATUS=%%s"
+        if /i "!BUN_CLEANUP_STATUS!"=="removed" (
+            if exist "%BUN_GLOBAL_LOCKFILE%" del /f /q "%BUN_GLOBAL_LOCKFILE%" >nul 2>&1
+            echo    - Vorhandenen Bun-Globaleintrag fuer %APP_NAME% bereinigt
+        ) else (
+            if /i "!BUN_CLEANUP_STATUS!"=="normalized" (
+                if exist "%BUN_GLOBAL_LOCKFILE%" del /f /q "%BUN_GLOBAL_LOCKFILE%" >nul 2>&1
+                echo    - Bun-Globalmanifest normalisiert
+            ) else (
+                if /i not "!BUN_CLEANUP_STATUS!"=="clean" (
+                    echo    ! Bun-Cleanup fehlgeschlagen oder ungueltiger Status: !BUN_CLEANUP_STATUS!
+                )
+            )
+        )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@install.bat` around lines 83 - 87, The current check treats an empty or
failed BUN_CLEANUP_STATUS as non-"clean" and may perform cleanup incorrectly;
update the condition that gates deletion/echo to ensure BUN_CLEANUP_STATUS is
defined and explicitly one of the expected success outcomes before proceeding.
Concretely, change the if that uses BUN_CLEANUP_STATUS (the block handling
deletion of "%BUN_GLOBAL_LOCKFILE%" and echo about Bun global cleanup) to first
test defined BUN_CLEANUP_STATUS (using if defined BUN_CLEANUP_STATUS) and then
check that its value is not "clean" (case-insensitive) — or alternately only
proceed when BUN_CLEANUP_STATUS equals "removed" or "normalized" — so a
missing/empty value from the bun --eval invocation will not trigger the cleanup
actions.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@install.bat`:
- Around line 83-87: The current check treats an empty or failed
BUN_CLEANUP_STATUS as non-"clean" and may perform cleanup incorrectly; update
the condition that gates deletion/echo to ensure BUN_CLEANUP_STATUS is defined
and explicitly one of the expected success outcomes before proceeding.
Concretely, change the if that uses BUN_CLEANUP_STATUS (the block handling
deletion of "%BUN_GLOBAL_LOCKFILE%" and echo about Bun global cleanup) to first
test defined BUN_CLEANUP_STATUS (using if defined BUN_CLEANUP_STATUS) and then
check that its value is not "clean" (case-insensitive) — or alternately only
proceed when BUN_CLEANUP_STATUS equals "removed" or "normalized" — so a
missing/empty value from the bun --eval invocation will not trigger the cleanup
actions.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 44ef071c-0ad7-4598-a77b-26e66ed7d65c

📥 Commits

Reviewing files that changed from the base of the PR and between ceeb4ca and 4598578.

📒 Files selected for processing (2)
  • install.bat
  • install.sh
🚧 Files skipped from review as they are similar to previous changes (1)
  • install.sh

@tyl3r-ch tyl3r-ch merged commit 32350e0 into main Apr 9, 2026
3 checks passed
@tyl3r-ch tyl3r-ch deleted the feature-2026-04-10 branch April 13, 2026 09:29
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