1 Commits
Author SHA1 Message Date
ckochandClaude Opus 4.8 efaab8bd32 Fix release pipeline: bepinex packaging + no silent failures
'GAME=BurglinGnomes ./tools/publish.sh' exited with zero output. Two causes:

1. build_release.sh was SUWSF-only and hard-failed on a missing SUWSF.ini for
   BepInEx games. It now reads METHOD from game.conf and packages BepInEx plus
   the prebuilt plugin instead.
2. publish.sh ran the build with stdout to /dev/null, so that error was
   invisible and  killed the script silently. Build output is now shown
   and failure reported explicitly.

Also: publish.sh creates the tag locally when missing (v1.1.0 never existed, so
the tag push would have failed too), and defaults the release body to the
game's own README so per-game notes are always accurate.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-21 16:40:41 -04:00
2 changed files with 42 additions and 15 deletions
+28 -9
View File
@@ -1,27 +1,46 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# Build a drop-in release zip for one game. # Build a drop-in release zip for one game. Handles both fix methods.
# ./tools/build_release.sh GundamBreaker4 # ./tools/build_release.sh GundamBreaker4 (METHOD=suwsf)
# Output: dist/<Game>_UltraWide_Fix.zip (attach to the GitHub Release) # ./tools/build_release.sh BurglinGnomes (METHOD=bepinex)
# Output: dist/<Game>_UltraWide_Fix.zip
set -euo pipefail set -euo pipefail
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "$HERE" cd "$HERE"
GAME="${1:?usage: build_release.sh <GameName>}" GAME="${1:?usage: build_release.sh <GameName>}"
GDIR="games/$GAME" GDIR="games/$GAME"
V="vendor/SUWSF-x64"
[ -d "$GDIR" ] || { echo "[!] no such game: $GDIR"; exit 1; } [ -d "$GDIR" ] || { echo "[!] no such game: $GDIR"; exit 1; }
for f in "$V/SUWSF.asi" "$V/dsound.dll" "$V/LICENSE" "$GDIR/SUWSF.ini"; do [ -f "$GDIR/game.conf" ] || { echo "[!] missing $GDIR/game.conf"; exit 1; }
[ -f "$f" ] || { echo "[!] missing $f"; exit 1; } # shellcheck disable=SC1090
done . "$GDIR/game.conf"
METHOD="${METHOD:-suwsf}"
OUT="dist/${GAME}_UltraWide_Fix" OUT="dist/${GAME}_UltraWide_Fix"
rm -rf "$OUT" "$OUT.zip" rm -rf "$OUT" "$OUT.zip"
mkdir -p "$OUT" mkdir -p "$OUT"
if [ "$METHOD" = "bepinex" ]; then
BEPZIP=$(ls vendor/BepInEx_win_x64_*.zip 2>/dev/null | head -1)
[ -f "$BEPZIP" ] || { echo "[!] missing BepInEx zip in vendor/"; exit 1; }
[ -f "$GDIR/$PLUGIN_DLL" ] || { echo "[!] missing prebuilt plugin $GDIR/$PLUGIN_DLL"; exit 1; }
command -v unzip >/dev/null || { echo "[!] unzip required"; exit 1; }
unzip -o -q "$BEPZIP" -d "$OUT"
mkdir -p "$OUT/BepInEx/plugins"
cp "$GDIR/$PLUGIN_DLL" "$OUT/BepInEx/plugins/"
echo "[+] Packaged BepInEx + $PLUGIN_DLL"
else
V="vendor/SUWSF-x64"
for f in "$V/SUWSF.asi" "$V/dsound.dll" "$V/LICENSE" "$GDIR/SUWSF.ini"; do
[ -f "$f" ] || { echo "[!] missing $f"; exit 1; }
done
cp "$V/SUWSF.asi" "$V/dsound.dll" "$GDIR/SUWSF.ini" "$OUT/" cp "$V/SUWSF.asi" "$V/dsound.dll" "$GDIR/SUWSF.ini" "$OUT/"
cp "$V/LICENSE" "$OUT/SUWSF-LICENSE.txt" cp "$V/LICENSE" "$OUT/SUWSF-LICENSE.txt"
echo "[+] Packaged SUWSF + patch ini"
fi
cp "$GDIR/README.md" "$OUT/README.md" 2>/dev/null || true cp "$GDIR/README.md" "$OUT/README.md" 2>/dev/null || true
cp THIRD_PARTY.md "$OUT/" 2>/dev/null || true cp THIRD_PARTY.md LICENSE "$OUT/" 2>/dev/null || true
( cd dist && zip -r -q "${GAME}_UltraWide_Fix.zip" "${GAME}_UltraWide_Fix" ) ( cd dist && zip -r -q "${GAME}_UltraWide_Fix.zip" "${GAME}_UltraWide_Fix" )
echo "[+] Built dist/${GAME}_UltraWide_Fix.zip" echo "[+] Built dist/${GAME}_UltraWide_Fix.zip"
( cd dist && sha256sum "${GAME}_UltraWide_Fix.zip" ) ( cd dist && sha256sum "${GAME}_UltraWide_Fix.zip" )
unzip -l "dist/${GAME}_UltraWide_Fix.zip"
+12 -4
View File
@@ -14,22 +14,30 @@ OWNER="${GITEA_OWNER:-ckoch}"
REPO="${GITEA_REPO:-UltraWidePatches}" REPO="${GITEA_REPO:-UltraWidePatches}"
GAME="${GAME:-GundamBreaker4}" GAME="${GAME:-GundamBreaker4}"
TAG="${TAG:-v1.0.0}" TAG="${TAG:-v1.0.0}"
NOTES="${NOTES:-RELEASE_NOTES.md}" NOTES="${NOTES:-games/$GAME/README.md}"
[ -f "$NOTES" ] || NOTES="RELEASE_NOTES.md"
API="$HOST/api/v1" API="$HOST/api/v1"
[ -n "${GITEA_TOKEN:-}" ] || { echo "[!] GITEA_TOKEN is not set. Create one at $HOST/user/settings/applications (scope: write:repository)"; exit 1; } [ -n "${GITEA_TOKEN:-}" ] || { echo "[!] GITEA_TOKEN is not set. Create one at $HOST/user/settings/applications (scope: write:repository)"; exit 1; }
AUTH=(-H "Authorization: token $GITEA_TOKEN") AUTH=(-H "Authorization: token $GITEA_TOKEN")
ZIPNAME="${GAME}_UltraWide_Fix.zip" ZIPNAME="${GAME}_UltraWide_Fix.zip"
# 1. build the artifact # 1. build the artifact -- do NOT swallow output; a failure here used to exit
bash tools/build_release.sh "$GAME" >/dev/null # the whole script silently because stdout went to /dev/null under `set -e`.
if ! bash tools/build_release.sh "$GAME"; then
echo "[!] build_release.sh failed for game '$GAME' (see above)"; exit 1
fi
ZIP="dist/$ZIPNAME" ZIP="dist/$ZIPNAME"
[ -f "$ZIP" ] || { echo "[!] build produced no $ZIP"; exit 1; } [ -f "$ZIP" ] || { echo "[!] build produced no $ZIP"; exit 1; }
echo "[+] Built $ZIP" echo "[+] Built $ZIP"
# 2. push code + tag # 2. push code + tag
git push origin main git push origin main
git push origin "$TAG" 2>/dev/null || echo "[i] tag $TAG already on remote" if ! git rev-parse -q --verify "refs/tags/$TAG" >/dev/null; then
git tag -a "$TAG" -m "$TAG"
echo "[+] Created tag $TAG at $(git rev-parse --short HEAD)"
fi
git push origin "$TAG" 2>&1 | tail -1
# 3. create the release (or reuse if it already exists) # 3. create the release (or reuse if it already exists)
REL_ID=$(curl -sf "${AUTH[@]}" "$API/repos/$OWNER/$REPO/releases/tags/$TAG" 2>/dev/null \ REL_ID=$(curl -sf "${AUTH[@]}" "$API/repos/$OWNER/$REPO/releases/tags/$TAG" 2>/dev/null \