eleven / ocho Public

Clone
git clone https://amadan.net/eleven/ocho

Plain git — no account needed to clone.

Download

Download this file

1#!/usr/bin/env bash
2# Build, sign, and upload a TestFlight release of the iPhone app (LChat), then
3# hand the uploaded build to ios/asc-testflight.mjs, which does the App Store
4# Connect side: wait out processing, declare export compliance, seed "What to
5# Test", and place the build with the tester groups.
6#
7# The Mac's counterpart is ios/release-mac.sh (Developer ID + Sparkle). Mint
8# both from the same version/build so the two apps stay in step — they are one
9# product (CLAUDE.md § Conventions).
10#
11# Usage: ios/release-ios.sh <marketing-version> <build-number> [--external]
12# ios/release-ios.sh 0.9.0 1 # internal testers only
13# ios/release-ios.sh 0.9.0 1 --external # …and submit for external review
14#
15# Required env:
16# LCHAT_ASC_KEY_PATH / LCHAT_ASC_KEY_ID / LCHAT_ASC_ISSUER_ID
17# The App Store Connect API key (see the operator runbook). The key must
18# have Admin role — an App Manager key can't mint the cloud distribution
19# certificate and dies with "Cloud signing permission error".
20# Optional env:
21# LCHAT_RELEASE_NOTES_MD Path to the release notes; becomes the build's
22# "What to Test" text for testers.
23# LCHAT_ASC_APP_ID Default 6787060127 (the Eleven Messenger app record).
24#
25# ALWAYS pass the -authenticationKey* flags (they're built in below): without
26# them xcodebuild scans Xcode's stored ASC accounts, and one dead account
27# session aborts the whole export with "Error Downloading App Information".
28set -euo pipefail
29
30VERSION="${1:?usage: release-ios.sh <marketing-version> <build-number> [--external]}"
31BUILD="${2:?usage: release-ios.sh <marketing-version> <build-number> [--external]}"
32EXTERNAL="${3:-}"
33: "${LCHAT_ASC_KEY_PATH:?LCHAT_ASC_KEY_PATH is required (ASC API key .p8 path)}"
34: "${LCHAT_ASC_KEY_ID:?LCHAT_ASC_KEY_ID is required}"
35: "${LCHAT_ASC_ISSUER_ID:?LCHAT_ASC_ISSUER_ID is required}"
36TEAM_ID="J5NDF5PCD8"
37
38REPO="$(cd "$(dirname "$0")/.." && pwd)"
39IOS="$REPO/ios"
40TMP="$(mktemp -d)"
41trap 'rm -rf "$TMP"' EXIT
42
43ASC_AUTH=(-authenticationKeyPath "$LCHAT_ASC_KEY_PATH" -authenticationKeyID "$LCHAT_ASC_KEY_ID" -authenticationKeyIssuerID "$LCHAT_ASC_ISSUER_ID")
44
45echo "Building Eleven $VERSION ($BUILD) — App Store Connect / TestFlight"
46
47cd "$IOS"
48xcodegen generate
49
50xcodebuild archive \
51 -project LChat.xcodeproj -scheme LChat -destination 'generic/platform=iOS' \
52 -archivePath "$TMP/LChat.xcarchive" -allowProvisioningUpdates \
53 CODE_SIGN_STYLE=Automatic MARKETING_VERSION="$VERSION" CURRENT_PROJECT_VERSION="$BUILD"
54
55# -exportOptionsPlist has no CLI flag form, so template a throwaway one.
56# manageAppVersionAndBuildNumber is deliberately FALSE: it would override the
57# numbers we just archived with whatever ASC thinks comes next, and the whole
58# point is that the Mac and the iPhone carry the same version.
59cat > "$TMP/export-options.plist" <<PLIST
60<?xml version="1.0" encoding="UTF-8"?>
61<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
62<plist version="1.0">
63<dict>
64 <key>method</key>
65 <string>app-store-connect</string>
66 <key>destination</key>
67 <string>upload</string>
68 <key>teamID</key>
69 <string>$TEAM_ID</string>
70 <key>signingStyle</key>
71 <string>automatic</string>
72 <key>uploadSymbols</key>
73 <true/>
74 <key>manageAppVersionAndBuildNumber</key>
75 <false/>
76</dict>
77</plist>
78PLIST
79
80xcodebuild -exportArchive -archivePath "$TMP/LChat.xcarchive" -exportPath "$TMP/export" \
81 -exportOptionsPlist "$TMP/export-options.plist" -allowProvisioningUpdates "${ASC_AUTH[@]}"
82
83echo "Uploaded. Handing over to App Store Connect…"
84exec node "$IOS/asc-testflight.mjs" "$VERSION" "$BUILD" $EXTERNAL
85