Cheatsheets
GitHub Actions
Workflows, triggers, matrix builds, caching, secrets, permissions, and OIDC.
Visualize
GitHub Actions — the job DAG
needs: orders jobs; independent jobs (test ∥ lint) run in parallel.
Press play: a push triggers the workflow, then jobs run by dependency order.
46 entries
Workflow basics6
.github/workflows/*.ymlWhere workflow files live
name: CIHuman-readable workflow name shown in the UI
on: [push, pull_request]Which events trigger the workflow
jobs:\n build:\n runs-on: ubuntu-latestDeclare one or more jobs
# minimal CI workflowCheckout + Node setup + install + lint + test + build
actions/checkout@v4Clone the repository onto the runner
Triggers8
on:\n push:\n branches: [main]\n paths: ['src/**']Run on push, filtered by branch and path
on:\n pull_request:\n types: [opened, synchronize, reopened]Run on pull request activity
on:\n workflow_dispatch:\n inputs: { ... }Manual trigger with typed inputs
on:\n schedule:\n - cron: '0 6 * * 1'Run on a cron schedule
on:\n workflow_call:\n inputs: { ... }\n secrets: { ... }Make this workflow reusable (called by others)
on:\n release:\n types: [published]Run when a release is published
on:\n issue_comment:\n types: [created]ChatOps — react to issue/PR comments
pull_request vs pull_request_targetSECURITY: secrets and fork PRs
Jobs & steps7
runs-on: ubuntu-latestChoose the runner OS/label
steps:\n - uses: actions/checkout@v4\n - run: npm ciuses vs run — the two kinds of step
needs: [build, test]Declare job dependencies (ordering)
outputs:\n sha: \${{ steps.meta.outputs.sha }}Pass values from one job to another
if: \${{ github.ref == 'refs/heads/main' }}Conditional execution + contexts
continue-on-error: trueLet a step/job fail without failing the run
timeout-minutes: 15Cap how long a job (or step) may run
Matrix builds5
strategy:\n matrix:\n node: [18, 20, 22]Run a job across multiple configurations
matrix:\n include: [ ... ]\n exclude: [ ... ]Add or remove specific matrix combinations
strategy:\n fail-fast: falseDon't cancel sibling matrix jobs on first failure
matrix: \${{ fromJSON(needs.setup.outputs.matrix) }}Dynamic matrix generated at runtime
strategy:\n max-parallel: 2Throttle how many matrix legs run at once
Caching & artifacts5
actions/cache@v4Cache dependencies between runs (key + restore-keys)
setup-node:\n with:\n cache: npmBuilt-in dependency caching in setup-* actions
actions/upload-artifact@v4Persist files/outputs from a run
actions/download-artifact@v4Pull artifacts into a later job
echo "## Summary" >> "$GITHUB_STEP_SUMMARY"Write rich Markdown to the run summary
Secrets & security5
env:\n TOKEN: \${{ secrets.MY_TOKEN }}Read a repository/org secret
permissions:\n contents: readLeast-privilege GITHUB_TOKEN
environment:\n name: productionEnvironment secrets + protection rules
# NEVER echo a secretMasking is not bulletproof — don't print secrets
permissions:\n id-token: writeOIDC — short-lived cloud creds, no stored keys
Reusable & composite5
uses: ./.github/workflows/build.ymlCall a reusable workflow
secrets: inheritForward all caller secrets to a reusable workflow
# action.yml -> runs.using: compositeComposite action — bundle steps into one reusable action
uses: actions/checkout@<sha>Pin marketplace actions to a SHA (supply chain)
uses: docker/build-push-action@v6\n with: { ... }Marketplace action with typed inputs
Control & performance5
concurrency:\n group: ci-\${{ github.ref }}\n cancel-in-progress: trueCancel superseded runs (one per branch/PR)
environment:\n name: production\n url: ...Deployment gates & tracking
services:\n postgres:\n image: postgres:16Service containers (DB/cache sidecars)
runs-on: [self-hosted, linux, x64]Self-hosted vs GitHub-hosted runners
# deploy only on main + environmentConditional deploy job (gated to main)