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
This commit is contained in:
StefanMo
2025-12-03 12:03:40 +01:00
committed by GitHub
parent 034892e890
commit 95fe3e0573
365 changed files with 2283 additions and 15142 deletions
+10 -210
View File
@@ -1,225 +1,25 @@
name: Docker SSoT Guard
permissions:
contents: read
concurrency:
group: ssot-guard-${{ github.ref }}
cancel-in-progress: true
name: Docker SSoT Guard (Minimal)
on:
push:
branches: [ main ]
paths:
- 'docker/**'
- 'dockerfiles/**'
- 'docker-compose*.yml*'
- 'scripts/**'
- '.github/workflows/ssot-guard.yml'
pull_request:
paths:
- 'docker/**'
- 'dockerfiles/**'
- 'docker-compose*.yml*'
- 'scripts/**'
- '.github/workflows/ssot-guard.yml'
jobs:
ssot-guard:
check-compose-config:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v5
with:
fetch-depth: 0
- uses: actions/checkout@v4
# FIX: .env aus Example erstellen, damit Variablen da sind
- name: Create .env context
run: cp docker/.env.example docker/.env
- name: Show environment
run: |
bash --version
docker --version || true
compose_ver=$(docker compose version 2>/dev/null || true); echo "docker compose: $compose_ver"
- name: Sync versions to env files
run: bash scripts/docker-versions-update.sh sync
- name: Generate docker-compose files (all)
run: bash scripts/generate-compose-files.sh all development
- name: Validate Docker SSoT consistency
run: bash scripts/validate-docker-consistency.sh all
- name: Build vs Runtime variable guards
run: |
set -euo pipefail
echo "[Guard] Prüfe, dass keine Laufzeit-Variablen in Build-Args-Dateien vorkommen..."
RUNTIME_KEYS_REGEX='^(GATEWAY_HOST|GATEWAY_PORT|WEB_APP_PORT|NODE_ENV|CONSUL_(HOST|PORT|ENABLED)|DB_(HOST|PORT|NAME|USER|USERNAME|PASSWORD)|POSTGRES_DB|REDIS_PORT|KEYCLOAK_PORT|PING_SERVICE_PORT|MEMBERS_SERVICE_PORT|HORSES_SERVICE_PORT|EVENTS_SERVICE_PORT|MASTERDATA_SERVICE_PORT|AUTH_SERVICE_PORT|MONITORING_SERVER_PORT|PROMETHEUS_PORT|GRAFANA_PORT|JWT_ISSUER|JWT_AUDIENCE)$'
FAIL=0
shopt -s nullglob
for f in docker/build-args/*.env config/build/*.env; do
[ -f "$f" ] || continue
BAD=$(grep -E '^[A-Z0-9_]+=' "$f" | cut -d= -f1 | grep -E "$RUNTIME_KEYS_REGEX" || true)
if [ -n "$BAD" ]; then
echo "Fehler: Laufzeit-Variablen in Build-Args Datei $f gefunden:"; echo "$BAD"; FAIL=1
fi
done
shopt -u nullglob
if [ $FAIL -ne 0 ]; then
echo "Build vs Runtime Trennung verletzt."; exit 1; fi
echo "[Guard] Prüfe, dass keine Build-/Versions-Variablen in Runtime-Env vorkommen..."
BUILD_KEYS_REGEX='^(GRADLE_VERSION|JAVA_VERSION|VERSION|APP_VERSION|[A-Z]+_IMAGE_TAG)$'
shopt -s nullglob
for f in config/env/.env .env.template; do
[ -f "$f" ] || continue
BAD=$(grep -E '^[A-Z0-9_]+=' "$f" | cut -d= -f1 | grep -E "$BUILD_KEYS_REGEX" || true)
if [ -n "$BAD" ]; then
echo "Fehler: Build-/Versions-Variablen in Runtime-Env $f gefunden:"; echo "$BAD"; FAIL=1
fi
done
shopt -u nullglob
if [ $FAIL -ne 0 ]; then
echo "Build-/Runtime-Mischung in Runtime-Env."; exit 1; fi
- name: Check versions.toml vs global.env consistency
run: |
set -euo pipefail
TOML=docker/versions.toml
GLOBAL=docker/build-args/global.env
[ -f "$TOML" ] || { echo "Missing $TOML"; exit 1; }
[ -f "$GLOBAL" ] || { echo "Missing $GLOBAL"; exit 1; }
get_toml_ver(){ awk -F'=' -v key="$1" '/^\[versions\]/{in_vers=1; next} /^\[/{in_vers=0} in_vers && gsub(/^[ \t]+|[ \t]+$/,"",$1) && $1==key {gsub(/[ "\t]/,"",$2); print $2; exit}' "$TOML"; }
mapfile -t checks < <(printf "%s\n" \
"GRADLE_VERSION:versions.gradle" \
"JAVA_VERSION:versions.java" \
"VERSION:versions.app-version" \
"PROMETHEUS_IMAGE_TAG:versions.prometheus" \
"GRAFANA_IMAGE_TAG:versions.grafana" \
"KEYCLOAK_IMAGE_TAG:versions.keycloak" \
"POSTGRES_IMAGE_TAG:versions.postgres" \
"REDIS_IMAGE_TAG:versions.redis" \
"CONSUL_IMAGE_TAG:versions.consul" \
"ZOOKEEPER_IMAGE_TAG:versions.zookeeper" \
"KAFKA_IMAGE_TAG:versions.kafka")
FAIL=0
for entry in "${checks[@]}"; do
var=${entry%%:*}; path=${entry##*:}
key=${path#*.}
case "$var" in
GRADLE_VERSION) expected=$(get_toml_ver gradle) ;;
JAVA_VERSION) expected=$(get_toml_ver java) ;;
VERSION) expected=$(get_toml_ver app-version) ;;
PROMETHEUS_IMAGE_TAG) expected=$(get_toml_ver prometheus) ;;
GRAFANA_IMAGE_TAG) expected=$(get_toml_ver grafana) ;;
KEYCLOAK_IMAGE_TAG) expected=$(get_toml_ver keycloak) ;;
POSTGRES_IMAGE_TAG) expected=$(get_toml_ver postgres) ;;
REDIS_IMAGE_TAG) expected=$(get_toml_ver redis) ;;
CONSUL_IMAGE_TAG) expected=$(get_toml_ver consul) ;;
ZOOKEEPER_IMAGE_TAG) expected=$(get_toml_ver zookeeper) ;;
KAFKA_IMAGE_TAG) expected=$(get_toml_ver kafka) ;;
esac
actual=$(grep -E "^${var}=" "$GLOBAL" | head -n1 | cut -d= -f2-)
if [ -z "$actual" ] || [ "$actual" != "$expected" ]; then
echo "Versions-Drift: $var global.env='$actual' != versions.toml('$expected')"; FAIL=1
fi
done
if [ $FAIL -ne 0 ]; then
echo "Versions SSoT-Drift erkannt."; exit 1; fi
- name: Check drift of generated artifacts (ignore timestamps)
run: |
set -euo pipefail
# Gather modified files after sync+generate
CHANGED=$(git diff --name-only)
if [ -z "$CHANGED" ]; then
echo "No drift detected."
exit 0
fi
echo "Changed files:" $CHANGED
fail=0
for f in $CHANGED; do
# Inspect actual content changes but ignore volatile timestamp/comment lines
# Ignore lines starting with + or - that are exactly the timestamp markers we generate
DIFF_FILTERED=$(git diff --unified=0 -- "$f" \
| awk 'BEGIN{show=0} { \
if ($0 ~ /^\+\+\+|^---|^@@/) { next } \
if ($0 ~ /^[+-]# (Generated:|Last updated:)/) { next } \
if ($0 ~ /^[+-]#\s*Generated from docker\/versions.toml/) { next } \
if ($0 ~ /^[+-]#\s*Environment:/) { next } \
if ($0 ~ /^[+-]#\s*Source:/) { next } \
if ($0 ~ /^[+-]$/) { next } \
if ($0 ~ /^[+-]/) { print $0 } \
}')
if [ -n "$DIFF_FILTERED" ]; then
echo "SSoT drift detected in $f:";
echo "$DIFF_FILTERED";
fail=1;
fi
done
if [ $fail -ne 0 ]; then
echo "\nERROR: Generated artifacts differ from repository (beyond timestamps)."
echo "Run:"
echo " bash scripts/docker-versions-update.sh sync"
echo " bash scripts/generate-compose-files.sh all"
echo "and commit the changes."
exit 1
fi
echo "No SSoT drift (ignoring timestamps)."
ssot-guard-envless:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v5
with:
fetch-depth: 0
- name: Show environment
run: |
bash --version
docker --version || true
compose_ver=$(docker compose version 2>/dev/null || true); echo "docker compose: $compose_ver"
- name: Generate docker-compose files (all)
run: bash scripts/generate-compose-files.sh all development
- name: Validate Docker SSoT consistency (envless)
run: DOCKER_SSOT_MODE=envless bash scripts/validate-docker-consistency.sh all
- name: Check drift of generated artifacts (ignore timestamps)
run: |
set -euo pipefail
CHANGED=$(git diff --name-only)
if [ -z "$CHANGED" ]; then
echo "No drift detected."
exit 0
fi
echo "Changed files:" $CHANGED
fail=0
for f in $CHANGED; do
DIFF_FILTERED=$(git diff --unified=0 -- "$f" \
| awk 'BEGIN{show=0} { \
if ($0 ~ /^\+\+\+|^---|^@@/) { next } \
if ($0 ~ /^[+-]# (Generated:|Last updated:)/) { next } \
if ($0 ~ /^[+-]#\s*Generated from docker\/versions.toml/) { next } \
if ($0 ~ /^[+-]#\s*Environment:/) { next } \
if ($0 ~ /^[+-]#\s*Source:/) { next } \
if ($0 ~ /^[+-]$/) { next } \
if ($0 ~ /^[+-]/) { print $0 } \
}')
if [ -n "$DIFF_FILTERED" ]; then
echo "SSoT drift detected in $f:";
echo "$DIFF_FILTERED";
fail=1;
fi
done
if [ $fail -ne 0 ]; then
echo "\nERROR: Generated artifacts differ from repository (beyond timestamps)."
echo "Run:"
echo " DOCKER_SSOT_MODE=envless bash scripts/generate-compose-files.sh all"
echo "and commit the changes."
exit 1
fi
echo "No SSoT drift (ignoring timestamps)."
# FIX: .yaml Extension nutzen (SSoT)
- name: Validate Docker Compose Config
run: docker compose --env-file docker/.env -f docker/docker-compose.yaml config