name: Performance Tests on: # Run on schedule (weekly on Sunday at midnight) schedule: - cron: '0 0 * * 0' # Manual trigger workflow_dispatch: # Run on PRs to main (optional, can be heavy) pull_request: branches: [main] paths: - 'frontend/**' - 'backend/**' env: NODE_VERSION: '20.x' jobs: # ========================================== # Lighthouse Performance Audit # ========================================== lighthouse: name: Lighthouse CI runs-on: ubuntu-latest defaults: run: working-directory: frontend steps: - name: Checkout code uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} cache: 'npm' cache-dependency-path: frontend/package-lock.json - name: Install dependencies run: npm ci - name: Build production bundle run: npm run build - name: Install Lighthouse CI run: npm install -g @lhci/cli@0.13.x - name: Run Lighthouse CI run: lhci autorun env: LHCI_GITHUB_APP_TOKEN: ${{ secrets.LHCI_GITHUB_APP_TOKEN }} - name: Upload Lighthouse results uses: actions/upload-artifact@v4 if: always() with: name: lighthouse-results path: .lighthouseci retention-days: 14 # ========================================== # Bundle Size Analysis # ========================================== bundle-analysis: name: Bundle Size Analysis runs-on: ubuntu-latest defaults: run: working-directory: frontend steps: - name: Checkout code uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} cache: 'npm' cache-dependency-path: frontend/package-lock.json - name: Install dependencies run: npm ci - name: Build and analyze bundle run: | npm run build echo "## Bundle Analysis" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "### Chunk Sizes" >> $GITHUB_STEP_SUMMARY echo "\`\`\`" >> $GITHUB_STEP_SUMMARY du -sh dist/assets/*.js | sort -h >> $GITHUB_STEP_SUMMARY echo "\`\`\`" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "### Total Size" >> $GITHUB_STEP_SUMMARY echo "\`\`\`" >> $GITHUB_STEP_SUMMARY du -sh dist >> $GITHUB_STEP_SUMMARY echo "\`\`\`" >> $GITHUB_STEP_SUMMARY - name: Check bundle size limits run: | # Main bundle should be under 500KB MAIN_SIZE=$(du -sb dist/assets/index*.js | cut -f1) if [ "$MAIN_SIZE" -gt 512000 ]; then echo "::warning::Main bundle exceeds 500KB limit" fi # Total JS should be under 2MB TOTAL_JS=$(du -sb dist/assets/*.js | awk '{sum+=$1} END {print sum}') if [ "$TOTAL_JS" -gt 2097152 ]; then echo "::warning::Total JS bundle exceeds 2MB limit" fi # Report sizes echo "Main bundle: $((MAIN_SIZE / 1024))KB" echo "Total JS: $((TOTAL_JS / 1024))KB" # ========================================== # k6 Load Tests # ========================================== load-tests: name: k6 Load Tests runs-on: ubuntu-latest if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' services: postgres: image: postgres:16 env: POSTGRES_DB: erp_generic_test POSTGRES_USER: erp_admin POSTGRES_PASSWORD: test_secret_2024 ports: - 5432:5432 options: >- --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 steps: - name: Checkout code uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} cache: 'npm' cache-dependency-path: backend/package-lock.json - name: Install k6 run: | sudo gpg -k sudo gpg --no-default-keyring --keyring /usr/share/keyrings/k6-archive-keyring.gpg --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys C5AD17C747E3415A3642D57D77C6C491D6AC1D69 echo "deb [signed-by=/usr/share/keyrings/k6-archive-keyring.gpg] https://dl.k6.io/deb stable main" | sudo tee /etc/apt/sources.list.d/k6.list sudo apt-get update sudo apt-get install k6 - name: Install backend dependencies working-directory: backend run: npm ci - name: Setup test database run: | cd database chmod +x scripts/create-test-database.sh TEST_DB_NAME=erp_generic_test \ POSTGRES_USER=erp_admin \ POSTGRES_PASSWORD=test_secret_2024 \ POSTGRES_HOST=localhost \ POSTGRES_PORT=5432 \ ./scripts/create-test-database.sh - name: Start backend server working-directory: backend run: | npm run build npm start & sleep 10 env: NODE_ENV: test DB_HOST: localhost DB_PORT: 5432 DB_NAME: erp_generic_test DB_USER: erp_admin DB_PASSWORD: test_secret_2024 JWT_SECRET: test-secret-key PORT: 4000 - name: Run k6 smoke test run: k6 run backend/tests/performance/load-test.js --vus 1 --duration 30s env: API_BASE_URL: http://localhost:4000 - name: Upload k6 results uses: actions/upload-artifact@v4 if: always() with: name: k6-results path: backend/tests/performance/results/ retention-days: 14 # ========================================== # Performance Summary # ========================================== performance-summary: name: Performance Summary runs-on: ubuntu-latest needs: [lighthouse, bundle-analysis] if: always() steps: - name: Download Lighthouse results uses: actions/download-artifact@v4 with: name: lighthouse-results path: lighthouse-results continue-on-error: true - name: Generate summary run: | echo "# Performance Test Results" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "## Status" >> $GITHUB_STEP_SUMMARY echo "- Lighthouse: ${{ needs.lighthouse.result }}" >> $GITHUB_STEP_SUMMARY echo "- Bundle Analysis: ${{ needs.bundle-analysis.result }}" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "See individual job artifacts for detailed results." >> $GITHUB_STEP_SUMMARY