Files
timer-app/.gitea/workflows/deploy.yaml
T
adminandClaude Opus 5 51c809dedc
Deploy auf den Timer-Server / deploy (push) Failing after 1m20s
Auf das 22.04-Runner-Image wechseln
Im 24.04-Image schlagen auf diesem Runner Syscalls fehl, die neuere
Programme benutzen: actions/checkout starb mit 'read ENOTCONN', rsync
bricht mit 'pipe: Permission denied' ab. Beides deutet auf das seccomp-
Profil des Docker-Hosts, nicht auf den Workflow.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-04 18:04:23 +02:00

135 lines
5.6 KiB
YAML

name: Deploy auf den Timer-Server
# Laeuft bei jedem Push auf main und laesst sich in der Gitea-Oberflaeche
# ("Actions" -> Workflow -> "Run workflow") auch von Hand ausloesen.
on:
push:
branches: [main]
workflow_dispatch:
jobs:
deploy:
# Nicht ubuntu-latest (24.04): in dem Image scheitern auf diesem Runner
# moderne Syscalls - actions/checkout stirbt mit "read ENOTCONN", rsync
# mit "pipe: Permission denied". Ursache ist das seccomp-Profil des
# Docker-Hosts, nicht der Workflow. Das aeltere Image kommt damit klar.
runs-on: ubuntu-22.04
env:
# Repository-Variablen (Settings -> Actions -> Variables)
DEPLOY_HOST: ${{ vars.DEPLOY_HOST }}
DEPLOY_USER: ${{ vars.DEPLOY_USER }}
DEPLOY_PATH: ${{ vars.DEPLOY_PATH }}
DEPLOY_SERVICE: ${{ vars.DEPLOY_SERVICE }}
DEPLOY_OWNER: ${{ vars.DEPLOY_OWNER }}
HEALTH_URL: ${{ vars.HEALTH_URL }}
# Repository-Secrets (Settings -> Actions -> Secrets)
DEPLOY_SSH_KEY: ${{ secrets.DEPLOY_SSH_KEY }}
DEPLOY_KNOWN_HOSTS: ${{ secrets.DEPLOY_KNOWN_HOSTS }}
steps:
# Bewusst kein actions/checkout: die JS-Aktion stirbt im Runner-Image
# von Gitea 1.27 beim Aufruf von git mit "read ENOTCONN" (Node-24-Fehler
# im Container). Ein Klon per Shell umgeht das und braucht kein Node.
- name: Werkzeuge und Code holen
env:
TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
apt-get update -qq
apt-get install -y -qq git rsync openssh-client curl
rm -rf quelle && mkdir quelle && cd quelle
git init -q
# Gitea meldet hier seine interne Adresse (http://192.168.1.5:3000),
# deshalb Schema und Rest getrennt behandeln statt https anzunehmen.
URL="${GITHUB_SERVER_URL%/}"
git remote add origin "${URL%%://*}://x-access-token:$TOKEN@${URL#*://}/$GITHUB_REPOSITORY.git"
# Nach SHA, falls der Server das nicht erlaubt ersatzweise nach Branch.
git fetch -q --depth 1 origin "$GITHUB_SHA" || git fetch -q --depth 1 origin "$GITHUB_REF_NAME"
git checkout -q FETCH_HEAD
echo "Ausgecheckt: $(git log --oneline -1)"
- name: Konfiguration pruefen
run: |
fehlt=""
for v in DEPLOY_HOST DEPLOY_USER DEPLOY_PATH DEPLOY_SERVICE DEPLOY_SSH_KEY DEPLOY_KNOWN_HOSTS; do
if [ -z "${!v:-}" ]; then fehlt="$fehlt $v"; fi
done
if [ -n "$fehlt" ]; then
echo "Es fehlen noch Variablen/Secrets:$fehlt"
echo "Nachzutragen unter Settings -> Actions -> Variables bzw. Secrets."
exit 1
fi
echo "Ziel: $DEPLOY_USER@$DEPLOY_HOST:$DEPLOY_PATH (Dienst: $DEPLOY_SERVICE)"
- name: SSH einrichten
run: |
mkdir -p ~/.ssh && chmod 700 ~/.ssh
printf '%s\n' "$DEPLOY_SSH_KEY" > ~/.ssh/id_ed25519
printf '%s\n' "$DEPLOY_KNOWN_HOSTS" > ~/.ssh/known_hosts
chmod 600 ~/.ssh/id_ed25519
chmod 644 ~/.ssh/known_hosts
- name: Dateien uebertragen
run: |
# --delete raeumt geloeschte Dateien auf dem Server weg. Die
# ausgeschlossenen Pfade sind davon ausgenommen (kein --delete-excluded!):
# Konfiguration, Datenbank und node_modules bleiben unangetastet.
rsync -rlpt --delete --out-format='%n' \
--exclude='.git/' --exclude='.gitea/' \
--exclude='.env' --exclude='.env.*' \
--exclude='data/' --exclude='node_modules/' \
-e 'ssh -o BatchMode=yes' \
quelle/ "$DEPLOY_USER@$DEPLOY_HOST:$DEPLOY_PATH/" | tee uebertragen.txt
- name: Abhaengigkeiten, Neustart und Health-Check
run: |
# Neu installiert wird nur, wenn sich die Paketliste geaendert hat.
# bcrypt und sqlite3 sind native Module: npm ci gehoert deshalb auf
# den Zielhost und nicht in den Runner-Container.
NPM=nein
RESTART=nein
if grep -q 'backend/package' uebertragen.txt; then NPM=ja; fi
if grep -qE '^(backend/|deploy/)' uebertragen.txt; then RESTART=ja; fi
if [ ! -s uebertragen.txt ]; then echo "Nichts geaendert."; fi
echo "npm ci: $NPM | Neustart: $RESTART"
ssh -o BatchMode=yes "$DEPLOY_USER@$DEPLOY_HOST" \
"NPM='$NPM' RESTART='$RESTART' \
DEPLOY_PATH='$DEPLOY_PATH' DEPLOY_SERVICE='$DEPLOY_SERVICE' \
DEPLOY_OWNER='${DEPLOY_OWNER:-timerapp:timerapp}' \
HEALTH_URL='${HEALTH_URL:-http://127.0.0.1:3003/health}' \
bash -euo pipefail -s" <<'REMOTE'
SUDO=""; [ "$(id -u)" -eq 0 ] || SUDO="sudo -n"
if [ "$NPM" = ja ]; then
echo "--- npm ci (nur Produktionsabhaengigkeiten)"
cd "$DEPLOY_PATH/backend"
$SUDO npm ci --omit=dev --no-audit --no-fund
fi
# Alles unter dem Anwendungsverzeichnis gehoert dem Dienstbenutzer.
$SUDO chown -R "$DEPLOY_OWNER" "$DEPLOY_PATH"
if [ "$RESTART" = nein ]; then
echo "--- Keine Backend-Aenderung: Neustart nicht noetig"
exit 0
fi
echo "--- Dienst neu starten: $DEPLOY_SERVICE"
$SUDO systemctl restart "$DEPLOY_SERVICE"
echo "--- Health-Check"
for i in $(seq 1 15); do
if curl -fsS --max-time 3 "$HEALTH_URL" >/dev/null 2>&1; then
echo "Dienst antwortet:"; curl -fsS "$HEALTH_URL"; echo
exit 0
fi
sleep 2
done
echo "Dienst antwortet nach 30 s nicht. Letzte Zeilen aus dem Journal:"
$SUDO journalctl -u "$DEPLOY_SERVICE" -n 40 --no-pager || true
exit 1
REMOTE