Skip to content

add bun support#7

Merged
twangodev merged 6 commits intomainfrom
feat/bun
Jan 6, 2026
Merged

add bun support#7
twangodev merged 6 commits intomainfrom
feat/bun

Conversation

@twangodev
Copy link
Copy Markdown
Owner

@twangodev twangodev commented Jan 5, 2026

Summary by CodeRabbit

  • New Features

    • Multi-platform standalone executables added.
    • CLI includes pre-bundled fonts for improved terminal display.
  • Chores

    • CI and build toolchain migrated to Bun-based tooling; publish workflow updated to include built binaries.
    • New build scripts and commands added to generate fonts and produce binaries; minor dev dependency updates.

✏️ Tip: You can customize this high-level summary in your review settings.

Copilot AI review requested due to automatic review settings January 5, 2026 23:42
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jan 5, 2026

📝 Walkthrough

Walkthrough

Swaps CI from Node/npm to Bun across workflow jobs, adds a Build Binaries job and artifact upload, introduces scripts to generate bundled figlet fonts and to build cross-platform binaries, updates package.json scripts/devDependencies, extends .gitignore, and calls font initialization at CLI startup.

Changes

Cohort / File(s) Summary
CI / Workflow
​.github/workflows/node.yml
Replaces Node.js/npm steps with Bun tooling, adds a Build Binaries job that runs bun build:all and uploads artifacts, updates Publish to depend on binaries and run Bun install/build before publishing, and standardizes checkout/action versions.
Build scripts
scripts/build-binaries.ts, scripts/generate-fonts.ts
Adds scripts/build-binaries.ts to iterate Bun targets and invoke bun build producing dist/bin/* (no per-target error handling). Adds scripts/generate-fonts.ts to scan figlet fonts and emit src/fonts.ts, exporting initializeFonts() and fontList.
Package config
package.json
Adds scripts: prebuild, build:fonts, build:binary, build:all; adds devDependencies react-devtools-core ^7.0.1 and @types/bun ^1.3.5.
Generated / Bundled output
src/fonts.ts (generated), dist/bin/ (output)
New generated fonts module and binary output directory are produced and added to ignore.
Project ignores
.gitignore
Adds ignores for src/fonts.ts, dist/bin/, w67, w67.exe; minor reordering of .idea/.
Runtime init
src/cli.tsx
Imports and invokes initializeFonts() at module startup to register fonts for bundled builds.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant GH as GitHub Actions
  participant Repo as Repository (scripts, src)
  participant Bun as Bun tool/runtime
  participant FS as Filesystem (dist/bin, src/fonts.ts)
  participant Npm as npm registry

  GH->>Repo: checkout
  GH->>Bun: setup Bun (action/setup-bun)
  GH->>Bun: bun install / bun run prebuild
  GH->>Repo: run `scripts/generate-fonts.ts`
  Repo->>FS: write `src/fonts.ts`
  GH->>Bun: bun run build:all (invokes build-binaries)
  Bun->>Repo: execute `scripts/build-binaries.ts`
  Repo->>Bun: bun build (per-target)
  Bun->>FS: emit `dist/bin/*` artifacts
  GH->>GH: upload artifacts
  GH->>Bun: bun install/build in Publish job
  GH->>Npm: npm publish (preserves npm publish step)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 I leapt from npm to Bun with cheer,
I bundled fonts and built things here,
I scanned and wrote each figlet tune,
I packed the bins beneath the moon,
Hop-hop — a shiny build is near!

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'add bun support' directly matches the main objective of the pull request, which replaces npm/Node.js with Bun across CI workflows, build scripts, and dependencies.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings

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.

# Conflicts:
#	.github/workflows/node.yml
#	package-lock.json
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds Bun support to enable building standalone executables for the w67 CLI tool across multiple platforms (macOS, Linux, Windows). The key changes include:

  • Replacing npm with Bun as the package manager and build tool
  • Adding scripts to generate font bundles and build cross-platform binaries
  • Removing the Node.js shebang from the CLI entry point
  • Updating CI/CD workflows to use Bun

Reviewed changes

Copilot reviewed 5 out of 8 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
src/cli.tsx Removed Node.js shebang; added font initialization call at module load
scripts/generate-fonts.ts New script to bundle all figlet fonts into a single importable module for compiled binaries
scripts/build-binaries.ts New script to build standalone executables for 7 different platform/architecture combinations
package.json Added Bun-based build scripts; added react-devtools-core v7.0.1 as devDependency
package-lock.json Deleted npm lockfile
bun.lock Added new Bun lockfile
.gitignore Added entries for generated fonts file and compiled binaries
.github/workflows/node.yml Migrated CI workflow from npm to Bun; added binary build job

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread scripts/build-binaries.ts Outdated
Comment thread src/cli.tsx
Comment thread src/cli.tsx
Comment thread scripts/generate-fonts.ts
Comment thread .github/workflows/node.yml
Comment thread package.json Outdated
Comment thread package.json
Comment thread scripts/generate-fonts.ts
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: 2

Fix all issues with AI Agents 🤖
In @package.json:
- Line 14: Update the package.json "build" script so fonts are generated before
TypeScript compilation: modify the "build" script to run the existing
"build:fonts" step prior to running tsc (or add a "prebuild" script that runs
"build:fonts"); ensure this produces the ./fonts.js file required by src/cli.tsx
so that npm run build and the prepublishOnly step succeed.
🧹 Nitpick comments (5)
scripts/generate-fonts.ts (1)

17-23: Add error handling for missing or empty fonts directory.

The script will fail silently or with unclear errors if node_modules/figlet/importable-fonts doesn't exist or contains no font files. Consider validating before proceeding.

🔎 Suggested validation checks
+import { existsSync, readdirSync, writeFileSync } from "fs";
-import { readdirSync, writeFileSync } from "fs";
 import { join, dirname } from "path";
 import { fileURLToPath } from "url";

 const __filename = fileURLToPath(import.meta.url);
 const __dirname = dirname(__filename);

 const fontsDir = join(__dirname, "../node_modules/figlet/importable-fonts");
 const outputFile = join(__dirname, "../src/fonts.ts");

+// Validate fonts directory exists
+if (!existsSync(fontsDir)) {
+  console.error(`Error: Fonts directory not found: ${fontsDir}`);
+  console.error("Please run 'npm install' or 'bun install' first.");
+  process.exit(1);
+}
+
 // Get all .js font files (exclude .d.ts type definitions)
 const fontFiles = readdirSync(fontsDir)
   .filter((f) => f.endsWith(".js"))
   .map((f) => f.replace(/\.js$/, ""));

+// Validate we found fonts
+if (fontFiles.length === 0) {
+  console.error(`Error: No font files found in ${fontsDir}`);
+  process.exit(1);
+}
+
 console.log(`Found ${fontFiles.length} fonts`);
scripts/build-binaries.ts (2)

25-42: Validate that dist/cli.js exists before building binaries.

The script assumes dist/cli.js exists but doesn't verify it. If TypeScript compilation hasn't run or failed, the builds will fail with unclear errors.

🔎 Suggested validation
 import { $ } from "bun";
-import { mkdir } from "fs/promises";
+import { mkdir, access } from "fs/promises";
+import { constants } from "fs";

 const targets = [
   // ... targets ...
 ];

 console.log("Building binaries for all platforms...\n");

+// Validate dist/cli.js exists
+try {
+  await access("dist/cli.js", constants.F_OK);
+} catch {
+  console.error("Error: dist/cli.js not found. Run 'bun run build' first.");
+  process.exit(1);
+}
+
 await mkdir("dist/bin", { recursive: true });

38-41: Consider more descriptive error messages.

The current error output only shows "Failed" without context. Consider logging the actual error or build command details to aid debugging.

🔎 Enhanced error reporting
   } catch (error) {
-    console.error(`  ✗ ${out} - Failed`);
+    console.error(`  ✗ ${out} - Failed:`, error instanceof Error ? error.message : error);
     failed++;
   }
.github/workflows/node.yml (2)

16-19: Consider pinning Bun version and enabling dependency caching.

The Bun setup doesn't specify a version, which could lead to inconsistent builds across runs if Bun releases breaking changes. Additionally, enabling caching would speed up CI runs.

🔎 Suggested improvements
      - uses: actions/checkout@v4
-      - uses: oven-sh/setup-bun@v2
+      - uses: oven-sh/setup-bun@v2
+        with:
+          bun-version: latest  # or pin to a specific version like '1.0.0'
       - run: bun install

For caching, you can also add:

      - uses: actions/cache@v4
        with:
          path: ~/.bun/install/cache
          key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lockb') }}
          restore-keys: |
            ${{ runner.os }}-bun-

60-61: Remove redundant build step in publish job.

The publish job runs bun run build even though it already depends on the build job. This duplicates work and wastes CI time. Consider either:

  1. Removing the build step and relying on the dependency, or
  2. Downloading build artifacts from the build job if they're needed.

Since you're rebuilding anyway, the build job dependency might also be redundant unless you want to ensure basic build validation passes before attempting to publish.

🔎 Option 1: Remove redundant build step
      - run: bun install
-      - run: bun run build
      - run: npm publish --provenance --access public

Note: This assumes the checkout and install are sufficient, or you download build artifacts. You may need to verify what files npm publish expects.

🔎 Option 2: Download build artifacts instead of rebuilding
      - run: bun install
-      - run: bun run build
+      - uses: actions/download-artifact@v4
+        with:
+          name: build-output
+          path: dist/
      - run: npm publish --provenance --access public

Note: This requires the build job to also upload artifacts.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a359b3b and 6b9292d.

⛔ Files ignored due to path filters (2)
  • bun.lock is excluded by !**/*.lock
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (6)
  • .github/workflows/node.yml
  • .gitignore
  • package.json
  • scripts/build-binaries.ts
  • scripts/generate-fonts.ts
  • src/cli.tsx
🧰 Additional context used
🪛 GitHub Actions: CI
src/cli.tsx

[error] 6-6: TS2307: Cannot find module './fonts.js' or its corresponding type declarations.

🔇 Additional comments (7)
.gitignore (1)

144-152: LGTM! Appropriate ignores for build artifacts.

The new ignore patterns correctly exclude generated files (fonts.ts), build outputs (dist/bin/), and compiled binaries (w67, w67.exe) from version control.

scripts/generate-fonts.ts (1)

28-35: LGTM! Clean approach to avoid import naming conflicts.

Using numbered variable names (font0, font1, etc.) effectively prevents naming collisions with font names that might be invalid JavaScript identifiers.

package.json (2)

15-17: LGTM! Build scripts correctly chain dependencies.

The new build scripts properly sequence operations:

  • build:fonts → generates font registry
  • build:binary → fonts → TypeScript → single binary
  • build:all → fonts → TypeScript → multi-platform binaries

51-51: Clarify the purpose of react-devtools-core.

This appears to be added as a peer dependency requirement for the ink package (v6.5.1), which declares react-devtools-core as a peer dependency. Please add a comment in package.json or clarify in the PR description that this was added to satisfy ink's peer dependency requirement.

scripts/build-binaries.ts (1)

11-23: LGTM! Comprehensive platform coverage.

The target list includes appropriate coverage across macOS, Linux (glibc and musl), and Windows on multiple architectures.

.github/workflows/node.yml (2)

30-42: Artifact path correctly matches build script output. The dist/bin/ directory specified in the artifact upload aligns with the output path defined in scripts/build-binaries.ts (line 35: outfile dist/bin/${out}).


44-62: Remove concern about downloading binaries—they are for releases, not npm publishing.

The binaries job creates standalone executables in dist/bin/ which are uploaded as artifacts for GitHub releases. However, the npm package only includes files in the dist directory (per the "files" field in package.json) and relies on the compiled JavaScript, not these binary executables. The "bin" field points to dist/cli.js (compiled JavaScript), not a binary artifact.

The workflow is correct as-is. The dependency on the binaries job is appropriate for ensuring the build completes successfully before publishing, even if the artifacts aren't downloaded.

Comment thread package.json
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: 1

Fix all issues with AI Agents 🤖
In @src/cli.tsx:
- Line 10: The call to initializeFonts() runs at module load with no error
handling; wrap the call in a try/catch (or move it into your main() startup
flow) so font initialization failures don't crash the app: locate
initializeFonts() in src/cli.tsx, surround the invocation with try { await or
call initializeFonts(); } catch (err) { console.error("Font initialization
failed:", err); /* fallback behavior or exit gracefully */ } and if you choose
async startup, remove the top-level call and invoke initializeFonts() inside
main() with the same try/catch.
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6b9292d and 33e989e.

📒 Files selected for processing (2)
  • package.json
  • src/cli.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • package.json

Comment thread src/cli.tsx
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: 2

Fix all issues with AI Agents 🤖
In @scripts/build-binaries.ts:
- Around line 15-18: Wrap the build invocation in a try/catch to avoid silent
crashes: for each iteration over targets (the loop using targets, out and the
await $`bun build ... --outfile dist/bin/${out}` invocation) catch any thrown
error, log a clear diagnostic including the target/out and the error
stack/message (e.g., console.error or processLogger.error), and ensure the
process exits with a non-zero status (process.exit(1)) or rethrows after
logging; optionally collect per-target failures and fail fast on the first error
or report all failures after the loop depending on desired behavior.
🧹 Nitpick comments (1)
scripts/build-binaries.ts (1)

15-18: Consider parallelizing builds for faster execution.

The script builds binaries sequentially, which may be slow for 8 targets. Consider parallelizing with Promise.all to reduce total build time.

🔎 Proposed refactor for parallel execution
-for (const target of targets) {
+await Promise.all(targets.map(async (target) => {
   const out = `w67-${target.replace("bun-", "")}${target.includes("windows") ? ".exe" : ""}`;
   try {
     console.log(`Building ${out}...`);
     await $`bun build ./dist/cli.js --compile --target=${target} --outfile dist/bin/${out}`;
     console.log(`  ✓ ${out} - Success`);
   } catch (error) {
     console.error(`  ✗ ${out} - Failed`);
     console.error(error);
     process.exit(1);
   }
-}
+}));

Note: This assumes your build environment can handle concurrent builds.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 33e989e and f4f43de.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (2)
  • package.json
  • scripts/build-binaries.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • package.json

Comment thread scripts/build-binaries.ts
@twangodev twangodev merged commit c62da5e into main Jan 6, 2026
5 checks passed
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