From 6862ad4f6c3c1acf12400c63490ae24bbe91a951 Mon Sep 17 00:00:00 2001 From: whyour Date: Sat, 24 Oct 2026 17:40:47 +0800 Subject: [PATCH] build: use sqlite3 1.1.3 ARM musl prebuilds (#3105) --- .github/workflows/release-readiness.yml | 13 +++++++++++-- docker/Dockerfile | 11 +++++++++-- docker/Dockerfile.310 | 11 +++++++++-- docker/Dockerfile.upgrade-bundle | 12 ------------ package.json | 4 ++-- pnpm-lock.yaml | 20 ++++++++++---------- 6 files changed, 41 insertions(+), 30 deletions(-) diff --git a/.github/workflows/release-readiness.yml b/.github/workflows/release-readiness.yml index 1a282830..facabafd 100644 --- a/.github/workflows/release-readiness.yml +++ b/.github/workflows/release-readiness.yml @@ -133,7 +133,7 @@ jobs: docker run --rm --network none --entrypoint node \ qinglong-readiness:${{ matrix.image }} \ -e 'const assert=require("node:assert/strict"); const {createRequire}=require("node:module"); for(const [name,want] of Object.entries({"@grpc/grpc-js":"1.14.5",compression:"1.8.2",multer:"2.4.0",sequelize:"6.37.8"}))assert.equal(require(name+"/package.json").version,want); const expressRequire=createRequire(require.resolve("express")); assert.equal(expressRequire("proxy-addr/package.json").version,"2.0.8"); const sockRequire=createRequire(require.resolve("sockjs")); assert.equal(sockRequire("websocket-driver/package.json").version,"0.7.5"); require("sqlite3"); require("nodemailer"); require("undici"); console.log("Minimal production patches and runtime imports verified")' - - name: Export ARMv6 image layers for Node regression checks + - name: Load ARMv6 image for SQLite and Node regression checks if: startsWith(matrix.image, 'alpine') uses: docker/build-push-action@v7 with: @@ -144,14 +144,23 @@ jobs: QL_URL=${{ steps.source.outputs.url }} QL_BRANCH=${{ steps.source.outputs.branch }} SOURCE_COMMIT=${{ steps.source.outputs.sha }} - outputs: type=docker,dest=${{ runner.temp }}/node-layers-arm.tar + tags: qinglong-readiness:${{ matrix.image }}-armv6 + load: true push: false provenance: false sbom: false + - name: Verify ARMv6 SQLite on an ARM1176 CPU without networking + if: startsWith(matrix.image, 'alpine') + run: | + docker run --rm --network none --platform linux/arm/v6 \ + -e QEMU_CPU=arm1176 --entrypoint node \ + qinglong-readiness:${{ matrix.image }}-armv6 --jitless \ + -e 'const assert=require("node:assert/strict"); const sqlite3=require("sqlite3"); const db=new sqlite3.Database(":memory:"); db.get("SELECT 42 AS n",(error,row)=>{assert.ifError(error); assert.equal(row.n,42); db.close()});' - name: Check Node binaries in every serialized image layer if: startsWith(matrix.image, 'alpine') run: | docker save qinglong-readiness:${{ matrix.image }} -o "$RUNNER_TEMP/node-layers-amd64.tar" + docker save qinglong-readiness:${{ matrix.image }}-armv6 -o "$RUNNER_TEMP/node-layers-arm.tar" python3 scripts/verify-image-node-layers.py "$RUNNER_TEMP/node-layers-amd64.tar" amd64 python3 scripts/verify-image-node-layers.py "$RUNNER_TEMP/node-layers-arm.tar" arm rm "$RUNNER_TEMP/node-layers-amd64.tar" "$RUNNER_TEMP/node-layers-arm.tar" diff --git a/docker/Dockerfile b/docker/Dockerfile index b95baf6e..8d2a1c37 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -3,6 +3,7 @@ FROM --platform=$BUILDPLATFORM node:18-alpine3.18 AS builder ARG TARGETARCH +ARG TARGETVARIANT ENV NPM_CONFIG_PREFIX=/opt/node-global ENV PATH=/opt/node-global/bin:${PATH} @@ -17,10 +18,16 @@ RUN set -x \ ppc64le) NODE_ARCH=ppc64 ;; \ *) NODE_ARCH="${TARGETARCH}" ;; \ esac \ + && case "${TARGETARCH}/${TARGETVARIANT:-}" in \ + arm/v6) NODE_LIBC=musl-armv6 ;; \ + arm/v7) NODE_LIBC=musl-armv7 ;; \ + arm/*) echo "Unsupported ARM variant: ${TARGETVARIANT:-unknown}" >&2; exit 1 ;; \ + *) NODE_LIBC=musl ;; \ + esac \ && npm_config_target_platform=linux \ npm_config_target_arch="${NODE_ARCH}" \ - npm_config_target_libc=musl \ - pnpm install --prod --frozen-lockfile + npm_config_target_libc="${NODE_LIBC}" \ + pnpm install --prod --frozen-lockfile --side-effects-cache=false # Pin amd64 to upstream's musl runtime after native URL parser crashes with APK Node. FROM --platform=linux/amd64 node:24.18.1-alpine3.24@sha256:f70403e87646dc51b45295f4b8b70cdad0b63d2297c4c9899119b03f7af7a6b3 AS node-runtime-amd64 diff --git a/docker/Dockerfile.310 b/docker/Dockerfile.310 index eea74383..22000149 100644 --- a/docker/Dockerfile.310 +++ b/docker/Dockerfile.310 @@ -3,6 +3,7 @@ FROM --platform=$BUILDPLATFORM node:18-alpine3.18 AS builder ARG TARGETARCH +ARG TARGETVARIANT ENV NPM_CONFIG_PREFIX=/opt/node-global ENV PATH=/opt/node-global/bin:${PATH} @@ -17,10 +18,16 @@ RUN set -x \ ppc64le) NODE_ARCH=ppc64 ;; \ *) NODE_ARCH="${TARGETARCH}" ;; \ esac \ + && case "${TARGETARCH}/${TARGETVARIANT:-}" in \ + arm/v6) NODE_LIBC=musl-armv6 ;; \ + arm/v7) NODE_LIBC=musl-armv7 ;; \ + arm/*) echo "Unsupported ARM variant: ${TARGETVARIANT:-unknown}" >&2; exit 1 ;; \ + *) NODE_LIBC=musl ;; \ + esac \ && npm_config_target_platform=linux \ npm_config_target_arch="${NODE_ARCH}" \ - npm_config_target_libc=musl \ - pnpm install --prod --frozen-lockfile + npm_config_target_libc="${NODE_LIBC}" \ + pnpm install --prod --frozen-lockfile --side-effects-cache=false # Pin amd64 to upstream's musl runtime after native URL parser crashes with APK Node. FROM --platform=linux/amd64 node:24.18.1-alpine3.24@sha256:f70403e87646dc51b45295f4b8b70cdad0b63d2297c4c9899119b03f7af7a6b3 AS node-runtime-amd64 diff --git a/docker/Dockerfile.upgrade-bundle b/docker/Dockerfile.upgrade-bundle index 1e4b074b..0a24920f 100644 --- a/docker/Dockerfile.upgrade-bundle +++ b/docker/Dockerfile.upgrade-bundle @@ -6,18 +6,6 @@ ENV QL_BUNDLE_BASE_IMAGE=${BASE_IMAGE} ARG TARGETARCH ARG TARGETVARIANT USER root -# The generic "arm" sqlite release is ARMv7. ARMv6 must compile its own addon. -RUN ulimit -c 0; if [ "$TARGETARCH/$TARGETVARIANT" = arm/v6 ]; then \ - apk add --no-cache --virtual .ql-bundle-build build-base binutils python3 nodejs-dev && \ - cd "$(readlink -f /ql/node_modules/sqlite3)" && \ - CFLAGS='-march=armv6 -mfpu=vfp -mfloat-abi=hard' \ - CXXFLAGS='-march=armv6 -mfpu=vfp -mfloat-abi=hard' \ - npm_config_nodedir=/usr npm_config_build_from_source=true QEMU_CPU=arm1176 \ - node -e 'require("node:child_process").execFileSync(process.execPath,[require.resolve("@mapbox/node-pre-gyp/bin/node-pre-gyp"),"rebuild","--napi_build_version=6"],{stdio:"inherit"})' && \ - readelf -A lib/binding/napi-v6-linux-arm/node_sqlite3.node | grep -E 'Tag_CPU_arch: v6($|K)' && \ - rm -rf build && \ - apk del .ql-bundle-build; \ - fi RUN ulimit -c 0; if [ "$TARGETARCH/$TARGETVARIANT" = arm/v6 ]; then \ export QEMU_CPU=arm1176; \ node --jitless /ql/scripts/build-upgrade-bundle.cjs /ql /out && \ diff --git a/package.json b/package.json index 8f25287a..9c041707 100644 --- a/package.json +++ b/package.json @@ -111,7 +111,7 @@ } }, "overrides": { - "sqlite3": "npm:@whyour/sqlite3@1.1.2", + "sqlite3": "npm:@whyour/sqlite3@1.1.3", "@codemirror/state": "6.5.4", "@codemirror/view": "6.39.16", "proxy-addr": "2.0.8", @@ -159,7 +159,7 @@ "request-ip": "3.3.0", "sequelize": "6.37.8", "sockjs": "^0.3.24", - "sqlite3": "npm:@whyour/sqlite3@1.1.2", + "sqlite3": "npm:@whyour/sqlite3@1.1.3", "toad-scheduler": "^3.0.1", "typedi": "^0.10.0", "undici": "^7.9.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 38aac98d..c055d1ca 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,7 +1,7 @@ lockfileVersion: '6.0' overrides: - sqlite3: npm:@whyour/sqlite3@1.1.2 + sqlite3: npm:@whyour/sqlite3@1.1.3 '@codemirror/state': 6.5.4 '@codemirror/view': 6.39.16 proxy-addr: 2.0.8 @@ -120,13 +120,13 @@ dependencies: version: 3.3.0 sequelize: specifier: 6.37.8 - version: 6.37.8(@whyour/sqlite3@1.1.2) + version: 6.37.8(@whyour/sqlite3@1.1.3) sockjs: specifier: ^0.3.24 version: 0.3.24 sqlite3: - specifier: npm:@whyour/sqlite3@1.1.2 - version: /@whyour/sqlite3@1.1.2 + specifier: npm:@whyour/sqlite3@1.1.3 + version: /@whyour/sqlite3@1.1.3 tar: specifier: 7.5.20 version: 7.5.20 @@ -3193,7 +3193,7 @@ packages: resolution: {integrity: sha512-Ngs9jhElXN7efS9WvvCC/p6rXMbihna8eNLVBc421Zf+VcFd+pR4DOcS6yA9V22EKtAy4DEj7LtvEEIm0bb80A==} engines: {node: '>= 18'} dependencies: - sqlite3: /@whyour/sqlite3@1.1.2 + sqlite3: /@whyour/sqlite3@1.1.3 transitivePeerDependencies: - encoding - supports-color @@ -5611,14 +5611,15 @@ packages: - supports-color dev: true - /@whyour/sqlite3@1.1.2: - resolution: {integrity: sha512-OY24/OJMqLHIGolo4GCFW4lrJKAoOB+ZqERXb7u7DKZQz7QR3f0GALE99BZWQBSZEVVZ/StVeAb2fCkMfTtuDQ==} + /@whyour/sqlite3@1.1.3: + resolution: {integrity: sha512-VeiureU2gq11OMeSMWlpckNfbY5QF+V0KEpRi1Zqh/s5GEPgCazt06xIg528tPAwK0MS9KCUEyLb+dKDIIFoEg==} requiresBuild: true peerDependenciesMeta: node-gyp: optional: true dependencies: '@mapbox/node-pre-gyp': 1.0.11 + detect-libc: 1.0.3 node-addon-api: 4.3.0 tar: 6.2.1 optionalDependencies: @@ -7601,7 +7602,6 @@ packages: resolution: {integrity: sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==} engines: {node: '>=0.10'} hasBin: true - dev: true /detect-libc@2.1.2: resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} @@ -13903,7 +13903,7 @@ packages: engines: {node: '>= 10.0.0'} dev: false - /sequelize@6.37.8(@whyour/sqlite3@1.1.2): + /sequelize@6.37.8(@whyour/sqlite3@1.1.3): resolution: {integrity: sha512-HJ0IQFqcTsTiqbEgiuioYFMSD00TP6Cz7zoTti+zVVBwVe9fEhev9cH6WnM3XU31+ABS356durAb99ZuOthnKw==} engines: {node: '>=10.0.0'} peerDependencies: @@ -13948,7 +13948,7 @@ packages: retry-as-promised: 7.0.4 semver: 7.7.4 sequelize-pool: 7.1.0 - sqlite3: /@whyour/sqlite3@1.1.2 + sqlite3: /@whyour/sqlite3@1.1.3 toposort-class: 1.0.1 uuid: 8.3.2 validator: 13.12.0