删除 pull request 预览看似只需一条命令。使用 Capgo时有一个陷阱:必须先离开当前激活的预览,然后按 ID 删除其 bundle。我们将构建一个安全的清理流程,包括受限的 API 密钥、预览查找、重置处理、bundle 删除以及 CI 自动化。
目录
- 步骤 1:为预览清理创建受限的 Capgo API 密钥
- 第 2 步:识别 Pull Request Preview 及其 Bundle ID
- 步骤 3:清理前先切换离开活跃预览
- 步骤 4:使用 API 密钥按 ID 删除预览 Bundle
- 第 5 步:Pull Request 关闭时自动清理
- 步骤 6:验证清理结果并防止 Rollout 被误删
- 常见问题
- 总结
步骤 1:为预览清理创建受限的 Capgo API 密钥
在 Capgo pull request 预览清理流程中,第一步是创建一个仅能执行 CI 任务所需操作的密钥。
切勿在 pull request 工作流中使用权限过大的组织级密钥。Pull request 可能来自尚未获得信任的分支,且工作流在运行失败时可能会打印出命令或环境变量。使用权限受限的密钥可以最大限度降低此类风险。
在 Capgo 中,请先为预览任务准备一个 App Preview 密钥。该密钥应绑定到你的任务所管理的 App 或预览范围。如果你的团队使用基于角色的访问控制 (RBAC),请将密钥限制在选定的 App 中,而不是授予整个组织的访问权限。Capgo 在其…… API 的 Web App 工作流密钥设置.
将该 Secret 存储在 CI 提供商的加密 Secret 存储中。请为其命名以体现其用途,例如CAPGO_PREVIEW_CLEANUP_KEY. 请勿将其放入 workflow 文件、shell 脚本、pull request 评论或生成的日志中。
通过环境变量将密钥传递给清理进程。当变量缺失时,脚本应报错退出。静默回退机制很危险,因为它可能将清理任务变成无认证的请求,或者诱导开发者将密钥粘贴到命令行中。
if [ -z "$CAPGO_PREVIEW_CLEANUP_KEY" ]; then echo "Missing preview cleanup key" exit 1
fi
将此密钥与用于发布生产 bundle 的密钥分开。发布任务可能需要上传 release。清理任务只需删除预览资源。分离密钥便于审查,并降低删除操作误触生产 channel 的风险。
尽可能在受保护的环境中使用相同的 secret。在任务可以操作共享 channel 之前,要求人工审批。对于普通的 pull request 预览,任务应仅操作临时 channel,不涉及其他内容。
核心要点: 使用专用的 App Preview 密钥,限制其应用范围,并将其存储在加密的 CI secrets 中。
在继续之前,先使用一个无害的只读操作测试该密钥。确认任务能访问目标应用,但无法访问无关应用或生产工作流。由于清理操作的具体请求细节尚未完全公开,首次测试请保持最小化,并在添加删除调用前查阅 SDK 或 Capgo 的支持指南。
步骤 2:识别 Pull Request Preview 及其 Bundle ID
Capgo pull request preview 清理 API 密钥仅在任务明确知道其拥有的 preview 和 bundle ID 时才有用。
为预览 channel 使用稳定的命名规则。常见的模式是“仓库名 + Pull Request 编号”。关键在于一致性:你的清理任务必须在 Pull Request 关闭后重新生成相同的标识符。
在创建预览时保存预览 channel 名称。你可以将其存放在 workflow 输出、Pull Request check 或少量 job metadata 中。不要依赖有人可能会在 dashboard 中修改的显示名称。
接下来,列出与该预览关联的 bundle。Capgo 的 Delete Bundle 操作需要 bundle ID。源文档指出,删除前需调用 list 接口获取所有可用的 bundle ID。请将该列表视为唯一事实来源,切勿根据文件名、commit hash 或分支名猜测 ID。
按预览 channel 或 workflow 控制的其他值过滤返回的记录。然后保留每个匹配项的确切 bundle ID。如果列表为空,就把清理标记为完成。除非 workflow 预期该预览应存在,否则空结果不算失败。
同时记录生成每个预览的 commit SHA。这可以作为删除前的二次校验。如果 channel 名称匹配但 commit 不符,就停下来请求审核。这一小步能避免旧清理任务运行时新预览正在构建所引发的竞态条件。

请勿在发布任务仍在运行时删除。请在预览构建与清理工作流之间添加依赖关系,或者使用以 Pull Request 编号为键的锁。清理任务应仅在关闭事件发生后、且所有待处理的预览上传结束后启动。
Capgo 的公开 API 借助经过身份验证的 HTTP 请求覆盖 channel 和 bundle 等资源,但清理操作在你的项目中仍需仔细验证。该 Capgo 公开 API 概览 是你在编写 wrapper 之前确认当前资源模型的最佳位置。
现在,你应该已经有一个预览标识符、一份确切的 bundle ID 列表,以及与每条记录关联的 commit SHA。如果缺少其中任何一个值,就先停下来。没有所有权检查的清理就是瞎猜。
步骤 3:清理前先切换离开活跃预览
在应用切换离开该活跃预览或你调用resetPreview之前,无法删除活跃预览。这是 Capgo Pull Request 预览清理流程中的关键细节。
把活跃预览看作应用当前选中的版本。先删除服务端记录会让应用指向一个已不存在的对象。Capgo 会阻止这种状态变更,因此清理任务必须先重置应用的预览状态,再移除预览。
首先,检查预览是否仍处于激活状态。如果是,请将应用移至安全渠道,或使用 updater 重置操作。具体选择取决于测试应用的配置方式。一次性测试应用可以返回其正常的默认渠道。共享测试应用可能需要使用专用的 staging 渠道。
使用resetPreview当需要直接清除预览状态时。请确保此调用与创建预览的同一 pull request 和应用绑定。清理脚本绝不能仅因渠道名称匹配就重置生产设备或共享发布渠道。
这里有一个有用的顺序规则:
- 确认 pull request 已关闭。
- 确认没有正在运行的预览 upload。
- 从激活的预览中切换出去,或调用
resetPreview. - 等待该状态变更完成。
- 然后才调用 Delete Preview。
不要将重置请求的成功 HTTP 响应视为应用已在所有设备上改变状态的证明。设备可能会稍后检查更新。一旦根据 API 响应清除了预览分配,您的服务器端清理即可继续,但请将设备行为与资源删除分开处理。
Capgo 支持基于 channel 的 rollout 控制,这使得这种分离更容易推理。Channel 是一个命名路径,告诉应用遵循哪个更新流。您的预览 channel 绝不能与生产设备使用的 channel 相同。
对于需要更严格边界的团队,请使用文档中记录的 Capgo channel 工作流用于预览自动化。它描述了临时 channel 模式,并有助于将清理任务与共享的默认 channel 隔离开来。
开源 updater 文档还记录了删除限制:活动预览需要先切换或重置。您可以在 Capgo Capacitor updater 仓库中查看源代码。当 dashboard 措辞对于 CI 决策来说过于简略时,该源代码非常有用。
专家提示: 将重置作为一个单独的记录步骤。如果 Delete Preview 失败,日志应显示预览是否仍处于活动状态,或者删除请求是否存在其他问题。
一旦活动状态消失,预览记录即可准备删除。不要将重置和删除合并为一行不透明的 shell 命令。两条清晰的命令更容易重试,也更容易审计。
步骤 4:使用 API 密钥按 ID 删除预览 Bundle
重置当前预览后,按每个预览 bundle 的确切 ID 将其删除。这一步中,Capgo 清理密钥会移除该 pull request 留下的存储对象。
从第 2 步的 bundle 列表开始。对每个匹配的 ID,通过 Capgo SDK 或你账户当前可用的公开 API 方法调用 Delete Bundle 操作。
检查 SDK 的方法签名,或联系 Capgo 支持确认当前请求结构。验证后,将方法和响应格式记录到团队内部的 runbook。该 runbook 应包含 API 版本、必需的 identifier,以及重试逻辑能处理的错误码。
在脚本中使用 dry-run 模式。它应打印出预览 channel 和将要删除的 bundle ID,而不发送删除请求。针对几个已关闭的 pull request 运行该模式。检查它是否排除了 production channel,并确保不会把空列表当作通配符。
安全删除循环有三道关卡:
- 拒绝缺失或格式错误的 bundle ID。
- 拒绝 channel 与 pull request 预览不匹配的 bundle。
- 只有所有权检查通过后才删除。
然后按类型处理每个响应。删除成功可标记为完成。如果已知该资源已被之前的重试删除,可将 not-found 响应视为已清理。权限错误应让任务失败并通知负责人。遇到限流时应暂停,并以有上限的延迟重试。
不要重试所有错误。无效 ID 不会在尝试三次后变得有效。授权错误通常意味着 key scope 有误。只重试瞬时故障,并设置最大运行时间,避免卡住的清理任务占用 CI 队列。
Bundle 删除与 Preview 删除是分开的。移除 preview channel 并不能自动证明所有 bundle 都已删除。你的任务应为每个 ID 保留结果,然后如果 API 支持,再发起最后一次列表请求。如果仍有 bundle 残留,请报告该 ID 并停止,而不是默默声称成功。
确保删除日志不包含密钥。可以记录 Pull Request 编号、preview 名称、bundle ID、请求结果和时间戳。切勿记录 API 密钥、Authorization header 或可能包含密钥的完整请求对象。
这种方法能提供有用的审计线索,又不会让日志变成另一个凭据泄露点。它也让清理失败后更容易继续,因为下次运行可以跳过已确认不存在的记录。
第 5 步:Pull Request 关闭时自动清理
由 Pull Request 关闭事件触发清理任务,但要添加检查,防止迟到的 build 删除新的 preview。
你的 workflow 应从事件 payload 中获取仓库和 Pull Request 编号。根据这些值重新生成 preview channel 名称。不要接受由 Pull Request 评论或不可信分支变量提供的 channel 名称。
一个实用的任务顺序如下:
- 从加密的 secrets 中加载受限的清理密钥。
- 确认该事件是已关闭的 Pull Request。
- 检查该 preview 是否属于预期的仓库和 app。
- 等待任何进行中的 preview deployment 完成。
- 从该 preview 切换走,或调用
resetPreview. - 列出该预览的 bundle ID。
- 删除每个已验证的 bundle。
- 删除预览记录。
- 将简短结果写入工作流摘要。
顺序很重要。如果先删除,活动的预览规则可能会阻止请求。如果跳过列表调用,你可能不知道哪些 bundle ID 仍然存在。如果通过猜测的名称删除,你有可能误操作错误的资源。

使用以拉取请求编号为键的并发规则。当关闭事件和重建事件几乎同时到达时,旧的清理任务不应与新部署竞争。取消过时的清理运行,或让任务等待直到部署锁释放。
Capgo 的单命令 CLI 工作流可以减少构建和发布工作周围的自定义 shell 调用。有关命令名称和支持的操作,请查看 Capgo CLI 命令文档。在提供经过验证的命令时使用 CLI。在清理操作需要直接请求时使用 SDK 或公共 API。
不要将清理放在每次推送都运行的工作流中。推送任务可能会删除仍在测试中的预览。关闭事件是正常清理的正确触发器。添加手动工作流调度以在任务失败时进行恢复。
也要设置保留回退。如果错过关闭事件,计划任务可以查找早于团队允许测试窗口的预览。该任务需要比正常关闭钩子更严格的安全措施。它应该只选择具有明确所有者和过期时间戳的预览。
对于 GitHub Actions,请保持权限最小化,仅传递清理步骤所需的值。Capgo 当前的 GitHub Actions 集成文档说明了 token 的存储位置以及工作流如何连接到 Capgo。
至此,你应该已经有一条自动化路径:响应关闭事件、等待竞争任务、重置活跃状态、列出 ID,并仅删除匹配的 bundle。这对日常开发来说足够快,又不会让清理变成盲目清扫。
步骤 6:验证清理结果并防止 Rollout 被误删
验证环节完成了 Capgo Pull Request 预览清理的闭环。仅凭删除响应不足以保障安全的发布流程。
清理任务运行后,再次检查预览 channel。确认它不再显示为活跃预览。然后按相同的应用和过滤条件检查 bundle 列表。预期结果是目标 bundle ID 已消失,而生产 bundle 仍然存在。
将这些值保存到 Job Summary:
- 仓库和 Pull Request 编号。
- 预览 channel 名称。
- 用于所有权检查的 Commit SHA。
- 找到的 Bundle ID。
- 已删除的 Bundle ID。
- 返回错误的 ID。
使用清晰的状态标识。“已清理”表示所有已验证的目标均已移除。“原本干净”表示本次运行前该资源已不存在。“需人工审查”表示一项或多项检查失败。切勿将部分删除标记为成功。
在 code 中添加生产环境防护。拒绝默认或 release 渠道名称。如果 bundle 元数据与预览应用不匹配,也拒绝该 bundle。防护机制应默认失败(fail closed)。当脚本无法确定目标时,应停止执行。
将回滚与清理分开处理。回滚改变设备接收的 bundle,而清理移除旧的预览资源。如果测试在 Pull Request 关闭后发现 bug,可能需要该 bundle 进行调查。如果团队常在合并后调试,请设置较短的保留窗口,而不是在事件到达时立即删除。
注意以下三种常见故障模式:
- 活动预览错误: 在重试“删除预览”之前,先重置或切换离开。
- 缺少 bundle ID: 重新运行 list 操作,而不是猜测。
- 权限错误: 检查密钥范围,如有需要则签发新密钥。
根据安全策略设定的时间表轮换清理密钥,如果密钥出现在日志或 commit 中,则立即轮换。除非泄露需要立即吊销,否则应在吊销旧密钥之前测试新密钥。
清理功能周围的文档空白值得在安全审查中特别注明。请将 SDK 和经过验证的 Capgo 指南作为实现依据,并将您自己的请求契约纳入版本控制。
核心要点: 删除后验证预览和 bundle 列表,在 code 中阻止生产目标,并将部分清理报告为失败。
只有当护栏清晰时,单条命令才真正有用。跟踪预览。采用可预测的 channel 名称。单独回滚发布变更。然后让清理任务完成其小职责,而不触及实时流量。
常见问题
我可以删除一个活动的 Capgo pull request 预览吗?
不可以。必须先切换掉活动预览,或者调用resetPreview。在活动状态清除后,运行 Delete Preview。这是在 CI 中设置 Capgo pull request 预览清理 API 密钥时需要记住的主要细节。
清理 Capgo 预览需要 bundle ID 吗?
需要。Capgo 的 Delete Bundle 操作需要 bundle ID,因此在删除前先列出可用的 bundle。将每个 ID 与预览 channel 和 commit 匹配,然后再发送删除请求。切勿从分支名称构建 ID,也不要假设删除预览会移除所有 bundle。
CI 应使用哪种类型的 API 密钥进行预览清理?
使用受限的 App Preview 密钥进行预览清理,并将其存储在 CI 提供商的加密密钥存储中。将密钥限制在所需的应用或作用域内。将其与用于发布生产更新的密钥分开。这样 Capgo 清理任务更易于审查,轮换也更安全。
我可以在 Pull Request 关闭时自动执行清理吗?
可以。在 Pull Request 关闭事件中触发清理,然后等待正在运行的部署任务结束,再重置预览。列出 bundle ID,删除已验证的匹配项,并确认结果。添加并发控制,避免迟到的构建与清理任务发生竞争。
为什么我的 Capgo 清理请求失败?
常见原因包括预览仍处于活跃状态、缺少 bundle ID,或密钥缺少所需的作用域。先重置预览,再重新执行 list 调用,并检查密钥权限。由于请求详情可能因 API 或 SDK 版本而异,修改脚本前请确认当前的方法和参数。
总结
使用 Capgo 配合专用预览密钥和严格的清理顺序:重置活跃预览,列出其 bundle ID,删除已验证的 bundle,然后移除预览。先针对一个已关闭的 Pull Request 做试运行,确认当前 SDK 中的请求结构,并在启用自动清理前添加生产通道保护。