From 4ca5644612590fd5ac6fdc4634ced9e582c3ef2b Mon Sep 17 00:00:00 2001 From: Jeff Lubetkin Date: Mon, 29 Jun 2026 16:35:36 -0700 Subject: [PATCH] native: detect libc via process.report, not `ldd` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit isMusl() shelled out to `ldd --version` and treated any failure as musl. Minimal images (distroless/scratch) ship no `ldd`, so the call throws and a glibc host is misdetected as musl — selecting a platform package/prebuild that doesn't exist and failing at load with "Native addon not found for linux-x64-musl". Use Node's process.report.header.glibcVersionRuntime (set on glibc, absent on musl), with a /lib/ld-musl-* fallback and a glibc default. Verified: distroless debian13 now resolves linux-x64; node:alpine still resolves musl. Bump to 0.1.1. Co-Authored-By: Claude Opus 4.8 (1M context) --- native/package.json | 12 ++++++------ native/src/index.ts | 24 +++++++++++++++++++----- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/native/package.json b/native/package.json index a580124..ed96e82 100644 --- a/native/package.json +++ b/native/package.json @@ -1,6 +1,6 @@ { "name": "@ashbyhq/libpg-query-native", - "version": "0.1.0", + "version": "0.1.1", "description": "PostgreSQL query parser — native N-API + jemalloc backend", "main": "./dist/index.js", "types": "./dist/index.d.ts", @@ -48,10 +48,10 @@ "typescript": "5.9.3" }, "optionalDependencies": { - "@ashbyhq/libpg-query-native-darwin-arm64": "0.1.0", - "@ashbyhq/libpg-query-native-linux-x64": "0.1.0", - "@ashbyhq/libpg-query-native-linux-arm64": "0.1.0", - "@ashbyhq/libpg-query-native-linux-x64-musl": "0.1.0", - "@ashbyhq/libpg-query-native-linux-arm64-musl": "0.1.0" + "@ashbyhq/libpg-query-native-darwin-arm64": "0.1.1", + "@ashbyhq/libpg-query-native-linux-x64": "0.1.1", + "@ashbyhq/libpg-query-native-linux-arm64": "0.1.1", + "@ashbyhq/libpg-query-native-linux-x64-musl": "0.1.1", + "@ashbyhq/libpg-query-native-linux-arm64-musl": "0.1.1" } } diff --git a/native/src/index.ts b/native/src/index.ts index 43bbf7f..f7994a7 100644 --- a/native/src/index.ts +++ b/native/src/index.ts @@ -83,13 +83,27 @@ function loadNativeAddon(): NativeAddon { function isMusl(): boolean { if (process.platform !== "linux") return false; + // Prefer Node's own libc marker: `glibcVersionRuntime` is set on glibc and + // absent on musl. This is reliable in minimal images (distroless/scratch) + // that ship no `ldd` binary — shelling out there throws and would otherwise + // be misread as musl, selecting the wrong platform package. try { - const { execSync } = require("child_process"); - const ldd = execSync("ldd --version 2>&1", { encoding: "utf8" }); - return ldd.includes("musl"); + const report = process.report?.getReport?.() as + | { header?: { glibcVersionRuntime?: string } } + | undefined; + if (report?.header != null) { + return report.header.glibcVersionRuntime == null; + } } catch { - // ldd --version exits non-zero on musl - return true; + // fall through to the filesystem probe + } + // Fallback (older runtimes without process.report): look for the musl + // dynamic loader on disk. Default to glibc — the common case — when unsure. + try { + const fs = require("fs"); + return fs.readdirSync("/lib").some((f: string) => f.startsWith("ld-musl-")); + } catch { + return false; } }