GitHub Actions — Cheat Sheet
CI/CD & GitHub Actions · 3 topics. Download the PDF or the Instagram carousel and share it.
Cheat Sheet · AiCanCode.org
GitHub Actions
CI/CD & GitHub Actions3 topicsQuick revision reference
1
GitHub Actions — Workflows, Jobs & Steps
GitHub Actions workflows consist of jobs that run on runners. Jobs contain steps — shell commands or reusable actions. Understanding job dependencies, matrix builds, and artifact passing is essential for effective pipelines.
- ✓Jobs run in parallel by default; use needs: to create sequential dependencies.
- ✓Matrix strategy multiplies a job across combinations — test NxM configurations in parallel.
- ✓Artifacts pass build outputs between jobs; they are not available between workflow runs.
- ✓Cache persists directories between runs — key should include a hash of the lockfile.
- ✓Environment protection rules in GitHub settings create manual approval gates for deployment jobs.
- ✓timeout-minutes prevents runaway jobs from consuming runner minutes forever.
Workflow structure — contexts and conditions
# .github/workflows/build.yml
name: Build and Test
on:
push:
branches: [main]
paths: # only trigger if these paths change
- 'src/**'
- 'package*.json'
- '.github/workflows/**'
workflow_dispatch: # manual trigger
inputs:
environment:
description: 'Target environment'
required: true
default: 'staging'
type: choice
options: [staging, production]
env: # workflow-level env vars (all jobs)
NODE_VERSION: '20'
REGISTRY: ghcr.io
jobs:
build:
runs-on: ubuntu-latest
timeout-minutes: 15 # fail job if it takes > 15 min
# Permissions for this job's GITHUB_TOKEN
permissions:
contents: read
packages: write # needed to push to GitHub Container Registry
# Outputs: pass values to downstream jobs
outputs:
image-tag: ${{ steps.meta.outputs.tags }}
git-sha: ${{ github.sha }}
steps:
- uses: actions/checkout@v4
# Contexts: github, env, secrets, inputs, steps, runner
- name: Print context info
run: |
echo "Branch: ${{ github.ref_name }}"
echo "SHA: ${{ github.sha }}"
echo "Actor: ${{ github.actor }}"
echo "Event: ${{ github.event_name }}"
echo "Repo: ${{ github.repository }}"
# Conditional steps
- name: Deploy to production
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
run: echo "Deploying to production..."2
Building & Pushing Docker Images in CI
A production Docker build pipeline builds multi-arch images, uses layer caching, scans for CVEs, and pushes to a registry with semantic version tags — all automated on every commit.
- ✓docker/metadata-action generates correct image tags automatically from git refs — no manual tag scripting.
- ✓type=sha always produces a unique immutable tag per commit — essential for production traceability.
- ✓GitHub Actions Cache (type=gha) stores Docker layer cache — 60-90% speedup on repeated builds.
- ✓OIDC authentication avoids storing long-lived cloud credentials in GitHub secrets.
- ✓Trivy scan before push — exit-code: 1 blocks the push if CRITICAL/HIGH CVEs are found.
- ✓Multi-arch builds (linux/amd64,linux/arm64) let dev Macs (M1/M2) and prod Linux servers use the same image.
.github/workflows/docker.yml — complete build pipeline
# .github/workflows/docker.yml
name: Build and Push Docker Image
on:
push:
branches: [main]
tags: ['v*.*.*'] # trigger on semver tags like v1.2.3
pull_request:
branches: [main]
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }} # owner/repo → ghcr.io/owner/repo
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write # push to GitHub Container Registry
security-events: write # upload Trivy SARIF to Security tab
steps:
- uses: actions/checkout@v4
# Enable Docker Buildx (multi-platform builder)
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
# Login to GitHub Container Registry
- name: Login to GHCR
if: github.event_name != 'pull_request' # don't push on PRs
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }} # auto-provided, no setup needed
# Generate image tags and labels from git metadata
- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=ref,event=branch # main → :main
type=ref,event=pr # PR #123 → :pr-123
type=semver,pattern={{version}} # v1.2.3 → :1.2.3
type=semver,pattern={{major}}.{{minor}} # v1.2.3 → :1.2
type=sha,prefix=sha- # :sha-abc1234 (always)
type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }}
# Build and push with layer caching
- name: Build and push
id: build
uses: docker/build-push-action@v5
with:
context: .
platforms: linux/amd64,linux/arm64 # multi-arch
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha # GitHub Actions cache
cache-to: type=gha,mode=max3
Reusable Workflows & Composite Actions
Reusable workflows let you define a pipeline once and call it from multiple repos. Composite actions bundle multiple steps into a single reusable unit — eliminating duplication across workflows.
- ✓Reusable workflows (workflow_call) share entire job sequences — best for org-wide pipeline standards.
- ✓Composite actions share step sequences within a job — best for common setup patterns.
- ✓Reusable workflows support inputs, secrets, and outputs — fully parameterisable.
- ✓Self-hosted runners are needed for private network access, special hardware, or compliance.
- ✓Actions Runner Controller (ARC) auto-scales self-hosted runners on Kubernetes from 0 to N.
- ✓Publish composite actions to a dedicated .github repo to share across all org repositories.
Reusable workflow definition and caller
# ── REUSABLE WORKFLOW: .github/workflows/build-and-push.yml ──────────────────
# (can be in the same repo or a shared .github repo)
name: Build and Push Docker Image (Reusable)
on:
workflow_call: # makes this workflow callable
inputs:
image-name:
required: true
type: string
environment:
required: false
type: string
default: staging
secrets:
registry-token:
required: true
outputs:
image-digest:
description: "SHA256 digest of the pushed image"
value: ${{ jobs.build.outputs.digest }}
jobs:
build:
runs-on: ubuntu-latest
outputs:
digest: ${{ steps.push.outputs.digest }}
steps:
- uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3
- uses: docker/login-action@v3
with:
registry: ghcr.io
password: ${{ secrets.registry-token }}
- name: Build and push
id: push
uses: docker/build-push-action@v5
with:
push: true
tags: ghcr.io/${{ inputs.image-name }}:latest
cache-from: type=gha
cache-to: type=gha,mode=max
# ── CALLER WORKFLOW: in any repo ─────────────────────────────────────────────
name: Release
on:
push:
branches: [main]
jobs:
build:
uses: my-org/.github/.github/workflows/build-and-push.yml@main
with:
image-name: my-org/my-app
environment: production
secrets:
registry-token: ${{ secrets.GITHUB_TOKEN }}
deploy:
needs: build
runs-on: ubuntu-latest
steps:
- run: echo "Deployed image digest: ${{ needs.build.outputs.image-digest }}"Learn this free with Aria, your AI tutor → AiCanCode.org/learn/cicd