Set up distribution and release

Records the channel decision: the Mac App Store, as version 2.0 of the
existing dev.rzen.indie.Kanban record - the 1.x app already listed
there under the Lanework name. The question the card held open was
settled by three prior rulings (the edition split's separate App Store
targets with base keeping the shipping bundle id, the 2.0 marketing
version, and the account's App-Store-shaped tooling); RELEASE.md
records the reasoning and why notarized-direct is not pursued for 2.0.

Pipeline carried over from the 1.x repo: scripts/release.sh (archive +
destination=upload export, --platform macos reminders in its epilogue),
ExportOptions-macOS.plist, .env.release.example (+ .gitignore entry for
the real credentials). scripts/metadata/ holds the fresh 2.0 listing -
rewritten description/what's-new for the rewrite (plain-files boards,
live outside edits, card windows, trash, undo, templates, agent guide,
accessibility), carried keywords/URLs/categories/pricing (free)/
availability (ALL), and review notes updated to the 2.0 UI. All fields
within API limits; asc-metadata --dry-run validates end-to-end against
the live record (version 2.0 would be created; pricing and availability
already correct). Local Release archive verified: Lanework 2.0 build
165, signed, correct identity.

Remaining steps are deliberately user-gated at RELEASE.md's PUSH POINT:
screenshots need a real display, and everything past the archive writes
to the live record of a shipping 1.x app.

Claude-Session: https://claude.ai/code/session_01SR4XGjmBE16ZUYWpfFHXwY
This commit is contained in:
2026-07-29 13:43:26 -04:00
parent f34707e17e
commit aad8857ea0
18 changed files with 240 additions and 0 deletions
+96
View File
@@ -0,0 +1,96 @@
#!/usr/bin/env bash
#
# release.sh — archive Kanban (macOS) and upload to TestFlight / App Store Connect.
#
# Usage: Scripts/release.sh
#
# 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:
# 1. Regenerates the Xcode project with XcodeGen.
# 2. CFBundleVersion is stamped with the git commit count during the archive
# by the postBuildScripts phase (app-versioning skill) — this script does
# not touch the build number itself, so commit everything before releasing.
# 3. xcodebuild archive -> .xcarchive (Release config; the full app-sandbox
# entitlements come from project.yml's Release config).
# 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"
APP_NAME="Kanban"
PROJECT="Kanban.xcodeproj"
SCHEME="Kanban"
BUNDLE_ID="dev.rzen.indie.Kanban"
BUILD_DIR="$ROOT/build"
# ---- 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 -------------------------------------------------------------
# CFBundleVersion is stamped during the archive by the postBuildScripts phase
# (app-versioning skill). MARKETING_VERSION is read here only for the log line.
BUILD_NUMBER="$(git rev-list HEAD --count)"
VERSION="$(grep -m1 'MARKETING_VERSION:' project.yml | sed -E 's/.*"([^"]+)".*/\1/')"
echo "📦 $APP_NAME $VERSION — build $BUILD_NUMBER"
mkdir -p "$BUILD_DIR"
ARCHIVE_PATH="$BUILD_DIR/$SCHEME.xcarchive"
EXPORT_PATH="$BUILD_DIR/$SCHEME-export"
rm -rf "$ARCHIVE_PATH" "$EXPORT_PATH"
echo ""
echo "🛠 Archiving $SCHEME (macOS, Release) ..."
xcodebuild archive \
-project "$PROJECT" \
-scheme "$SCHEME" \
-configuration Release \
-destination "generic/platform=macOS" \
-archivePath "$ARCHIVE_PATH" \
CODE_SIGN_STYLE=Automatic \
DEVELOPMENT_TEAM="$APPLE_TEAM_ID" \
"${AUTH[@]}"
echo "🚀 Exporting + uploading to App Store Connect ..."
xcodebuild -exportArchive \
-archivePath "$ARCHIVE_PATH" \
-exportPath "$EXPORT_PATH" \
-exportOptionsPlist "$SCRIPT_DIR/ExportOptions-macOS.plist" \
"${AUTH[@]}"
echo "$APP_NAME uploaded (build $BUILD_NUMBER)."
echo ""
echo "🎉 Done. The build appears in App Store Connect > TestFlight after processing (~515 min)."
echo ""
echo "➡️ App Store listing + review (macOS). The asc scripts default to iOS, so"
echo " pass --platform macos here — REQUIRED, or they create a spurious iOS version:"
echo " set -a; source .env.release; set +a; swift ../indie-skills/skills/appstore-publish/scripts/asc-metadata.swift --bundle $BUNDLE_ID --version $VERSION --platform macos --dry-run"
echo " set -a; source .env.release; set +a; swift ../indie-skills/skills/appstore-publish/scripts/asc-submit.swift --bundle $BUNDLE_ID --version $VERSION --platform macos"
echo " Use the version matching the macOS App Store version in ASC (see Scripts/metadata/README.md)."