I was recently tasked with performing a spike at work to see if we could implement reusable workflows. My team maintain a large number of python repositories, each one containing several workflows to perform specific CI tasks (linting, code formatting etc) that must pass before a pull request can be reviewed.
With our current setup, making a change to the workflow, for example updating an action version, would require us to make the update in the workflow and create a pull request in each python repository. This however takes valuable developer time which could be used on more important tickets and created overhead as we would need to keep track of which repositories have been updated.
Reusable workflows looked like they may be a solution to our problem. A reusable workflow is pretty much what it says on the tin, a workflow that is declared, and can then be called from other repositories to run the jobs in the reusable workflow. By implementing reusable workflows, we would be able to save developer time as the change needed would only need to be made in one workflow, and make having to remember which repositories had been updated redundant, as no changes would be need to be made in the calling repositories, only the reusable workflow.
I'm pleased to say that my spike was a success, allowing us to drastically reduce the workflow files in our repositories to a single CI workflow that calls off to our reusable workflow repository. It has been a great learning experience to dive into workflows, jobs steps and actions, and even to work with conditional logic to only run certain jobs and steps in certain cases.
Obviously I can't share private work code, so I've written a simple reusable workflow below as an example of how you can set one up. For further information on setting up reusable workflows to be called from private reposititories, passing inputs or secrets, and more advanced usage etc see the GitHub official documentation in the resources section at the end of this post.
Setting up a simple reusable workflows for HTML validation
Create a reusable workflow
You can call reusable workflows from within the same repository where you will be calling the reusable workflow from, but for this example I've create a new repository to store all my reusable workflows in one central place.
In the repository create a
.github
folder and within that aworkflows
folder.Create your reusable workflow file - I've called mine
html_validation.yml
on:
workflow_call:
jobs:
html:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4.2.2
- name: validate-html
uses: Cyb3r-Jak3/html5validator-action@v7.2.0
with:
root: .
As this is the reusable workflow that will be called, we need to include the trigger on: workflow_call
. This is what allows the workflow to be called from other repositories.
This is a simple workflow with one job called Validation, and two steps - the first performs a checkout of the repository, then we validate the HTML using the Cyb3r-Jak3/html5validator-action
action.
Call a reusable workflow
Now we need to declare the calling workflow - this is the workflow in our repository that will calling the reusable workflow.
Provide the trigger you would like the workflow to be called on in the calling repository - this example is calling the workflow on a push to the main branch, but you could set this up for on a pull request, or other branches etc. Take a look at the GitHub documentation to get an idea of the types of triggers you could use for your own workflows.
Next we'll declare a job,
Validate
and call off to our reusable workflow with theuses
.-
The format for calling our reusable workflow is:
<GitHub Username>
/<Repository Name>
/.github
/workflows
/<filename>
@<branch>
name: CI
on:
push:
branches: [main]
jobs:
Validate:
uses: kera-cudmore/example-reusable-workflows/.github/workflows/html_validation.yml@main
Ok time for the results!
When we push a change in the calling repository, we can view the workflows runs in the actions tab, and then select the run with your commit message:
We are then shown a summary of the CI job - showing the workflow file that triggered the run ci.yml
, and the jobs run, Validate
and html
.
Clicking on the validate/html
jobs box will then show you the steps detail page. You can expand the steps to view more information, for example the inputs passed in or the commands run as part of the step.
This expanded view is very useful to debug when a job fails, as you can see at which step the job failed and view the logs. The example below shows that the html validation step failed as element p is not allowed as a child of element h1 - this gives us an area of the code to check, and points to the h1 tag not being closed.
I've included the two repositories I created for this post in the resources below, feel free to fork them and play with the workflows.
Resources
Do you use reusable workflows to do something fun in your repositories? Never used them before but think you'll give them a go? Let me know in the comments below 😊
Top comments (0)