🎉 DevOps Interview Prep Bundle is live — 1000+ Q&A across 20 topicsGet it →
All Cheatsheets

GitHub Actions Cheatsheet

GitHub Actions workflow syntax, triggers, jobs, secrets, caching, Docker builds, and common patterns for CI/CD pipelines.

7 sections59 commandsClick any row to copy

Workflow Triggers

on: push
on: push: branches: [main, develop]
on: push: paths: - 'src/**' - '!docs/**'
on: pull_request: types: [opened, synchronize]
on: schedule: - cron: '0 2 * * *'
on: workflow_dispatch
on: workflow_dispatch: inputs: environment: type: choice options: [staging, prod]
on: release: types: [published]

Trigger on every push to any branch

Trigger on push to specific branches

Trigger only when src/ changes (ignore docs/)

Trigger on PR open and new commits

Trigger daily at 2am UTC

Manual trigger from GitHub UI

Manual trigger with dropdown input

Trigger when a release is published

Job Basics

jobs: build: runs-on: ubuntu-latest
runs-on: [self-hosted, linux, x64]
needs: [test, lint]
if: github.ref == 'refs/heads/main'
if: github.event_name == 'pull_request'
if: failure()
continue-on-error: true
timeout-minutes: 30
strategy: matrix: node: [18, 20, 22]
strategy: fail-fast: false

Job running on latest Ubuntu

Run on self-hosted runner with labels

Job waits for test and lint jobs to pass

Run job only on main branch

Run only on pull request events

Run only if previous step/job failed

Don't fail workflow if this step fails

Cancel job if it runs over 30 minutes

Run job for each Node.js version

Continue matrix jobs even if one fails

Steps & Actions

- uses: actions/checkout@v4
- uses: actions/checkout@v4 with: fetch-depth: 0
- uses: actions/setup-node@v4 with: node-version: '20' cache: 'npm'
- uses: actions/setup-python@v5 with: python-version: '3.11'
- name: Run tests run: | pip install -r requirements.txt pytest tests/ -v
- uses: actions/upload-artifact@v4 with: name: build-output path: dist/
- uses: actions/download-artifact@v4 with: name: build-output
- uses: actions/cache@v4 with: path: ~/.cache/pip key: ${{ runner.os }}-pip-${{ hashFiles('requirements.txt') }}

Checkout repository code

Full git history (needed for some tools)

Setup Node.js with npm cache

Setup Python

Multi-line run step

Upload build output as artifact

Download artifact from previous job

Cache pip dependencies

Secrets & Environment

env: DATABASE_URL: ${{ secrets.DATABASE_URL }}
env: NODE_ENV: production PORT: 3000
- name: Deploy env: API_KEY: ${{ secrets.API_KEY }}
echo "MY_VAR=hello" >> $GITHUB_ENV
echo "VERSION=$(cat VERSION)" >> $GITHUB_ENV
echo "::add-mask::$SECRET_VALUE"
${{ vars.MY_VARIABLE }}
${{ github.sha }}
${{ github.ref_name }}
${{ github.actor }}

Use a secret as environment variable

Set environment variables for all steps

Secret available only in this step

Set environment variable for subsequent steps

Set dynamic env var from command output

Mask a value in logs

Use a repository variable (non-secret)

Current commit SHA

Branch or tag name

User who triggered the workflow

Docker & Registry

- uses: docker/setup-buildx-action@v3
- uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }}
- uses: docker/login-action@v3 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }}
- uses: docker/build-push-action@v5 with: push: true tags: ghcr.io/${{ github.repository }}:${{ github.sha }}
- uses: docker/build-push-action@v5 with: cache-from: type=gha cache-to: type=gha,mode=max
- uses: docker/metadata-action@v5 id: meta with: images: ghcr.io/${{ github.repository }}
- uses: aws-actions/configure-aws-credentials@v4 with: role-to-assume: arn:aws:iam::123:role/GHARole aws-region: us-east-1
- uses: aws-actions/amazon-ecr-login@v2

Setup Docker Buildx for multi-platform builds

Login to GitHub Container Registry

Login to Docker Hub

Build and push Docker image

Build with GitHub Actions cache

Auto-generate image tags (semver, sha, latest)

AWS OIDC auth (no long-lived credentials)

Login to Amazon ECR after AWS credentials

Outputs & Conditionals

- id: version run: echo "tag=v1.2.3" >> $GITHUB_OUTPUT
${{ steps.version.outputs.tag }}
outputs: image-tag: value: ${{ steps.build.outputs.tag }}
${{ needs.build.outputs.image-tag }}
if: contains(github.event.head_commit.message, '[skip ci]')
if: startsWith(github.ref, 'refs/tags/v')
if: github.event.pull_request.draft == false
concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true

Set step output

Read step output in subsequent steps

Expose job output to other jobs

Read output from another job

Skip if commit message contains [skip ci]

Run only on version tags

Skip draft PRs

Cancel in-progress runs on new push

Common Patterns

permissions: id-token: write contents: read
permissions: packages: write contents: read
- uses: actions/github-script@v7 with: script: | github.rest.issues.createComment({...})
- uses: softprops/action-gh-release@v1 with: files: dist/*.tar.gz
- uses: peter-evans/create-pull-request@v6
- run: echo "GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }}" | gh auth login --with-token
- uses: slackapi/slack-github-action@v1 with: webhook: ${{ secrets.SLACK_WEBHOOK }}

Required for OIDC (AWS/GCP auth without secrets)

Required to push to GitHub Container Registry

Comment on PR using GitHub API

Create GitHub release and attach files

Auto-create a PR from workflow changes

Authenticate gh CLI in workflow

Send Slack notification from workflow