133 lines
4.6 KiB
Bash
Executable File
133 lines
4.6 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
|
cd "$ROOT_DIR"
|
|
|
|
TS="$(date -u +"%Y%m%dT%H%M%SZ")"
|
|
OUT_DIR="${TMPDIR:-/tmp}/werkout_watch_hardware_pass_${TS}"
|
|
mkdir -p "$OUT_DIR"
|
|
|
|
export SWIFTPM_MODULECACHE_OVERRIDE="${TMPDIR:-/tmp}/werkout_swiftpm_module_cache"
|
|
export CLANG_MODULE_CACHE_PATH="${TMPDIR:-/tmp}/werkout_clang_module_cache"
|
|
export XDG_CACHE_HOME="${TMPDIR:-/tmp}/werkout_xdg_cache"
|
|
mkdir -p "$SWIFTPM_MODULECACHE_OVERRIDE" "$CLANG_MODULE_CACHE_PATH" "$XDG_CACHE_HOME"
|
|
|
|
PKG_CACHE_DIR="$OUT_DIR/package_cache"
|
|
PKG_CLONES_DIR="$OUT_DIR/source_packages"
|
|
XCODE_TEMP_HOME="$OUT_DIR/home"
|
|
mkdir -p "$PKG_CACHE_DIR" "$PKG_CLONES_DIR" "$XCODE_TEMP_HOME"
|
|
|
|
IOS_DEST_FILE="$OUT_DIR/ios_showdestinations.txt"
|
|
WATCH_DEST_FILE="$OUT_DIR/watch_showdestinations.txt"
|
|
|
|
HOME="$XCODE_TEMP_HOME" xcodebuild -project iphone/Werkout_ios.xcodeproj \
|
|
-scheme 'Werkout_ios' \
|
|
-disableAutomaticPackageResolution \
|
|
-clonedSourcePackagesDirPath "$PKG_CLONES_DIR" \
|
|
-packageCachePath "$PKG_CACHE_DIR" \
|
|
-showdestinations > "$IOS_DEST_FILE" 2>&1 || {
|
|
echo "Failed to query iOS destinations."
|
|
echo "Inspect: $IOS_DEST_FILE"
|
|
tail -n 80 "$IOS_DEST_FILE" || true
|
|
exit 3
|
|
}
|
|
|
|
HOME="$XCODE_TEMP_HOME" xcodebuild -project iphone/Werkout_ios.xcodeproj \
|
|
-scheme 'Werkout_watch Watch App' \
|
|
-disableAutomaticPackageResolution \
|
|
-clonedSourcePackagesDirPath "$PKG_CLONES_DIR" \
|
|
-packageCachePath "$PKG_CACHE_DIR" \
|
|
-showdestinations > "$WATCH_DEST_FILE" 2>&1 || {
|
|
echo "Failed to query watchOS destinations."
|
|
echo "Inspect: $WATCH_DEST_FILE"
|
|
tail -n 80 "$WATCH_DEST_FILE" || true
|
|
exit 3
|
|
}
|
|
|
|
IOS_ELIGIBLE_LINE="$(awk '/Available destinations/{flag=1;next}/Ineligible destinations/{flag=0}flag' "$IOS_DEST_FILE" \
|
|
| rg "platform:iOS, arch:arm64, id:" \
|
|
| rg -v "placeholder" \
|
|
| head -n 1 || true)"
|
|
|
|
WATCH_ELIGIBLE_LINE="$(awk '/Available destinations/{flag=1;next}/Ineligible destinations/{flag=0}flag' "$WATCH_DEST_FILE" \
|
|
| rg "platform:watchOS, arch:" \
|
|
| rg -v "undefined_arch|placeholder" \
|
|
| head -n 1 || true)"
|
|
|
|
if [[ -z "$IOS_ELIGIBLE_LINE" ]]; then
|
|
echo "No eligible physical iOS destination found."
|
|
echo "Inspect: $IOS_DEST_FILE"
|
|
exit 2
|
|
fi
|
|
|
|
if [[ -z "$WATCH_ELIGIBLE_LINE" ]]; then
|
|
echo "No eligible physical watchOS destination found."
|
|
echo "Inspect: $WATCH_DEST_FILE"
|
|
exit 2
|
|
fi
|
|
|
|
IOS_ID="$(echo "$IOS_ELIGIBLE_LINE" | sed -E 's/.*id:([^,]+),.*/\1/')"
|
|
WATCH_ID="$(echo "$WATCH_ELIGIBLE_LINE" | sed -E 's/.*id:([^,]+),.*/\1/')"
|
|
|
|
echo "Using iOS destination: $IOS_ELIGIBLE_LINE"
|
|
echo "Using watchOS destination: $WATCH_ELIGIBLE_LINE"
|
|
|
|
echo
|
|
echo "Preflight compile for selected hardware destinations..."
|
|
|
|
set -o pipefail
|
|
HOME="$XCODE_TEMP_HOME" xcodebuild -project iphone/Werkout_ios.xcodeproj \
|
|
-scheme 'Werkout_ios' \
|
|
-configuration Debug \
|
|
-destination "id=$IOS_ID" \
|
|
-disableAutomaticPackageResolution \
|
|
-clonedSourcePackagesDirPath "$PKG_CLONES_DIR" \
|
|
-packageCachePath "$PKG_CACHE_DIR" \
|
|
CODE_SIGNING_ALLOWED=NO \
|
|
build > "$OUT_DIR/ios_hardware_build.log" 2>&1
|
|
|
|
HOME="$XCODE_TEMP_HOME" xcodebuild -project iphone/Werkout_ios.xcodeproj \
|
|
-scheme 'Werkout_watch Watch App' \
|
|
-configuration Debug \
|
|
-destination "id=$WATCH_ID" \
|
|
-disableAutomaticPackageResolution \
|
|
-clonedSourcePackagesDirPath "$PKG_CLONES_DIR" \
|
|
-packageCachePath "$PKG_CACHE_DIR" \
|
|
CODE_SIGNING_ALLOWED=NO \
|
|
build > "$OUT_DIR/watch_hardware_build.log" 2>&1
|
|
|
|
cat > "$OUT_DIR/manual_disconnect_reconnect_checklist.md" <<'EOF'
|
|
# Manual Hardware Disconnect/Reconnect Pass
|
|
|
|
1. Launch iOS app on the selected physical iPhone/iPad.
|
|
2. Launch watch app on the paired physical Apple Watch.
|
|
3. Start a workout from iOS and confirm watch receives first exercise.
|
|
4. Disconnect watch from phone transport:
|
|
- Disable Bluetooth on iPhone for 30 seconds, or
|
|
- Enable Airplane Mode on watch for 30 seconds.
|
|
5. While disconnected, trigger 5+ state changes on phone:
|
|
- Next/previous exercise
|
|
- Pause/resume
|
|
- Complete workout
|
|
6. Reconnect transport.
|
|
7. Verify on watch:
|
|
- Latest state is applied.
|
|
- No crash.
|
|
- No infinite stale replay loop.
|
|
8. Repeat with two cycles of disconnect/reconnect in same workout.
|
|
|
|
Pass criteria:
|
|
- Watch converges to current exercise/time state after each reconnect.
|
|
- Queue replay does not exceed recent max-capped payload behavior.
|
|
- Completion payload arrives exactly once.
|
|
|
|
Log capture suggestion:
|
|
log stream --style compact --predicate '(subsystem == "com.werkout.ios" || subsystem == "com.werkout.watch")'
|
|
EOF
|
|
|
|
echo
|
|
echo "Hardware preflight complete."
|
|
echo "Artifacts: $OUT_DIR"
|
|
echo "Runbook: $OUT_DIR/manual_disconnect_reconnect_checklist.md"
|