├── .github ├── auto-merge.yml ├── dependabot.yml ├── labels.yml ├── workflows │ ├── release-drafter.yml │ ├── repository.yml │ └── test.yml └── release-drafter.yml ├── LICENSE.md ├── action.yml └── README.md /.github/auto-merge.yml: -------------------------------------------------------------------------------- 1 | --- 2 | requiredLabels: 3 | - PR-merge 4 | 5 | reportStatus: true 6 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | --- 2 | version: 2 3 | updates: 4 | - package-ecosystem: "github-actions" 5 | directory: "/" 6 | schedule: 7 | interval: "daily" 8 | labels: 9 | - "C-dependency" 10 | - "PR-merge" 11 | -------------------------------------------------------------------------------- /.github/labels.yml: -------------------------------------------------------------------------------- 1 | # The labels in this file are automatically synced with the repository 2 | # using the micnncim/action-label-syncer action. 3 | --- 4 | - name: C-dependency 5 | color: 1abc9c 6 | description: "Category: Dependency" 7 | - name: PR-block 8 | color: 3498db 9 | description: "Pull Request: Do not merge" 10 | - name: PR-merge 11 | color: 3498db 12 | description: "Pull Request: Merge when ready" 13 | -------------------------------------------------------------------------------- /.github/workflows/release-drafter.yml: -------------------------------------------------------------------------------- 1 | name: Release Drafter 2 | 3 | on: 4 | push: 5 | # branches to consider in the event; optional, defaults to all 6 | branches: 7 | - master 8 | 9 | jobs: 10 | update_release_draft: 11 | runs-on: ubuntu-latest 12 | steps: 13 | # Drafts your next Release notes as Pull Requests are merged into "master" 14 | - uses: release-drafter/release-drafter@v5 15 | with: 16 | publish: true 17 | env: 18 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 19 | -------------------------------------------------------------------------------- /.github/workflows/repository.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Repository 3 | 4 | on: 5 | push: 6 | branches: 7 | - master 8 | paths: 9 | - .github/labels.yml 10 | 11 | jobs: 12 | labels: 13 | name: Labels 14 | runs-on: ubuntu-latest 15 | 16 | steps: 17 | - name: Checkout code 18 | uses: actions/checkout@v3 19 | 20 | - name: Sync labels 21 | uses: micnncim/action-label-syncer@v1 22 | env: 23 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 24 | with: 25 | manifest: .github/labels.yml 26 | -------------------------------------------------------------------------------- /.github/release-drafter.yml: -------------------------------------------------------------------------------- 1 | name-template: 'v$RESOLVED_VERSION 🌈' 2 | tag-template: 'v$RESOLVED_VERSION' 3 | categories: 4 | - title: '🚀 Features' 5 | labels: 6 | - 'feature' 7 | - 'enhancement' 8 | - title: '🐛 Bug Fixes' 9 | labels: 10 | - 'fix' 11 | - 'bugfix' 12 | - 'bug' 13 | - title: '🧰 Maintenance' 14 | label: 'chore' 15 | change-template: '- $TITLE @$AUTHOR (#$NUMBER)' 16 | change-title-escapes: '\<*_&' # You can add # and @ to disable mentions, and add ` to disable code blocks. 17 | version-resolver: 18 | major: 19 | labels: 20 | - 'major' 21 | minor: 22 | labels: 23 | - 'minor' 24 | patch: 25 | labels: 26 | - 'patch' 27 | default: patch 28 | template: | 29 | ## Changes 30 | 31 | $CHANGES 32 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # MIT License 2 | 3 | **Copyright (c) 2022 [cytopia](https://github.com/cytopia)** 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: test 3 | on: 4 | pull_request: 5 | 6 | jobs: 7 | test-default: 8 | name: test success 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Checkout repository 12 | uses: actions/checkout@v3 13 | with: 14 | fetch-depth: 0 15 | - name: retry 16 | uses: ./ 17 | with: 18 | command: true 19 | 20 | test-fail-command-1: 21 | name: test fail command 1 22 | runs-on: ubuntu-latest 23 | steps: 24 | - name: Checkout repository 25 | uses: actions/checkout@v3 26 | with: 27 | fetch-depth: 0 28 | - name: retry 29 | uses: ./ 30 | with: 31 | command: false 32 | retries: 2 33 | pause: 1 34 | fail_command: | 35 | echo "This command has failed" \ 36 | && echo "Failed command concatenated" 37 | continue-on-error: true 38 | 39 | test-fail-command-2: 40 | name: test fail command 2 41 | runs-on: ubuntu-latest 42 | steps: 43 | - name: Checkout repository 44 | uses: actions/checkout@v3 45 | with: 46 | fetch-depth: 0 47 | - name: retry 48 | uses: ./ 49 | with: 50 | command: false 51 | retries: 2 52 | pause: 1 53 | fail_command: | 54 | sudo sysctl -w net.ipv4.ip_forward=1 \ 55 | && sudo systemctl restart docker 56 | continue-on-error: true 57 | -------------------------------------------------------------------------------- /action.yml: -------------------------------------------------------------------------------- 1 | # https://help.github.com/en/articles/metadata-syntax-for-github-actions 2 | name: 'Shell command retry action' 3 | description: "GitHub Action to repeatedly retry a shell command upon failure." 4 | author: 'cytopia' 5 | branding: 6 | icon: 'code' 7 | color: 'red' 8 | 9 | inputs: 10 | retries: 11 | description: 'How many times to retry on failure' 12 | required: false 13 | default: 10 14 | pause: 15 | description: 'How many seconds to wait between retries' 16 | required: false 17 | default: 10 18 | command: 19 | description: 'Shell command to execute' 20 | required: true 21 | default: 'true' 22 | fail_command: 23 | description: 'Shell command to execute on every failure of given command (The fail_command will always succeed via: || true)' 24 | required: false 25 | default: '' 26 | workdir: 27 | description: 'Switch to this working directory prior executing shell command' 28 | required: false 29 | default: '' 30 | 31 | runs: 32 | using: "composite" 33 | steps: 34 | - name: execute 35 | shell: bash 36 | run: | 37 | retry() { 38 | for n in $(seq ${RETRIES}); do 39 | echo "[${n}/${RETRIES}] ${*}"; 40 | if eval "${*}"; then 41 | echo "[SUCC] ${n}/${RETRIES}"; 42 | return 0; 43 | fi; 44 | if [ -n "${FAIL_COMMAND}" ]; then 45 | echo "Executing fail command:"; 46 | echo "${FAIL_COMMAND}"; 47 | eval "${FAIL_COMMAND}" || true; 48 | fi; 49 | sleep ${PAUSE}; 50 | echo "[FAIL] ${n}/${RETRIES}"; 51 | done; 52 | return 1; 53 | } 54 | if [ -n "${WORKDIR}" ]; then 55 | cd "${WORKDIR}" 56 | fi 57 | retry ${COMMAND} 58 | env: 59 | RETRIES: ${{ inputs.retries }} 60 | PAUSE: ${{ inputs.pause }} 61 | COMMAND: ${{ inputs.command }} 62 | WORKDIR: ${{ inputs.workdir }} 63 | FAIL_COMMAND: ${{ inputs.fail_command }} 64 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Shell command retry action 2 | 3 | [![GitHub release](https://img.shields.io/github/release/cytopia/shell-command-retry-action.svg?logo=github)](https://github.com/cytopia/shell-command-retry-action/releases/latest) 4 | [![GitHub marketplace](https://img.shields.io/badge/marketplace-shell--command--retry--action-blue?logo=github)](https://github.com/marketplace/actions/shell-command-retry-action) 5 | [![](https://img.shields.io/badge/github-cytopia%2Fshell--command--retry--action-red.svg?logo=github)](https://github.com/cytopia/shell-command-retry-action "github.com/cytopia/shell-command-retry-action") 6 | [![test](https://github.com/cytopia/shell-command-retry-action/actions/workflows/test.yml/badge.svg)](https://github.com/cytopia/shell-command-retry-action/actions/workflows/test.yml) 7 | 8 | This action allows you to retry shell command for a few times in case they fail. This is especially useful for all kind of network related tasks, such as downloading files or similar. In case the remote endpoint has some issues, the job will not simply fail because of this, but retry the command and eventually reach success. 9 | 10 | 11 | ## :arrow_forward: Inputs 12 | 13 | The following inputs can be used to alter the Docker tag name determination: 14 | 15 | | Input | Required | Default | Description | 16 | |----------------|----------|----------|-------------------------------------------| 17 | | `retries` | No | `10` | How many times to retry on failure. | 18 | | `pause` | No | `10` | How many seconds to wait between retries. | 19 | | `command` | Yes | `` | Shell command to execute. | 20 | | `workdir` | No | `` | Switch to this working directory prior executing the shell command. | 21 | | `fail_command` | No | `` | Shell command to execute on every failure of given `command`. | 22 | 23 | 24 | ## :arrow_backward: Outputs 25 | 26 | None 27 | 28 | 29 | ## :computer: Usage 30 | 31 | ```yaml 32 | on: [push] 33 | 34 | jobs: 35 | job1: 36 | runs-on: ubuntu-latest 37 | name: Pull docker image 38 | steps: 39 | 40 | - name: Checkout repository 41 | uses: actions/checkout@v2 42 | with: 43 | fetch-depth: 0 44 | 45 | - name: Build docker image 46 | uses: cytopia/shell-command-retry-action@v0.1.2 47 | with: 48 | retries: 10 49 | pause: 10 50 | command: | 51 | docker build -t test . 52 | # Builing docker sometimes fails on GH Action runner due to network issues. 53 | # We ensure that forwarding is reenabled and the daemon is restarted 54 | # Before retrying the docker build command 55 | fail_command: | 56 | sudo sysctl -w net.ipv4.ip_forward=1 \ 57 | && sudo systemctl restart docker \ 58 | ``` 59 | 60 | 61 | ## :exclamation: Keep up-to-date with GitHub Dependabot 62 | 63 | Since [Dependabot](https://docs.github.com/en/github/administering-a-repository/keeping-your-actions-up-to-date-with-github-dependabot) has [native GitHub Actions support](https://docs.github.com/en/github/administering-a-repository/configuration-options-for-dependency-updates#package-ecosystem), to enable it on your GitHub repo all you need to do is add the `.github/dependabot.yml` file: 64 | 65 | ```yml 66 | version: 2 67 | updates: 68 | # Maintain dependencies for GitHub Actions 69 | - package-ecosystem: "github-actions" 70 | directory: "/" 71 | schedule: 72 | interval: "daily" 73 | ``` 74 | 75 | 76 | ## :octocat: [cytopia](https://github.com/cytopia) GitHub Actions 77 | 78 | | Name | Description | 79 | |----------------------------------|-------------| 80 | | [docker-tag-action] | Determines Docker tags based on git branch, commit or git tag | 81 | | [git-ref-matrix-action] | Create stringified JSON list of git refs to be used as a build matrix | 82 | | [shell-command-retry-action] | Retries shell commands to avoid failing pipelines due to network issues | 83 | | [upload-artifact-verify-action] | Upload artifact and verifies it by downloading it again | 84 | | [upload-artifact-retry-action] | Retries `upload-artifact-verify-action` | 85 | | [download-artifact-retry-action] | Download artifact with retry functionality | 86 | 87 | [docker-tag-action]: https://github.com/cytopia/docker-tag-action 88 | [git-ref-matrix-action]: https://github.com/cytopia/git-ref-matrix-action 89 | [shell-command-retry-action]: https://github.com/cytopia/shell-command-retry-action 90 | [upload-artifact-verify-action]: https://github.com/cytopia/upload-artifact-verify-action 91 | [upload-artifact-retry-action]: https://github.com/cytopia/upload-artifact-retry-action 92 | [download-artifact-retry-action]: https://github.com/cytopia/download-artifact-retry-action 93 | 94 | 95 | ## :page_facing_up: License 96 | 97 | **[MIT License](LICENSE)** 98 | 99 | Copyright (c) 2022 [cytopia](https://github.com/cytopia) 100 | --------------------------------------------------------------------------------