Skip to content

PR CI

PR CI #85

Workflow file for this run

name: PR CI
on:
pull_request:
branches:
- main
paths-ignore:
- '**.md'
- 'docs/**'
- '.gitignore'
- 'LICENSE'
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
# Stage 1: Fast Unit Tests (Parallel)
backend-unit-tests:
name: Backend Unit Tests
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Java 25
uses: actions/setup-java@v4
with:
java-version: '25'
distribution: 'temurin'
cache: 'maven'
- name: Cache Maven dependencies
uses: actions/cache@v4
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
restore-keys: |
${{ runner.os }}-maven-
- name: Run backend unit tests
run: ./mvnw -pl backend clean test
- name: Upload test results
if: always()
uses: actions/upload-artifact@v4
with:
name: backend-unit-test-results
path: backend/target/surefire-reports/
retention-days: 7
backend-integration-tests:
name: Backend Integration Tests
runs-on: ubuntu-latest
timeout-minutes: 20
services:
postgres:
image: postgis/postgis:17-3.5
env:
POSTGRES_DB: geopulse_test
POSTGRES_USER: geopulse_test
POSTGRES_PASSWORD: testpass
ports:
- 5432:5432
options: >-
--health-cmd "pg_isready -U geopulse_test -d geopulse_test"
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Java 25
uses: actions/setup-java@v4
with:
java-version: '25'
distribution: 'temurin'
cache: 'maven'
- name: Cache Maven dependencies
uses: actions/cache@v4
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
restore-keys: |
${{ runner.os }}-maven-
- name: Compile integration test classes
run: ./mvnw -pl backend -DskipITs=false test-compile
env:
QUARKUS_DATASOURCE_JDBC_URL: jdbc:postgresql://localhost:5432/geopulse_test
QUARKUS_DATASOURCE_USERNAME: geopulse_test
QUARKUS_DATASOURCE_PASSWORD: testpass
- name: Run backend integration tests
run: ./mvnw -pl backend -DskipITs=false failsafe:integration-test failsafe:verify
env:
QUARKUS_DATASOURCE_JDBC_URL: jdbc:postgresql://localhost:5432/geopulse_test
QUARKUS_DATASOURCE_USERNAME: geopulse_test
QUARKUS_DATASOURCE_PASSWORD: testpass
- name: Upload integration test results
if: always()
uses: actions/upload-artifact@v4
with:
name: backend-integration-test-results
path: backend/target/failsafe-reports/
retention-days: 7
frontend-unit-tests:
name: Frontend Unit Tests
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
cache-dependency-path: frontend/package-lock.json
- name: Install dependencies
run: |
cd frontend
npm ci
- name: Run frontend unit tests
run: |
cd frontend
npm run test:run -- --passWithNoTests
- name: Upload test results
if: always()
uses: actions/upload-artifact@v4
with:
name: frontend-test-results
path: frontend/coverage/
retention-days: 7
code-quality:
name: Code Quality (PMD)
runs-on: ubuntu-latest
timeout-minutes: 10
continue-on-error: true # Non-blocking
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Java 25
uses: actions/setup-java@v4
with:
java-version: '25'
distribution: 'temurin'
cache: 'maven'
- name: Run PMD analysis
run: ./mvnw -pl backend pmd:check
- name: Show PMD violations
if: always()
run: |
if [ -f backend/target/pmd.xml ]; then
echo "=== PMD Violations ==="
cat backend/target/pmd.xml
fi
- name: Upload PMD report
if: always()
uses: actions/upload-artifact@v4
with:
name: pmd-report
path: backend/target/pmd.xml
retention-days: 7
# Stage 2: Smoke E2E Tests
smoke-e2e-tests:
name: Smoke E2E Tests
runs-on: ubuntu-latest
needs: [backend-unit-tests, backend-integration-tests, frontend-unit-tests]
timeout-minutes: 30
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Start E2E environment
run: |
docker compose -f tests/docker-compose.e2e.yml up -d geopulse-postgres-e2e geopulse-backend-e2e geopulse-ui-e2e
- name: Wait for services to be healthy
run: |
echo "Waiting for backend to be ready..."
timeout 120 bash -c 'until curl -f http://localhost:8081/api/health; do echo "Waiting..."; sleep 5; done'
echo "Waiting for frontend to be ready..."
timeout 60 bash -c 'until curl -f http://localhost:5556; do echo "Waiting..."; sleep 5; done'
echo "All services are ready!"
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
cache-dependency-path: tests/package-lock.json
- name: Install Playwright dependencies
run: |
cd tests
npm ci
npx playwright install --with-deps chromium
- name: Run smoke E2E tests
run: |
cd tests
npx playwright test \
e2e/authentication.spec.js \
e2e/health.spec.js \
e2e/user-registration.spec.js \
e2e/error-handling.spec.js
env:
BASE_URL: http://localhost:5556
PLAYWRIGHT_WORKERS: 4
CI: true
- name: Upload Playwright report
if: always()
uses: actions/upload-artifact@v4
with:
name: playwright-smoke-report
path: tests/playwright-report/
retention-days: 7
- name: Upload test results
if: always()
uses: actions/upload-artifact@v4
with:
name: playwright-smoke-results
path: tests/test-results/
retention-days: 7
- name: Show environment logs on failure
if: failure()
run: |
echo "=== Backend logs ==="
docker logs geopulse-backend-e2e || true
echo "=== Frontend logs ==="
docker logs geopulse-ui-e2e || true
echo "=== Database logs ==="
docker logs geopulse-postgres-e2e || true
- name: Cleanup
if: always()
run: |
docker compose -f tests/docker-compose.e2e.yml down -v || echo "Cleanup failed but continuing"
docker system prune -f || true
# Summary job - required for branch protection
pr-ci-summary:
name: PR CI Summary
runs-on: ubuntu-latest
needs: [backend-unit-tests, backend-integration-tests, frontend-unit-tests, smoke-e2e-tests]
if: always()
steps:
- name: Check all jobs status
run: |
if [[ "${{ needs.backend-unit-tests.result }}" != "success" ]] || \
[[ "${{ needs.backend-integration-tests.result }}" != "success" ]] || \
[[ "${{ needs.frontend-unit-tests.result }}" != "success" ]] || \
[[ "${{ needs.smoke-e2e-tests.result }}" != "success" ]]; then
echo "❌ PR CI failed. Check the logs above for details."
exit 1
fi
echo "✅ All PR CI checks passed!"