How to retry failed steps in GitHub Action Workflows
Tags: github
Published: 2022-12-07 09:41:54

Sometimes things can go wrong in your  [GitHub Action workflow](https://docs.github.com/en/actions/using-workflows) step(s) and you may want to retry the step(s). This article will cover 2 ways to approach the retrying of steps.

### Pre-requisites
- [Git](https://git-scm.com/) (should be installed in your path)
- [GitHub account](https://github.com/) - we'll need this to use GitHub actions


## Initial setup
In order to follow along, here are the steps you can take to setup your GitHub actions workflow.


#### Initialize your git repository
In your terminal, run `git init` to create an empty git repository or skip this step if you already have an existing git repository.

#### Create workflow file
GitHub workflow files are usually `.yaml/.yml` files that contain a series of jobs and steps to be executed by GitHub actions. These files often reside in  `.github/workflows`. If the directories do not exist, go ahead and create them.  Create a file  `retry.yml`  in  `.github/workflows`. For now, the file can contain the following:

```yml
name: "Retry action using retry step"
on:
	# This action is called when this is pushed to github
	push:
	# This action can be manually triggered
	workflow_call:
jobs:
    # This name is up to you
	retry-job:
		runs-on: "ubuntu-latest"
		name: My Job
		steps:
			- name: Checkout repository
			  uses: actions/checkout@v3
			
			- name: Print
			  run: |
				echo 'Hello'
```

## Testing your workflow
You can test your GitHub Action workflow by pushing your changes to GitHub and going to the `actions` tab of the repository or you can choose to test locally using act. 


# Retrying failed steps
## Approach 1: Using the [retry-step](https://github.com/marketplace/actions/retry-step) action
By using the using the [retry-step action](https://github.com/marketplace/actions/retry-step), we can retry any failed shell commands. If our step or series of steps are shell commands then we can use the `retry-step` action to retry them. 

> If however you'd like to try retry a step that is using another action, then the `retry-step` action will NOT work for you. In that case, you may want to try the alternative steps mentioned below.

Modify your action file to contain the following:
```yml
name: "Retry action using retry step"
on:
	# This action is called when this is pushed to github
	push:
	# This action can be manually triggered
	workflow_call:
jobs:
    # This name is up to you
	retry-job:
		runs-on: "ubuntu-latest"
		name: My Job
		steps:
			- name: Checkout repository
			  uses: actions/checkout@v3
			
			
			- name: Use the reusable workflow
			  # Use the retry action
			  uses: nick-fields/retry@v2
			  with:
				max_attempts: 3
				retry_on: error
				timeout_seconds: 5
				# You can specify the shell commands you want to retry here
				command: |
					echo 'some command that would potentially fail'				
```

## Approach 2: Duplicate steps
If you are trying to retry steps that use other actions, the `retry-step` action may not get the job done. In such a case, you can still retry steps by retrying steps conditionally depending on whether or not a step failed. 

GitHub provides us with two main additional attributes in our steps:
- `continue-on-error` - Setting this to `true` means that the even if the current step fails, the job will continue on to the next one (by default failure stops a job's running).
- `steps.{id}.outcome` - where `{id}` is an `id` you add to the steps you want to retry.
This can be used to tell whether a step failed or not, potential values include `'failure'` and `'success'`.
- `if` - allows us to conditionally run a step

```yml
name: "Retry action using retry step"
on:
	# This action is called when this is pushed to GitHub
	push:
	# This action can be manually triggered
	workflow_call:
jobs:
    # This name is up to you
	retry-job:
		runs-on: "ubuntu-latest"
		name: My Job
		steps:
			- name: Checkout repository
			  uses: actions/checkout@v3
			  
			- name: Some action that can fail
			  # You need to specify an id to be able to tell what the status of this action was
			  id: myStepId1
			  # This needs to be true to proceed to the next step of failure
			  continue-on-error: true
			  uses: actions/someaction

			# Duplicate of the step that might fail ~ manual retry
			- name: Some action that can fail
			  id: myStepId2
			  # Only run this step if step 1 fails. It knows that step one failed because we specified an `id` for the first step
			  if: steps.myStepId1.outcome == 'failure'
			  # This needs to be true to proceed to the next step of failure
			  continue-on-error: true
			  uses: actions/someaction
```


## Bonus: Retrying multiple steps
If you want to retry multiple steps at once, then you can use [composite actions](https://docs.github.com/en/actions/creating-actions/creating-a-composite-action) to group the steps you want to retry and then use the duplicate steps approach mentioned above. 


# Conclusion
How do you decide which approach to use? 
- If you are retrying a step that is only shell commands then you can use the [retry step action](https://github.com/marketplace/actions/retry-step).
- If you are retrying a step that needs to use another action, then you can use duplication of steps with conditional running to manually retry the steps.

---
_This Dot Labs is a JavaScript consulting firm that enables companies to build and improve their digital technologies with confidence. For expert architectural guidance, training, consulting, engineering leadership, and development services in React, Angular, Vue, Web Components, GraphQL, Node, Bazel, Polymer, and more, visit [thisdot.co](https://www.thisdot.co/)_