From 482f5c8dc7e703f77c11942c256f9a692145d5c8 Mon Sep 17 00:00:00 2001 From: Boshen Date: Wed, 29 Apr 2026 19:30:29 +0800 Subject: [PATCH 1/3] feat: auto-skip actions/setup-node on Alpine Linux actions/setup-node only ships glibc Node binaries via the GitHub toolcache, so installing Node into an Alpine container shadows the container's musl-native Node with a binary that cannot run. Subprocesses that spawn `node` then fail with ENOENT (the glibc dynamic linker is missing on Alpine). Add an `install-node` input defaulting to `auto`: detect Alpine via /etc/alpine-release and skip actions/setup-node when present, falling back to the container's Node. Users can force-install with `'true'` or opt out entirely with `'false'`. Co-Authored-By: Claude Opus 4.7 (1M context) --- README.md | 3 +++ action.yml | 16 ++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/README.md b/README.md index 0431c57..d06147f 100644 --- a/README.md +++ b/README.md @@ -3,3 +3,6 @@ * Reads node version file (.node-version) from project root * Only saves pnpm cache on the main branch * Restores pnpm cache on PR +* Auto-detects Alpine Linux containers and skips `actions/setup-node` + (which only ships glibc binaries) so the container's musl Node is used. + Override with `install-node: true | false`. diff --git a/action.yml b/action.yml index 9b41c39..4d0abeb 100644 --- a/action.yml +++ b/action.yml @@ -21,12 +21,28 @@ inputs: required: false description: 'Optional CPU architecture for pnpm supportedArchitectures configuration (e.g., x64, arm64).' + install-node: + required: false + default: 'auto' + description: 'Whether to install Node.js via actions/setup-node. "auto" (default) skips installation on Alpine Linux, where the GitHub toolcache only ships glibc Node binaries that cannot run on musl, and uses the container/system Node instead. "true" forces install. "false" skips.' + runs: using: composite steps: + - name: Detect Alpine Linux + id: detect + shell: bash + run: | + if [ -f /etc/alpine-release ]; then + echo "is-alpine=true" >> "$GITHUB_OUTPUT" + else + echo "is-alpine=false" >> "$GITHUB_OUTPUT" + fi + - uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0 - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 + if: ${{ inputs.install-node == 'true' || (inputs.install-node == 'auto' && steps.detect.outputs.is-alpine != 'true') }} with: node-version-file: .node-version architecture: ${{ inputs.architecture }} From 6d1b0ae8445197eb4ee006b276f8e5b29e4a544d Mon Sep 17 00:00:00 2001 From: Boshen Date: Wed, 29 Apr 2026 20:03:10 +0800 Subject: [PATCH 2/3] refactor: skip Alpine detect on non-Linux, drop redundant else branch Co-Authored-By: Claude Opus 4.7 (1M context) --- action.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/action.yml b/action.yml index 4d0abeb..eca4555 100644 --- a/action.yml +++ b/action.yml @@ -31,12 +31,11 @@ runs: steps: - name: Detect Alpine Linux id: detect + if: runner.os == 'Linux' shell: bash run: | if [ -f /etc/alpine-release ]; then echo "is-alpine=true" >> "$GITHUB_OUTPUT" - else - echo "is-alpine=false" >> "$GITHUB_OUTPUT" fi - uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0 From a866f096daf8febf6999d4227cbc424f1ac7eddc Mon Sep 17 00:00:00 2001 From: Boshen Date: Wed, 29 Apr 2026 21:31:33 +0800 Subject: [PATCH 3/3] refactor: drop install-node input, always auto-detect Alpine The tri-state input added more surface area than it earned: - install-node: true is nonsensical (glibc Node can't run on musl) - install-node: false has no real use case (skip the action entirely) - install-node: auto is the only useful behavior Just auto-detect /etc/alpine-release on Linux and skip actions/setup-node when present. Co-Authored-By: Claude Opus 4.7 (1M context) --- README.md | 5 ++--- action.yml | 9 +++------ 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index d06147f..aa32c1f 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,5 @@ * Reads node version file (.node-version) from project root * Only saves pnpm cache on the main branch * Restores pnpm cache on PR -* Auto-detects Alpine Linux containers and skips `actions/setup-node` - (which only ships glibc binaries) so the container's musl Node is used. - Override with `install-node: true | false`. +* Skips `actions/setup-node` on Alpine Linux (which only ships glibc + binaries) and uses the container's musl Node instead. diff --git a/action.yml b/action.yml index eca4555..65c2e2f 100644 --- a/action.yml +++ b/action.yml @@ -21,14 +21,11 @@ inputs: required: false description: 'Optional CPU architecture for pnpm supportedArchitectures configuration (e.g., x64, arm64).' - install-node: - required: false - default: 'auto' - description: 'Whether to install Node.js via actions/setup-node. "auto" (default) skips installation on Alpine Linux, where the GitHub toolcache only ships glibc Node binaries that cannot run on musl, and uses the container/system Node instead. "true" forces install. "false" skips.' - runs: using: composite steps: + # actions/setup-node only ships glibc Node binaries; on Alpine those can't + # run, so use the container's musl Node instead. - name: Detect Alpine Linux id: detect if: runner.os == 'Linux' @@ -41,7 +38,7 @@ runs: - uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0 - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 - if: ${{ inputs.install-node == 'true' || (inputs.install-node == 'auto' && steps.detect.outputs.is-alpine != 'true') }} + if: steps.detect.outputs.is-alpine != 'true' with: node-version-file: .node-version architecture: ${{ inputs.architecture }}