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.
urchin only executes test files that have the executable bit, silently skipping the rest,
and `npm run test:check-exec` would catch non-executable ones, but no workflow ran it -
so several test files have never actually run.
Make all of them executable, and fix the ones that were broken:
- the io.js source-install tests, skipped since 2016: io.js requires python 2 and gcc <= 5,
so they now skip on toolchains that can not compile it,
and a new gcc:4.9-container CI job runs them unmodified -
resolving, downloading, checksumming, and compiling io.js for real.
New `fake source` variants exercise nvm's source pipeline everywhere -
cache lookup, offline resolution, extraction, configure, make, make install, activation -
via a tiny fake source tree seeded into the download cache and installed with `--offline`.
Also strengthen the `nvm run | grep` assertions with `--silent`,
since the version banner used to satisfy the grep even when the built binary could not run,
and give the final assertions the `die` they always meant to call.
- `nvm uninstall ... incorrect file permissions fails nicely`, parked in 2025 as failing:
`sudo npm` resets PATH, so node 5's npm crashed under the system node.
The permissions check only trips on files that are neither writable nor self-owned,
and that precondition only needs `sudo touch` - not npm, jspm, or the network -
so use that, against a fake installed version,
and skip only where passwordless sudo does not exist.
- `nvm install --offline`: `nvm ls | tail -1` always grabbed an alias line, never a version;
use `nvm_ls` and skip its trailing `system <version>` line.
- `nvm exec ... help should not parse`: in a BRE, `[options]` is a bracket expression,
so the grep could never match node's literal `Usage: node [options]` output.
- `nvm use ... nvmrc containing not installed version`: current output once again matches its expectations verbatim; no changes needed.
Rewrite `test:check-exec` in POSIX sh - npm runs scripts with /bin/sh, which is dash on Ubuntu,
where the previous `[[`/`$'\n'` bashisms would break;
match by extension, so that filenames containing dots can not dodge the check;
and disable git's `core.quotePath` mangling of the non-ASCII test filenames.
Then wire it into the lint workflow.
The two `v0.40.0` + `nvmrc` jobs fail by design (https://github.com/nvm-sh/nvm/issues/3405),
but job-level `continue-on-error` still displays them as failures on every run,
which reads like the contributor broke something.
Tolerate failure only in the steps that exercise the bug, scoped to that matrix combination,
and add a final step that fails the job when the expected failure did not happen -
so those jobs are green exactly when v0.40.0 misbehaves as documented,
and turn red as a signal to remove this handling if v0.40.0 ever starts passing.
This also restores strict failure semantics to the passing `v0.40.0` + `no nvmrc` jobs,
which the job-level `continue-on-error` was needlessly masking.
The branch-reset step sent `force` as a string via `gh api -f "force=true"`,
which the Git refs API rejects ("not a boolean", HTTP 422), failing the release run.
Use `-F` so it is sent as a boolean.
Also resolve the version from the latest `vX.Y.Z` tag
(via the tags API) rather than `releases/latest`,
so a manual `workflow_dispatch` with no input works even before the GitHub release object for a freshly pushed tag is published.
Upstream's `.gitmodules` uses a relative submodule url (`../nvmrc.git`),
which resolves against the superproject's origin:
on a fork without its own `nvmrc` fork that is `<owner>/nvmrc`,
which 404s and fails `actions/checkout` with `submodules: true`.
Keep `submodules: true` (so a fork's own `nvmrc` is used when present),
but mark checkout `continue-on-error` and, only when it failed,
re-point the submodule at `nvm-sh/nvmrc` and update.
CodeQL (actions/missing-workflow-permissions)
flagged the matrix, test, and finisher jobs of nvm-install-test.yml for not declaring permissions.
Every other test workflow already sets least-privilege permissions per job; add them here to match:
`contents: read` for the matrix and test jobs, `contents: none` for the no-op finisher.
harden-runner runs with `egress-policy: block`, and the allow-list only included
`production.cloudflare.docker.com`. DockerHub serves image blobs from either its
Cloudflare or its CloudFront CDN; when a pull was routed to CloudFront
(`production.cloudfront.docker.com`) the connection was dropped, causing
`error pulling image configuration: ... connect: connection refused` and exit
125 in the xenial, installation_node, and fast (httpbin) suites. Allow both CDNs.
Container-based suites and the `nvm_download` httpbin check hard-fail whenever DockerHub is briefly unreachable
(observed: `dial tcp ...:443: connect: connection refused` while pulling images),
even though the change under test is fine.
This is unrelated to any test logic.
- tests-xenial / tests-installation-node: retry the `docker pull` up to 5 times before `docker run`, mirroring the existing apt-get retry
- `nvm_download` test: retry the httpbin pull and skip the auth-header checks (rather than fail) when the image cannot be pulled or run, and make cleanup tolerant of a missing container.
The Debian WSL image has stale apt sources pointing to ftp.debian.org
which no longer hosts bullseye-backports. The previous fix ran sed
after the first setup-wsl call, but that call already failed because
additional-packages triggers apt-get update internally.
For wsl_matrix (Debian, Ubuntu):
- Ubuntu: install with additional-packages directly (no apt issue)
- Debian: install without packages first, fix sources.list with sed,
then run apt-get update/upgrade/install manually with retries
- Exclude Debian and Ubuntu-20.04 --lts since node v24+ has exec
format errors on WSL1
For wsl_matrix_unofficial (Alpine):
- Remove the Debian-specific fix entirely (Alpine uses apk, not apt)
See https://github.com/Vampire/setup-wsl/issues/76