This post walks through the GitHub Actions release workflow I use for diff-tgz β a Rust CLI tool distributed via Homebrew. The pipeline builds for four targets (macOS arm64/x86_64, Linux arm64/x86_64), signs and notarizes the macOS binaries, publishes a GitHub release, and bumps the Homebrew tap formula automatically.
The full workflow file lives at .github/workflows/release.yml and is triggered on any tag push matching *.*.*.
Secrets you need to configure π
Before the workflow can run you have to add seven secrets in your repository settings (Settings β Secrets and variables β Actions).
APPLE_ID π
Your Apple ID email address β the one associated with your Apple Developer account.
DISTRIBUTION_CERT_BASE_64 π
A base64-encoded Developer ID Application certificate exported from Xcode.
To get it:
- Open Xcode β Settings β Accounts, select your Apple ID and click Manage Certificates.
- Right-click your Developer ID Application certificate and choose Export Certificateβ¦.
- Save it as a
.p12file and choose a strong export password (this becomesDISTRIBUTION_CERT_PASS). - Base64-encode the file:
| |
Paste the result as the secret value.
DISTRIBUTION_CERT_PASS π
The password you chose when exporting the .p12 file above.
NOTARY_TOOL_PASS π
An app-specific password for your Apple ID. Create one at appleid.apple.com under Sign-In and Security β App-Specific Passwords. This is what xcrun notarytool uses to authenticate with Apple’s notarization service.
SIGNING_IDENTITY π
The full name of your signing identity as it appears in the keychain. Run this locally to find it:
| |
It comes in the form Developer ID Application: Your Name (CERTID). Copy the whole string including the certificate type prefix.
TEAM_ID π
Your 10-character Apple Developer Team ID. You can find it in App Store Connect under Users and Access β Keys, or at developer.apple.com/account in the Membership section.
TAP_REPO_TOKEN π
A GitHub Personal Access Token with contents: write access scoped to your Homebrew tap repository. The workflow uses it to check out the tap repo and push the updated formula after each release. Create one at GitHub β Settings β Developer settings β Personal access tokens β Fine-grained tokens and grant it write access to the tap repository only.
How the workflow uses them π
Setting up the certificate keychain π
| |
This step decodes the base64 certificate back to a .p12 file, creates a temporary keychain, imports the certificate into it, and grants codesign access to the key without a GUI prompt. The keychain password (KEYCHAIN_PASS) is just a local ephemeral value used within this job β it doesn’t need to be a secret.
Storing notarytool credentials π
| |
notarytool store-credentials saves the credentials under the profile name notarytool in the keychain. Later steps reference this profile by name so the credentials never appear in plain text in the command line.
Signing and notarizing π
| |
codesign uses the --options runtime flag (-o runtime), which is required by Apple for notarization. The binary is then zipped β notarytool requires an archive β and submitted. The --wait flag blocks until Apple returns a verdict, making it easy to catch failures in the CI log.
Bumping the Homebrew tap π
The bump_homebrew job runs after the GitHub release is created. It checks out the tap repository using TAP_REPO_TOKEN, computes SHA-256 checksums for all four release archives, runs a Ruby script to update the formula, and pushes the commit back:
| |
Without TAP_REPO_TOKEN the checkout would use the default GITHUB_TOKEN, which only has access to the current repository.
Summary π
| Secret | Where to get it |
|---|---|
APPLE_ID | Your Apple ID email |
DISTRIBUTION_CERT_BASE_64 | Export from Xcode, base64 -i cert.p12 |
DISTRIBUTION_CERT_PASS | Password chosen during export |
NOTARY_TOOL_PASS | App-specific password from appleid.apple.com |
SIGNING_IDENTITY | security find-identity -v -p codesigning |
TEAM_ID | App Store Connect β Users and Access β Keys |
TAP_REPO_TOKEN | GitHub PAT with contents: write on tap repo |