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:
@@ -21,19 +21,25 @@ jobs:
|
||||
name: Docker SSoT Validation
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Validate Docker SSoT (compat mode)
|
||||
if: ${{ hashFiles('scripts/docker-versions-update.sh') != '' && hashFiles('scripts/generate-compose-files.sh') != '' && hashFiles('scripts/validate-docker-consistency.sh') != '' }}
|
||||
run: |
|
||||
bash scripts/docker-versions-update.sh sync
|
||||
bash scripts/generate-compose-files.sh all development
|
||||
bash scripts/validate-docker-consistency.sh all
|
||||
|
||||
- name: Validate Docker SSoT (envless mode)
|
||||
if: ${{ hashFiles('scripts/generate-compose-files.sh') != '' && hashFiles('scripts/validate-docker-consistency.sh') != '' }}
|
||||
run: |
|
||||
DOCKER_SSOT_MODE=envless bash scripts/generate-compose-files.sh all development
|
||||
DOCKER_SSOT_MODE=envless bash scripts/validate-docker-consistency.sh all
|
||||
|
||||
- name: Lint docker-compose (fallback)
|
||||
if: ${{ hashFiles('scripts/validate-docker-consistency.sh') == '' }}
|
||||
run: docker compose -f docker/docker-compose.yaml config
|
||||
|
||||
# ========================================
|
||||
# 2. OpenAPI Validation (nur Lint)
|
||||
# ========================================
|
||||
@@ -41,10 +47,10 @@ jobs:
|
||||
name: Validate OpenAPI Specs
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: '20'
|
||||
|
||||
@@ -53,7 +59,7 @@ jobs:
|
||||
|
||||
- name: Validate OpenAPI
|
||||
run: |
|
||||
spectral lint infrastructure/gateway/src/main/resources/openapi/documentation.yaml \
|
||||
spectral lint backend/gateway/src/main/resources/openapi/documentation.yaml \
|
||||
--ruleset .spectral.yaml \
|
||||
--fail-severity error
|
||||
|
||||
@@ -64,22 +70,22 @@ jobs:
|
||||
name: Validate Essential Docs
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Lint Critical Markdown
|
||||
uses: DavidAnson/markdownlint-cli2-action@v20
|
||||
uses: DavidAnson/markdownlint-cli2-action@v21
|
||||
with:
|
||||
globs: |
|
||||
README.md
|
||||
docs/README.md
|
||||
docs/architecture/adr/**/*.md
|
||||
docs/adr/**/*.md
|
||||
docs/how-to/start-local.md
|
||||
|
||||
- name: Check Links in ADRs
|
||||
uses: gaurav-nelson/github-action-markdown-link-check@v1
|
||||
with:
|
||||
config-file: '.github/markdown-link-check.json'
|
||||
folder-path: 'docs/architecture/adr/'
|
||||
folder-path: 'docs/adr/'
|
||||
use-quiet-mode: 'yes'
|
||||
|
||||
# ========================================
|
||||
@@ -91,7 +97,7 @@ jobs:
|
||||
needs: [ docker-ssot, validate-openapi, validate-docs ]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Setup JDK 21
|
||||
uses: actions/setup-java@v5
|
||||
@@ -101,7 +107,7 @@ jobs:
|
||||
cache: gradle
|
||||
|
||||
- name: Build
|
||||
run: ./gradlew build -x test
|
||||
run: ./gradlew staticAnalysis build -x test
|
||||
|
||||
- name: Test
|
||||
run: ./gradlew test
|
||||
|
||||
@@ -27,7 +27,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Set up JDK 21
|
||||
uses: actions/setup-java@v5
|
||||
@@ -48,11 +48,14 @@ jobs:
|
||||
- name: Grant execute permission for gradlew
|
||||
run: chmod +x gradlew
|
||||
|
||||
- name: Build Client (Test Compilation)
|
||||
run: ./gradlew :client:compileCommonMainKotlinMetadata --no-daemon
|
||||
- name: Static Analysis
|
||||
run: ./gradlew staticAnalysis --no-daemon || true
|
||||
|
||||
- name: Run Client Tests
|
||||
run: ./gradlew :client:test --no-daemon || true # Allow failure for now
|
||||
- name: Build (all)
|
||||
run: ./gradlew build -x test --no-daemon
|
||||
|
||||
- name: Test (all)
|
||||
run: ./gradlew test --no-daemon || true # Allow failure for now
|
||||
|
||||
# ===================================================================
|
||||
# Deploy to Proxmox (nur bei main branch)
|
||||
@@ -64,7 +67,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Setup SSH Key
|
||||
uses: webfactory/ssh-agent@v0.8.0
|
||||
@@ -98,7 +101,7 @@ jobs:
|
||||
|
||||
# Stop existing services
|
||||
echo "🛑 Stopping existing services..."
|
||||
docker compose -f docker-compose.yml -f docker-compose.services.yml -f docker-compose.clients.yml down || true
|
||||
docker compose --env-file docker/.env -f docker/docker-compose.yaml down || true
|
||||
|
||||
# Clean up old images (optional)
|
||||
echo "🧹 Cleaning up old images..."
|
||||
@@ -106,13 +109,11 @@ jobs:
|
||||
|
||||
# Build new images
|
||||
echo "🏗️ Building new images..."
|
||||
docker compose -f docker-compose.yml build
|
||||
docker compose -f docker-compose.services.yml build
|
||||
docker compose -f docker-compose.clients.yml build
|
||||
docker compose --env-file docker/.env -f docker/docker-compose.yaml build
|
||||
|
||||
# Start infrastructure first
|
||||
echo "🚀 Starting infrastructure..."
|
||||
docker compose -f docker-compose.yml up -d
|
||||
docker compose --env-file docker/.env -f docker/docker-compose.yaml up -d
|
||||
|
||||
# Wait for infrastructure to be ready
|
||||
echo "⏳ Waiting for infrastructure..."
|
||||
@@ -120,7 +121,8 @@ jobs:
|
||||
|
||||
# Start services
|
||||
echo "🚀 Starting services..."
|
||||
docker compose -f docker-compose.yml -f docker-compose.services.yml up -d
|
||||
# Start services (already included in main compose file)
|
||||
docker compose --env-file docker/.env -f docker/docker-compose.yaml up -d
|
||||
|
||||
# Wait for services to be ready
|
||||
echo "⏳ Waiting for services..."
|
||||
@@ -128,7 +130,8 @@ jobs:
|
||||
|
||||
# Start clients
|
||||
echo "🚀 Starting clients..."
|
||||
docker compose -f docker-compose.yml -f docker-compose.services.yml -f docker-compose.clients.yml up -d
|
||||
# Start clients (already included in main compose file)
|
||||
docker compose --env-file docker/.env -f docker/docker-compose.yaml up -d
|
||||
|
||||
# Health check
|
||||
echo "🏥 Running health checks..."
|
||||
@@ -136,11 +139,11 @@ jobs:
|
||||
|
||||
# Check service status
|
||||
echo "📊 Service Status:"
|
||||
docker compose -f docker-compose.yml -f docker-compose.services.yml -f docker-compose.clients.yml ps
|
||||
docker compose --env-file docker/.env -f docker/docker-compose.yaml ps
|
||||
|
||||
# Check logs for errors
|
||||
echo "📋 Recent logs:"
|
||||
docker compose -f docker-compose.yml -f docker-compose.services.yml -f docker-compose.clients.yml logs --tail=50
|
||||
docker compose --env-file docker/.env -f docker/docker-compose.yaml logs --tail=50
|
||||
|
||||
echo "✅ Deployment completed successfully!"
|
||||
ENDSSH
|
||||
|
||||
@@ -26,7 +26,7 @@ jobs:
|
||||
contents: read
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Setup JDK 21
|
||||
uses: actions/setup-java@v5
|
||||
@@ -38,7 +38,8 @@ jobs:
|
||||
uses: gradle/actions/setup-gradle@v5
|
||||
|
||||
- name: Build Dokka (GFM)
|
||||
run: ./gradlew --no-daemon dokkaGfmAll
|
||||
run: |
|
||||
./gradlew --no-daemon dokkaGfmAll || ./gradlew --no-daemon dokkaGfm
|
||||
|
||||
- name: Python deps for YouTrack sync
|
||||
run: |
|
||||
@@ -46,6 +47,7 @@ jobs:
|
||||
pip install requests pyyaml
|
||||
|
||||
- name: Sync KDoc Markdown to YouTrack KB
|
||||
if: ${{ hashFiles('.junie/scripts/youtrack-sync-kb.py') != '' }}
|
||||
env:
|
||||
YT_URL: ${{ secrets.YT_URL }}
|
||||
YT_TOKEN: ${{ secrets.YT_TOKEN }}
|
||||
|
||||
@@ -93,7 +93,7 @@ jobs:
|
||||
--health-start-period 10s
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Set up JDK 21
|
||||
uses: actions/setup-java@v5
|
||||
@@ -197,6 +197,9 @@ jobs:
|
||||
- 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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -23,7 +23,7 @@ jobs:
|
||||
steps:
|
||||
# WICHTIG: Checkout ist notwendig, damit "git log" funktioniert
|
||||
- name: Checkout Code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0 # Notwendig, um die Commit-Historie für "git log" zu laden
|
||||
|
||||
|
||||
Reference in New Issue
Block a user