Step 6
GitHub Actions quality gate
25 min
GitHub Actions quality gate
Block merges until the tests pass. The most reliable way to end "works on my machine".
1. Minimal workflow
name: test
on:
pull_request:
push:
branches: [main]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with: { node-version: "20", cache: "pnpm" }
- run: pnpm install --frozen-lockfile
- run: pnpm lint
- run: pnpm typecheck
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with: { node-version: "20", cache: "pnpm" }
- run: pnpm install --frozen-lockfile
- run: pnpm test --run
--frozen-lockfile prevents silent dependency mutation.
2. Matrix
strategy:
matrix:
node: [20, 22]
os: [ubuntu-latest, macos-latest]
runs-on: ${{ matrix.os }}
Budget carefully; free minutes run out.
3. Cache
- uses: actions/cache@v4
with:
path: ~/.cache/pnpm
key: pnpm-${{ hashFiles('pnpm-lock.yaml') }}
4. Playwright E2E
e2e:
timeout-minutes: 20
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with: { node-version: "20", cache: "pnpm" }
- run: pnpm install --frozen-lockfile
- run: pnpm exec playwright install --with-deps chromium
- run: pnpm exec playwright test
- uses: actions/upload-artifact@v4
if: always()
with:
name: playwright-report
path: playwright-report/
5. Real DB (testcontainers)
GitHub Actions ships Docker, so testcontainers works without services:.
6. Secrets
- run: pnpm test
env:
DATABASE_URL: ${{ secrets.TEST_DB_URL }}
Never echo secrets to logs.
7. Branch protection
Require status checks to passRequire branches to be up to date- Disable admin bypass
Makes a red build structurally unmergeable.
8. Alerts
- name: Slack on failure
if: failure()
uses: slackapi/slack-github-action@v1
with:
payload: |
{ "text": "${{ github.repository }} main build failed: ${{ github.run_id }}" }
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}
Alert on main only; PR-level pings are noise.
9. Gotchas
- Wrong cache key
- Tight timeouts → blocked CI
- Missing
playwright install --with-deps - No artifact upload → you can't debug failures
10. Cost
Private repos: 2000 free minutes/month. Monitor matrix jobs closely.
Closing
Half a day of setup returns weeks of avoided "works on my machine" debates. The larger the team, the bigger the compounding.
Next
- backend/06-api-handler-pattern
- philosophy/02-ssot-everywhere
🎉 You finished Testing strategy and quality gates
What's next? Pick another course below.