Contribute
Releasing the Mac app
For maintainers. A release is a DMG people drag into Applications plus a signed update bundle that installed apps fetch themselves, built by one GitHub Actions workflow.
Cut a release#
Set the version in
packages/desktop/src-tauri/tauri.conf.json(and the package manifests) to a plainMAJOR.MINOR.PATCH, add a section toCHANGELOG.md, and commit.Tag that commit with the same version and push the tag:
git tag v0.2.0 git push origin v0.2.0.github/workflows/release.ymlbuilds on a macOS runner. It refuses a tag that does not match the app version, then publishes to the GitHub Release:File What it is One-Connect-macOS-arm64.dmgThe installer One-Connect-macOS-arm64.app.tar.gzand.sigThe signed update bundle SHA256SUMS.txtChecksums of every file latest.jsonon theupdatesreleaseThe feed installed apps poll every six hours
To try a build without publishing, run the workflow from the Actions tab on a branch; the files are kept as a workflow artifact. Running it on a tag with pre-release checked publishes a GitHub pre-release without updating the feed, so existing installs are never offered preview builds.
Locally, pnpm desktop:dmg builds the app and DMG. macOS asks once to let the terminal control Finder, which lays out the DMG window.
What the secrets unlock#
All secrets are optional.
| Secret | Without it | With it |
|---|---|---|
APPLE_CERTIFICATE, APPLE_CERTIFICATE_PASSWORD | Ad-hoc signed: macOS blocks the first launch until the user chooses Open Anyway | Signed with your Developer ID and the hardened runtime |
APPLE_API_KEY, APPLE_API_ISSUER, APPLE_API_KEY_P8 | Not notarized | The app and DMG are notarized and stapled, so they open without a warning, even offline |
TAURI_SIGNING_PRIVATE_KEY (and optional _PASSWORD) | No update bundle or feed | Installed apps offer Restart to update |
APPLE_SIGNING_IDENTITY | Read from the certificate | Pins one identity when the certificate holds several |
Set up the Apple secrets#
Join the Apple Developer Program as an individual or organization.
In Xcode → Settings → Accounts, or at developer.apple.com → Certificates, create a Developer ID Application certificate. In Keychain Access, export it with its private key as a
.p12file with a password.At App Store Connect → Users and Access → Integrations → App Store Connect API, create a key with the Developer role. Download the
.p8file (it downloads only once) and note the key ID and issuer ID.Add the secrets from your own terminal:
base64 -i DeveloperID.p12 | gh secret set APPLE_CERTIFICATE gh secret set APPLE_CERTIFICATE_PASSWORD gh secret set APPLE_API_KEY --body "<key ID>" gh secret set APPLE_API_ISSUER --body "<issuer ID>" gh secret set APPLE_API_KEY_P8 < AuthKey_XXXXXXXXXX.p8
The updater key#
The app ships the updater's public key (plugins.updater.pubkey in tauri.conf.json) and accepts only update bundles signed by the matching private key. Upload the private key once:
gh secret set TAURI_SIGNING_PRIVATE_KEY < ~/.tauri/one-connect-updater.keyWarning
Back the private key up somewhere safe, such as a password manager. If it is lost, installed apps can never be updated again, and users would have to download the next version by hand. To rotate it, ship one release signed with the old key whose configuration carries the new public key.
Notes#
- Releases are Apple silicon only. An Intel or universal build needs
--target universal-apple-darwinand both Rust targets. - The bundle identifier
dev.agentcontrolcenter.desktopis bound into notarization, the update feed and the app-data folder. Keep it, or change it before the first signed release. - The engine's only native binary is the bundled Node.js runtime, already signed by the Node.js project.
The website#
The website and these docs are built and published from the separate one-connect-website repository.