Conditionally running a second job in a GitHub Actions workflow#
My simonwillisonblog-backup workflow periodically creates a JSON backup of my blog’s PostgreSQL database, using db-to-sqlite and sqlite-diffable. It then commits any changes back to the repo using this pattern:
1 - name: Commit any changes2 run: |-3 git config user.name "Automated"4 git config user.email "actions@users.noreply.github.com"5 git add simonwillisonblog6 timestamp=$(date -u)7 git commit -m "Latest data: ${timestamp}" || exit 08 git push
I decided to upgrade it to also build and deploy a SQLite database of the content to datasette.simonwillison.net - but only if a change had been detected.
I figured out the following pattern for doing that.
First, I added a line to the above block that set a change_detected
output variable for that step if it made it past the || exit 0
. I also added an id
to the step so I could reference it later on:
1 - name: Commit any changes2 id: commit_and_push3 run: |-4 git config user.name "Automated"5 git config user.email "actions@users.noreply.github.com"6 git add simonwillisonblog7 timestamp=$(date -u)8 git commit -m "Latest data: ${timestamp}" || exit 09 git push10 echo "::set-output name=change_detected::1"
This next piece took me a while to figure out: I also had to declare that output variable at the top of the initial job, copying the result of the named step:
1jobs:2 backup:3 runs-on: ubuntu-latest4 outputs:5 change_detected: ${{ steps.commit_and_push.outputs.change_detected }}
Without this, the output is not visible to the second job.
My second job started like this:
1 build_and_deploy:2 runs-on: ubuntu-latest3 needs: backup4 if: ${{ inputs.force_deploy || needs.backup.outputs.change_detected }}5 steps:
This second job is called build_and_deploy
and specify that it needs: backup
- so it should run directly after that backup job completes.
That new job has an if:
expression which looks at needs.backup.outputs.change_detected
to read the variable that was set by my echo "::set-output
line.
I’m also checking inputs.force_deploy
here. That’s a separate mechanism, which allows me to trigger the workflow with manually and specify that a deploy should happen even if no changes were detected - useful for when I alter the code that configures the deployed Datasette instance.
The force_deploy
variable comes from this section at the start of the YAML:
1on:2 push:3 branches:4 - main5 workflow_dispatch:6 inputs:7 force_deploy:8 description: 'Deploy even if no changes detected'9 required: false10 type: boolean
This configuration adds the following UI which I can use to manually trigger the workflow: