Skip to content

Email infra (Brevo SMTP via nodemailer) + F-2 partial mitigation for issue #27 #57

Email infra (Brevo SMTP via nodemailer) + F-2 partial mitigation for issue #27

Email infra (Brevo SMTP via nodemailer) + F-2 partial mitigation for issue #27 #57

Workflow file for this run

name: CI
on:
pull_request:
push:
branches:
- main
- dev
workflow_dispatch:
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true
jobs:
validate:
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Check out repository
uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
cache-dependency-path: |
package-lock.json
dashboard/package-lock.json
website/package-lock.json
- name: Install root dependencies
run: npm ci
- name: Install dashboard dependencies
run: npm --prefix dashboard ci
- name: Install website dependencies
run: npm --prefix website ci
- name: Type check (backend)
run: npx tsc --noEmit
- name: Lint (backend)
run: npm run lint --if-present
- name: Run tests (backend)
run: npm test
- name: Type check (dashboard)
run: npm --prefix dashboard run typecheck
- name: Lint (dashboard)
run: npm --prefix dashboard run lint
- name: Run tests (dashboard)
run: npm --prefix dashboard test
- name: Dep-trail audit (DP6 advisory)
run: ./scripts/check-dep-trail.sh advisory
- name: Build backend, dashboard, and docs
run: npm run build:all
e2e:
name: Playwright (dashboard happy path)
runs-on: ubuntu-latest
needs: validate
timeout-minutes: 20
services:
postgres:
image: postgres:16-alpine
env:
POSTGRES_DB: zeroauth_e2e
POSTGRES_USER: zeroauth
POSTGRES_PASSWORD: zeroauth-e2e
ports:
- 5432:5432
options: >-
--health-cmd "pg_isready -U zeroauth -d zeroauth_e2e"
--health-interval 10s
--health-timeout 5s
--health-retries 10
# NOTE: NODE_ENV is deliberately NOT set at the job level — setting
# NODE_ENV=production makes `npm ci` skip devDependencies (typescript,
# vitest, eslint, etc.), and the build then can't find tsc. We pass
# the server-runtime env only in the "Start backend" step below.
env:
E2E_BASE_URL: http://localhost:3000
steps:
- name: Check out repository
uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
cache-dependency-path: |
package-lock.json
dashboard/package-lock.json
website/package-lock.json
- name: Install root dependencies
run: npm ci
- name: Install dashboard dependencies
run: npm --prefix dashboard ci
- name: Install website dependencies
run: npm --prefix website ci
- name: Build everything
run: npm run build:all
- name: Cache Playwright browsers
uses: actions/cache@v4
with:
path: ~/.cache/ms-playwright
key: ${{ runner.os }}-playwright-${{ hashFiles('dashboard/package-lock.json') }}
- name: Install Playwright browser (chromium)
run: npm --prefix dashboard run e2e:install
- name: Start backend (background)
env:
NODE_ENV: production
PORT: 3000
API_BASE_URL: http://localhost:3000
CORS_ORIGINS: http://localhost:3000
TRUST_PROXY: 'false'
JWT_SECRET: ci-e2e-jwt-secret-not-used-in-production-environments-only
SESSION_SECRET: ci-e2e-session-secret-not-used-in-production-environments-only
ADMIN_API_KEY: ci-e2e-admin-key
ENABLE_DEMO_AUTH: 'false'
LOG_LEVEL: warn
BLOCKCHAIN_RPC_URL: https://sepolia.base.org
BLOCKCHAIN_CHAIN_ID: '84532'
BLOCKCHAIN_PRIVATE_KEY: ''
DID_REGISTRY_ADDRESS: ''
VERIFIER_CONTRACT_ADDRESS: ''
VERIFY_ON_CHAIN: 'false'
ZKP_WASM_PATH: circuits/build/identity_proof_js/identity_proof.wasm
ZKP_ZKEY_PATH: circuits/build/circuit_final.zkey
ZKP_VKEY_PATH: circuits/build/verification_key.json
USE_REDIS_SESSIONS: 'false'
REDIS_URL: redis://localhost:6379
POSTGRES_HOST: localhost
POSTGRES_PORT: '5432'
POSTGRES_DB: zeroauth_e2e
POSTGRES_USER: zeroauth
POSTGRES_PASSWORD: zeroauth-e2e
run: |
node dist/server.js > /tmp/server.log 2>&1 &
echo $! > /tmp/server.pid
# Wait for /api/health to respond
for i in $(seq 1 60); do
if curl -sf http://localhost:3000/api/health > /dev/null; then
echo "server up after ${i}s"
break
fi
sleep 1
done
curl -sf http://localhost:3000/api/health || (cat /tmp/server.log && exit 1)
- name: Run Playwright tests
run: npm --prefix dashboard run e2e
- name: Stop backend
if: always()
run: |
if [ -f /tmp/server.pid ]; then
kill "$(cat /tmp/server.pid)" 2>/dev/null || true
fi
- name: Upload server log on failure
if: failure()
uses: actions/upload-artifact@v4
with:
name: server-log
path: /tmp/server.log
if-no-files-found: ignore
- name: Upload Playwright report
if: always()
uses: actions/upload-artifact@v4
with:
name: playwright-report
path: dashboard/playwright-report
retention-days: 14
if-no-files-found: ignore