Remotion 仓库的 Vercel 部署监控实战:SKILL.md 技能定义与 check-deployment.py 状态机实现解析
【免费下载链接】remotion🎥 Make videos programmatically with React项目地址: https://gitcode.com/GitHub_Trending/re/remotion
在 Remotion 开源仓库(Make videos programmatically with React)的 Agent 技能体系中,Vercel Monitor 负责回答一个高频问题:「我推上去的 PR 对应的 Vercel 部署,到底 ready 了没有?」本篇基于该技能目录下的 SKILL.md、check-deployment.py 与 openai.yaml,完整拆解其监控原则、部署定位策略、状态判定流程与心跳监控的创建方式。读完你可以掌握「如何把一个会漂移的 Vercel 预览链接,转化为一个可长期轮询、状态唯一可信的不可变部署引用」这一完整方案。
技能定位:什么时候会触发这个监控
SKILL.md的 frontmatter 定义了触发条件:当用户输入/vercel或$vercel、要求「监视/监控某个 Vercel 部署」「等待 Vercel 预览或 PR 预览就绪」「部署变成 READY 后同时告知 deployment URL 和 preview URL」时,技能生效。它的核心承诺写在标题下方:
Monitor one immutable Vercel deployment for the
remotionproject and notify the current task when that exact deployment becomes ready or fails.
即:只监控一个不可变的部署,并且只关心这个精确部署的成败。配套的 openai.yaml 给出接口元信息:
interface: display_name: 'Vercel Monitor' short_description: 'Monitor Vercel previews until ready' default_prompt: 'Use $vercel to monitor the remotion Vercel deployment and tell me when the preview is ready.'这说明该技能是面向 Agent(Codex)自动化的可执行指令集,而不是给人阅读的流程手册——文中大量使用 "must / never" 的强约束语句来消除 Agent 的自由发挥空间。
五条不可妥协的监控规则
文档用 "Non-negotiable rules" 一节开宗明义列出了五条铁律,这是整个技能的设计内核:
- 绝不从 HTTP 响应推断部署状态。分支预览别名(branch preview alias)可能在上一个部署上返回 200,而新部署还在构建中——curl 一个 200 不能证明新部署已上线。
- 绝不监控分支预览别名。别名是可移动的(movable),可能解析到更旧或更新的部署。
- 监控必须钉死在不可变引用上:Vercel 部署 ID(
dpl_...前缀)或不可变的自动部署主机名(<project>-<random>-<scope>.vercel.app)。 - 只读机器可读的部署状态,不解析人类可读的 CLI 输出。
- 默认项目与 scope 都是
remotion;bugs项目被明确排除,除非用户点名要它。
第 5 条与仓库现实对应:本仓库同时部署了两个 Vercel 项目——文档站(remotion)与 packages/bugs 的 bug 复现服务。监控器必须锁定remotion,否则会误报bugs项目的部署状态。
定位精确部署:四级优先来源
部署引用不唯一——同一个 PR 可能反复触发部署,所以第一步是「找到那个唯一的 deployment ID」。文档给出按优先级排列的四个来源:
| 优先级 | 来源 | 说明 |
|---|---|---|
| 1 | 用户直接提供的 Vercel 部署/dashboard URL | 最权威 |
| 2 | 活动 GitHub PR 上的Vercel – remotioncheck | dashboard URL 形如https://vercel.com/remotion/remotion/<deployment-id-suffix> |
| 3 | Vercel bot 在 PR 评论中的remotion行 | 与上一条互补 |
| 4 | vercel list remotion --scope remotion --format=json | 用.deployments[].meta精确匹配 PR、commit SHA 或分支 |
两条关键换算与匹配规则:
- dashboard URL → 部署 ID:取 URL 最后一段路径加
dpl_前缀。文档中的示例:https://vercel.com/remotion/remotion/AbCd1234对应dpl_AbCd1234。 vercel list匹配条件:选取满足全部已知身份字段的新部署——.name == "remotion"、已知 PR 时.meta.githubPrId == <PR 号>、已知 commit 时.meta.githubCommitSha == <完整 SHA>。文档特别强调:不要静默回退到另一个 commit;若无法精确定位,必须向用户索要 dashboard URL、PR 号或 commit SHA。
同时提醒:Vercel PR 评论里的Preview链接通常是分支别名,可以保留到最终通知里展示,但不得用于状态检查。
读取状态:check-deployment.py 检查器
文档规定从仓库根目录运行捆绑的检查器:
python3 .agents/skills/vercel/scripts/check-deployment.py <deployment-id-or-url>检查器内部实际调用:
vercel inspect <deployment-id-or-immutable-url> \ --scope remotion \ --format=json它对返回值做三件事:校验项目归属、拒绝会移动的别名、输出归一化的 JSON。上层只消费其中的state字段,其分类为:
| state | 语义 |
|---|---|
READY | 成功(终态) |
ERROR/CANCELED/CANCELLED | 失败(终态) |
BUILDING/QUEUED/INITIALIZING | 进行中 |
UNKNOWN | 非终态;仅当持续出现或阻碍建立可信监控时才上报诊断信息 |
补充一条纪律:HTTP 探测只允许在READY之后作为可选的可达性检查使用,永远不能把一个非 ready 或 unknown 的部署提升为READY。
源码级实现:check-deployment.py 逐段解析
check-deployment.py 只有约 170 行,是理解上述规则的最好载体。
1. 引用归一化(normalize_reference)。该函数接收三种输入(L22-L44):
- dashboard URL:host 为
vercel.com或www.vercel.com时,解析路径要求恰好三段/<scope>/<project>/<deployment>;若 URL 中的 scope/project 与期望值(默认remotion/remotion)不一致直接抛错,例如把bugs项目的 dashboard URL 传进来会被拒绝;最后一段若未带dpl_前缀则自动补上。 - 裸部署 ID:以
dpl_开头直接透传。 - 不可变主机名:以
.vercel.app结尾的 hostname 直接使用。 - 其余输入一律
ValueError:Expected a dpl_ deployment ID, dashboard URL, or vercel.app URL.
2. 子进程调用与错误兜底。检查器以check=False运行vercel inspect(L65-L97),三种失败路径统一收敛为state: "UNKNOWN"且退出码为 2:CLI 非零退出(附带 stderr 诊断)、stdout 不是合法 JSON、以及后续的归属校验失败。这保证了心跳轮询永远拿得到一份结构稳定的 JSON,而不是面对 CLI 的五花八门的报错文本。
3. 项目与 scope 归属校验(L99-L110):
name = deployment.get("name") context_name = deployment.get("contextName") if name != args.project or (context_name is not None and context_name != args.scope): # state: UNKNOWN, error: "Deployment belongs to a different Vercel project or scope."即便dpl_ID 是手敲的,也会在这里被挡住——防止监控到别的项目的部署。
4. 移动别名拒绝(L112-L130)。若用户传入的是.vercel.app主机名,检查器会与vercel inspect返回的规范主机名(deployment["url"])比对:两者不一致即判定为「会移动的别名」并拒绝,输出:
{ "state": "UNKNOWN", "error": "Refusing to monitor a moving Vercel alias.", "alias": "remotion-git-pr-1234.vercel.app", "currently_resolves_to": "remotion-abc123-vercel.vercel.app", "deployment_id": "dpl_..." }注意错误信息里同时给出了当前实际解析到的不可变主机名,方便调用方改用它重新发起监控。
5. readyState 状态机(L132-L144):
IN_PROGRESS_STATES = {"BUILDING", "QUEUED", "INITIALIZING"} FAILURE_STATES = {"ERROR", "CANCELED", "CANCELLED"} state = str(deployment.get("readyState") or "UNKNOWN").upper() if state == "READY": terminal, outcome = True, "success" elif state in FAILURE_STATES: terminal, outcome = True, "failure" elif state in IN_PROGRESS_STATES: terminal, outcome = False, "in_progress" else: terminal, outcome = False, "unknown"终态(terminal: true)分成功与失败两类;注意失败集合同时容纳CANCELED和CANCELLED两种拼写,这是对上游字段取值不统一的防御。
6. 归一化输出。成功路径上检查器输出包含state、terminal、outcome、deployment_id、deployment_url(由规范主机名拼出)、dashboard_url(若未随输入提供则按https://vercel.com/{scope}/{project}/{去掉 dpl_ 前缀的 ID}反推)、preview_aliases(由deployment["aliases"]生成,仅供最终通知展示)、project、scope、created_at的 JSON。--scope与--project参数默认值均为remotion,与 SKILL.md 的「默认 remotion 项目与 remotion scope」规则一一对应。
创建监控:一分钟心跳与自包含提示词模板
文档的 "Create the monitor" 一节规定:使用 Agent 的自动化能力创建一个一分钟一次、有次数上限(通常 30 次,即约 30 分钟窗口)的心跳。心跳提示词必须自包含,包含六个要素:钉死的部署 ID 或不可变主机名、dashboard URL、已知的分支预览别名(仅用于最终通知)、项目/PR/分支/commit 上下文、精确的检查器命令、以及上文全部终态规则。
文档给出了逐字模板:
Monitor this exact Vercel deployment until it reaches a terminal state. Pinned deployment: <dpl_id_or_immutable_hostname> Dashboard: <dashboard_url> Preview alias (reporting only; never use for state): <preview_url_or_unknown> Context: <project/pr/branch/commit> From the repository root, run: python3 .agents/skills/vercel/scripts/check-deployment.py <pinned_deployment> Only the JSON `state` is authoritative. - READY: reply "Vercel deployment is ready" and include Dashboard and Preview. - ERROR, CANCELED, or CANCELLED: reply with the failure state and include both links. - BUILDING, QUEUED, INITIALIZING, or UNKNOWN: stay quiet and check again next time. Never curl the preview URL to determine readiness. After reporting a terminal state, delete or pause this heartbeat if its automation ID is available.模板里几个值得注意的工程细节:
stay quiet是显式要求:中间态不发消息,避免每 30 秒轰炸用户一次「还在构建中」。- 终态后自我清理:报告终态后应删除或暂停心跳(若自动化 ID 可用),防止僵尸监控。
- 预览别名在模板中被标注 "reporting only; never use for state",把「不可变引用做状态、别名只做展示」的双轨制直接写进每次心跳的指令里。
创建心跳前的最后一步:先跑一次检查器
文档结尾还有一条容易被忽略的流程约束:
Before creating a heartbeat, run the checker once. If the deployment is already terminal, report immediately instead. Otherwise, tell the user which exact deployment is being watched and the cadence.
即:建立心跳前先手动执行一次check-deployment.py。若部署已处于终态,立刻报告结果,根本不值得建心跳;否则要向用户交代「正在监视哪个精确部署、轮询节奏是什么」。这既避免了对已完成部署做无意义的 30 分钟轮询,也让监控行为对用户透明可审计。
与仓库内其他 Vercel 工作流的衔接
该技能并非孤立存在。pr 技能定义了 PR 创建后的预览链接流程:最多轮询 60 秒等待 Vercel bot 评论(间隔 5 秒),从remotion项目行(忽略bugs行)提取Preview链接并写入 PR body 的## Preview小节;且明确「只等 Vercel 评论出现,不等待部署完成、不创建 Vercel 心跳、不探测预览页」。可以看到两者职责清晰分层:pr 技能只负责拿到预览链接写进 PR,而真正的部署就绪监控全部交给本技能——一旦需要「等到 READY」,就走/vercel技能 +check-deployment.py的不可变引用监控路径。
小结:这套方案的可迁移设计
从 SKILL.md 到 check-deployment.py,这个不到 200 行脚本加一篇规则文档的小技能,示范了一套可迁移的「远程部署就绪监控」模式:
- 引用钉死:一切状态查询只针对
dpl_ID 或不可变主机名,别名仅用于展示; - 单一可信源:状态判定只认
vercel inspect --format=json的机器可读输出,state字段是唯一权威; - 状态机显式化:
READY成功、ERROR/CANCELED/CANCELLED失败、BUILDING/QUEUED/INITIALIZING进行中、其余一律UNKNOWN且不当作终态; - 失败收敛:CLI 报错、坏 JSON、项目/scope 不符、移动别名,全部归一为
UNKNOWN + 诊断信息 + 退出码 2,让上层轮询逻辑永远面对同一种结构; - 有限窗口轮询:一分钟心跳 × 30 次上限,终态即报即清理,先探测后建心跳。
对于任何在 CI 平台、边缘部署或 Serverless 环境需要「等某个精确构建就绪再通知」的 Agent 自动化场景,这套「不可变引用 + 归一化状态 + 有界心跳」的写法都可直接借鉴。
【免费下载链接】remotion🎥 Make videos programmatically with React项目地址: https://gitcode.com/GitHub_Trending/re/remotion
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考