Add upstream-merge.sh script, simplify skill
Build Deploy email notification tool / Apply-Kubernetes-Resources (push) Successful in 8s

The shell script handles all automatable workflow steps:
- git fetch, branch creation, master merge, push + MR link
- Gender grep with exit 1 on findings (Claude intervenes)
- Waits for MR merge (read prompt)
- Tag, build pipeline polling via Gitea API (GITEA_TOKEN)
- GitOps YAML updates for cgm72 and sola
- URL polling for both deployments
- Resume mode (--resume) to continue after gender fix

The skill now just starts the script and handles exit-code 1.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-10-03 22:28:13 +02:00
co-authored by Claude Sonnet 4.6
parent 35655a4036
commit 1e3a3ec3af
2 changed files with 263 additions and 192 deletions
+39 -192
View File
@@ -1,202 +1,49 @@
Führe den vollständigen Upstream-Merge-Workflow für pretix_cgo durch. Gehe dabei strikt Schritt für Schritt vor und warte an den markierten Stellen auf Bestätigung.
Führe den Upstream-Merge-Workflow für pretix_cgo durch.
## Ablauf
Starte das Script:
```bash
bash /home/monsi/git_gemeinde/pretix_cgo/.claude/upstream-merge.sh
```
Das Script läuft weitgehend automatisch durch. Es hält selbst an den zwei manuellen Checkpoints an (MR-Merge-Bestätigung, cgm72-Prüfung) – diese Eingaben macht der Nutzer direkt im Terminal.
---
## Schritt 1 – Master aktualisieren
## Exit-Code 1 – Gender-Befunde
Das Script hat gegenderte Sprache gefunden und gibt Datei + Zeilen aus. Du übernimmst:
1. Zeige die Befunde dem Nutzer mit konkreten Ersetzungsvorschlägen:
- Binneni (`*`, `:`, `_`, `(in)`) → maskuline Grundform (z.B. `Teilnehmer*in` → `Teilnehmer`)
- Partizip-Plural (z.B. `Teilnehmenden`) → maskuline Grundform (`Teilnehmer`)
- Zeige jeweils den vollständigen `msgstr`-Block als Kontext.
2. Warte auf Freigabe durch den Nutzer.
3. Korrekturen direkt in den Dateien vornehmen, dann committen und pushen:
```bash
git checkout master
git pull
git -C /home/monsi/git_gemeinde/pretix_cgo \
add src/pretix/locale/de/ src/pretix/locale/de_Informal/
git -C /home/monsi/git_gemeinde/pretix_cgo \
commit -m "Remove gendered language from de/de_Informal translations"
git -C /home/monsi/git_gemeinde/pretix_cgo push
```
4. Script fortsetzen:
```bash
bash /home/monsi/git_gemeinde/pretix_cgo/.claude/upstream-merge.sh --resume
```
---
## Schritt 2 – Upstream-Tags holen & neuesten Tag ermitteln
## Andere Fehler
```bash
git fetch upstream --tags
```
Bestimme danach den neuesten upstream-Tag (Format `vYYYY.M.P`, **ohne** das `.0`-Suffix unserer eigenen Tags):
```bash
git tag --sort=-version:refname | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' | head -1
```
Merke dir diesen Tag als `UPSTREAM_TAG` (z.B. `v2026.5.0`) und leite daraus den Branch-Namen ab: `upstream/2026.5.0` (ohne führendes `v`).
---
## Schritt 3 – Branch erstellen
```bash
git checkout -b upstream/<VERSION> tags/<UPSTREAM_TAG>
# Beispiel: git checkout -b upstream/2026.5.0 tags/v2026.5.0
```
---
## Schritt 4 – Master mergen (immer, nicht optional)
```bash
git merge master
```
Bei Merge-Konflikten: Konflikte anzeigen und gemeinsam mit dem Nutzer lösen, bevor es weitergeht.
---
## Schritt 5 – Branch pushen & MR anlegen
Push mit Push Option, damit Gitea direkt einen MR anlegt:
```bash
git push --set-upstream origin upstream/<VERSION> -o merge_request.create
```
---
## Schritt 6 – Gender-Prüfung in den deutschen Übersetzungen
**Erst nach dem Merge mit master** die folgenden vier Dateien auf gegenderte Sprache prüfen:
- `src/pretix/locale/de/LC_MESSAGES/django.po`
- `src/pretix/locale/de/LC_MESSAGES/djangojs.po`
- `src/pretix/locale/de_Informal/LC_MESSAGES/django.po`
- `src/pretix/locale/de_Informal/LC_MESSAGES/djangojs.po`
Suche in den `msgstr`-Zeilen (und den zugehörigen `msgid`-Zeilen für Kontext) nach folgenden Mustern:
| Muster | Beispiele |
|--------|-----------|
| Binneni mit `*` | `Teilnehmer*in`, `Käufer*innen` |
| Binneni mit `:` | `Teilnehmer:in`, `Käufer:innen` |
| Binneni mit `_` | `Teilnehmer_in`, `Käufer_innen` |
| Binneni mit `(in)` | `Teilnehmer(in)`, `Käufer(innen)` |
| Partizip-Plural auf `-enden` | `Teilnehmenden`, `Helfenden`, `Organisierenden`, `Bestellenden`, `Buchenden`, `Zahlenden` |
**Ausgabe der Befunde:** Zeige für jeden Treffer:
1. Datei + Zeilennummer
2. Den vollständigen `msgstr`-Block (mehrzeilig wenn nötig) als Kontext
3. Den konkreten Vorschlag für die Ersetzung (z.B. `Teilnehmer*in` → `Teilnehmer`, `Teilnehmenden` → `Teilnehmer`)
Warte dann auf Freigabe durch den Nutzer, bevor Änderungen vorgenommen werden.
Nach Freigabe: Korrekturen direkt in den Dateien vornehmen und committen:
```bash
git add src/pretix/locale/de/ src/pretix/locale/de_Informal/
git commit -m "Remove gendered language from de/de_Informal translations"
git push
```
---
## Schritt 7 – Warten auf Merge-Bestätigung
**Hier pausieren.** Den Nutzer auffordern zu bestätigen, sobald der MR auf Gitea gemergt wurde.
---
## Schritt 8 – Master aktualisieren und neuen Tag vergeben
Nach Bestätigung:
```bash
git checkout master
git pull
```
Den neuen Tag ableiten: `<UPSTREAM_TAG>.0` **ohne führendes `v`** (z.B. `v2026.5.0` → `2026.5.0.0`):
```bash
git tag <VERSION>.0
# Beispiel: git tag 2026.5.0.0
git push origin <VERSION>.0
```
Ausgabe: Bestätigung mit dem neuen Tag und kurzem Status.
---
## Schritt 9 – Warten auf Build-Pipeline
Nutze den Gitea MCP Server, um den Pipeline-Lauf für den soeben gepushten Tag zu überwachen:
- **Repo:** `CGM_Public` / `pretix_cgo`
- **Methode:** `mcp__gitea__actions_run_read` mit `method: list_runs`
- Warte, bis ein Run mit dem passenden Ref (`refs/tags/<NEUER_TAG>`) den Status `success` erreicht.
- Prüfe alle ~30 Sekunden erneut und zeige dem Nutzer den aktuellen Status (running / success / failure).
- Bei `failure`: sofort stoppen und dem Nutzer melden.
Erst wenn der Build erfolgreich (`success`) abgeschlossen ist, weitermachen.
---
## Schritt 10 – cgm72 GitOps-Update
Im GitOps-Repo unter `../OrtlerstrasseGitOps/` (liegt immer neben dem pretix_cgo-Repo):
1. In `pretix-cgm72/pretix-deployment.yaml` den Image-Tag aktualisieren:
- Suche: `cr.ortlerstrasse.de/cgo/pretix:<ALTER_TAG>`
- Ersetze mit: `cr.ortlerstrasse.de/cgo/pretix:<NEUER_TAG>` (= der in Schritt 8 gesetzte Git-Tag, z.B. `2026.5.0.0`)
2. Committen und pushen (im OrtlerstrasseGitOps-Verzeichnis):
```bash
git -C ../OrtlerstrasseGitOps add pretix-cgm72/pretix-deployment.yaml
git -C ../OrtlerstrasseGitOps commit -m "Update pretix-cgm72 to <NEUER_TAG>"
git -C ../OrtlerstrasseGitOps push
```
Der GitOps-Operator wendet das YAML automatisch via `kubectl apply` an und rollt den Container neu aus.
---
## Schritt 11 – cgm72: Container-Neustart abwarten und Loginseite prüfen
Warte, bis der Container neu gestartet ist, und prüfe dann die Loginseite:
- **URL:** `https://anmeldung.christliche-gemeinde.de/`
- **Prüfung:** HTTP 200 und die Seite enthält typische Pretix-Inhalte (z.B. Stichwort „pretix" oder ein Login-Formular im Body)
Methode: Nutze `mcp__claude_ai_Simon_Fetch__fetch_page` (oder `curl -sI`), um die URL alle ~30 Sekunden abzurufen. Erwarte einen kurzen Ausfall während des Neustarts – warte danach auf eine erfolgreiche Antwort.
Zeige dem Nutzer das Ergebnis (Status-Code + kurzen Seitenausschnitt als Bestätigung).
---
## Schritt 12 – Manuelle Bestätigung für cgm72
**Hier pausieren.** Den Nutzer auffordern zu bestätigen, dass cgm72 korrekt funktioniert (`https://anmeldung.christliche-gemeinde.de/`), bevor mit sola fortgefahren wird.
---
## Schritt 13 – sola GitOps-Update
Im GitOps-Repo unter `../OrtlerstrasseGitOps/` (liegt immer neben dem pretix_cgo-Repo):
1. In `pretix-sola/pretix-deployment.yaml` den Image-Tag aktualisieren:
- Suche: `cr.ortlerstrasse.de/cgo/pretix:<ALTER_TAG>`
- Ersetze mit: `cr.ortlerstrasse.de/cgo/pretix:<NEUER_TAG>`
2. Committen und pushen:
```bash
git -C ../OrtlerstrasseGitOps add pretix-sola/pretix-deployment.yaml
git -C ../OrtlerstrasseGitOps commit -m "Update pretix-sola to <NEUER_TAG>"
git -C ../OrtlerstrasseGitOps push
```
---
## Schritt 14 – sola: Container-Neustart abwarten und Loginseite prüfen
Warte, bis der Container neu gestartet ist, und prüfe dann die Loginseite:
- **URL:** `https://anmeldung.sola-muenchen.de`
- **Prüfung:** HTTP 200 und die Seite enthält typische Pretix-Inhalte
Methode: wie in Schritt 11.
Ausgabe: Bestätigung mit kurzem Abschluss-Status des gesamten Workflows.
| Exit-Code | Bedeutung | Aktion |
|-----------|----------------------------------|-------------------------------|
| 2 | Build fehlgeschlagen oder Timeout | Nutzer informieren, stoppen |
| 3 | Loginseite nach 5 Min. nicht OK | Nutzer informieren, stoppen |
+224
View File
@@ -0,0 +1,224 @@
#!/bin/bash
# Upstream-Merge-Workflow für pretix_cgo
# Aufruf: ./upstream-merge.sh – vollständiger Lauf
# ./upstream-merge.sh --resume – nach Gender-Bereinigung fortsetzen
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
GITOPS_DIR="$(cd "$REPO_DIR/../OrtlerstrasseGitOps" && pwd)"
STATE_FILE="$SCRIPT_DIR/.upstream-merge-state"
GITEA_API="https://git.ortlerstrasse.de/api/v1"
GITEA_OWNER="CGM_Public"
GITEA_REPO="pretix_cgo"
# GITEA_TOKEN aus interaktiver Shell laden falls nicht gesetzt
if [[ -z "${GITEA_TOKEN:-}" ]] && [[ -f ~/.bashrc ]]; then
GITEA_TOKEN=$(bash -i -c 'echo $GITEA_TOKEN' 2>/dev/null) || GITEA_TOKEN=""
fi
set -euo pipefail
# --- Ausgabe-Utilities ---
green() { echo -e "\033[0;32m[✓]\033[0m $*"; }
yellow() { echo -e "\033[1;33m[→]\033[0m $*"; }
red() { echo -e "\033[0;31m[✗]\033[0m $*" >&2; }
pause() { echo ""; yellow "$1"; read -rp " [Enter zum Fortfahren] "; echo ""; }
# --- State speichern/laden ---
save_state() {
cat > "$STATE_FILE" <<EOF
UPSTREAM_TAG=$UPSTREAM_TAG
VERSION=$VERSION
BRANCH=$BRANCH
NEW_TAG=$NEW_TAG
EOF
}
load_state() {
if [[ ! -f "$STATE_FILE" ]]; then
red "Kein State-File gefunden ($STATE_FILE). Bitte ohne --resume starten."
exit 1
fi
# shellcheck source=/dev/null
source "$STATE_FILE"
green "State geladen: UPSTREAM_TAG=$UPSTREAM_TAG | BRANCH=$BRANCH | NEW_TAG=$NEW_TAG"
}
# --- Build-Pipeline pollen ---
poll_pipeline() {
local tag_sha="$1"
if [[ -z "${GITEA_TOKEN:-}" ]]; then
yellow "GITEA_TOKEN nicht gesetzt – Pipeline-Polling nicht möglich."
pause "Build manuell auf Gitea prüfen, dann Enter drücken."
return
fi
yellow "Warte auf Pipeline-Run für SHA ${tag_sha:0:12}..."
local run_id=""
for i in $(seq 1 12); do
sleep 10
run_id=$(curl -sf -H "Authorization: token $GITEA_TOKEN" \
"$GITEA_API/repos/$GITEA_OWNER/$GITEA_REPO/actions/runs?limit=10" \
| jq -r --arg sha "$tag_sha" \
'.workflow_runs[] | select(.head_sha == $sha) | .id' \
| head -1 || true)
[[ -n "$run_id" ]] && break
echo " ... noch kein Run ($i/12, warte 10s)"
done
if [[ -z "$run_id" ]]; then
red "Pipeline-Run nicht gefunden nach 2 Minuten."
pause "Build manuell prüfen, dann Enter drücken."
return
fi
green "Pipeline-Run #$run_id gefunden, überwache..."
for i in $(seq 1 30); do
sleep 20
local result
result=$(curl -sf -H "Authorization: token $GITEA_TOKEN" \
"$GITEA_API/repos/$GITEA_OWNER/$GITEA_REPO/actions/runs/$run_id" \
| jq -r '"\(.status)/\(.conclusion // "")"')
echo " Status: $result"
case "$result" in
completed/success) green "Build erfolgreich!"; return ;;
completed/*) red "Build fehlgeschlagen: $result"; exit 2 ;;
esac
[[ $i -eq 30 ]] && { red "Timeout: Build nach 10 Minuten nicht fertig."; exit 2; }
done
}
# --- URL pollen bis HTTP 200 ---
poll_url() {
local url="$1"
local label="$2"
yellow "Warte auf $label ($url)..."
for i in $(seq 1 20); do
sleep 15
local http
http=$(curl -sLo /dev/null -w "%{http_code}" "$url" 2>/dev/null || echo "000")
echo " HTTP: $http"
[[ "$http" == "200" ]] && { green "$label erreichbar (HTTP 200)."; return; }
echo " ... warte ($i/20)"
done
red "$label nicht erreichbar nach 5 Minuten."
exit 3
}
# ============================================================
# Hauptlogik
# ============================================================
RESUME=false
[[ "${1:-}" == "--resume" ]] && RESUME=true
if $RESUME; then
load_state
else
# --- Phase 1: Git-Setup ---
cd "$REPO_DIR"
green "Schritt 1: Master aktualisieren..."
git checkout master
git pull
green "Schritt 2: Upstream-Tags holen..."
git fetch upstream --tags
UPSTREAM_TAG=$(git tag --sort=-version:refname | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' | head -1)
VERSION="${UPSTREAM_TAG#v}"
BRANCH="upstream/$VERSION"
NEW_TAG="${VERSION}.0"
green "Upstream-Tag: $UPSTREAM_TAG | Branch: $BRANCH | Neuer Tag: $NEW_TAG"
save_state
green "Schritt 3: Branch erstellen..."
git checkout -b "$BRANCH" "tags/$UPSTREAM_TAG"
green "Schritt 4: Master mergen..."
git merge master
green "Schritt 5: Branch pushen + MR anlegen..."
PUSH_OUT=$(git push --set-upstream origin "$BRANCH" -o merge_request.create 2>&1 || true)
echo "$PUSH_OUT"
MR_URL=$(echo "$PUSH_OUT" | grep -oP 'https://\S+' | head -1 || true)
[[ -n "$MR_URL" ]] && yellow "MR-Link: $MR_URL"
# --- Phase 2: Gender-Prüfung ---
green "Schritt 6: Gender-Prüfung..."
PO_FILES=(
"src/pretix/locale/de/LC_MESSAGES/django.po"
"src/pretix/locale/de/LC_MESSAGES/djangojs.po"
"src/pretix/locale/de_Informal/LC_MESSAGES/django.po"
"src/pretix/locale/de_Informal/LC_MESSAGES/djangojs.po"
)
GENDER_PATTERN='([A-ZÄÖÜ][a-zäöü]+(\*|:|_)(in(nen)?)\b|[A-ZÄÖÜ][a-zäöü]+\((in|innen)\)|\b(Teilnehmenden|Helfenden|Organisierenden|Bestellenden|Buchenden|Zahlenden)\b)'
GENDER_HITS=$(grep -n -E "$GENDER_PATTERN" "${PO_FILES[@]}" 2>/dev/null || true)
if [[ -n "$GENDER_HITS" ]]; then
red "Gender-Befunde – Bereinigung notwendig. Bitte Claude übernehmen lassen:"
echo ""
echo "$GENDER_HITS"
echo ""
yellow "Nach der Bereinigung: git add + git commit + git push, dann script mit --resume starten."
exit 1
fi
green "Gender-Prüfung: Keine Befunde."
fi
# --- Phase 3: Warten auf MR-Merge ---
pause "Schritt 7: MR auf Gitea mergen, dann Enter drücken."
# --- Phase 4: Tag setzen + Build ---
cd "$REPO_DIR"
green "Schritt 8: Master aktualisieren + Tag $NEW_TAG setzen..."
git checkout master
git pull
TAG_SHA=$(git rev-parse HEAD)
git tag "$NEW_TAG"
git push origin "$NEW_TAG"
green "Tag $NEW_TAG gepusht (SHA: ${TAG_SHA:0:12})."
green "Schritt 9: Build-Pipeline überwachen..."
poll_pipeline "$TAG_SHA"
# --- Phase 5: cgm72 GitOps-Update ---
green "Schritt 10: cgm72 GitOps-Update..."
CGM72_YAML="$GITOPS_DIR/pretix-cgm72/pretix-deployment.yaml"
OLD_TAG=$(grep -oP 'cr\.ortlerstrasse\.de/cgo/pretix:\K[0-9]\S+' "$CGM72_YAML")
sed -i "s|cr.ortlerstrasse.de/cgo/pretix:${OLD_TAG}|cr.ortlerstrasse.de/cgo/pretix:${NEW_TAG}|" "$CGM72_YAML"
git -C "$GITOPS_DIR" add pretix-cgm72/pretix-deployment.yaml
git -C "$GITOPS_DIR" commit -m "Update pretix-cgm72 to $NEW_TAG"
git -C "$GITOPS_DIR" push
green "cgm72 YAML aktualisiert ($OLD_TAG → $NEW_TAG)."
green "Schritt 11: Warte auf cgm72..."
poll_url "https://anmeldung.christliche-gemeinde.de/" "cgm72"
# --- Phase 6: Manuelle Bestätigung cgm72 ---
pause "Schritt 12: cgm72 manuell prüfen (https://anmeldung.christliche-gemeinde.de/). OK? Enter drücken."
# --- Phase 7: sola GitOps-Update ---
green "Schritt 13: sola GitOps-Update..."
SOLA_YAML="$GITOPS_DIR/pretix-sola/pretix-deployment.yaml"
OLD_TAG_SOLA=$(grep -oP 'cr\.ortlerstrasse\.de/cgo/pretix:\K[0-9]\S+' "$SOLA_YAML")
sed -i "s|cr.ortlerstrasse.de/cgo/pretix:${OLD_TAG_SOLA}|cr.ortlerstrasse.de/cgo/pretix:${NEW_TAG}|" "$SOLA_YAML"
git -C "$GITOPS_DIR" add pretix-sola/pretix-deployment.yaml
git -C "$GITOPS_DIR" commit -m "Update pretix-sola to $NEW_TAG"
git -C "$GITOPS_DIR" push
green "sola YAML aktualisiert ($OLD_TAG_SOLA → $NEW_TAG)."
green "Schritt 14: Warte auf sola..."
poll_url "https://anmeldung.sola-muenchen.de" "sola"
# Aufräumen
rm -f "$STATE_FILE"
echo ""
green "============================================"
green " Upstream-Merge $NEW_TAG abgeschlossen ✓"
green "============================================"