188 lines
6.7 KiB
Bash
Executable file
188 lines
6.7 KiB
Bash
Executable file
#!/usr/bin/env bash
|
||
|
||
# ============================================================
|
||
# Steuerkram Test-Runner mit automatischer Issue-Erstellung
|
||
#
|
||
# Verwendung (im Container):
|
||
# docker compose exec -u www-data web ./scripts/container/run-tests.sh [ISSUE_NUMMER]
|
||
#
|
||
# Parameter:
|
||
# ISSUE_NUMMER (optional) Nummer des aktuell bearbeiteten Issues,
|
||
# auf das bei neu erstellten Bug-Issues verwiesen wird.
|
||
#
|
||
# Umgebungsvariablen:
|
||
# CODEBERG_TOKEN Codeberg-API-Token (für Issue-Erstellung)
|
||
#
|
||
# Exit-Code: 0 = alle Tests OK, 1 = Fehler gefunden (oder Auswertung fehlgeschlagen)
|
||
# ============================================================
|
||
|
||
set -euo pipefail
|
||
|
||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
PROJECT_DIR="$(dirname "$(dirname "$SCRIPT_DIR")")"
|
||
CURRENT_ISSUE="${1:-}"
|
||
REPO="fds2610/Steuerkram"
|
||
API_BASE="https://codeberg.org/api/v1"
|
||
|
||
cd "$PROJECT_DIR"
|
||
|
||
# ── PHP als www-data ausführen ───────────────────────────────
|
||
# Als root angelegte Dateien unterhalb von data/ sind für Apache/PHP (www-data)
|
||
# nicht beschreibbar und blockieren später echte Uploads. Deshalb laufen die
|
||
# Tests mit derselben Kennung wie die Anwendung.
|
||
if [ "$(id -u)" = "0" ] && id www-data >/dev/null 2>&1; then
|
||
PHP="setpriv --reuid=www-data --regid=www-data --clear-groups php"
|
||
else
|
||
PHP="php"
|
||
fi
|
||
|
||
# ── Tests ausführen ──────────────────────────────────────────
|
||
echo ""
|
||
echo "Führe Tests aus..."
|
||
# STDERR wird bewusst NICHT mitgefangen: tests/run.php schreibt im --json-Modus
|
||
# etwaige PHP-Warnungen/-Notices dorthin, damit STDOUT ausschließlich das JSON
|
||
# enthält (siehe tests/run.php). STDERR landet direkt im Terminal.
|
||
JSON_OUTPUT=$($PHP tests/run.php --json) && EXIT_CODE=0 || EXIT_CODE=$?
|
||
|
||
# Auch die lesbare Ausgabe zeigen
|
||
$PHP tests/run.php || true
|
||
|
||
# ── Ergebnis auswerten ───────────────────────────────────────
|
||
if [ "$EXIT_CODE" -eq 0 ]; then
|
||
echo ""
|
||
echo "✓ Alle Tests bestanden. Commit kann fortgesetzt werden."
|
||
exit 0
|
||
fi
|
||
|
||
# tests/run.php meldet Fehlschläge (oder einen sonstigen Fehler) über den
|
||
# Exit-Code. Die Details holen wir uns per PHP aus dem JSON – lässt sich die
|
||
# Ausgabe nicht auswerten, bricht das Skript hier ab (set -e), statt
|
||
# fälschlich Erfolg zu melden.
|
||
FAILED=$(echo "$JSON_OUTPUT" | php -r '
|
||
$d = json_decode(stream_get_contents(STDIN), true);
|
||
if (!is_array($d) || !array_key_exists("failed", $d)) {
|
||
fwrite(STDERR, "Ungültige JSON-Ausgabe von tests/run.php --json\n");
|
||
exit(1);
|
||
}
|
||
echo $d["failed"];
|
||
')
|
||
FAILURES_JSON=$(echo "$JSON_OUTPUT" | php -r '
|
||
$d = json_decode(stream_get_contents(STDIN), true);
|
||
if (!is_array($d) || !array_key_exists("failures", $d)) {
|
||
fwrite(STDERR, "Ungültige JSON-Ausgabe von tests/run.php --json\n");
|
||
exit(1);
|
||
}
|
||
echo json_encode($d["failures"]);
|
||
')
|
||
|
||
echo ""
|
||
echo "✗ ${FAILED} Test(s) fehlgeschlagen."
|
||
|
||
# ── Issues erstellen (nur wenn Token vorhanden) ──────────────
|
||
if [ -z "${CODEBERG_TOKEN:-}" ]; then
|
||
echo ""
|
||
echo "Hinweis: CODEBERG_TOKEN nicht gesetzt – keine automatischen Issues erstellt."
|
||
echo "Fehlgeschlagene Tests:"
|
||
echo "$FAILURES_JSON" | php -r '
|
||
$d = json_decode(stream_get_contents(STDIN), true);
|
||
foreach ((is_array($d) ? $d : []) as $f) { echo " • {$f}\n"; }
|
||
'
|
||
exit 1
|
||
fi
|
||
|
||
echo ""
|
||
echo "Erstelle automatische Bug-Issues auf Codeberg..."
|
||
|
||
CREATED_ISSUES=()
|
||
|
||
# Jede Fehlermeldung als eigenes Issue anlegen
|
||
while IFS= read -r failure; do
|
||
[ -z "$failure" ] && continue
|
||
|
||
# Titel kürzen (max. 100 Zeichen)
|
||
TITLE="[BUG] Test fehlgeschlagen: ${failure:0:80}"
|
||
|
||
# Body zusammenbauen (mit echten Zeilenumbrüchen, kein "\n"-Text)
|
||
BODY_LINES=(
|
||
"## Automatisch erkannter Testfehler"
|
||
""
|
||
"**Fehlermeldung:** \`${failure}\`"
|
||
""
|
||
"**Erkannt am:** $(date '+%Y-%m-%d %H:%M:%S')"
|
||
""
|
||
"**Commit:** $(git rev-parse --short HEAD 2>/dev/null || echo 'unbekannt')"
|
||
""
|
||
)
|
||
if [ -n "$CURRENT_ISSUE" ]; then
|
||
BODY_LINES+=("Dieser Fehler wurde beim Bearbeiten von Issue #${CURRENT_ISSUE} entdeckt." "")
|
||
fi
|
||
BODY_LINES+=(
|
||
"### Schritte zur Reproduktion"
|
||
"1. \`docker compose exec -u www-data web php tests/run.php\` ausführen"
|
||
"2. Fehler tritt im oben genannten Test auf"
|
||
""
|
||
"_Dieser Issue wurde automatisch durch den Test-Runner erstellt._"
|
||
"_Das Label 'automate' wurde bewusst NICHT gesetzt (Human-in-the-loop)._"
|
||
)
|
||
BODY=$(printf '%s\n' "${BODY_LINES[@]}")
|
||
|
||
PAYLOAD=$(TITLE="$TITLE" BODY="$BODY" php -r '
|
||
echo json_encode([
|
||
"title" => getenv("TITLE"),
|
||
"body" => getenv("BODY"),
|
||
"labels" => [],
|
||
]);
|
||
')
|
||
|
||
RESPONSE=$(curl -s -X POST \
|
||
-H "Authorization: token $CODEBERG_TOKEN" \
|
||
-H "Content-Type: application/json" \
|
||
-d "$PAYLOAD" \
|
||
"${API_BASE}/repos/${REPO}/issues")
|
||
|
||
ISSUE_NR=$(echo "$RESPONSE" | php -r '
|
||
$d = json_decode(stream_get_contents(STDIN), true);
|
||
echo (is_array($d) && isset($d["number"])) ? $d["number"] : "?";
|
||
')
|
||
CREATED_ISSUES+=("#${ISSUE_NR}")
|
||
echo " → Issue #${ISSUE_NR} erstellt: ${failure:0:60}..."
|
||
|
||
done < <(echo "$FAILURES_JSON" | php -r '
|
||
$d = json_decode(stream_get_contents(STDIN), true);
|
||
foreach ((is_array($d) ? $d : []) as $f) { echo $f, "\n"; }
|
||
')
|
||
|
||
# ── Kommentar im aktuellen Issue hinterlassen ─────────────────
|
||
if [ -n "$CURRENT_ISSUE" ] && [ ${#CREATED_ISSUES[@]} -gt 0 ]; then
|
||
ISSUE_LINKS=$(printf '%s, ' "${CREATED_ISSUES[@]}")
|
||
ISSUE_LINKS="${ISSUE_LINKS%, }"
|
||
|
||
COMMENT_LINES=(
|
||
"### Automatische Testläufe"
|
||
""
|
||
"Beim Bearbeiten dieses Issues wurden **${FAILED} Test(s)** fehlgeschlagen."
|
||
""
|
||
"Folgende Bug-Issues wurden automatisch erstellt (ohne 'automate'-Label – bitte manuell prüfen):"
|
||
""
|
||
)
|
||
for issue in "${CREATED_ISSUES[@]}"; do
|
||
COMMENT_LINES+=("- ${issue}")
|
||
done
|
||
COMMENT_LINES+=("" "_Commit: $(git rev-parse --short HEAD 2>/dev/null || echo 'unbekannt')_")
|
||
COMMENT=$(printf '%s\n' "${COMMENT_LINES[@]}")
|
||
|
||
PAYLOAD=$(COMMENT="$COMMENT" php -r '
|
||
echo json_encode(["body" => getenv("COMMENT")]);
|
||
')
|
||
|
||
curl -s -X POST \
|
||
-H "Authorization: token $CODEBERG_TOKEN" \
|
||
-H "Content-Type: application/json" \
|
||
-d "$PAYLOAD" \
|
||
"${API_BASE}/repos/${REPO}/issues/${CURRENT_ISSUE}/comments" > /dev/null
|
||
|
||
echo ""
|
||
echo "Kommentar mit Links zu Bug-Issues in Issue #${CURRENT_ISSUE} hinterlassen."
|
||
fi
|
||
|
||
exit 1
|