Skip to main content

在用于 Xcode 开发的 macOS 运行器上安装 Apple 证书

您可以在 GitHub Actions 运行器上安装 Apple 代码签名证书,以在持续集成 (CI) 工作流程中对 Xcode 应用签名。

Note

GitHub Enterprise Server 目前不支持 GitHub 托管的运行器。 可以在 GitHub public roadmap 上查看有关未来支持计划的更多信息。

简介

本指南显示如何在持续集成 (CI) 工作流程中添加一个步骤,以在 GitHub Actions 运行器上安装 Apple 代码签名证书和预配配置文件。 这将允许您签署您的 Xcode 应用以发布到 Apple App Store 或分发到测试组。

先决条件

你应该熟悉 YAML 和 GitHub Actions 的语法。 有关详细信息,请参阅:

您应该了解 Xcode 应用的构建和签名。 有关详细信息,请参阅 Apple 开发人员文档

为您的证书和预配配置文件创建密码

签名过程包括存储证书和预配配置文件、将它们传输给运行器、将它们导入运行器的密钥链,以及在构建中使用它们。

要在运行器上使用您的证书和预配配置文件,我们强烈建议您使用 GitHub 密码。 有关创建机密并在工作流中使用它们的详细信息,请参阅“在 GitHub Actions 中使用机密”。

在您的仓库或组织中为下列项目创建密钥:

  • 您的 Apple 签名证书。

    • 这是你的 p12 证书文件。 有关从 Xcode 导出签名证书的详细信息,请参阅 Xcode 文档

    • 当您将证书保存为密钥时,您应该将其转换为 Base64 。 在此示例中,机密命名为 BUILD_CERTIFICATE_BASE64

    • 使用以下命令将证书转换为 Base64 并将其复制到剪贴板:

      base64 -i BUILD_CERTIFICATE.p12 | pbcopy
      
  • 您的 Apple 签名证书的密码。

    • 在此示例中,机密命名为 P12_PASSWORD
  • 您的 Apple 预配配置文件。

    • 有关从 Xcode 导出预置描述文件的详细信息,请参阅 Xcode 文档

    • 当您将预配配置文件保存为密钥时,您应该将其转换为 Base64 。 在此示例中,机密命名为 BUILD_PROVISION_PROFILE_BASE64

    • 使用以下命令将预配配置文件转换为 Base64 并将其复制到剪贴板:

      base64 -i PROVISIONING_PROFILE.mobileprovision | pbcopy
      
  • 密钥链密码。

    • 将在运行器上创建一个新的密钥链,因此新密钥链的密码可以是任何新的随机字符串。 在此示例中,机密命名为 KEYCHAIN_PASSWORD

在工作流程中添加一个步骤

此示例工作流程包括从 GitHub 密钥导入 Apple 证书和配置文件并将其安装在运行器上的步骤。

YAML
name: App build
on: push

jobs:
  build_with_signing:
    runs-on: macos-latest

    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
      - name: Install the Apple certificate and provisioning profile
        env:
          BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }}
          P12_PASSWORD: ${{ secrets.P12_PASSWORD }}
          BUILD_PROVISION_PROFILE_BASE64: ${{ secrets.BUILD_PROVISION_PROFILE_BASE64 }}
          KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
        run: |
          # create variables
          CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12
          PP_PATH=$RUNNER_TEMP/build_pp.mobileprovision
          KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db

          # import certificate and provisioning profile from secrets
          echo -n "$BUILD_CERTIFICATE_BASE64" | base64 --decode -o $CERTIFICATE_PATH
          echo -n "$BUILD_PROVISION_PROFILE_BASE64" | base64 --decode -o $PP_PATH

          # create temporary keychain
          security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
          security set-keychain-settings -lut 21600 $KEYCHAIN_PATH
          security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH

          # import certificate to keychain
          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

          # apply provisioning profile
          mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
          cp $PP_PATH ~/Library/MobileDevice/Provisioning\ Profiles
      - name: Build app
          # ...

Note

对于 iOS 生成目标,预置描述文件的扩展名应为 .mobileprovision。 对于 macOS 生成目标,扩展名应为 .provisionprofile。 应更新上述示例工作流以反映目标平台。

自托管运行器上的必要清理

GitHub 托管的运行器是孤立的虚拟机器,在作业执行结束时自动销毁。 这意味着在运行器中使用的证书和预配配置文件将在运行器完成任务后被销毁。

在自托管运行器上,$RUNNER_TEMP 目录在任务执行结束时被清除,但在运行器上可能仍然存在密钥链和预置描述文件。

如果您使用自托管的运行器, 您应该在工作流程中添加最后一步,以帮助确保这些敏感文件在作业结束时被删除。 下面显示的工作流程步骤是如何执行此操作的一个示例。

- name: Clean up keychain and provisioning profile
  if: ${{ always() }}
  run: |
    security delete-keychain $RUNNER_TEMP/app-signing.keychain-db
    rm ~/Library/MobileDevice/Provisioning\ Profiles/build_pp.mobileprovision