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.