presseportale/dev/betrieb/deploy.sh
Kevin Adametz ce6e8b48e0 deploy: Worker-Prüfung am Ende von deploy.sh — monitoring:queue-probe stellt einen Test-Job ein und wartet bis 60 s; ohne Worker Exit 3 mit Hinweis
Anlass 06.10.2026: Nach dem Deploy von v1.3.0 hat queue:restart den Worker
beendet, Supervisor lief nicht, über eine Stunde blieben KI-Prüfungen und
Mails liegen, ohne dass es auffiel.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 16:11:58 +00:00

160 lines
4.8 KiB
Bash
Executable file

#!/usr/bin/env bash
#
# Deploy eines Git-Tags auf Live (Ablauf und Hintergrund: dev/betrieb/git-deploy.md).
#
# Aufruf im App-Verzeichnis auf dem Server:
#
# cd ~/pressekonto.com
# bash dev/betrieb/deploy.sh v1.2.0 # ohne neue Migrationen
# bash dev/betrieb/deploy.sh v1.2.0 --migrations # mit Migrationen, DB-Backup vorher!
#
# Optionen:
# --migrations Neue Migrationen ausführen. Ohne diese Option bricht das
# Skript ab, sobald der Tag neue Migrationen mitbringt.
# --clear-schedule php artisan schedule:clear-cache (alte withoutOverlapping-Sperren).
#
# Umgebung:
# PK_FPM_RELOAD Befehl zum Neuladen von PHP-FPM
# (Standard: echo "" | sudo -S service php8.4-fpm reload).
# Leer setzen, wenn FPM von Hand in Ploi neu geladen wird.
#
# Exit-Codes: 0 fertig, 1 abgebrochen (siehe Ausgabe), 2 falscher Aufruf,
# 3 live, aber kein Queue-Worker hat den Test-Job abgeholt.
#
# Rollback: dasselbe Skript mit dem vorherigen Tag.
set -euo pipefail
# Git ersetzt diese Datei beim Checkout. Bash liest Skripte stückweise, deshalb
# läuft der Deploy aus einer Kopie.
if [[ -z "${PK_DEPLOY_COPY:-}" ]]; then
copy="$(mktemp)"
cp "$0" "$copy"
PK_DEPLOY_COPY="$copy" exec bash "$copy" "$@"
fi
trap 'rm -f "$PK_DEPLOY_COPY"' EXIT
tag="${1:-}"
shift || true
run_migrations=0
clear_schedule=0
for option in "$@"; do
case "$option" in
--migrations) run_migrations=1 ;;
--clear-schedule) clear_schedule=1 ;;
*) echo "Unbekannte Option: $option" >&2; exit 2 ;;
esac
done
if [[ ! "$tag" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "Aufruf: bash dev/betrieb/deploy.sh vX.Y.Z [--migrations] [--clear-schedule]" >&2
exit 2
fi
if [[ ! -f artisan || ! -d .git ]]; then
echo "Im App-Verzeichnis aufrufen (artisan und .git fehlen hier)." >&2
exit 2
fi
step() { printf '\n==> %s\n' "$*"; }
step "Arbeitsverzeichnis prüfen"
drift="$(git status --porcelain)"
if [[ -n "$drift" ]]; then
echo "Das Arbeitsverzeichnis weicht vom ausgecheckten Stand ab:" >&2
echo "$drift" >&2
echo "Erst klären (git diff), dann deployen. Nichts wurde verändert." >&2
exit 1
fi
step "Tags von origin holen"
git fetch --quiet --tags origin
if ! git rev-parse --quiet --verify "refs/tags/$tag^{commit}" > /dev/null; then
echo "Tag $tag gibt es auf origin nicht." >&2
exit 1
fi
previous="$(cat RELEASE 2>/dev/null || git describe --tags --always)"
echo "Live: $previous → Ziel: $tag"
if [[ "$(git rev-parse HEAD)" == "$(git rev-parse "$tag^{commit}")" ]]; then
echo "$tag ist bereits ausgecheckt. Nichts zu tun."
exit 0
fi
new_migrations="$(git diff --name-only --diff-filter=A HEAD "$tag" -- database/migrations)"
if [[ -n "$new_migrations" ]]; then
echo "Neue Migrationen:"
echo "$new_migrations" | sed 's/^/ /'
if [[ "$run_migrations" -ne 1 ]]; then
echo "Abbruch: DB-Backup ziehen und mit --migrations erneut aufrufen. Nichts wurde verändert." >&2
exit 1
fi
fi
trap 'echo; echo "!! Deploy abgebrochen. Die Seite bleibt im Wartungsmodus." >&2; echo "!! Rollback: bash dev/betrieb/deploy.sh $previous" >&2; rm -f "$PK_DEPLOY_COPY"' ERR
step "Wartungsmodus"
php artisan down --retry=60
step "Checkout $tag"
git checkout --quiet --detach "$tag"
echo "$tag" > RELEASE
step "Composer"
composer install --no-dev --optimize-autoloader --no-interaction
if [[ -n "$new_migrations" ]]; then
step "Migrationen"
php artisan migrate --force
fi
if [[ -d public/vendor/livewire ]]; then
php artisan vendor:publish --tag=livewire:assets --force
fi
step "Caches"
php artisan config:cache
php artisan route:cache
php artisan view:clear
php artisan view:cache
php artisan event:cache
if [[ "$clear_schedule" -eq 1 ]]; then
php artisan schedule:clear-cache
fi
step "Worker und PHP-FPM"
php artisan queue:restart
default_fpm_reload='echo "" | sudo -S service php8.4-fpm reload'
fpm_reload="${PK_FPM_RELOAD-$default_fpm_reload}"
if [[ -n "$fpm_reload" ]]; then
bash -c "$fpm_reload"
else
echo "PHP-FPM jetzt in Ploi neu laden (Server ▸ PHP ▸ Restart), danach Enter."
read -r
fi
step "Wartungsmodus aus"
php artisan up
step "Version"
php artisan about --only=pressekonto
trap - ERR
# Läuft ein Worker? `queue:restart` oben beendet ihn; neu starten muss ihn
# Supervisor. Am 06.10.2026 lief Supervisor nicht, und nach dem Deploy von
# v1.3.0 blieben KI-Prüfungen und Mails über eine Stunde liegen.
step "Queue-Worker"
if ! php artisan monitoring:queue-probe --wait=60; then
echo
echo "!! Deploy $tag ist live, aber KEIN Queue-Worker läuft." >&2
echo "!! Jetzt in Ploi Site ▸ Queue (und Supervisor) prüfen — sonst bleiben Prüfungen und Mails liegen." >&2
exit 3
fi
echo
echo "Deploy $tag fertig (vorher $previous). Weiter mit den Prüfungen in dev/betrieb/git-deploy.md, Abschnitt D."