#!/usr/bin/env bash # Generate v0 OTA artifacts for one APK (stdout = channel stable.json). # # Usage: # ./scripts/generate-ota-v0.sh path/to/app-release.apk https://host[:port] [out-dir] [channel] # # channel — JSON under v0/ota/channel/ (stable, staging, dev, nightly, or custom) # Writes under out-dir (default: ./ota-publish): # v0/ota/channel/stable.json # v0/ota/00/00.MM/00.MM.mm/android_cast_00.MM.mm.BB_manifest.json # v0/ota/00/00.MM/00.MM.mm/android_cast_00.MM.mm.BB_sign.json # v0/ota/00/00.MM/00.MM.mm/android_cast_00.MM.mm.BB.otapkg # v0/ota/00/00.MM/00.MM.mm/android_cast_00.MM.mm.BB.otabundle.zip (STORE zip) set -euo pipefail apk="${1:?APK path required}" host_base="${2:?Base URL required, e.g. https://192.168.1.1:8080}" out_dir="${3:-ota-publish}" channel="${4:-stable}" if [[ ! -f "$apk" ]]; then echo "APK not found: $apk" >&2 exit 1 fi pad2() { printf '%02d' "$1"; } major="" minor="" build="" if command -v aapt >/dev/null 2>&1; then badging="$(aapt dump badging "$apk" 2>/dev/null || true)" version_code="$(echo "$badging" | sed -n "s/.*versionCode='\([^']*\)'.*/\1/p" | head -1)" version_name="$(echo "$badging" | sed -n "s/.*versionName='\([^']*\)'.*/\1/p" | head -1)" if [[ -n "${version_code:-}" ]]; then major=$((version_code / 10000)) minor=$(((version_code / 100) % 100)) build=$((version_code % 100)) fi fi if [[ -z "${major:-}" ]]; then echo "Could not read versionCode from APK (install build-tools / aapt)." >&2 exit 1 fi maj_p="$(pad2 "$major")" min_p="$(pad2 "$minor")" bld_p="$(pad2 "$build")" ver_p="${maj_p}.${min_p}.${bld_p}" base="${host_base%/}/v0/ota/00/${maj_p}/${ver_p}" artifact_base="${base}/android_cast_${ver_p}.${bld_p}" apk_url="${artifact_base}.otapkg" sign_url="${artifact_base}_sign.json" manifest_url="${artifact_base}_manifest.json" bundle_url="${artifact_base}.otabundle.zip" sha256="$(sha256sum "$apk" | awk '{print $1}')" apk_size="$(stat -c%s "$apk" 2>/dev/null || wc -c <"$apk" | tr -d ' ')" rel_root="${out_dir}/v0/ota" rel_dir="${rel_root}/00/${maj_p}/${ver_p}" mkdir -p "${rel_dir}" "${rel_root}/channel" pkg_name="android_cast_${ver_p}.${bld_p}.otapkg" cp -f "$apk" "${rel_dir}/${pkg_name}" sign_name="android_cast_${ver_p}.${bld_p}_sign.json" manifest_name="android_cast_${ver_p}.${bld_p}_manifest.json" bundle_name="android_cast_${ver_p}.${bld_p}.otabundle.zip" cat >"${rel_dir}/${sign_name}" <"${rel_dir}/${manifest_name}" </dev/null || wc -c <"${rel_dir}/${bundle_name}" | tr -d ' ')" # Patch manifest with bundle fields (jq optional; use temp file + heredoc rewrite) cat >"${rel_dir}/${manifest_name}" <"${channel_file}" <&2 echo "Channel: ${host_base%/}/v0/ota/channel/${channel}.json" >&2 echo "Bundle: ${bundle_url} (${bundle_size} bytes)" >&2 cat "${channel_file}"