Skip to content

Comments

chore: migrate from Yarn to Bun#3020

Draft
anymaniax wants to merge 2 commits intofeature/package-exports-devfrom
feature/migrate-bun
Draft

chore: migrate from Yarn to Bun#3020
anymaniax wants to merge 2 commits intofeature/package-exports-devfrom
feature/migrate-bun

Conversation

@anymaniax
Copy link
Collaborator

@anymaniax anymaniax commented Feb 22, 2026

Summary

  • Replaced Yarn 4.x with Bun as the package manager across the entire monorepo
  • Migrated Yarn Catalogs from .yarnrc.yml to Bun's native catalog/catalogs fields in root package.json (Bun supports the same catalog: protocol)
  • Updated all 4 CI/CD workflows to use oven-sh/setup-bun@v2 instead of corepack + Yarn
  • Updated husky hooks, release-it config, eslint config, Dockerfile, and all sample/package scripts
  • Updated all documentation (README, CONTRIBUTING, DEBUGGING, sample READMEs)
  • Removed yarn.lock, .yarnrc.yml, .yarn/ directory, and docs/yarn.lock
  • Fixed test in @orval/core that relied on Yarn's flat hoisting behavior

Notes

  • Root package.json devDependencies have inlined versions because Bun doesn't support catalog: references in the root package itself
    (bun#26219)
  • packageManager field kept as bun@1.3.9 (required by Turbo for workspace resolution)
  • End-user facing docs (docs/content/docs/installation.mdx, skill files) still list yarn as a PM option for orval users — this is intentional

Summary by CodeRabbit

  • Chores
    • Migrated package manager from Yarn to Bun across the project.
    • Updated all build, test, and deployment scripts to use Bun commands instead of Yarn.
    • Updated GitHub Actions workflows for CI/CD with Bun setup and commands.
    • Removed Yarn-specific configuration files and lockfiles; now using Bun lockfile.
    • Updated documentation and development guides to reflect Bun usage.

@coderabbitai
Copy link

coderabbitai bot commented Feb 22, 2026

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • ✅ Review completed - (🔄 Check again to review again)
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/migrate-bun

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

Copy link

@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

Caution

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

⚠️ Outside diff range comments (1)
DEBUGGING.md (1)

52-56: ⚠️ Potential issue | 🟡 Minor

Use bun run test to invoke the package script, not Bun's built-in runner.

With runtimeExecutable: "bun" and args ["test", "${file}"], this runs bun test (Bun's built-in test runner), which bypasses the project's package.json test script. Bun's built-in commands take precedence over same-named scripts. Use bun run test -- ${file} (or bun run vitest -- ${file}) to ensure the configured test script runs instead.

🔧 Suggested update
-  "runtimeExecutable": "bun",
-  "args": [
-    "test",
-    "${file}" // Refers to the currently open file in the editor
-  ],
+  "runtimeExecutable": "bun",
+  "args": [
+    "run",
+    "test",
+    "--",
+    "${file}" // Refers to the currently open file in the editor
+  ],
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@DEBUGGING.md` around lines 52 - 56, The debug config currently sets
runtimeExecutable: "bun" with args ["test", "${file}"], which invokes Bun's
built-in test runner instead of the project's package script; update the args to
call the package script via Bun's run command (e.g., use args ["run", "test",
"--", "${file}"] or ["run", "vitest", "--", "${file}"]) so the configured test
script in package.json is executed when using runtimeExecutable: "bun".
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/release-prepare.yaml:
- Around line 50-53: The current for-loop that updates versions (the block
iterating over packages/*/package.json and package.json and using jq to write
tmp.$$.json then mv) misses nested workspaces (samples/**) and tests; update the
loop to enumerate all package.json files for workspaces (e.g., use find . -name
package.json -not -path '*/node_modules/*' or parse the root package.json
"workspaces" field) so every workspace package.json is updated with jq --arg v
... '.version = $v' and moved via tmp.$$.json before running bun run
test:snapshots:update; ensure the new iteration still excludes node_modules and
preserves the existing jq/temp-file pattern.

In @.github/workflows/release-publish.yaml:
- Around line 54-60: The workflow currently swallows publish errors via "npm
publish ... || true"; update the loop that iterates over pkg
(packages/*/package.json) to track failures instead: remove the "|| true",
capture the exit code of npm publish for each package (using the pkg/dir
variables), set a flag variable (e.g., publish_failed=1) if any publish fails,
and after the loop check that flag and exit non‑zero to fail the job so later
tag/release steps only run on success.

In @.husky/pre-commit:
- Line 1: The hook currently only contains the command "bun run format:staged"
and is missing the Husky shim/shebang header; update the .husky/pre-commit hook
to include a POSIX shebang and source the Husky shim/initializer at the top of
the file before the existing bun run format:staged command so the hook runs
reliably across environments (i.e., add the standard "#!/usr/bin/env sh" shebang
and the line that sources the repository's husky.sh before invoking bun run
format:staged).

In `@samples/mcp/petstore/Dockerfile`:
- Around line 7-9: The Dockerfile currently installs the latest Bun (RUN npm
install -g bun) which can drift from the repo's declared packageManager
bun@1.3.9; update the installation command to pin Bun to 1.3.9 (keep the
subsequent RUN bun install --frozen-lockfile and CMD ["bun","run","dev"]
unchanged) so the container uses the same Bun version as package.json for
reproducible builds.

---

Outside diff comments:
In `@DEBUGGING.md`:
- Around line 52-56: The debug config currently sets runtimeExecutable: "bun"
with args ["test", "${file}"], which invokes Bun's built-in test runner instead
of the project's package script; update the args to call the package script via
Bun's run command (e.g., use args ["run", "test", "--", "${file}"] or ["run",
"vitest", "--", "${file}"]) so the configured test script in package.json is
executed when using runtimeExecutable: "bun".

---

Duplicate comments:
In @.github/workflows/release-prepare.yaml:
- Around line 28-33: The workflow currently uses oven-sh/setup-bun@v2 without
pinning a specific Bun version; change the "Setup Bun" step (the GitHub Actions
step named "Setup Bun") to pin a fixed version (for example oven-sh/setup-bun@v2
with inputs or a tag like oven-sh/setup-bun@<specific-version>) and ensure the
"Install dependencies" step that runs `bun install --frozen-lockfile` remains
compatible; update the action invocation to include the explicit Bun version
input or exact action tag so the workflow uses a reproducible Bun release.

In @.github/workflows/release-publish.yaml:
- Around line 26-27: The workflow step named "Setup Bun" currently uses the
floating tag oven-sh/setup-bun@v2; replace that with a specific pinned release
(e.g. a full semver tag or commit SHA) to avoid drifting versions and ensure it
matches the pinned Bun version used in the PR checks; update the uses reference
for the "Setup Bun" step so the action is oven-sh/setup-bun@<pinned-version>
(match the same exact version used elsewhere in your repository).

Comment on lines +50 to +53
for pkg in packages/*/package.json package.json; do
jq --arg v "${{ github.event.inputs.version }}" '.version = $v' "$pkg" > tmp.$$.json && mv tmp.$$.json "$pkg"
done
bun run test:snapshots:update
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check workspace configuration
echo "=== Workspaces defined in root package.json ==="
jq -r '.workspaces[]?' package.json 2>/dev/null || echo "No workspaces field found"

echo ""
echo "=== All package.json files in repository ==="
fd -g 'package.json' --type f | sort

Repository: orval-labs/orval

Length of output: 1783


Verify version bump coverage for all intended workspaces.

The loop only covers packages/*/package.json and the root, but the workspace configuration defines three globs: packages/*, samples/**, and tests. This misses:

  • Nested workspaces under samples/ (e.g., samples/hono/hono-with-fetch-client/hono-app/package.json)
  • The tests/package.json workspace

Use find . -name package.json -not -path '*/node_modules/*' to ensure all workspaces are version-bumped, or derive the list from the workspaces field in package.json.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/release-prepare.yaml around lines 50 - 53, The current
for-loop that updates versions (the block iterating over packages/*/package.json
and package.json and using jq to write tmp.$$.json then mv) misses nested
workspaces (samples/**) and tests; update the loop to enumerate all package.json
files for workspaces (e.g., use find . -name package.json -not -path
'*/node_modules/*' or parse the root package.json "workspaces" field) so every
workspace package.json is updated with jq --arg v ... '.version = $v' and moved
via tmp.$$.json before running bun run test:snapshots:update; ensure the new
iteration still excludes node_modules and preserves the existing jq/temp-file
pattern.

Comment on lines +54 to +60
run: |
for pkg in packages/*/package.json; do
dir=$(dirname "$pkg")
if ! jq -e '.private' "$pkg" > /dev/null 2>&1 || [ "$(jq -r '.private' "$pkg")" = "false" ] || [ "$(jq -r '.private' "$pkg")" = "null" ]; then
echo "Publishing $(jq -r '.name' "$pkg")..."
cd "$dir" && npm publish --access public || true
cd -
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

find . -name "release-publish.yaml" -o -name "release-publish.yml" | head -20

Repository: orval-labs/orval

Length of output: 100


🏁 Script executed:

cat -n .github/workflows/release-publish.yaml | head -80

Repository: orval-labs/orval

Length of output: 3252


🏁 Script executed:

# Verify there are no other error handlers or conditions after the publish step
cat -n .github/workflows/release-publish.yaml | sed -n '53,80p'

Repository: orval-labs/orval

Length of output: 1309


🏁 Script executed:

# Check if there are any on-error handlers or continue-on-error flags
grep -n "continue-on-error\|if:\|on-error" .github/workflows/release-publish.yaml

Repository: orval-labs/orval

Length of output: 174


Don't swallow publish failures.
npm publish ... || true suppresses errors and allows the workflow to succeed even when a package fails to publish. Since subsequent steps create GitHub tags and releases unconditionally (lines 70-80), this can result in a tagged release with missing npm packages. Track failures across the loop and fail the job if any publish attempt fails.

🔧 Suggested fix
       - name: Publish workspaces to npm
         run: |
+          failed=0
           for pkg in packages/*/package.json; do
             dir=$(dirname "$pkg")
             if ! jq -e '.private' "$pkg" > /dev/null 2>&1 || [ "$(jq -r '.private' "$pkg")" = "false" ] || [ "$(jq -r '.private' "$pkg")" = "null" ]; then
               echo "Publishing $(jq -r '.name' "$pkg")..."
-              cd "$dir" && npm publish --access public || true
-              cd -
+              if ! (cd "$dir" && npm publish --access public); then
+                echo "Publish failed for $(jq -r '.name' "$pkg")"
+                failed=1
+              fi
             fi
           done
+          exit $failed
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/release-publish.yaml around lines 54 - 60, The workflow
currently swallows publish errors via "npm publish ... || true"; update the loop
that iterates over pkg (packages/*/package.json) to track failures instead:
remove the "|| true", capture the exit code of npm publish for each package
(using the pkg/dir variables), set a flag variable (e.g., publish_failed=1) if
any publish fails, and after the loop check that flag and exit non‑zero to fail
the job so later tag/release steps only run on success.

@@ -1 +1 @@
yarn format:staged
bun run format:staged
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Restore Husky shim/shebang to keep hooks reliable.
Without the standard Husky header, the hook can fail to execute in some environments.

🔧 Suggested fix
+#!/usr/bin/env sh
+. "$(dirname -- "$0")/_/husky.sh"
+
 bun run format:staged
📝 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.

Suggested change
bun run format:staged
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
bun run format:staged
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.husky/pre-commit at line 1, The hook currently only contains the command
"bun run format:staged" and is missing the Husky shim/shebang header; update the
.husky/pre-commit hook to include a POSIX shebang and source the Husky
shim/initializer at the top of the file before the existing bun run
format:staged command so the hook runs reliably across environments (i.e., add
the standard "#!/usr/bin/env sh" shebang and the line that sources the
repository's husky.sh before invoking bun run format:staged).

Comment on lines +7 to +9
RUN npm install -g bun
RUN bun install --frozen-lockfile
CMD ["bun", "run", "dev"]
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# Find the package.json files to check for bun version declaration
find . -name "package.json" -type f | head -20

Repository: orval-labs/orval

Length of output: 735


🏁 Script executed:

# Also check for other version declaration files
fd -t f "\.(tool-versions|bun-version|bun)$" --max-depth 5

Repository: orval-labs/orval

Length of output: 42


🏁 Script executed:

# Check the content of package.json in the petstore sample directory
find . -path "*/samples/mcp/petstore/package.json" -type f -exec cat {} \;

Repository: orval-labs/orval

Length of output: 677


🏁 Script executed:

# Check the root package.json
head -100 ./package.json

Repository: orval-labs/orval

Length of output: 3107


🏁 Script executed:

# Search for bun.lockb or other lockfiles
find . -maxdepth 3 -name "bun.lockb" -o -name ".tool-versions" -o -name ".bun-version"

Repository: orval-labs/orval

Length of output: 42


🏁 Script executed:

# Check if there's an engines field in petstore package.json
cat ./samples/mcp/petstore/package.json | grep -A 5 "engines"

Repository: orval-labs/orval

Length of output: 42


🏁 Script executed:

# Check the Dockerfile content
cat -n ./samples/mcp/petstore/Dockerfile

Repository: orval-labs/orval

Length of output: 297


Pin Bun to the repo's declared version for reproducible builds.
The root package.json declares "packageManager": "bun@1.3.9". Installing the latest Bun in the Dockerfile can drift from this version and introduce unexpected behavior in Docker builds. Pin the version to match the repo's declaration.

🔧 Suggested change
-RUN npm install -g bun
+RUN npm install -g bun@1.3.9
📝 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.

Suggested change
RUN npm install -g bun
RUN bun install --frozen-lockfile
CMD ["bun", "run", "dev"]
RUN npm install -g bun@1.3.9
RUN bun install --frozen-lockfile
CMD ["bun", "run", "dev"]
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@samples/mcp/petstore/Dockerfile` around lines 7 - 9, The Dockerfile currently
installs the latest Bun (RUN npm install -g bun) which can drift from the repo's
declared packageManager bun@1.3.9; update the installation command to pin Bun to
1.3.9 (keep the subsequent RUN bun install --frozen-lockfile and CMD
["bun","run","dev"] unchanged) so the container uses the same Bun version as
package.json for reproducible builds.

@ScriptType
Copy link
Contributor

My ai atleast says the coderabbit mentioned issues are real.

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.

2 participants