$ run as a normal user# run as root (or with sudo)
Test many versions with a matrix
A matrix runs the same job once for each combination of values.
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
max-parallel: 4
matrix:
os: [ubuntu-latest, windows-latest]
python: ["3.11", "3.12", "3.13"]
exclude:
- os: windows-latest
python: "3.11"
include:
- os: ubuntu-latest
python: "3.12"
coverage: true
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python }}
- run: pytest
- if: matrix.coverage
run: pytest --cov| Key | Meaning |
|---|---|
fail-fast: false | Let the other combinations finish when one fails |
max-parallel | Limit parallel jobs |
exclude / include | Remove / add combinations or extra values |
At work
A matrix over environments (env: [dev, staging]) plans every environment in one PR.
Reuse a whole workflow
A reusable workflow starts with on: workflow_call, takes inputs and secrets, and is called like a job.
on:
workflow_call:
inputs:
env:
type: string
required: true
secrets:
INFRACOST_KEY:
required: false
jobs:
plan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: terraform -chdir=envs/${{ inputs.env }} init && terraform -chdir=envs/${{ inputs.env }} planon: pull_request
jobs:
staging:
uses: ./.github/workflows/terraform-plan.yml
with:
env: staging
prod:
uses: s0sta/pipelines/.github/workflows/terraform-plan.yml@v1
with:
env: prod
secrets: inherit| Reuse type | Shares |
|---|---|
| Composite action | Some steps inside a job |
| Reusable workflow | Whole jobs, with their runners and environments |
Stop parallel deployments with concurrency
concurrency lets only one run of a group go at a time. A new run can cancel the old one (for PR checks) or wait (for deployments).
concurrency:
group: deploy-${{ github.ref }}
cancel-in-progress: falseconcurrency:
group: pr-${{ github.event.pull_request.number }}
cancel-in-progress: trueRemember
Never run two Terraform applies on the same state at once. A concurrency group per environment is a second safety net next to state locking.
Set timeouts and retries
A stuck job uses minutes for hours. Set limits.
jobs:
test:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- run: ./slow-test.sh
timeout-minutes: 5
continue-on-error: false