Migrate to Vite 6 + Comprehensive Testing Infrastructure (#27) #152
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: CI Pipeline (Build → Test BE/FE in Parallel) | |
| on: | |
| push: | |
| pull_request: | |
| workflow_dispatch: | |
| jobs: | |
| # ============================================ | |
| # STAGE 1: DETECT CHANGES | |
| # ============================================ | |
| detect-changes: | |
| name: Detect Changed Files | |
| runs-on: ubuntu-latest | |
| outputs: | |
| backend: ${{ steps.filter.outputs.backend }} | |
| frontend: ${{ steps.filter.outputs.frontend }} | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: dorny/paths-filter@v3 | |
| id: filter | |
| with: | |
| filters: | | |
| backend: | |
| - 'src/**' | |
| - 'pom.xml' | |
| - 'docker-compose.yml' | |
| - '.github/workflows/**' | |
| frontend: | |
| - 'coupon-system-frontend/**' | |
| - '!coupon-system-frontend/node_modules/**' | |
| - '.github/workflows/**' | |
| # ============================================ | |
| # STAGE 2: BUILD | |
| # ============================================ | |
| build-backend: | |
| name: Build Backend | |
| runs-on: ubuntu-latest | |
| needs: detect-changes | |
| if: needs.detect-changes.outputs.backend == 'true' | |
| env: | |
| DB_URL: jdbc:postgresql://localhost:5432/couponsystem | |
| DB_USER: testuser | |
| DB_PASSWORD: test_db_password_ci_123 | |
| POSTGRES_PASSWORD: test_postgres_password_ci_123 | |
| ADMIN_EMAIL: admin@admin.com | |
| ADMIN_PASSWORD: $2b$14$8sxQJWhyKIFiSbgX75YBqexuY8oz17Q.nDSqgA3YDTTEddj/icEAO | |
| JWT_SECRET: test_jwt_secret_key_for_ci_environments_only_do_not_use_in_production | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Set up JDK 25 | |
| uses: actions/setup-java@v5 | |
| with: | |
| java-version: '25' | |
| distribution: 'temurin' | |
| cache: 'maven' | |
| - name: Start PostgreSQL | |
| run: | | |
| docker compose up -d postgres | |
| echo "Waiting for PostgreSQL to be healthy..." | |
| for i in {1..40}; do | |
| if docker compose ps postgres | grep -q "healthy"; then | |
| echo "PostgreSQL is ready!" | |
| exit 0 | |
| fi | |
| echo "Waiting... ($i/40)" | |
| sleep 3 | |
| done | |
| echo "Timeout waiting for PostgreSQL" | |
| docker compose logs postgres | |
| exit 1 | |
| - name: Build with Maven (skip tests) | |
| run: mvn -B package -DskipTests --file pom.xml | |
| - name: Upload backend artifact | |
| uses: actions/upload-artifact@v6 | |
| with: | |
| name: backend-build | |
| path: target/*.jar | |
| retention-days: 1 | |
| - name: Cleanup | |
| if: always() | |
| run: docker compose down -v | |
| build-frontend: | |
| name: Build Frontend | |
| runs-on: ubuntu-latest | |
| needs: detect-changes | |
| if: needs.detect-changes.outputs.frontend == 'true' | |
| defaults: | |
| run: | |
| working-directory: coupon-system-frontend | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Set up Node.js 20 | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: '20' | |
| cache: 'npm' | |
| cache-dependency-path: coupon-system-frontend/package-lock.json | |
| - name: Install dependencies | |
| run: npm ci | |
| - name: Build frontend | |
| run: npm run build | |
| - name: Upload frontend build artifact | |
| uses: actions/upload-artifact@v6 | |
| with: | |
| name: frontend-build | |
| path: coupon-system-frontend/dist | |
| retention-days: 1 | |
| # ============================================ | |
| # STAGE 3: TEST (Parallel Execution) | |
| # ============================================ | |
| test-backend: | |
| name: Test Backend (678 tests) | |
| runs-on: ubuntu-latest | |
| needs: [detect-changes, build-backend] | |
| if: needs.detect-changes.outputs.backend == 'true' | |
| env: | |
| DB_URL: jdbc:postgresql://localhost:5432/couponsystem | |
| DB_USER: testuser | |
| DB_PASSWORD: test_db_password_ci_123 | |
| POSTGRES_PASSWORD: test_postgres_password_ci_123 | |
| ADMIN_EMAIL: admin@admin.com | |
| ADMIN_PASSWORD: $2b$14$8sxQJWhyKIFiSbgX75YBqexuY8oz17Q.nDSqgA3YDTTEddj/icEAO | |
| JWT_SECRET: test_jwt_secret_key_for_ci_environments_only_do_not_use_in_production | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Set up JDK 25 | |
| uses: actions/setup-java@v5 | |
| with: | |
| java-version: '25' | |
| distribution: 'temurin' | |
| cache: 'maven' | |
| - name: Start PostgreSQL | |
| run: | | |
| docker compose up -d postgres | |
| echo "Waiting for PostgreSQL to be healthy..." | |
| for i in {1..40}; do | |
| if docker compose ps postgres | grep -q "healthy"; then | |
| echo "PostgreSQL is ready!" | |
| exit 0 | |
| fi | |
| echo "Waiting... ($i/40)" | |
| sleep 3 | |
| done | |
| echo "Timeout waiting for PostgreSQL" | |
| docker compose logs postgres | |
| exit 1 | |
| - name: Run backend tests with coverage | |
| run: mvn test jacoco:report | |
| - name: Upload backend coverage report | |
| uses: actions/upload-artifact@v6 | |
| with: | |
| name: backend-coverage-report | |
| path: target/site/jacoco/ | |
| - name: Cleanup | |
| if: always() | |
| run: docker compose down -v | |
| test-frontend: | |
| name: Test Frontend (399 tests) | |
| runs-on: ubuntu-latest | |
| needs: [detect-changes, build-frontend] | |
| if: needs.detect-changes.outputs.frontend == 'true' | |
| defaults: | |
| run: | |
| working-directory: coupon-system-frontend | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Set up Node.js 20 | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: '20' | |
| cache: 'npm' | |
| cache-dependency-path: coupon-system-frontend/package-lock.json | |
| - name: Install dependencies | |
| run: npm ci | |
| - name: Run frontend tests | |
| run: npm test -- --run --reporter=verbose | |
| - name: Generate frontend coverage report | |
| if: always() | |
| continue-on-error: true | |
| run: npm run test:coverage || true | |
| - name: Upload frontend coverage report | |
| if: always() | |
| uses: actions/upload-artifact@v6 | |
| with: | |
| name: frontend-coverage-report | |
| path: coupon-system-frontend/coverage/ | |
| continue-on-error: true | |
| # ============================================ | |
| # STAGE 4: SECURITY SCAN (Main branch only) | |
| # ============================================ | |
| security-scan: | |
| name: OWASP Security Scan | |
| runs-on: ubuntu-latest | |
| needs: [test-backend] | |
| if: github.ref == 'refs/heads/main' && needs.detect-changes.outputs.backend == 'true' | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Set up JDK 25 | |
| uses: actions/setup-java@v5 | |
| with: | |
| java-version: '25' | |
| distribution: 'temurin' | |
| cache: 'maven' | |
| - name: Free up disk space | |
| run: | | |
| sudo rm -rf /tmp/* | |
| sudo apt-get clean | |
| sudo rm -rf /usr/share/dotnet | |
| sudo rm -rf /opt/ghc | |
| sudo rm -rf /usr/local/share/boost | |
| df -h | |
| - name: Cache OWASP Dependency-Check data | |
| uses: actions/cache@v5 | |
| with: | |
| path: dependency-check-data | |
| key: ${{ runner.os }}-owasp-data-v2-${{ hashFiles('**/pom.xml') }} | |
| restore-keys: | | |
| ${{ runner.os }}-owasp-data-v2- | |
| ${{ runner.os }}-owasp-data- | |
| - name: OWASP Dependency Check | |
| continue-on-error: true | |
| run: | | |
| mvn dependency-check:check \ | |
| -Dowasp.skip=false \ | |
| -Ddata.directory=${{ github.workspace }}/dependency-check-data | |
| env: | |
| NVD_API_KEY: ${{ secrets.NVD_API_KEY }} | |
| - name: Upload OWASP report | |
| uses: actions/upload-artifact@v6 | |
| if: always() | |
| with: | |
| name: owasp-report | |
| path: target/dependency-check-report.html | |
| # ============================================ | |
| # STAGE 5: SUMMARY | |
| # ============================================ | |
| ci-summary: | |
| name: CI Summary | |
| runs-on: ubuntu-latest | |
| needs: [detect-changes, test-backend, test-frontend] | |
| if: always() | |
| steps: | |
| - name: Check all test results | |
| run: | | |
| echo "## CI Pipeline Summary" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "### Changes Detected:" >> $GITHUB_STEP_SUMMARY | |
| echo "- Backend: ${{ needs.detect-changes.outputs.backend }}" >> $GITHUB_STEP_SUMMARY | |
| echo "- Frontend: ${{ needs.detect-changes.outputs.frontend }}" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "### Test Results:" >> $GITHUB_STEP_SUMMARY | |
| echo "- Backend Tests: ${{ needs.test-backend.result }}" >> $GITHUB_STEP_SUMMARY | |
| echo "- Frontend Tests: ${{ needs.test-frontend.result }}" >> $GITHUB_STEP_SUMMARY | |
| # Fail if any test job failed | |
| if [[ "${{ needs.test-backend.result }}" == "failure" ]] || \ | |
| [[ "${{ needs.test-frontend.result }}" == "failure" ]]; then | |
| echo "❌ One or more test suites failed!" | |
| exit 1 | |
| fi | |
| echo "✅ All tests passed!" |