Files
MeshChatX/scripts/sign-android-apks.sh

135 lines
4.1 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
usage() {
cat <<'EOF'
Sign Android release APKs (and optionally add SourceStamp).
Required env vars:
SIGNING_KEYSTORE_PATH Path to signing keystore (.jks/.keystore)
SIGNING_KEY_ALIAS Alias of signing key
SIGNING_KEYSTORE_PASSWORD Keystore password
SIGNING_KEY_PASSWORD Key password (defaults to SIGNING_KEYSTORE_PASSWORD)
Optional env vars:
ANDROID_HOME Android SDK root (or ANDROID_SDK_ROOT)
APK_GLOB Glob for unsigned APKs
(default: android/app/build/outputs/apk/*/release/*-unsigned.apk)
ENABLE_SOURCESTAMP true/false (default: false)
SOURCESTAMP_KEYSTORE_PATH Path to SourceStamp keystore
SOURCESTAMP_KEY_ALIAS Alias in SourceStamp keystore
SOURCESTAMP_KEYSTORE_PASSWORD SourceStamp keystore password
SOURCESTAMP_KEY_PASSWORD SourceStamp key password
Output:
Creates sibling files for each unsigned APK:
*-aligned.apk
*-signed.apk
Examples:
SIGNING_KEYSTORE_PATH=android/keystore/meshchatx-release.jks \
SIGNING_KEY_ALIAS=meshchatx-release \
SIGNING_KEYSTORE_PASSWORD='...' \
SIGNING_KEY_PASSWORD='...' \
bash scripts/sign-android-apks.sh
SIGNING_KEYSTORE_PATH=android/keystore/meshchatx-release.jks \
SIGNING_KEY_ALIAS=meshchatx-release \
SIGNING_KEYSTORE_PASSWORD='...' \
SIGNING_KEY_PASSWORD='...' \
ENABLE_SOURCESTAMP=true \
SOURCESTAMP_KEYSTORE_PATH=android/keystore/meshchatx-stamp.jks \
SOURCESTAMP_KEY_ALIAS=meshchatx-stamp \
SOURCESTAMP_KEYSTORE_PASSWORD='...' \
SOURCESTAMP_KEY_PASSWORD='...' \
bash scripts/sign-android-apks.sh
EOF
}
if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
usage
exit 0
fi
require_env() {
local name="$1"
if [[ -z "${!name:-}" ]]; then
echo "Missing required env var: ${name}" >&2
exit 1
fi
}
require_env SIGNING_KEYSTORE_PATH
require_env SIGNING_KEY_ALIAS
require_env SIGNING_KEYSTORE_PASSWORD
SIGNING_KEY_PASSWORD="${SIGNING_KEY_PASSWORD:-${SIGNING_KEYSTORE_PASSWORD}}"
ANDROID_HOME="${ANDROID_HOME:-${ANDROID_SDK_ROOT:-}}"
if [[ -z "${ANDROID_HOME}" ]]; then
echo "Set ANDROID_HOME (or ANDROID_SDK_ROOT) to your Android SDK path." >&2
exit 1
fi
BT_DIR="$(ls -d "${ANDROID_HOME}"/build-tools/* 2>/dev/null | sort -V | tail -n 1)"
if [[ -z "${BT_DIR}" ]]; then
echo "No Android build-tools found under ${ANDROID_HOME}/build-tools." >&2
exit 1
fi
if [[ ! -x "${BT_DIR}/zipalign" || ! -x "${BT_DIR}/apksigner" ]]; then
echo "Missing zipalign/apksigner in ${BT_DIR}. Install build-tools via sdkmanager." >&2
exit 1
fi
APK_GLOB="${APK_GLOB:-android/app/build/outputs/apk/*/release/*-unsigned.apk}"
shopt -s nullglob
APKS=( ${APK_GLOB} )
shopt -u nullglob
if [[ ${#APKS[@]} -eq 0 ]]; then
echo "No unsigned APKs matched: ${APK_GLOB}" >&2
exit 1
fi
ENABLE_SOURCESTAMP="${ENABLE_SOURCESTAMP:-false}"
if [[ "${ENABLE_SOURCESTAMP}" == "true" ]]; then
require_env SOURCESTAMP_KEYSTORE_PATH
require_env SOURCESTAMP_KEY_ALIAS
require_env SOURCESTAMP_KEYSTORE_PASSWORD
SOURCESTAMP_KEY_PASSWORD="${SOURCESTAMP_KEY_PASSWORD:-${SOURCESTAMP_KEYSTORE_PASSWORD}}"
fi
for apk in "${APKS[@]}"; do
base="${apk%-unsigned.apk}"
aligned="${base}-aligned.apk"
signed="${base}-signed.apk"
echo "Aligning ${apk}"
"${BT_DIR}/zipalign" -p -f 4 "${apk}" "${aligned}"
sign_args=(
sign
--ks "${SIGNING_KEYSTORE_PATH}"
--ks-key-alias "${SIGNING_KEY_ALIAS}"
--ks-pass "pass:${SIGNING_KEYSTORE_PASSWORD}"
--key-pass "pass:${SIGNING_KEY_PASSWORD}"
--out "${signed}"
)
if [[ "${ENABLE_SOURCESTAMP}" == "true" ]]; then
sign_args+=(
--stamp-signer
--stamp-ks "${SOURCESTAMP_KEYSTORE_PATH}"
--stamp-key-alias "${SOURCESTAMP_KEY_ALIAS}"
--stamp-ks-pass "pass:${SOURCESTAMP_KEYSTORE_PASSWORD}"
--stamp-key-pass "pass:${SOURCESTAMP_KEY_PASSWORD}"
)
fi
echo "Signing ${aligned}"
"${BT_DIR}/apksigner" "${sign_args[@]}" "${aligned}"
echo "Verifying ${signed}"
"${BT_DIR}/apksigner" verify --verbose --print-certs "${signed}"
done
echo "Done."