Release signing
How to sign and publish Tanvrit Compute release builds. The scaffolding is in place; the only thing missing is the actual keystore + provisioning profile + Apple Team ID, which are provisioned once per account.
Android (Google Play)
One-time setup
- Generate a release keystore (keep this file off the repo — store in
1Password / secrets manager / GitHub Actions encrypted secrets):
`` keytool -genkeypair -v \ -keystore tanvrit-compute-release.jks \ -keyalg RSA -keysize 4096 -validity 10950 \ -alias tanvrit-compute ``
10,950 days ≈ 30 years; Play Store will still accept it past 25 years.
- Upload the certificate fingerprint to Play Console → App integrity →
App signing. Pick Play App Signing and upload this keystore as the upload key. Google manages the release signing key on their side from then on.
Per-release env vars
The build reads these at assembly time. Set them in the GitHub Actions workflow (encrypted secrets) or export them locally before building:
ANDROID_KEYSTORE_PATH=/secure/path/tanvrit-compute-release.jks
ANDROID_KEYSTORE_PASSWORD=…
ANDROID_KEY_ALIAS=tanvrit-compute
ANDROID_KEY_PASSWORD=…
Alternatively drop them into ~/.gradle/gradle.properties (NOT the repo's gradle.properties) under these keys:
android.keystore.path=…
android.keystore.password=…
android.key.alias=…
android.key.password=…
Build + upload
./gradlew :composeApp:bundleRelease
# Output: composeApp/build/outputs/bundle/release/composeApp-release.aab
# Upload via Play Console or the fastlane / upload-google-play action.
When no keystore is configured the release build falls back to the debug signer — useful for internal testing but rejected by Play Store.
iOS (App Store Connect / TestFlight)
One-time setup
- Join the Apple Developer Program
- Find your 10-character Team ID at <https://developer.apple.com/account>
- Register the app in App Store Connect with bundle ID
- Configure automatic signing in Xcode: open
(<https://developer.apple.com/programs/>).
(Membership → Team ID).
com.tanvrit.compute.portal (matches iosApp/iosApp/Info.plist).
iosApp/iosApp.xcworkspace, select the iosApp target → Signing & Capabilities → set Team to your org; Xcode will provision the certificate + profile automatically.
ExportOptions.plist
Replace APPLE_TEAM_ID in iosApp/ExportOptions.plist with the Team ID from step 2 above. Commit the change.
Entitlements
iosApp/iosApp.entitlements declares:
- Keychain access group (for session token storage).
- Associated domains (
applinks:compute.tanvrit.com) for Universal
Links. To actually enable Universal Links, also host https://compute.tanvrit.com/.well-known/apple-app-site-association with your app's appID — see Apple's docs for the format. (Not hosted yet; add when needed.)
Build + upload
# 1. Archive the Release configuration
xcodebuild -workspace iosApp/iosApp.xcworkspace \
-scheme iosApp -configuration Release \
-archivePath build/ComputePortal.xcarchive archive
# 2. Export a signed .ipa using the options plist above
xcodebuild -exportArchive \
-archivePath build/ComputePortal.xcarchive \
-exportOptionsPlist iosApp/ExportOptions.plist \
-exportPath build/ipa
# 3. Upload to App Store Connect
xcrun altool --upload-app --type ios -f build/ipa/iosApp.ipa \
--apiKey $APP_STORE_CONNECT_API_KEY_ID \
--apiIssuer $APP_STORE_CONNECT_ISSUER_ID
App Store Connect API keys are provisioned at <https://appstoreconnect.apple.com/access/api>. They replace the older username + app-specific-password flow and don't expire.
Desktop (no signing needed today)
The Compose Desktop distribution ships unsigned DMG / MSI / DEB to GitHub Releases. Users on macOS see the standard Gatekeeper warning until we enroll in the Apple Developer program and sign via codesign + notarize with xcrun notarytool. That's a follow-up.