Skip to content

Migrate to Vite 6 + Comprehensive Testing Infrastructure (#27) #152

Migrate to Vite 6 + Comprehensive Testing Infrastructure (#27)

Migrate to Vite 6 + Comprehensive Testing Infrastructure (#27) #152

Workflow file for this run

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!"