ci: self-skip schema-parity + verify-non-root so they're safe to require (#1237) #742
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: frontend-e2e | |
| # Runs only when a PR carries the `ui` label. Adds a browser test layer for | |
| # UI changes; gated to avoid spending ~5 min of CI on every backend PR. | |
| # Trigger manually by adding the `ui` label to a PR. | |
| on: | |
| pull_request: | |
| types: [opened, synchronize, reopened, labeled] | |
| jobs: | |
| e2e: | |
| if: contains(github.event.pull_request.labels.*.name, 'ui') | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 25 | |
| defaults: | |
| run: | |
| working-directory: src/frontend | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: actions/setup-node@v6 | |
| with: | |
| node-version: '20' | |
| cache: 'npm' | |
| cache-dependency-path: src/frontend/package-lock.json | |
| - name: Install npm dependencies | |
| run: npm ci | |
| - name: Cache Playwright browsers | |
| uses: actions/cache@v5 | |
| with: | |
| path: ~/.cache/ms-playwright | |
| key: playwright-${{ runner.os }}-${{ hashFiles('src/frontend/package-lock.json') }} | |
| - name: Install Playwright browser | |
| run: npx playwright install --with-deps chromium | |
| - name: Generate CI admin password | |
| # I-01 fix (cso-diff-2026-05-17): replace the previous hardcoded | |
| # `CiTestPassword!1` fallback with a per-run random value so the | |
| # repo never publishes a default admin credential, even one only | |
| # reachable from the runner sandbox. Honours an explicit | |
| # E2E_ADMIN_PASSWORD secret override when set. The literal `Aa1!` | |
| # suffix guarantees OWASP ASVS 2.1 complexity classes on the | |
| # random branch (upper / lower / digit / special) — `tr -d` | |
| # strips base64 chars that would break form-encoded curl bodies | |
| # later. | |
| env: | |
| OVERRIDE: ${{ secrets.E2E_ADMIN_PASSWORD }} | |
| run: | | |
| set -euo pipefail | |
| if [ -n "${OVERRIDE:-}" ]; then | |
| PASS="$OVERRIDE" | |
| else | |
| PASS="$(openssl rand -base64 24 | tr -d '/+=\n')Aa1!" | |
| fi | |
| echo "::add-mask::$PASS" | |
| echo "ADMIN_PASSWORD=$PASS" >> "$GITHUB_ENV" | |
| - name: Start Trinity stack | |
| working-directory: ${{ github.workspace }} | |
| env: | |
| # ADMIN_PASSWORD is inherited from GITHUB_ENV (see the | |
| # "Generate CI admin password" step above). | |
| ANTHROPIC_API_KEY: ${{ secrets.E2E_ANTHROPIC_API_KEY || 'placeholder' }} | |
| run: | | |
| # Generate the minimum .env needed to boot. Real secrets are not | |
| # required for e2e — login uses ADMIN_PASSWORD only. | |
| cp .env.example .env | |
| echo "ADMIN_PASSWORD=$ADMIN_PASSWORD" >> .env | |
| echo "ANTHROPIC_API_KEY=$ANTHROPIC_API_KEY" >> .env | |
| echo "SECRET_KEY=$(openssl rand -hex 32)" >> .env | |
| ./scripts/deploy/start.sh | |
| - name: Wait for backend health | |
| run: | | |
| for i in {1..60}; do | |
| if curl -fsS http://localhost:8000/health >/dev/null 2>&1; then | |
| echo "backend healthy"; exit 0 | |
| fi | |
| sleep 2 | |
| done | |
| echo "backend never became healthy"; exit 1 | |
| # Issue #874 regression guards (`verify-non-root`, | |
| # `verify-prod-frontend-uid`) moved to .github/workflows/container-security.yml | |
| # so they run unconditionally on infrastructure PRs (this workflow | |
| # is `ui`-label gated and would otherwise skip them on backend PRs). | |
| - name: Skip first-time setup wizard | |
| working-directory: ${{ github.workspace }} | |
| run: | | |
| # On a fresh DB the admin user is bootstrapped from ADMIN_PASSWORD, | |
| # but `setup_completed` stays false (the backfill migration runs | |
| # before admin creation). Without this flag the frontend redirects | |
| # every route to /setup. Mark setup complete directly. | |
| docker exec trinity-backend python3 -c "from database import db; db.set_setting('setup_completed', 'true'); print('setup_completed=true')" | |
| - name: Run Playwright smoke tests | |
| env: | |
| # ADMIN_PASSWORD is inherited from GITHUB_ENV (see the "Generate | |
| # CI admin password" step). | |
| E2E_BASE_URL: http://localhost | |
| # Only @smoke-tagged specs run in CI. @visual / @interactive specs | |
| # are local-only until their flake/baseline story is sorted (#596). | |
| run: npm run test:e2e:smoke | |
| - name: Collect Trinity logs on failure | |
| if: failure() | |
| working-directory: ${{ github.workspace }} | |
| run: | | |
| docker compose logs --no-color --tail=200 backend frontend mcp-server > trinity-logs.txt || true | |
| - name: Upload Playwright report | |
| if: always() | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: playwright-report | |
| path: src/frontend/e2e/playwright-report/ | |
| retention-days: 14 | |
| - name: Upload failure artifacts | |
| if: failure() | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: e2e-failure-artifacts | |
| path: | | |
| src/frontend/e2e/test-results/ | |
| trinity-logs.txt | |
| retention-days: 14 |