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#

  1. Set the version in packages/desktop/src-tauri/tauri.conf.json (and the package manifests) to a plain MAJOR.MINOR.PATCH, add a section to CHANGELOG.md, and commit.

  2. Tag that commit with the same version and push the tag:

    git tag v0.2.0
    git push origin v0.2.0
  3. .github/workflows/release.yml builds on a macOS runner. It refuses a tag that does not match the app version, then publishes to the GitHub Release:

    FileWhat it is
    One-Connect-macOS-arm64.dmgThe installer
    One-Connect-macOS-arm64.app.tar.gz and .sigThe signed update bundle
    SHA256SUMS.txtChecksums of every file
    latest.json on the updates releaseThe 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.

SecretWithout itWith it
APPLE_CERTIFICATE, APPLE_CERTIFICATE_PASSWORDAd-hoc signed: macOS blocks the first launch until the user chooses Open AnywaySigned with your Developer ID and the hardened runtime
APPLE_API_KEY, APPLE_API_ISSUER, APPLE_API_KEY_P8Not notarizedThe 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 feedInstalled apps offer Restart to update
APPLE_SIGNING_IDENTITYRead from the certificatePins one identity when the certificate holds several

Set up the Apple secrets#

  1. Join the Apple Developer Program as an individual or organization.

  2. 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 .p12 file with a password.

  3. At App Store Connect → Users and Access → Integrations → App Store Connect API, create a key with the Developer role. Download the .p8 file (it downloads only once) and note the key ID and issuer ID.

  4. 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.key

Warning

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-darwin and both Rust targets.
  • The bundle identifier dev.agentcontrolcenter.desktop is 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.

Edit this page on GitHub