fix(workout): verify created app mobile blockers

Make the standalone hemx-workout command generated by workout new carry external blocker acknowledgements in release-manifest.json and fail mobile-verify when the manifest or BLOCKERS.md omits current Android/iOS signing/toolchain blockers.

req: examples/006
This commit is contained in:
slhx agent
2026-06-12 13:57:14 +02:00
parent 4bbf417531
commit f343e8aaee
+32 -1
View File
@@ -226,6 +226,32 @@ write_blockers() {{
}} > "$OUT/BLOCKERS.md"
}}
write_blockers_json() {{
first=1
if [ -z "${{ANDROID_HOME:-${{ANDROID_SDK_ROOT:-}}}}" ]; then [ "$first" = 1 ] || printf ', '; printf '"%s"' 'Android SDK not found: set ANDROID_HOME or ANDROID_SDK_ROOT before producing signed Android artifacts'; first=0; fi
if ! command -v java >/dev/null 2>&1; then [ "$first" = 1 ] || printf ', '; printf '"%s"' 'Java runtime not found: Android packaging requires a JDK'; first=0; fi
if [ -z "${{HEMX_WORKOUT_ANDROID_KEYSTORE:-}}" ]; then [ "$first" = 1 ] || printf ', '; printf '"%s"' 'Android signing key not configured: set HEMX_WORKOUT_ANDROID_KEYSTORE for store-ready signing'; first=0; fi
if [ -z "${{HEMX_WORKOUT_GOOGLE_PLAY_TRACK:-}}" ]; then [ "$first" = 1 ] || printf ', '; printf '"%s"' 'Google Play submission target not configured: set HEMX_WORKOUT_GOOGLE_PLAY_TRACK after choosing the Play Console track outside this app'; first=0; fi
if ! command -v xcodebuild >/dev/null 2>&1; then [ "$first" = 1 ] || printf ', '; printf '"%s"' 'Xcode command line tools not found: iOS archive/export requires xcodebuild on macOS'; first=0; fi
if [ -z "${{HEMX_WORKOUT_IOS_TEAM_ID:-}}" ]; then [ "$first" = 1 ] || printf ', '; printf '"%s"' 'iOS signing team not configured: set HEMX_WORKOUT_IOS_TEAM_ID for App Store/TestFlight export'; first=0; fi
if [ -z "${{HEMX_WORKOUT_APP_STORE_CONNECT_TEAM:-}}" ]; then [ "$first" = 1 ] || printf ', '; printf '"%s"' 'App Store Connect submission team not configured: set HEMX_WORKOUT_APP_STORE_CONNECT_TEAM after choosing the Apple account outside this app'; fi
}}
check_blocker() {{
grep -F "$1" "$OUT/BLOCKERS.md" >/dev/null || {{ echo "BLOCKERS.md missing external blocker: $1" >&2; exit 1; }}
grep -F "$1" "$OUT/release-manifest.json" >/dev/null || {{ echo "release-manifest.json missing external blocker: $1" >&2; exit 1; }}
}}
check_external_blockers() {{
[ -n "${{ANDROID_HOME:-${{ANDROID_SDK_ROOT:-}}}}" ] || check_blocker 'Android SDK not found: set ANDROID_HOME or ANDROID_SDK_ROOT before producing signed Android artifacts'
command -v java >/dev/null 2>&1 || check_blocker 'Java runtime not found: Android packaging requires a JDK'
[ -n "${{HEMX_WORKOUT_ANDROID_KEYSTORE:-}}" ] || check_blocker 'Android signing key not configured: set HEMX_WORKOUT_ANDROID_KEYSTORE for store-ready signing'
[ -n "${{HEMX_WORKOUT_GOOGLE_PLAY_TRACK:-}}" ] || check_blocker 'Google Play submission target not configured: set HEMX_WORKOUT_GOOGLE_PLAY_TRACK after choosing the Play Console track outside this app'
command -v xcodebuild >/dev/null 2>&1 || check_blocker 'Xcode command line tools not found: iOS archive/export requires xcodebuild on macOS'
[ -n "${{HEMX_WORKOUT_IOS_TEAM_ID:-}}" ] || check_blocker 'iOS signing team not configured: set HEMX_WORKOUT_IOS_TEAM_ID for App Store/TestFlight export'
[ -n "${{HEMX_WORKOUT_APP_STORE_CONNECT_TEAM:-}}" ] || check_blocker 'App Store Connect submission team not configured: set HEMX_WORKOUT_APP_STORE_CONNECT_TEAM after choosing the Apple account outside this app'
}}
case "$CMD" in
dev|run)
exec cargo run --manifest-path "$APP_DIR/Cargo.toml" --bin workout-app
@@ -257,7 +283,8 @@ case "$CMD" in
"environment_boundary": "public mobile shell config lives here; secrets and signing credentials stay outside the app repo",
"rollback": "redeploy the previous server binary and matching mobile shell metadata; rebuild store artifacts with the previous version/signing inputs",
"android": "android/twa-release.json",
"ios": "ios/webview-release.json"
"ios": "ios/webview-release.json",
"external_blockers": [$(write_blockers_json)]
}}
EOF
cat > "$OUT/android/twa-release.json" <<EOF
@@ -278,6 +305,7 @@ EOF
grep -F 'app-owned command/event/projection records' "$OUT/release-manifest.json" >/dev/null
grep -F 'host_result_kinds' "$OUT/android/twa-release.json" >/dev/null
grep -F 'host_result_kinds' "$OUT/ios/webview-release.json" >/dev/null
check_external_blockers
echo "workout-mobile-verified\tout=$OUT"
;;
doctor)
@@ -1089,6 +1117,9 @@ mod tests {
assert!(command.contains("mobile-verify"));
assert!(command.contains(hemx_js::RUNTIME_JS_HASH));
assert!(command.contains("app-owned command/event/projection records"));
assert!(command.contains("external_blockers"));
assert!(command.contains("check_external_blockers"));
assert!(command.contains("BLOCKERS.md missing external blocker"));
assert!(destination.join("src/lib.rs").exists());
assert!(destination.join("templates/workout.heml").exists());
let _ = fs::remove_dir_all(&destination);