name: SME demo end-to-end (issue #805)

# Playwright spec for the FIRST SME tenant happy path on a healthy
# otech (parent epic openova-io/openova#795). Lives next to
# .github/workflows/cosmetic-guards.yaml — same dev-server pattern,
# but tagged @sme-demo so the two suites run independently.
#
# Mock-mode today: every back-end surface (tenant discovery,
# /api/v1/sme/users, /api/v1/sme/tenants, /api/v1/sme/billing/ledger,
# WordPress/OpenClaw/Webmail placeholders) is stubbed via page.route
# (see e2e/lib/sme-fixtures.ts). The screenshot evidence the DoD
# checklist requires is captured AT CI time and uploaded as an
# artefact.
#
# Live-mode follow-up: once #804 (tenant provisioning pipeline) lands
# and a fresh otech is provisioned, this workflow gets a sibling
# matrix entry that opts out of the mocks and dials the real
# console.acme.<otech-fqdn>.
#
# Per docs/INVIOLABLE-PRINCIPLES.md #4a (GitHub Actions is the only
# build path), this workflow does NOT build any container images —
# it only runs the Playwright suite against a freshly-installed dev
# tree.

on:
  push:
    branches: [main]
    paths:
      - 'products/catalyst/bootstrap/ui/**'
      - '.github/workflows/sme-demo-e2e.yaml'
  pull_request:
    paths:
      - 'products/catalyst/bootstrap/ui/**'
      - '.github/workflows/sme-demo-e2e.yaml'
  workflow_dispatch:

jobs:
  sme-demo:
    name: SME demo Playwright happy path
    runs-on: ubuntu-latest
    timeout-minutes: 15
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Setup Node
        uses: actions/setup-node@v4
        with:
          node-version: '22'
          cache: 'npm'
          cache-dependency-path: products/catalyst/bootstrap/ui/package-lock.json

      - name: Install Catalyst UI dependencies
        working-directory: products/catalyst/bootstrap/ui
        run: npm ci

      - name: Install Playwright browser (chromium)
        working-directory: products/catalyst/bootstrap/ui
        run: npx playwright install --with-deps chromium

      - name: Boot Catalyst UI in sovereign mode
        working-directory: products/catalyst/bootstrap/ui
        env:
          # Force sovereign mode so SovereignConsoleLayout's auth gate
          # has a non-null sovereignFQDN to dispatch off; without this,
          # localhost falls into catalyst-zero mode and the /console/*
          # routes hang on `sov-auth-loading`.
          VITE_CATALYST_MODE: sovereign
          VITE_SOVEREIGN_FQDN: acme.otech.example
          HOST: 0.0.0.0
        run: |
          nohup npm run dev > /tmp/catalyst-ui-dev.log 2>&1 &
          echo $! > /tmp/catalyst-ui.pid

      - name: Wait for Catalyst UI to be ready
        run: |
          for i in $(seq 1 60); do
            if curl -sf -o /dev/null http://localhost:5173/wizard; then
              echo "UI ready after ${i}s"
              exit 0
            fi
            sleep 1
          done
          echo "UI failed to start in 60s — log follows:"
          cat /tmp/catalyst-ui-dev.log || true
          exit 1

      - name: Run SME demo Playwright spec
        working-directory: products/catalyst/bootstrap/ui
        env:
          PLAYWRIGHT_HOST: http://localhost:5173
          PLAYWRIGHT_BASEPATH: /
        run: npx playwright test e2e/sme-demo.spec.ts --grep "@sme-demo" --reporter=list

      - name: Stop Catalyst UI
        if: always()
        run: |
          if [ -f /tmp/catalyst-ui.pid ]; then
            kill "$(cat /tmp/catalyst-ui.pid)" 2>/dev/null || true
          fi

      - name: Upload screenshot evidence
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: sme-demo-screenshots
          path: products/catalyst/bootstrap/ui/e2e/screenshots/805-*
          retention-days: 30

      - name: Upload Playwright report (failure only)
        if: failure()
        uses: actions/upload-artifact@v4
        with:
          name: sme-demo-report
          path: |
            products/catalyst/bootstrap/ui/playwright-report/
            products/catalyst/bootstrap/ui/test-results/
          retention-days: 7
