Release Agents Host¶
Agents Host is downloaded from the project's GitHub releases, outside the App Store. That
is the page the Agents window's Get Agents Host… opens. Pushing a version tag on main
publishes a release. The tag starts the release workflow, which:
- builds Agents Host with agentsd, agents-control and agents-relay inside;
- signs it with Developer ID, notarizes and staples it, as
Agents-Host-<version>.dmg; - staples the same app and zips it as
Agents-Host-<version>.zip, for Macs that may not mount a disk image; - builds the static Linux agentsd as
agentsd-linux-<arch>-<version>.tar.gz; - creates the release with these files and a
SHA256SUMS; - in its
testflightjob, archives the Mac window and the Remote (one Universal app), checks both archives withscripts/check-store-archive.sh, uploads them to TestFlight and waits until App Store Connect has processed both. Nothing goes to App Review.
The Release workflow (.agents/workflows/release.md, the release skill) does all of
this with nobody watching, every two weeks or when you press Run now: it has the
high and medium findings fixed first, chooses the version and writes the notes. The steps
below are the same thing by hand.
Before you start¶
You set this up once, as the Apple Developer account's Account Holder.
- A Developer ID Application certificate. In Xcode ▸ Settings ▸ Accounts ▸ Manage
Certificates, click + ▸ Developer ID Application. Then right-click it and choose
Export Certificate… to save it as a
.p12with a password. - The relay's profile. agents-relay reaches CloudKit, which needs a profile outside the
App Store too. In the developer site's Profiles, make a Developer ID profile for the
App ID
com.alexecollins.agents.bridge, with the certificate from step 1. Name it exactly Agents Relay Developer ID and download it. - The
releaseenvironment. In Keychain Access, under My Certificates, export Developer ID Application: … as a.p12. Then runscripts/release-secrets.sh path/to/DeveloperID.p12and delete the.p12. The script createsrelease, allows only tags matchingv*to deploy to it, and sets these secrets (or set them yourself in Settings ▸ Environments):
| Secret | Value |
|---|---|
DEVELOPER_ID_P12 |
base64 -i DeveloperID.p12 |
DEVELOPER_ID_P12_PASSWORD |
the password from step 1 |
RELAY_PROFILE |
base64 -i Agents_Relay_Developer_ID.provisionprofile |
ASC_KEY_P8 |
the App Store Connect API key's .p8, as text |
ASC_KEY_ID, ASC_ISSUER_ID |
that key's ID and its issuer ID |
- The TestFlight secrets. Export Apple Distribution: … and 3rd Party Mac
Developer Installer: … from Keychain Access as two
.p12files. Install the four App Store profiles: Agents Universal Mac App Store, Agents Remote App Store, Agents Remote Notify App Store and Agents Remote Widget App Store. Then runscripts/release-secrets.sh --store Distribution.p12 Installer.p12and delete both.p12files. It sets:
| Secret | Value |
|---|---|
APPLE_DISTRIBUTION_P12, APPLE_DISTRIBUTION_P12_PASSWORD |
the Apple Distribution identity and its password |
MAC_INSTALLER_P12, MAC_INSTALLER_P12_PASSWORD |
the 3rd Party Mac Developer Installer identity and its password |
PROFILE_UNIVERSAL_MAC |
base64 of "Agents Universal Mac App Store" |
PROFILE_REMOTE |
base64 of "Agents Remote App Store" |
PROFILE_REMOTE_NOTIFY |
base64 of "Agents Remote Notify App Store" |
PROFILE_REMOTE_WIDGET |
base64 of "Agents Remote Widget App Store" |
Without them the GitHub release still goes out, and the testflight job fails at its
first step, naming the secrets that are missing.
Steps¶
- Choose the version, for example
0.2.0: minor when an enhancement merged since the last tag, otherwise patch..agents/skills/release/scripts/release-plan.pysays which, and lists the merged pull requests. The build number is the workflow's run number, so it always goes up. - Tag main and push the tag. The tag's message becomes the release notes; a tag without one gets notes made from the merged pull requests:
git tag -a --cleanup=verbatim v0.2.0 origin/main -F notes.md
git push origin v0.2.0
- Follow the release run in the repository's Actions. The Linux job takes about ten minutes. The Mac job takes longer, mostly waiting for Apple's notary.
- When it finishes, the release is on the Releases page as Agents Host 0.2.0, and
0.2.0 (the run number) is on TestFlight for iOS and macOS.
swift scripts/asc-builds.swift 0.2.0 <run number>says each build's state.
To make a release again from a tag that is already there (after fixing a secret, say), run the release workflow by hand and give it the tag. It replaces the release's files.
Build one on this Mac¶
scripts/release-host.sh 0.2.0 does what the workflow's Mac job does. It needs the
Developer ID identity in your keychain, the relay's profile installed, and ASC_KEY_ID,
ASC_ISSUER_ID and ASC_KEY_PATH set. It needs the Linux agentsd in App/Resources/servers,
from scripts/build-linux-agentsd.sh.
scripts/release-host.sh --dry-run 0.2.0 needs none of that. It signs ad hoc and doesn't
notarize, which proves the build and the packaging. Gatekeeper refuses the result.
scripts/release-store.sh 0.2.0 <build> does what the testflight job does. It needs the
two identities and the four profiles, and the App Store Connect key in ~/.private_keys.
--no-upload stops before the upload. --dry-run needs no certificate: it proves both
archives build and pass check-store-archive.sh.
If something goes wrong¶
- "is not on main": the tag points at a commit main doesn't have. Delete the tag
(
git push origin :refs/tags/v0.2.0), then tag a commit on main. - No "Developer ID Application" identity:
DEVELOPER_ID_P12or its password is wrong. - The notary refuses it: the run's log has the submission ID. Run
xcrun notarytool log <id> --key … --key-id … --issuer …to see why. - "The release environment has no …": a TestFlight secret is missing. Run
scripts/release-secrets.sh --store …, then run the release workflow again with the tag. - An upload is refused as a duplicate: that build number is taken for the version. Run the workflow again: the new run number is a new build.