name: Build and Publish Docker Images run-name: Build & Publish by @${{ github.actor }} on: push: branches: [ "main" ] paths: - 'backend/**' - 'platform/**' - 'core/**' - 'frontend/**' - 'config/docker/**' - 'docker-compose.yaml' - '.gitea/workflows/docker-publish.yaml' env: # Interner Registry-Endpunkt: direkter HTTP-Zugriff, umgeht Pangolin-Tunnel komplett REGISTRY_INTERNAL: 10.0.0.22:3000 IMAGE_PREFIX: mocode-software/meldestelle JAVA_VERSION: "25" GRADLE_VERSION: "9.4.0" KEYCLOAK_IMAGE_TAG: "26.5.5" # Workers auf 4 limitiert: verhindert OOM auf dem 16GB Runner (VM 102) GRADLE_OPTS: "-Dorg.gradle.parallel=true -Dorg.gradle.workers.max=4" JVM_OPTS_ARM64: "-XX:ActiveProcessorCount=8 -XX:+UseZGC -XX:+UseTransparentHugePages" jobs: build-and-push: runs-on: ubuntu-latest strategy: fail-fast: false # max-parallel: 1 → sequenzielle Ausführung verhindert RAM-OOM auf Zora (16GB VM) max-parallel: 1 matrix: include: # Plan-B fokussiert: Nur Mail-Service + Web-App bauen/pushen (beschleunigt CI deutlich) - service: mail-service context: . dockerfile: backend/services/mail/Dockerfile image: mail-service - service: web-app context: . dockerfile: config/docker/caddy/web-app/Dockerfile image: web-app steps: - name: Checkout repository uses: actions/checkout@v4 - name: Set up JDK ${{ env.JAVA_VERSION }} uses: actions/setup-java@v4 with: java-version: ${{ env.JAVA_VERSION }} distribution: "temurin" cache: gradle - name: Setup Gradle Cache uses: actions/cache@v4 with: path: | ~/.gradle/caches ~/.gradle/wrapper key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} restore-keys: | ${{ runner.os }}-gradle- # Verhindert mysteriöse Build-Fehler durch korrupte Node/Kotlin-Caches (nur web-app relevant) - name: Cleanup stale build caches if: matrix.service == 'web-app' run: | rm -rf frontend/shells/meldestelle-web/build/js/node_modules/.cache || true rm -rf frontend/shells/meldestelle-web/build/js/.yarn/cache || true rm -rf ~/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-compiler-embeddable || true - name: Build Frontend (Wasm JS) if: matrix.service == 'web-app' run: | chmod +x gradlew ./gradlew :frontend:shells:meldestelle-web:wasmJsBrowserDistribution \ -Pproduction=true \ --max-workers=4 \ -Dkotlin.daemon.jvm.options="-Xmx4g" - name: Stage Web Assets for Docker build if: matrix.service == 'web-app' run: | set -e DIST_DIR="frontend/shells/meldestelle-web/build/dist/wasmJs/productionExecutable" if [ ! -d "$DIST_DIR" ]; then echo "❌ Erwarteter Build-Ordner nicht gefunden: $DIST_DIR" >&2 echo "Hinweis: Prüfe Gradle-Ausgabe und Modulpfad (:frontend:shells:meldestelle-web)" >&2 ls -la frontend/shells/meldestelle-web/build || true exit 1 fi mkdir -p config/docker/caddy/web-app/_site rsync -a --delete "$DIST_DIR/" config/docker/caddy/web-app/_site/ echo "✓ Assets gestaged: config/docker/caddy/web-app/_site" ls -la config/docker/caddy/web-app/_site | sed -n '1,200p' # Pangolin-Bypass: Credentials direkt in config.json schreiben. # Kein "docker login" → kein Daemon-Ping → kein HTTPS-Fehler. # BuildKit liest ~/.docker/config.json und verwendet diese Credentials beim Push. # - name: Registry-Credentials konfigurieren (kein Daemon-Kontakt) # run: | # mkdir -p ~/.docker # AUTH=$(echo -n "${{ secrets.REGISTRY_USER }}:${{ secrets.REGISTRY_TOKEN }}" | base64 -w 0) # printf '{"auths":{"%s":{"auth":"%s"}}}\n' "${{ env.REGISTRY_INTERNAL }}" "${AUTH}" > ~/.docker/config.json # echo "✓ Credentials für ${{ env.REGISTRY_INTERNAL }} gespeichert" # NEU (sauber, nach daemon.json-Fix): - name: Login to Gitea Registry uses: docker/login-action@v3 with: registry: ${{ env.REGISTRY_INTERNAL }} username: ${{ secrets.REGISTRY_USER }} password: ${{ secrets.REGISTRY_TOKEN }} # BuildKit-Instanz mit HTTP-Unterstützung für die interne Registry konfigurieren. # KEIN sudo, KEIN systemctl, KEIN Neustart — rein konfigurativ. - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 with: config-inline: | [registry."10.0.0.22:3000"] http = true insecure = true - name: Extract metadata id: meta uses: docker/metadata-action@v5 with: images: ${{ env.REGISTRY_INTERNAL }}/${{ env.IMAGE_PREFIX }}/${{ matrix.image }} tags: | type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }} type=sha,format=long - name: Build and push Docker image uses: docker/build-push-action@v6 with: context: ${{ matrix.context }} file: ${{ matrix.dockerfile }} push: true platforms: linux/arm64 tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} provenance: false sbom: false build-args: | DOCKER_BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ') VERSION=${{ github.sha }} GRADLE_VERSION=${{ env.GRADLE_VERSION }} JAVA_VERSION=${{ env.JAVA_VERSION }} KEYCLOAK_IMAGE_TAG=${{ env.KEYCLOAK_IMAGE_TAG }} JVM_OPTS_APPEND=${{ env.JVM_OPTS_ARM64 }}