12345678set -eu910JAVA_HOME="${JAVA_HOME:-/Applications/Android Studio.app/Contents/jbr/Contents/Home}"11export JAVA_HOME1213ROOT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)14cd "$ROOT_DIR"1516171819. "$ROOT_DIR/scripts/kepr-build-helpers.sh"2021PROPERTIES_FILE="$ROOT_DIR/local.properties"22if [ ! -r "$PROPERTIES_FILE" ]; then23 echo "refusing to publish: local.properties is missing or unreadable" >&224 exit 125fi2627property() {28 29 30 sed -n "s/^$1=//p" "$PROPERTIES_FILE" | sed -n '1p'31}3233STORE_FILE_PROPERTY=$(property peachStoreFile)34STORE_PASSWORD=$(property peachStorePassword)35KEY_ALIAS=$(property peachKeyAlias)36KEY_PASSWORD=$(property peachKeyPassword)3738if [ -z "$STORE_FILE_PROPERTY" ] || [ -z "$STORE_PASSWORD" ] ||39 [ -z "$KEY_ALIAS" ] || [ -z "$KEY_PASSWORD" ]; then40 echo "refusing to publish: incomplete release signing configuration" >&241 exit 142fi4344case "$STORE_FILE_PROPERTY" in45 /*) STORE_FILE="$STORE_FILE_PROPERTY" ;;46 *) STORE_FILE="$ROOT_DIR/$STORE_FILE_PROPERTY" ;;47esac48if [ ! -f "$STORE_FILE" ] || [ ! -r "$STORE_FILE" ]; then49 echo "refusing to publish: configured release keystore is missing or unreadable" >&250 exit 151fi5253545556SDK_ROOT="${ANDROID_HOME:-${ANDROID_SDK_ROOT:-}}"57if [ -z "$SDK_ROOT" ]; then58 SDK_ROOT=$(property sdk.dir)59fi60if [ -z "$SDK_ROOT" ] || [ ! -d "$SDK_ROOT/build-tools" ]; then61 echo "refusing to publish: Android SDK build-tools directory not found" >&262 exit 163fi6465BUILD_TOOLS_DIR=$(find_stable_build_tools_dir "$SDK_ROOT" || true)66if [ -z "$BUILD_TOOLS_DIR" ]; then67 echo "refusing to publish: no versioned build-tools directory has apksigner and aapt2" >&268 exit 169fi70APKSIGNER="$BUILD_TOOLS_DIR/apksigner"71AAPT2="$BUILD_TOOLS_DIR/aapt2"7273ROOT_VERSION=$(read_root_semver "$ROOT_DIR/VERSION" || true)74if [ -z "$ROOT_VERSION" ]; then75 echo "refusing to publish: VERSION is missing or not strict semantic version" >&276 exit 177fi7879"$ROOT_DIR/gradlew" --no-configuration-cache :app:assembleRelease8081APK="$ROOT_DIR/app/build/outputs/apk/release/app-release.apk"82METADATA="$ROOT_DIR/app/build/outputs/apk/release/output-metadata.json"83if [ ! -f "$APK" ] || [ ! -r "$APK" ]; then84 echo "refusing to publish: release APK was not produced" >&285 exit 186fi87if [ ! -f "$METADATA" ] || [ ! -r "$METADATA" ]; then88 echo "refusing to publish: Gradle output metadata was not produced" >&289 exit 190fi9192BADGING_FILE=$(mktemp "${TMPDIR:-/tmp}/peach-apk-badging.XXXXXX")93cleanup_badging() {94 [ -e "$BADGING_FILE" ] && trash "$BADGING_FILE"95}96trap cleanup_badging EXIT HUP INT TERM97"$AAPT2" dump badging "$APK" > "$BADGING_FILE"98if ! validate_release_metadata \99 "$METADATA" \100 "$BADGING_FILE" \101 "$ROOT_VERSION" \102 "com.peachpasswords"; then103 exit 1104fi105106107108109SIGNING_OUTPUT=$("$APKSIGNER" verify --verbose --print-certs "$APK" 2>/dev/null) || {110 echo "refusing to publish: apksigner verification failed" >&2111 exit 1112}113if ! printf '%s\n' "$SIGNING_OUTPUT" | grep -Eq 'Verified using v[234] scheme.*: true'; then114 echo "refusing to publish: APK is not signed with APK Signature Scheme v2 or newer" >&2115 exit 1116fi117118PINNED_RELEASE_CERT_SHA256="e10b975178f0bee7fb5a4802519da70ec2988b6ef7d8c9401fbbcff5a1137668"119CERT_DIGEST_COUNT=$(printf '%s\n' "$SIGNING_OUTPUT" | grep -c 'certificate SHA-256 digest:' || true)120if [ "$CERT_DIGEST_COUNT" -ne 1 ]; then121 echo "refusing to publish: release APK must have exactly one signer certificate" >&2122 exit 1123fi124CERT_DIGEST=$(printf '%s\n' "$SIGNING_OUTPUT" |125 sed -n 's/.*certificate SHA-256 digest:[[:space:]]*//p' |126 sed -n '1p' | tr -d '[:space:]' | tr '[:upper:]' '[:lower:]')127if [ "$CERT_DIGEST" != "$PINNED_RELEASE_CERT_SHA256" ]; then128 echo "refusing to publish: APK signer certificate does not match the pinned Peach release digest" >&2129 exit 1130fi131132133mkdir -p "$ROOT_DIR/build/kepr"134cp "$APK" "$ROOT_DIR/build/kepr/peach-android.apk"135echo "release APK verified and staged: build/kepr/peach-android.apk"