Files
rzen cf8616107b Add IndieAbout + IndieBackup, TestFlight release pipeline
IndieAbout: About section in iOS Settings and macOS About window; LICENSE
switched to the portfolio-standard ISC text (reflowed for in-app rendering).

IndieBackup: files-only backup/restore of the iCloud container documents
('.notesbackup' document type on both platforms), SwiftData cache rebuilt
via SyncEngine.rebuildCache() after restore, monitors suspended during the
file swap, onOpenURL import with pre-launch queueing.

Release pipeline: Scripts/release.sh (ios|mac|all) archives and uploads via
xcodebuild + ASC API key; platform-partitioned build numbers (iOS even,
macOS odd) since both targets share one bundle ID and build sequence.
2026-07-14 20:50:06 -04:00

115 lines
3.9 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
#
# release.sh — archive Notes and upload to TestFlight / App Store Connect.
#
# Usage: Scripts/release.sh [ios|mac|all] (default: all)
#
# 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 from the git commit count, platform-partitioned
# (iOS even, macOS odd — Scripts/update_build_number.sh, a post-build
# phase wired in project.yml).
# 3. xcodebuild archive -> .xcarchive
# 4. xcodebuild -exportArchive with destination=upload -> App Store Connect.
#
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
cd "$ROOT"
PROJECT="Notes.xcodeproj"
BUILD_DIR="$ROOT/build"
PLATFORM="${1:-all}"
# ---- credentials ------------------------------------------------------------
ENV_FILE="$ROOT/.env.release"
if [ -f "$ENV_FILE" ]; then
set -a; . "$ENV_FILE"; set +a
fi
: "${APPLE_TEAM_ID:?Set APPLE_TEAM_ID (copy .env.release.example -> .env.release)}"
: "${ASC_KEY_ID:?Set ASC_KEY_ID in .env.release}"
: "${ASC_ISSUER_ID:?Set ASC_ISSUER_ID in .env.release}"
: "${ASC_KEY_PATH:?Set ASC_KEY_PATH in .env.release}"
[ -f "$ASC_KEY_PATH" ] || { echo "❌ API key not found at: $ASC_KEY_PATH"; exit 1; }
AUTH=(
-authenticationKeyPath "$ASC_KEY_PATH"
-authenticationKeyID "$ASC_KEY_ID"
-authenticationKeyIssuerID "$ASC_ISSUER_ID"
-allowProvisioningUpdates
)
# ---- regenerate project -----------------------------------------------------
if command -v xcodegen >/dev/null 2>&1; then
echo "🧩 Generating $PROJECT ..."
xcodegen generate
elif [ ! -d "$PROJECT" ]; then
echo "❌ $PROJECT missing and xcodegen not installed."; exit 1
fi
# ---- versioning -------------------------------------------------------------
# The Info.plists hold the literal "$(MARKETING_VERSION)" (resolved at build
# time), so read the real value from project.yml. The build number is stamped
# per-platform by Scripts/update_build_number.sh during the archive (even for
# iOS, odd for macOS — see that script); shown here for reference.
BUILD_NUMBER="$(git rev-list HEAD --count)"
MARKETING_VERSION="$(grep -m1 'MARKETING_VERSION:' project.yml | sed -E 's/.*"([^"]+)".*/\1/')"
echo "📦 Version $MARKETING_VERSION — iOS build $((BUILD_NUMBER * 2)), macOS build $((BUILD_NUMBER * 2 + 1))"
mkdir -p "$BUILD_DIR"
# ---- per-platform archive + upload ------------------------------------------
# args: <scheme> <generic destination> <ExportOptions plist>
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 ""
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[@]}"
echo "✅ $scheme uploaded."
}
do_ios() {
archive_and_upload "Notes" "generic/platform=iOS" "$SCRIPT_DIR/ExportOptions-iOS.plist"
}
do_mac() {
archive_and_upload "NotesMac" "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 "🎉 Done. Builds appear in App Store Connect > TestFlight after processing (~515 min)."