Executing GitHub Actions jobs or steps only when specific files change
Sometimes you want to execute a step or a job only when some files are modified. For instance, you may want to lint and deploy the documentation only when a file under docs
is modified. This scenario is not directly supported by GitHub Actions. However, you can do it manually by using git
, PowerShell Core
, and GitHub Actions expressions.
The main idea is to use git diff
to get the list of modified files. Then, you can filter the list of files using a regex (easy using PowerShell!). Finally, you can set the output of the step/job by using a workflow command.
#Conditional steps
Use the following workflow if you want to run a step conditionally.
name: demo
on:
push:
branches:
- 'main'
jobs:
conditional_step:
runs-on: 'ubuntu-20.04'
steps:
- uses: actions/checkout@v2
with:
# Checkout as many commits as needed for the diff
fetch-depth: 2
- shell: pwsh
# Give an id to the step, so we can reference it later
id: check_file_changed
run: |
# Diff HEAD with the previous commit
$diff = git diff --name-only HEAD^ HEAD
# Check if a file under docs/ or with the .md extension has changed (added, modified, deleted)
$SourceDiff = $diff | Where-Object { $_ -match '^docs/' -or $_ -match '.md$' }
$HasDiff = $SourceDiff.Length -gt 0
# Set the output named "docs_changed"
Write-Host "::set-output name=docs_changed::$HasDiff"
# Run the step only with "docs_changed" equals "True"
- shell: pwsh
# steps.<step_id>.outputs.<output name>
if: steps.check_file_changed.outputs.docs_changed == 'True'
run: echo publish docs
#Conditional jobs
Use the following workflow if you want to run a job conditionally.
name: sample
on:
push:
branches:
- 'main'
jobs:
conditional_job_check_files:
runs-on: 'ubuntu-20.04'
# Declare outputs for next jobs
outputs:
docs_changed: ${{ steps.check_file_changed.outputs.docs_changed }}
steps:
- uses: actions/checkout@v2
with:
# Checkout as many commits as needed for the diff
fetch-depth: 2
- shell: pwsh
id: check_file_changed
run: |
# Diff HEAD with the previous commit
$diff = git diff --name-only HEAD^ HEAD
# Check if a file under docs/ or with the .md extension has changed (added, modified, deleted)
$SourceDiff = $diff | Where-Object { $_ -match '^docs/' -or $_ -match '.md$' }
$HasDiff = $SourceDiff.Length -gt 0
# Set the output named "docs_changed"
Write-Host "::set-output name=docs_changed::$HasDiff"
# Run the job only with "docs_changed" equals "True"
conditional_job:
runs-on: 'ubuntu-20.04'
needs: [ conditional_job_check_files ]
if: needs.conditional_job_check_files.outputs.docs_changed == 'True'
steps:
- shell: pwsh
run: echo publish docs
#Additional resources
Do you have a question or a suggestion about this post? Contact me!