diff --git a/Scripts/ExportOptions-macOS.plist b/Scripts/ExportOptions-macOS.plist
new file mode 100644
index 0000000..5527d0e
--- /dev/null
+++ b/Scripts/ExportOptions-macOS.plist
@@ -0,0 +1,23 @@
+
+
+
+
+
+ method
+ app-store-connect
+ teamID
+ C32Z8JNLG6
+
+ destination
+ upload
+ signingStyle
+ automatic
+ uploadSymbols
+
+ stripSwiftSymbols
+
+ manageAppVersionAndBuildNumber
+
+
+
diff --git a/Scripts/release.sh b/Scripts/release.sh
index f5e522a..ac68ab2 100755
--- a/Scripts/release.sh
+++ b/Scripts/release.sh
@@ -1,16 +1,19 @@
#!/usr/bin/env bash
#
-# release.sh — archive Workouts (iOS app with the embedded watch app) and upload
-# to TestFlight / App Store Connect. No third-party tooling: pure xcodebuild + the
-# App Store Connect API key. Credentials live in .env.release (gitignored); see
-# .env.release.example.
+# release.sh — archive Workouts and upload to TestFlight / App Store Connect.
#
-# What it does:
+# Usage: Scripts/release.sh [ios|mac|all] (default: ios)
+#
+# No third-party tooling: pure xcodebuild + the App Store Connect API key.
+# Credentials live in .env.release (gitignored); see .env.release.example.
+#
+# What it does, per platform:
# 1. Regenerates the Xcode project with XcodeGen.
-# 2. Stamps CFBundleVersion (CURRENT_PROJECT_VERSION) with the git commit count
-# for both the iOS app and the embedded watch app.
-# 3. xcodebuild archive (the watch app rides along in the same archive)
-# 4. xcodebuild -exportArchive with destination=upload -> App Store Connect.
+# 2. xcodebuild archive (the watch app rides along in the iOS archive).
+# CFBundleVersion is stamped by the update_build_info.sh post-build phase,
+# platform-partitioned: iOS/watchOS even (commits*2), macOS odd (commits*2+1)
+# — both platforms share one ASC build-number space.
+# 3. xcodebuild -exportArchive with destination=upload -> App Store Connect.
#
set -euo pipefail
@@ -19,8 +22,8 @@ ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
cd "$ROOT"
PROJECT="Workouts.xcodeproj"
-SCHEME="Workouts"
BUILD_DIR="$ROOT/build"
+PLATFORM="${1:-ios}"
# ---- credentials ------------------------------------------------------------
ENV_FILE="$ROOT/.env.release"
@@ -49,38 +52,70 @@ fi
# ---- versioning -------------------------------------------------------------
BUILD_NUMBER="$(git rev-list HEAD --count)"
MARKETING_VERSION="$(grep -m1 'MARKETING_VERSION:' project.yml | sed -E 's/.*"([^"]+)".*/\1/')"
-echo "📦 Version $MARKETING_VERSION (build $BUILD_NUMBER)"
+echo "📦 Version $MARKETING_VERSION — iOS build $((BUILD_NUMBER * 2)), macOS build $((BUILD_NUMBER * 2 + 1))"
mkdir -p "$BUILD_DIR"
-ARCHIVE="$BUILD_DIR/Workouts.xcarchive"
-EXPORT="$BUILD_DIR/Workouts-export"
-rm -rf "$ARCHIVE" "$EXPORT"
-echo "🛠 Archiving (iOS app + embedded watch app) ..."
-xcodebuild archive \
- -project "$PROJECT" \
- -scheme "$SCHEME" \
- -configuration Release \
- -destination 'generic/platform=iOS' \
- -archivePath "$ARCHIVE" \
- CURRENT_PROJECT_VERSION="$BUILD_NUMBER" \
- CODE_SIGN_STYLE=Automatic \
- DEVELOPMENT_TEAM="$APPLE_TEAM_ID" \
- "${AUTH[@]}"
+# ---- per-platform archive + upload ------------------------------------------
+# args:
+archive_and_upload() {
+ local scheme="$1" destination="$2" export_plist="$3"
+ local archive_path="$BUILD_DIR/$scheme.xcarchive"
+ local export_path="$BUILD_DIR/$scheme-export"
-echo "🚀 Exporting + uploading to App Store Connect ..."
-xcodebuild -exportArchive \
- -archivePath "$ARCHIVE" \
- -exportPath "$EXPORT" \
- -exportOptionsPlist "$SCRIPT_DIR/ExportOptions-iOS.plist" \
- "${AUTH[@]}"
+ echo ""
+ echo "──────── $scheme ────────"
+
+ rm -rf "$archive_path" "$export_path"
+
+ echo "🛠 Archiving $scheme ..."
+ xcodebuild archive \
+ -project "$PROJECT" \
+ -scheme "$scheme" \
+ -configuration Release \
+ -destination "$destination" \
+ -archivePath "$archive_path" \
+ CODE_SIGN_STYLE=Automatic \
+ DEVELOPMENT_TEAM="$APPLE_TEAM_ID" \
+ "${AUTH[@]}"
+
+ echo "🚀 Exporting + uploading $scheme to App Store Connect ..."
+ xcodebuild -exportArchive \
+ -archivePath "$archive_path" \
+ -exportPath "$export_path" \
+ -exportOptionsPlist "$export_plist" \
+ "${AUTH[@]}"
+
+ case "$scheme" in
+ *Mac) local plat_build=$((BUILD_NUMBER * 2 + 1)) ;;
+ *) local plat_build=$((BUILD_NUMBER * 2)) ;;
+ esac
+ echo "✅ $scheme uploaded (build $plat_build)."
+}
+
+do_ios() {
+ archive_and_upload "Workouts" "generic/platform=iOS" \
+ "$SCRIPT_DIR/ExportOptions-iOS.plist"
+}
+
+do_mac() {
+ archive_and_upload "Workouts Mac" "generic/platform=macOS" \
+ "$SCRIPT_DIR/ExportOptions-macOS.plist"
+}
+
+case "$PLATFORM" in
+ ios) do_ios ;;
+ mac|macos) do_mac ;;
+ all) do_ios; do_mac ;;
+ *) echo "Usage: Scripts/release.sh [ios|mac|all]"; exit 1 ;;
+esac
echo ""
-echo "✅ Uploaded build $BUILD_NUMBER. Appears in App Store Connect > TestFlight after processing (~5–15 min)."
+echo "🎉 Done. Builds appear in App Store Connect > TestFlight after processing (~5–15 min)."
echo ""
echo "➡️ Push metadata, then stage/submit for review with the canonical scripts"
echo " (apps sit as siblings of indie-skills under ~/Documents/indie; --bundle"
-echo " and --version are required flags — there are no per-app defaults):"
+echo " and --version are required flags; pass --platform macos for the Mac listing):"
echo ""
echo " set -a; source .env.release; set +a; swift ../indie-skills/skills/appstore-publish/scripts/asc-metadata.swift --bundle dev.rzen.indie.Workouts --version $MARKETING_VERSION --dry-run"
echo " set -a; source .env.release; set +a; swift ../indie-skills/skills/appstore-publish/scripts/asc-metadata.swift --bundle dev.rzen.indie.Workouts --version $MARKETING_VERSION"