Skip to content

πŸ›‘οΈ Sentinel: [security improvement] Dual Rate-Limiting #405

πŸ›‘οΈ Sentinel: [security improvement] Dual Rate-Limiting

πŸ›‘οΈ Sentinel: [security improvement] Dual Rate-Limiting #405

Workflow file for this run

name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
quality:
name: Quality Gates
runs-on: ubuntu-latest
services:
postgres:
image: postgres:16
env:
POSTGRES_USER: test
POSTGRES_PASSWORD: test
POSTGRES_DB: amph_v2_test
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
env:
DATABASE_URL: postgresql://test:test@localhost:5432/amph_v2_test
JWT_SECRET: test-secret-min-32-characters-long-aaaaaaaa
NODE_ENV: test
steps:
- uses: actions/checkout@v7
with:
# gitleaks diffs the PR commit against its parent (`git log <sha>^..<sha>`),
# which needs that parent to exist locally. The default shallow
# (depth-1) checkout omits it, so gitleaks fails with "unknown
# revision" on every PR regardless of what changed.
fetch-depth: 0
- uses: pnpm/action-setup@v6
- uses: actions/setup-node@v7
with:
node-version: 22
cache: pnpm
- run: pnpm install --frozen-lockfile
# Prisma 7 removed @prisma/client's install-time auto-generate, so the
# client must be generated before anything typechecks against it.
- name: Generate Prisma client
run: pnpm prisma generate
- name: TypeScript check
run: pnpm typecheck
- name: Lint (includes no-ai-slop)
run: pnpm lint
- name: Secret scan
uses: gitleaks/gitleaks-action@v3
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Prisma schema validation
run: |
pnpm prisma format --check
pnpm prisma validate
- name: Apply migrations
run: pnpm prisma migrate deploy
- name: Unit + integration tests
# Not `pnpm test -- --coverage`: pnpm forwards the literal `--` to
# vitest, which then reads `--coverage` as a filename filter and
# emits no coverage output at all.
run: pnpm test:coverage
- name: Coverage threshold check
run: |
node scripts/check-coverage.js
- name: Build
run: pnpm build
# Sprint 11 / STORY-048 β€” upload source maps to Sentry
- name: Upload Sentry source maps
if: env.SENTRY_AUTH_TOKEN != ''
env:
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }}
run: pnpm sentry:sourcemaps
e2e:
name: E2E Tests
runs-on: ubuntu-latest
needs: quality
# The Playwright suite drives the real app (signup β†’ sign-in β†’ courses β†’
# pricing), so it needs a reachable Postgres with migrations + seed data
# and the same runtime env the dev server expects.
services:
postgres:
image: postgres:16
env:
POSTGRES_USER: test
POSTGRES_PASSWORD: test
POSTGRES_DB: amph_v2_e2e
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
env:
DATABASE_URL: postgresql://test:test@localhost:5432/amph_v2_e2e
JWT_SECRET: test-secret-min-32-characters-long-aaaaaaaa
# The seed fails loudly if these are unset (C5 hardening). CI-only test
# credentials, never used outside this ephemeral Postgres.
ADMIN_EMAIL: admin@ci.local
ADMIN_PASSWORD: ci-test-password-not-secret
steps:
- uses: actions/checkout@v7
- uses: pnpm/action-setup@v6
- uses: actions/setup-node@v7
with:
node-version: 22
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm prisma generate
- run: pnpm prisma migrate deploy
- name: Seed database
run: pnpm exec tsx prisma/seed.ts
- run: pnpm exec playwright install --with-deps chromium
- run: pnpm build
- run: pnpm test:e2e
- uses: actions/upload-artifact@v7
if: always()
with:
name: playwright-report
path: playwright-report/
retention-days: 7
lighthouse:
name: Lighthouse CI
runs-on: ubuntu-latest
needs: quality
# Lighthouse boots the production server and audits /pricing, which
# queries the database β€” so it needs the same Postgres + seed as e2e.
services:
postgres:
image: postgres:16
env:
POSTGRES_USER: test
POSTGRES_PASSWORD: test
POSTGRES_DB: amph_v2_lhci
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
env:
DATABASE_URL: postgresql://test:test@localhost:5432/amph_v2_lhci
JWT_SECRET: test-secret-min-32-characters-long-aaaaaaaa
# The seed fails loudly if these are unset (C5 hardening). CI-only test
# credentials, never used outside this ephemeral Postgres.
ADMIN_EMAIL: admin@ci.local
ADMIN_PASSWORD: ci-test-password-not-secret
steps:
- uses: actions/checkout@v7
- uses: pnpm/action-setup@v6
- uses: actions/setup-node@v7
with:
node-version: 22
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm prisma generate
- run: pnpm prisma migrate deploy
- name: Seed database
run: pnpm exec tsx prisma/seed.ts
- run: pnpm build
- name: Run Lighthouse CI
uses: treosh/lighthouse-ci-action@v12
with:
configPath: .lighthouserc.json
uploadArtifacts: true