230 lines
8.1 KiB
YAML
230 lines
8.1 KiB
YAML
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 25
|
||
uses: actions/setup-java@v5
|
||
with:
|
||
java-version: 25
|
||
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
|