|
| 1 | +# workflow-restarter |
| 2 | + |
| 3 | +## Description |
| 4 | + |
| 5 | +Although GitHub provides built-in programatic mechanisms for retrying individual steps within a workflow, it doesn't provide one for retrying entire workflows. One possible reason for this limitation may be to prevent accidental infinite retry loops around failing workflows. Any workflow that fails, however, can be manually re-started from the failed workflow on the `Actions` tab of the repository. For more information on restarting github worklows see [Re-running workflows and jobs](https://docs.github.com/en/actions/managing-workflow-runs/re-running-workflows-and-jobs). |
| 6 | + |
| 7 | +Nevertheless, it is possible to programmatically restart a workflow after it fails and the section below shows how to restart a failing workflow 3 times using the `workflow-restarter` re-usable workflow. |
| 8 | + |
| 9 | +## Usage |
| 10 | + |
| 11 | +If setting up the the `workflow-restarter` for the first time, then make sure to initialize it first and then configure another workflow to programmatically restart on failure. |
| 12 | + |
| 13 | +### Initialize the `Workflow Restarter` |
| 14 | + |
| 15 | +First, configure the `workflow-restarter-proxy` custom action by creating a `workflow-restarter.yml` file beneath the `.github/workflows` directory in your repository. |
| 16 | + |
| 17 | +Second, configure the `workflow-restarter` re-usable workflow: |
| 18 | + |
| 19 | +```yaml |
| 20 | +name: Workflow Restarter |
| 21 | +on: |
| 22 | + workflow_dispatch: |
| 23 | + inputs: |
| 24 | + repo: |
| 25 | + description: "GitHub repository name." |
| 26 | + required: true |
| 27 | + type: string |
| 28 | + run_id: |
| 29 | + description: "The ID of the workflow run to rerun." |
| 30 | + required: true |
| 31 | + type: string |
| 32 | + retries: |
| 33 | + description: "The number of times to retry the workflow run." |
| 34 | + required: false |
| 35 | + type: string |
| 36 | + default: "3" |
| 37 | + |
| 38 | +jobs: |
| 39 | + call-reusable-workflow: |
| 40 | + uses: puppetlabs/cat-github-actions/.github/workflows/workflow-restarter.yml@main |
| 41 | + with: |
| 42 | + repo: ${{ inputs.repo }} |
| 43 | + run_id: ${{ inputs.run_id }} |
| 44 | + retries: ${{ inputs.retries }} |
| 45 | +``` |
| 46 | +
|
| 47 | +Finally, verify that the `workflow-restarter.yml` performs as expected: |
| 48 | +1. Add a `workflow-restarter-test.yml` file to `.github/workflows`, copy the contents of `./github/workflows/workflow-restarter-test` from this repository |
| 49 | +2. Kick off the `workflow-restarter-test` and it should fail and be re-started 3 times. For example output see the [appendix below](#verify-workflow-restarter-with-workflow-restarter-test). |
| 50 | + |
| 51 | +### Configure an existing workflow to use `on-failure-workflow-restarter` |
| 52 | + |
| 53 | +Now add something like the following `yaml` job at the end of your workflow, changing only the `needs` section to suit. |
| 54 | + |
| 55 | +For example, the following will trigger a restart if either the `acceptance` or the `unit` jobs preceeding it fail. A restart of the failing jobs will be attempted 3 times at which point if the failing jobs continue to fail, then the workflow will be marked as failed. If, however, at any point the `acceptance` and `unit` both pass fine then the restarted workflow will be marked as successful |
| 56 | + |
| 57 | +```yaml |
| 58 | + on-failure-workflow-restarter-proxy: |
| 59 | + # (1) run this job after the "acceptance" job and... |
| 60 | + needs: [acceptance, unit] |
| 61 | + # (2) continue ONLY IF "acceptance" fails |
| 62 | + if: always() && needs.acceptance.result == 'failure' || needs.unit.result == 'failure' |
| 63 | + runs-on: ubuntu-latest |
| 64 | + steps: |
| 65 | + # (3) checkout this repository in order to "see" the following custom action |
| 66 | + - name: Checkout repository |
| 67 | + uses: actions/checkout@v2 |
| 68 | +
|
| 69 | + # (4) "use" the custom action to retrigger the failed "acceptance job" above |
| 70 | + # NOTE: pass the SOURCE_GITHUB_TOKEN to the custom action because (a) it must have |
| 71 | + # this to trigger the reusable workflow that restarts the failed job; and |
| 72 | + # (b) custom actions do not have access to the calling workflow's secrets |
| 73 | + - name: Trigger reusable workflow |
| 74 | + uses: ./.github/actions/workflow-restarter-proxy |
| 75 | + env: |
| 76 | + SOURCE_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
| 77 | + with: |
| 78 | + repository: ${{ github.repository }} |
| 79 | + run_id: ${{ github.run_id }} |
| 80 | +``` |
| 81 | + |
| 82 | +## Appendix |
| 83 | + |
| 84 | +### Verify `Workflow Restarter` with `Workflow Restarter TEST` |
| 85 | + |
| 86 | +The following shows 3 `Workflow Restarter` occuring after the `Workflow Restarter TEST`, which is set to fail continuously. |
| 87 | + |
| 88 | + |
| 89 | + |
| 90 | +Looking closer at the `Workflow Restarter TEST` reveals |
| 91 | + |
| 92 | +* that the workflow includes 2 jobs `unit` and `acceptance`; and |
| 93 | +* that the workflow has been re-run 3 times, e.g., |
| 94 | + |
| 95 | + |
| 96 | + |
| 97 | +Further, the following sequence of screenshots shows that only failed jobs are re-run. |
| 98 | + |
| 99 | +* The `on-failure-workflow-restarter` job **(1)** is triggered by the failure of the `unit` job and **(2)** successfully calls the `workflow-restarter` workflow |
| 100 | +* The `workflow-restarter` in turn triggers a re-run of the `unit` job **(3)** and the `Workflow Restarter TEST` shows this as an incremented attempt count at **(4)**. |
| 101 | + |
| 102 | + |
| 103 | + |
| 104 | + |
| 105 | + |
| 106 | + |
0 commit comments