#!/bin/sh # Build and publish the release APK for Kepr Builds. # # Kepr Beta builds use the established release certificate. Validate the produced # APK's package, version, ABI, and signing identity before staging it. set -eu JAVA_HOME="/opt/homebrew/opt/openjdk@17/libexec/openjdk.jdk/Contents/Home" if [ ! -d "$JAVA_HOME" ]; then echo "refusing to publish: required Java 17 runtime not found at $JAVA_HOME" >&2 exit 1 fi export JAVA_HOME ROOT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd) cd "$ROOT_DIR" # Keep the tool-selection and public metadata gates shared with the hermetic # negative-path test; this script owns build orchestration only. # shellcheck source=scripts/kepr-build-helpers.sh . "$ROOT_DIR/scripts/kepr-build-helpers.sh" # Resolve the SDK from the environment first, then the non-secret sdk.dir in # local.properties. Pick the newest *versioned* build-tools directory containing both # tools; build-tools/latest is intentionally never trusted or consulted. SDK_ROOT="${ANDROID_HOME:-${ANDROID_SDK_ROOT:-}}" if [ -z "$SDK_ROOT" ]; then SDK_ROOT=$(sed -n 's/^sdk\.dir=//p' "$ROOT_DIR/local.properties" 2>/dev/null | sed -n '1p') fi if [ -z "$SDK_ROOT" ] || [ ! -d "$SDK_ROOT/build-tools" ]; then echo "refusing to publish: Android SDK build-tools directory not found" >&2 exit 1 fi BUILD_TOOLS_DIR=$(find_stable_build_tools_dir "$SDK_ROOT" || true) if [ -z "$BUILD_TOOLS_DIR" ]; then echo "refusing to publish: no versioned build-tools directory has aapt2" >&2 exit 1 fi AAPT2="$BUILD_TOOLS_DIR/aapt2" ROOT_VERSION=$(read_root_semver "$ROOT_DIR/VERSION" || true) if [ -z "$ROOT_VERSION" ]; then echo "refusing to publish: VERSION is missing or not strict semantic version" >&2 exit 1 fi "$ROOT_DIR/gradlew" --no-configuration-cache :app:assembleRelease case "${KEPR_TARGET:-}" in android-arm64) APK_NAME="app-arm64-v8a-release.apk" EXPECTED_ABI="arm64-v8a" ;; android-x86) APK_NAME="app-x86_64-release.apk" EXPECTED_ABI="x86_64" ;; *) echo "refusing to publish: unsupported KEPR_TARGET '${KEPR_TARGET:-unset}'" >&2 exit 1 ;; esac APK="$ROOT_DIR/app/build/outputs/apk/release/$APK_NAME" METADATA="$ROOT_DIR/app/build/outputs/apk/release/output-metadata.json" if [ ! -f "$APK" ] || [ ! -r "$APK" ]; then echo "refusing to publish: release APK was not produced" >&2 exit 1 fi if [ ! -f "$METADATA" ] || [ ! -r "$METADATA" ]; then echo "refusing to publish: Gradle output metadata was not produced" >&2 exit 1 fi BADGING_FILE=$(mktemp "${TMPDIR:-/tmp}/peach-apk-badging.XXXXXX") cleanup_badging() { [ -e "$BADGING_FILE" ] && trash "$BADGING_FILE" } trap cleanup_badging EXIT HUP INT TERM "$AAPT2" dump badging "$APK" > "$BADGING_FILE" if ! validate_release_metadata \ "$METADATA" \ "$BADGING_FILE" \ "$ROOT_VERSION" \ "com.peachpasswords" \ "$APK_NAME" \ "$EXPECTED_ABI"; then exit 1 fi # Only a fully verified artifact reaches the Kepr staging directory. The # basename includes SemVer + ABI so Kepr's Content-Disposition carries both # to the browser, matching the {version}/{platform} tokens in kepr.build. mkdir -p "$ROOT_DIR/build/kepr" STAGED_NAME="peach-android-${ROOT_VERSION}-${KEPR_TARGET}.apk" cp "$APK" "$ROOT_DIR/build/kepr/$STAGED_NAME" echo "release APK verified and staged: build/kepr/$STAGED_NAME"