ci(quick-260916-dcz): Gitea-Release je Freigabe-Tag aus CHANGELOG.md (publish-release.sh, idempotent, --dry-run), Schritt in ci.yml
- publish-release.sh: POSIX sh, Entscheidung anhand GITHUB_REF wie publish-images.sh, --tag/--dry-run, Abschnitt per awk, JSON nur per jq --arg, Token nur aus GITEA_TOKEN ueber Header-Datei, GET/tags -> PATCH oder POST, Exit 1 ohne Abschnitt - ci.yml: vierter Schritt im Job publish mit GITEA_TOKEN aus secrets.REGISTRY_TOKEN ueber env - Bewiesen: dry-run v1.0.0 (Body 2227 Zeichen), v9.9.9 Exit 1, main nichts zu tun, API-Basis aus GITHUB_SERVER_URL; Docker-Abbild traegt den Changelog nur im Server-Bundle (1/0); Release Tessera 1.0.0 (id 1) angelegt, zweiter Lauf PATCH, genau ein Release Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018N9CD3ebPKm1b32bPpBknY
This commit is contained in:
Executable
+155
@@ -0,0 +1,155 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# publish-release.sh -- Gitea-Release je Freigabe-Tag aus CHANGELOG.md anlegen
|
||||||
|
# (quick-260916-dcz).
|
||||||
|
#
|
||||||
|
# Entscheidung wie publish-images.sh allein anhand GITHUB_REF:
|
||||||
|
# refs/tags/vX.Y.Z -> Abschnitt "## X.Y.Z" aus CHANGELOG.md schneiden und als
|
||||||
|
# Release "Tessera X.Y.Z" anlegen (bzw. aktualisieren, wenn
|
||||||
|
# der Release zum Tag schon existiert -- idempotent)
|
||||||
|
# alles andere -> nichts zu tun (Exit 0)
|
||||||
|
#
|
||||||
|
# Aufrufformen:
|
||||||
|
# sh .gitea/scripts/publish-release.sh # im CI, Tag aus GITHUB_REF
|
||||||
|
# sh .gitea/scripts/publish-release.sh --tag v1.0.0 # lokal, expliziter Tag
|
||||||
|
# sh .gitea/scripts/publish-release.sh --dry-run --tag v1.0.0 # nur JSON und Ziel zeigen
|
||||||
|
#
|
||||||
|
# Umgebung:
|
||||||
|
# GITEA_TOKEN Zugriffstoken (Pflicht im echten Lauf; im CI aus secrets.REGISTRY_TOKEN
|
||||||
|
# ueber `env`). Wird nie ausgegeben und nie als Argument uebergeben --
|
||||||
|
# der Authorization-Header kommt aus einer temporaeren Datei.
|
||||||
|
# GITEA_API API-Basis; sonst GITHUB_API_URL, sonst GITHUB_SERVER_URL/api/v1,
|
||||||
|
# sonst http://localhost:3002/api/v1 (nur lokal erreichbar).
|
||||||
|
# GITEA_REPO owner/repo; sonst GITHUB_REPOSITORY, sonst schalli/tessera-ctl.
|
||||||
|
# CHANGELOG_FILE Pfad zur Aenderungsliste; Vorgabe CHANGELOG.md.
|
||||||
|
#
|
||||||
|
# Fehlt der Abschnitt fuer die Version, endet das Skript mit Exit 1 -- es entsteht
|
||||||
|
# nie ein leerer Release. JSON wird ausschliesslich mit jq gebaut.
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
echo "Aufruf: publish-release.sh [--dry-run] [--tag vX.Y.Z]" >&2
|
||||||
|
}
|
||||||
|
|
||||||
|
DRY_RUN=0
|
||||||
|
TAG=""
|
||||||
|
while [ $# -gt 0 ]; do
|
||||||
|
case "$1" in
|
||||||
|
--dry-run) DRY_RUN=1 ;;
|
||||||
|
--tag)
|
||||||
|
[ $# -ge 2 ] || { usage; exit 2; }
|
||||||
|
TAG="$2"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*) usage; exit 2 ;;
|
||||||
|
esac
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ -z "$TAG" ]; then
|
||||||
|
REF="${GITHUB_REF:-}"
|
||||||
|
case "$REF" in
|
||||||
|
refs/tags/v*) TAG="${REF#refs/tags/}" ;;
|
||||||
|
*)
|
||||||
|
echo "Kein Freigabe-Tag (nur refs/tags/v*): nichts zu tun."
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! echo "$TAG" | grep -Eq '^v[0-9]+\.[0-9]+\.[0-9]+$'; then
|
||||||
|
echo "Ungueltiger Tag '$TAG' (erwartet vX.Y.Z)." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
VERSION="${TAG#v}"
|
||||||
|
|
||||||
|
API="${GITEA_API:-${GITHUB_API_URL:-${GITHUB_SERVER_URL:+${GITHUB_SERVER_URL}/api/v1}}}"
|
||||||
|
API="${API:-http://localhost:3002/api/v1}"
|
||||||
|
API="${API%/}"
|
||||||
|
REPO="${GITEA_REPO:-${GITHUB_REPOSITORY:-schalli/tessera-ctl}}"
|
||||||
|
echo "Gitea-API: $API Repo: $REPO Tag: $TAG"
|
||||||
|
|
||||||
|
CHANGELOG="${CHANGELOG_FILE:-CHANGELOG.md}"
|
||||||
|
if [ ! -f "$CHANGELOG" ]; then
|
||||||
|
echo "$CHANGELOG nicht gefunden." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
command -v jq >/dev/null 2>&1 || { echo "jq fehlt." >&2; exit 1; }
|
||||||
|
|
||||||
|
# Abschnitt "## X.Y.Z" bis zur naechsten "## "-Ueberschrift, ohne die eigene
|
||||||
|
# Ueberschrift; danach fuehrende und abschliessende Leerzeilen entfernen.
|
||||||
|
BODY=$(awk -v ver="$VERSION" '
|
||||||
|
BEGIN { esc = ver; gsub(/\./, "\\.", esc); pat = "^## " esc "( |$)" }
|
||||||
|
$0 ~ pat { f = 1; next }
|
||||||
|
/^## / { if (f) exit }
|
||||||
|
f { print }
|
||||||
|
' "$CHANGELOG" | awk '
|
||||||
|
{ line[NR] = $0; if ($0 !~ /^[[:space:]]*$/) last = NR }
|
||||||
|
END { for (i = 1; i <= last; i++) print line[i] }
|
||||||
|
' | sed '1{/^$/d}')
|
||||||
|
|
||||||
|
if [ -z "$BODY" ]; then
|
||||||
|
echo "$CHANGELOG hat keinen Abschnitt fuer Version $VERSION (erwartet eine Zeile '## $VERSION – <Datum>'). Kein Release ohne Text." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
NAME="Tessera $VERSION"
|
||||||
|
CREATE_JSON=$(jq -n --arg tag "$TAG" --arg name "$NAME" --arg body "$BODY" \
|
||||||
|
'{tag_name: $tag, name: $name, body: $body, draft: false, prerelease: false}')
|
||||||
|
UPDATE_JSON=$(jq -n --arg name "$NAME" --arg body "$BODY" '{name: $name, body: $body}')
|
||||||
|
|
||||||
|
RELEASES_URL="$API/repos/$REPO/releases"
|
||||||
|
TAG_URL="$API/repos/$REPO/releases/tags/$TAG"
|
||||||
|
|
||||||
|
if [ "$DRY_RUN" -eq 1 ]; then
|
||||||
|
echo "Probelauf (kein Netzaufruf):"
|
||||||
|
echo " POST $RELEASES_URL"
|
||||||
|
echo " PATCH $RELEASES_URL/<id> (falls GET $TAG_URL bereits 200 liefert)"
|
||||||
|
printf '%s\n' "$CREATE_JSON"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "${GITEA_TOKEN:-}" ]; then
|
||||||
|
echo "Kein Zugriffstoken in der Umgebung gesetzt (siehe Kopfkommentar)." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
umask 077
|
||||||
|
TMPDIR_REL=$(mktemp -d)
|
||||||
|
trap 'rm -rf "$TMPDIR_REL"' EXIT INT TERM
|
||||||
|
HDR="$TMPDIR_REL/headers"
|
||||||
|
RESP="$TMPDIR_REL/response.json"
|
||||||
|
JSONFILE="$TMPDIR_REL/payload.json"
|
||||||
|
printf 'Authorization: token %s\nContent-Type: application/json\n' "$GITEA_TOKEN" > "$HDR"
|
||||||
|
|
||||||
|
CODE=$(curl -sS --header @"$HDR" -o "$RESP" -w '%{http_code}' "$TAG_URL")
|
||||||
|
case "$CODE" in
|
||||||
|
200)
|
||||||
|
ID=$(jq -r .id "$RESP")
|
||||||
|
printf '%s' "$UPDATE_JSON" > "$JSONFILE"
|
||||||
|
CODE=$(curl -sS --header @"$HDR" -X PATCH --data @"$JSONFILE" -o "$RESP" -w '%{http_code}' "$RELEASES_URL/$ID")
|
||||||
|
if [ "$CODE" = "200" ]; then
|
||||||
|
echo "Release $TAG aktualisiert (id $ID)"
|
||||||
|
else
|
||||||
|
echo "PATCH $RELEASES_URL/$ID antwortete mit $CODE:" >&2
|
||||||
|
cat "$RESP" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
404)
|
||||||
|
printf '%s' "$CREATE_JSON" > "$JSONFILE"
|
||||||
|
CODE=$(curl -sS --header @"$HDR" -X POST --data @"$JSONFILE" -o "$RESP" -w '%{http_code}' "$RELEASES_URL")
|
||||||
|
if [ "$CODE" = "201" ]; then
|
||||||
|
echo "Release $TAG angelegt (id $(jq -r .id "$RESP"))"
|
||||||
|
else
|
||||||
|
echo "POST $RELEASES_URL antwortete mit $CODE:" >&2
|
||||||
|
cat "$RESP" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "GET $TAG_URL antwortete mit $CODE:" >&2
|
||||||
|
cat "$RESP" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
# Kanalmodell (quick-260914-ku1): main -> Kanal beta (Etiketten beta + latest);
|
# Kanalmodell (quick-260914-ku1): main -> Kanal beta (Etiketten beta + latest);
|
||||||
# Tag v* -> Kanal live (Etiketten live + vX.Y.Z); Zweig live ohne Tag wird nur geprueft.
|
# Tag v* -> Kanal live (Etiketten live + vX.Y.Z); Zweig live ohne Tag wird nur geprueft.
|
||||||
# Die Entscheidung trifft .gitea/scripts/publish-images.sh anhand GITHUB_REF.
|
# Die Entscheidung trifft .gitea/scripts/publish-images.sh anhand GITHUB_REF.
|
||||||
|
# Tag v* (quick-260916-dcz): zusaetzlich Gitea-Release aus dem CHANGELOG.md-Abschnitt (publish-release.sh).
|
||||||
name: Tessera CI/CD
|
name: Tessera CI/CD
|
||||||
|
|
||||||
on:
|
on:
|
||||||
@@ -66,3 +67,8 @@ jobs:
|
|||||||
|
|
||||||
- name: Versionsstempel berechnen, Abbilder bauen und veroeffentlichen
|
- name: Versionsstempel berechnen, Abbilder bauen und veroeffentlichen
|
||||||
run: sh .gitea/scripts/publish-images.sh
|
run: sh .gitea/scripts/publish-images.sh
|
||||||
|
|
||||||
|
- name: Gitea-Release zum Freigabe-Tag anlegen (nur bei Tags v*)
|
||||||
|
env:
|
||||||
|
GITEA_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
|
||||||
|
run: sh .gitea/scripts/publish-release.sh
|
||||||
|
|||||||
Reference in New Issue
Block a user