ci: Qualitaets-Gate vor dem Image-Build
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
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]>
This commit is contained in:
1 parent
835323e466
commit
85d1a46f64
2 files changed
+135
No files matched your search
@@ -3,14 +3,89 @@ 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
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
#!/usr/bin/env bash
|
||||
# Prüft im CI-Job die Grenzen des isolierten Runners (Label ci-isolated,
|
||||
# Runner-Doku im VyCept-Repo, docs/BETRIEB.md 11b; Kopie von dort). Läuft als erster Schritt jedes Prüf-Jobs, damit jeder
|
||||
# Runner bei jedem Lauf geprüft wird. Schlägt fehl, wenn der Job mehr darf als
|
||||
# vorgesehen – oder wenn die Prüfung selbst nichts aussagen würde.
|
||||
set -euo pipefail
|
||||
|
||||
fail() {
|
||||
echo "Runner-Isolation verletzt: $*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
reachable() {
|
||||
timeout 5 bash -c "exec 3<>/dev/tcp/$1/$2" 2>/dev/null
|
||||
}
|
||||
|
||||
# Namen mit Wiederholung auflösen: Das DNS des Job-Netzes antwortet unter Last
|
||||
# gelegentlich erst beim zweiten Versuch.
|
||||
resolve() {
|
||||
local address=""
|
||||
for _ in 1 2 3 4 5; do
|
||||
address=$(getent hosts "$1" | awk '{ print $1; exit }' || true)
|
||||
if [ -n "$address" ]; then echo "$address"; return 0; fi
|
||||
sleep 2
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
# 1. Kein Zugang zum Docker-Daemon über den Socket.
|
||||
[ -z "${DOCKER_HOST:-}" ] || fail "DOCKER_HOST ist gesetzt ($DOCKER_HOST)"
|
||||
for socket in /var/run/docker.sock /run/docker.sock; do
|
||||
[ ! -e "$socket" ] || fail "Docker-Socket $socket ist sichtbar"
|
||||
done
|
||||
|
||||
# 2. Kein Zugang zur Docker-API des Daemons im Runner-Pod (Gateway des Job-Netzes):
|
||||
# 2375 (ohne TLS) zu, 2376 nur mit Client-Zertifikat, das der Job nicht hat.
|
||||
gateway_hex=$(awk '$2 == "00000000" { print $3; exit }' /proc/net/route)
|
||||
[ -n "$gateway_hex" ] || fail "kein Standard-Gateway gefunden – Prüfung wäre wirkungslos"
|
||||
gateway=$(printf '%d.%d.%d.%d' "0x${gateway_hex:6:2}" "0x${gateway_hex:4:2}" "0x${gateway_hex:2:2}" "0x${gateway_hex:0:2}")
|
||||
if reachable "$gateway" 2375; then fail "Docker-API ohne TLS am Gateway $gateway:2375"; fi
|
||||
if curl -sk --max-time 5 "https://$gateway:2376/version" >/dev/null 2>&1; then
|
||||
fail "Docker-API am Gateway $gateway:2376 ohne Client-Zertifikat nutzbar"
|
||||
fi
|
||||
|
||||
# 3. Kein Clusternetz: Kubernetes-API (Service und Knoten) und fremde Namespaces.
|
||||
for target in 10.43.0.1:443 10.50.1.51:6443 10.50.1.52:6443 10.50.1.53:6443; do
|
||||
if reachable "${target%:*}" "${target##*:}"; then fail "$target ist erreichbar"; fi
|
||||
done
|
||||
resolve kubernetes.default.svc.cluster.local >/dev/null || fail "Clusternamen nicht auflösbar – Prüfung wäre wirkungslos"
|
||||
# Fremder Namespace (VyCept-Datenbank) und eigener Namespace (Gitea-Datenbank).
|
||||
for target in vycept-postgres.vycept.svc.cluster.local:5432 gitea-postgres.gitea.svc.cluster.local:5432; do
|
||||
host=${target%:*}
|
||||
address=$(resolve "$host") || fail "$host nicht auflösbar – Prüfung wäre wirkungslos"
|
||||
if reachable "$address" "${target##*:}"; then fail "$host ($address) ist erreichbar"; fi
|
||||
done
|
||||
|
||||
# 4. Internet bleibt erreichbar (npm, GitHub, Images).
|
||||
reachable registry.npmjs.org 443 || fail "Internet (registry.npmjs.org) nicht erreichbar"
|
||||
|
||||
echo "Runner-Isolation in Ordnung (Gateway $gateway, kein Socket, kein Clusternetz)"
|
||||
Reference in new issue
Block a user