GitHub Actions: CI/CD that scales with your repo

Sep 12, 2025
githubactionscicd
0

Why GitHub Actions

GitHub Actions lets you automate everything that happens after a commit: linting, tests, builds, security checks, and deployments. It runs close to your code, integrates with the PR experience, and scales from small repos to large monorepos.

Core concepts (90‑second refresher)

  • Workflow: A YAML file in .github/workflows/ that describes triggers and jobs.
  • Job: Runs on its own VM/runner. Jobs can run in parallel or sequence.
  • Step: A command or an action inside a job.
  • Action: A reusable function (e.g., actions/checkout@v4).
  • Secrets/Vars: Store credentials and configuration safely.

Minimal CI for a TypeScript/Next.js project

name: CI
on:
  pull_request:
  push:
    branches: [ main ]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: npm
      - run: npm ci
      - run: npm run lint
      - run: npm run build

Fast builds with caching

  • Use actions/setup-node with cache: npm or pnpm.
  • Cache build artifacts you can reuse (e.g., Turbo or Nx caches) to speed up PRs.

Secrets and environments

Keep credentials out of code:

  • Add secrets under GitHub → Repo → Settings → Secrets and variables → Actions.
  • Reference them in workflows using ${{ secrets.MY_SECRET }}.

Example: expose a key to a step without echoing it in logs:

- name: Run script with secret
  env:
    SERVICE_KEY: ${{ secrets.SERVICE_KEY }}
  run: node scripts/secure-task.js

Example: Auto-apply database migrations with Supabase

This repo includes a workflow that applies SQL migrations in supabase/migrations/** whenever you push to main. Set two repository secrets:

  • SUPABASE_ACCESS_TOKEN – Create in Supabase (Account → Access Tokens)
  • SUPABASE_PROJECT_REF – Your project ID (Project settings)

Workflow (excerpt):

name: Supabase Migrations
on:
  push:
    branches: [ main ]
    paths: [ 'supabase/migrations/**' ]

jobs:
  apply:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: supabase/setup-cli@v1
        with:
          version: latest
      - name: Link & push
        env:
          SUPABASE_ACCESS_TOKEN: ${{ secrets.SUPABASE_ACCESS_TOKEN }}
          SUPABASE_PROJECT_REF: ${{ secrets.SUPABASE_PROJECT_REF }}
        run: |
          supabase link --project-ref "$SUPABASE_PROJECT_REF"
          supabase db push --include-all

Deploy tips

  • Use separate workflows for CI (fast checks) and CD (deploy after CI passes).
  • Protect main with required checks to keep production stable.
  • Add a preview environment for PRs; deploy only when PR is approved.

Common pitfalls and fixes

  • Long installs → cache dependencies and use npm ci.
  • Flaky tests → run retries on a smaller subset, isolate network calls.
  • Secret leaks → never print secrets; set ACTIONS_STEP_DEBUG only in a temporary environment.
  • Monorepo complexity → use path filters to run jobs only for changed packages.

Checklist

  • Lint, type-check, unit tests on PRs
  • Build artifacts cached
  • Secrets configured in GitHub
  • Database migrations automated
  • Preview deploys for PRs

With a few YAML files and disciplined secrets management, Actions gives you a fast, reliable pipeline that grows with your team.