action.yaml 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. name: Set up macOS codesigning
  2. description: Sets up code signing certificates, provisioning profiles, and notarization information
  3. inputs:
  4. codesignIdentity:
  5. description: Codesigning identity
  6. required: true
  7. installerIdentity:
  8. description: Codesigning identity for package installer
  9. required: false
  10. codesignCertificate:
  11. description: PKCS12 certificate in base64 format
  12. required: true
  13. certificatePassword:
  14. description: Password required to install PKCS12 certificate
  15. required: true
  16. keychainPassword:
  17. description: Password to use for temporary keychain
  18. required: false
  19. notarizationUser:
  20. description: Apple ID to use for notarization
  21. required: false
  22. notarizationPassword:
  23. description: Application password for notarization
  24. provisioningProfile:
  25. description: Provisioning profile in base64 format
  26. required: false
  27. outputs:
  28. haveCodesignIdent:
  29. description: True if necessary codesigning credentials were found
  30. value: ${{ steps.codesign.outputs.haveCodesignIdent }}
  31. haveProvisioningProfile:
  32. description: True if necessary provisioning profile credentials were found
  33. value: ${{ steps.provisioning.outputs.haveProvisioningProfile || steps.codesign.outputs.haveProvisioningProfile }}
  34. provisioningProfileUUID:
  35. description: UUID of imported provisioning profile
  36. value: ${{ steps.provisioning.outputs.provisioningProfileUUID }}
  37. haveNotarizationUser:
  38. description: True if necessary notarization credentials were found
  39. value: ${{ steps.notarization.outputs.haveNotarizationUser || steps.codesign.outputs.haveNotarizationUser }}
  40. codesignIdent:
  41. description: Codesigning identity
  42. value: ${{ steps.codesign.outputs.codesignIdent }}
  43. installerIdent:
  44. description: Codesigning identity for package installer
  45. value: ${{ steps.codesign.outputs.installerIdent }}
  46. codesignTeam:
  47. description: Codesigning team
  48. value: ${{ steps.codesign.outputs.codesignTeam }}
  49. runs:
  50. using: composite
  51. steps:
  52. - name: Check Runner Operating System 🏃‍♂️
  53. if: runner.os != 'macOS'
  54. shell: bash
  55. run: |
  56. : Check Runner Operating System 🏃‍♂️
  57. echo "setup-macos-codesigning action requires a macOS-based runner."
  58. exit 2
  59. - name: macOS Codesigning ✍️
  60. shell: zsh --no-rcs --errexit --pipefail {0}
  61. id: codesign
  62. env:
  63. MACOS_SIGNING_IDENTITY: ${{ inputs.codesignIdentity }}
  64. MACOS_SIGNING_IDENTITY_INSTALLER: ${{ inputs.installerIdentity}}
  65. MACOS_SIGNING_CERT: ${{ inputs.codesignCertificate }}
  66. MACOS_SIGNING_CERT_PASSWORD: ${{ inputs.certificatePassword }}
  67. MACOS_KEYCHAIN_PASSWORD: ${{ inputs.keychainPassword }}
  68. run: |
  69. : macOS Code Signing ✍️
  70. if (( ${+RUNNER_DEBUG} )) setopt XTRACE
  71. if [[ ${MACOS_SIGNING_IDENTITY} && ${MACOS_SIGNING_IDENTITY_INSTALLER} && ${MACOS_SIGNING_CERT} ]] {
  72. print 'haveCodesignIdent=true' >> $GITHUB_OUTPUT
  73. local -r certificate_path="${RUNNER_TEMP}/build_certificate.p12"
  74. local -r keychain_path="${RUNNER_TEMP}/app-signing.keychain-db"
  75. print -n "${MACOS_SIGNING_CERT}" | base64 --decode --output=${certificate_path}
  76. : "${MACOS_KEYCHAIN_PASSWORD:="$(print ${RANDOM} | shasum | head -c 32)"}"
  77. print '::group::Keychain setup'
  78. security create-keychain -p "${MACOS_KEYCHAIN_PASSWORD}" ${keychain_path}
  79. security set-keychain-settings -lut 21600 ${keychain_path}
  80. security unlock-keychain -p "${MACOS_KEYCHAIN_PASSWORD}" ${keychain_path}
  81. security import "${certificate_path}" -P "${MACOS_SIGNING_CERT_PASSWORD}" -A \
  82. -t cert -f pkcs12 -k ${keychain_path} \
  83. -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/xcrun
  84. security set-key-partition-list -S 'apple-tool:,apple:' -k "${MACOS_KEYCHAIN_PASSWORD}" \
  85. ${keychain_path} &> /dev/null
  86. security list-keychain -d user -s ${keychain_path} 'login-keychain'
  87. print '::endgroup::'
  88. local -r team_id="${${MACOS_SIGNING_IDENTITY##* }//(\(|\))/}"
  89. print "codesignIdent=${MACOS_SIGNING_IDENTITY}" >> $GITHUB_OUTPUT
  90. print "installerIdent=${MACOS_SIGNING_IDENTITY_INSTALLER}" >> $GITHUB_OUTPUT
  91. print "MACOS_KEYCHAIN_PASSWORD=${MACOS_KEYCHAIN_PASSWORD}" >> $GITHUB_ENV
  92. print "codesignTeam=${team_id}" >> $GITHUB_OUTPUT
  93. } else {
  94. print 'haveCodesignIdent=false' >> $GITHUB_OUTPUT
  95. print 'haveProvisioningProfile=false' >> $GITHUB_OUTPUT
  96. print 'haveNotarizationUser=false' >> $GITHUB_OUTPUT
  97. }
  98. - name: Provisioning Profile 👤
  99. shell: zsh --no-rcs --errexit --pipefail {0}
  100. id: provisioning
  101. if: ${{ fromJSON(steps.codesign.outputs.haveCodesignIdent) }}
  102. env:
  103. MACOS_SIGNING_PROVISIONING_PROFILE: ${{ inputs.provisioningProfile }}
  104. run: |
  105. : Provisioning Profile 👤
  106. if (( ${+RUNNER_DEBUG} )) setopt XTRACE
  107. if [[ "${MACOS_SIGNING_PROVISIONING_PROFILE}" ]] {
  108. print 'haveProvisioningProfile=true' >> $GITHUB_OUTPUT
  109. local -r profile_path="${RUNNER_TEMP}/build_profile.provisionprofile"
  110. print -n "${MACOS_SIGNING_PROVISIONING_PROFILE}" \
  111. | base64 --decode --output="${profile_path}"
  112. print '::group::Provisioning Profile Setup'
  113. mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
  114. security cms -D -i ${profile_path} -o ${RUNNER_TEMP}/build_profile.plist
  115. local -r uuid="$(plutil -extract UUID raw ${RUNNER_TEMP}/build_profile.plist)"
  116. local -r team_id="$(plutil -extract TeamIdentifier.0 raw -expect string ${RUNNER_TEMP}/build_profile.plist)"
  117. if [[ ${team_id} != '${{ steps.codesign.outputs.codesignTeam }}' ]] {
  118. print '::notice::Code Signing team in provisioning profile does not match certificate.'
  119. }
  120. cp ${profile_path} ~/Library/MobileDevice/Provisioning\ Profiles/${uuid}.provisionprofile
  121. print "provisioningProfileUUID=${uuid}" >> $GITHUB_OUTPUT
  122. print '::endgroup::'
  123. } else {
  124. print 'haveProvisioningProfile=false' >> $GITHUB_OUTPUT
  125. }
  126. - name: Notarization 🧑‍💼
  127. id: notarization
  128. if: fromJSON(steps.codesign.outputs.haveCodesignIdent)
  129. shell: zsh --no-rcs --errexit --pipefail {0}
  130. env:
  131. MACOS_NOTARIZATION_USERNAME: ${{ inputs.notarizationUser }}
  132. MACOS_NOTARIZATION_PASSWORD: ${{ inputs.notarizationPassword }}
  133. run: |
  134. : Notarization 🧑‍💼
  135. if (( ${+RUNNER_DEBUG} )) setopt XTRACE
  136. if [[ ${MACOS_NOTARIZATION_USERNAME} && ${MACOS_NOTARIZATION_PASSWORD} ]] {
  137. print 'haveNotarizationUser=true' >> $GITHUB_OUTPUT
  138. } else {
  139. print 'haveNotarizationUser=false' >> $GITHUB_OUTPUT
  140. }