Cheat SheetsCI/CD & GitHub ActionsGitHub Actions

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=max
3

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