fix: ship correct better-sqlite3 native module for arm64 Linux builds#1522
Draft
the-narwhal wants to merge 6 commits into
Draft
fix: ship correct better-sqlite3 native module for arm64 Linux builds#1522the-narwhal wants to merge 6 commits into
the-narwhal wants to merge 6 commits into
Conversation
The linux publish job ran entirely on ubuntu-latest (x86_64). Because `postinstall` runs `electron-rebuild`, better-sqlite3.node was compiled for the host (x64) before electron-builder ever ran. With `asarUnpack: '**/*.node'` copying the .node file verbatim, every arm64 .deb and .rpm package shipped an x86_64 native module and would crash on real arm64 hardware. Fix by splitting the single build-linux job into two jobs — one on ubuntu-latest for x64 targets and one on ubuntu-24.04-arm for arm64 targets. Each job installs dependencies natively, so electron-rebuild produces the correct .node binary for that architecture automatically. Also add arm64 to the AppImage target arch list, which was missing despite deb and rpm already including it.
… build Add a verification step to both build-linux-x64 and build-linux-arm64 in publish.yml that inspects the ELF header of the unpacked .node file before tarring or uploading artifacts. The job fails hard with the actual arch string in the log if there is a mismatch, so a regression can never produce a silently broken release. Also add a temporary test-build-linux.yml (workflow_dispatch) to produce downloadable artifacts for manual testing without a real release. Remove before merging.
… per job The --arm64/--x64 CLI flags are not reliably filtered in electron-builder's programmatic API. When both arches are listed in the config, electron-builder builds all of them regardless of the flag, downloading the x64 better-sqlite3 prebuilt first which then contaminates the arm64 package with the wrong binary. Drive the target arch entirely through TARGET_ARCH in electron-builder-config.mjs so each CI job only ever builds for its own architecture, preventing cross-arch native module contamination entirely.
the-narwhal
marked this pull request as ready for review
April 14, 2026 03:48
the-narwhal
marked this pull request as draft
April 14, 2026 04:14
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #1513 and potentially fixes #1413
Bug: arm64 Linux packages contained an x86_64
better-sqlite3native moduleRoot cause
The
build-linuxpublish job ran onubuntu-latest(x86_64). Thepostinstallhook (electron-rebuild) compiledbetter-sqlite3.nodefor the host machine before electron-builder ran. BecauseasarUnpack: '**/*.node'copies.nodefiles verbatim into every output package, all arm64.deband.rpmartifacts ended up with an x86_64 native module inside — causing them to crash or fail to load on actual arm64 hardware.A second smaller issue:
AppImagewas the only Linux target missingarm64from its arch list, despitedebandrpmalready including it.What was discovered during testing
Two additional issues surfaced while validating the fix on a real arm64 Fedora machine:
electron-builder's
--arm64/--x64CLI flags do not filter targets in the programmatic API. When both arches are listed in the config, electron-builder builds all of them regardless of the flag. It downloads the x64better-sqlite3prebuilt first, which then contaminates the arm64 package — both packages end up with the same x86-64 binary. The fix is to drive the target arch through the config directly via aTARGET_ARCHenv var.electron-builder bundles an x86-only
fpmbinary.fpmis used to produce.deband.rpmpackages. On an arm64 runner, the bundledfpm-1.9.3-linux-x86binary fails withExec format error. The fix is to installfpmas a Ruby gem on the arm64 runner and setUSE_SYSTEM_FPM=true.Changes
electron-builder-config.mjsarm64to theAppImagetarget arch list so it is consistent withdebandrpm.TARGET_ARCHenv var support — when set, only that architecture is built. This is what ensures each CI job only ever packages its own arch, preventing cross-arch native module contamination..github/workflows/publish.ymlbuild-linux→build-linux-x64, running onubuntu-latestwithTARGET_ARCH: x64.build-linux-arm64job running onubuntu-24.04-armwithTARGET_ARCH: arm64,USE_SYSTEM_FPM: 'true', and a step to installfpmvia Ruby gem before building..nodefile and hard-fails the job — before tarring or uploading — if the binary doesn't match the expected architecture. A regression can no longer produce a silently broken release.Because
yarn install(and thereforeelectron-rebuild) runs natively on each runner,better-sqlite3.nodeis compiled for the correct architecture automatically — no cross-compilation toolchain or Docker required.Before / After
linux-x64.deb/.rpm/.AppImagelinux-arm64.deb/.rpm.node.node— verified on Fedora aarch64linux-arm64.AppImage.node