# .gitea/workflows/lighthouse-ci.yml # Lighthouse CI for performance and accessibility testing of the StellaOps Web UI name: Lighthouse CI on: push: branches: [main] paths: - 'src/Web/StellaOps.Web/**' - '.gitea/workflows/lighthouse-ci.yml' pull_request: branches: [main, develop] paths: - 'src/Web/StellaOps.Web/**' schedule: # Run weekly on Sunday at 2 AM UTC - cron: '0 2 * * 0' workflow_dispatch: env: NODE_VERSION: '20' LHCI_BUILD_CONTEXT__CURRENT_BRANCH: ${{ github.head_ref || github.ref_name }} LHCI_BUILD_CONTEXT__COMMIT_SHA: ${{ github.sha }} jobs: lighthouse: name: Lighthouse Audit runs-on: ubuntu-22.04 defaults: run: working-directory: src/Web/StellaOps.Web steps: - name: Checkout repository uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} cache: 'npm' cache-dependency-path: src/Web/StellaOps.Web/package-lock.json - name: Install dependencies run: npm ci - name: Build production bundle run: npm run build -- --configuration production - name: Install Lighthouse CI run: npm install -g @lhci/cli@0.13.x - name: Run Lighthouse CI run: | lhci autorun \ --collect.staticDistDir=./dist/stella-ops-web/browser \ --collect.numberOfRuns=3 \ --assert.preset=lighthouse:recommended \ --assert.assertions.categories:performance=off \ --assert.assertions.categories:accessibility=off \ --upload.target=filesystem \ --upload.outputDir=./lighthouse-results - name: Evaluate Lighthouse Results id: lhci-results run: | # Parse the latest Lighthouse report REPORT=$(ls -t lighthouse-results/*.json | head -1) if [ -f "$REPORT" ]; then PERF=$(jq '.categories.performance.score * 100' "$REPORT" | cut -d. -f1) A11Y=$(jq '.categories.accessibility.score * 100' "$REPORT" | cut -d. -f1) BP=$(jq '.categories["best-practices"].score * 100' "$REPORT" | cut -d. -f1) SEO=$(jq '.categories.seo.score * 100' "$REPORT" | cut -d. -f1) echo "performance=$PERF" >> $GITHUB_OUTPUT echo "accessibility=$A11Y" >> $GITHUB_OUTPUT echo "best-practices=$BP" >> $GITHUB_OUTPUT echo "seo=$SEO" >> $GITHUB_OUTPUT echo "## Lighthouse Results" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "| Category | Score | Threshold | Status |" >> $GITHUB_STEP_SUMMARY echo "|----------|-------|-----------|--------|" >> $GITHUB_STEP_SUMMARY # Performance: target >= 90 if [ "$PERF" -ge 90 ]; then echo "| Performance | $PERF | >= 90 | :white_check_mark: |" >> $GITHUB_STEP_SUMMARY else echo "| Performance | $PERF | >= 90 | :warning: |" >> $GITHUB_STEP_SUMMARY fi # Accessibility: target >= 95 if [ "$A11Y" -ge 95 ]; then echo "| Accessibility | $A11Y | >= 95 | :white_check_mark: |" >> $GITHUB_STEP_SUMMARY else echo "| Accessibility | $A11Y | >= 95 | :x: |" >> $GITHUB_STEP_SUMMARY fi # Best Practices: target >= 90 if [ "$BP" -ge 90 ]; then echo "| Best Practices | $BP | >= 90 | :white_check_mark: |" >> $GITHUB_STEP_SUMMARY else echo "| Best Practices | $BP | >= 90 | :warning: |" >> $GITHUB_STEP_SUMMARY fi # SEO: target >= 90 if [ "$SEO" -ge 90 ]; then echo "| SEO | $SEO | >= 90 | :white_check_mark: |" >> $GITHUB_STEP_SUMMARY else echo "| SEO | $SEO | >= 90 | :warning: |" >> $GITHUB_STEP_SUMMARY fi fi - name: Check Quality Gates run: | PERF=${{ steps.lhci-results.outputs.performance }} A11Y=${{ steps.lhci-results.outputs.accessibility }} FAILED=0 # Performance gate (warning only, not blocking) if [ "$PERF" -lt 90 ]; then echo "::warning::Performance score ($PERF) is below target (90)" fi # Accessibility gate (blocking) if [ "$A11Y" -lt 95 ]; then echo "::error::Accessibility score ($A11Y) is below required threshold (95)" FAILED=1 fi if [ "$FAILED" -eq 1 ]; then exit 1 fi - name: Upload Lighthouse Reports uses: actions/upload-artifact@v4 if: always() with: name: lighthouse-reports path: src/Web/StellaOps.Web/lighthouse-results/ retention-days: 30 axe-accessibility: name: Axe Accessibility Audit runs-on: ubuntu-22.04 defaults: run: working-directory: src/Web/StellaOps.Web steps: - name: Checkout repository uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} cache: 'npm' cache-dependency-path: src/Web/StellaOps.Web/package-lock.json - name: Install dependencies run: npm ci - name: Install Playwright browsers run: npx playwright install --with-deps chromium - name: Build production bundle run: npm run build -- --configuration production - name: Start preview server run: | npx serve -s dist/stella-ops-web/browser -l 4200 & sleep 5 - name: Run Axe accessibility tests run: | npm run test:a11y || true - name: Upload Axe results uses: actions/upload-artifact@v4 if: always() with: name: axe-accessibility-results path: src/Web/StellaOps.Web/test-results/ retention-days: 30