#!/usr/bin/env bash # Write the update manifest for a built APK. # # 🔴 The version in the manifest is read back OUT of the APK, never typed. A # manifest that claims a version the APK is not is worse than no manifest: it # either offers an update that installs as the same build (and so appears to do # nothing), or fails to offer one that exists. Reading it from the artifact is # what makes the two incapable of disagreeing. # # Usage: scripts/release-manifest.sh [notes] > android-latest.json set -euo pipefail apk="${1:?usage: release-manifest.sh [notes]}" notes="${2:-}" [ -f "$apk" ] || { echo "no such APK: $apk" >&2; exit 1; } # aapt2 ships with the build tools; find the newest one rather than pinning a # version that will be wrong on the next machine. sdk="${ANDROID_HOME:-$HOME/Library/Android/sdk}" aapt2="$(find "$sdk/build-tools" -maxdepth 2 -name aapt2 -type f 2>/dev/null | sort -V | tail -1)" [ -n "$aapt2" ] || { echo "aapt2 not found under $sdk/build-tools" >&2; exit 1; } badging="$("$aapt2" dump badging "$apk")" 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; } sha="$(shasum -a 256 "$apk" | cut -d' ' -f1)" # ⚠️ No `url` field, deliberately. The client builds the download URL from the # relay it is signed in to and ignores anything the manifest says about where # the APK lives — a relay that could name the host could hand its users a # different app. Adding one here would be dead weight at best and a trap for # the next person to implement a client at worst. cat <