From 4d84a0a8984b1985feaef15531e9e9c1c6922d5d Mon Sep 17 00:00:00 2001 From: Bruno Verachten Date: Wed, 15 Apr 2026 15:27:28 +0200 Subject: [PATCH 1/5] ci: add riscv64 to static Node.js build matrix Uses ubuntu-24.04-riscv runner and manylinux_2_39_riscv64 for testing (manylinux2014 has no riscv64 image). Dockerfile-test updated to take a full MANYLINUX_IMAGE arg instead of constructing from MANYLINUX_ARCH. Signed-off-by: Bruno Verachten --- .github/workflows/build-static-node.yml | 11 ++++++----- staticnode/Dockerfile-test | 4 ++-- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build-static-node.yml b/.github/workflows/build-static-node.yml index 8a03ee5c..2b5540da 100644 --- a/.github/workflows/build-static-node.yml +++ b/.github/workflows/build-static-node.yml @@ -36,9 +36,10 @@ jobs: fail-fast: false matrix: IMAGE: - - {RUNNER: "ubuntu-latest", MANYLINUX_ARCH: "x86_64"} - - {RUNNER: "ubuntu-24.04-arm", MANYLINUX_ARCH: "aarch64"} - - {RUNNER: "ubuntu-24.04-ppc64le", MANYLINUX_ARCH: "ppc64le"} + - {RUNNER: "ubuntu-latest", MANYLINUX_IMAGE: "quay.io/pypa/manylinux2014_x86_64"} + - {RUNNER: "ubuntu-24.04-arm", MANYLINUX_IMAGE: "quay.io/pypa/manylinux2014_aarch64"} + - {RUNNER: "ubuntu-24.04-ppc64le", MANYLINUX_IMAGE: "quay.io/pypa/manylinux2014_ppc64le"} + - {RUNNER: "ubuntu-24.04-riscv", MANYLINUX_IMAGE: "quay.io/pypa/manylinux_2_39_riscv64"} NODE_CONFIG: ${{ fromJson(needs.load-node-versions.outputs.versions) }} steps: - uses: actions/checkout@v6.0.1 @@ -54,10 +55,10 @@ jobs: run: | echo building node.js $NODE_VERSION docker build --tag ghcr.io/pyca/static-nodejs-$NODE_ARCH:$NODE_VERSION --build-arg VERSION=$NODE_VERSION --build-arg ARCH=$NODE_ARCH --build-arg SHA256SUM=$NODE_SHA256SUM staticnode - - name: Test static node.js on manylinux2014 + - name: Test static node.js run: | cd staticnode - docker build -f Dockerfile-test -t test-node --build-arg MANYLINUX_ARCH=${{ matrix.IMAGE.MANYLINUX_ARCH }} --build-arg CONTAINER_NAME=ghcr.io/pyca/static-nodejs-$NODE_ARCH:$NODE_VERSION . + docker build -f Dockerfile-test -t test-node --build-arg MANYLINUX_IMAGE=${{ matrix.IMAGE.MANYLINUX_IMAGE }} --build-arg CONTAINER_NAME=ghcr.io/pyca/static-nodejs-$NODE_ARCH:$NODE_VERSION . docker run test-node /staticnode/bin/node -e "console.log('hello world'); console.log(process.version)" - name: Login to docker run: 'docker login -u "$DOCKER_USERNAME" -p "$DOCKER_PASSWORD" ghcr.io' diff --git a/staticnode/Dockerfile-test b/staticnode/Dockerfile-test index 34390818..6f8b8335 100644 --- a/staticnode/Dockerfile-test +++ b/staticnode/Dockerfile-test @@ -1,6 +1,6 @@ -ARG MANYLINUX_ARCH +ARG MANYLINUX_IMAGE ARG CONTAINER_NAME FROM ${CONTAINER_NAME} AS staticnodejs -FROM quay.io/pypa/manylinux2014_${MANYLINUX_ARCH} +FROM ${MANYLINUX_IMAGE} COPY --from=staticnodejs /out /staticnode/ From d501c4ae398d87b814d38260741583dd1c7adf13 Mon Sep 17 00:00:00 2001 From: Bruno Verachten Date: Wed, 15 Apr 2026 15:29:44 +0200 Subject: [PATCH 2/5] fix: use binutils instead of binutils-gold on riscv64 binutils-gold is not available as a separate Alpine package on riscv64. Standard binutils (ld.bfd) is sufficient for the static Node.js build. Signed-off-by: Bruno Verachten --- staticnode/Dockerfile | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/staticnode/Dockerfile b/staticnode/Dockerfile index 5a6edff8..3469be34 100644 --- a/staticnode/Dockerfile +++ b/staticnode/Dockerfile @@ -1,6 +1,6 @@ FROM alpine:latest ARG VERSION -# One of x64 or arm64 or ppc64le +# One of x64 or arm64 or ppc64le or riscv64 ARG ARCH # The sha256sum for the node source tarball ARG SHA256SUM @@ -8,7 +8,11 @@ ARG SHA256SUM RUN mkdir -p /build WORKDIR /build -RUN apk add --no-cache binutils-gold curl g++ gcc gnupg libgcc linux-headers make ninja python3 libstdc++ patch +RUN if [ "$ARCH" = "riscv64" ]; then \ + apk add --no-cache binutils curl g++ gcc gnupg libgcc linux-headers make ninja python3 libstdc++ patch; \ + else \ + apk add --no-cache binutils-gold curl g++ gcc gnupg libgcc linux-headers make ninja python3 libstdc++ patch; \ + fi RUN mkdir -p /out/bin RUN curl -O https://nodejs.org/dist/$VERSION/node-$VERSION.tar.gz From 3d5a0ee54e2c1fe6a580ca8aeb3f25895ca57d17 Mon Sep 17 00:00:00 2001 From: Bruno Verachten Date: Wed, 15 Apr 2026 15:53:13 +0200 Subject: [PATCH 3/5] fix: pass --openssl-no-asm for riscv64 static Node.js build Node.js bundled OpenSSL hardcodes linux-x86_64 config paths and passes -m64 even when --dest-cpu=riscv64 is set. --openssl-no-asm skips arch-specific OpenSSL assembly and uses the generic config. Signed-off-by: Bruno Verachten --- staticnode/Dockerfile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/staticnode/Dockerfile b/staticnode/Dockerfile index 3469be34..8f3066ef 100644 --- a/staticnode/Dockerfile +++ b/staticnode/Dockerfile @@ -32,7 +32,9 @@ RUN cd node-$VERSION && \ ppc64le) CPU=ppc64 ;; \ *) CPU="$ARCH" ;; \ esac && \ - ./configure --dest-cpu=$CPU --fully-static --ninja --without-inspector --with-intl=none --without-npm --without-corepack && \ + EXTRA_FLAGS="" && \ + if [ "$ARCH" = "riscv64" ]; then EXTRA_FLAGS="--openssl-no-asm"; fi && \ + ./configure --dest-cpu=$CPU --fully-static --ninja --without-inspector --with-intl=none --without-npm --without-corepack $EXTRA_FLAGS && \ ninja -j$(nproc) -C out/Release node RUN cp /build/node-$VERSION/LICENSE /out/LICENSE && cp /build/node-$VERSION/out/Release/node /out/bin/node From c47d3ff4ecdbeb6ef0a9f993564ce0e3afc7b65f Mon Sep 17 00:00:00 2001 From: Bruno Verachten Date: Thu, 16 Apr 2026 08:56:02 +0200 Subject: [PATCH 4/5] fix: pin base image to alpine:3.21 to avoid GCC 15 build failures alpine:latest now resolves to GCC 15.2.0 which causes two separate failures when building Node.js v24.5.0: - riscv64: GCC 15 internal compiler error (segfault) in V8's thread-id.cc after ~5 hours of build time - ppc64le: GCC 15 treats highway's ppc_vsx-inl.h template-body diagnostics as errors, failing at ~9 minutes Pin to alpine:3.21 (GCC 14.2.0) to restore stable builds across all architectures. Signed-off-by: Bruno Verachten --- staticnode/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/staticnode/Dockerfile b/staticnode/Dockerfile index 8f3066ef..874bde4b 100644 --- a/staticnode/Dockerfile +++ b/staticnode/Dockerfile @@ -1,4 +1,4 @@ -FROM alpine:latest +FROM alpine:3.21 ARG VERSION # One of x64 or arm64 or ppc64le or riscv64 ARG ARCH From 5421f4e04ee4c250adac7e4b2fe055eb38da1725 Mon Sep 17 00:00:00 2001 From: Bruno Verachten Date: Thu, 16 Apr 2026 16:09:13 +0200 Subject: [PATCH 5/5] ci: increase job timeout to 8h for riscv64 build Node.js v24.5.0 on riscv64 takes more than 6 hours to compile V8, hitting the default GitHub Actions timeout. Set timeout-minutes to 480 (8h) to let the build complete. Signed-off-by: Bruno Verachten --- .github/workflows/build-static-node.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build-static-node.yml b/.github/workflows/build-static-node.yml index 2b5540da..0fab6e5e 100644 --- a/.github/workflows/build-static-node.yml +++ b/.github/workflows/build-static-node.yml @@ -29,6 +29,7 @@ jobs: build: runs-on: ${{ matrix.IMAGE.RUNNER }} needs: load-node-versions + timeout-minutes: 480 permissions: contents: read packages: write