Skip to content

feat: migrate to bun#740

Merged
magne4000 merged 16 commits into
mainfrom
magne4000/dev
May 29, 2026
Merged

feat: migrate to bun#740
magne4000 merged 16 commits into
mainfrom
magne4000/dev

Conversation

@magne4000

@magne4000 magne4000 commented May 28, 2026

Copy link
Copy Markdown
Member

Summary by CodeRabbit

  • Chores

    • Switched repo tooling from pnpm to Bun (pinned), updated scripts, CI workflows, and release/publish flows.
    • Converted workspace dependency specifiers to workspace:* and removed legacy workspace config.
    • Added Bun-based deploy/publish helpers and made CLI entrypoints executable.
    • Renovate ignore list now treats Bun as manually managed.
  • Documentation

    • Updated developer guides and onboarding to reflect Bun/Nx commands, prerequisites, and local-replication notes.

Review Change Stack

@coderabbitai

coderabbitai Bot commented May 28, 2026

Copy link
Copy Markdown

Note

Reviews paused

It 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 reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR migrates the repo from pnpm/Turborepo to Bun/Nx: CI workflows and scripts now use Bun, root manifests declare Bun and workspaces, boilerplates normalize workspace specifiers, Bun deploy/publish scripts and workspace utilities are added, CLI entrypoints updated, tests/types adjusted, and docs updated.

Changes

Build System Overhaul

Layer / File(s) Summary
CI workflows and Renovate
.github/workflows/*, .github/renovate.json5
CI workflows replace pnpm steps with Bun setup (oven-sh/setup-bun), use bun install and bun run ...; BUN_VERSION added to workflows and Renovate ignore list updated to include bun.
Root package.json, bump, and lockfile handling
package.json, bump.config.ts, biome.json
Root package.json adds workspaces and trustedDependencies, updates scripts to use Bun, adds engines.bun and packageManager: bun@1.3.11; bump flow runs bun install to refresh bun.lock; biome.json references bun.lock.
Workspace config removal
pnpm-workspace.yaml
pnpm-workspace.yaml removed (pnpm-specific workspace config deleted).
Boilerplate dependency workspace specifiers
boilerplates/*/package.json
Many boilerplate manifests change @batijs/* entries from workspace: to workspace:* and expand workspace devDependencies where applicable.
Package scripts and tooling
packages/*/package.json, website/package.json
Package-level prepublishOnly and other scripts switched from pnpm to bun; some packages add tooling deps (e.g., rolldown); packages/tests-utils adds files packaging config.
Bun-based deploy/publish and workspace utilities
scripts/deploy.ts, scripts/publish.ts, scripts/lib/workspaces.ts, scripts/lib/publish.ts, scripts/publish-widget.ts
New scripts implement pack-and-stage via bun pm pack, per-package publish via bunx npm publish, and a filesystem-based workspace loader loadWorkspaces().
CLI discovery and entrypoints
packages/cli/rolldown-bundle-all.ts, packages/cli/cli.js, packages/compile/cli.js
Boilerplate discovery moved to filesystem scan of boilerplates/; CLI JS entrypoints now include Node shebangs for direct execution.
Tests, types, and tsconfig
packages/tests/*, packages/tsconfig.base.json
Removed Verdaccio registry checks; tests always execute CLI via Bun/node; GlobalContext simplified to include tmpdir; preserveSymlinks removed from tsconfig; Nx env invocation adjusted.

Developer Documentation Updates

Layer / File(s) Summary
AGENTS.md
AGENTS.md
Developer and CI command examples updated from pnpm/Turborepo to bun/Nx; project layout and caching notes reflect Nx.
CONTRIBUTING.md
CONTRIBUTING.md
Install/build/test/boilerplate creation commands updated to Bun; system requirements include Node >=22 and Bun >=1.3.11.
Boilerplate README and examples
BOILERPLATES.md, packages/tests/README.md
Boilerplate creation and test execution docs updated to use bun and Nx (nx run-many), and other examples switched to bun run ....

Possibly related PRs

  • vikejs/bati#738: Related environment/registry changes touching package scripts and test runtime logic.
  • vikejs/bati#734: Touches transform behavior referenced by build tooling also modified in this migration.
  • vikejs/bati#719: Earlier PR that introduced publish-widget.yml using pnpm; this PR updates that workflow to Bun.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 11.11% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: migrate to bun' accurately captures the main objective of this pull request - a comprehensive migration from pnpm to bun across workflows, dependencies, and configuration.
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 and usage tips.

@magne4000 magne4000 marked this pull request as ready for review May 28, 2026 13:32

@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: 8

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
.github/workflows/reusable.run-tests.yml (1)

47-50: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Pin Bun setup action to commit hash for supply-chain security.

The oven-sh/setup-bun@v2 action uses a mutable tag reference instead of an immutable commit SHA.

🔒 Suggested fix
       - uses: oven-sh/setup-bun@v2
+      - uses: oven-sh/setup-bun@<commit-sha>  # v2
         name: Install bun
         with:
           bun-version: ${{ env.BUN_VERSION }}
🤖 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 @.github/workflows/reusable.run-tests.yml around lines 47 - 50, Replace the
mutable tag usage of the GitHub Action by pinning oven-sh/setup-bun to an
immutable commit SHA: locate the line that reads "uses: oven-sh/setup-bun@v2" in
the workflow and change it to use the specific commit SHA for the
oven-sh/setup-bun repository while preserving the existing inputs (e.g.,
bun-version: ${{ env.BUN_VERSION }}); update the commit SHA to the latest
verified release commit and commit that change so the action runs from an
immutable reference.
🧹 Nitpick comments (2)
scripts/publish.ts (1)

53-56: ⚡ Quick win

Consider adding error handling to publish all eligible packages.

The current implementation uses fail-fast behavior: if bun publish fails for any package, the script exits immediately without attempting to publish remaining packages. Depending on your release workflow, you might want to publish as many packages as possible and report failures at the end.

♻️ Optional resilient publish approach
+const failures: { name: string; error: unknown }[] = [];
+
 for (const { name, dir } of targets) {
   console.log(`\n=== ${name} ===`);
-  await $`bun publish ${forwardedArgs}`.cwd(dir);
+  try {
+    await $`bun publish ${forwardedArgs}`.cwd(dir);
+  } catch (error) {
+    console.error(`failed to publish ${name}`);
+    failures.push({ name, error });
+  }
 }
+
+if (failures.length > 0) {
+  console.error(`\n${failures.length} package(s) failed to publish:`);
+  for (const { name } of failures) console.error(`  - ${name}`);
+  process.exit(1);
+}

Alternatively, keep the fail-fast behavior if it's intentional for your release process.

🤖 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 `@scripts/publish.ts` around lines 53 - 56, The publish loop over targets
currently fails fast; modify the loop that iterates "for (const { name, dir } of
targets)" and the invocation of `await $\`bun publish
${forwardedArgs}\`.cwd(dir)` so that failures are caught per-package
(try/catch), allow the loop to continue publishing remaining packages, record
failed package names and error details in an array, and after the loop print a
summary of failures and exit with a non-zero status if any failed; keep the
success logging for each package and ensure errors include the package `name`
and `dir` when recorded.
scripts/deploy.ts (1)

88-88: ⚡ Quick win

Add safety validation before destructive removal.

The script performs rm -rf on a user-provided output path without validation. If an incorrect path is provided (e.g., repo root, source directory, or system path), this could cause data loss.

🛡️ Proposed safety check
+ // Safety: prevent deleting critical paths
+ const dangerousPaths = [repoRoot, srcDir, process.cwd(), "/", process.env.HOME].filter(Boolean);
+ if (dangerousPaths.some(p => outDir === p || p?.startsWith(outDir + "/"))) {
+   console.error(`refusing to delete protected path: ${outDir}`);
+   process.exit(2);
+ }
+
  await rm(outDir, { recursive: true, force: true });
🤖 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 `@scripts/deploy.ts` at line 88, Before calling rm(outDir...), add a safety
validation: resolve and realpath the provided outDir (use
path.resolve/fs.realpath) and ensure it is not root ("/" or drive root), not the
repository root (compare against process.cwd()), not "." or "..", and is a
subdirectory of an expected build/output base (e.g., verify resolved path
startsWith path.resolve(process.cwd(), "dist" or configured outputBase)). Also
require an explicit confirmation/force flag (e.g., --yes or --force) before
permitting destructive removal, and throw/exit with a clear error if validation
fails; only then perform await rm(outDir, { recursive: true, force: true }).
🤖 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 @.github/workflows/checks.yml:
- Around line 28-31: Replace the mutable action tag oven-sh/setup-bun@v2 with an
immutable commit SHA to improve supply-chain security: look up the v2 release
commit SHA on the setup-bun GitHub releases page and update the workflow's uses
entry (the one referencing oven-sh/setup-bun@v2) to
oven-sh/setup-bun@<COMMIT_SHA>, leaving bun-version: 1.3.11 and the step name
unchanged.

In @.github/workflows/publish-widget.yml:
- Around line 35-38: Replace the mutable action reference "uses:
oven-sh/setup-bun@v2" in the "Install bun" step with an immutable commit SHA for
oven-sh/setup-bun (i.e., pin the action to a specific commit) to prevent
supply-chain risk; locate the step named "Install bun" that currently declares
bun-version: 1.3.11 and update its uses value to the corresponding commit SHA
for the v2 release of oven-sh/setup-bun.

In @.github/workflows/publish.yml:
- Around line 34-37: Replace the mutable tag reference "uses:
oven-sh/setup-bun@v2" with an immutable commit SHA to hardpin the action; locate
the "uses: oven-sh/setup-bun@v2" line in the publish workflow and change the ref
after the @ to the specific commit hash for the oven-sh/setup-bun repo (keeping
the existing bun-version input intact) so the workflow uses a fixed, verifiable
commit instead of the v2 tag.

In @.github/workflows/reusable.init-tests.yml:
- Around line 26-29: Replace the mutable action tag "uses: oven-sh/setup-bun@v2"
with an immutable commit SHA to pin the GitHub Action for supply-chain security;
update the line referencing the action (the "uses" entry currently paired with
the "Install bun" step and using bun-version: ${{ env.BUN_VERSION }}) to use the
specific commit SHA of oven-sh/setup-bun instead of "`@v2`" so the workflow always
runs a fixed, auditable revision.

In @.github/workflows/tests-entry.yml:
- Line 80: Update the commented command in .github/workflows/tests-entry.yml so
it matches the real regen command: replace the snippet/comment that currently
reads "bun run test:e2e:workflow-write" with the actual command "bun run
test:e2e workflow-write" (this aligns with the package.json script mapping and
AGENTS.md guidance).

In `@boilerplates/eslint/package.json`:
- Around line 15-16: Update the inconsistent workspace protocol in package.json
by changing the dependency specifier for "`@batijs/compile`" to use "workspace:*"
to match "`@batijs/core`" and the rest of the boilerplates; locate the
"`@batijs/compile`" entry in the dependencies block and replace "workspace:^" with
"workspace:*" so all `@batijs/`* entries use the same workspace protocol.

In `@packages/build/package.json`:
- Line 23: The peerDependencies entry for "`@batijs/core`" currently uses
"workspace:*" in package.json which may not be rewritten by bun pm pack on
publish; inspect and update the publish flow so peerDependencies are normalized:
modify scripts/deploy.ts to verify that bun pm pack rewrites peerDependencies or
add a step that replaces "workspace:*" (or "workspace:^") in package.json
peerDependencies with the resolved semver (e.g., the version from `@batijs/core`
package.json or the lockfile) before packing/publishing; target the
peerDependencies object and the "`@batijs/core`" key specifically and ensure the
rewritten value is written into the staged package.json used by bun pm pack.

In `@scripts/deploy.ts`:
- Line 56: The current tar extraction in scripts/deploy.ts shells out to the
host tar binary (the line using await $`tar -xzf ${join(tmp, tar)} -C ${destDir}
--strip-components=1`.quiet()) which breaks on Windows; update packInto/deploy
to either (A) add a Node tar dependency (e.g., "tar"/"node-tar"), import it in
scripts/deploy.ts, and replace the shell invocation with a pure-JS extraction
call (use tar.x or equivalent, passing the archive path, cwd/destination and
strip/components option) referencing the tmp/tar and destDir variables, or (B)
explicitly document in README/package.json that a POSIX-compatible tar is
required and why; prefer option A for portability and ensure package.json is
updated with the new dependency and any TypeScript types if needed.

---

Outside diff comments:
In @.github/workflows/reusable.run-tests.yml:
- Around line 47-50: Replace the mutable tag usage of the GitHub Action by
pinning oven-sh/setup-bun to an immutable commit SHA: locate the line that reads
"uses: oven-sh/setup-bun@v2" in the workflow and change it to use the specific
commit SHA for the oven-sh/setup-bun repository while preserving the existing
inputs (e.g., bun-version: ${{ env.BUN_VERSION }}); update the commit SHA to the
latest verified release commit and commit that change so the action runs from an
immutable reference.

---

Nitpick comments:
In `@scripts/deploy.ts`:
- Line 88: Before calling rm(outDir...), add a safety validation: resolve and
realpath the provided outDir (use path.resolve/fs.realpath) and ensure it is not
root ("/" or drive root), not the repository root (compare against
process.cwd()), not "." or "..", and is a subdirectory of an expected
build/output base (e.g., verify resolved path startsWith
path.resolve(process.cwd(), "dist" or configured outputBase)). Also require an
explicit confirmation/force flag (e.g., --yes or --force) before permitting
destructive removal, and throw/exit with a clear error if validation fails; only
then perform await rm(outDir, { recursive: true, force: true }).

In `@scripts/publish.ts`:
- Around line 53-56: The publish loop over targets currently fails fast; modify
the loop that iterates "for (const { name, dir } of targets)" and the invocation
of `await $\`bun publish ${forwardedArgs}\`.cwd(dir)` so that failures are
caught per-package (try/catch), allow the loop to continue publishing remaining
packages, record failed package names and error details in an array, and after
the loop print a summary of failures and exit with a non-zero status if any
failed; keep the success logging for each package and ensure errors include the
package `name` and `dir` when recorded.
🪄 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: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: cf248ce1-c7b2-424d-978f-edc9e2c7778b

📥 Commits

Reviewing files that changed from the base of the PR and between 2325e50 and 74aa176.

⛔ Files ignored due to path filters (2)
  • bun.lock is excluded by !**/*.lock
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (76)
  • .github/renovate.json5
  • .github/workflows/checks.yml
  • .github/workflows/publish-widget.yml
  • .github/workflows/publish.yml
  • .github/workflows/reusable.init-tests.yml
  • .github/workflows/reusable.run-tests.yml
  • .github/workflows/tests-entry.yml
  • AGENTS.md
  • BOILERPLATES.md
  • CONTRIBUTING.md
  • biome.json
  • boilerplates/auth0/package.json
  • boilerplates/authjs/package.json
  • boilerplates/aws/package.json
  • boilerplates/biome/package.json
  • boilerplates/cloudflare/package.json
  • boilerplates/compiled/package.json
  • boilerplates/d1-kysely/package.json
  • boilerplates/d1-sqlite/package.json
  • boilerplates/d1/package.json
  • boilerplates/docker-compose/package.json
  • boilerplates/dokploy/package.json
  • boilerplates/drizzle/package.json
  • boilerplates/edgeone/package.json
  • boilerplates/eslint/package.json
  • boilerplates/express/package.json
  • boilerplates/fastify/package.json
  • boilerplates/google-analytics/package.json
  • boilerplates/h3/package.json
  • boilerplates/hono/package.json
  • boilerplates/kysely/package.json
  • boilerplates/mantine/package.json
  • boilerplates/netlify/package.json
  • boilerplates/oxlint/package.json
  • boilerplates/plausible.io/package.json
  • boilerplates/pnpm/package.json
  • boilerplates/prettier/package.json
  • boilerplates/prisma/package.json
  • boilerplates/react-sentry/package.json
  • boilerplates/react/package.json
  • boilerplates/sentry/package.json
  • boilerplates/shadcn-ui/package.json
  • boilerplates/shared-db/package.json
  • boilerplates/shared-server/package.json
  • boilerplates/shared-todo/package.json
  • boilerplates/shared/package.json
  • boilerplates/solid-sentry/package.json
  • boilerplates/solid/package.json
  • boilerplates/sqlite/package.json
  • boilerplates/storybook/package.json
  • boilerplates/tailwindcss/package.json
  • boilerplates/telefunc/package.json
  • boilerplates/trpc/package.json
  • boilerplates/ts-rest/package.json
  • boilerplates/universal-deploy/package.json
  • boilerplates/vercel/package.json
  • boilerplates/vue-sentry/package.json
  • boilerplates/vue/package.json
  • package.json
  • packages/build/package.json
  • packages/cli/cli.js
  • packages/cli/package.json
  • packages/cli/rolldown-bundle-all.ts
  • packages/compile/cli.js
  • packages/compile/package.json
  • packages/core/package.json
  • packages/features/package.json
  • packages/tests-utils/package.json
  • packages/tests/README.md
  • packages/tests/package.json
  • packages/tests/src/index.ts
  • packages/tsconfig.base.json
  • pnpm-workspace.yaml
  • scripts/deploy.ts
  • scripts/publish.ts
  • website/package.json
💤 Files with no reviewable changes (1)
  • pnpm-workspace.yaml

Comment thread .github/workflows/checks.yml
Comment thread .github/workflows/publish-widget.yml
Comment thread .github/workflows/publish.yml
Comment thread .github/workflows/reusable.init-tests.yml
Comment thread .github/workflows/tests-entry.yml
Comment thread boilerplates/eslint/package.json
Comment thread packages/build/package.json
Comment thread scripts/deploy.ts Outdated
@coderabbitai

coderabbitai Bot commented May 28, 2026

Copy link
Copy Markdown

Actionable comments posted: 0

@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: 0

🧹 Nitpick comments (1)
scripts/lib/workspaces.ts (1)

17-21: ⚡ Quick win

Workspaces parsing matches this repo’s current package.json

scripts/lib/workspaces.ts (lines 17–21) assumes root.workspaces is an array; this repo’s root package.json uses workspaces as a list of strings with no non-string entries, so the assertion/iteration won’t fail for the current configuration.

🤖 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 `@scripts/lib/workspaces.ts` around lines 17 - 21, The code currently asserts
Array.isArray(root.workspaces) then casts to string[] and iterates, but it
doesn't ensure each entry is a string before calling string methods like
glob.endsWith; update the check to assert both that root.workspaces is an array
and that every element is a string (e.g., assert(Array.isArray(root.workspaces)
&& root.workspaces.every(w => typeof w === "string"), "root package.json:
workspaces must be an array of strings")) so the subsequent for (const glob of
root.workspaces) loop and use of glob (e.g., glob.endsWith) are type-safe.
🤖 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 `@scripts/lib/workspaces.ts`:
- Around line 17-21: The code currently asserts Array.isArray(root.workspaces)
then casts to string[] and iterates, but it doesn't ensure each entry is a
string before calling string methods like glob.endsWith; update the check to
assert both that root.workspaces is an array and that every element is a string
(e.g., assert(Array.isArray(root.workspaces) && root.workspaces.every(w =>
typeof w === "string"), "root package.json: workspaces must be an array of
strings")) so the subsequent for (const glob of root.workspaces) loop and use of
glob (e.g., glob.endsWith) are type-safe.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 124a50f4-832c-4846-9eb7-5a52dad3f87e

📥 Commits

Reviewing files that changed from the base of the PR and between 509bca0 and 47dee0f.

📒 Files selected for processing (5)
  • boilerplates/wip/VPS.md
  • packages/tests/src/index.ts
  • scripts/deploy.ts
  • scripts/lib/workspaces.ts
  • scripts/publish.ts
💤 Files with no reviewable changes (1)
  • boilerplates/wip/VPS.md
🚧 Files skipped from review as they are similar to previous changes (2)
  • scripts/deploy.ts
  • packages/tests/src/index.ts

@coderabbitai

coderabbitai Bot commented May 28, 2026

Copy link
Copy Markdown

Actionable comments posted: 0

@coderabbitai

coderabbitai Bot commented May 28, 2026

Copy link
Copy Markdown

Actionable comments posted: 0

@magne4000 magne4000 merged commit c76d417 into main May 29, 2026
177 checks passed
@magne4000 magne4000 deleted the magne4000/dev branch May 29, 2026 07:32
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