Skip to content

Commit 3e25b8d

Browse files
committed
ci: switch riscv64 to cross-compilation from x86_64
Native Node.js compilation on ubuntu-24.04-riscv exceeds 8 hours even with ninja + no-inspector + no-intl. Cross-compiling from x86_64 with gcc-riscv64-linux-gnu produces an equivalent fully-static riscv64 binary in roughly the same time as other native matrix entries (~2h). The build runs on ubuntu-latest, extracts the binary, then repackages it as a linux/riscv64 Docker image via buildx so platform metadata is correct. The test uses QEMU via docker/setup-qemu-action to run the riscv64 binary in CI. Also reduces timeout-minutes from 480 to 120 (native builds finish well under 2h; cross-compile is similarly bounded).
1 parent 1858334 commit 3e25b8d

1 file changed

Lines changed: 76 additions & 17 deletions

File tree

.github/workflows/build-static-node.yml

Lines changed: 76 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@ name: Build Static Node.js Container
33
on:
44
pull_request:
55
paths:
6-
- '.github/workflows/build-static-node.yml'
7-
- 'staticnode/**'
6+
- ".github/workflows/build-static-node.yml"
7+
- "staticnode/**"
88
push:
99
branches:
1010
- main
1111
paths:
12-
- '.github/workflows/build-static-node.yml'
13-
- 'staticnode/**'
12+
- ".github/workflows/build-static-node.yml"
13+
- "staticnode/**"
1414

1515
jobs:
1616
load-node-versions:
@@ -24,43 +24,102 @@ jobs:
2424
- name: Load Node.js versions
2525
id: load-versions
2626
run: |
27-
echo "versions=$(cat staticnode/node-versions.json | jq -c '.')" >> $GITHUB_OUTPUT
27+
echo "versions=$(cat staticnode/node-versions.json | jq -c ".")" >> $GITHUB_OUTPUT
2828
2929
build:
3030
runs-on: ${{ matrix.IMAGE.RUNNER }}
3131
needs: load-node-versions
32-
timeout-minutes: 480
32+
timeout-minutes: 120
3333
permissions:
3434
contents: read
3535
packages: write
3636
strategy:
3737
fail-fast: false
3838
matrix:
3939
IMAGE:
40-
- {RUNNER: "ubuntu-latest", MANYLINUX_IMAGE: "quay.io/pypa/manylinux2014_x86_64"}
41-
- {RUNNER: "ubuntu-24.04-arm", MANYLINUX_IMAGE: "quay.io/pypa/manylinux2014_aarch64"}
42-
- {RUNNER: "ubuntu-24.04-ppc64le", MANYLINUX_IMAGE: "quay.io/pypa/manylinux2014_ppc64le"}
43-
- {RUNNER: "ubuntu-24.04-riscv", MANYLINUX_IMAGE: "quay.io/pypa/manylinux_2_39_riscv64"}
40+
- {RUNNER: "ubuntu-latest", ARCH: "", MANYLINUX_IMAGE: "quay.io/pypa/manylinux2014_x86_64"}
41+
- {RUNNER: "ubuntu-24.04-arm", ARCH: "", MANYLINUX_IMAGE: "quay.io/pypa/manylinux2014_aarch64"}
42+
- {RUNNER: "ubuntu-24.04-ppc64le", ARCH: "", MANYLINUX_IMAGE: "quay.io/pypa/manylinux2014_ppc64le"}
43+
- {RUNNER: "ubuntu-latest", ARCH: "riscv64", MANYLINUX_IMAGE: "quay.io/pypa/manylinux_2_39_riscv64"}
4444
NODE_CONFIG: ${{ fromJson(needs.load-node-versions.outputs.versions) }}
4545
steps:
4646
- uses: actions/checkout@v6.0.1
4747
with:
4848
persist-credentials: false
49+
- name: Set up QEMU for riscv64 test
50+
if: matrix.IMAGE.ARCH == 'riscv64'
51+
uses: docker/setup-qemu-action@v3
52+
with:
53+
platforms: linux/riscv64
54+
- name: Set up Docker Buildx
55+
if: matrix.IMAGE.ARCH == 'riscv64'
56+
uses: docker/setup-buildx-action@v3
4957
- name: Set Node.js version
5058
run: |
5159
echo "NODE_VERSION=${{ matrix.NODE_CONFIG.version }}" >> $GITHUB_ENV
5260
echo "NODE_SHA256SUM=${{ matrix.NODE_CONFIG.sha256sum }}" >> $GITHUB_ENV
53-
arch=$(echo "${{ runner.arch }}" | tr '[:upper:]' '[:lower:]')
54-
echo "NODE_ARCH=$arch" >> $GITHUB_ENV
55-
- name: Build the Docker image
61+
if [ -n "${{ matrix.IMAGE.ARCH }}" ]; then
62+
echo "NODE_ARCH=${{ matrix.IMAGE.ARCH }}" >> $GITHUB_ENV
63+
else
64+
arch=$(echo "${{ runner.arch }}" | tr '[:upper:]' '[:lower:]')
65+
echo "NODE_ARCH=$arch" >> $GITHUB_ENV
66+
fi
67+
- name: Build the Docker image (native)
68+
if: matrix.IMAGE.ARCH != 'riscv64'
69+
run: |
70+
echo building node.js $NODE_VERSION for $NODE_ARCH
71+
docker build --tag ghcr.io/pyca/static-nodejs-$NODE_ARCH:$NODE_VERSION \
72+
--build-arg VERSION=$NODE_VERSION \
73+
--build-arg ARCH=$NODE_ARCH \
74+
--build-arg SHA256SUM=$NODE_SHA256SUM \
75+
staticnode
76+
- name: Cross-compile Node.js for riscv64 on x86_64
77+
if: matrix.IMAGE.ARCH == 'riscv64'
5678
run: |
57-
echo building node.js $NODE_VERSION
58-
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
59-
- name: Test static node.js
79+
echo cross-compiling node.js $NODE_VERSION for riscv64
80+
docker build \
81+
--tag cross-builder-node \
82+
--build-arg VERSION=$NODE_VERSION \
83+
--build-arg SHA256SUM=$NODE_SHA256SUM \
84+
--file staticnode/Dockerfile.riscv64-cross \
85+
staticnode
86+
mkdir -p /tmp/node-riscv64/bin
87+
docker create --name node-cross cross-builder-node
88+
docker cp node-cross:/out/bin/node /tmp/node-riscv64/bin/node
89+
docker cp node-cross:/out/LICENSE /tmp/node-riscv64/LICENSE
90+
docker rm node-cross
91+
printf 'FROM scratch
92+
COPY bin/node /out/bin/node
93+
COPY LICENSE /out/LICENSE
94+
' \
95+
> /tmp/Dockerfile.inject
96+
docker buildx build \
97+
--platform linux/riscv64 \
98+
--tag ghcr.io/pyca/static-nodejs-riscv64:$NODE_VERSION \
99+
--file /tmp/Dockerfile.inject \
100+
--load \
101+
/tmp/node-riscv64
102+
- name: Test static node.js (native)
103+
if: matrix.IMAGE.ARCH != 'riscv64'
60104
run: |
61105
cd staticnode
62-
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 .
106+
docker build -f Dockerfile-test -t test-node \
107+
--build-arg MANYLINUX_IMAGE=${{ matrix.IMAGE.MANYLINUX_IMAGE }} \
108+
--build-arg CONTAINER_NAME=ghcr.io/pyca/static-nodejs-$NODE_ARCH:$NODE_VERSION .
63109
docker run test-node /staticnode/bin/node -e "console.log('hello world'); console.log(process.version)"
110+
- name: Test static node.js (riscv64 via QEMU)
111+
if: matrix.IMAGE.ARCH == 'riscv64'
112+
run: |
113+
cd staticnode
114+
docker buildx build \
115+
--platform linux/riscv64 \
116+
-f Dockerfile-test -t test-node \
117+
--build-arg MANYLINUX_IMAGE=${{ matrix.IMAGE.MANYLINUX_IMAGE }} \
118+
--build-arg CONTAINER_NAME=ghcr.io/pyca/static-nodejs-riscv64:$NODE_VERSION \
119+
--load \
120+
.
121+
docker run --platform linux/riscv64 test-node \
122+
/staticnode/bin/node -e "console.log('hello world'); console.log(process.version)"
64123
- name: Login to docker
65124
run: 'docker login -u "$DOCKER_USERNAME" -p "$DOCKER_PASSWORD" ghcr.io'
66125
env:

0 commit comments

Comments
 (0)