#!/usr/bin/env bash # The app's release job (#7), in OxygenFlow's Android image with no network: # a signed release APK of the version in gradle.properties, checked with # apksigner, in dist/ beside its SHA256SUMS, for a release on oxygenhub.io. # # The key comes from the job's secrets, mounted as files and never in the # environment: android-keystore (the PKCS12 keystore, base64) and # android-keystore-password; and firebase-config (google-services.json, for # alerts). Locally, give the same files: # KEYSTORE_B64=path PASSWORD_FILE=path [FIREBASE_CONFIG=path] scripts/release.sh set -euo pipefail cd "$(dirname "$0")/.." b64=${KEYSTORE_B64:-/run/secrets/android-keystore} password=${PASSWORD_FILE:-/run/secrets/android-keystore-password} # Firebase's client settings for alerts (#16): google-services.json, the # repository's firebase-config secret; without it the release takes no alerts. firebase=${FIREBASE_CONFIG:-/run/secrets/firebase-config} for f in "$b64" "$password"; do [ -s "$f" ] || { echo "release: no $f: the job needs the android-keystore secrets" >&2; exit 1; } done version=$(sed -n 's/^oxygenhub\.version=//p' gradle.properties) [ -n "$version" ] || { echo "release: no oxygenhub.version in gradle.properties" >&2; exit 1; } # As ci.sh: the image's JDKs for Gradle's daemon, never a download. jdks=$( (ls -d /opt/gradle-home/jdks/*/ 2>/dev/null || true) | sed 's:/$::' | paste -sd, -) if [ -n "$jdks" ] && [ -n "${GRADLE_USER_HOME:-}" ]; then mkdir -p "$GRADLE_USER_HOME" { echo "org.gradle.java.installations.paths=$jdks" echo "org.gradle.java.installations.auto-download=false" } >> "$GRADLE_USER_HOME/gradle.properties" fi # The keystore, decoded where only this job can read it, and gone after. keys=$(mktemp -d) trap 'rm -rf "$keys"' EXIT chmod 700 "$keys" base64 -d "$b64" > "$keys/release.p12" export OXYGENHUB_KEYSTORE="$keys/release.p12" OXYGENHUB_KEYSTORE_PASSWORD_FILE="$password" if [ -s "$firebase" ]; then cp "$firebase" app/google-services.json trap 'rm -rf "$keys" app/google-services.json' EXIT else echo "release: no $firebase: this release takes no alerts" >&2 fi gradle=$(command -v gradle || echo ./gradlew) "$gradle" --offline --no-daemon :app:assembleRelease apk=app/build/outputs/apk/release/app-release.apk [ -f "$apk" ] || { echo "release: no $apk (was it signed? an unsigned build is app-release-unsigned.apk)" >&2; exit 1; } sdk=${ANDROID_HOME:-${ANDROID_SDK_ROOT:-}} apksigner=$(ls -d "$sdk"/build-tools/*/apksigner 2>/dev/null | sort -V | tail -1) "$apksigner" verify --print-certs "$apk" | grep -E '^Signer #1 certificate (DN|SHA-256)' # Kept as an artifact by a fixed name; SHA256SUMS gives the name it takes # in a release, with the version (as OxygenHub's and OxygenFlow's dist do). rm -rf dist mkdir -p dist cp "$apk" dist/oxygenhub-android-universal.apk echo "$(sha256sum < dist/oxygenhub-android-universal.apk | cut -d' ' -f1) oxygenhub-android-$version-universal.apk" > dist/SHA256SUMS echo "release: oxygenhub-android-$version-universal.apk"