meldestelle/.github/workflows/integration-tests.yml
StefanMo 95fe3e0573
chore(ci): Align GH Workflows with Docker SSoT, new paths; minimal SSoT guard; staticAnalysis (#23)
* chore(MP-21): snapshot pre-refactor state (Epic 1)

* chore(MP-22): scaffold new repo structure, relocate Docker Compose, move frontend/backend modules, update Makefile; add docs mapping and env template

* MP-22 Epic 2: Erfolgreich umgesetzt und verifiziert

* MP-23 Epic 3: Gradle/Build Governance zentralisieren

* MP-23 Epic 3: Gradle/Build Governance zentralisieren

* chore(devops)!: Docker-SSoT (.env) konsolidiert, Compose-Mounts ergänzt, Makefile entfernt

- ENV Single Source of Truth
  - docker/.env.example neu (inkl. REDIS_PASSWORD, Ports, Build-Overrides)
  - config/.env(.example) als DEPRECATED markiert (Verweis auf docker/.env[.example])

- Docker Compose vereinheitlicht (docker/docker-compose.yaml)
  - Postgres: zentralen postgresql.conf mounten (../config/postgres/postgresql.conf)
    und Start mit -c config_file=/etc/postgresql/postgresql.conf
  - Redis: zentralen redis.conf mounten (../config/redis/redis.conf)
    und Start via "redis-server … ${REDIS_PASSWORD:+--requirepass $REDIS_PASSWORD}"
  - Web-Nginx: ../config/nginx/nginx.prod.conf → /etc/nginx/nginx.conf (ro)
  - Monitoring: Prometheus/Grafana nutzen ../config/monitoring/* als SSoT

- Frontend/DI/Network (MP-23 Grundlage)
  - :frontend:core:network Modul mit Koin `apiClient` (Ktor + JSON/Retry/Timeout/Logging)
  - Plattform-Basis-URL-Auflösung (JVM: ENV API_BASE_URL; JS: globalThis.API_BASE_URL / Same-Origin)
  - Web index.html setzt API_BASE_URL (Query `?apiBaseUrl=…` > Same-Origin > Fallback)

- Build/Gradle & Module-Refs
  - settings.gradle.kts: neue Frontend-/Backend-Pfade bereits inkludiert
  - Features/Shell: Abhängigkeiten auf :frontend:shared / :frontend:core:* angepasst
  - Ping-API-Refs auf :backend:services:ping:ping-api vereinheitlicht

- Dockerfiles angepasst
  - backend/infrastructure/gateway/Dockerfile → Tasks/Pfade auf :backend:gateway
  - backend/services/ping/Dockerfile → Tasks/Pfade auf :backend:services:ping:ping-service

- Static Analysis / Guards
  - config/detekt/detekt.yml hinzugefügt
  - Leichter Arch-Guard (Frontend) gegen manuelle Authorization-Header vorbereitet

- Doku
  - docs/ARCHITECTURE.md (Struktur, Mapping, Next Steps) ergänzt
  - docs/adr/README.md angelegt

BREAKING CHANGES:
- Makefile komplett entfernt (bitte direkt `docker compose` verwenden)
- ENV-Quelle ist jetzt docker/.env (statt config/.env oder Root)
- Compose-Datei unter docker/docker-compose.yaml (nicht mehr compose.yaml im Repo-Root)

Verifikation (lokal):
- ENV anlegen: `cp docker/.env.example docker/.env` (Werte anpassen)
- Compose prüfen: `docker compose --env-file docker/.env -f docker/docker-compose.yaml config`
- Infrastruktur: `docker compose --env-file docker/.env -f docker/docker-compose.yaml -p meldestelle up -d postgres redis keycloak web-app`
- Services bauen: `docker compose --env-file docker/.env -f docker/docker-compose.yaml -p meldestelle build api-gateway ping-service --no-cache --progress=plain`

Refs: MP-22 (Epic 2), MP-23 (Epic 3)

* chore(devops)!: Docker-SSoT (.env) konsolidiert, Compose-Mounts ergänzt, Makefile entfernt

- ENV Single Source of Truth
  - docker/.env.example neu (inkl. REDIS_PASSWORD, Ports, Build-Overrides)
  - config/.env(.example) als DEPRECATED markiert (Verweis auf docker/.env[.example])

- Docker Compose vereinheitlicht (docker/docker-compose.yaml)
  - Postgres: zentralen postgresql.conf mounten (../config/postgres/postgresql.conf)
    und Start mit -c config_file=/etc/postgresql/postgresql.conf
  - Redis: zentralen redis.conf mounten (../config/redis/redis.conf)
    und Start via "redis-server … ${REDIS_PASSWORD:+--requirepass $REDIS_PASSWORD}"
  - Web-Nginx: ../config/nginx/nginx.prod.conf → /etc/nginx/nginx.conf (ro)
  - Monitoring: Prometheus/Grafana nutzen ../config/monitoring/* als SSoT

- Frontend/DI/Network (MP-23 Grundlage)
  - :frontend:core:network Modul mit Koin `apiClient` (Ktor + JSON/Retry/Timeout/Logging)
  - Plattform-Basis-URL-Auflösung (JVM: ENV API_BASE_URL; JS: globalThis.API_BASE_URL / Same-Origin)
  - Web index.html setzt API_BASE_URL (Query `?apiBaseUrl=…` > Same-Origin > Fallback)

- Build/Gradle & Module-Refs
  - settings.gradle.kts: neue Frontend-/Backend-Pfade bereits inkludiert
  - Features/Shell: Abhängigkeiten auf :frontend:shared / :frontend:core:* angepasst
  - Ping-API-Refs auf :backend:services:ping:ping-api vereinheitlicht

- Dockerfiles angepasst
  - backend/infrastructure/gateway/Dockerfile → Tasks/Pfade auf :backend:gateway
  - backend/services/ping/Dockerfile → Tasks/Pfade auf :backend:services:ping:ping-service

- Static Analysis / Guards
  - config/detekt/detekt.yml hinzugefügt
  - Leichter Arch-Guard (Frontend) gegen manuelle Authorization-Header vorbereitet

- Doku
  - docs/ARCHITECTURE.md (Struktur, Mapping, Next Steps) ergänzt
  - docs/adr/README.md angelegt

BREAKING CHANGES:
- Makefile komplett entfernt (bitte direkt `docker compose` verwenden)
- ENV-Quelle ist jetzt docker/.env (statt config/.env oder Root)
- Compose-Datei unter docker/docker-compose.yaml (nicht mehr compose.yaml im Repo-Root)

Verifikation (lokal):
- ENV anlegen: `cp docker/.env.example docker/.env` (Werte anpassen)
- Compose prüfen: `docker compose --env-file docker/.env -f docker/docker-compose.yaml config`
- Infrastruktur: `docker compose --env-file docker/.env -f docker/docker-compose.yaml -p meldestelle up -d postgres redis keycloak web-app`
- Services bauen: `docker compose --env-file docker/.env -f docker/docker-compose.yaml -p meldestelle build api-gateway ping-service --no-cache --progress=plain`

Refs: MP-22 (Epic 2), MP-23 (Epic 3)

* chore(devops)!: Docker-SSoT (.env) konsolidiert, Compose-Mounts ergänzt, Makefile entfernt

- ENV Single Source of Truth
  - docker/.env.example neu (inkl. REDIS_PASSWORD, Ports, Build-Overrides)
  - config/.env(.example) als DEPRECATED markiert (Verweis auf docker/.env[.example])

- Docker Compose vereinheitlicht (docker/docker-compose.yaml)
  - Postgres: zentralen postgresql.conf mounten (../config/postgres/postgresql.conf)
    und Start mit -c config_file=/etc/postgresql/postgresql.conf
  - Redis: zentralen redis.conf mounten (../config/redis/redis.conf)
    und Start via "redis-server … ${REDIS_PASSWORD:+--requirepass $REDIS_PASSWORD}"
  - Web-Nginx: ../config/nginx/nginx.prod.conf → /etc/nginx/nginx.conf (ro)
  - Monitoring: Prometheus/Grafana nutzen ../config/monitoring/* als SSoT

- Frontend/DI/Network (MP-23 Grundlage)
  - :frontend:core:network Modul mit Koin `apiClient` (Ktor + JSON/Retry/Timeout/Logging)
  - Plattform-Basis-URL-Auflösung (JVM: ENV API_BASE_URL; JS: globalThis.API_BASE_URL / Same-Origin)
  - Web index.html setzt API_BASE_URL (Query `?apiBaseUrl=…` > Same-Origin > Fallback)

- Build/Gradle & Module-Refs
  - settings.gradle.kts: neue Frontend-/Backend-Pfade bereits inkludiert
  - Features/Shell: Abhängigkeiten auf :frontend:shared / :frontend:core:* angepasst
  - Ping-API-Refs auf :backend:services:ping:ping-api vereinheitlicht

- Dockerfiles angepasst
  - backend/infrastructure/gateway/Dockerfile → Tasks/Pfade auf :backend:gateway
  - backend/services/ping/Dockerfile → Tasks/Pfade auf :backend:services:ping:ping-service

- Static Analysis / Guards
  - config/detekt/detekt.yml hinzugefügt
  - Leichter Arch-Guard (Frontend) gegen manuelle Authorization-Header vorbereitet

- Doku
  - docs/ARCHITECTURE.md (Struktur, Mapping, Next Steps) ergänzt
  - docs/adr/README.md angelegt

BREAKING CHANGES:
- Makefile komplett entfernt (bitte direkt `docker compose` verwenden)
- ENV-Quelle ist jetzt docker/.env (statt config/.env oder Root)
- Compose-Datei unter docker/docker-compose.yaml (nicht mehr compose.yaml im Repo-Root)

Verifikation (lokal):
- ENV anlegen: `cp docker/.env.example docker/.env` (Werte anpassen)
- Compose prüfen: `docker compose --env-file docker/.env -f docker/docker-compose.yaml config`
- Infrastruktur: `docker compose --env-file docker/.env -f docker/docker-compose.yaml -p meldestelle up -d postgres redis keycloak web-app`
- Services bauen: `docker compose --env-file docker/.env -f docker/docker-compose.yaml -p meldestelle build api-gateway ping-service --no-cache --progress=plain`

Refs: MP-22 (Epic 2), MP-23 (Epic 3)

* chore(ci): Workflows an Docker-SSoT & neue Struktur angepasst, minimaler SSoT-Guard

- ssot-guard.yml: Option B (minimal) → `docker compose -f docker/docker-compose.yaml config` als Lint
- integration-tests.yml: `./gradlew staticAnalysis` vor Integrationstests
- docs-kdoc-sync.yml: Dokka-Task Fallback (dokkaGfmAll || dokkaGfm), YouTrack-Sync nur wenn Script vorhanden
- deploy-proxmox.yml: Compose-Pfade auf docker/docker-compose.yaml + `--env-file docker/.env`; Build/Test Schritte vereinheitlicht
- ci-main.yml: SSoT-Skripte per `if: hashFiles(...)` guarded, Compose-Lint Fallback; OpenAPI‑Pfad → backend/gateway; ADR‑Pfade → docs/adr/**; `staticAnalysis` in Build integriert
- youtrack-sync.yml: unverändert (funktional)

Refs: MP-22, MP-23

* chore(ci): Workflows an Docker-SSoT & neue Struktur angepasst, minimaler SSoT-Guard

- ssot-guard.yml: Option B (minimal) → `docker compose -f docker/docker-compose.yaml config` als Lint
- integration-tests.yml: `./gradlew staticAnalysis` vor Integrationstests
- docs-kdoc-sync.yml: Dokka-Task Fallback (dokkaGfmAll || dokkaGfm), YouTrack-Sync nur wenn Script vorhanden
- deploy-proxmox.yml: Compose-Pfade auf docker/docker-compose.yaml + `--env-file docker/.env`; Build/Test Schritte vereinheitlicht
- ci-main.yml: SSoT-Skripte per `if: hashFiles(...)` guarded, Compose-Lint Fallback; OpenAPI‑Pfad → backend/gateway; ADR‑Pfade → docs/adr/**; `staticAnalysis` in Build integriert
- youtrack-sync.yml: unverändert (funktional)

Refs: MP-22, MP-23

* fix(ci): create .env from example before validating compose config

* fix(ci): update ssot-guard filename (.yaml) and sync workflow state

* fixing

* fix(webpack): correct sql.js fallback configuration for webpack 5
2025-12-03 12:03:40 +01:00

230 lines
8.1 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

name: Integration Tests
permissions:
contents: read
concurrency:
group: integration-tests-${{ github.ref }}
cancel-in-progress: true
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main, develop ]
jobs:
integration-tests:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
keycloak_db: [postgres, dev-file]
env:
KEYCLOAK_VERSION: "26.4.2"
services:
postgres:
image: postgres:16-alpine
env:
POSTGRES_USER: meldestelle
POSTGRES_PASSWORD: meldestelle
POSTGRES_DB: meldestelle
ports:
- 5432:5432
options: >-
--health-cmd "pg_isready -U meldestelle -d $${POSTGRES_DB}"
--health-interval 10s
--health-timeout 5s
--health-retries 12
--health-start-period 20s
redis:
image: redis:7-alpine
ports:
- 6379:6379
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5
zookeeper:
image: confluentinc/cp-zookeeper:7.5.0
env:
ZOOKEEPER_CLIENT_PORT: 2181
ports:
- 2181:2181
options: >-
--health-cmd "nc -z localhost 2181 || exit 1"
--health-interval 10s
--health-timeout 5s
--health-retries 3
--health-start-period 10s
kafka:
image: confluentinc/cp-kafka:7.5.0
env:
KAFKA_BROKER_ID: 1
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:29092,PLAINTEXT_HOST://localhost:9092
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT
KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
ports:
- 9092:9092
options: >-
--health-cmd "kafka-topics --bootstrap-server localhost:9092 --list || exit 1"
--health-interval 10s
--health-timeout 5s
--health-retries 3
--health-start-period 30s
zipkin:
image: openzipkin/zipkin:2
ports:
- 9411:9411
options: >-
--health-cmd "wget -q -O - http://localhost:9411/health || exit 1"
--health-interval 10s
--health-timeout 5s
--health-retries 3
--health-start-period 10s
steps:
- uses: actions/checkout@v6
- name: Set up JDK 21
uses: actions/setup-java@v5
with:
java-version: 21
distribution: 'temurin'
cache: 'gradle'
- name: Setup Gradle (modern)
uses: gradle/actions/setup-gradle@v5
- name: Wait for Postgres to be ready (pg_isready in service network)
if: ${{ matrix.keycloak_db == 'postgres' }}
run: |
echo "Waiting for Postgres..."
for i in {1..40}; do
if docker run --rm --network ${{ job.services.postgres.network }} \
postgres:16-alpine pg_isready -h postgres -p 5432 -U meldestelle -d meldestelle; then
echo "Postgres is ready"; break; fi; echo -n "."; sleep 3; done
- name: Start Keycloak with Postgres (dev) and wait for readiness
if: ${{ matrix.keycloak_db == 'postgres' }}
run: |
set -euo pipefail
echo "Starting Keycloak (DB=postgres)..."
docker run -d --name keycloak \
--network ${{ job.services.postgres.network }} \
-p 8180:8080 \
-e KC_BOOTSTRAP_ADMIN_USERNAME=admin \
-e KC_BOOTSTRAP_ADMIN_PASSWORD=admin \
-e KC_DB=postgres \
-e KC_DB_URL=jdbc:postgresql://postgres:5432/meldestelle \
-e KC_DB_USERNAME=meldestelle \
-e KC_DB_PASSWORD=meldestelle \
-e KC_HEALTH_ENABLED=true \
-e JAVA_OPTS="-Xms256m -Xmx1024m -XX:MaxRAMPercentage=60" \
quay.io/keycloak/keycloak:${{ env.KEYCLOAK_VERSION }} \
start-dev
echo "Giving Keycloak 30s to initialize..."; sleep 30
wait_for() {
local url="$1"; local label="$2"; local timeout="${3:-180}"; local interval="${4:-5}"
echo "Waiting for $label ($url) ..."
if ! timeout ${timeout}s bash -c 'until curl -fsS --output /dev/null '"$url"'; do echo -n "."; sleep '"$interval"'; done'; then
echo "\n[WAIT] Timeout on $url"
return 1
fi
echo "\n[WAIT] $label is up"
}
if ! wait_for http://localhost:8180/ "root" 180 5; then
docker logs --tail=200 keycloak || true
exit 1
fi
if ! wait_for http://localhost:8180/health "health" 180 5; then
echo "[INFO] /health nicht erreichbar versuche /q/health (Quarkus default)"
wait_for http://localhost:8180/q/health "q-health" 180 5 || true
fi
wait_for http://localhost:8180/health/ready "health-ready" 300 5 || true
wait_for http://localhost:8180/admin/master/console/ "admin-console" 300 5 || (docker logs --tail=400 keycloak && exit 1)
- name: Start Keycloak with dev-file (no Postgres) and wait for readiness
if: ${{ matrix.keycloak_db == 'dev-file' }}
run: |
set -euo pipefail
echo "Starting Keycloak (DB=dev-file, no Postgres)..."
docker run -d --name keycloak \
-p 8180:8080 \
-e KC_BOOTSTRAP_ADMIN_USERNAME=admin \
-e KC_BOOTSTRAP_ADMIN_PASSWORD=admin \
-e KC_DB=dev-file \
-e KC_HEALTH_ENABLED=true \
-e JAVA_OPTS="-Xms256m -Xmx1024m -XX:MaxRAMPercentage=60" \
quay.io/keycloak/keycloak:${{ env.KEYCLOAK_VERSION }} \
start-dev
echo "Giving Keycloak 20s to initialize..."; sleep 20
wait_for() {
local url="$1"; local label="$2"; local timeout="${3:-180}"; local interval="${4:-5}"
echo "Waiting for $label ($url) ..."
if ! timeout ${timeout}s bash -c 'until curl -fsS --output /dev/null '"$url"'; do echo -n "."; sleep '"$interval"'; done'; then
echo "\n[WAIT] Timeout on $url"
return 1
fi
echo "\n[WAIT] $label is up"
}
if ! wait_for http://localhost:8180/ "root" 180 5; then
docker logs --tail=200 keycloak || true
exit 1
fi
if ! wait_for http://localhost:8180/health "health" 180 5; then
echo "[INFO] /health nicht erreichbar versuche /q/health (Quarkus default)"
wait_for http://localhost:8180/q/health "q-health" 180 5 || true
fi
wait_for http://localhost:8180/health/ready "health-ready" 300 5 || true
wait_for http://localhost:8180/admin/master/console/ "admin-console" 300 5 || (docker logs --tail=400 keycloak && exit 1)
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Static Analysis
run: ./gradlew staticAnalysis --no-daemon
- name: Run integration tests
run: ./gradlew integrationTest --no-daemon --parallel
env:
# Environment variables for Redis connection
REDIS_HOST: localhost
REDIS_PORT: 6379
# Keycloak base URL for integration tests (manual container)
KEYCLOAK_AUTH_SERVER_URL: http://localhost:8180
# Spring profile for integration tests
SPRING_PROFILES_ACTIVE: integration-test
- name: Upload test reports
uses: actions/upload-artifact@v5
if: always()
with:
name: integration-test-reports
path: |
**/build/reports/tests/integrationTest/
**/build/test-results/integrationTest/
retention-days: 7
- name: Dump service logs (Keycloak, Postgres)
if: always()
run: |
echo "=== Docker ps ===" && docker ps -a || true
echo "=== Keycloak logs (tail) ===" && docker logs --tail=400 keycloak || true
echo "=== Postgres logs (tail) ===" && docker logs --tail=200 $(docker ps -a --filter "name=postgres" --format "{{.ID}}") || true