From f37d916ccf24d8b33730383110eb3b4821034826 Mon Sep 17 00:00:00 2001 From: Steve Boyd Date: Wed, 29 Jul 2026 15:50:56 +1200 Subject: [PATCH] FIX Retry running nvm install --- action.yml | 15 +++++++++++---- nvm-install-retry.sh | 29 +++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 4 deletions(-) create mode 100644 nvm-install-retry.sh diff --git a/action.yml b/action.yml index 336200d..9b913d6 100644 --- a/action.yml +++ b/action.yml @@ -227,18 +227,23 @@ runs: fi # this loads nvm into the current terminal [[ -s "$NVM_DIR/nvm.sh" ]] && \. "$NVM_DIR/nvm.sh" --no-use + # this loads nvm_install_retry, which retries `nvm install` on network failures + \. ${{ github.action_path }}/nvm-install-retry.sh ADMIN_NPM_VERSION= if [[ -d vendor/silverstripe/admin ]]; then cd vendor/silverstripe/admin - nvm install + nvm_install_retry nvm use ADMIN_NPM_VERSION=$(npm -v) npm install --ignore-scripts -g yarn yarn install --ignore-scripts --network-concurrency 1 cd ../../.. fi - nvm install - nvm use + # `nvm use` is enough if this module uses the same node version as admin + if ! nvm use; then + nvm_install_retry + nvm use + fi if [[ $(npm -v) != $ADMIN_NPM_VERSION ]]; then npm install --ignore-scripts -g yarn; fi @@ -344,9 +349,11 @@ runs: export NVM_DIR="$HOME/.nvm" # this loads nvm into the current terminal [[ -s "$NVM_DIR/nvm.sh" ]] && \. "$NVM_DIR/nvm.sh" + # this loads nvm_install_retry, which retries `nvm install` on network failures + \. ${{ github.action_path }}/nvm-install-retry.sh # Swap to correct version and make sure yarn is installed NPM_VERSION=$(cat vendor/silverstripe/documentation-lint/.nvmrc) - nvm install $NPM_VERSION && nvm use $NPM_VERSION + nvm_install_retry $NPM_VERSION && nvm use $NPM_VERSION npm install --ignore-scripts --global yarn # Run the linting script vendor/bin/doclint diff --git a/nvm-install-retry.sh b/nvm-install-retry.sh new file mode 100644 index 0000000..9c9f415 --- /dev/null +++ b/nvm-install-retry.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash + +# Wrapper for `nvm install` that retries on failure. +# +# nvm resolves loose versions such as "18" by downloading https://nodejs.org/dist/index.tab. +# That download is made with curl in silent mode, so a network blip or a 429 from nodejs.org +# produces an empty version list and nvm exits 3 with a misleading +# "Version '18' not found - try `nvm ls-remote`" message rather than a download error. +# +# Source this file after loading nvm.sh, then call `nvm_install_retry` in place of `nvm install`. +# Any arguments are passed through to `nvm install`. +nvm_install_retry() { + local attempt + local attempts=3 + for ((attempt = 1; attempt <= attempts; attempt++)); do + if nvm install "$@"; then + return 0 + fi + echo "nvm install ${*} failed (attempt ${attempt} of ${attempts})" + if [[ $attempt -lt $attempts ]]; then + # Show what the remote version list actually did, to distinguish a genuinely + # missing version from a failed download, then back off before retrying + nvm ls-remote --no-colors > /dev/null || echo "nvm ls-remote also failed" + sleep $((attempt * 10)) + fi + done + echo "Could not install the node version requested by .nvmrc" + return 1 +}