Codesign and notarize macOS/iOS artifacts on a self-hosted mac runner: ephemeral keychain, hardened-runtime sign, notarytool, guaranteed teardown.
  • Shell 88.7%
  • Makefile 11.3%
Find a file
Stephen Way fc3c3daf8c
All checks were successful
test / unit (push) Successful in 21s
Initial release: apple-codesign-action
Codesign and optionally notarize macOS/iOS artifacts on a self-hosted
mac runner. Throwaway keychain per run, hardened-runtime signing,
notarytool submit + wait, optional staple, and guaranteed keychain
teardown in the post step (even on failure or cancel).

Lifts the keychain/codesign/notarytool logic that mac release pipelines
hand-roll (e.g. fj's release.yml) into one reusable action. Composite,
mac-only. Offline suite asserts the command flow against faked Apple
tooling; the real signing path runs on a mac runner with a real identity.
2026-06-01 18:35:54 -07:00
.forgejo/workflows Initial release: apple-codesign-action 2026-06-01 18:35:54 -07:00
scripts Initial release: apple-codesign-action 2026-06-01 18:35:54 -07:00
tests Initial release: apple-codesign-action 2026-06-01 18:35:54 -07:00
.gitignore Initial release: apple-codesign-action 2026-06-01 18:35:54 -07:00
action.yml Initial release: apple-codesign-action 2026-06-01 18:35:54 -07:00
CHANGELOG.md Initial release: apple-codesign-action 2026-06-01 18:35:54 -07:00
LICENSE Initial release: apple-codesign-action 2026-06-01 18:35:54 -07:00
Makefile Initial release: apple-codesign-action 2026-06-01 18:35:54 -07:00
README.md Initial release: apple-codesign-action 2026-06-01 18:35:54 -07:00

Apple Codesign

Sign and notarize on hardware you own. Codesign and (optionally) notarize macOS/iOS artifacts on a self-hosted mac runner, with a throwaway keychain that never leaks your signing identity beyond the run. The signing cert never goes to a hosted service.

Part of the Fjord Actions bundle. This lifts the keychain-import + codesign + notarytool dance that every mac release pipeline hand-rolls into one reusable, self-cleaning step.

Usage

jobs:
  release:
    runs-on: macos        # your self-hosted mac runner
    steps:
      - uses: actions/checkout@v6
      - run: cargo build --release      # or xcodebuild, etc. -> produces the artifact

      - uses: https://rasterhub.com/rasterstate/apple-codesign-action@v1
        with:
          certificate-p12-base64: ${{ secrets.MACOS_CERT_P12_BASE64 }}
          certificate-password:   ${{ secrets.MACOS_CERT_PASSWORD }}
          signing-identity: 'Developer ID Application: Acme LLC (TEAMID)'
          paths: |
            target/release/myapp
          options: runtime
          notarize: true
          apple-api-key-base64: ${{ secrets.APPLE_API_KEY_BASE64 }}
          apple-api-key-id:     ${{ secrets.APPLE_API_KEY_ID }}
          apple-api-issuer:     ${{ secrets.APPLE_API_ISSUER }}
          staple: false          # staple .app/.dmg/.pkg; a bare binary can't be stapled

The keychain is created in RUNNER_TEMP, used for the signing, and always deleted in the post step, even if signing fails or the job is cancelled.

Inputs

Input Default Description
certificate-p12-base64 (required) Base64 of the signing .p12.
certificate-password (required) Password for the .p12.
signing-identity (required) codesign identity, e.g. Developer ID Application: Acme LLC (TEAMID).
paths (required) Artifacts to sign, one per line.
keychain-password generated Password for the ephemeral keychain.
options runtime codesign --options value. Empty to omit.
entitlements Path to an entitlements plist.
timestamp true Add a secure timestamp.
deep false --deep (Apple discourages it).
verify true codesign --verify after signing.
notarize false Submit to Apple notary and wait.
apple-api-key-base64 / apple-api-key-id / apple-api-issuer App Store Connect API key (required when notarize).
staple false Staple the ticket (for .app/.dmg/.pkg).

Requirements

A self-hosted mac runner with Xcode command-line tools (codesign, security, xcrun notarytool). There is no GitHub-hosted equivalent that lets you bring your own signing trust to a runner you control, that's the point.

Notes

  • Bare binaries can't be stapled (only .app/.dmg/.pkg carry a ticket). Notarization still validates a bare binary; just leave staple: false.
  • The cert and the App Store Connect key are written to RUNNER_TEMP, used, and removed; the keychain is removed in the post step. On an ephemeral per-job mac VM that's belt-and-suspenders, on a long-lived runner it's essential.

License

MIT, see LICENSE.