Skip to content

CI Pipeline

CI Pipeline #701

Workflow file for this run

name: CI Pipeline
on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]
schedule:
- cron: "0 2 * * *"
workflow_dispatch:
jobs:
backend-lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4.2.2
- name: Set up JDK 21
uses: actions/setup-java@v3.14.1
with:
distribution: "temurin"
java-version: "21"
cache: "maven"
- name: Run backend lint (Checkstyle)
run: |
cd backend
mvn checkstyle:check -Dcheckstyle.config.location=checkstyle.xml
backend:
runs-on: ubuntu-latest
needs: backend-lint
steps:
- uses: actions/checkout@v4.2.2
- name: Clean Maven cache
run: |
rm -rf ~/.m2/repository
rm -rf backend/target
- name: Set up JDK 21
uses: actions/setup-java@v3.14.1
with:
distribution: "temurin"
java-version: "21"
cache: "maven"
# - name: Format code with Google Java Format ✨
# uses: axel-op/googlejavaformat-action@v3
# with:
# args: --set-exit-if-changed
# files: backend/**/*.java
- name: Verify with maven and generate coverage report
env:
TEST_TURNSTILE_SECRET_KEY: ${{ secrets.TEST_TURNSTILE_SECRET_KEY }}
run: |
cd backend
touch .env
mvn -Dspring.profiles.active=test clean verify jacoco:report
- name: Upload JaCoCo coverage report as artifact
uses: actions/upload-artifact@v4
with:
name: jacoco-coverage-report
path: backend/target/site/jacoco/
retention-days: 7
frontend-lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4.2.2
- name: Set up Node.js
uses: actions/setup-node@v3.9.1
with:
node-version: "22"
- name: Setup pnpm
uses: pnpm/action-setup@v4.1.0
with:
version: "10.10.0"
- name: Install dependencies
run: |
cd frontend
pnpm install --frozen-lockfile
- name: Run frontend lint
run: |
cd frontend
rm -f cypress.config.d.ts
rm -f vitest.config.d.ts
pnpm exec eslint . --max-warnings=0
frontend:
runs-on: ubuntu-latest
needs: frontend-lint
steps:
- uses: actions/checkout@v4.2.2
- name: Clean frontend artifacts
run: |
rm -rf frontend/node_modules
rm -rf frontend/dist
- name: Set up Node.js
uses: actions/setup-node@v3.9.1
with:
node-version: "22"
- name: Setup pnpm
uses: pnpm/action-setup@v4.1.0
with:
version: "10.10.0"
- name: Install dependencies
run: |
cd frontend
pnpm install --force --no-cache
- name: Build frontend
run: |
cd frontend
pnpm run build
- name: Run tests
run: |
cd frontend
pnpm run test:a11y
pnpm run test:coverage -- --coverage.thresholds.lines=80 --coverage.thresholds.functions=80 --coverage.thresholds.branches=80 --coverage.thresholds.statements=80
- name: Upload frontend coverage report as artifact
uses: actions/upload-artifact@v4
with:
name: frontend-coverage-report
path: frontend/coverage/
retention-days: 7
frontend-e2e:
runs-on: ubuntu-latest
needs: frontend
steps:
- uses: actions/checkout@v4.2.2
- name: Set up Node.js
uses: actions/setup-node@v3.9.1
with:
node-version: "22"
- name: Setup pnpm
uses: pnpm/action-setup@v4.1.0
with:
version: "10.10.0"
- name: Install dependencies
run: |
cd frontend
pnpm install --frozen-lockfile
- name: Build frontend for preview server
run: |
cd frontend
pnpm run build
- name: Run Cypress E2E tests
run: |
cd frontend
pnpm run test:e2e
frontend-e2e-fullstack-smoke:
runs-on: ubuntu-latest
needs: [backend, frontend]
if: github.event_name == 'pull_request' || github.event_name == 'push'
steps:
- uses: actions/checkout@v4.2.2
- name: Set up Node.js
uses: actions/setup-node@v3.9.1
with:
node-version: "22"
- name: Setup pnpm
uses: pnpm/action-setup@v4.1.0
with:
version: "10.10.0"
- name: Install frontend dependencies
run: |
cd frontend
pnpm install --frozen-lockfile
- name: Prepare E2E mail hook secret
run: echo "E2E_MAIL_HOOK_SECRET=$(openssl rand -hex 16)" >> "$GITHUB_ENV"
- name: Write backend/.env for Docker Compose
run: |
{
echo "SPRING_DATASOURCE_URL=jdbc:mysql://db:3306/krisefikser"
echo "SPRING_DATASOURCE_USERNAME=root"
echo "SPRING_DATASOURCE_PASSWORD=root"
echo "JWT_SECRET=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
echo "TURNSTILE_SECRET_KEY=1x0000000000000000000000000000000AA"
echo "FRONTEND_URL=http://127.0.0.1:5173"
echo "MAILTRAP_API_TOKEN=unused-e2e-mail-captured-in-memory"
echo "E2E_MAIL_HOOK_SECRET=${E2E_MAIL_HOOK_SECRET}"
} > backend/.env
- name: Build frontend
env:
VITE_API_URL: http://127.0.0.1:8080
VITE_WS_URL: ws://127.0.0.1:8080/ws
VITE_TURNSTILE_SITE_KEY: 1x00000000000000000000AA
run: |
cd frontend
pnpm run build
- name: Start database and backend
env:
AUTH_ADMIN_TWO_FACTOR_ENABLED: "false"
SPRING_PROFILES_ACTIVE: dev,e2e
run: |
docker compose up -d db backend
for i in {1..60}; do
STATUS_CODE=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:8080/api/auth/me || true)
if [ "$STATUS_CODE" = "401" ] || [ "$STATUS_CODE" = "200" ]; then
echo "Backend is healthy (HTTP $STATUS_CODE)"
exit 0
fi
echo "Waiting for backend (HTTP $STATUS_CODE)..."
sleep 5
done
echo "Backend did not become healthy in time"
docker compose logs backend
exit 1
- name: Run full-stack smoke E2E
env:
CYPRESS_e2eMailHookSecret: ${{ env.E2E_MAIL_HOOK_SECRET }}
run: |
cd frontend
pnpm run test:e2e:fullstack:smoke
frontend-e2e-fullstack-regression:
runs-on: ubuntu-latest
needs: [frontend]
if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'
steps:
- uses: actions/checkout@v4.2.2
- name: Set up Node.js
uses: actions/setup-node@v3.9.1
with:
node-version: "22"
- name: Setup pnpm
uses: pnpm/action-setup@v4.1.0
with:
version: "10.10.0"
- name: Install frontend dependencies
run: |
cd frontend
pnpm install --frozen-lockfile
- name: Prepare E2E mail hook secret
run: echo "E2E_MAIL_HOOK_SECRET=$(openssl rand -hex 16)" >> "$GITHUB_ENV"
- name: Write backend/.env for Docker Compose
run: |
{
echo "SPRING_DATASOURCE_URL=jdbc:mysql://db:3306/krisefikser"
echo "SPRING_DATASOURCE_USERNAME=root"
echo "SPRING_DATASOURCE_PASSWORD=root"
echo "JWT_SECRET=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
echo "TURNSTILE_SECRET_KEY=1x0000000000000000000000000000000AA"
echo "FRONTEND_URL=http://127.0.0.1:5173"
echo "MAILTRAP_API_TOKEN=unused-e2e-mail-captured-in-memory"
echo "E2E_MAIL_HOOK_SECRET=${E2E_MAIL_HOOK_SECRET}"
} > backend/.env
- name: Build frontend with E2E coverage instrumentation
env:
CYPRESS_COVERAGE: "true"
VITE_API_URL: http://127.0.0.1:8080
VITE_WS_URL: ws://127.0.0.1:8080/ws
VITE_TURNSTILE_SITE_KEY: 1x00000000000000000000AA
run: |
cd frontend
pnpm run build:coverage
- name: Start database and backend
env:
AUTH_ADMIN_TWO_FACTOR_ENABLED: "false"
SPRING_PROFILES_ACTIVE: dev,e2e
run: |
docker compose up -d db backend
for i in {1..60}; do
STATUS_CODE=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:8080/api/auth/me || true)
if [ "$STATUS_CODE" = "401" ] || [ "$STATUS_CODE" = "200" ]; then
echo "Backend is healthy (HTTP $STATUS_CODE)"
exit 0
fi
echo "Waiting for backend (HTTP $STATUS_CODE)..."
sleep 5
done
echo "Backend did not become healthy in time"
docker compose logs backend
exit 1
- name: Run full-stack regression E2E
env:
CYPRESS_COVERAGE: 'true'
CYPRESS_e2eMailHookSecret: ${{ env.E2E_MAIL_HOOK_SECRET }}
run: |
cd frontend
pnpm run test:e2e:fullstack:regression
- name: Generate E2E coverage report
if: success() || failure()
run: |
cd frontend
if [ -d .nyc_output ] && [ -n "$(ls -A .nyc_output 2>/dev/null)" ]; then
pnpm exec nyc report --report-dir coverage-e2e --reporter=lcov --reporter=html --reporter=text-summary
else
echo "No .nyc_output; skipping nyc report"
fi
- name: Upload E2E coverage report
if: success() || failure()
uses: actions/upload-artifact@v4
with:
name: frontend-e2e-coverage-report
path: frontend/coverage-e2e/
retention-days: 7
if-no-files-found: ignore