diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 92ca247..84ab9de 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,7 +36,7 @@ jobs: - name: Setup Python uses: actions/setup-python@v7 with: - python-version: "3.10" + python-version: "3.11" cache: 'pip' - name: Install Python dependencies @@ -124,7 +124,7 @@ jobs: - name: Setup Python uses: actions/setup-python@v7 with: - python-version: "3.10" + python-version: "3.11" cache: 'pip' - name: Install Python dependencies @@ -160,6 +160,43 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + test_retries: + name: Test retry inputs + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ ubuntu-latest, macos-latest, windows-latest ] + defaults: + run: + shell: bash + steps: + + - name: Checkout repo + uses: actions/checkout@v7 + + - name: Setup Python + uses: actions/setup-python@v7 + with: + python-version: "3.11" + cache: 'pip' + + - name: Install Python dependencies + run: pip install -r test/requirements.txt + + - name: Install executables + uses: ./ + with: + path: "" + cache: 'false' + retries: 5 + retry_wait_seconds: 1 + + - name: Test installation + run: python test/test.py "" "executables" + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + test_tag: name: Test release tag input runs-on: ${{ matrix.os }} @@ -179,7 +216,7 @@ jobs: - name: Setup Python uses: actions/setup-python@v7 with: - python-version: "3.10" + python-version: "3.11" cache: 'pip' - name: Install Python dependencies diff --git a/README.md b/README.md index cee590d..88e80a0 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,8 @@ An action to setup MODFLOW 6 and related programs. - [`subset`](#subset) - [`cache`](#cache) - [`ostag`](#ostag) + - [`retries`](#retries) + - [`retry_wait_seconds`](#retry_wait_seconds) - [Outputs](#outputs) - [`cache-hit`](#cache-hit) - [MODFLOW Resources](#modflow-resources) @@ -66,6 +68,8 @@ The action accepts the following optional inputs: - `owner` - `path` - `repo` +- `retries` +- `retry_wait_seconds` - `subset` - `tag` @@ -116,6 +120,16 @@ The `cache` input is a boolean that controls whether the action caches the MODFL The `ostag` input allows selecting a release by operating system. By default, this is the system the action is running on. Typically one will not need to override this default — one reason to do so is to select an Intel macOS distribution on an ARM macOS runner. +### `retries` + +The `retries` input is the number of extra attempts the action makes to download the executables before giving up. The default is `3`. Set it to `0` to attempt the download only once. + +This value is also passed to `curl` (via `--retry`) for the release metadata and install script requests. + +### `retry_wait_seconds` + +The number of seconds to wait between download attempts. The default is `5`. + ## Outputs The action has the following outputs: diff --git a/action.yml b/action.yml index a4a6c51..aef4f23 100644 --- a/action.yml +++ b/action.yml @@ -32,7 +32,15 @@ inputs: description: Operating system tag; default is to automatically choose. required: false default: '' - + retries: + description: Number of times to retry the download if it fails (e.g. a reset connection). Set to 0 to disable. + required: false + default: '3' + retry_wait_seconds: + description: Seconds to wait between download attempts. + required: false + default: '5' + outputs: cache-hit: description: Whether the installation was restored from cache @@ -79,7 +87,7 @@ runs: shell: bash run: | # get info for the executables repository's latest release - release_json=$(curl -H "Accept: application/vnd.github+json" -H "Authorization: Bearer $GH_TOKEN" "https://api.github.com/repos/${{ inputs.owner }}/${{ inputs.repo }}/releases/latest") || echo "No release to check, skipping" + release_json=$(curl --retry ${{ inputs.retries }} --retry-all-errors --retry-delay ${{ inputs.retry_wait_seconds }} -H "Accept: application/vnd.github+json" -H "Authorization: Bearer $GH_TOKEN" "https://api.github.com/repos/${{ inputs.owner }}/${{ inputs.repo }}/releases/latest") || echo "No release to check, skipping" # get asset ID of the release's metadata file, if one exists get_download_url=" @@ -97,7 +105,7 @@ runs: # asset_id is empty if code.json asset wasn't found on the release if [[ -n "$download_url" ]]; then echo "Downloading code.json from $download_url to $code_json" - curl -L -H "Authorization: Bearer $GH_TOKEN" "$download_url" >> "$code_json" + curl -L --retry ${{ inputs.retries }} --retry-all-errors --retry-delay ${{ inputs.retry_wait_seconds }} -H "Authorization: Bearer $GH_TOKEN" "$download_url" >> "$code_json" echo "Found code.json for distribution '${{ inputs.repo }}' with contents:" cat "$code_json" else @@ -161,6 +169,10 @@ runs: export SSL_CERT_FILE="$cert_file" fi + retries="${{ inputs.retries }}" + wait_seconds="${{ inputs.retry_wait_seconds }}" + max_attempts=$((retries + 1)) + # download the installation script if necessary if command -v get-modflow &> /dev/null then @@ -169,12 +181,26 @@ runs: else echo "get-modflow command not available, downloading install script" script_path="$RUNNER_TEMP/get_modflow.py" - curl https://raw.githubusercontent.com/modflowpy/flopy/develop/flopy/utils/get_modflow.py -o "$script_path" + curl --fail --silent --show-error --location \ + --retry "$retries" --retry-all-errors --retry-delay "$wait_seconds" \ + https://raw.githubusercontent.com/modflowpy/flopy/develop/flopy/utils/get_modflow.py -o "$script_path" cmd="python3 $script_path" fi + # the download reaches out to github and occasionally has its connection + # reset, so retry a few times before giving up (see the retries input) echo "starting installation" - $cmd $MODFLOW_BIN_PATH $args + attempt=1 + until $cmd $MODFLOW_BIN_PATH $args; do + status=$? + if [ "$attempt" -ge "$max_attempts" ]; then + echo "get-modflow failed after $attempt attempt(s) (exit $status)" + exit $status + fi + echo "get-modflow attempt $attempt/$max_attempts failed (exit $status); retrying in ${wait_seconds}s" + attempt=$((attempt + 1)) + sleep "$wait_seconds" + done env: GITHUB_TOKEN: ${{ steps.set-github-token.outputs.token }}