Help center › CI/CD and automation

Code signing in CI builds

Import your signing certificate and provisioning profile into a temporary keychain for each job.

An unattended build can’t answer keychain prompts, so CI jobs usually put the certificate in a temporary keychain of their own. These are the steps from GitHub’s guide; they work in any CI that runs shell commands. Keep the certificate, its password and the profile in your CI’s secrets, never in the repository.

KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db
security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
security set-keychain-settings -lut 21600 $KEYCHAIN_PATH
security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH

security import $CERTIFICATE_PATH -P "$P12_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH
security set-key-partition-list -S apple-tool:,apple: -k "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
security list-keychain -d user -s $KEYCHAIN_PATH

mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
cp $PP_PATH ~/Library/MobileDevice/Provisioning\ Profiles

Clean up after every job

Your RunMac keeps its files between jobs (unlike GitHub’s own runners), so delete the keychain and profile at the end, even when the job fails:

security delete-keychain $RUNNER_TEMP/app-signing.keychain-db
rm ~/Library/MobileDevice/Provisioning\ Profiles/build_pp.mobileprovision

In GitHub Actions, put that in a final step with if: ${{ always() }}. fastlane can manage signing for you instead.

Related

Use your Mac as a GitHub Actions runnerRegister a self-hosted runner and run it as a service so it survives reboots.Use your Mac as a GitLab RunnerInstall GitLab Runner for Apple silicon, register it with the shell executor and run it as a service.Ship to TestFlight with fastlaneInstall fastlane and upload builds with an App Store Connect API key.

Still stuck?

Signed-in customers can message us from the portal; we reply within 24 hours on business days (AEST).