mirror of
https://github.com/nvm-sh/nvm.git
synced 2026-07-18 12:58:21 +08:00
[actions] add tests-alpine: a green fast suite and a musl-binary regression matrix
The full suite cannot run on Alpine: the install-based suites pin ancient Node (0.10.x, io.js) that has no musl binary and cannot source-compile on musl. Run the fast unit suite instead (mirroring the ubuntu runner: non-root via su-exec, passwordless sudo, a PTY, no system node), plus a binary-only regression matrix that installs every (Alpine, Node) pair with a real unofficial musl binary via `nvm install -b`: x64 back to node 8.17.0 on old Alpine, arm64 at the v20.20.1/v22.21.1/v24.9.0 floors on modern Alpine.
This commit is contained in:
@@ -0,0 +1,193 @@
|
|||||||
|
name: 'Tests: alpine'
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
fast:
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
# Native runners per arch (no QEMU): arm64 uses the ubuntu-24.04-arm image.
|
||||||
|
name: 'fast ${{ matrix.arch }} (alpine ${{ matrix.alpine }}, ${{ matrix.shell }})'
|
||||||
|
runs-on: ${{ matrix.arch == 'arm64' && 'ubuntu-24.04-arm' || 'ubuntu-latest' }}
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
alpine:
|
||||||
|
- '3.15'
|
||||||
|
- '3.19'
|
||||||
|
- '3'
|
||||||
|
arch:
|
||||||
|
- x64
|
||||||
|
- arm64
|
||||||
|
shell:
|
||||||
|
- sh
|
||||||
|
- bash
|
||||||
|
- dash
|
||||||
|
- zsh
|
||||||
|
# - ksh (#574)
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Harden Runner
|
||||||
|
uses: step-security/harden-runner@v2
|
||||||
|
with:
|
||||||
|
allowed-endpoints:
|
||||||
|
github.com:443
|
||||||
|
registry.npmjs.org:443
|
||||||
|
raw.githubusercontent.com:443
|
||||||
|
nodejs.org:443
|
||||||
|
iojs.org:443
|
||||||
|
unofficial-builds.nodejs.org:443
|
||||||
|
dl-cdn.alpinelinux.org:443
|
||||||
|
dl-cdn.alpinelinux.org:80
|
||||||
|
registry-1.docker.io:443
|
||||||
|
auth.docker.io:443
|
||||||
|
production.cloudflare.docker.com:443
|
||||||
|
production.cloudfront.docker.com:443
|
||||||
|
- uses: actions/checkout@v6
|
||||||
|
id: checkout
|
||||||
|
continue-on-error: true
|
||||||
|
with:
|
||||||
|
submodules: true
|
||||||
|
- name: 'nvmrc submodule fallback (forks without their own nvmrc)'
|
||||||
|
if: steps.checkout.outcome == 'failure'
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
git submodule set-url test/fixtures/nvmrc https://github.com/nvm-sh/nvmrc.git
|
||||||
|
git submodule sync --recursive
|
||||||
|
git submodule update --init --recursive
|
||||||
|
- uses: ljharb/actions/node/install@main
|
||||||
|
name: 'npm install (on host; node_modules is mounted into the container)'
|
||||||
|
with:
|
||||||
|
node-version: 'lts/*'
|
||||||
|
skip-ls-check: true
|
||||||
|
- run: npm ls urchin
|
||||||
|
- name: 'Run fast tests on Alpine ${{ matrix.alpine }} (${{ matrix.arch }})'
|
||||||
|
run: |
|
||||||
|
for i in 1 2 3 4 5; do
|
||||||
|
docker pull alpine:${{ matrix.alpine }} && break
|
||||||
|
echo "docker pull failed, attempt $i/5"; sleep $((i * 5))
|
||||||
|
done
|
||||||
|
docker run --rm \
|
||||||
|
-v "${{ github.workspace }}:/workspace" \
|
||||||
|
-w /workspace \
|
||||||
|
-e "TEST_SHELL=${{ matrix.shell }}" \
|
||||||
|
-e "TERM=xterm-256color" \
|
||||||
|
-e "GITHUB_ACTIONS=true" \
|
||||||
|
alpine:${{ matrix.alpine }} \
|
||||||
|
sh -c '
|
||||||
|
set -ex
|
||||||
|
cat /etc/alpine-release; uname -m
|
||||||
|
for i in 1 2 3 4 5; do
|
||||||
|
apk add --no-cache \
|
||||||
|
make bash zsh dash \
|
||||||
|
grep sed gawk coreutils util-linux findutils ncurses \
|
||||||
|
curl wget ca-certificates openssl tar xz gzip git \
|
||||||
|
sudo su-exec libstdc++ libgcc && break
|
||||||
|
echo "apk add failed, attempt $i/5"; sleep $((i * 5))
|
||||||
|
done
|
||||||
|
# Mirror the ubuntu runner: run the suite as a non-root user with
|
||||||
|
# passwordless sudo and a PTY so the permission/terminal tests
|
||||||
|
# behave the same. The user takes the mounted checkout uid so
|
||||||
|
# files stay host-owned (no chown; post-checkout cleanup works).
|
||||||
|
# No node is installed, so no active version skews the output.
|
||||||
|
HOST_UID="$(stat -c %u /workspace)"
|
||||||
|
adduser -D -u "$HOST_UID" tester 2>/dev/null || adduser -D tester
|
||||||
|
echo "tester ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/tester
|
||||||
|
chmod 0440 /etc/sudoers.d/tester
|
||||||
|
export NVM_DIR=/workspace HOME=/home/tester
|
||||||
|
unset NVM_BIN NVM_INC NVM_CD_FLAGS
|
||||||
|
su-exec tester script -q -e -c "make TEST_SUITE=fast SHELL=$TEST_SHELL URCHIN=/workspace/node_modules/.bin/urchin test-$TEST_SHELL" /dev/null
|
||||||
|
'
|
||||||
|
|
||||||
|
musl-binary:
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
# Regression lock, same-era diagonal only: modern musl node needs a newer
|
||||||
|
# libstdc++ than old Alpine ships, and arm64-musl exists only from
|
||||||
|
# v20.20.1/v22.21.1/v24.9.0 (built on modern Alpine), so arm64 pins modern Alpine.
|
||||||
|
name: 'musl-binary ${{ matrix.arch }} (alpine ${{ matrix.alpine }}, node ${{ matrix.node }})'
|
||||||
|
runs-on: ${{ matrix.arch == 'arm64' && 'ubuntu-24.04-arm' || 'ubuntu-latest' }}
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- { arch: x64, alpine: '3.10', node: v8.17.0 }
|
||||||
|
- { arch: x64, alpine: '3.10', node: v10.24.1 }
|
||||||
|
- { arch: x64, alpine: '3.12', node: v12.22.12 }
|
||||||
|
- { arch: x64, alpine: '3.15', node: v14.21.3 }
|
||||||
|
- { arch: x64, alpine: '3.16', node: v16.20.2 }
|
||||||
|
- { arch: x64, alpine: '3.18', node: v18.20.4 }
|
||||||
|
- { arch: x64, alpine: '3.20', node: v20.18.1 }
|
||||||
|
- { arch: x64, alpine: '3', node: v22.12.0 }
|
||||||
|
- { arch: arm64, alpine: '3.20', node: v20.20.1 }
|
||||||
|
- { arch: arm64, alpine: '3', node: v22.21.1 }
|
||||||
|
- { arch: arm64, alpine: '3', node: v24.9.0 }
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Harden Runner
|
||||||
|
uses: step-security/harden-runner@v2
|
||||||
|
with:
|
||||||
|
allowed-endpoints:
|
||||||
|
github.com:443
|
||||||
|
registry.npmjs.org:443
|
||||||
|
unofficial-builds.nodejs.org:443
|
||||||
|
dl-cdn.alpinelinux.org:443
|
||||||
|
dl-cdn.alpinelinux.org:80
|
||||||
|
registry-1.docker.io:443
|
||||||
|
auth.docker.io:443
|
||||||
|
production.cloudflare.docker.com:443
|
||||||
|
production.cloudfront.docker.com:443
|
||||||
|
- uses: actions/checkout@v6
|
||||||
|
with:
|
||||||
|
submodules: false
|
||||||
|
- name: 'Install node ${{ matrix.node }} from a musl binary on Alpine ${{ matrix.alpine }}'
|
||||||
|
run: |
|
||||||
|
for i in 1 2 3 4 5; do
|
||||||
|
docker pull alpine:${{ matrix.alpine }} && break
|
||||||
|
echo "docker pull failed, attempt $i/5"; sleep $((i * 5))
|
||||||
|
done
|
||||||
|
docker run --rm \
|
||||||
|
-v "${{ github.workspace }}:/workspace" \
|
||||||
|
-w /workspace \
|
||||||
|
-e "NODE_VERSION=${{ matrix.node }}" \
|
||||||
|
-e "TERM=xterm-256color" \
|
||||||
|
alpine:${{ matrix.alpine }} \
|
||||||
|
sh -c '
|
||||||
|
set -ex
|
||||||
|
cat /etc/alpine-release; uname -m
|
||||||
|
# libstdc++/libgcc are load-bearing: the unofficial musl node
|
||||||
|
# binary dynamically links them. No build toolchain: -b forbids
|
||||||
|
# the source fallback, so a missing binary is a hard failure.
|
||||||
|
for i in 1 2 3 4 5; do
|
||||||
|
apk add --no-cache \
|
||||||
|
bash ca-certificates curl wget tar xz gzip \
|
||||||
|
grep sed coreutils libstdc++ libgcc && break
|
||||||
|
echo "apk add failed, attempt $i/5"; sleep $((i * 5))
|
||||||
|
done
|
||||||
|
export NVM_DIR=/workspace
|
||||||
|
unset NVM_BIN NVM_INC NVM_CD_FLAGS
|
||||||
|
# The default nodejs.org mirror serves no -musl artifacts; this one does.
|
||||||
|
export NVM_NODEJS_ORG_MIRROR=https://unofficial-builds.nodejs.org/download/release
|
||||||
|
. /workspace/nvm.sh --no-use
|
||||||
|
nvm install -b --skip-default-packages "$NODE_VERSION"
|
||||||
|
nvm use "$NODE_VERSION"
|
||||||
|
[ "$(node -v)" = "$NODE_VERSION" ] || { echo "version mismatch: $(node -v)"; exit 1; }
|
||||||
|
node -e "process.exit(0)"
|
||||||
|
ldd "$(command -v node)" | grep -qi musl
|
||||||
|
'
|
||||||
|
|
||||||
|
all:
|
||||||
|
permissions:
|
||||||
|
contents: none
|
||||||
|
name: 'all alpine tests'
|
||||||
|
needs: [fast, musl-binary]
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- run: true
|
||||||
Reference in New Issue
Block a user