# 令牌与 CI 发布

创建 API Key，在 CI 中自动打包并发布。

## 先确认本地已经能发布 {#before}

CI 只是把[首次发布](/docs/publish)搬进流水线。先在本地验证同一原生基线、打包命令与目标，再配置自动化，避免同时排查构建和认证两类问题。

## 创建发布令牌 {#what-is-api-key}

控制台侧栏打开 **API Key**（`/settings/tokens`），创建令牌，选择所需权限、应用范围与有效期。完整值只展示一次，立即保存到 CI Secrets。

令牌的操作受所选权限与应用范围约束，不等同于无限制账号会话。CLI 使用 `PAKTA_API_TOKEN`，发出 `x-api-token` 请求头；交互登录使用会话令牌。SDK 只使用公开 appKey。

## 准备发布配置 {#configuration}

提交应用项目的 `package.json`、lockfile、只含公开标识的 `update.json` 和 `targets.json`。`update.json` 由本地 `selectApp` 生成；首次流水线不要依赖交互选应用。

```json title="targets.json · 替换为已验证的生产目标"
[
  { "channel": "default", "packageVersion": "1.0.0", "rollout": 10 }
]
```

还需要与本地一致的 Node、Metro/Hermes 与平台构建依赖。iOS、HarmonyOS 或特殊 Android 构建，应选择能运行相同命令的 runner，不假定通用 Linux 镜像就足够。

## GitHub Actions 示例 {#ci}

以下是**加入现有 job 的 steps 片段**，不是完整工作流。假定 checkout、Node 和所需工具链已经配置好，工作目录为 App 根目录，在 CI 中安装与本地一致版本的 CLI：

```yaml title="现有 workflow 的 steps"
- name: Install locked dependencies
  run: |
    npm ci
    npm install -g rn-update-cli@1.1.0

- name: Verify identity and targets
  env:
    PAKTA_API_TOKEN: ${{ secrets.PAKTA_API_TOKEN }}
    NO_INTERACTIVE: 'true'
  run: |
    pakta me
    pakta publish .pakta/output/android.ppk --platform android --name "$GITHUB_RUN_ID" --targets targets.json --dryRun --no-interactive

- name: Bundle and publish
  env:
    PAKTA_API_TOKEN: ${{ secrets.PAKTA_API_TOKEN }}
    NO_INTERACTIVE: 'true'
  run: |
    pakta bundle --platform android --output .pakta/output/android.ppk --no-interactive
    pakta publish .pakta/output/android.ppk --platform android --name "$GITHUB_RUN_ID" --targets targets.json --sourcemap .pakta/intermedia/android/index.bundlejs.map --no-interactive
```

上述 `run` 使用 Bash。Expo 的 bundle 命令加 `--expo`；自定义 map 路径时同步修改发布参数。自托管在两个步骤的 env 中加入自己的 `RNU_SERVICE_URL`。

## 无交互发布与失败恢复 {#non-interactive}

- 明确提供 `--targets`、原生包 `--packageId` 或 `--packageVersion`，不要依赖交互选择。
- `--dryRun` 不上传、不创建渠道、不发布，不能当作完整发布成功。
- 保存成功结果的更新包 `packageId` 和全部 `deploymentIds`。若失败输出提供可重试投放 ID，用精确 ID 恢复：

```bash
pakta publish --deploymentIds DEPLOYMENT_ID_1,DEPLOYMENT_ID_2 --platform android --no-interactive
```

替换占位 ID；不要猜测其他草稿。并行流水线应按应用和目标串行化投放，避免互相替换。对同次构建归档 `.ppk`、map、提交号与发布输出。

## 完成标志 {#verify}

流水线退出成功、控制台出现预期在线目标、匹配的设备完成激活与健康确认。只有上传成功还不够，按[实时数据](/docs/analytics)验收。

## 令牌维护 {#security}

每条流水线独立发令牌；不用时撤销，到期前轮换。仅从 CI Secret 注入，不放进 `update.json`、App 或日志。认证失败先检查过期、撤销、应用范围与权限，再用 `me` 核对账号。

## 相关阅读 {#related}

[CLI 命令](/docs/cli) · [渠道投放](/docs/channels) · [生产检查清单](/docs/bestpractice)。
