diff --git a/README.md b/README.md index e0a4d5d..d81a2e2 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,7 @@ A collection of reusable GitHub Actions and Workflows for Shopware extensions an |--------|-------------|------| | [setup-extension](setup-extension/) | Checkouts Shopware and extension, installs dependencies | [README](setup-extension/README.md) | | [shopware-version](shopware-version/) | Gets the Shopware version that matches the current branch | [README](shopware-version/README.md) | +| [npm-ci-retry](npm-ci-retry/) | Runs npm install commands with retry handling | [README](npm-ci-retry/README.md) | | [versions](versions/) | Gets version information for current and LTS major versions | [README](versions/README.md) | ### Workflow Orchestration diff --git a/npm-ci-retry/README.md b/npm-ci-retry/README.md new file mode 100644 index 0000000..b638980 --- /dev/null +++ b/npm-ci-retry/README.md @@ -0,0 +1,12 @@ +# npm ci retry + +Runs `npm ci` or another install command with three attempts and npm retry settings. + +## Usage + +```yaml +- uses: shopware/github-actions/npm-ci-retry@main + with: + working-directory: path/to/package + command: npm ci +``` diff --git a/npm-ci-retry/action.yml b/npm-ci-retry/action.yml new file mode 100644 index 0000000..afda2ca --- /dev/null +++ b/npm-ci-retry/action.yml @@ -0,0 +1,38 @@ +name: "npm ci with retry" +description: >- + Runs `npm ci` (or an equivalent install command) with retries and offline + preference so transient registry resets (ECONNRESET) don't fail the job. + Cache `~/.npm` in a preceding step to make the retries reuse tarballs offline. + +inputs: + working-directory: + description: "Directory to run the install in." + required: false + default: "." + command: + description: "Install command to run (e.g. `npm ci` or `composer run npm:storefront ci`)." + required: false + default: "npm ci" + +runs: + using: composite + steps: + - shell: bash + working-directory: ${{ inputs.working-directory }} + env: + npm_config_fetch_retries: "5" + npm_config_fetch_retry_mintimeout: "20000" + npm_config_fetch_retry_maxtimeout: "120000" + npm_config_prefer_offline: "true" + run: | + for attempt in 1 2 3; do + if ${{ inputs.command }}; then + break + fi + if [ "${attempt}" -eq 3 ]; then + echo "::error::'${{ inputs.command }}' failed after ${attempt} attempts" + exit 1 + fi + echo "::warning::'${{ inputs.command }}' failed (attempt ${attempt}/3); retrying in $((attempt * 15))s" + sleep "$((attempt * 15))" + done