Files
Fractured/tools/fractured-launcher-electron/scripts/gitea-replace-launcher-only.sh
T
Docker Build 0bb6b0ef84 feat(launcher): script to replace launcher-only on legacy Gitea release
- gitea-replace-launcher-only.sh: swap Fractured-Launcher* + yml without wiping MPQs
- Only remove latest.yml / latest-linux.yml if a replacement exists in dist/
- README: bridge rollout steps and checklist item

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-12 21:44:13 -05:00

110 lines
3.6 KiB
Bash
Executable File

#!/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."