CI/CD and Automation
Automates CI/CD pipeline setup. Use when setting up or modifying build and deployment pipelines, automating quality gates, or establishing deployment strategies.
Automates CI/CD pipeline setup. Use when setting up or modifying build and deployment pipelines, automating quality gates, or establishing deployment strategies.
Automate quality gates so that no change reaches production without passing tests, lint, type checking, and build.
Shift Left: Catch problems as early in the pipeline as possible. A bug caught in linting costs minutes; the same bug caught in production costs hours.
Faster is Safer: Smaller batches and more frequent releases reduce risk, not increase it. A deployment with 3 changes is easier to debug than one with 30.
Every change goes through these gates before merge:
Pull Request Opened
│
▼
┌─────────────────┐
│ LINT CHECK │ eslint, prettier
│ ↓ pass │
│ TYPE CHECK │ tsc --noEmit
│ ↓ pass │
│ UNIT TESTS │ jest/vitest
│ ↓ pass │
│ BUILD │ npm run build
│ ↓ pass │
│ INTEGRATION │ API/DB tests
│ ↓ pass │
│ E2E (optional) │ Playwright/Cypress
│ ↓ pass │
│ SECURITY AUDIT │ npm audit
│ ↓ pass │
│ BUNDLE SIZE │ bundlesize check
└─────────────────┘
│
▼
Ready for review
No gate can be skipped. If lint fails, fix lint — don't disable the rule.
# .github/workflows/ci.yml
name: CI
on:
pull_request:
branches: [main]
push:
branches: [main]
jobs:
quality:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '22'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Lint
run: npm run lint
- name: Type check
run: npx tsc --noEmit
- name: Test
run: npm test -- --coverage
- name: Build
run: npm run build
- name: Security audit
run: npm audit --audit-level=high
integration:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:16
env:
POSTGRES_DB: testdb
POSTGRES_USER: ci_user
POSTGRES_PASSWORD: ${{ secrets.CI_DB_PASSWORD }}
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '22'
cache: 'npm'
- run: npm ci
- name: Run migrations
run: npx prisma migrate deploy
env:
DATABASE_URL: postgresql://ci_user:${{ secrets.CI_DB_PASSWORD }}@localhost:5432/testdb
- name: Integration tests
run: npm run test:integration
env:
DATABASE_URL: postgresql://ci_user:${{ secrets.CI_DB_PASSWORD }}@localhost:5432/testdb
e2e:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '22'
cache: 'npm'
- run: npm ci
- name: Install Playwright
run: npx playwright install --with-deps chromium
- name: Build
run: npm run build
- name: Run E2E tests
run: npx playwright test
- uses: actions/upload-artifact@v4
if: failure()
with:
name: playwright-report
path: playwright-report/
When CI fails:
CI fails
│
▼
Copy the failure output
│
▼
Feed it to the agent:
"The CI pipeline failed with this error:
[paste specific error]
Fix the issue and verify locally before pushing again."
│
▼
Agent fixes → pushes → CI runs again
Every PR gets a preview deployment for manual testing:
deploy-preview:
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
steps:
- uses: actions/checkout@v4
- name: Deploy preview
run: npx vercel --token=${{ secrets.VERCEL_TOKEN }}
Feature flags decouple deployment from release:
// Simple feature flag pattern
if (featureFlags.isEnabled('new-checkout-flow', { userId })) {
return renderNewCheckout();
}
return renderLegacyCheckout();
PR merged to main
│
▼
Staging deployment (auto)
│ Manual verification
▼
Production deployment (manual trigger)
│
▼
Monitor for errors (15-minute window)
│
├── Errors detected → Rollback
└── Clean → Done
When the pipeline exceeds 10 minutes:
Slow CI pipeline?
├── Cache dependencies
│ └── Use actions/cache or setup-node cache option
├── Run jobs in parallel
│ └── Split lint, typecheck, test, build into separate jobs
├── Only run what changed
│ └── Use path filters to skip unrelated jobs
├── Use matrix builds
│ └── Shard test suites across multiple runners
└── Optimize the test suite
└── Remove slow tests from the critical path
After setting up or modifying CI: