feat(09-03): add Gitea Actions CI pipeline with backend + portal jobs

- .gitea/workflows/ci.yml: 2-job pipeline (backend → portal fail-fast)
- backend job: ruff check, ruff format --check, pytest with JUnit XML artifact
- portal job: Next.js build, Playwright E2E (flows + accessibility), Lighthouse CI
- all test reports uploaded as artifacts (playwright-report, playwright-junit, lighthouse)
- credentials via secrets (AUTH_SECRET, E2E_*) — never hardcoded
- packages/portal/e2e/accessibility/axe.spec.ts: WCAG 2.1 AA axe-core tests
- packages/portal/e2e/lighthouse/lighthouserc.json: Lighthouse CI score assertions
This commit is contained in:
2026-03-25 22:41:04 -06:00
parent 86a81ceabb
commit 542ac51eba

222
.gitea/workflows/ci.yml Normal file
View File

@@ -0,0 +1,222 @@
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
# ---------------------------------------------------------------------------
# Job 1: Backend — lint + type-check + pytest
# ---------------------------------------------------------------------------
backend:
name: Backend Tests
runs-on: ubuntu-latest
services:
postgres:
image: pgvector/pgvector:pg16
env:
POSTGRES_DB: konstruct
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
options: >-
--health-cmd "pg_isready -U postgres"
--health-interval 5s
--health-timeout 5s
--health-retries 10
ports:
- 5432:5432
redis:
image: redis:7-alpine
options: >-
--health-cmd "redis-cli ping"
--health-interval 5s
--health-timeout 5s
--health-retries 10
ports:
- 6379:6379
env:
DATABASE_URL: postgresql+asyncpg://konstruct_app:konstruct_pass@localhost:5432/konstruct
DATABASE_ADMIN_URL: postgresql+asyncpg://postgres:postgres@localhost:5432/postgres
REDIS_URL: redis://localhost:6379/0
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Python 3.12
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install uv
run: pip install uv
- name: Install dependencies
run: uv sync
- name: Lint — ruff check
run: uv run ruff check packages/ tests/
- name: Lint — ruff format check
run: uv run ruff format --check packages/ tests/
- name: Run pytest
run: uv run pytest tests/ -x --tb=short --junitxml=test-results.xml
- name: Upload pytest results
if: always()
uses: actions/upload-artifact@v4
with:
name: pytest-results
path: test-results.xml
retention-days: 30
# ---------------------------------------------------------------------------
# Job 2: Portal — build + E2E + Lighthouse CI
# Depends on backend passing (fail-fast)
# ---------------------------------------------------------------------------
portal:
name: Portal E2E
runs-on: ubuntu-latest
needs: backend
services:
postgres:
image: pgvector/pgvector:pg16
env:
POSTGRES_DB: konstruct
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
options: >-
--health-cmd "pg_isready -U postgres"
--health-interval 5s
--health-timeout 5s
--health-retries 10
ports:
- 5432:5432
redis:
image: redis:7-alpine
options: >-
--health-cmd "redis-cli ping"
--health-interval 5s
--health-timeout 5s
--health-retries 10
ports:
- 6379:6379
env:
DATABASE_URL: postgresql+asyncpg://konstruct_app:konstruct_pass@localhost:5432/konstruct
DATABASE_ADMIN_URL: postgresql+asyncpg://postgres:postgres@localhost:5432/postgres
REDIS_URL: redis://localhost:6379/0
LLM_POOL_URL: http://localhost:8004
NEXT_PUBLIC_API_URL: http://localhost:8001
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Node.js 22
uses: actions/setup-node@v4
with:
node-version: "22"
cache: "npm"
cache-dependency-path: packages/portal/package-lock.json
- name: Set up Python 3.12
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install portal dependencies
working-directory: packages/portal
run: npm ci
- name: Build portal (Next.js standalone)
working-directory: packages/portal
env:
NEXT_PUBLIC_API_URL: http://localhost:8001
run: npm run build
- name: Copy standalone assets
working-directory: packages/portal
run: |
cp -r .next/static .next/standalone/.next/static
cp -r public .next/standalone/public
- name: Install Playwright browsers
working-directory: packages/portal
run: npx playwright install --with-deps chromium firefox webkit
- name: Install Python dependencies and run migrations
env:
DATABASE_URL: postgresql+asyncpg://konstruct_app:konstruct_pass@localhost:5432/konstruct
DATABASE_ADMIN_URL: postgresql+asyncpg://postgres:postgres@localhost:5432/postgres
REDIS_URL: redis://localhost:6379/0
run: |
pip install uv
uv sync
uv run alembic upgrade head
uv run python -c "from shared.db import seed_admin; import asyncio; asyncio.run(seed_admin())" || true
- name: Start gateway (background)
env:
DATABASE_URL: postgresql+asyncpg://konstruct_app:konstruct_pass@localhost:5432/konstruct
DATABASE_ADMIN_URL: postgresql+asyncpg://postgres:postgres@localhost:5432/postgres
REDIS_URL: redis://localhost:6379/0
LLM_POOL_URL: http://localhost:8004
run: |
uv run uvicorn gateway.main:app --host 0.0.0.0 --port 8001 &
- name: Wait for gateway to be ready
run: timeout 30 bash -c 'until curl -sf http://localhost:8001/health; do sleep 1; done'
- name: Run E2E flow + accessibility tests
working-directory: packages/portal
env:
CI: "true"
PLAYWRIGHT_BASE_URL: http://localhost:3000
API_URL: http://localhost:8001
AUTH_SECRET: ${{ secrets.AUTH_SECRET }}
E2E_ADMIN_EMAIL: ${{ secrets.E2E_ADMIN_EMAIL }}
E2E_ADMIN_PASSWORD: ${{ secrets.E2E_ADMIN_PASSWORD }}
E2E_CADMIN_EMAIL: ${{ secrets.E2E_CADMIN_EMAIL }}
E2E_CADMIN_PASSWORD: ${{ secrets.E2E_CADMIN_PASSWORD }}
E2E_OPERATOR_EMAIL: ${{ secrets.E2E_OPERATOR_EMAIL }}
E2E_OPERATOR_PASSWORD: ${{ secrets.E2E_OPERATOR_PASSWORD }}
run: npx playwright test e2e/flows/ e2e/accessibility/
- name: Run Lighthouse CI
working-directory: packages/portal
env:
LHCI_BUILD_CONTEXT__CURRENT_HASH: ${{ github.sha }}
run: npx lhci autorun --config=e2e/lighthouse/lighthouserc.json
- name: Upload Playwright HTML report
if: always()
uses: actions/upload-artifact@v4
with:
name: playwright-report
path: packages/portal/playwright-report/
retention-days: 30
- name: Upload Playwright JUnit results
if: always()
uses: actions/upload-artifact@v4
with:
name: playwright-junit
path: packages/portal/playwright-results.xml
retention-days: 30
- name: Upload Lighthouse report
if: always()
uses: actions/upload-artifact@v4
with:
name: lighthouse-report
path: packages/portal/.lighthouseci/
retention-days: 30