#!/usr/bin/env bash # Replace only launcher installer + latest.yml attachments on a Gitea release. # Does NOT delete Wow.exe, MPQs, or patch-manifest — use this to publish a # "bridge" build (e.g. 1.0.13 with new baked Gitea URL) on a legacy host while # keeping game assets already on that release. # # Usage: # export GITEA_BASE_URL=http://legacy-host:port # or https://... # export GITEA_TOKEN=gta_... # export GITEA_OWNER=Dawnsorrow # export GITEA_REPO=Fractured-Distro # ./gitea-replace-launcher-only.sh /path/to/electron/dist latest # set -euo pipefail SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) # shellcheck source=release-sync-filters.sh . "$SCRIPT_DIR/release-sync-filters.sh" DIST_DIR="${1:?first arg: electron-builder dist directory (contains .exe / .AppImage / latest*.yml)}" TAG="${2:?second arg: release tag (e.g. latest)}" : "${GITEA_BASE_URL:?Set GITEA_BASE_URL}" : "${GITEA_TOKEN:?Set GITEA_TOKEN}" : "${GITEA_OWNER:?Set GITEA_OWNER}" : "${GITEA_REPO:?Set GITEA_REPO}" BASE="${GITEA_BASE_URL%/}" API="$BASE/api/v1" AUTH_H=(-H "Authorization: token ${GITEA_TOKEN}" -H "Accept: application/json") TAG_ENC=$(python3 -c "import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1], safe=''))" "$TAG") REL_JSON=$(mktemp) trap 'rm -f "$REL_JSON"' EXIT code=$(curl -sS -o "$REL_JSON" -w "%{http_code}" "${AUTH_H[@]}" \ "$API/repos/${GITEA_OWNER}/${GITEA_REPO}/releases/tags/${TAG_ENC}") if [ "$code" != "200" ]; then echo "Gitea GET release by tag failed HTTP $code (release must already exist):" >&2 cat "$REL_JSON" >&2 exit 1 fi rel_id=$(jq -r '.id' "$REL_JSON") if [ -z "$rel_id" ] || [ "$rel_id" = "null" ]; then echo "Could not resolve Gitea release id" >&2 exit 1 fi should_delete_attachment() { local l l=$(printf '%s' "${1##*/}" | tr '[:upper:]' '[:lower:]') case "$l" in fractured-launcher*) return 0 ;; *.blockmap) return 0 ;; builder-debug.yml|builder-debug.yaml) return 0 ;; esac return 1 } should_delete_yml_attachment() { local l l=$(printf '%s' "${1##*/}" | tr '[:upper:]' '[:lower:]') case "$l" in latest.yml) [ -f "$DIST_DIR/latest.yml" ] ;; latest-linux.yml) [ -f "$DIST_DIR/latest-linux.yml" ] ;; latest-mac.yml) [ -f "$DIST_DIR/latest-mac.yml" ] ;; *) return 1 ;; esac } while read -r line; do [ -z "$line" ] && continue aid=$(printf '%s' "$line" | cut -f1) aname=$(printf '%s' "$line" | cut -f2-) if should_delete_attachment "$aname" || should_delete_yml_attachment "$aname"; then echo "Removing old attachment: $aname (id=$aid)" curl -fsS -X DELETE "${AUTH_H[@]}" \ "$API/repos/${GITEA_OWNER}/${GITEA_REPO}/releases/${rel_id}/assets/${aid}" || true fi done < <(jq -r '(.attachments // .assets // [])[] | "\(.id)\t\(.name)"' "$REL_JSON") shopt -s nullglob upload_paths=() for f in "$DIST_DIR"/Fractured-Launcher*.exe "$DIST_DIR"/Fractured-Launcher*.AppImage \ "$DIST_DIR"/latest.yml "$DIST_DIR"/latest-linux.yml "$DIST_DIR"/latest-mac.yml; do [ -f "$f" ] || continue bn=$(basename "$f") if should_skip_gitea_upload "$bn"; then continue fi upload_paths+=("$f") done if [ "${#upload_paths[@]}" -eq 0 ]; then echo "No launcher files to upload under $DIST_DIR (expected Fractured-Launcher*.exe, *.AppImage, latest.yml, latest-linux.yml)." >&2 exit 1 fi for f in "${upload_paths[@]}"; do bn=$(basename "$f") echo "Uploading $bn …" curl -fsS -X POST "${AUTH_H[@]}" \ -F "attachment=@${f}" \ "$API/repos/${GITEA_OWNER}/${GITEA_REPO}/releases/${rel_id}/assets" done echo "Done. Release $TAG (id=$rel_id): replaced ${#upload_paths[@]} launcher file(s); game assets left intact."