Private
Public Access
1
0
Files
EscapeFromTeacher/.github/workflows/deploy.yaml
Sebastian Unterschütz e295d1ad61
All checks were successful
Dynamic Branch Deploy / build-and-deploy (push) Successful in 15s
replace namespace placeholders across all manifests and update CiliumNetworkPolicy
2026-04-22 11:53:24 +02:00

216 lines
9.1 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
name: Dynamic Branch Deploy
on: [push]
env:
REGISTRY: git.zb-server.de
# WICHTIG: Deine echte Haupt-Domain
BASE_DOMAIN: escape-from-school.de
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
# 1. Code auschecken (fetch-depth: 2 für git diff gegen den vorherigen Commit)
- name: Checkout Code
uses: actions/checkout@v3
with:
fetch-depth: 2
# 2. Variablen vorbereiten (MIT HAUPT-DOMAIN LOGIK)
- name: Prepare Environment Variables
id: prep
run: |
# 1. Repo und Branch Namen säubern
# Voller Pfad für Docker Image (z.B. "user/escape-teacher")
FULL_IMAGE_PATH=$(echo "${{ gitea.repository }}" | tr '[:upper:]' '[:lower:]')
# Nur der Projektname für K8s (z.B. "escape-teacher")
REPO_LOWER=$(echo "$FULL_IMAGE_PATH" | cut -d'/' -f2)
# Branch Name säubern (Sonderzeichen zu Bindestrichen)
BRANCH_LOWER=$(echo "${{ gitea.ref_name }}" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9-]/-/g')
# 2. Logik: Ist es der Haupt-Branch?
if [ "$BRANCH_LOWER" = "main" ] || [ "$BRANCH_LOWER" = "master" ]; then
APP_URL="${{ env.BASE_DOMAIN }}"
TARGET_NS="${REPO_LOWER}"
BUILD_MODE="main"
echo "Mode: PRODUCTION (Root Domain)"
else
APP_URL="${REPO_LOWER}-${BRANCH_LOWER}.${{ env.BASE_DOMAIN }}"
TARGET_NS="${REPO_LOWER}-${BRANCH_LOWER}"
BUILD_MODE="dev"
echo "Mode: DEVELOPMENT (Subdomain)"
fi
# Image Tag (Commit Hash) und stabiler Branch-Tag
IMAGE_TAG="${{ gitea.sha }}"
BRANCH_TAG="${TARGET_NS}-latest"
# Debug Ausgabe
echo "DEBUG: Branch: $BRANCH_LOWER"
echo "DEBUG: Namespace: $TARGET_NS"
echo "DEBUG: URL: $APP_URL"
echo "DEBUG: Branch-Tag: $BRANCH_TAG"
echo "DEBUG: Build-Mode: $BUILD_MODE"
# In Gitea Actions Environment schreiben
echo "FULL_IMAGE_PATH=$FULL_IMAGE_PATH" >> $GITHUB_ENV
echo "REPO_NAME=$REPO_LOWER" >> $GITHUB_ENV
echo "TARGET_NS=$TARGET_NS" >> $GITHUB_ENV
echo "APP_URL=$APP_URL" >> $GITHUB_ENV
echo "IMAGE_TAG=$IMAGE_TAG" >> $GITHUB_ENV
echo "BRANCH_TAG=$BRANCH_TAG" >> $GITHUB_ENV
echo "BUILD_MODE=$BUILD_MODE" >> $GITHUB_ENV
# 3. Prüfen ob ein Image-Rebuild nötig ist
- name: Detect Source Changes
run: |
# Beim allerersten Commit gibt es kein HEAD~1 → immer bauen
if ! git rev-parse HEAD~1 >/dev/null 2>&1; then
echo "NEEDS_BUILD=true" >> $GITHUB_ENV
echo "→ Erster Commit, Image wird gebaut"
exit 0
fi
CHANGED=$(git diff --name-only HEAD~1 HEAD)
echo "Geänderte Dateien:"
echo "$CHANGED"
# Rebuild wenn Source-Code, Dockerfile oder Assets geändert wurden
if echo "$CHANGED" | grep -qE '(^Dockerfile$|^go\.(mod|sum)$|^(cmd|pkg|assets_raw)/)'; then
echo "NEEDS_BUILD=true" >> $GITHUB_ENV
echo "→ Quelldateien geändert Image wird neu gebaut"
else
echo "NEEDS_BUILD=false" >> $GITHUB_ENV
echo "→ Keine Quelländerungen Image-Build wird übersprungen"
fi
# 4. Image bauen und pushen (NUR wenn NEEDS_BUILD=true)
- name: Build and Push with Kaniko
if: env.NEEDS_BUILD == 'true'
uses: aevea/action-kaniko@v0.12.0
with:
registry: ${{ env.REGISTRY }}
username: ${{ gitea.actor }}
password: ${{ secrets.PACKAGE_TOKEN }}
image: ${{ env.FULL_IMAGE_PATH }}
tag: ${{ env.IMAGE_TAG }}
cache: true
extra_args: --skip-tls-verify-pull --insecure --build-arg BUILD_MODE=${{ env.BUILD_MODE }}
# 5. Stabilen Branch-Tag aktualisieren (NUR nach erfolgreichem Build)
# Damit weiß der nächste Nicht-Build-Push welches Image er verwenden soll.
- name: Tag as branch-latest
if: env.NEEDS_BUILD == 'true'
run: |
AUTH=$(echo -n "${{ gitea.actor }}:${{ secrets.PACKAGE_TOKEN }}" | base64 -w0)
REGISTRY_API="https://${{ env.REGISTRY }}/v2/${{ env.FULL_IMAGE_PATH }}"
# Fetch the manifest (try OCI index first, then v2, then v1)
for MEDIA_TYPE in \
"application/vnd.oci.image.index.v1+json" \
"application/vnd.docker.distribution.manifest.list.v2+json" \
"application/vnd.docker.distribution.manifest.v2+json" \
"application/vnd.oci.image.manifest.v1+json"; do
MANIFEST=$(curl -sk \
-H "Authorization: Basic $AUTH" \
-H "Accept: $MEDIA_TYPE" \
"${REGISTRY_API}/manifests/${{ env.IMAGE_TAG }}")
if echo "$MANIFEST" | grep -q '"mediaType"\|"schemaVersion"\|"manifests"\|"layers"'; then
break
fi
done
echo "Manifest fetched, pushing as ${{ env.BRANCH_TAG }}..."
curl -sk -X PUT \
-H "Authorization: Basic $AUTH" \
-H "Content-Type: $MEDIA_TYPE" \
-d "$MANIFEST" \
"${REGISTRY_API}/manifests/${{ env.BRANCH_TAG }}" \
-o /dev/null -w "HTTP %{http_code}\n"
# 6. Deploy-Image festlegen
# - Build passiert: SHA-Tag verwenden (exakt dieser Stand)
# - Build übersprungen: Branch-Latest-Tag verwenden (letztes gebautes Image)
- name: Set Deploy Image
run: |
if [ "$NEEDS_BUILD" = "true" ]; then
DEPLOY_IMAGE="${{ env.REGISTRY }}/${{ env.FULL_IMAGE_PATH }}:${{ env.IMAGE_TAG }}"
echo "→ Deploy mit neuem Image: $DEPLOY_IMAGE"
else
DEPLOY_IMAGE="${{ env.REGISTRY }}/${{ env.FULL_IMAGE_PATH }}:${{ env.BRANCH_TAG }}"
echo "→ Deploy mit bestehendem Image: $DEPLOY_IMAGE"
fi
echo "DEPLOY_IMAGE=$DEPLOY_IMAGE" >> $GITHUB_ENV
# 7. Setup Kubectl
- name: Setup Kubectl
run: |
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
chmod +x kubectl
mv kubectl /usr/local/bin/
mkdir -p $HOME/.kube
echo "${{ secrets.KUBE_CONFIG }}" > $HOME/.kube/config
chmod 600 $HOME/.kube/config
# Internal DNS Trick (für Kommunikation innerhalb des Clusters)
sed -i 's|server: https://.*:6443|server: https://kubernetes.default.svc:443|g' $HOME/.kube/config
# 8. Deploy to Kubernetes
- name: Deploy to Kubernetes
run: |
# Namespace erstellen (falls nicht existiert)
kubectl create namespace ${{ env.TARGET_NS }} --dry-run=client -o yaml | kubectl apply -f -
# Platzhalter in allen K8s-Manifesten ersetzen
sed -i "s|\${APP_URL}|${{ env.APP_URL }}|g" k8s/ingress.yaml
sed -i "s|\${IMAGE_NAME}|${{ env.DEPLOY_IMAGE }}|g" k8s/app.yaml
# TARGET_NS überall ersetzen (z.B. für Middlewares oder explizite Namespaces)
find k8s/ -name "*.yaml" -exec sed -i "s|\${TARGET_NS}|${{ env.TARGET_NS }}|g" {} +
# Admin-Credentials Secret anlegen/aktualisieren (aus Gitea Secret)
kubectl create secret generic admin-credentials \
--from-literal=username="${{ secrets.ADMIN_USER }}" \
--from-literal=password="${{ secrets.ADMIN_PASSWORD }}" \
--namespace=${{ env.TARGET_NS }} \
--dry-run=client -o yaml | kubectl apply -f -
# Anwenden
echo "Deploying to Namespace: ${{ env.TARGET_NS }} (Image: ${{ env.DEPLOY_IMAGE }})"
kubectl apply -f k8s/compress-middleware.yaml -n ${{ env.TARGET_NS }}
kubectl apply -f k8s/pvc.yaml -n ${{ env.TARGET_NS }}
kubectl apply -f k8s/nats.yaml -n ${{ env.TARGET_NS }}
kubectl apply -f k8s/redis.yaml -n ${{ env.TARGET_NS }}
kubectl apply -f k8s/app.yaml -n ${{ env.TARGET_NS }}
kubectl apply -f k8s/cilium-netpol.yaml -n ${{ env.TARGET_NS }}
kubectl apply -f k8s/ingress.yaml -n ${{ env.TARGET_NS }}
# HPA nur für Main/Master Branch
if [ "${{ env.TARGET_NS }}" == "${{ env.REPO_NAME }}" ]; then
echo "Main Branch: Applying HPA..."
kubectl apply -f k8s/hpa.yaml -n ${{ env.TARGET_NS }}
else
echo "Feature Branch: Skipping HPA."
kubectl delete hpa escape-game-hpa -n ${{ env.TARGET_NS }} --ignore-not-found
fi
# Pod nur neu starten wenn ein neues Image gebaut wurde
# Bei reinen k8s-Änderungen reicht kubectl apply, kein Restart nötig
if [ "$NEEDS_BUILD" = "true" ]; then
kubectl rollout restart deployment/escape-game -n ${{ env.TARGET_NS }}
fi
# 9. Summary
- name: Summary
run: |
if [ "$NEEDS_BUILD" = "true" ]; then
echo "🔨 Image neu gebaut und deployed: ${{ env.DEPLOY_IMAGE }}"
else
echo "⚡ Image-Build übersprungen (keine Quelländerungen)"
echo "📦 Bestehendes Image verwendet: ${{ env.DEPLOY_IMAGE }}"
fi
echo "🚀 Deployed to https://${{ env.APP_URL }}"