> ## Documentation Index
> Fetch the complete documentation index at: https://docs.devinenterprise.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 使用 Devin 将 iOS 构建上传到 TestFlight

> 设置 App Store Connect、API 密钥和 Devin secrets，让 Devin 能够在 macOS VM 上归档 iOS 应用并将构建上传到 TestFlight。

Devin 可以归档 iOS 应用、完成签名、上传到 TestFlight，并将构建添加到 beta 组。它会在 [macOS VM](/zh/onboard-devin/environment/macos-support) 上运行 `xcodebuild`，并使用你存储为 Devin secrets 的 App Store Connect API 密钥进行身份验证。

在 Devin 上传构建之前，你需要：

1. 在 App Store Connect 中设置你的应用。
2. 创建一个 App Store Connect API 密钥。
3. 将该密钥和你的 Team ID 作为 secrets 添加到 Devin。
4. 确保 Devin 能够访问 Apple 的服务器。

<Note>
  上传到 TestFlight 需要使用 macOS 会话。如果你使用的是 Dedicated SaaS 部署，请联系你的账户团队启用 macOS VM。
</Note>

<div id="requirements">
  ## 要求
</div>

| 要求                           | 详情                                                                |
| ---------------------------- | ----------------------------------------------------------------- |
| Apple Developer Program 会员资格 | 拥有该 app 的团队需具备付费会员资格。                                             |
| App Store Connect 中的 app 记录  | 一个与 Xcode 项目 bundle ID 相同的 app。                                   |
| App Store Connect API 密钥     | 具备 **App Manager** 角色的团队密钥。                                       |
| Devin secrets                | `ASC_KEY_ID`、`ASC_ISSUER_ID`、`ASC_PRIVATE_KEY` 和 `APPLE_TEAM_ID`。 |
| 网络访问                         | Devin 的 macOS VM 能够访问 Apple 的服务器。                                 |

<div id="set-up-app-store-connect">
  ## 设置 App Store Connect
</div>

以下步骤需在 Apple Developer 门户和 App Store Connect 中完成，Devin 无法代你完成：大多数步骤需要 Account Holder 或 Admin 权限，部分还需要在个人 Apple 账户上完成双重身份验证。

<Steps>
  <Step title="接受最新协议">
    由 Account Holder 登录 [App Store Connect](https://appstoreconnect.apple.com)，在 **Business** 中接受所有待处理的协议。只要还有必需协议未接受，上传就会失败。
  </Step>

  <Step title="注册 bundle ID">
    在 [Apple Developer 门户](https://developer.apple.com/account/resources/identifiers/list) 中，前往 **Certificates, Identifiers & Profiles → Identifiers**，注册一个与你 app target 的 bundle ID 相匹配的 App ID。如果该标识符已存在，可跳过此步骤。
  </Step>

  <Step title="创建 app 记录">
    在 App Store Connect 中，前往 **Apps**，点击 **+**，选择 **New App**。依次选择平台、名称、主要语言、上一步中的 bundle ID 以及 SKU。如果该 bundle ID 没有对应的 app 记录，TestFlight 上传会失败。
  </Step>

  <Step title="创建 beta 组">
    打开该 app，前往 **TestFlight**，然后创建一个组：

    * **Internal testing**：测试人员必须是你 App Store Connect 团队中的用户。构建处理完成后即可安装使用。
    * **External testing**：测试人员可以是任何拥有电子邮箱地址的人，也可通过公开链接加入。请先填写 **Test Information** (beta app 描述、反馈邮箱和审核联系信息) 。每个版本的首个构建都需要经过 Beta App Review。
  </Step>

  <Step title="回答出口合规问题">
    测试人员安装之前，每个构建都必须回答出口合规问题。若要让每个构建都跳过该问题，可在 app 的 `Info.plist` 中设置 `ITSAppUsesNonExemptEncryption`。如果 app 仅使用豁免类加密 (例如 HTTPS) ，将其设置为 `NO`。
  </Step>
</Steps>

<div id="create-an-app-store-connect-api-key">
  ## 创建 App Store Connect API 密钥
</div>

Devin 使用 App Store Connect API 密钥进行身份验证，而不是 Apple 账户。该密钥无需双重身份验证。

<Steps>
  <Step title="启用 API 访问权限">
    在 App Store Connect 中，前往 **Users and Access → Integrations → App Store Connect API**。如果尚未启用 API 访问权限，需由 Account Holder 点击 **Request Access** 并接受条款。
  </Step>

  <Step title="生成团队密钥">
    在 **Team Keys** 下点击 **+**，输入名称 (例如 `Devin TestFlight`) ，并选择 **App Manager** 角色。生成密钥需要 Admin 角色。如果 Xcode 无法使用 App Manager 密钥创建分发证书，请改为生成 **Admin** 角色的密钥。
  </Step>

  <Step title="下载私钥">
    点击新密钥旁的 **Download**，保存 `AuthKey_<KEY_ID>.p8`。Apple 仅允许下载该文件一次，如果丢失，只能吊销该密钥并重新生成。
  </Step>

  <Step title="复制 Issuer ID 和 Key ID">
    **Issuer ID** 显示在密钥表格上方，**Key ID** 位于该密钥所在行。
  </Step>

  <Step title="查找你的 Team ID">
    在 [Apple Developer 门户](https://developer.apple.com/account)中，前往 **Membership details** 并复制 **Team ID**。它是一个 10 位字符的字符串，例如 `A1B2C3D4E5`。
  </Step>
</Steps>

<Warning>
  任何持有该 `.p8` 文件的人，都能为你团队中的所有 app 上传构建版本并管理 TestFlight。请仅将其存放在 Devin secrets 中，切勿提交到代码仓库。
</Warning>

<div id="add-secrets-to-devin">
  ## 向 Devin 添加 secrets
</div>

在 [Secrets 页面](https://app.devin.ai/settings/secrets)上以原始 secret 的形式添加以下值：

| Secret 名称         | 值                                                                                              | 获取位置                                                                        |
| ----------------- | ---------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- |
| `ASC_KEY_ID`      | 密钥 ID，例如 `2X9R4HXF34`                                                                          | App Store Connect → Users and Access → Integrations → App Store Connect API |
| `ASC_ISSUER_ID`   | 签发方 ID，为一个 UUID                                                                                | 同一页面，密钥表格上方                                                                 |
| `ASC_PRIVATE_KEY` | `AuthKey_<KEY_ID>.p8` 的完整内容，包括 `-----BEGIN PRIVATE KEY-----` 和 `-----END PRIVATE KEY-----` 这两行 | 创建密钥时下载的那个文件                                                                |
| `APPLE_TEAM_ID`   | Team ID，例如 `A1B2C3D4E5`                                                                        | Apple Developer 门户 → Membership details                                     |

在 Mac 上复制私钥，请运行：

```bash theme={null}
pbcopy < AuthKey_<KEY_ID>.p8
```

为 secrets 选择作用域：

* **Organization**：你的组织中的所有会话都可以使用该密钥。当团队借助 Devin 发布构建时，请使用此作用域。
* **Personal**：只有你启动的会话才能使用该密钥。

secrets 仅在添加之后启动的会话中可用。有关作用域的更多信息，请参见 [Secrets](/zh/product-guides/secrets)。

<div id="allow-network-access">
  ## 允许网络访问
</div>

Devin 的 macOS VM 需要访问 Apple 的服务器，以完成构建产物的签名和上传。如果你的组织使用了受限的网络策略，请将 `api.appstoreconnect.apple.com` 以及 `xcodebuild` 在签名和上传时使用的其他 Apple 主机加入允许列表。允许 `*.apple.com` 即可覆盖这些主机。

主机被阻止时通常表现为身份验证错误，而非网络错误。请参阅[故障排查](#troubleshooting)。

<div id="upload-a-build">
  ## 上传构建产物
</div>

启动一个 macOS 会话，并让 Devin 上传构建产物：

```text theme={null}
归档 MyApp scheme 并上传到 TestFlight。build 号要高于 App Store Connect 中
的最新 build，将该 build 添加到 "QA" 组，
完成后把 build 号发给我。
```

Devin 使用这些 secrets 执行以下操作：

1. 将 `ASC_PRIVATE_KEY` 写入 `~/.appstoreconnect/private_keys/AuthKey_$ASC_KEY_ID.p8`，权限设为 `0600`。
2. 通过 App Store Connect API 查询最新的 build 号，并选取一个更大的编号。
3. 使用 `xcodebuild archive` 归档 app。
4. 使用 `xcodebuild -exportArchive` 对 build 进行签名并上传。
5. 等待处理完成，然后通过 App Store Connect API 将该 build 添加到 beta 组。

导出步骤使用的 export options plist 中，`destination` 设置为 `upload`：

```xml theme={null}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>method</key><string>app-store-connect</string>
  <key>destination</key><string>upload</string>
  <key>teamID</key><string>A1B2C3D4E5</string>
  <key>signingStyle</key><string>automatic</string>
</dict>
</plist>
```

以及以下命令：

```bash theme={null}
xcodebuild -project MyApp.xcodeproj -scheme MyApp \
  -configuration Release -destination 'generic/platform=iOS' \
  -archivePath build/MyApp.xcarchive \
  CURRENT_PROJECT_VERSION=<build-number> archive

xcodebuild -exportArchive \
  -archivePath build/MyApp.xcarchive \
  -exportOptionsPlist ExportOptions.plist \
  -exportPath build/export \
  -allowProvisioningUpdates \
  -authenticationKeyID "$ASC_KEY_ID" \
  -authenticationKeyIssuerID "$ASC_ISSUER_ID" \
  -authenticationKeyPath ~/.appstoreconnect/private_keys/AuthKey_$ASC_KEY_ID.p8
```

`-allowProvisioningUpdates` 可让 Xcode 使用 API 密钥创建分发证书和预配 Profile，因此 VM 上无需预先安装签名资产。

如果你的代码仓库中已有发布脚本，例如 `fastlane` lane 或 `make` target，可以直接让 Devin 使用它。`fastlane` 也能通过 `app_store_connect_api_key` 接收同一个密钥。

<div id="save-the-steps-in-your-blueprint">
  ### 将步骤保存到蓝图中
</div>

为避免在每条提示中重复这些指示，请将它们添加到代码仓库[蓝图](/zh/onboard-devin/environment/blueprints)的 `knowledge` 部分：

```yaml theme={null}
runs-on: macos

knowledge:
  - name: testflight
    contents: |
      To upload a TestFlight build:
      1. Write $ASC_PRIVATE_KEY to ~/.appstoreconnect/private_keys/AuthKey_$ASC_KEY_ID.p8 (chmod 600).
      2. Use a build number higher than the latest build in App Store Connect.
      3. Archive the MyApp scheme, then run xcodebuild -exportArchive with
         ExportOptions.plist (destination: upload, teamID: $APPLE_TEAM_ID),
         -allowProvisioningUpdates, and the -authenticationKey* flags.
      4. Add the build to the "QA" beta group.
```

<div id="troubleshooting">
  ## 故障排查
</div>

**导出时出现 `No Accounts with App Store Connect Access` 或 `Failed to Use Accounts`。** 先检查网络访问。如果 VM 无法访问 Apple 的服务器，即使密钥有效，`xcodebuild` 也会报这个错误。留意上方几行中是否有 `ITunesConnectFoundationErrorDomain Code=-1003`。如果网络正常，请确认该密钥具备 App Manager 角色。

**`No profiles for '<bundle ID>' were found`。** 该 bundle ID 未在 `APPLE_TEAM_ID` 对应的团队中注册，或 App Store Connect 中没有对应的 app 记录。

**`The provided entity includes an attribute with a value that has already been used`。** 该版本的 build 号已被使用过，请改用更高的 build 号重新上传。

**构建上传成功，但测试人员无法安装。** 在 App Store Connect → TestFlight 中查看该构建。它可能仍在处理中、缺少出口合规信息，或正在等待 Beta App Review。

**Xcode 无法创建分发证书。** 该密钥的角色不具备管理证书的权限。请生成具有 Admin 角色的密钥，或让 Admin 在 Apple Developer 门户中创建分发证书。

**会话中的环境变量为空。** secrets 只对添加之后启动的会话生效，请启动一个新会话。
