diff --git a/.gitea/scripts/publish-release.sh b/.gitea/scripts/publish-release.sh index 8bc31a1..eee9710 100755 --- a/.gitea/scripts/publish-release.sh +++ b/.gitea/scripts/publish-release.sh @@ -21,9 +21,21 @@ # 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. +# DESKTOP_DIST Ordner mit den Desktop-Paketen und manifest.json (Phase 18, +# 18-02); Vorgabe desktop-dist. Fehlt manifest.json bei Tags, +# bricht das Skript ab -- der Release-Text ist dann schon +# angelegt/aktualisiert, der Job wird sichtbar rot. # # Fehlt der Abschnitt fuer die Version, endet das Skript mit Exit 1 -- es entsteht # nie ein leerer Release. JSON wird ausschliesslich mit jq gebaut. +# +# Release-Dateien (Phase 18, 18-02): jede Datei aus manifest.json wird idempotent +# angehaengt -- GET .../releases/{id}/assets, vorhandene Datei gleichen Namens per +# DELETE .../releases/{id}/assets/{asset_id} entfernen, dann frisch per +# POST .../releases/{id}/assets?name=... (multipart-Feld attachment) hochladen. +# Der multipart-Upload braucht eine zweite Header-Datei ($HDR_AUTH) OHNE +# Content-Type: application/json -- curl setzt den multipart-Content-Type sonst +# nicht korrekt, wenn der JSON-Header schon gesetzt ist. set -eu usage() { @@ -101,11 +113,21 @@ UPDATE_JSON=$(jq -n --arg name "$NAME" --arg body "$BODY" '{name: $name, body: $ RELEASES_URL="$API/repos/$REPO/releases" TAG_URL="$API/repos/$REPO/releases/tags/$TAG" +DESKTOP_DIST="${DESKTOP_DIST:-desktop-dist}" +MANIFEST="$DESKTOP_DIST/manifest.json" + if [ "$DRY_RUN" -eq 1 ]; then echo "Probelauf (kein Netzaufruf):" echo " POST $RELEASES_URL" echo " PATCH $RELEASES_URL/ (falls GET $TAG_URL bereits 200 liefert)" printf '%s\n' "$CREATE_JSON" + if [ -f "$MANIFEST" ]; then + for FNAME in $(jq -r '.files[].name' "$MANIFEST"); do + echo " POST $RELEASES_URL//assets?name=$FNAME" + done + else + echo " ($MANIFEST fehlt -- keine geplanten Uploads im Probelauf)" + fi exit 0 fi @@ -118,9 +140,46 @@ umask 077 TMPDIR_REL=$(mktemp -d) trap 'rm -rf "$TMPDIR_REL"' EXIT INT TERM HDR="$TMPDIR_REL/headers" +HDR_AUTH="$TMPDIR_REL/headers-auth" RESP="$TMPDIR_REL/response.json" +ASSETS_RESP="$TMPDIR_REL/assets.json" JSONFILE="$TMPDIR_REL/payload.json" printf 'Authorization: token %s\nContent-Type: application/json\n' "$GITEA_TOKEN" > "$HDR" +# Zweite Header-Datei ohne Content-Type: application/json -- der multipart-Upload +# (POST .../assets) darf keinen JSON-Content-Type mitbekommen. +printf 'Authorization: token %s\n' "$GITEA_TOKEN" > "$HDR_AUTH" + +# upload_asset FILE NAME RELEASE_ID -- idempotent: vorhandene Datei gleichen Namens +# wird zuerst entfernt (GET -> DELETE), dann frisch hochgeladen (POST multipart). +upload_asset() { + ASSET_FILE="$1" + ASSET_NAME="$2" + ASSET_RELEASE_ID="$3" + + ASSETS_CODE=$(curl -sS --header @"$HDR" -o "$ASSETS_RESP" -w '%{http_code}' "$RELEASES_URL/$ASSET_RELEASE_ID/assets") + if [ "$ASSETS_CODE" != "200" ]; then + echo "GET $RELEASES_URL/$ASSET_RELEASE_ID/assets antwortete mit $ASSETS_CODE:" >&2 + cat "$ASSETS_RESP" >&2 + exit 1 + fi + + EXISTING_ID=$(jq -r --arg n "$ASSET_NAME" '.[] | select(.name == $n) | .id' "$ASSETS_RESP") + if [ -n "$EXISTING_ID" ]; then + DEL_CODE=$(curl -sS --header @"$HDR" -X DELETE -o "$RESP" -w '%{http_code}' "$RELEASES_URL/$ASSET_RELEASE_ID/assets/$EXISTING_ID") + if [ "$DEL_CODE" != "204" ]; then + echo "DELETE $RELEASES_URL/$ASSET_RELEASE_ID/assets/$EXISTING_ID antwortete mit $DEL_CODE:" >&2 + cat "$RESP" >&2 + exit 1 + fi + fi + + UPLOAD_CODE=$(curl -sS --header @"$HDR_AUTH" -X POST -F "attachment=@${ASSET_FILE};filename=${ASSET_NAME}" -o "$RESP" -w '%{http_code}' "$RELEASES_URL/$ASSET_RELEASE_ID/assets?name=$ASSET_NAME") + if [ "$UPLOAD_CODE" != "201" ]; then + echo "POST $RELEASES_URL/$ASSET_RELEASE_ID/assets?name=$ASSET_NAME antwortete mit $UPLOAD_CODE:" >&2 + cat "$RESP" >&2 + exit 1 + fi +} CODE=$(curl -sS --header @"$HDR" -o "$RESP" -w '%{http_code}' "$TAG_URL") case "$CODE" in @@ -140,7 +199,8 @@ case "$CODE" in 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"))" + ID=$(jq -r .id "$RESP") + echo "Release $TAG angelegt (id $ID)" else echo "POST $RELEASES_URL antwortete mit $CODE:" >&2 cat "$RESP" >&2 @@ -153,3 +213,16 @@ case "$CODE" in exit 1 ;; esac + +# Release-Dateien aus dem Manifest anhaengen (Phase 18, 18-02). Der Release-Text +# ist an dieser Stelle bereits angelegt/aktualisiert -- fehlt das Manifest, wird +# das trotzdem hart abgebrochen (kein Release ohne Pakete bei einem Freigabe-Tag). +if [ ! -f "$MANIFEST" ]; then + echo "$MANIFEST fehlt -- kein Release ohne Desktop-Pakete." >&2 + exit 1 +fi + +for FNAME in $(jq -r '.files[].name' "$MANIFEST"); do + upload_asset "$DESKTOP_DIST/$FNAME" "$FNAME" "$ID" + echo "Release-Datei $FNAME hochgeladen" +done