2026-06-25 19:30:58 -07:00
|
|
|
# TestFlight Release CI
|
|
|
|
|
|
|
|
|
|
Gitea Actions publishes iOS releases from tags that match:
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
release/vN.N.N
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
For example:
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
git tag release/v1.10.0
|
|
|
|
|
git push origin release/v1.10.0
|
|
|
|
|
```
|
|
|
|
|
|
2026-06-25 22:12:17 -07:00
|
|
|
The release job runs on the `xcode` runner label, creates the runner user's
|
|
|
|
|
login keychain from Gitea secrets, makes that keychain the user default for the
|
2026-06-25 21:44:42 -07:00
|
|
|
duration of the job, installs the App Store provisioning profile in both the
|
|
|
|
|
legacy MobileDevice directory and the Xcode UserData directory used by newer
|
|
|
|
|
Xcode releases, builds and uploads the app with fastlane, then creates or
|
|
|
|
|
updates the matching Gitea release with the generated IPA as an asset. The job
|
2026-06-25 22:12:17 -07:00
|
|
|
restores the previous user default keychain and deletes the user login keychain
|
|
|
|
|
and installed profiles in an `always()` cleanup step. No signing material is
|
|
|
|
|
installed into the system keychain.
|
2026-06-25 19:30:58 -07:00
|
|
|
|
|
|
|
|
Required repository secrets:
|
|
|
|
|
|
|
|
|
|
```text
|
2026-06-25 20:51:01 -07:00
|
|
|
APP_STORE_CONNECT_API_KEY_ID
|
|
|
|
|
APP_STORE_CONNECT_API_ISSUER_ID
|
|
|
|
|
APP_STORE_CONNECT_API_KEY_CONTENT
|
2026-06-25 19:30:58 -07:00
|
|
|
APPSTORE_CERTIFICATES_FILE_BASE64
|
|
|
|
|
APPSTORE_CERTIFICATES_PASSWORD
|
2026-06-25 20:51:01 -07:00
|
|
|
APPSTORE_PROVISIONING_PROFILE_BASE64
|
2026-06-25 19:30:58 -07:00
|
|
|
```
|
|
|
|
|
|
2026-06-25 20:51:01 -07:00
|
|
|
Generate or refresh the signing assets locally with:
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
cd ios
|
|
|
|
|
fastlane ios create_ci_signing
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
The generated `build/signing/ci-secrets.env` file is ignored by Git. Copy its
|
|
|
|
|
certificate and provisioning profile values into the repository secrets listed
|
|
|
|
|
above. The workflow uses the `Sybil AppStore CI` provisioning profile name by
|
|
|
|
|
default.
|
|
|
|
|
|
2026-06-25 21:25:13 -07:00
|
|
|
Fastlane keeps two signing names separate. `SYBIL_CODE_SIGN_IDENTITY` is the
|
|
|
|
|
exact certificate common name used when exporting a local p12 for secrets, while
|
2026-06-25 22:10:06 -07:00
|
|
|
`SYBIL_XCODE_CODE_SIGN_IDENTITY` defaults to the certificate SHA-1 fingerprint
|
|
|
|
|
that Xcode uses during archive. `SYBIL_EXPORT_SIGNING_CERTIFICATE` defaults to
|
|
|
|
|
the generic `Apple Distribution` selector used in the export options.
|
2026-06-25 21:25:13 -07:00
|
|
|
|
2026-06-25 21:44:42 -07:00
|
|
|
The Release signing settings are also present in `Apps/Sybil/project.yml` so
|
|
|
|
|
XcodeGen emits a manually signed App Store archive configuration. CI passes the
|
|
|
|
|
installed provisioning profile UUID to Fastlane as
|
|
|
|
|
`SYBIL_PROVISIONING_PROFILE_UUID`; Fastlane writes that UUID into the generated
|
2026-06-25 22:02:19 -07:00
|
|
|
project before archiving. CI also passes the temporary keychain path as
|
|
|
|
|
`CODE_SIGN_KEYCHAIN` so Xcode searches the disposable keychain for the imported
|
|
|
|
|
Distribution identity.
|
2026-06-25 21:44:42 -07:00
|
|
|
|
2026-06-25 21:03:43 -07:00
|
|
|
If the Apple team has reached the Distribution certificate limit, set
|
|
|
|
|
`SYBIL_SIGNING_CERTIFICATE_ID` to the portal id for a certificate whose private
|
|
|
|
|
key exists in the local login keychain before running `create_ci_signing`. The
|
|
|
|
|
lane will export the local identity and create the provisioning profile against
|
|
|
|
|
that existing certificate instead of creating another Distribution certificate.
|
|
|
|
|
|
2026-06-25 20:51:01 -07:00
|
|
|
If `create_ci_signing` fails with an expired or missing agreement error, the
|
|
|
|
|
Apple Developer Program account holder must accept the current agreements in
|
|
|
|
|
App Store Connect before new certificates or provisioning profiles can be
|
|
|
|
|
created through the API.
|
|
|
|
|
|
2026-06-25 19:30:58 -07:00
|
|
|
The workflow uses Gitea's built-in `GITEA_TOKEN` for release creation and asset
|
|
|
|
|
upload, with `contents: write` permissions. In Gitea this covers release asset
|
|
|
|
|
publication.
|