dev/notes

Spot a mistake? Highlight any text in a post and click Report — it goes straight to the author.

intermediate · DevOps · August 17, 2026 · 1 min read

How to Set Up GitHub Actions for CI/CD

Set up GitHub Actions for continuous integration and deployment. Automate tests and deploys on every push with a reusable workflow.

CI/CD in one file

GitHub Actions runs a YAML workflow on your repo’s runners. A single file in .github/workflows/ can install dependencies, run tests, build, and deploy — all triggered by a push or pull request.

Step 1 — Create the workflow

.github/workflows/ci.yml:

name: CI

on:
  push:
    branches: [main]
  pull_request:

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

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

      - run: npm ci
      - run: npm run typecheck
      - run: npm test
      - run: npm run build

npm ci installs exactly what package-lock.json pins, which is deterministic in CI (unlike npm install).

Step 2 — Add caching and concurrency

Faster runs and no two deploys racing:

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

jobs:
  build:
    # ...steps above...
    - run: npm ci
    - run: npm run build

Step 3 — Deploy to Cloudflare Pages

Add a deploy job that uses CF_API_TOKEN from repo secrets:

  deploy:
    needs: build
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    steps:
      - uses: actions/checkout@v4
      - uses: cloudflare/wrangler-action@v3
        with:
          apiToken: ${{ secrets.CF_API_TOKEN }}
          command: pages deploy dist --project-name=your-project

Step 4 — Add secrets

GitHub → Settings → Secrets and variables → Actions → New repository secret:

  • CF_API_TOKEN — a Cloudflare API token with Pages edit scope.

Secrets are encrypted at rest, masked in logs, and never exposed to forks’ pull requests.

Troubleshooting

  • npm ci fails on a missing lockfile — commit package-lock.json; CI must not generate it.
  • Workflow doesn’t run — YAML must live in .github/workflows/*.yml on the default branch, and the on: triggers must match.
  • Secrets empty in a PR from a fork — by design. Secrets are only available in workflows from your own branches.

Summary

Every push to main now typechecks, tests, builds, and deploys automatically. The workflow is the source of truth for “is this shippable?” — no manual steps.

Related posts

Comments

One comment per thread every 30 minutes · edits are unlimited.