Tutorial GitHub Actions CI/CD DevOps YAML Workflow Developer Tools Cheat Sheet

Free GitHub Actions CI/CD Cheat Sheet Online — 120+ GitHub Actions Workflow Commands & YAML Reference

· 20 min read

Free GitHub Actions CI/CD Cheat Sheet Online

GitHub Actions is the CI/CD platform built into every GitHub repository. It automates build, test, and deployment workflows — triggered by push, pull request, schedule, manual dispatch, or any of 20+ webhook events. Workflows are defined in YAML under .github/workflows/. If you can write a YAML file, you can build a pipeline. But the platform is deep: expressions, contexts, matrix strategies, environments, OIDC, service containers, reusable workflows, artifact sharing, dependency caching, self-hosted runners — there is a lot to know.

Our free interactive GitHub Actions CI/CD Cheat Sheet covers more than 120 entries across ten categories: Core Workflow, Job & Step Configuration, Build & Test, Deployment, YAML Syntax, Matrix Strategies, Artifacts & Caching, Runners & Environments, Secrets & Security, and Events & Triggers. Every entry includes a plain-language description and a copyable YAML example. The interface is searchable, filterable by category, and works entirely in your browser. No signup. No ads. No tracking. Bookmark it.

If you are working across the full DevOps stack, see our Git Commands Expansion Cheat Sheet for advanced version control, our Docker Commands Expansion Cheat Sheet for container operations, our Kubernetes Commands Cheat Sheet for orchestration, our Terraform Commands Cheat Sheet for infrastructure as code, and our DevOps Commands Cheat Sheet for a cross-tool reference covering Docker, Kubernetes, AWS CLI, Helm, and Terraform.

What is GitHub Actions?

GitHub Actions is a serverless CI/CD engine. You write a workflow YAML file, push it to your repository, and GitHub executes it on hosted runners (Ubuntu, Windows, macOS) or your own self-hosted machines. There is nothing to provision, no CI server to maintain.

The model is deceptively simple: a workflow is triggered by an event. The workflow contains one or more jobs that run on runners. Each job contains sequential steps — either shell commands (run:) or prebuilt actions (uses:). Jobs run in parallel by default; use needs to create sequential dependencies. Actions are the reusable building blocks: thousands of community actions exist for checkout, language setup, caching, artifact storage, Docker builds, deployment, notifications, and more.

GitHub Actions is deeply integrated with GitHub itself. The automatically generated GITHUB_TOKEN has scoped permissions to the repository. OIDC lets workflows authenticate to AWS, Azure, and GCP without long-lived secrets. Deployment environments provide protection rules and isolated secrets. Matrix strategies let you test across OS/version combinations with a single job definition. Artifacts pass build outputs between jobs. And the entire system is auditable — every workflow run, every log line, is stored and searchable.

But the YAML syntax is unforgiving. Indentation matters. Expressions use [object Object] syntax with a custom expression language. Context variables are namespaced (github.ref, secrets.NPM_TOKEN, needs.build.outputs.name). Functions like fromJSON(), contains(), hashFiles() enable dynamic behavior. Getting all of this right takes practice — and a good cheat sheet.

GitHub Actions Cheat Sheet Overview

Our cheat sheet organizes GitHub Actions entries into ten categories mapped to real CI/CD workflows:

  • Core Workflow — workflow_dispatch, push, pull_request, schedule, workflow_call, workflow_run, jobs, steps, runs-on, name, if, needs. The skeleton of every pipeline.
  • Job & Step Config — continue-on-error, timeout-minutes, strategy, defaults, concurrency, permissions, container, services, env, outputs, max-parallel.
  • Build & Test — actions/checkout, setup-node, setup-python, setup-java, setup-go, cache, upload-artifact, download-artifact, run (single/multiline), working-directory, env.
  • Deployment — deploy-pages, gh-pages, docker/build-push-action, docker/login-action, docker/metadata-action, ssh-action, Cloudflare Pages, Vercel, Netlify, AWS S3.
  • YAML Syntax — on single/multiple events, activity types, paths/branches/tags filters, expressions [object Object], fromJSON(), toJSON(), contains().
  • Matrix Strategies — matrix basic, include/exclude, conditional matrix, dynamic matrix, fail-fast, max-parallel, OS/language matrix, containers, custom name.
  • Artifacts & Caching — upload/download-artifact, cache with hashFiles, restore-keys, retention-days, artifact patterns, cross-job sharing, cache across branches.
  • Runners & Environments — ubuntu/windows/macos, version pinning, self-hosted runners, labels, runner groups, environments, protection rules, env secrets/variables.
  • Secrets & Security — GITHUB_TOKEN, custom secrets, OIDC, permissions (job/workflow), CodeQL, Dependabot, secret scanning, environment secrets, reusable workflow secrets, security hardening.
  • Events & Triggers — issues, issue_comment, pull_request_target, pull_request_review, release, registry_package, deployment, status, discussion, create/delete, workflow_run, repository_dispatch.

Each category contains 12 entries with production-ready YAML examples you can copy directly into your workflow files.

Core Workflow: The Pipeline Skeleton

Every GitHub Actions workflow starts with a name, an event trigger, and one or more jobs. The core workflow entries cover the structural elements that every pipeline needs.

workflow_dispatch enables manual triggering from the GitHub UI or REST API. It accepts typed inputs — strings, choices, booleans, environments — making it perfect for parameterized deployments:

on:
  workflow_dispatch:
    inputs:
      environment:
        description: 'Deploy target'
        required: true
        type: choice
        options: [staging, production]

push and pull_request are the most common event triggers. Push runs on every commit to specified branches; pull_request runs when PRs are opened, updated, or reopened:

on:
  push:
    branches: [main, develop]
    tags: ['v*']
  pull_request:
    branches: [main]
    types: [opened, synchronize, reopened]

schedule uses POSIX cron syntax for time-based triggers. Scheduled workflows run on the default branch and are not guaranteed to execute at exact times — GitHub may delay them during high load:

on:
  schedule:
    - cron: '0 8 * * 1-5'   # Weekdays at 08:00 UTC

workflow_call makes a workflow reusable. Define inputs (typed, with defaults), secrets (passed by the caller), and outputs (computed by the called workflow):

on:
  workflow_call:
    inputs:
      node-version:
        type: string
        required: false
        default: '20'
    outputs:
      artifact-name:
        value: ${{ jobs.build.outputs.name }}

jobs are the execution unit. Define a runner, steps, and optional dependencies. Use needs to chain jobs:

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci && npm run build
  deploy:
    needs: build
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'

The if conditional supports success(), failure(), always(), and cancelled() status functions, plus expression evaluation. Combined with the name property, these make workflow logs readable and workflow flow controllable.

Job & Step Configuration: The Control Panel

Beyond basic jobs and steps, GitHub Actions provides deep configuration options that control execution behavior, resource limits, and parallelism.

concurrency prevents overlapping workflow runs. Define a group (often including github.ref) and set cancel-in-progress: true to auto-cancel queued runs when a new one starts:

concurrency:
  group: deploy-${{ github.ref }}
  cancel-in-progress: true

strategy with matrix creates multiple job variations from a single definition. Combine with include/exclude for fine-grained control:

strategy:
  matrix:
    node: [18, 20, 22]
    os: [ubuntu-latest, windows-latest]
  fail-fast: false
  max-parallel: 4

timeout-minutes at the job or step level prevents runaway processes from consuming hours of runner time. continue-on-error lets a flaky step fail without killing the job — the step result is recorded but execution continues.

container runs the entire job inside a Docker container. services run sidecar containers alongside your job — essential for integration tests that need a real database or message broker:

services:
  postgres:
    image: postgres:16-alpine
    env:
      POSTGRES_PASSWORD: password
    ports:
      - 5432:5432

defaults.run sets default shell and working directory for all run steps. outputs on a job makes values available to dependent jobs via needs.JOB_ID.outputs.NAME.

Build & Test: The Factory Floor

This is where the actual work happens. The Build & Test category covers the actions and patterns you use every day.

actions/checkout@v4 is almost always the first step in any job. It clones your repository onto the runner. Key options: fetch-depth: 0 for full history (needed for blame, rebase checks, and versioning based on git tags), submodules: recursive for submodule-heavy projects:

- uses: actions/checkout@v4
  with:
    fetch-depth: 0
    submodules: recursive

Language setup actions — setup-node@v4, setup-python@v5, setup-java@v4, setup-go@v5 — configure the runtime and enable dependency caching with a single flag:

- uses: actions/setup-node@v4
  with:
    node-version: 20
    cache: 'npm'

run steps are the shell commands. Single-line runs work for quick commands; multiline YAML blocks (using |) are better for sequences. Use working-directory to scope a step to a subdirectory. Use step-level env for per-step environment overrides:

- name: Build and test
  run: |
    npm ci
    npm run build
    npm test -- --coverage
  env:
    NODE_ENV: test

Deployment: The Shipping Dock

GitHub Actions has first-class support for deployment workflows. The deployment category covers actions for major platforms plus SSH-based server deployment.

For Docker, the standard pattern is a three-step sequence: login, metadata, build-push:

- uses: docker/login-action@v3
  with:
    registry: ghcr.io
    username: ${{ github.actor }}
    password: ${{ secrets.GITHUB_TOKEN }}
- uses: docker/metadata-action@v5
  id: meta
  with:
    images: ghcr.io/myorg/myapp
    tags: type=ref,event=branch
- uses: docker/build-push-action@v6
  with:
    context: .
    push: true
    tags: ${{ steps.meta.outputs.tags }}
    platforms: linux/amd64,linux/arm64

For cloud platforms: Cloudflare Pages uses cloudflare/wrangler-action@v3 with API token and account ID. Vercel uses amondnet/vercel-action@v25 with token, org ID, and project ID. Netlify uses nwtgck/actions-netlify@v3 with auth token and site ID. AWS S3 uses aws-actions/configure-aws-credentials@v4 (supporting OIDC) followed by aws s3 sync.

For VPS/SSH deployment, appleboy/ssh-action@v1 executes remote commands:

- uses: appleboy/ssh-action@v1
  with:
    host: ${{ secrets.SERVER_HOST }}
    username: ${{ secrets.SERVER_USER }}
    key: ${{ secrets.SERVER_SSH_KEY }}
    script: cd /app && git pull && docker compose up -d

The environment keyword associates a job with a deployment environment. This exposes environment-specific secrets and variables, and enables protection rules (required reviewers, wait timers, branch restrictions) configured in GitHub Settings.

YAML Syntax: The Blueprint Language

GitHub Actions YAML is deceptively simple. The syntax itself is standard YAML, but the semantics — the expression language, contexts, and functions — deserve dedicated study.

on defines triggers. A single event, multiple events as a list, or detailed configuration with types and filters:

on:
  push:
    paths:
      - 'src/**'
      - '!src/docs/**'
    branches-ignore:
      - 'wip/**'
  pull_request:
    branches: [main]

Path filtering (on.push.paths) is one of the most underutilized optimizations. Only trigger a workflow when relevant files change — a CSS-only change should not trigger a backend test suite.

Expressions use [object Object] syntax and access contexts: github (event data, ref, sha, actor), env (variables), secrets (encrypted secrets), vars (configuration variables), needs (dependent job outputs), inputs (workflow_dispatch or workflow_call inputs), matrix (current matrix values), runner (OS, architecture, name), job (status, container info).

Essential functions include fromJSON() (parse JSON strings into objects — critical for dynamic matrices), toJSON() (serialize to JSON — pass complex values between jobs), contains() (check if a string or array contains a value), and hashFiles() (compute a hash of specified files — the backbone of cache key generation).

Matrix Strategies: The Assembly Line Multiplier

The matrix strategy is GitHub Actions' killer feature for CI testing. Define a job once, run it across multiple OS/runtime combinations automatically.

A basic matrix creates the Cartesian product of all dimensions. 3 operating systems x 4 Node versions = 12 parallel jobs:

strategy:
  matrix:
    os: [ubuntu-latest, windows-latest, macos-latest]
    node: [18, 20, 22, 24]
  fail-fast: false

include adds special cases to any existing matrix combination. exclude removes unsupported pairings (e.g., certain Node versions on Windows ARM). Use matrix.name to give each job a human-readable label in the UI:

strategy:
  matrix:
    os: [ubuntu-latest, windows-latest]
    node: [18, 22]
  name: "${{ matrix.os }} - Node ${{ matrix.node }}"

Dynamic matrices enable configuration-driven CI. A setup job computes the matrix as JSON, outputs it, and a test job reads it with fromJSON(needs.setup.outputs.matrix). This pattern lets you define which tests to run based on changed files, labels, or external configuration:

jobs:
  setup:
    runs-on: ubuntu-latest
    outputs:
      matrix: ${{ steps.set-matrix.outputs.matrix }}
    steps:
      - id: set-matrix
        run: echo "matrix={"node":["18","20","22"]}" >> $GITHUB_OUTPUT
  test:
    needs: setup
    strategy:
      matrix: ${{ fromJSON(needs.setup.outputs.matrix) }}

Artifacts & Caching: The Conveyor Belt

Artifacts and caches are both persistence mechanisms, but they serve different purposes.

Artifacts (upload-artifact/download-artifact) pass data between jobs in the same workflow run: build outputs, test reports, coverage data, compiled binaries. Artifacts persist for up to 90 days by default. Use pattern with wildcards to download multiple artifacts. The merge-multiple: true flag combines multiple uploads into one directory:

# Build job uploads
- uses: actions/upload-artifact@v4
  with:
    name: dist
    path: dist/

# Deploy job downloads
- uses: actions/download-artifact@v4
  with:
    name: dist
    path: ./dist

Caches (actions/cache@v4) persist dependencies across workflow runs. The cache key typically uses hashFiles() on lock files so the cache rotates when dependencies change. restore-keys provide fallback for partial cache hits:

- uses: actions/cache@v4
  with:
    path: |
      ~/.npm
      node_modules
    key: npm-${{ runner.os }}-${{ hashFiles('package-lock.json') }}
    restore-keys: |
      npm-${{ runner.os }}-
      npm-

Key difference: artifacts are per-workflow-run and immutable once uploaded, caches are per-key and shared across runs (but also immutable — you can't update a cache, only create a new one with a new key).

Runners & Environments: The Machine Floor

GitHub provides three hosted runner families: ubuntu-latest (Ubuntu 24.04, x64 or ARM64 with the -arm suffix), windows-latest (Windows Server 2025), and macos-latest (macOS 14 on Apple silicon). Each comes with a preinstalled toolchain — Docker, Node, Python, Go, Java, .NET, and hundreds of CLI utilities.

Pin OS versions for reproducibility: ubuntu-24.04 instead of ubuntu-latest. When -latest points to a new LTS, your workflows could break if they depend on specific preinstalled tool versions.

Self-hosted runners let you use your own infrastructure. Register a runner with a single command, add custom labels, and target it with runs-on: [self-hosted, linux, gpu]. Use runner groups for access control — restrict production runners to specific repositories or workflows.

Environments provide deployment isolation. Configure them in GitHub Settings with: required reviewers (up to 6 people must approve), wait timers (delay before deploy), deployment branches (only main can deploy to production), and custom deployment branches and tags. Environment-scoped secrets and variables prevent staging workflows from accessing production credentials.

Secrets & Security: The Vault

Security in GitHub Actions operates on multiple layers. The GITHUB_TOKEN is automatically generated per workflow run with scoped permissions. Custom secrets store API keys, tokens, and SSH keys — redacted from logs automatically. OIDC eliminates the need for long-lived cloud credentials entirely:

- uses: aws-actions/configure-aws-credentials@v4
  with:
    role-to-assume: arn:aws:iam::ACCOUNT:role/GitHubActions
    aws-region: us-east-1
# No access keys stored in GitHub secrets!

Permissions follow the principle of least privilege. Set them at the workflow level as defaults, override at the job level for specific needs:

permissions:
  contents: read
  pull-requests: write
  id-token: write

CodeQL (code scanning), Dependabot (dependency updates), and secret scanning (push protection) are built-in security features. Pin actions to commit SHAs for supply chain security. Use step-security/harden-runner to audit outbound network access from workflows.

Events & Triggers: The Start Button

Twenty-plus event types trigger GitHub Actions workflows. Beyond push and pull_request, specialized events enable sophisticated automation:

  • issues and issue_comment — automate issue triage, labeling, and auto-close stale issues.
  • pull_request_target — runs in the context of the base repository (access to secrets), not the fork. Handle with extreme care — never check out PR code in this context.
  • pull_request_review — auto-merge on approval, enforce review policies programmatically.
  • release — trigger CD pipelines on release publication. Build artifacts, publish packages, update changelogs.
  • workflow_run — chain workflows. Trigger a post-deploy notification workflow when the deploy workflow completes.
  • repository_dispatch — trigger workflows from external systems via REST API with custom payloads. Enables CI/CD from observability alerts, CMS updates, or external schedulers.
  • discussion — react to GitHub Discussions activity for community automation.
  • registry_package — react to new packages published in GitHub Packages.

Combine events with activity types, path filters, and branch filters for precise trigger control. A workflow that only runs when Python files change in a PR to main is far more efficient than one that runs on every push to every branch.

Production GitHub Actions Workflow: A Real Example

Here is a complete production CI/CD pipeline that ties together the most important patterns:

name: CI/CD Pipeline

on:
  push:
    branches: [main]
    paths-ignore: ['**.md', 'docs/**']
  pull_request:
    branches: [main]
  workflow_dispatch:
    inputs:
      deploy_env:
        type: choice
        options: [staging, production]

concurrency:
  group: ci-${{ github.ref }}
  cancel-in-progress: true

permissions:
  contents: read
  pull-requests: write
  id-token: write

jobs:
  # 1. Build and test across Node versions
  build:
    strategy:
      matrix:
        node: [18, 20, 22]
      fail-fast: false
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node }}
          cache: 'npm'

      - run: npm ci
      - run: npm run build
      - run: npm test -- --coverage

      - uses: actions/upload-artifact@v4
        with:
          name: dist-node-${{ matrix.node }}
          path: dist/

  # 2. Docker build and push
  docker:
    needs: build
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/download-artifact@v4
        with:
          name: dist-node-22
          path: dist/

      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - uses: docker/metadata-action@v5
        id: meta
        with:
          images: ghcr.io/myorg/myapp
          tags: type=sha,format=short

      - uses: docker/build-push-action@v6
        with:
          context: .
          push: true
          tags: ${{ steps.meta.outputs.tags }}

  # 3. Deploy to staging
  deploy-staging:
    needs: docker
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    environment:
      name: staging
      url: https://staging.example.com
    steps:
      - uses: appleboy/ssh-action@v1
        with:
          host: ${{ secrets.STAGING_HOST }}
          username: deploy
          key: ${{ secrets.SSH_KEY }}
          script: |
            cd /app
            docker compose pull web
            docker compose up -d --force-recreate web

  # 4. Deploy to production (manual dispatch only)
  deploy-production:
    if: github.event_name == 'workflow_dispatch' && inputs.deploy_env == 'production'
    needs: docker
    runs-on: ubuntu-latest
    environment:
      name: production
      url: https://example.com
    steps:
      - uses: appleboy/ssh-action@v1
        with:
          host: ${{ secrets.PROD_HOST }}
          username: deploy
          key: ${{ secrets.SSH_KEY }}
          script: |
            cd /app
            docker compose pull web
            docker compose up -d --force-recreate web

This pipeline demonstrates: concurrent matrix testing, artifact passing between jobs, Docker multi-stage builds, environment-separated deployments, concurrency control, minimal permissions, and manual dispatch for production deploys. Every pattern is battle-tested.

Conclusion

GitHub Actions turns your repository into a CI/CD platform. Once you understand the core concepts — events trigger workflows, workflows contain jobs, jobs run steps on runners — the remaining skill is knowing which actions exist, what YAML patterns work, and how to debug when things go wrong. Our cheat sheet covers the 120+ entries you will reach for when writing real pipelines.

Keep the cheat sheet open during your next workflow authoring session. When you need a matrix strategy, a cache key pattern, an OIDC role assumption, a concurrency group, or the exact syntax for path filters, the answer is there. Combine it with our Git Commands Expansion Cheat Sheet for version control mastery, our Docker Commands Expansion Cheat Sheet for container operations, our Kubernetes Commands Cheat Sheet for orchestration, our Terraform Commands Cheat Sheet for infrastructure provisioning, and our DevOps Commands Cheat Sheet for cross-tool reference.

Now go automate something. That is what GitHub Actions does best.

Found this useful? Check out our free developer tools or browse more articles.