From ad7c63ff4f2f5f83c26ead2a8bf9445bf28b79cc Mon Sep 17 00:00:00 2001 From: Paul Hitt Date: Sat, 5 Sep 2026 11:38:31 -0400 Subject: [PATCH] An APK no longer ships without a word about what changed in it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Publishing was three steps done by hand, and only two of them left a trace. The manifest and the APK could go out with nothing anywhere saying what was in the build — which is how 0.8 shipped with notes and 0.9 shipped with none. The gate goes on the manifest rather than on a checklist, because the manifest is the step that cannot be skipped: it is what the in-app updater reads, so an APK published without it offers nobody an update. A checklist item is skipped on exactly the busy evening the notes matter most. 🔴 It matches on the `versionName` read out of the APK, never a number typed here — the same reason this script already reads the version rather than accepting one. The two cannot disagree. The check itself lives in the relay repository (Scripts/covers-android.py), because that is what serves the /releases page and defines the format. Parsing the JSON here would leave a second copy of the schema to drift out of step with the first, and a drifted gate is a gate that passes everything. ⚠️ FN_SKIP_RELEASE_NOTES=1 still publishes, and says so loudly on stderr — a skipped gate that printed nothing would be a gate nobody remembered turning off. A missing relay checkout is a refusal, not a pass, and names FN_RELAY_DIR. Proven on a real APK in all four states: covered (manifest written, valid JSON), uncovered (refused, and stdout stays EMPTY so no half-written manifest lands), skipped, and no checkout. Every message goes to stderr, because this script's stdout is the manifest itself. --- scripts/release-manifest.sh | 65 +++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/scripts/release-manifest.sh b/scripts/release-manifest.sh index 0a624db..5eca96f 100755 --- a/scripts/release-manifest.sh +++ b/scripts/release-manifest.sh @@ -26,6 +26,71 @@ code="$(sed -n "s/.*versionCode='\([0-9]*\)'.*/\1/p" <<<"$badging" | head -1)" name="$(sed -n "s/.*versionName='\([^']*\)'.*/\1/p" <<<"$badging" | head -1)" [ -n "$code" ] && [ -n "$name" ] || { echo "could not read version from $apk" >&2; exit 1; } +# --------------------------------------------------------------------------- +# 🔴 **A build does not ship without its release notes.** +# +# The gate lives here, on the manifest, because the manifest is the step that +# cannot be skipped — it is what the in-app updater reads, so an APK published +# without it offers nobody an update. A reminder in a checklist would be +# skipped on exactly the busy evening the notes matter most. +# +# ⚠️ It matches on `versionName` read out of the APK above, never on a number +# typed here, for the same reason the manifest does: the two cannot disagree. +# +# The changelog lives in the relay repository because that is what serves the +# page, and the check lives THERE too — see Scripts/covers-android.py. Parsing +# the JSON here would leave a second copy of the schema to drift. +if [ "${FN_SKIP_RELEASE_NOTES:-}" = "1" ]; then + # Loud, and on stderr: a skipped gate that printed nothing would be a gate + # nobody remembered turning off. + echo "⚠️ FN_SKIP_RELEASE_NOTES=1 — writing a manifest for $name with no" >&2 + echo " release notes. Nothing on /releases will mention this build." >&2 +else + relay_dir="${FN_RELAY_DIR:-$(cd "$(dirname "$0")/../.." && pwd)/flamenet-relay}" + checker="$relay_dir/Scripts/covers-android.py" + if [ ! -f "$checker" ]; then + cat >&2 <&2 <