#!/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. publish — MOBILE_PUBLISH is a comma list of targets, DEFAULT "erp": # erp scripts/publish-mobile-update.sh → ERP server-side channel (app.logship.de, # data/mobile-releases/, no ERP deploy needed) — the channel all devices use # landing scripts/stage-mobile-update.sh → ../logship/logyou-landing public/logship # (legacy channel, only for update checks without a session; commit + push = deploy) # sftp scripts/upload-mobile-update.sh → SFTP web root (Blut24) # # Interactive: run without arguments and it asks for everything — version name (Enter = auto # bump), release notes, publish target (Enter = ERP only) and a final confirmation. Every answer # can be pre-set to run it non-interactively: # # Usage: # scripts/release-app.sh # interactive (defaults: auto-bump, ERP channel only) # scripts/release-app.sh 1.1.0 # explicit versionName (skips the version prompt) # scripts/release-app.sh --no-upload # build + stage only, don't publish # scripts/release-app.sh --push # when "landing" is a target: also git push the website repo # scripts/release-app.sh --yes # no prompts at all (uses defaults / env values) # RELEASE_NOTES="..." scripts/release-app.sh # skip the notes prompt # MOBILE_PUBLISH=erp,landing scripts/release-app.sh # skip the target 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 PUSH_SITE=0 ASSUME_YES=0 NEW_NAME_ARG="" for a in "$@"; do case "$a" in --no-upload) NO_UPLOAD=1 ;; --push) PUSH_SITE=1 ;; --yes|-y) ASSUME_YES=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 )) # 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 )) AUTO_NAME="" if [[ "${PARTS[$last]}" =~ ^[0-9]+$ ]]; then PARTS[$last]=$(( ${PARTS[$last]} + 1 )) AUTO_NAME="$(IFS='.'; echo "${PARTS[*]}")" fi echo bold "Current app version: $CUR_NAME (code $CUR_CODE)" if [ -n "$NEW_NAME_ARG" ]; then NEW_NAME="$NEW_NAME_ARG" elif [ "$ASSUME_YES" = "1" ]; then NEW_NAME="$AUTO_NAME" else read -rp "New versionName [${AUTO_NAME:-required}]: " NEW_NAME NEW_NAME="${NEW_NAME:-$AUTO_NAME}" fi if [ -z "$NEW_NAME" ]; then err "versionName '$CUR_NAME' doesn't end in a number — enter an explicit version"; exit 1; fi if ! [[ "$NEW_NAME" =~ ^[0-9]+(\.[0-9]+){1,3}$ ]]; then err "invalid versionName '$NEW_NAME' (expected e.g. 1.0.42)"; exit 1; fi if [ "$NEW_NAME" = "$CUR_NAME" ]; then err "versionName must increase (still $CUR_NAME) — the in-app updater compares versionName"; exit 1; fi bold "Release $CUR_NAME (code $CUR_CODE) -> $NEW_NAME (code $NEW_CODE)" # -------------------------------------------------------------------------- # Release notes # -------------------------------------------------------------------------- RELEASE_NOTES="${RELEASE_NOTES:-}" if [ -z "$RELEASE_NOTES" ] && [ "$ASSUME_YES" != "1" ]; then read -rp "Release notes (DE) [Verbesserungen und Fehlerbehebungen.]: " RELEASE_NOTES fi RELEASE_NOTES="${RELEASE_NOTES:-Verbesserungen und Fehlerbehebungen.}" # -------------------------------------------------------------------------- # Publish target (default: ERP channel only) # -------------------------------------------------------------------------- MOBILE_PUBLISH="${MOBILE_PUBLISH:-}" if [ "$NO_UPLOAD" = "1" ]; then MOBILE_PUBLISH="" elif [ -z "$MOBILE_PUBLISH" ]; then if [ "$ASSUME_YES" = "1" ]; then MOBILE_PUBLISH="erp" else echo echo "Publish to:" echo " 1) ERP channel only (app.logship.de — what all devices use) [default]" echo " 2) ERP channel + logyou.de website repo (legacy channel)" echo " 3) SFTP web root (Blut24 / upload-mobile-update.sh)" echo " 4) nothing — build + stage only" read -rp "Choice [1]: " choice case "${choice:-1}" in 1) MOBILE_PUBLISH="erp" ;; 2) MOBILE_PUBLISH="erp,landing" ;; 3) MOBILE_PUBLISH="sftp" ;; 4) MOBILE_PUBLISH=""; NO_UPLOAD=1 ;; *) err "invalid choice"; exit 1 ;; esac if [[ ",$MOBILE_PUBLISH," == *",landing,"* ]] && [ "$PUSH_SITE" != "1" ]; then read -rp "Also git push the website repo (= deploy logyou.de)? [y/N] " p case "$p" in y|Y) PUSH_SITE=1 ;; esac fi fi fi echo bold "Summary" printf ' version : %s (code %s)\n' "$NEW_NAME" "$NEW_CODE" printf ' notes : %s\n' "$RELEASE_NOTES" printf ' publish : %s%s\n' "${MOBILE_PUBLISH:-none (build + stage only)}" "$( [ "$PUSH_SITE" = "1" ] && printf ' (+ push website repo)' )" if [ "$ASSUME_YES" != "1" ]; then read -rp "Build and publish this release? [y/N] " go case "$go" in y|Y) ;; *) echo "Aborted."; exit 0;; esac fi # -------------------------------------------------------------------------- # 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" ] || [ -z "$MOBILE_PUBLISH" ]; then echo; ok "Build complete (upload skipped: --no-upload)." echo " Publish later with: scripts/publish-mobile-update.sh (ERP channel)" echo " scripts/stage-mobile-update.sh (logyou.de legacy channel)" else IFS=',' read -r -a PUBLISH_TARGETS <<< "$MOBILE_PUBLISH" for target in "${PUBLISH_TARGETS[@]}"; do case "$(printf '%s' "$target" | tr -d ' ')" in erp) echo; bold "Publishing into the ERP release channel…" "$SCRIPT_DIR/publish-mobile-update.sh" ;; landing) echo; bold "Publishing into the logyou.de website repo (legacy channel)…" if [ "$PUSH_SITE" = "1" ]; then "$SCRIPT_DIR/stage-mobile-update.sh" --push; else "$SCRIPT_DIR/stage-mobile-update.sh" --commit; fi ;; sftp) echo; bold "Publishing via SFTP…" "$SCRIPT_DIR/upload-mobile-update.sh" ;; "") ;; *) err "unknown MOBILE_PUBLISH target: $target"; exit 1 ;; esac done 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\""