Skip to content

Commit 6c6ea45

Browse files
authored
refactor: replace Bun.build with fossilize for Node SEA binaries (#1003)
## Phase 6: Replace Bun Binary Compilation with Fossilize Final phase of the Bun → Node.js migration. Replaces `Bun.build({ compile: true })` with [fossilize](https://github.com/BYK/fossilize) for producing Node SEA (Single Executable Application) binaries. This completely removes Bun from the codebase. ### Architecture Change ``` BEFORE: src/bin.ts → [esbuild ESM] → dist-bin/bin.js → [Bun.build compile] → binary AFTER: src/bin.ts → [esbuild CJS] → dist-build/bin.js → [fossilize --no-bundle] → binary ``` ### Changes **Build script (`script/build.ts`):** - Replaced `Bun.build({ compile: true })` with `npx fossilize --no-bundle` - Switched esbuild format from ESM to CJS (Node SEA requirement) - Added `import-meta-url.js` inject + define for CJS compatibility - Target `node22` (downlevels `using` declarations unsupported in CJS) - Removed sourcemap backup/restore dance (fossilize doesn't generate its own map) - Separated build output (`dist-build/`) from fossilize output (`dist-bin/`) - Replaced all `Bun.$`, `Bun.file`, `Bun.write` with Node.js equivalents - Dropped musl targets (Node doesn't publish musl/Alpine binaries) **Ink sidecar (`src/lib/init/ui/ink-ui.ts`):** - Added `node:sea.getAsset()` runtime path for SEA binaries - Sidecar embedded via fossilize `--assets` flag - Extracts to temp file and `import()`s at runtime - Dev and npm bundle paths unchanged **SQLite (`src/lib/db/sqlite.ts`):** - Removed `bun:sqlite` try/catch fallback — Node-only now **Binary entry (`src/bin.ts`):** - Suppresses `ExperimentalWarning: SQLite is an experimental feature` **CI (`.github/workflows/ci.yml`):** - Removed `setup-bun` entirely (no more Bun in CI) - Added `rcodesign` v0.29.0 installation for macOS code signing from Linux - Added Apple cert/key environment setup (matches Spotlight's approach) - `FOSSILIZE_SIGN` env var controls signing (enabled on main/release pushes) - Dropped musl targets from build matrix (7 → 5 targets) **Other cleanup:** - Removed `Bun` from `biome.jsonc` globals - Updated `package.json` build scripts: `bun run` → `pnpm tsx` - Added `dist-build/` to `.gitignore` and biome excludes - `text-import-plugin`: file imports return path string for all formats (no more ESM external for Bun.compile) ### Benchmark Results | Mode | Avg Startup | Notes | |------|------------|-------| | Baseline (no cache) | ~870ms | Current approach | | useCodeCache | ~740ms | ~15% faster (same-platform only) | | useSnapshot | N/A | Crashes — too many unsupported modules | Code cache improvement deferred — requires fossilize PR to support per-platform `useCodeCache`. ### What's Gone - `setup-bun` from CI - `bun:sqlite` fallback - `Bun.build()` / `Bun.$` / `Bun.file` / `Bun.write` in build script - `Bun` global declaration - musl binary targets ### Testing - Local build succeeds on Linux x64 (Node SEA via fossilize) - Binary runs `--help` and `--version` correctly - No SQLite warning in output - binpunch ICU hole-punching works on Node SEA binaries
1 parent c064547 commit 6c6ea45

17 files changed

Lines changed: 577 additions & 376 deletions

File tree

.github/workflows/ci.yml

Lines changed: 36 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -75,21 +75,19 @@ jobs:
7575
{
7676
echo 'matrix<<MATRIX_EOF'
7777
if [[ "${{ github.event_name }}" == "pull_request" ]]; then
78-
# PRs build linux-x64 (smoke test + e2e) and linux-x64-musl (Alpine smoke test)
78+
# PRs build linux-x64 (smoke test + e2e)
7979
echo '{"include":[
80-
{"target":"linux-x64", "os":"ubuntu-latest", "can-test":true},
81-
{"target":"linux-x64-musl", "os":"ubuntu-latest", "can-test":false}
80+
{"target":"linux-x64", "os":"ubuntu-latest", "can-test":true}
8281
]}'
8382
else
84-
# main, release/**, workflow_call: full cross-platform matrix
83+
# main, release/**, workflow_call: full cross-platform matrix.
84+
# All targets cross-compiled from ubuntu-latest via fossilize.
8585
echo '{"include":[
86-
{"target":"darwin-arm64", "os":"macos-latest", "can-test":true},
87-
{"target":"linux-x64", "os":"ubuntu-latest", "can-test":true},
88-
{"target":"linux-x64-musl", "os":"ubuntu-latest", "can-test":false},
89-
{"target":"windows-x64", "os":"windows-latest","can-test":true},
90-
{"target":"darwin-x64", "os":"macos-latest", "can-test":false},
91-
{"target":"linux-arm64", "os":"ubuntu-latest", "can-test":false},
92-
{"target":"linux-arm64-musl", "os":"ubuntu-latest", "can-test":false}
86+
{"target":"darwin-arm64", "os":"ubuntu-latest", "can-test":false},
87+
{"target":"linux-x64", "os":"ubuntu-latest", "can-test":true},
88+
{"target":"windows-x64", "os":"ubuntu-latest", "can-test":false},
89+
{"target":"darwin-x64", "os":"ubuntu-latest", "can-test":false},
90+
{"target":"linux-arm64", "os":"ubuntu-latest", "can-test":false}
9391
]}'
9492
fi
9593
echo 'MATRIX_EOF'
@@ -246,9 +244,6 @@ jobs:
246244
matrix: ${{ fromJSON(needs.changes.outputs.build-targets) }}
247245
steps:
248246
- uses: actions/checkout@v6
249-
- uses: oven-sh/setup-bun@v2
250-
with:
251-
bun-version: "1.3.13"
252247
- uses: pnpm/action-setup@v4
253248
- uses: actions/setup-node@v6
254249
with:
@@ -262,6 +257,28 @@ jobs:
262257
if: steps.cache.outputs.cache-hit != 'true'
263258
shell: bash
264259
run: pnpm install --frozen-lockfile
260+
- name: Setup codesign dependencies
261+
env:
262+
APPLE_CERT_DATA: ${{ secrets.CSC_LINK }}
263+
APPLE_API_KEY: ${{ secrets.APPLE_API_KEY }}
264+
run: |
265+
curl -L 'https://github.com/indygreg/apple-platform-rs/releases/download/apple-codesign%2F0.29.0/apple-codesign-0.29.0-x86_64-unknown-linux-musl.tar.gz' -o 'rcodesign.tar.gz'
266+
echo 'dbe85cedd8ee4217b64e9a0e4c2aef92ab8bcaaa41f20bde99781ff02e600002 rcodesign.tar.gz' | sha256sum -c
267+
tar -xzf rcodesign.tar.gz --strip-components=1
268+
mv rcodesign /usr/local/bin/rcodesign
269+
rm rcodesign.tar.gz
270+
if [ -n "$APPLE_CERT_DATA" ]; then
271+
echo "$APPLE_CERT_DATA" | base64 --decode > /tmp/certs.p12
272+
echo 'APPLE_CERT_PATH=/tmp/certs.p12' >> $GITHUB_ENV
273+
fi
274+
if [ -n "$APPLE_API_KEY" ]; then
275+
echo "$APPLE_API_KEY" | base64 -d > /tmp/apple_key.json
276+
cat /tmp/apple_key.json | jq .private_key -r > /tmp/apple_key.pem
277+
echo "APPLE_API_KEY_ISSUER_ID=$(cat /tmp/apple_key.json | jq .issuer_id -r | tr -d '\n\r')" >> $GITHUB_ENV
278+
echo "APPLE_API_KEY_ID=$(cat /tmp/apple_key.json | jq .key_id -r | tr -d '\n\r')" >> $GITHUB_ENV
279+
echo "APPLE_API_KEY_P8_PATH=/tmp/apple_key.pem" >> $GITHUB_ENV
280+
echo 'APPLE_API_KEY_PATH=/tmp/apple_key.json' >> $GITHUB_ENV
281+
fi
265282
- name: Set nightly version
266283
# Inject the nightly version (computed once in the changes job) into
267284
# package.json before the build so it gets baked into the binary.
@@ -278,7 +295,11 @@ jobs:
278295
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
279296
# Set on main/release branches so build.ts runs binpunch + creates .gz
280297
RELEASE_BUILD: ${{ github.event_name != 'pull_request' && '1' || '' }}
281-
run: bun run build --target ${{ matrix.target }}
298+
# Codesigning: only on main/release pushes (fork PRs lack secrets)
299+
FOSSILIZE_SIGN: ${{ github.event_name == 'push' && (github.ref_name == 'main' || startsWith(github.ref_name, 'release/')) && 'y' || 'n' }}
300+
APPLE_CERT_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }}
301+
APPLE_TEAM_ID: ${{ vars.APPLE_TEAM_ID }}
302+
run: pnpm run build -- --target ${{ matrix.target }}
282303
- name: Smoke test
283304
if: matrix.can-test
284305
shell: bash
@@ -288,11 +309,6 @@ jobs:
288309
else
289310
./dist-bin/sentry-${{ matrix.target }} --help
290311
fi
291-
- name: Smoke test (musl/Alpine)
292-
if: matrix.target == 'linux-x64-musl'
293-
run: |
294-
docker run --rm -v "$PWD/dist-bin:/dist-bin:ro" alpine:latest \
295-
sh -c "apk add --no-cache libstdc++ libgcc >/dev/null 2>&1 && /dist-bin/sentry-linux-x64-musl --help"
296312
- name: Upload binary artifact
297313
uses: actions/upload-artifact@v7
298314
with:

.github/workflows/docs-preview.yml

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,6 @@ jobs:
3333
steps:
3434
- uses: actions/checkout@v6
3535

36-
- uses: oven-sh/setup-bun@v2
37-
with:
38-
bun-version: "1.3.13"
3936
- uses: pnpm/action-setup@v4
4037

4138
# Astro 6 requires Node >= 22.12. Pin an explicit version so the docs
@@ -58,7 +55,7 @@ jobs:
5855
run: echo "version=$(node -p 'require("./package.json").version')" >> "$GITHUB_OUTPUT"
5956

6057
- name: Generate docs content
61-
run: bun run generate:schema && bun run generate:docs
58+
run: pnpm run generate:schema && pnpm run generate:docs
6259

6360
- name: Build Docs for Preview
6461
working-directory: docs
@@ -70,8 +67,8 @@ jobs:
7067
SENTRY_RELEASE: ${{ steps.version.outputs.version }}
7168
PUBLIC_SENTRY_RELEASE: ${{ steps.version.outputs.version }}
7269
run: |
73-
bun install --frozen-lockfile
74-
bun run build
70+
pnpm install --frozen-lockfile
71+
pnpm run build
7572
7673
- name: Inject debug IDs and upload sourcemaps
7774
if: env.SENTRY_AUTH_TOKEN != ''
@@ -80,8 +77,8 @@ jobs:
8077
SENTRY_ORG: sentry
8178
SENTRY_PROJECT: cli-website
8279
run: |
83-
bun run --bun src/bin.ts sourcemap inject docs/dist/
84-
bun run --bun src/bin.ts sourcemap upload docs/dist/ \
80+
pnpm run cli sourcemap inject docs/dist/
81+
pnpm run cli sourcemap upload docs/dist/ \
8582
--release "${{ steps.version.outputs.version }}" \
8683
--url-prefix "~/"
8784

.github/workflows/eval-skill-fork.yml

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,6 @@ jobs:
3636
with:
3737
ref: ${{ github.event.pull_request.head.sha }}
3838

39-
- uses: oven-sh/setup-bun@v2
40-
with:
41-
bun-version: "1.3.13"
4239
- uses: pnpm/action-setup@v4
4340

4441
- uses: actions/cache@v5
@@ -50,11 +47,11 @@ jobs:
5047
run: pnpm install --frozen-lockfile
5148

5249
- name: Generate docs and skill files
53-
run: bun run generate:schema && bun run generate:docs
50+
run: pnpm run generate:schema && pnpm run generate:docs
5451

5552
- name: Eval SKILL.md
5653
id: eval
57-
run: bun run eval:skill
54+
run: pnpm run eval:skill
5855
env:
5956
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
6057
continue-on-error: true

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package-lock.json
66
out
77
dist
88
dist-bin
9+
dist-build
910
*.tgz
1011

1112
# fossilize build cache

0 commit comments

Comments
 (0)