GitHub Actions (S1E04) - Matrix, Timeout, Concurrency, Context

Matrix
A matrix strategy lets you use variables in a single job definition to automatically create multiple job runs that are based on the combinations of the variables.
jobs:
example_matrix:
strategy:
matrix:
version: [10, 12]
os: [ubuntu-22.04, ubuntu-20.04]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.version }}
The above matrix will create four jobs in the following order:
{version: 10, os: ubuntu-22.04}
{version: 10, os: ubuntu-20.04}
{version: 12, os: ubuntu-22.04}
{version: 12, os: ubuntu-20.04}
Expanding and exclude the matrix
Use jobs.<job_id>.strategy.matrix.include
to expand existing matrix configurations or to add new configurations. The value of include
is a list of objects.
To remove specific configurations defined in the matrix, use jobs.<job_id>.strategy.matrix.exclude
.
jobs:
example_matrix:
strategy:
max-parallel: 2 # Run 2 jobs in parallel instead of all jobs running in parallel
matrix:
os: [ubuntu-22.04, ubuntu-20.04, windows-latest]
version: [10, 12]
include:
- os: ubuntu-22.04 # inclue version 14 for ubuntu-22.04
version: 14
- os: ubuntu-latest
version: 16 # inclue version 16 for ubuntu-latest
exclude:
- os: ubuntu-20.04
version: 12 # skip version 12 for ubuntu-20.04
- os: windows-latest # Skip all versions for windows-latest
runs-on: ${{ matrix.os }}
steps:
- run : echo "OS: ${{ matrix.os }} and version ${{ matrix.version }}"
The above workflow will result in
example_matrix (ubuntu-22.04, 10)
example_matrix (ubuntu-20.04, 10)
example_matrix (ubuntu-22.04, 12)
example_matrix (ubuntu-22.04, 14)
example_matrix (ubuntu-latest, 16)
Handling failures
jobs:
test:
continue-on-error: true # continue the job if failed
strategy:
fail-fast: false # continue
matrix:
os: [ubuntu-22.04, ubuntu-20.04, windows-latest]
version: [10, 12]
runs-on: ${{ matrix.os }}
steps:
- run : echo "OS: ${{ matrix.os }} and version ${{ matrix.version }}"
fail-fast
: Default is true. GitHub will cancel all in-progress and queued jobs in the matrix if any job in the matrix fails. Set at job level
continue-on-error
: applies to a single job. If set to false and that job fails, other jobs in the matrix will continue running. Can set at job/step level
Skip workflow
You can skip workflow runs triggered by the push
and pull_request
events by including a command in your commit message.
Add the following strings to the commit message in a push, or the HEAD commit of a pull request:
[skip ci]
[ci skip]
[no ci]
[skip actions]
[actions skip]
Alternatively add a skip-checks
trailer to your commit message preceded by two empty lines.
Concurrency
By default, multiple workflow runs, or jobs can run at the same time.
Control the concurrency of workflow & jobs, so that you can ensure that only one run or one job runs at a time in a specific context.
Ex. Multiple commits in a short time can trigger concurrent workflow runs but you may only need the latest workflow/job run to execute or each workflow run to wait for the previous ones to finish.
This can be defined at the workflow or job level.
name: Workflow-4-concurrency on: workflow_dispatch #Ensure only single instance of the workflow will run at a time. concurrency: # At the workflow level group: prod-deployemnt cancel-in-progress: true jobs: build: runs-on: ubuntu-latest #Ensure only single instance of the job will run at a time. concurrency: # At the job level group: prod-deployemnt cancel-in-progress: true steps: - name: Build and test code run: echo "The code build and test is over"
If we run multiple workflows runs for the above workflow the latest workflow run will cause the already running one to fail.
When
cancel-in-progress: false
the next concurrent workflow run will go into waiting state and if another run is started the waiting workflow will get cancelled and the latest run will enter the waiting state.There can be at most one running and one pending job in a concurrency group at any time.
Context
Contexts are a way to access information about workflow runs, variables, runner environments, jobs, and steps. Each context is an object that contains properties, which can be strings or other objects.
To print the contents of the context.
name: Context testing
on: push
jobs:
dump_contexts_to_log:
runs-on: ubuntu-latest
steps:
- name: Dump GitHub context
env:
GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo "$GITHUB_CONTEXT"
- name: Dump job context
env:
JOB_CONTEXT: ${{ toJson(job) }}
run: echo "$JOB_CONTEXT"
The below snippet shows the output generated.
{
"token": "***",
"job": "dump_contexts_to_log",
"ref": "refs/heads/my_branch",
"sha": "c27d339ee6075c1f744c5d4b200f7901aad2c369",
"repository": "octocat/hello-world",
#Only partial data is shown
Context Usage - If
We can use the if statement to evaluate the context information with expressions.
name: CI
on: push
jobs:
prod-check:
if: ${{ github.ref == 'refs/heads/main' }}
runs-on: ubuntu-latest
steps:
- run: echo "Deploying to production server on branch $GITHUB_REF"
- the
if
statement checks thegithub.ref
context to determine the current branch name; if the name isrefs/heads/main
, then the subsequent steps are executed.
Timeouts
Set the timeout in minutes at job or step level after which process will be killed.
jobs:
build:
runs-on: ubuntu-latest
timeout-minutes: 5 #Ensure the job is killed after 5 min
steps:
- name: Build and test code
timeout-minutes: 3 #Ensure the step is killed after 3 mins
run: echo "The code build and test is over"
References
Subscribe to my newsletter
Read articles from Jeason Joseph directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Jeason Joseph
Jeason Joseph
I am an DevOps Engineer working since 2018. Had the opportunity to provide consulting services to many IT service companies. Passionate about learning new technology.