Skip to content

refactor: Migrate build process from npm run build to esbuild for…#336

Open
dasein108 wants to merge 1 commit intomainfrom
fix-mcpb-bundle
Open

refactor: Migrate build process from npm run build to esbuild for…#336
dasein108 wants to merge 1 commit intomainfrom
fix-mcpb-bundle

Conversation

@dasein108
Copy link
Collaborator

@dasein108 dasein108 commented Feb 10, 2026

User description

… bundling and dependency management.


CodeAnt-AI Description

Switch MCPB build to esbuild and bundle only native runtime dependencies

What Changed

  • The build script now uses esbuild to produce the dist bundle directly instead of running the previous TypeScript build step; the bundle directory is cleaned and recreated before bundling
  • The bundle's package.json is generated to include only native runtime dependencies (sharp and @vscode/ripgrep) while everything else is bundled into the output
  • All platform-specific ripgrep binaries are copied into the bundle and a runtime wrapper is installed so ripgrep works across platforms
  • esbuild was added to package.json and package-lock updated to the esbuild 0.27.3 artifacts and related package version bumps

Impact

✅ Faster local bundling with esbuild
✅ Smaller MCPB bundle by embedding non-native code
✅ Reliable ripgrep runtime across platforms

💡 Usage Guide

Checking Your Pull Request

Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.

Talking to CodeAnt AI

Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:

@codeant-ai ask: Your question here

This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.

Example

@codeant-ai ask: Can you suggest a safer alternative to storing this secret?

Preserve Org Learnings with CodeAnt

You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:

@codeant-ai: Your feedback here

This helps CodeAnt AI learn and adapt to your team's coding style and standards.

Example

@codeant-ai: Do not flag unused imports.

Retrigger review

Ask CodeAnt AI to review the PR again, by typing:

@codeant-ai: review

Check Your Repository Health

To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.

Summary by CodeRabbit

Release Notes

  • Chores
    • Transitioned bundling process to esbuild for improved build performance and more efficient packaging workflows
    • Enhanced cross-platform compatibility with updated ripgrep binary handling, configuration procedures, and installation setup
    • Refined build system reliability with improved error handling, comprehensive manifest validation, and enhanced diagnostic logging throughout the build pipeline

@codeant-ai
Copy link
Contributor

codeant-ai bot commented Feb 10, 2026

CodeAnt AI is reviewing your PR.


Thanks for using CodeAnt! 🎉

We're free for open-source projects. if you're enjoying it, help us grow by sharing.

Share on X ·
Reddit ·
LinkedIn

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 10, 2026

📝 Walkthrough

Walkthrough

This pull request introduces esbuild as a build dependency and refactors the MCPB bundling script to use esbuild for bundling, adds manifest template interpolation, implements production dependency installation within the bundle directory, and introduces cross-platform ripgrep setup with binary copying and runtime wrapper configuration.

Changes

Cohort / File(s) Summary
Build Dependencies
package.json
Added esbuild to both dependencies and devDependencies sections.
Build Script Refactoring
scripts/build-mcpb.cjs
Replaced TypeScript compilation with esbuild-based bundling workflow. Refactored manifest generation to read from manifest.template.json and interpolate version. Updated bundle copying logic to skip dist folder (handled by esbuild). Added production dependency installation step (npm install --omit=dev --production) within bundle. Introduced cross-platform ripgrep binary setup with executable permission handling and runtime wrapper replacement. Enhanced error handling and logging throughout bundling and ripgrep setup stages.

Sequence Diagram

sequenceDiagram
    participant Build as Build Script
    participant FS as File System
    participant Bundler as esbuild
    participant Manifest as manifest.json
    participant Deps as npm Dependencies
    participant Ripgrep as ripgrep Setup
    
    Build->>FS: Clean and create bundle dir
    Build->>FS: Ensure dist folder exists
    Build->>Bundler: Run esbuild with config
    Bundler->>FS: Output to mcpb-bundle/dist/index.js
    Build->>FS: Copy template files to bundle
    Build->>Manifest: Read manifest.template.json
    Build->>Manifest: Interpolate version from package.json
    Build->>Manifest: Validate and write manifest.json
    Build->>FS: Write bundle package.json (native deps only)
    Build->>Deps: Install production deps in bundle
    Deps->>FS: node_modules created in bundle
    Build->>Ripgrep: Copy ripgrep binaries
    Ripgrep->>FS: Set executable permissions
    Ripgrep->>FS: Replace index.js with runtime wrapper
    Build->>Build: Output completion guidance
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

size:L

Poem

🐰 A bundler arrives with esbuild's speed,
Manifest templates are all we need,
Ripgrep hops in with binaries tight,
Production deps installed just right—
The MCPB build now takes flight!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes the main change: migrating the build process to esbuild, which aligns with the significant refactoring evident in scripts/build-mcpb.cjs and the esbuild dependency addition in package.json.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix-mcpb-bundle

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.

@codeant-ai codeant-ai bot added the size:L This PR changes 100-499 lines, ignoring generated files label Feb 10, 2026
@codeant-ai
Copy link
Contributor

codeant-ai bot commented Feb 10, 2026

Sequence Diagram

The PR replaces the previous "npm run build" step with an esbuild-based bundling flow. The script now cleans/creates the bundle directory, runs esbuild to produce a self-contained dist, writes a minimal bundle package.json with only native deps, and installs ripgrep runtime assets into the bundle.

sequenceDiagram
    participant CI as Developer/CI
    participant Script as scripts/build-mcpb.cjs
    participant Esbuild as esbuild
    participant FS as File System (bundle/)
    
    CI->>Script: run build script
    Script->>FS: Clean & create bundle directory
    Script->>Esbuild: npx esbuild src/index.ts -> mcpb-bundle/dist/index.js
    Esbuild-->>Script: bundled dist files
    Script->>FS: Create manifest + bundle package.json (only native deps: sharp, @vscode/ripgrep)
    Script->>FS: Copy ripgrep binaries & install wrapper
    Script-->>CI: Bundle ready (mcpb-bundle with dist and runtime deps)
Loading

Generated by CodeAnt AI

@codeant-ai
Copy link
Contributor

codeant-ai bot commented Feb 10, 2026

Nitpicks 🔍

🔒 No security issues identified
⚡ Recommended areas for review

  • Unsafe dependency access
    The new bundle package.json directly accesses packageJson.dependencies.sharp and packageJson.dependencies["@vscode/ripgrep"]. If those keys are missing, the script will write undefined into the bundle package.json or throw. Validate presence and fail early with a helpful message or omit absent deps.

  • Clean removal risk
    The script uses fs.rmSync(BUNDLE_DIR, { recursive: true }) to delete the bundle directory. On some platforms or node versions this may fail (permissions, locked files). Consider using force: true or handling errors to avoid leaving a half-cleaned state that later steps assume doesn't exist.

  • Hardcoded esbuild command
    The execSync esbuild call hardcodes arguments (including mcpb-bundle/dist/index.js) and uses npx and a single string command. This is brittle cross-platform and may hide failures (shell quoting, PATH differences). Consider constructing the outfile path via path.join and using an argument array or execFileSync to avoid shell parsing issues and to make the command robust.

@codeant-ai
Copy link
Contributor

codeant-ai bot commented Feb 10, 2026

CodeAnt AI finished reviewing your PR.

Copy link
Contributor

@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.

Caution

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

⚠️ Outside diff range comments (2)
scripts/build-mcpb.cjs (2)

76-76: ⚠️ Potential issue | 🟡 Minor

Use replaceAll() for more robust string replacement.

The manifest template currently contains only one {{VERSION}} placeholder, so the existing code works. However, using replaceAll() is a better defensive practice and ensures the code handles multiple occurrences correctly if the template is modified in the future.

Proposed fix
-const manifestContent = manifestTemplate.replace('{{VERSION}}', packageJson.version);
+const manifestContent = manifestTemplate.replaceAll('{{VERSION}}', packageJson.version);

151-185: ⚠️ Potential issue | 🟡 Minor

Add a guard to fail fast if no ripgrep binaries are found.

The paths in build-mcpb.cjs and download-all-ripgrep.cjs are correctly aligned (both reference node_modules/@vscode/ripgrep/bin), and the binary naming matches the expected rg-* pattern. However, if download-all-ripgrep.cjs has not been run or the directory doesn't exist, fs.readdirSync(ripgrepBinSrc).filter(f => f.startsWith('rg-')) would silently return an empty array, causing the forEach loop to be a no-op and resulting in a broken bundle with no ripgrep binaries.

Proposed fix — fail fast if no binaries found
     const binaries = fs.readdirSync(ripgrepBinSrc).filter(f => f.startsWith('rg-'));
+    if (binaries.length === 0) {
+        throw new Error('No ripgrep binaries found in ' + ripgrepBinSrc);
+    }
     binaries.forEach(binary => {
🧹 Nitpick comments (2)
scripts/build-mcpb.cjs (2)

91-98: package.json is copied in Step 5 (line 94) then overwritten in Step 6 (line 137).

The copy of package.json from the project root is immediately overwritten by the bundle-specific package.json. Remove it from filesToCopy to avoid confusion — the commented-out dist entry already sets the precedent for skipping files handled differently.

Proposed fix
 const filesToCopy = [
     // 'dist', // Skipped because we generate dist via esbuild directly into bundle
-
-    'package.json',
     'README.md',
     'LICENSE',
     'PRIVACY.md',
     'icon.png'
 ];

Also applies to: 119-139


144-144: --omit=dev and --production are redundant.

Both flags achieve the same effect (skip devDependencies). --production is the legacy form; --omit=dev is the modern equivalent. Pick one.

Proposed fix
-    execSync('npm install --omit=dev --production', { cwd: BUNDLE_DIR, stdio: 'inherit' });
+    execSync('npm install --omit=dev', { cwd: BUNDLE_DIR, stdio: 'inherit' });

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L This PR changes 100-499 lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant