Docker Image bauen und veroeffentlichen / typecheck (push) Failing after 1m56s
Docker Image bauen und veroeffentlichen / lint (push) Successful in 2m17s
Docker Image bauen und veroeffentlichen / test (push) Successful in 3m10s
Docker Image bauen und veroeffentlichen / build-and-push (push) Skipped
Der Workflow baute bisher bei jedem Push auf main ungeprueft ein Image. Jetzt laufen lint (inkl. pnpm audit ab high), typecheck und test auf dem isolierten Runner (ci-isolated, ohne Docker-Socket und Clusternetz); build-and-push startet nur, wenn alle drei gruen sind. Muster und Runner-Pruefskript aus dem VyCept-Repo (docs/BETRIEB.md 11b). Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
193 lines
8.2 KiB
YAML
193 lines
8.2 KiB
YAML
name: Docker Image bauen und veroeffentlichen
|
|
|
|
# Laeuft bei jedem Push auf main (rollierendes ":latest" + ":<kurzer-commit-hash>")
|
|
# und bei Versions-Tags wie "v1.2.3" (zusaetzlich als eigener Tag). Manuell
|
|
# ueber "Run workflow" in der Gitea-Weboberflaeche ebenfalls startbar.
|
|
#
|
|
# Qualitaets-Gate: Ein Image entsteht nur, wenn lint (inkl. audit), typecheck
|
|
# und test gruen sind. Die Pruefungen laufen auf "ci-isolated" (Jobs ohne
|
|
# Docker-Socket und ohne Clusternetz, Runner-Doku im VyCept-Repo,
|
|
# docs/BETRIEB.md 11b); nur der Image-Build braucht "docker-builder".
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
tags: ["v*"]
|
|
workflow_dispatch:
|
|
|
|
# Ein neuer Push bricht den ueberholten Lauf ab, statt ihn zu Ende zu rechnen.
|
|
concurrency:
|
|
group: docker-build-${{ gitea.ref }}
|
|
cancel-in-progress: true
|
|
|
|
env:
|
|
NEXT_TELEMETRY_DISABLED: "1"
|
|
|
|
jobs:
|
|
lint:
|
|
runs-on: ci-isolated
|
|
timeout-minutes: 10
|
|
steps:
|
|
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
|
|
- name: Runner-Isolation pruefen
|
|
run: bash scripts/ci-runner-isolation.sh
|
|
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
|
with: { node-version: "22" }
|
|
- uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
|
|
with:
|
|
path: |
|
|
~/.cache/pnpm
|
|
~/.cache/pnpm-store
|
|
key: pnpm-${{ hashFiles('pnpm-lock.yaml') }}
|
|
restore-keys: pnpm-
|
|
- run: export pnpm_config_store_dir="$HOME/.cache/pnpm-store" pnpm_config_cache_dir="$HOME/.cache/pnpm" && corepack enable && pnpm install --frozen-lockfile
|
|
- run: pnpm lint
|
|
# Bekannte Luecken in Laufzeit-Abhaengigkeiten (ab "high") brechen den Lauf ab.
|
|
- run: pnpm audit --prod --audit-level high
|
|
|
|
typecheck:
|
|
runs-on: ci-isolated
|
|
timeout-minutes: 10
|
|
steps:
|
|
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
|
|
- name: Runner-Isolation pruefen
|
|
run: bash scripts/ci-runner-isolation.sh
|
|
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
|
with: { node-version: "22" }
|
|
- uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
|
|
with:
|
|
path: |
|
|
~/.cache/pnpm
|
|
~/.cache/pnpm-store
|
|
key: pnpm-${{ hashFiles('pnpm-lock.yaml') }}
|
|
restore-keys: pnpm-
|
|
# postinstall erzeugt beide Prisma-Clients (Postgres + MySQL), die tsc braucht.
|
|
- run: export pnpm_config_store_dir="$HOME/.cache/pnpm-store" pnpm_config_cache_dir="$HOME/.cache/pnpm" && corepack enable && pnpm install --frozen-lockfile
|
|
- run: pnpm typecheck
|
|
|
|
test:
|
|
runs-on: ci-isolated
|
|
timeout-minutes: 15
|
|
steps:
|
|
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
|
|
- name: Runner-Isolation pruefen
|
|
run: bash scripts/ci-runner-isolation.sh
|
|
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
|
with: { node-version: "22" }
|
|
- uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
|
|
with:
|
|
path: |
|
|
~/.cache/pnpm
|
|
~/.cache/pnpm-store
|
|
key: pnpm-${{ hashFiles('pnpm-lock.yaml') }}
|
|
restore-keys: pnpm-
|
|
- run: export pnpm_config_store_dir="$HOME/.cache/pnpm-store" pnpm_config_cache_dir="$HOME/.cache/pnpm" && corepack enable && pnpm install --frozen-lockfile
|
|
# Unit- und Komponententests (jsdom), ohne Datenbank.
|
|
- run: pnpm test
|
|
|
|
build-and-push:
|
|
needs: [lint, typecheck, test]
|
|
runs-on: docker-builder
|
|
env:
|
|
# Fest hinterlegt statt ${{ gitea.server_url }}: das hat in manchen
|
|
# Gitea-Versionen einen Bug (leerer Wert im Runner, siehe
|
|
# go-gitea/gitea#23276) und liefert selbst wenn es funktioniert eine
|
|
# volle URL MIT "https://"-Schema — docker login/Image-Tags brauchen
|
|
# aber den reinen Hostnamen ohne Schema. Bei einem Umzug auf eine
|
|
# andere Gitea-Instanz hier anpassen. Nur noch fuer Doku/OCI-Labels
|
|
# relevant — der eigentliche Push laeuft ueber REGISTRY_PUSH (s.u.),
|
|
# Kubernetes zieht die Images weiterhin ueber diesen Hostnamen.
|
|
REGISTRY: git.encry.de
|
|
# Gitea-Registry-Push laeuft ueber den Cluster-internen Service-Namen
|
|
# statt git.encry.de: Docker-Registry-Blob-Uploads (PUT) vertragen sich
|
|
# nicht mit dem Cloudflare-Proxy vor git.encry.de — "413 Payload Too
|
|
# Large" auch bei kleinen Layern, unabhaengig von der eigentlichen
|
|
# Groesse. Der Runner-Pod (gitea-runner, Namespace "gitea") erreicht
|
|
# den Gitea-Service direkt ueber Kubernetes-DNS ("gitea:80" — siehe
|
|
# dessen eigene GITEA_INSTANCE_URL-Env, die denselben Hostnamen nutzt),
|
|
# ohne ueber Cloudflare zu hairpinnen. Push und Pull landen im selben
|
|
# Registry-Pfad (Owner/Repo:Tag) — der Hostname ist nur die Verbindung,
|
|
# nicht Teil des gespeicherten Images, daher bleibt der Pull in den
|
|
# k8s-Manifesten unveraendert ueber git.encry.de.
|
|
REGISTRY_PUSH: gitea:80
|
|
steps:
|
|
- name: Code auschecken
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Image-Namen in Kleinbuchstaben ermitteln
|
|
# OCI-Registries erlauben nur Kleinbuchstaben im Repository-Pfad;
|
|
# ${{ gitea.repository }} ("Owner/Repo") behaelt die Gross-/
|
|
# Kleinschreibung des Gitea-Repos bei.
|
|
id: image
|
|
run: echo "name=$(echo '${{ gitea.repository }}' | tr '[:upper:]' '[:lower:]')" >> "$GITEA_OUTPUT"
|
|
|
|
- name: Docker Buildx einrichten
|
|
uses: docker/setup-buildx-action@v3
|
|
with:
|
|
# REGISTRY_PUSH ist Klartext-HTTP (Gitea-Service intern ohne TLS)
|
|
# statt HTTPS — BuildKit lehnt das ohne diese Freigabe ab.
|
|
config-inline: |
|
|
[registry."gitea:80"]
|
|
http = true
|
|
|
|
- name: Bei der Gitea-Container-Registry anmelden
|
|
uses: docker/login-action@v3
|
|
with:
|
|
registry: ${{ env.REGISTRY_PUSH }}
|
|
username: ${{ gitea.actor }}
|
|
# GITEA_TOKEN hat aktuell KEIN Package-Write-Recht (Gitea-
|
|
# Einschraenkung, Stand heute) — deshalb ein separates Personal
|
|
# Access Token als Repo-/Org-Secret REGISTRY_TOKEN anlegen
|
|
# (Scope: "package", Gitea-Einstellungen -> Anwendungen ->
|
|
# Access Tokens) und unter Repo-Einstellungen -> Actions ->
|
|
# Secrets als REGISTRY_TOKEN hinterlegen.
|
|
password: ${{ secrets.REGISTRY_TOKEN }}
|
|
|
|
- name: Metadaten (Tags/Labels) ermitteln
|
|
id: meta
|
|
uses: docker/metadata-action@v5
|
|
with:
|
|
images: ${{ env.REGISTRY_PUSH }}/${{ steps.image.outputs.name }}
|
|
tags: |
|
|
type=raw,value=latest,enable={{is_default_branch}}
|
|
type=sha,format=short
|
|
type=semver,pattern={{version}}
|
|
|
|
- name: Metadaten Werkzeuge
|
|
id: meta-tools
|
|
uses: docker/metadata-action@v5
|
|
with:
|
|
images: ${{ env.REGISTRY_PUSH }}/${{ steps.image.outputs.name }}-tools
|
|
tags: |
|
|
type=raw,value=latest,enable={{is_default_branch}}
|
|
type=sha,format=short
|
|
type=semver,pattern={{version}}
|
|
|
|
# Ein einzelnes Image traegt beide Prisma-Client-Varianten (Postgres +
|
|
# MySQL, waehlt zur Laufzeit per DATABASE_PROVIDER, siehe
|
|
# src/lib/prisma.ts) UND die Migrations-/Seed-Tools (siehe Dockerfile-
|
|
# Kommentar bei "AS migrator") — die App migriert/seedet sich beim
|
|
# Start selbst (idempotent), kein separates Migrations-Image/Job mehr.
|
|
- name: Image bauen und pushen
|
|
uses: docker/build-push-action@v6
|
|
with:
|
|
context: .
|
|
target: runner
|
|
push: true
|
|
tags: ${{ steps.meta.outputs.tags }}
|
|
labels: ${{ steps.meta.outputs.labels }}
|
|
cache-from: type=gha
|
|
cache-to: type=gha,mode=max
|
|
|
|
# Werkzeug-Image fuer die CronJobs (Dockerfile "AS tools"); nutzt die
|
|
# gemeinsamen Build-Stufen aus dem Cache des ersten Builds.
|
|
- name: Werkzeuge bauen und pushen
|
|
uses: docker/build-push-action@v6
|
|
with:
|
|
context: .
|
|
target: tools
|
|
push: true
|
|
tags: ${{ steps.meta-tools.outputs.tags }}
|
|
labels: ${{ steps.meta-tools.outputs.labels }}
|
|
cache-from: type=gha
|
|
cache-to: type=gha,mode=max
|