@@ -2,101 +2,162 @@ name: Build & Deploy
on :
push :
branches : [ main, staging]
branches :
- main
tags :
- 'v*'
jobs :
build-and-deploy :
runs-on : docker
steps :
# ═══════════════════════════════════════════════════════════════════════════════
# LOGGING: Workflow Start - Full Transparency
# ═══════════════════════════════════════════════════════════════════════════════
- name : 📋 Log Workflow Start
# ──────────────────────────────────────────────────────────────────────────────
# Workflow Start & Basic Info
# ──────────────────────────────────────────────────────────────────────────────
- name : 📢 Workflow Start
run : |
echo "🚀 Starting deployment for ${{ github.repository }} (${{ github.ref }}) "
echo " • Branch: ${{ github.ref_name }} "
echo " • Commit: ${{ github.sha }} "
echo " • Timestamp: $(date -u +'%Y-%m-%d %H:%M:%S UTC')"
echo "┌──────────────────────────────────────────────────────────────┐ "
echo "│ 🚀 Deployment Workflow gestartet │ "
echo "├──────────────────────────────────────────────────────────────┤ "
echo "│ Repository: ${{ github.repository }} │"
echo "│ Ref: ${{ github.ref }} │"
echo "│ Ref-Name: ${{ github.ref_name }} │"
echo "│ Commit: ${{ github.sha }} │"
echo "│ Actor: ${{ github.actor }} │"
echo "│ Datum: $(date -u +'%Y-%m-%d %H:%M:%S UTC') │"
echo "└──────────────────────────────────────────────────────────────┘"
- name : Checkout repository
uses : actions/checkout@v4
with :
fetch-depth : 0
# ═══════════════════════════════════════════════════════════════════════════════
# LOGGING: Registry Login Phase
# ═══════════════════════════════════════════════════════════════════════════════
- name : 🔐 Login to private registry
# ──────────────────────────────────────────────────────────────────────────────
# Environment bestimmen + Commit-Message holen
# ──────────────────────────────────────────────────────────────────────────────
- name : 🔍 Environment & Version ermitteln
id : determine
run : |
echo "🔐 Authenticating with registry.infra.mintel.me... "
TAG="${{ github.ref_name }} "
SHORT_SHA="${{ github.sha }}"
SHORT_SHA="${SHORT_SHA:0:9}"
# Get base domain from secret or env if possible, otherwise placeholder
# In a real project, you'd likely have a primary domain secret
DOMAIN_BASE=$(echo "${{ secrets.NEXT_PUBLIC_BASE_URL }}" | sed -E 's|https?://||' | sed -E 's|/.*||')
# Commit-Message holen (erste Zeile)
COMMIT_MSG=$(git log -1 --pretty=%s || echo "No commit message available")
if [[ "${{ github.ref_type }}" == "branch" && "$TAG" == "main" ]]; then
TARGET="testing"
IMAGE_TAG="main-${SHORT_SHA}"
ENV_FILE=".env.testing"
TRAEFIK_HOST="\`testing.${DOMAIN_BASE}\`"
IS_PROD="false"
GOTIFY_TITLE="🧪 Testing-Deploy"
GOTIFY_PRIORITY=4
elif [[ "${{ github.ref_type }}" == "tag" ]]; then
if [[ "$TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
TARGET="production"
IMAGE_TAG="$TAG"
ENV_FILE=".env.prod"
TRAEFIK_HOST="\`${DOMAIN_BASE}\`, \`www.${DOMAIN_BASE}\`"
IS_PROD="true"
GOTIFY_TITLE="🚀 Production-Release"
GOTIFY_PRIORITY=6
elif [[ "$TAG" =~ -rc\. || "$TAG" =~ -beta\. || "$TAG" =~ -alpha\. ]]; then
TARGET="staging"
IMAGE_TAG="$TAG"
ENV_FILE=".env.staging"
TRAEFIK_HOST="\`staging.${DOMAIN_BASE}\`"
IS_PROD="false"
GOTIFY_TITLE="🧪 Staging-Deploy (Pre-Release)"
GOTIFY_PRIORITY=5
else
TARGET="skip"
GOTIFY_TITLE="❓ Unbekannter Tag"
GOTIFY_PRIORITY=3
fi
else
TARGET="skip"
fi
echo "target=$TARGET" >> $GITHUB_OUTPUT
echo "image_tag=$IMAGE_TAG" >> $GITHUB_OUTPUT
echo "env_file=$ENV_FILE" >> $GITHUB_OUTPUT
echo "traefik_host=$TRAEFIK_HOST" >> $GITHUB_OUTPUT
echo "is_prod=$IS_PROD" >> $GITHUB_OUTPUT
echo "gotify_title=$GOTIFY_TITLE" >> $GITHUB_OUTPUT
echo "gotify_priority=$GOTIFY_PRIORITY" >> $GITHUB_OUTPUT
echo "short_sha=$SHORT_SHA" >> $GITHUB_OUTPUT
echo "commit_msg=$COMMIT_MSG" >> $GITHUB_OUTPUT
- name : ⏭️ Skip Deployment
if : steps.determine.outputs.target == 'skip'
run : |
echo "Deployment übersprungen – kein passender Trigger (main oder v*-Tag)"
exit 0
# ──────────────────────────────────────────────────────────────────────────────
# Registry Login
# ──────────────────────────────────────────────────────────────────────────────
- name : 🔐 Registry Login
run : |
echo "🔐 Login zu registry.infra.mintel.me ..."
echo "${{ secrets.REGISTRY_PASS }}" | docker login registry.infra.mintel.me -u "${{ secrets.REGISTRY_USER }}" --password-stdin
# ═══════════════════════════════════════════════════════════════════════════════
# LOGGING: Build Phase
# ═══════════════════════════════════════════════════════════════════════════════
- name : 🏗️ Build Docker i mage
# ──────────────────────────────────────────────────────────────────────────────
# Build & Push
# ──────────────────────────────────────────────────────────────────────────────
- name : 🏗️ Docker I mage bauen & pushen
env :
NEXT_PUBLIC_BASE_URL : ${{ github.ref_name == 'main' && secrets.NEXT_PUBLIC_BASE_URL || (secrets.STAGING_NEXT_PUBLIC_BASE_URL || secrets.NEXT_PUBLIC_BASE_URL) }}
NEXT_PUBLIC_UMAMI_WEBSITE_ID : ${{ github.ref_name == 'main' && secrets.NEXT_PUBLIC_UMAMI_WEBSITE_ID || (secrets.STAGING_NEXT_PUBLIC_UMAMI_WEBSITE_ID || secrets.NEXT_PUBLIC_UMAMI_WEBSITE_ID ) }}
NEXT_PUBLIC_UMAMI_SCRIPT_URL : ${{ github.ref_name == 'main' && secrets.NEXT_PUBLIC_UMAMI_SCRIPT_URL || (secrets.STAGING_NEXT_PUBLIC_UMAMI_SCRIPT_URL || secrets.NEXT_PUBLIC_UMAMI_SCRIPT_URL ) }}
IMAGE_TAG : ${{ steps.determine.outputs.image_tag }}
NEXT_PUBLIC_BASE_URL : ${{ steps.determine.outputs.target == 'production' && secrets.NEXT_PUBLIC_BASE_URL || (steps.determine.outputs.target == 'staging' && secrets.STAGING_NEXT_PUBLIC_BASE_URL || secrets.TESTING_NEXT_PUBLIC_BASE_URL || secrets.NEXT_PUBLIC_BASE_URL ) }}
NEXT_PUBLIC_UMAMI_WEBSITE_ID : ${{ steps.determine.outputs.target == 'production' && secrets.NEXT_PUBLIC_UMAMI_WEBSITE_ID || (steps.determine.outputs.target == 'staging' && secrets.STAGING_NEXT_PUBLIC_UMAMI_WEBSITE_ID || secrets.TESTING_NEXT_PUBLIC_UMAMI_WEBSITE_ID || secrets.NEXT_PUBLIC_UMAMI_WEBSITE_ID ) }}
NEXT_PUBLIC_UMAMI_SCRIPT_URL : ${{ steps.determine.outputs.target == 'production' && secrets.NEXT_PUBLIC_UMAMI_SCRIPT_URL || (steps.determine.outputs.target == 'staging' && secrets.STAGING_NEXT_PUBLIC_UMAMI_SCRIPT_URL || secrets.TESTING_NEXT_PUBLIC_UMAMI_SCRIPT_URL || secrets.NEXT_PUBLIC_UMAMI_SCRIPT_URL) }}
run : |
echo "🏗️ Building Docker image (linux/arm64) for branch ${{ github.ref_name }}... "
echo "🏗️ Building → ${{ steps.determine.outputs.target }} / $IMAGE_TAG "
docker buildx build \
--pull \
--platform linux/arm64 \
--build-arg NEXT_PUBLIC_BASE_URL="$NEXT_PUBLIC_BASE_URL" \
--build-arg NEXT_PUBLIC_UMAMI_WEBSITE_ID="$NEXT_PUBLIC_UMAMI_WEBSITE_ID" \
--build-arg NEXT_PUBLIC_UMAMI_SCRIPT_URL="$NEXT_PUBLIC_UMAMI_SCRIPT_URL" \
-t registry.infra.mintel.me/${{ github.repository }}:${{ github.sha }} \
-t registry.infra.mintel.me/${{ github.repository }}:latest \
-t registry.infra.mintel.me/${{ github.repository }}:$IMAGE_TAG \
--push .
# ═══════════════════════════════════════════════════════════════════════════════
# LOGGING: Deployment Phase
# ═══════════════════════════════════════════════════════════════════════════════
- name : 🚀 Deploy to server
# ──────────────────────────────────────────────────────────────────────────────
# Deploy via SSH
# ──────────────────────────────────────────────────────────────────────────────
- name : 🚀 Deploy to ${{ steps.determine.outputs.target }}
env :
NEXT_PUBLIC_BASE_URL : ${{ github.ref_name == 'main' && secrets.NEXT_PUBLIC_BASE_URL || (secrets.STAGING_NEXT_PUBLIC_BASE_URL || secrets.NEXT_PUBLIC_BASE_URL) }}
NEXT_PUBLIC_UMAMI_WEBSITE_ID : ${{ github.ref_name == 'main' && secrets.NEXT_PUBLIC_UMAMI_WEBSITE_ID || (secrets.STAGING_NEXT_PUBLIC_UMAMI_WEBSITE_ID || secrets.NEXT_PUBLIC_UMAMI_WEBSITE_ID) }}
NEXT_PUBLIC_UMAMI_SCRIPT_URL : ${{ github.ref_name == 'main' && secrets.NEXT_PUBLIC_UMAMI_SCRIPT_URL || (secrets.STAGING_NEXT_PUBLIC_UMAMI_SCRIPT_URL || secrets.NEXT_PUBLIC_UMAMI_SCRIPT_URL) }}
SENTRY_DSN : ${{ github.ref_name == 'ma in' && secrets.SENTRY_DSN || ( secrets.STAGING_SENTRY_DSN || secrets.SENTRY_DSN ) }}
MAIL_HOST : ${{ github.ref_name == 'ma in' && secrets.MAIL_HOST || ( secrets.STAGING_MAIL_HOST || secrets.MAIL_HOST ) }}
MAIL_PORT : ${{ github.ref_name == 'ma in' && secrets.MAIL_PORT || ( secrets.STAGING_MAIL_PORT || secrets.MAIL_PORT ) }}
MAIL_USERNAME : ${{ github.ref_name == 'ma in' && secrets.MAIL_USERNAME || ( secrets.STAGING_MAIL_USERNAME || secrets.MAIL_USERNAME ) }}
MAIL_PASSWORD : ${{ github.ref_name == 'main' && secrets.MAIL_PASSWORD || (secrets.STAGING_MAIL_PASSWORD || secrets.MAIL_PASSWORD ) }}
MAIL_FROM : ${{ github.ref_name == 'ma in' && secrets.MAIL_FROM || ( secrets.STAG ING_MAIL_FROM || secrets.MAIL_FROM ) }}
MAIL_RECIPIENTS : ${{ github.ref_name == 'main' && secrets.MAIL_RECIPIENTS || (secrets.STAGING_MAIL_RECIPIENTS || secrets.MAIL_RECIPIENTS ) }}
IMAGE_TAG : ${{ steps.determine.outputs.image_tag }}
ENV_FILE : ${{ steps.determine.outputs.env_file }}
TRAEFIK_HOST : ${{ steps.determine.outputs.traefik_host }}
NEXT_PUBLIC_BASE_URL : ${{ steps.determine.outputs.target == 'production' && secrets.NEXT_PUBLIC_BASE_URL || (steps.determine.outputs.target == 'stag ing ' && secrets.STAGING_NEXT_PUBLIC_BASE_URL || secrets.TESTING_NEXT_PUBLIC_BASE_URL || secrets.NEXT_PUBLIC_BASE_URL ) }}
NEXT_PUBLIC_UMAMI_WEBSITE_ID : ${{ steps.determine.outputs.target == 'production' && secrets.NEXT_PUBLIC_UMAMI_WEBSITE_ID || (steps.determine.outputs.target == 'stag ing ' && secrets.STAGING_NEXT_PUBLIC_UMAMI_WEBSITE_ID || secrets.TESTING_NEXT_PUBLIC_UMAMI_WEBSITE_ID || secrets.NEXT_PUBLIC_UMAMI_WEBSITE_ID ) }}
NEXT_PUBLIC_UMAMI_SCRIPT_URL : ${{ steps.determine.outputs.target == 'production' && secrets.NEXT_PUBLIC_UMAMI_SCRIPT_URL || (steps.determine.outputs.target == 'stag ing ' && secrets.STAGING_NEXT_PUBLIC_UMAMI_SCRIPT_URL || secrets.TESTING_NEXT_PUBLIC_UMAMI_SCRIPT_URL || secrets.NEXT_PUBLIC_UMAMI_SCRIPT_URL ) }}
SENTRY_DSN : ${{ steps.determine.outputs.target == 'production' && secrets.SENTRY_DSN || (steps.determine.outputs.target == 'stag ing ' && secrets.STAGING_SENTRY_DSN || secrets.TESTING_SENTRY_DSN || secrets.SENTRY_DSN ) }}
MAIL_HOST : ${{ steps.determine.outputs.target == 'production' && secrets.MAIL_HOST || (steps.determine.outputs.target == 'staging' && secrets.STAGING_MAIL_HOST || secrets.TESTING_MAIL_HOST || secrets.MAIL_HOST ) }}
MAIL_PORT : ${{ steps.determine.outputs.target == 'production' && secrets.MAIL_PORT || (steps.determine.outputs.target == 'stag ing ' && secrets.STAGING_MAIL_PORT || secrets.TE STING_MAIL_PORT || secrets.MAIL_PORT ) }}
MAIL_USERNAME : ${{ steps.determine.outputs.target == 'production' && secrets.MAIL_USERNAME || (steps.determine.outputs.target == 'staging' && secrets.STAGING_MAIL_USERNAME || secrets.TESTING_MAIL_USERNAME || secrets.MAIL_USERNAME ) }}
MAIL_PASSWORD : ${{ steps.determine.outputs.target == 'production' && secrets.MAIL_PASSWORD || (steps.determine.outputs.target == 'staging' && secrets.STAGING_MAIL_PASSWORD || secrets.TESTING_MAIL_PASSWORD || secrets.MAIL_PASSWORD) }}
MAIL_FROM : ${{ steps.determine.outputs.target == 'production' && secrets.MAIL_FROM || (steps.determine.outputs.target == 'staging' && secrets.STAGING_MAIL_FROM || secrets.TESTING_MAIL_FROM || secrets.MAIL_FROM) }}
MAIL_RECIPIENTS : ${{ steps.determine.outputs.target == 'production' && secrets.MAIL_RECIPIENTS || (steps.determine.outputs.target == 'staging' && secrets.STAGING_MAIL_RECIPIENTS || secrets.TESTING_MAIL_RECIPIENTS || secrets.MAIL_RECIPIENTS) }}
run : |
BRANCH=${{ github.ref_name }}
# Derive domain from NEXT_PUBLIC_BASE_URL (strip https:// and trailing slash)
DOMAIN=$(echo "$NEXT_PUBLIC_BASE_URL" | sed -E 's|https?://||' | sed -E 's|/.*||')
if [ "$BRANCH" = "main" ]; then
ENV_FILE=.env.prod
# For production, we want both root and www
TRAEFIK_HOST="\`$DOMAIN\`, \`www.$DOMAIN\`"
else
ENV_FILE=.env.staging
TRAEFIK_HOST="\`$DOMAIN\`"
fi
echo "🚀 Deploying branch $BRANCH to $ENV_FILE..."
echo "🌐 Domain: $DOMAIN"
# Setup SSH
echo "Deploying ${{ steps.determine.outputs.target }} → $IMAGE_TAG"
# SSH vorbereiten
mkdir -p ~/.ssh
echo "${{ secrets.SSH_KEY }}" > ~/.ssh/id_ed25519
chmod 600 ~/.ssh/id_ed25519
ssh-keyscan -H ${{ secrets.SSH_HOST }} >> ~/.ssh/known_hosts 2>/dev/null
# Create .env file content
# .env-Datei erstellen
cat > /tmp/app.env << EOF
# ============================================================================
# Environment Configuration ($BRANCH)
# ============================================================================
# Auto-generated by CI/CD workflow
# ============================================================================
# Generated by CI - ${{ steps.determine.outputs.target }} - $(date -u)
NODE_ENV=production
NEXT_PUBLIC_BASE_URL=$NEXT_PUBLIC_BASE_URL
NEXT_PUBLIC_UMAMI_WEBSITE_ID=$NEXT_PUBLIC_UMAMI_WEBSITE_ID
@@ -108,90 +169,80 @@ jobs:
MAIL_PASSWORD=$MAIL_PASSWORD
MAIL_FROM=$MAIL_FROM
MAIL_RECIPIENTS=$MAIL_RECIPIENTS
# Deployment variables for docker-compose
IMAGE_TAG=${{ github.sha }}
IMAGE_TAG=$IMAGE_TAG
TRAEFIK_HOST=$TRAEFIK_HOST
ENV_FILE=$ENV_FILE
EOF
APP_DIR="/home/deploy/sites/${{ github.event.repository.name }}"
ssh -o StrictHostKeyChecking=accept-new root@${{ secrets.SSH_HOST }} "mkdir -p $APP_DIR"
scp -o StrictHostKeyChecking=accept-new /tmp/app.env root@${{ secrets.SSH_HOST }}:$APP_DIR/$ENV_FILE
scp -o StrictHostKeyChecking=accept-new docker-compose.yml root@${{ secrets.SSH_HOST }}:$APP_DIR/docker-compose.yml
ssh -o StrictHostKeyChecking=accept-new root@${{ secrets.SSH_HOST }} bash << EOF
set -e
cd $ APP_DIR
chmod 600 $ENV_FILE
chown deploy:deploy $ENV_FILE
echo "${{ secrets.REGISTRY_PASS }}" | docker login registry.infra.mintel.me -u "${{ secrets.REGISTRY_USER }}" --password-stdin
echo "📥 Pulling images..."
IMAGE_TAG=${{ github.sha }} ENV_FILE=$ENV_FILE TRAEFIK_HOST="$TRAEFIK_HOST" docker compose --env-file $ENV_FILE pull
echo "🚀 Starting containers..."
IMAGE_TAG=${{ github.sha }} ENV_FILE=$ENV_FILE TRAEFIK_HOST="$TRAEFIK_HOST" docker compose --env-file $ENV_FILE up -d
echo "🧹 Cleaning up old images..."
docker system prune -f
echo "⏳ Giving the app a few seconds to warm up..."
sleep 10
echo "🔍 Checking c ontainer status... "
docker compose --env-file $ENV_FILE ps
if ! docker compose --env-file $ENV_FILE ps | grep -q "Up"; then
echo "❌ Container failed to start "
docker compose --env-file $ENV_FILE logs --tail=10 0
exit 1
fi
echo "✅ Deployment complete !"
ssh -o StrictHostKeyChecking=accept-new root@${{ secrets.SSH_HOST }} bash << ' EOF'
set -e
APP_DIR="/home/deploy/sites/${{ github.event.repository.name }}"
cd $APP_DIR
chmod 600 $ENV_FILE
chown deploy:deploy $ENV_FILE
echo "${{ secrets.REGISTRY_PASS }}" | docker login registry.infra.mintel.me -u "${{ secrets.REGISTRY_USER }}" --password-stdin
echo "→ Pulling image: $IMAGE_TAG"
IMAGE_TAG=$IMAGE_TAG ENV_FILE=$ENV_FILE TRAEFIK_HOST="$TRAEFIK_HOST" docker compose --env-file $ENV_FILE pull
echo "→ Starting containers..."
IMAGE_TAG=$IMAGE_TAG ENV_FILE=$ENV_FILE TRAEFIK_HOST="$TRAEFIK_HOST" docker compose --env-file $ENV_FILE up -d
docker system prune -f --filter "until=168h"
echo "→ Waiting 15s for warmup..."
sleep 15
echo "→ Container status: "
docker compose --env-file $ENV_FILE ps
if ! docker compose --env-file $ENV_FILE ps | grep -q "Up"; then
echo "❌ Fehler: Container nicht Up! "
docker compose --env-file $ENV_FILE logs --tail=15 0
exit 1
fi
echo "✅ Deployment erfolgreich auf ${{ steps.determine.outputs.target }} !"
EOF
rm -f /tmp/app.env
# ═══════════════════════════════════════════════════════════════════════════════
# LOGGING: Workflow Summar y
# ═══════════════════════════════════════════════════════════════════════════════
- name : 📊 Workflow Summary
# ──────────────────────────────────────────────────────────────────────────────
# Summary & Gotif y
# ──────────────────────────────────────────────────────────────────────────────
- name : 📊 Deployment Summary
if : always()
run : |
echo "📊 Status: ${{ job.status }} "
echo "🎯 Target: ${{ secrets.SSH_HOST }} "
echo "🌿 Branch: ${{ github.ref_name }}"
echo "┌──────────────────────────────┐ "
echo "│ Deployment Summary │ "
echo "├──────────────────────────────┤"
echo "│ Status: ${{ job.status }} │"
echo "│ Umgebung: ${{ steps.determine.outputs.target || 'skipped' }} │"
echo "│ Version: ${{ steps.determine.outputs.image_tag }} │"
echo "│ Commit: ${{ steps.determine.outputs.short_sha }} │"
echo "│ Message: ${{ steps.determine.outputs.commit_msg }} │"
echo "└──────────────────────────────┘"
# ═══════════════════════════════════════════════════════════════════════════════
# NOTIFICATION: Gotify
# ═══════════════════════════════════════════════════════════════════════════════
- name : 🔔 Gotify Notification (Success)
- name : 🔔 Gotify - Success
if : success()
run : |
echo "Sending success notification to Gotify..."
curl -k -s -X POST "${{ secrets.GOTIFY_URL }}/message?token=${{ secrets.GOTIFY_TOKEN }}" \
-F "title=✅ Deployment Success: ${{ github.repository }}" \
-F "message=The deployment of ${{ github.repository }} (branch: ${{ github.ref_name }}) was successful.
Commit: ${{ github.sha }}
Actor: ${{ github.actor }}
Run ID: ${{ github.run_id }}" \
-F "priority=5"
curl -s -k -X POST "${{ secrets.GOTIFY_URL }}/message?token=${{ secrets.GOTIFY_TOKEN }}" \
-F "title=${{ steps.determine.outputs.gotify_title }}" \
-F "message=Erfolgreich deployt auf **${{ steps.determine.outputs.target }}**\n\nVersion: **${{ steps.determine.outputs.image_tag }}**\nCommit: ${{ steps.determine.outputs.short_sha }} (${{ steps.determine.outputs.commit_msg }})\nVon: ${{ github.actor }}\nRun: ${{ github.run_id }}" \
-F "priority=${{ steps.determine.outputs.gotify_priority }}" || true
- name : 🔔 Gotify Notification ( Failure)
- name : 🔔 Gotify - Failure
if : failure()
run : |
echo "Sending failure notification to Gotify..."
curl -k -s -X POST "${{ secrets.GOTIFY_URL }}/message?token=${{ secrets.GOTIFY_TOKEN }}" \
-F "title=❌ Deployment Failed: ${{ github.repository }} " \
-F "message=The deployment of ${{ github.repository }} (branch: ${{ github.ref_name }}) failed!
Commit: ${{ github.sha }}
Actor: ${{ github.actor }}
Run ID: ${{ github.run_id }}
Please check the logs for details." \
-F "priority=8"
curl -s -k -X POST "${{ secrets.GOTIFY_URL }}/message?token=${{ secrets.GOTIFY_TOKEN }}" \
-F "title=❌ Deployment FEHLGESCHLAGEN – ${{ steps.determine.outputs.target || 'unknown' }}" \
-F "message=**Fehler beim Deploy auf ${{ steps.determine.outputs.target }}**\n\nVersion: ${{ steps.determine.outputs.image_tag || '?' }}\nCommit: ${{ steps.determine.outputs.short_sha || '?' }}\nVon: ${{ github.actor }}\nRun: ${{ github.run_id }}\n\nBitte Logs prüfen! " \
-F "priority=8" || true