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
|
||||
Reference in New Issue
Block a user