diff --git a/scripts/build_ipas.sh b/scripts/build_ipas.sh index 4cd9d54..3205e0e 100755 --- a/scripts/build_ipas.sh +++ b/scripts/build_ipas.sh @@ -6,12 +6,14 @@ cd "$(dirname "$0")/.." PROJECT="$PWD/FuelBoard.xcodeproj" SCHEME="FuelBoard" DERIVED_DATA="/tmp/fuelboard-build-ipas" -SERVE_DIR="/tmp/ipa-serve" +SERVE_DIR="$PWD/Builds" FULL_IPA="$SERVE_DIR/FuelBoard-watch.ipa" SIDELOAD_IPA="$SERVE_DIR/FuelBoard-sideload.ipa" HOST="192.168.1.131" PORT="8765" +export SERVE_DIR + APP_PATH="$DERIVED_DATA/Build/Products/Release-iphoneos/FuelBoard.app" STAGE_FULL="/tmp/fuelboard-ipa-stage-full" STAGE_SIDELOAD="/tmp/fuelboard-ipa-stage-sideload" @@ -46,7 +48,9 @@ import os, shutil, zipfile app = '/tmp/fuelboard-build-ipas/Build/Products/Release-iphoneos/FuelBoard.app' stage = '/tmp/fuelboard-ipa-stage-full' payload = os.path.join(stage, 'Payload') -out = '/tmp/ipa-serve/FuelBoard-watch.ipa' +serve = os.environ['SERVE_DIR'] +out = os.path.join(serve, 'FuelBoard-watch.ipa') +os.makedirs(serve, exist_ok=True) if os.path.exists(stage): shutil.rmtree(stage) os.makedirs(payload, exist_ok=True) @@ -73,7 +77,8 @@ import os, shutil, zipfile app = '/tmp/fuelboard-build-ipas/Build/Products/Release-iphoneos/FuelBoard.app' stage = '/tmp/fuelboard-ipa-stage-sideload' payload = os.path.join(stage, 'Payload') -out = '/tmp/ipa-serve/FuelBoard-sideload.ipa' +serve = os.environ['SERVE_DIR'] +out = os.path.join(serve, 'FuelBoard-sideload.ipa') if os.path.exists(stage): shutil.rmtree(stage) os.makedirs(payload, exist_ok=True) @@ -117,6 +122,7 @@ for name, path in paths.items(): PY echo "==> URLs" +echo "Serving: ipa-serve # in $(basename "$PWD"), or: ipa-serve fuelboard" echo "Watch-capable IPA: http://$HOST:$PORT/FuelBoard-watch.ipa" echo "Sideload-safe IPA: http://$HOST:$PORT/FuelBoard-sideload.ipa" echo "Xcode log: /tmp/fuelboard-build-ipas-xcodebuild.log" diff --git a/scripts/install.sh b/scripts/install.sh new file mode 100755 index 0000000..1c32d4e --- /dev/null +++ b/scripts/install.sh @@ -0,0 +1,73 @@ +#!/bin/bash +# install.sh — build FuelBoard dev-signed and install straight to a paired iPhone. +# +# Streamlined flow (single command): +# ./scripts/install.sh # build + install + launch on the first paired iPhone +# ./scripts/install.sh --device UDID # target a specific device (xcrun devicectl list devices) +# ./scripts/install.sh --no-launch # install but don't auto-launch +# +# Why this exists: sideloading (SideStore/AltStore) got replaced on 2026-09-25 by a +# proper dev-signed install via devicectl — the phone is paired, so no LAN server, +# no delete/reinstall dance, and the installed app is a real signed build. The +# Release config targets the device (not the simulator) and reuses Xcode automatic +# signing with the project's DEVELOPMENT_TEAM. +# +# Requires: a paired + unlocked iPhone (xcrun devicectl list devices), and the +# Apple Development identity in the keychain. + +set -euo pipefail +cd "$(dirname "$0")/.." + +PROJECT="$PWD/FuelBoard.xcodeproj" +SCHEME="FuelBoard" +DERIVED_DATA="/tmp/fuelboard-devinstall" +APP="$DERIVED_DATA/Build/Products/Release-iphoneos/FuelBoard.app" +DEVICE="" +DEVICE_NAME="(first paired iPhone)" +LAUNCH=1 + +while [[ $# -gt 0 ]]; do + case "$1" in + --device) DEVICE="$2"; shift 2 ;; + --no-launch) LAUNCH=0; shift ;; + *) echo "unknown arg: $1" >&2; exit 1 ;; + esac +done + +# Resolve the device if not given: the first connected physical iPhone. +# devicectl --device wants the CoreDevice Identifier (field 3 of `list devices`, +# e.g. C519BE18-...). NOTE: xcodebuild -destination wants the hardware UDID +# (00008130-...), so we build with the generic platform destination and only use +# the CoreDevice Identifier for devicectl install/launch. +if [[ -z "$DEVICE" ]]; then + DEVICE="$(xcrun devicectl list devices 2>/dev/null | awk '/(available \(paired\))/ && /iPhone/ {print $3; exit}')" + if [[ -z "$DEVICE" ]]; then + echo "install.sh: no paired iPhone found. Check: xcrun devicectl list devices" >&2 + exit 1 + fi +fi + +echo "==> Build (Release, dev-signed, generic iOS destination)" +rm -rf "$DERIVED_DATA" +xcodebuild -project "$PROJECT" -scheme "$SCHEME" -configuration Release \ + -destination 'generic/platform=iOS' \ + -derivedDataPath "$DERIVED_DATA" \ + CODE_SIGN_STYLE=Automatic \ + build 2>&1 | grep -E "error:|BUILD (SUCCEEDED|FAILED)|Signing Identity" | tail -8 + +echo "==> Verify bundle" +test -d "$APP" || { echo "build failed: no app at $APP" >&2; exit 1; } +echo " bundle: $(plutil -extract CFBundleIdentifier raw "$APP/Info.plist")" \ + " $(plutil -extract CFBundleShortVersionString raw "$APP/Info.plist")" \ + "($(plutil -extract CFBundleVersion raw "$APP/Info.plist"))" + +echo "==> Install via devicectl" +xcrun devicectl device install app --device "$DEVICE" "$APP" 2>&1 | tail -6 + +if [[ "$LAUNCH" -eq 1 ]]; then + BID="$(plutil -extract CFBundleIdentifier raw "$APP/Info.plist")" + echo "==> Launch" + xcrun devicectl device process launch --device "$DEVICE" "$BID" 2>&1 | tail -4 +fi + +echo "==> Done ✅ (delete the old icon on the phone if you want it refreshed)" \ No newline at end of file