listless

A simple list app for Apple platforms
Log | Files | Refs | README | LICENSE

commit a18a5e59728f1e9182b392786ae8ee9dd1bdff48
parent b4aaa89c596e328a80b67443d8d19513a3fbf60c
Author: Michael Camilleri <[email protected]>
Date:   Mon,  2 Mar 2026 09:36:09 +0900

Update AGENTS.md regarding app distribution

Diffstat:
MAGENTS.md | 93++++++++++---------------------------------------------------------------------
1 file changed, 11 insertions(+), 82 deletions(-)

diff --git a/AGENTS.md b/AGENTS.md @@ -21,91 +21,20 @@ - `xcodebuild test -scheme "Listless iOS" -destination 'platform=iOS Simulator,name=iPhone 16,OS=18.6'` runs unit + UI tests. - `swift format lint --recursive .` must be clean before opening a PR. -## TestFlight Release (asc CLI) -- Use `asc` for App Store Connect/TestFlight automation. -- In this repo, `asc` auth is stored in `./.asc/config.json` (local file auth); `ASC_BYPASS_KEYCHAIN=1` is not needed for normal commands. -- In sandboxed coding-agent environments, `asc` may fail with `dial tcp: lookup api.appstoreconnect.apple.com: no such host`; this means outbound network is blocked and the command must be re-run with unrestricted network permissions. -- Listless app identifier in App Store Connect: `6759801710` (bundle ID `net.inqk.listless`). -- Internal beta group currently used: `Personal` (`bc458e15-2743-471c-a16d-c25fb88e07de`). +## TestFlight Release +- Publish scripts live in `.asc/` and handle archiving, signing, exporting, and uploading via `xcrun iTMSTransporter`. +- Signing uses a temporary keychain (created and cleaned up by the scripts) with distribution `.p12` files from `.asc/`. No login keychain unlock is required. +- App Store Connect API auth uses a `.p8` key file in `.asc/`, referenced by `$KEY_ID` from `secrets.sh`. - Build numbers come from scheme pre-action (`YEAR.COMMIT_COUNT`), so archiving from latest `HEAD` produces the latest-commit build. +- Internal testers automatically receive all builds; no explicit group assignment is needed. -### One-time auth setup -- `asc auth login --bypass-keychain --local --name "listless-asc-cli" --key-id "<KEY_ID>" --issuer-id "<ISSUER_ID>" --private-key "./Generated/AuthKey_<KEY_ID>.p8"` -- Verify: `asc apps list --limit 5 --output table` -- If auth/debug seems broken, run: `asc auth doctor` +### iOS +- Run `.asc/publish-ios.sh` from the repo root. +- Archives without code signing, then exports an IPA with manual signing (`iPhone Distribution` cert, `Listless iOS Distribution` profile). -### Temporary keychain workaround (headless signing, less-intrusive) -- Use this when export fails with `No Accounts`, missing distribution cert errors, or `errSecInternalComponent`. -- Goal: avoid changing default keychain; only add a temporary keychain to the user search list. -- Create/unlock temp keychain and import signing `.p12` identities: - - `security create-keychain -p "<PASS>" "<TMP_KEYCHAIN_PATH>"` - - `security unlock-keychain -p "<PASS>" "<TMP_KEYCHAIN_PATH>"` - - `security set-keychain-settings -lut 21600 "<TMP_KEYCHAIN_PATH>"` - - `security import "<CERT>.p12" -k "<TMP_KEYCHAIN_PATH>" -P "<P12_PASS>" -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild` - - `security set-key-partition-list -S apple-tool:,apple:,codesign:,productbuild: -s -k "<PASS>" "<TMP_KEYCHAIN_PATH>"` -- Prepend temp keychain in search list, keep login as default: - - `security list-keychains -d user -s "<TMP_KEYCHAIN_PATH>" "$HOME/Library/Keychains/login.keychain-db"` - - `security default-keychain -d user -s "$HOME/Library/Keychains/login.keychain-db"` -- After export/upload, restore normal user keychain list: - - `security list-keychains -d user -s "$HOME/Library/Keychains/login.keychain-db"` - - `security default-keychain -d user -s "$HOME/Library/Keychains/login.keychain-db"` - -### iOS TestFlight (internal group) -1. Archive iOS app from latest commit: - - `xcodebuild -scheme "Listless iOS" -project Listless.xcodeproj -configuration Release -destination 'generic/platform=iOS' -archivePath /tmp/Listless-latest.xcarchive archive` -2. Export IPA (App Store Connect method): - - Write `/tmp/Listless-ExportOptions.plist` with: - - `method=app-store-connect` - - `signingStyle=automatic` - - `teamID=7TD7PZBNXP` - - `destination=export` - - `stripSwiftSymbols=true` - - `manageAppVersionAndBuildNumber=false` - - Export: - - `xcodebuild -exportArchive -archivePath /tmp/Listless-latest.xcarchive -exportPath /tmp/Listless-export -exportOptionsPlist /tmp/Listless-ExportOptions.plist` - - IPA path: `/tmp/Listless-export/Listless iOS.ipa` -3. Upload + publish: - - `asc publish testflight --app 6759801710 --ipa '/tmp/Listless-export/Listless iOS.ipa' --group bc458e15-2743-471c-a16d-c25fb88e07de --wait --output table` -4. Notes: - - If local distribution signing is required, apply the temporary keychain workaround before `xcodebuild -exportArchive`. - - Do not pass `--notify` for this internal-group flow. - - If `publish testflight` returns `Cannot add internal group to a build`, treat it as non-fatal; verify with build beta detail (`internalBuildState`). - -### macOS TestFlight (internal group, headless) -1. Archive macOS app from latest commit: - - `xcodebuild -scheme "Listless macOS" -project Listless.xcodeproj -configuration Release -destination 'generic/platform=macOS' -archivePath /tmp/Listless-mac-latest.xcarchive archive` -2. Ensure macOS App Store signing identities exist locally: - - Required cert identities during export: - - `3rd Party Mac Developer Application` - - `3rd Party Mac Developer Installer` - - Keep `login.keychain-db` as default (less intrusive). Import certs there if needed. -3. Export App Store `.pkg`: - - Use manual export options with: - - `method=app-store-connect` - - `signingStyle=manual` - - `teamID=7TD7PZBNXP` - - `signingCertificate=3rd Party Mac Developer Application` - - `installerSigningCertificate=3rd Party Mac Developer Installer` - - `provisioningProfiles.net.inqk.listless=<MAC_APP_STORE profile name>` - - Run: - - `xcodebuild -exportArchive -archivePath /tmp/Listless-mac-latest.xcarchive -exportPath /tmp/Listless-mac-export-<TS> -exportOptionsPlist /tmp/Listless-mac-ExportOptions-<TS>.plist` - - PKG path: `/tmp/Listless-mac-export-<TS>/Listless.pkg` -4. Upload `.pkg` with Transporter CLI (`iTMSTransporter`): - - `xcrun iTMSTransporter -m upload -assetFile '/tmp/Listless-mac-export-<TS>/Listless.pkg' -apiKey '<KEY_ID>' -apiIssuer '<ISSUER_ID>' -v informational` - - Place `AuthKey_<KEY_ID>.p8` under `./private_keys/` (or one of Transporter’s default private key directories) so `-apiKey` auth resolves. -5. Known asc limitation: - - In `asc` v0.36.0, `asc builds upload --pkg` can fail with `uti` mismatch (`com.apple.installer-package-archive` vs expected `com.apple.pkg`). Prefer Transporter upload for macOS. -6. Verify internal TestFlight state: - - `asc builds find --app 6759801710 --build-number '<YEAR.COMMIT_COUNT>' --platform MAC_OS --output table` - - `asc builds build-beta-detail get --build '<BUILD_ID>' --output json --pretty` - - Success criterion: `"internalBuildState": "IN_BETA_TESTING"`. - - If key access/signing fails during export, apply the temporary keychain workaround first. - -### Verify upload/distribution state -- Latest build: `asc builds latest --app 6759801710 --output table` -- Specific build: `asc builds find --app 6759801710 --build-number "<YEAR.COMMIT_COUNT>" --output table` -- Internal state: `asc builds build-beta-detail get --build "<BUILD_ID>" --output json --pretty` -- Success criterion for internal TestFlight: `"internalBuildState": "IN_BETA_TESTING"`. +### macOS +- Run `.asc/publish-macos.sh` from the repo root. +- Archives with signing (required to preserve App Sandbox entitlements), then exports a `.pkg` with manual signing (`3rd Party Mac Developer Application` + `3rd Party Mac Developer Installer` certs, `Listless macOS Distribution` profile). ## Build Number - `CFBundleVersion` in both Info.plist files uses `$(CURRENT_PROJECT_VERSION)`, sourced from `Generated/BuildNumber.xcconfig`.