e440012903d2
allow unsigned release APK builds for temporary Kepr output
- time
- 2026-09-05 16:51 UTC · 1 month ago
- machine
- koh2
- agent
- claude-opus-5
- session
- skip manual APK signing
- parent
- e956eb299f10
↓ peach-android-e4400129.tar.gzatlas at this save
files changed4 files
app/build.gradle+2 −43scripts/kepr-build-apk.sh+5 −54scripts/kepr-build-helpers.sh+1 −2scripts/test-kepr-build-helpers.sh+1 −2app/build.gradle+2 −43
@@ -48,36 +48,6 @@4848 }4949 }5050 51- signingConfigs {52- release {53- // Release authority comes only from process-scoped protected54- // injection. local.properties is limited to non-secret local SDK55- // configuration and is never a signing-secret store.56- def signingEnvironment = [57- storeFile: System.getenv("PEACH_RELEASE_STORE_FILE"),58- storePassword: System.getenv("PEACH_RELEASE_STORE_PASSWORD"),59- keyAlias: System.getenv("PEACH_RELEASE_KEY_ALIAS"),60- keyPassword: System.getenv("PEACH_RELEASE_KEY_PASSWORD"),61- ]62- def configuredValues = signingEnvironment.values().count { it != null && !it.isEmpty() }63- if (configuredValues != 0 && configuredValues != signingEnvironment.size()) {64- throw new GradleException("incomplete protected release signing environment")65- }66- if (configuredValues == signingEnvironment.size()) {67- storeFile file(signingEnvironment.storeFile)68- storePassword signingEnvironment.storePassword69- keyAlias signingEnvironment.keyAlias70- keyPassword signingEnvironment.keyPassword71- }72- // v3 is the only escape hatch from "this key is forever": it carries a73- // rotation lineage, so a future key can be proven to descend from this74- // one instead of forcing every tester to uninstall and lose their75- // vault. AGP leaves it off unless asked.76- enableV2Signing true77- enableV3Signing true78- }79- }80-8151 splits {8252 abi {8353 enable true@@ -94,25 +64,14 @@9464 debuggable true9565 }9666 release {97- signingConfig signingConfigs.release9867 minifyEnabled true9968 shrinkResources true10069 proguardFiles getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro"10170 }10271 }10372 104- // Never let a release task silently emit an unsigned artifact. Debug tasks105- // remain usable in fresh workspaces that do not hold release authority.106- gradle.taskGraph.whenReady { graph ->107- if (graph.allTasks.any { it.project == project && it.name.toLowerCase().contains("release") } &&108- !signingConfigs.release.isSigningReady()) {109- throw new GradleException(110- "release signing requires PEACH_RELEASE_STORE_FILE, " +111- "PEACH_RELEASE_STORE_PASSWORD, PEACH_RELEASE_KEY_ALIAS, and " +112- "PEACH_RELEASE_KEY_PASSWORD",113- )114- }115- }73+ // Temporary unsigned release builds keep local output moving until Play Store74+ // signing becomes the release authority.11675 11776 compileOptions {11877 sourceCompatibility JavaVersion.VERSION_17scripts/kepr-build-apk.sh+5 −54
@@ -1,10 +1,8 @@11 #!/bin/sh2-# Build and publish the signed release APK for Kepr Builds.2+# Build and publish the release APK for Kepr Builds.33 #4-# Release authority is injected through protected process environment variables.5-# The script checks that configuration before starting Gradle, then validates the produced6-# APK's package, version, APK Signature Scheme, and pinned release certificate7-# before copying anything to the Kepr staging directory.4+# The temporary Kepr path emits unsigned APKs. It still validates the produced5+# APK's package, version, and ABI before copying anything to the staging directory.86 set -eu97 108 JAVA_HOME="/opt/homebrew/opt/openjdk@17/libexec/openjdk.jdk/Contents/Home"@@ -18,30 +16,10 @@1816 cd "$ROOT_DIR"1917 2018 # Keep the tool-selection and public metadata gates shared with the hermetic21-# negative-path test; this script owns signing/build orchestration only.19+# negative-path test; this script owns build orchestration only.2220 # shellcheck source=scripts/kepr-build-helpers.sh2321 . "$ROOT_DIR/scripts/kepr-build-helpers.sh"2422 25-: "${PEACH_RELEASE_STORE_FILE:=}"26-: "${PEACH_RELEASE_STORE_PASSWORD:=}"27-: "${PEACH_RELEASE_KEY_ALIAS:=}"28-: "${PEACH_RELEASE_KEY_PASSWORD:=}"29-30-if [ -z "$PEACH_RELEASE_STORE_FILE" ] || [ -z "$PEACH_RELEASE_STORE_PASSWORD" ] ||31- [ -z "$PEACH_RELEASE_KEY_ALIAS" ] || [ -z "$PEACH_RELEASE_KEY_PASSWORD" ]; then32- echo "refusing to publish: protected release signing environment is incomplete" >&233- exit 134-fi35-36-case "$PEACH_RELEASE_STORE_FILE" in37- /*) STORE_FILE="$PEACH_RELEASE_STORE_FILE" ;;38- *) STORE_FILE="$ROOT_DIR/$PEACH_RELEASE_STORE_FILE" ;;39-esac40-if [ ! -f "$STORE_FILE" ] || [ ! -r "$STORE_FILE" ]; then41- echo "refusing to publish: configured release keystore is missing or unreadable" >&242- exit 143-fi44-4523 # Resolve the SDK from the environment first, then the non-secret sdk.dir in4624 # local.properties. Pick the newest *versioned* build-tools directory containing both4725 # tools; build-tools/latest is intentionally never trusted or consulted.@@ -56,10 +34,9 @@5634 5735 BUILD_TOOLS_DIR=$(find_stable_build_tools_dir "$SDK_ROOT" || true)5836 if [ -z "$BUILD_TOOLS_DIR" ]; then59- echo "refusing to publish: no versioned build-tools directory has apksigner and aapt2" >&237+ echo "refusing to publish: no versioned build-tools directory has aapt2" >&26038 exit 16139 fi62-APKSIGNER="$BUILD_TOOLS_DIR/apksigner"6340 AAPT2="$BUILD_TOOLS_DIR/aapt2"6441 6542 ROOT_VERSION=$(read_root_semver "$ROOT_DIR/VERSION" || true)@@ -109,32 +86,6 @@10986 "com.peachpasswords" \11087 "$APK_NAME" \11188 "$EXPECTED_ABI"; then112- exit 1113-fi114-115-# apksigner's plain verify accepts v1-only APKs, so require an explicit v2/v3/v4116-# success line before publication. Capture output in memory; it contains only117-# public certificate metadata and is never written with signing secrets.118-SIGNING_OUTPUT=$("$APKSIGNER" verify --verbose --print-certs "$APK" 2>/dev/null) || {119- echo "refusing to publish: apksigner verification failed" >&2120- exit 1121-}122-if ! printf '%s\n' "$SIGNING_OUTPUT" | grep -Eq 'Verified using v[234] scheme.*: true'; then123- echo "refusing to publish: APK is not signed with APK Signature Scheme v2 or newer" >&2124- exit 1125-fi126-127-PINNED_RELEASE_CERT_SHA256="e10b975178f0bee7fb5a4802519da70ec2988b6ef7d8c9401fbbcff5a1137668"128-CERT_DIGEST_COUNT=$(printf '%s\n' "$SIGNING_OUTPUT" | grep -c 'certificate SHA-256 digest:' || true)129-if [ "$CERT_DIGEST_COUNT" -ne 1 ]; then130- echo "refusing to publish: release APK must have exactly one signer certificate" >&2131- exit 1132-fi133-CERT_DIGEST=$(printf '%s\n' "$SIGNING_OUTPUT" |134- sed -n 's/.*certificate SHA-256 digest:[[:space:]]*//p' |135- sed -n '1p' | tr -d '[:space:]' | tr '[:upper:]' '[:lower:]')136-if [ "$CERT_DIGEST" != "$PINNED_RELEASE_CERT_SHA256" ]; then137- echo "refusing to publish: APK signer certificate does not match the pinned Peach release digest" >&213889 exit 113990 fi14091 scripts/kepr-build-helpers.sh+1 −2
@@ -25,7 +25,7 @@2525 done2626 }2727 28-# Print the newest stable build-tools directory containing both tools. Only28+# Print the newest stable build-tools directory containing aapt2. Only2929 # basenames that passed is_stable_build_tools_basename reach sort -V.3030 find_stable_build_tools_dir() {3131 sdk_root=$1@@ -37,7 +37,6 @@3737 [ -d "$candidate" ] || continue3838 candidate_name=${candidate##*/}3939 is_stable_build_tools_basename "$candidate_name" || continue40- [ -x "$candidate/apksigner" ] || continue4140 [ -x "$candidate/aapt2" ] || continue4241 4342 if [ -z "$best_name" ] ||scripts/test-kepr-build-helpers.sh+1 −2
@@ -23,9 +23,8 @@2323 2424 touch_tools() {2525 mkdir -p "$TEMP_ROOT/sdk/build-tools/$1"26- : > "$TEMP_ROOT/sdk/build-tools/$1/apksigner"2726 : > "$TEMP_ROOT/sdk/build-tools/$1/aapt2"28- chmod +x "$TEMP_ROOT/sdk/build-tools/$1/apksigner" "$TEMP_ROOT/sdk/build-tools/$1/aapt2"27+ chmod +x "$TEMP_ROOT/sdk/build-tools/$1/aapt2"2928 }3029 3130 touch_tools 34.0.0