#!/usr/bin/env bash # # release-app.sh — one-command release of the BUNDLED Capacitor app. # # Does the whole cycle: # 1. bump the version (android/app/build.gradle + android/update-files/version.json) # 2. npm run build:app (rebuild the mobile-only static SPA → .output/public) # 3. npm run cap:sync:app (copy the bundle into android/) # 4. gradle assembleDebug (build the APK) + stage it into android/update-files/ # 5. scripts/upload-mobile-update.sh (publish APK + version.json so devices get the update) # # Usage: # scripts/release-app.sh # auto-bump the patch (e.g. 1.0.2 -> 1.0.3) # scripts/release-app.sh 1.1.0 # set an explicit versionName # scripts/release-app.sh --no-upload # build + stage only, don't publish # RELEASE_NOTES="..." scripts/release-app.sh # skip the notes prompt # # versionCode is always auto-incremented by 1. versionName must strictly increase or the in-app # updater won't offer the release. # set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" cd "$REPO_ROOT" GRADLE="android/app/build.gradle" VERSION_JSON="android/update-files/version.json" APK_BUILT="android/app/build/outputs/apk/debug/app-debug.apk" APK_STAGED="android/update-files/logship-mobile.apk" bold() { printf '\033[1m%s\033[0m\n' "$*"; } err() { printf '\033[31mERROR:\033[0m %s\n' "$*" >&2; } ok() { printf '\033[32m✔\033[0m %s\n' "$*"; } # -------------------------------------------------------------------------- # Args # -------------------------------------------------------------------------- NO_UPLOAD=0 NEW_NAME_ARG="" for a in "$@"; do case "$a" in --no-upload) NO_UPLOAD=1 ;; -h|--help) sed -n '3,22p' "$0" | sed 's/^# \{0,1\}//'; exit 0 ;; --*) err "unknown option: $a"; exit 1 ;; *) NEW_NAME_ARG="$a" ;; esac done # -------------------------------------------------------------------------- # Current version # -------------------------------------------------------------------------- CUR_CODE="$(grep -E 'versionCode +[0-9]+' "$GRADLE" | head -1 | grep -oE '[0-9]+' | head -1)" CUR_NAME="$(grep -E 'versionName +"[^"]*"' "$GRADLE" | head -1 | sed -E 's/.*versionName +"([^"]*)".*/\1/')" if [ -z "$CUR_CODE" ] || [ -z "$CUR_NAME" ]; then err "could not read current versionCode/versionName from $GRADLE"; exit 1 fi NEW_CODE=$(( CUR_CODE + 1 )) if [ -n "$NEW_NAME_ARG" ]; then NEW_NAME="$NEW_NAME_ARG" else # auto-increment the last dotted numeric segment (bash 3.2 safe — no negative array index) IFS='.' read -r -a PARTS <<< "$CUR_NAME" last=$(( ${#PARTS[@]} - 1 )) if ! [[ "${PARTS[$last]}" =~ ^[0-9]+$ ]]; then err "versionName '$CUR_NAME' doesn't end in a number — pass an explicit version: scripts/release-app.sh "; exit 1 fi PARTS[$last]=$(( ${PARTS[$last]} + 1 )) NEW_NAME="$(IFS='.'; echo "${PARTS[*]}")" fi echo bold "Release $CUR_NAME (code $CUR_CODE) -> $NEW_NAME (code $NEW_CODE)" # -------------------------------------------------------------------------- # Release notes # -------------------------------------------------------------------------- RELEASE_NOTES="${RELEASE_NOTES:-}" if [ -z "$RELEASE_NOTES" ]; then read -rp "Release notes (DE) [Verbesserungen und Fehlerbehebungen.]: " RELEASE_NOTES RELEASE_NOTES="${RELEASE_NOTES:-Verbesserungen und Fehlerbehebungen.}" fi read -rp "Build${NO_UPLOAD:+ (no upload)} this release? [y/N] " go case "$go" in y|Y) ;; *) echo "Aborted."; exit 0;; esac # -------------------------------------------------------------------------- # 1. Bump versions # -------------------------------------------------------------------------- sed -E "s/versionCode +[0-9]+/versionCode $NEW_CODE/; s/versionName +\"[^\"]*\"/versionName \"$NEW_NAME\"/" \ "$GRADLE" > "$GRADLE.tmp" && mv "$GRADLE.tmp" "$GRADLE" ok "build.gradle → versionName $NEW_NAME / versionCode $NEW_CODE" REL_DATE="$(date +%Y-%m-%d)" MIN_REQ="$(grep -oE '"minRequiredVersion"[^,}]*' "$VERSION_JSON" 2>/dev/null | sed -E 's/.*: *"([^"]*)".*/\1/')" MIN_REQ="${MIN_REQ:-1.0.0}" # JSON-escape the notes (backslash + double-quote) ESC_NOTES="$(printf '%s' "$RELEASE_NOTES" | sed 's/\\/\\\\/g; s/"/\\"/g')" cat > "$VERSION_JSON" </dev/null | sort -V | tail -1 || true)" if [ -n "$AAPT" ]; then APK_VER="$("$AAPT" dump badging "$APK_STAGED" 2>/dev/null | grep -oE "versionCode='[0-9]+' versionName='[^']+'")" echo " APK: $APK_VER" fi # -------------------------------------------------------------------------- # 5. Publish # -------------------------------------------------------------------------- if [ "$NO_UPLOAD" = "1" ]; then echo; ok "Build complete (upload skipped: --no-upload)." echo " Publish later with: scripts/upload-mobile-update.sh" else echo; bold "Publishing…" "$SCRIPT_DIR/upload-mobile-update.sh" fi echo ok "Done — released $NEW_NAME (code $NEW_CODE)." echo " ↪ Commit the version bump: git add $GRADLE $VERSION_JSON && git commit -m \"release app $NEW_NAME\""