Flutter中文网

Flutter中文网

用Codemagic CLI和GitHub Actions把Flutter应用部署到App Store Connect

24
2024-07-15

打包、签名和发布移动应用的过程非常繁琐且耗时,尤其是在大型团队中,而且还要将包分发给测试。这就是为什么Codemagic提供了一个基于云的移动应用CI/CD服务,可以自动化整个工作流程,而无需花费太多时间和精力进行配置。但如果您想在本地或其他CI/CD环境中(如GitHub Actions)使用Codemagic的功能,那么Codemagic CLI工具就派上用场了。

Codemagic CLI工具是用来做什么的?

Codemagic CLI是Codemagic用来运行其CI/CD服务的一组免费和开源的命令行工具。它们可以简化与移动应用开发相关的各种任务,如构建、代码签名和发布。无论你使用的是什么框架或技术,都可以在任何iOS或Android项目中使用它们。由于它们不断地通过Codemagic团队及其他公司的贡献者进行改进,因此它们的文档非常完善并始终保持最新状态。

Codemagic CLI工具的一个关键优势在于其平台无关性,可以在多个操作系统上使用。其支持范围涵盖iOS和Android平台,无需为不同的应用商店使用不同的工具。与需要大量配置的fastlane不同,Codemagic CLI工具旨在简单易用,因此无论是初学者还是经验丰富的开发人员都可以轻松上手。

在本文中,我将向您展示如何使用Codemagic CLI工具与GitHub Actions一起将您的Flutter应用程序部署到App Store Connect。您将学习如何:

  • 为App Store Connect生成一个API密钥。

  • 创建一个GitHub Actions工作流,运行Codemagic CLI工具并上传您的包到App Store Connect。

  • 在本地机器上安装并使用Codemagic CLI工具。

通过按照这些步骤操作,您可以简化应用程序分发流程,节省时间和资源。此外,您还可以使用Codemagic CLI工具执行其他任务,例如版本控制或注册新的测试设备。

在App Store Connect中进行设置

在深入探讨技术细节之前,有必要确认一些先决条件。我假设你已经加入了苹果开发者计划,拥有注册的bundle ID,并且在App Store Connect中已经有一个现成的Flutter应用。如果不是,请确保在继续前进之前将所有事宜都安排好。

为App Store Connect生成一个API密钥

在本文的这一部分,我将向您演示如何为 App Store Connect 生成 API 密钥。此密钥非常重要,因为它赋予了 Codemagic CLI 工具上传您的应用程序到 App Store Connect 所需的权限。

为了确保Codemagic CLI工具能够上传和从App Store Connect中获取数据,您需要使用App Manager权限生成一个App Store Connect API密钥。

  1. 登录App Store Connect,然后导航至“用户和访问权限”>“集成”。

  2. 点击“生成新API密钥”按钮以生成新的API密钥。

  3. 请输入密钥名称,并选择访问级别。选择“应用程序管理器”访问权限。

  4. 一旦生成密钥,您就会看到它被添加到活跃密钥列表中。点击“下载API密钥”保存私钥以备将来使用。请注意,密钥只能下载一次。

App Store Connect生成新的API密钥

请记录下活跃密钥表格上方的发行者ID(Issuer ID)以及生成的密钥的密钥ID(Key ID),因为在设置你的流水线(pipeline)时会需要这些信息。

记录下活跃密钥表格上方的发行者ID(Issuer ID)和密钥ID(Key ID)

创建环境

在这个部分,你将学习如何设置我们稍后建立流水线所需要的必要环境变量和secrets

在继续之前,请确保您已按照本文前面的步骤操作,并且应用程序记录和代码之间完全匹配。例如,如果bundle ID不匹配,可能会导致意想不到且难以调试的场景。幸运的是,CLI工具已减轻了一些潜在的痛点。

配置密钥和变量

要在 GitHub Actions中使用Codemagic CLI工具,您需要在GitHub存储库中配置一些环境变量和secrets。环境变量是可由工作流步骤访问的纯文本值。secrets是加密值,仅供您和需要它们的工作流步骤查看。您应该使用secrets存储敏感信息,例如密码、密钥或证书。

要在您的存储库中添加新的密钥和变量,您可以导航到“设置”>“密钥和变量”,然后分别在“密钥”和“变量”选项卡中创建新的值。

要继续学习,您需要设置以下变量:

  • APP_STORE_CONNECT_ISSUER_ID你可以在苹果开发者门户的活跃API密钥表中找到它,如前文所述(例如,它是一个小写字母数字组合,如 aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee )。

  • APP_STORE_CONNECT_KEY_IDENTIFIER这是你在上一节中创建的API密钥的ID。你可以在Apple Developer门户中找到它,它位于密钥名称的旁边,并且也应该包含在密钥文件名中(例如, ABC1234567 是一个大写字母和数字的10位值)。

  • APP_STORE_APP_ID这是你在 App Store Connect 中应用的 App ID。你可以通过在 App Store Connect 门户中选择你的应用并查看“通用”>“应用信息”部分来找到它(它是一个 10 位数的数字,例如  0123456789 )。

你应该在GitHub的用户界面上看到类似这样的内容:

GitHub的用户界面

除了上述设置的变量外,我们还需要设置所需的密钥。首先,导航至“密钥”标签页,创建以下密钥:

  • APP_STORE_CONNECT_PRIVATE_KEY这是你在前文下载的API密钥文件的内容。它是一个以.p8为扩展名的文本文件,以-----BEGIN PRIVATE KEY-----开始,以-----END PRIVATE KEY-----结束。你可以直接复制粘贴文件内容到secret字段中。同样,你可以在终端使用以下命令来复制内容到剪切板:

    cat /path/to/api/key/AuthKey_XXXYYYZZZ.p8 | pbcopy
    

现在,我们有两种方式来为我们的应用设置代码签名:我们可以让Codemagic CLI工具为我们处理,或者我们可以自行配置(如果你已经手头有相关证书)。我将为你介绍如何进行这两种设置。

自动证书和配置文件生成

如果你想使用现有的代码签名证书和配置文件,可以直接跳到下一节“使用现有证书和配置文件”。

然而,如果您想使用自动代码签名功能,则需要创建并提供一个证书私钥和一个App Store Connect API密钥给Codemagic CLI工具。该证书私钥是一个2048位RSA密钥,将包含在Codemagic创建的证书中。App Store Connect API密钥与上述变量中使用的相同。Codemagic生成的文件将在App Store Connect中可用。

除了上述的变量和secret集之外,我们还需要在“Secrets”选项中设置一个额外的secret

  • CERTIFICATE_PRIVATE_KEY:这是您需要生成的证书私钥的内容。您可以使用以下终端命令创建一个新的密钥并将其保存为一个名为“ cert_key ”的文件:

    ssh-keygen -t rsa -b 2048 -m PEM -f cert_key -q -N ""
    

    在创建密钥之后,您需要将文件的内容复制并粘贴到“secret”字段中。您可以使用以下终端命令将内容复制到剪贴板中:

    cat cert_key | pbcopy
    

设置完所有必要的密钥后,您应该在界面中看到类似以下的内容:

使用现有的证书和配置文件

如果你已经有现有的分发代码签名文件,并且想继续使用它们,可以跳过前面步骤中提到的生成证书私钥的过程,并将证书、配置文件和密码作为额外的机密信息存储在GitHub存储库中。请确保使用的是分发证书,并且配置文件中包含该证书,否则管道将无法正常运行。

为了使用现有的代码签名文件,除了在“配置密钥和变量”步骤中显示的 APP_STORE_CONNECT_PRIVATE_KEY 密钥外,还需要创建以下密钥:

  • DIST_CERTIFICATE:这是你的分发证书文件的内容,它是一个以.p12为扩展名的二进制文件。你需要对文件内容进行base64编码,然后将其复制到secret字段。base64编码是一种将二进制数据转换为可以轻松传输和存储的文本数据的方式。你可以使用图形化工具或者终端命令进行base64编码。例如,在macOS上,你可以使用以下终端命令来base64编码文件,并将其复制到你的剪贴板:

    base64 -i <cert_name>.p12 | pbcopy
  • DIST_CERTIFICATE_PASSWORD:这是您分发证书文件的密码。这是您在使用 Keychain Access 导出证书或使用终端命令创建证书时输入的文本值。您可以直接将密码复制并粘贴到“secret”字段中。

  • DIST_PROFILE:这是你的分发配置文件的内容,它是一个以.mobileprovision为扩展名的二进制文件。你需要对文件内容进行base64编码,并将其复制到秘密值字段。你可以使用与证书文件相同的方法来对配置文件进行base64编码和复制。

    base 64 -i <profile_name>.mobileprovision | pbcopy
    

设置完所有必要的密钥后,您应该在界面中看到类似以下的内容:

设置完所有必要的密钥后的界面

建立GitHub Actions流水线

在本节中,您将学习如何使用 GitHub Actions 来自动化 Flutter 应用程序的构建,并使用 Codemagic CLI 工具将应用程序上传到 App Store Connect。

请将自己的 YAML 文件保存在项目的  .github/workflows/  目录中,并确保文件扩展名为  .yaml .

GitHub Actions 已经预先安装了 Python。如前所述,对于 Codemagic CLI 工具,需要 Python 3.7 或更高版本。您可以使用“setup-python”动作来安装特定版本的 Python。

此外,正如之前所说,在我们的管道中也有两种设置方式:自动生成代码签名文件,或者使用现有的签名凭据。无论哪种方式,YAML结构和命令都是相似的,我会分别给出示例和完整的管道示例。

这是一个简单的GitHub Actions YAML文件,它会输出  Hello world! 

name: Hello World Workflow
on: [push]
jobs:
  build:
    runs-on: ubuntu-latest
  steps:
    - name: Echo Hello World
      run: echo "Hello, World!"

该工作流会在对存储库进行任何推送操作时触发,并在最新的Ubuntu环境中运行( ubuntu-latest )。

然而,我们需要对某些东西进行修改,以便让一切正常运行。首先,出于测试目的,我们将把工作流设置为手动触发( workflow_dispatch )。我们还需要设置管道,以便使用我们之前配置的环境变量和密钥与 App Store Connect 交互并为应用程序签名。

因此,要构建和部署您的iOS应用程序,您需要对YAML文件进行以下更改和/或添加:

  1. 你需要从你的仓库中获取代码:使用“actions/checkout@v4”动作将你的仓库内容检出到runner上:

    - uses: actions/checkout@v4
  2. 更改机器配置,否则流水线将无法正确编译您的应用程序:将“runs-on”更改为使用“ mac-latest ”:

    runs-on: mac-latest
    
  3. 安装 Flutter:使用 Subosito 提供的Flutter action就好。我们将使用稳定版本,但可以选择特定版本或其他渠道:

    - name: Set up Flutter
      uses: subosito/flutter-action@v2
      with:
        channel: 'stable'
    
  4. 安装 Codemagic CLI 工具: 为安装 Codemagic CLI 工具添加一个job

    - name: Install Codemagic CLI tools
      run: pip install codemagic-cli-tools
    
  5. 设置环境变量:根据您是使用现有凭据还是希望 Codemagic 处理签名文件的创建,相应地设置您的环境部分。请注意,变量可以使用  vars  前缀在管道中设置,secrets使用  secrets  前缀设置:

    build:
      runs-on: macos-latest
      env:
        APP_STORE_CONNECT_ISSUER_ID: ${{ vars.APP_STORE_CONNECT_ISSUER_ID }}
        APP_STORE_CONNECT_KEY_IDENTIFIER: ${{ vars.APP_STORE_CONNECT_KEY_IDENTIFIER }}
        APP_STORE_CONNECT_PRIVATE_KEY: ${{ secrets.APP_STORE_CONNECT_PRIVATE_KEY }}
        CERTIFICATE_PRIVATE_KEY: ${{ secrets.CERTIFICATE_PRIVATE_KEY }}
        APP_STORE_APP_ID: ${{ vars.APP_STORE_APP_ID }}
    

    如果你正在使用使用现有的证书和配置文件进行设置,你需要调整你的设置。不要使用` CERTIFICATE_PRIVATE_KEY `, 而是添加你在前面步骤中配置的密钥:

        DIST_CERTIFICATE: ${{ secrets.DIST_CERTIFICATE }}
        DIST_CERTIFICATE_PASSWORD: ${{ secrets.DIST_CERTIFICATE_PASSWORD }}
        DIST_PROFILE: ${{ secrets.DIST_PROFILE }}
  6. 初始化钥匙串:使用“ keychain initialize ”命令为代码签名创建一个新的钥匙串。

    - name: Set up keychain
      run: keychain initialize
    
  7. 获取签名文件或设置现有文件:如果您希望CLI工具生成新文件,请使用 app-store-connect fetch-signing-files 命令。如果您要使用现有文件,请在构建机器上对其进行解码。在两种情况下,您都可以使用 keychain add-certificates 命令将证书添加到密钥链中:

    选项1 - 获取签名文件

    - name: Fetch signing files
      run: |
        app-store-connect fetch-signing-files $(xcode-project detect-bundle-id) \
        --type IOS_APP_STORE \
        --create    
    - name: Set up signing certificate
      run: keychain add-certificates
    

    第二种方法 - 使用现有文件进行设置

    如果你选择现有证书方法,那么请使用以下脚本来替换上面的脚本:

    - name: Set up Provisioning profiles
      run: |
        PROFILES_HOME="$HOME/Library/MobileDevice/Provisioning Profiles"
        mkdir -p "$PROFILES_HOME"
        PROFILE_PATH="$(mktemp "$PROFILES_HOME"/$(uuidgen).mobileprovision)"
        echo ${DIST_PROFILE} | base64 --decode > "$PROFILE_PATH"
        echo "Saved provisioning profile $PROFILE_PATH"         
    - name: Set up signing certificate
      run: |
        echo $DIST_CERTIFICATE | base64 --decode > /tmp/certificate.p12
        keychain add-certificates --certificate /tmp/certificate.p12 --certificate-password $DIST_CERTIFICATE_PASSWORD    
    

    不幸的是,使用GitHub Actions时,我们必须接受某些步骤需要一些不太美观的脚本和设置工作。如果您以前使用过Codemagic CI/CD(而不是其特定工具),那么您可能知道很多这种基础代码都被整理成了不同的YAML部分。

    注意:对于选项1,我们使用 xcode-project detect-bundle-id 动作从项目中获取bundle ID。这可以由一个硬编码的值替换,但当前的方法可以降低出现拼写错误或错误的风险,因为如果在App Store Connect和管道中bundle ID不匹配,则很难找到问题所在。

  8. 在Xcode项目中设置代码签名设置:使用` xcode-project use-profiles `命令配置Xcode项目以使用已获取或已解码的签名配置文件:

    - name: Set up code signing settings on Xcode project
      run: xcode-project use-profiles
    
  9. 增加构建号:使用  app-store-connect get-latest-testflight-build-number  命令从 TestFlight 获取应用程序的最新构建号。使用  agvtool new-version -all  命令将版本号增加 1。

    - name: Increment build number
      run: |
        cd ios
        agvtool new-version -all $(($(app-store-connect get-latest-testflight-build-number "$APP_STORE_APP_ID") + 1))    
    

    注意:在 Codemagic CLI 工具中,针对 Google Play 也有相同的命令。我认为这是最有用的工具之一,因为版本控制通常很难以一致的方式设置,尤其是在同时向两个商店部署时。它还可以保证每个新构建的版本号增加 1,而不是依赖于某些伪版本号。

  10. 构建.ipa文件进行分发:使用带有 flutter build ipa 命令和 --release 标志的命令以发布模式构建应用程序。此外,添加 --export-options-plist 标志以正确设置打包设置:

    - name: Build ipa for distribution
      run: |
            flutter build ipa --release --export-options-plist=$HOME/export_options.plist
    

    这个`b0`文件是`b1`命令的输出结果。

  11. 将应用程序发布到App Store Connect:使用 app-store-connect publish 命令将构建好的应用程序打包文件发布到App Store Connect,通过向命令传递带有 --path 标志的文件路径即可:

    - name: Publish the app to App Store Connect
      run: |
        APP_FILE=$(find $(pwd) -name "*.ipa")
        app-store-connect publish \
        --path "$APP_FILE"    
    

就是这样!使用这个工作流,您可以使用 GitHub Actions 和 Codemagic CLI 工具自动化将 iOS 应用发布到 App Store Connect 的过程。

有了这个管道,你可以确保每个新的build都会上传带有递增版本号的应用程序。在下面的截图中,你可以看到运行这两个工作流(自动签名和手动签名)的结果。如果您只设置了其中一个管道(这是有意义的),那么当然只会生成一个build。

自动签名和手动签名的结果

完整的自动处理流程示例

下面是使用 Codemagic CLI 工具处理生成新代码签名凭据(证书和配置文件)的完整流程:

name: Publish to App Store Connect

on:
 workflow_dispatch:
 
jobs:
 build:
   runs-on: macos-latest
   env:
     APP_STORE_CONNECT_ISSUER_ID: ${{ vars.APP_STORE_CONNECT_ISSUER_ID }}
     APP_STORE_CONNECT_KEY_IDENTIFIER: ${{ vars.APP_STORE_CONNECT_KEY_IDENTIFIER }}
     APP_STORE_CONNECT_PRIVATE_KEY: ${{ secrets.APP_STORE_CONNECT_PRIVATE_KEY }}
     CERTIFICATE_PRIVATE_KEY: ${{ secrets.CERTIFICATE_PRIVATE_KEY }}
     APP_STORE_APP_ID: ${{ vars.APP_STORE_APP_ID }}

   steps:
   - uses: actions/checkout@v4

   - name: Set up Flutter
     uses: subosito/flutter-action@v2
     with:
       channel: 'stable'

   - name: Install Codemagic CLI tools
     run: pip install codemagic-cli-tools

   - name: Set up keychain
     run: keychain initialize

   - name: Fetch signing files
     run: |
       app-store-connect fetch-signing-files $(xcode-project detect-bundle-id) \
       --type IOS_APP_STORE \
       --create       

   - name: Set up signing certificate
     run: keychain add-certificates

   - name: Set up code signing settings on Xcode project
     run: xcode-project use-profiles

   - name: Increment build number
     run: |
       cd ios
       agvtool new-version -all $(($(app-store-connect get-latest-testflight-build-number "$APP_STORE_APP_ID") + 1))       

   - name: Build ipa for distribution
     run: |
              flutter build ipa --release --export-options-plist=$HOME/export_options.plist

   - name: Publish the app to App Store Connect
     run: |
       APP_FILE=$(find $(pwd) -name "*.ipa")
       app-store-connect publish \
       --path "$APP_FILE"       

现有证书和配置文件的完整示例管道

下面是一个演示如何在管道中使用现有代码签名凭据的完整示例:

name: Publish to App Store Connect (manual)

on:
 workflow_dispatch:

jobs:
 build:
   runs-on: macos-latest
   env:
     APP_STORE_CONNECT_ISSUER_ID: ${{ vars.APP_STORE_CONNECT_ISSUER_ID }}
     APP_STORE_CONNECT_KEY_IDENTIFIER: ${{ vars.APP_STORE_CONNECT_KEY_IDENTIFIER }}
     APP_STORE_CONNECT_PRIVATE_KEY: ${{ secrets.APP_STORE_CONNECT_PRIVATE_KEY }}
     DIST_CERTIFICATE: ${{ secrets.DIST_CERTIFICATE }}
     DIST_CERTIFICATE_PASSWORD: ${{ secrets.DIST_CERTIFICATE_PASSWORD }}
     DIST_PROFILE: ${{ secrets.DIST_PROFILE }}
     APP_STORE_APP_ID: ${{ vars.APP_STORE_APP_ID }}

   steps:
   - uses: actions/checkout@v4

   - name: Set up Flutter
     uses: subosito/flutter-action@v2
     with:
       channel: 'stable'

   - name: Install Codemagic CLI tools
     run: pip install codemagic-cli-tools

   - name: Set up keychain
     run: keychain initialize

   - name: Set up Provisioning profiles
     run: |
       PROFILES_HOME="$HOME/Library/MobileDevice/Provisioning Profiles"
       mkdir -p "$PROFILES_HOME"
       PROFILE_PATH="$(mktemp "$PROFILES_HOME"/$(uuidgen).mobileprovision)"
       echo ${DIST_PROFILE} | base64 --decode > "$PROFILE_PATH"
       echo "Saved provisioning profile $PROFILE_PATH"            
   - name: Set up signing certificate
     run: |
       echo $DIST_CERTIFICATE | base64 --decode > /tmp/certificate.p12
       keychain add-certificates --certificate /tmp/certificate.p12 --certificate-password $DIST_CERTIFICATE_PASSWORD       

   - name: Set up code signing settings on Xcode project
     run: xcode-project use-profiles

   - name: Increment build number
     run: |
       cd ios
       agvtool new-version -all $(($(app-store-connect get-latest-testflight-build-number "$APP_STORE_APP_ID") + 1))       

   - name: Build ipa for distribution
     run: |
              flutter build ipa --release --export-options-plist=$HOME/export_options.plist

   - name: Publish the app to App Store Connect
     run: |
       APP_FILE=$(find $(pwd) -name "*.ipa")
       app-store-connect publish \
       --path "$APP_FILE"       

额外福利 - 适用于本地使用和更多工具!

除了可以在各种CI/CD管道中使用Codemagic CLI工具外,它们在本地环境中也表现良好。与CI/CD环境类似,如果您想在本地运行它们,需要安装Python 3.7。

首先,您可以使用以下简单的命令安装这些工具:

pip3 install codemagic-cli-tools

在本地运行这些工具有很多好处。例如,你可以在尝试在持续集成/持续部署(CI/CD)管道中设置环境(例如变量、配置)之前,先在本地测试设置环境。这可以帮助你减少问题数量,简化调试过程,以免不小心错误设置了某些变量。此外,这可能有助于你节省宝贵的构建时间。

Codemagic 文档中有一些很棒的示例,说明如何在本地使用一些工具来对应用程序进行归档。但是有一件事你应该记住:在本地机器上运行完 keychain initialize 之后,你也需要运行 keychain use-login ,以便将你的登录钥匙串设置为默认值。这样可以避免应用程序出现任何身份验证问题。

但是这些工具并不仅限于归档:Codemagic CLI工具还可以帮助您轻松完成其他各种任务,例如生成变更日志、管理审核提交或注册设备。

生成变更日志

运行`git log`命令将生成一个文本摘要,列出您在存储库中所做的更改(提交):

vearnold@Arnolds-MBP cm_cli_tools_demo % git-changelog generate
* Add manual pipeline
* Add pipeline
* Create flutter demo project
Generated 3 change log lines

关于这个工具的更多信息可以在官方文档中找到。

评论提交

你可以使用 app-store-connect review-submissions 命令来创建、列出和管理审核提交。当你想要自动化提交应用程序(无论是在本地还是在流水线中)时,这会非常有用。你可以使用这个工具来检查你的构建状态(通常情况下它不会立即被处理),并在准备好时提交。

对于使用Codemagic CI/CD的用户来说,这非常简单,因为该功能已经内置到管道中,无需自行编写脚本来ping苹果。从某种意义上说,这也是免费的,因为Codemagic在构建完成后的后处理步骤中执行此操作,不会消耗构建分钟。但是,正如前面所说,在其他管道或本地环境中也可以很好地利用此功能!

关于这个工具及其使用方法的更多信息可以在官方文档 中找到。

注册设备

另一个有用的工具是 app-store-connect devices register ,它允许您将设备注册到您的配置文件中。当您想在新设备上测试您的应用程序时,这非常方便。您无需前往苹果开发者门户并手动进行操作。只需运行以下命令,输入设备名称和UDID即可:

app-store-connect devices register --name iPhone8-Arnold --udid <device_udid>

如果您拥有大量测试设备,那么这个方法会更加有效(甚至更好),因为您无需在苹果开发者门户中逐一添加这些设备,只需执行一次命令即可。该命令可以同时添加多个设备!

关于这个工具及其使用方法的更多信息可以在官方文档中找到。

结论

虽然Codemagic CI/CD本身提供了一个经过优化的、适用于移动开发、代码签名和简单YAML配置的流畅环境,但CLI工具还提供了可以在Codemagic内部和外部的管道中使用的其他功能。无论您是在本地工作还是在CI/CD管道中工作,这些工具都可以为您的移动应用构建和发布提供灵活的解决方案。

在本文中,我演示了如何在GitHub Actions管道中使用Codemagic CLI工具发布iOS构建到App Store Connect,展示了它们的易用性和灵活性。强烈建议您尝试一下!:)