← All cheatsheets

CI/CD

GitHub Actions — workflow patterns that come up daily

## Triggers
```yaml
on:
  push:
    branches: [main]
  pull_request:
    branches: [main]
  schedule:
    - cron: "0 6 * * *"
  workflow_dispatch:
```

## Jobs + dependencies
```yaml
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
  deploy:
    needs: build
    runs-on: ubuntu-latest
```

## Setup language runtimes
```yaml
- uses: actions/setup-node@v4
  with:
    node-version: 22
    cache: pnpm
- uses: actions/setup-python@v5
  with:
    python-version: "3.12"
```

## Secrets + env
```yaml
env:
  AUTO_APPLY_DRY_RUN: "true"
steps:
  - run: pnpm exec tsx scripts/run.ts
    env:
      ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
```

## Conditional steps
```yaml
- if: github.ref == 'refs/heads/main'
  run: pnpm deploy
- if: failure()
  run: ./notify-on-failure.sh
```

## Cache (faster builds)
```yaml
- uses: actions/cache@v4
  with:
    path: ~/.cache/pnpm
    key: pnpm-${{ hashFiles('pnpm-lock.yaml') }}
```

## Reusable workflow
`uses: ./.github/workflows/reusable-ci.yml` or external `org/repo/.github/workflows/file.yml@ref`

## Permissions hardening
```yaml
permissions:
  contents: read
  pull-requests: write
```
Default broad permissions are an attack surface; declare what you need.