Files
getDomain/docs/schemas/release_hub_contract.md
2026-04-18 23:52:51 +08:00

610 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# domainCheck Release Hub Contract
## 1. 目标
这份文档用于冻结 Release / Rollout / Launchpad / Gate 的正式 contract。
核心原则:
- 先有 Release再有 Rollout
- Release 是不可变版本对象
- Rollout 是分批推进对象
- Gate 是是否可发的统一门禁对象
- Launchpad 是给页面与 Codex 消费的发布驾驶舱对象
建议与 [ops_job_contract.md](/www/wwwroot/getDomain/docs/schemas/ops_job_contract.md:1) 配套阅读,因为 Rollout 的真正执行颗粒度最终仍然是 `ops job`
---
## 2. Release Object
来源:
- `POST /api/v1/ops/releases`
- `GET /api/v1/ops/releases`
- `GET /api/v1/ops/releases/latest`
- `GET /api/v1/ops/releases/{id}`
- `POST /api/v1/ops/releases/{id}/activate`
最小字段:
```json
{
"id": 1,
"release_version": "2026.04.18+bd6bcb2",
"channel": "stable",
"commit_sha": "bd6bcb2",
"status": "ready",
"status_label": "已就绪",
"artifact_url": "https://release.example.com/domaincheck-2026.04.18.tgz",
"checksum": "sha256:...",
"notes": "",
"metadata": {},
"created_by": "www",
"created_at": "2026-04-18 05:30:00",
"activated_at": "2026-04-18 05:35:00",
"summary": "2026.04.18+bd6bcb2 已就绪,制品与校验信息齐备,可进入 Rollout。",
"summary_text": "2026.04.18+bd6bcb2 已就绪,制品与校验信息齐备,可进入 Rollout。",
"focus_ref": {
"kind": "release_hub",
"release_id": 1,
"release_version": "2026.04.18+bd6bcb2",
"channel": "stable",
"rollout_id": 0,
"rollout_code": "",
"section": "release_detail"
}
}
```
约束:
- 同一 `release_version` 只对应一份发布物
- Release 创建后不应重新指向另一份 artifact
- `artifact_url + checksum` 是发布可验证性的最小基线
推荐状态:
- `draft`
- `ready`
- `active`
- `archived`
---
## 3. Rollout Object
来源:
- `POST /api/v1/ops/releases/{id}/rollouts`
- `GET /api/v1/ops/rollouts/{id}`
- `GET /api/v1/ops/rollouts/{id}/jobs`
- `POST /api/v1/ops/rollouts/{id}/advance`
最小字段:
```json
{
"id": 11,
"release_id": 1,
"rollout_code": "rollout-20260418-001",
"target_selector": {
"region": "mainland",
"role": "worker"
},
"target_nodes": [
"mainland-worker-01",
"mainland-controller-01"
],
"policy": {
"batch_size": 1,
"require_approval_between_batches": true,
"rollback_on_failure": true
},
"status": "running",
"status_label": "执行中",
"batch_cursor": 1,
"batches_total": 2,
"jobs_total": 2,
"jobs_created": 1,
"result_summary": {},
"target_node_codes": [
"mainland-worker-01",
"mainland-controller-01"
],
"summary": "当前已覆盖 1/2 台节点,仍有 1 条任务执行中。",
"summary_text": "当前已覆盖 1/2 台节点,仍有 1 条任务执行中。",
"focus_ref": {
"kind": "release_rollout",
"rollout_id": 11,
"rollout_code": "rollout-20260418-001",
"release_id": 1,
"section": "rollout_jobs"
}
}
```
正式定义:
> 某个 Release 在某批目标节点上的一次分批推进计划
推荐状态:
- `planned`
- `running`
- `awaiting_approval`
- `ready_for_next_batch`
- `halted`
- `completed`
- `completed_with_issues`
---
## 4. Default Rollout Gate
来源:
- `GET /api/v1/ops/overview`
- `overview.release_hub.default_rollout_gate`
这层是 Release Hub 最关键的后端 gate contract。
最小字段:
```json
{
"status": "attention",
"status_label": "待处理",
"status_type": "warning",
"summary": "当前已有 Release但默认目标节点中仍有未接管或未通过巡检的节点。",
"summary_text": "当前已有 Release但默认目标节点中仍有未接管或未通过巡检的节点。",
"release": {
"id": 1,
"release_version": "2026.04.18+bd6bcb2",
"status": "ready",
"status_label": "已就绪"
},
"execution_mode": "remote-agent",
"execution_mode_label": "Node Agent",
"target_node_codes": [
"mainland-worker-01"
],
"default_target_node_codes": [
"mainland-worker-01"
],
"blocking_reasons": [],
"warning_reasons": [
"存在未通过标准巡检的节点"
],
"recommendations": [
"先执行标准巡检,再进入 Rollout"
],
"operational_readiness": {
"summary": "remote-agent 就绪 1/2标准巡检通过 1/2",
"rows": []
},
"focus_ref": {
"kind": "release_hub",
"release_id": 1,
"release_version": "2026.04.18+bd6bcb2",
"channel": "stable",
"rollout_id": 0,
"rollout_code": "",
"section": "default_rollout_gate"
}
}
```
推荐状态:
- `missing_release`
- `release_not_ready`
- `artifact_missing`
- `no_targets`
- `blocked`
- `attention`
- `ready`
要求:
- 首页驾驶建议
- Release 页面门禁
- Rollout 预检
- Codex 自动驾驶
必须共用这同一份 Gate。
---
## 5. Default Rollout Execution
来源:
- `overview.release_hub.default_rollout_execution`
- `overview.release_hub.default_rollout_gate_options`
作用:
- 告诉页面 / Codex 这轮默认应使用什么执行方式
- 给出其他可选 gate / mode
最小字段:
```json
{
"recommended_mode": "remote-agent",
"recommended_mode_label": "Node Agent",
"recommended_gate": {},
"gates": {
"remote-agent": {},
"ssh": {}
}
}
```
推荐执行模式:
- `remote-agent`
- `ssh`
- `control-plane`
说明:
- 正式发布优先 `remote-agent`
- `ssh` 只作为首发接管与紧急救援兜底
- `control-plane` 不应用来承载大规模 Worker 发布
---
## 6. Release Launchpad
来源:
- `overview.release_hub.launchpad`
作用:
- 给页面与 Codex 提供更偏“驾驶舱”的发布聚合视角
最小字段:
```json
{
"latest_package": {},
"latest_release": {},
"worker_rollout_preview": {},
"control_rollout_preview": {},
"launchpad_status": {
"status": "attention",
"status_label": "待处理",
"summary": "建议先完成 Worker 点状灰度,再决定是否推进控制面。",
"summary_text": "建议先完成 Worker 点状灰度,再决定是否推进控制面。",
"recommended_action_code": "open_release_deploy_worker",
"recommended_target_node_code": "mainland-worker-01",
"recommended_recovery_label": "签发接入工单",
"recommended_recovery_summary": "当前节点仍处于接入阶段,建议先签发 onboarding.bootstrap。",
"onboarding_bootstrap_pending_nodes": 1,
"onboarding_acceptance_ready_nodes": 0,
"recommended_mode": "remote-agent",
"recommended_mode_label": "Node Agent",
"focus_ref": {
"kind": "release_hub",
"release_id": 1,
"release_version": "2026.04.18+bd6bcb2",
"channel": "stable",
"rollout_id": 0,
"rollout_code": "",
"section": "release_launchpad",
"mode": "worker"
}
}
}
```
`launchpad_status` 至少应回答:
- 当前先补什么
- 推荐动作码是什么
- 当前首个缺口节点是谁
- 当前恢复动作的人类标签是什么
- 当前缺口更偏“待接入”还是“待验收”
- 推荐执行方式是什么
- 先看 Worker 预案还是先看 Control 预案
正式约束:
- `recommended_target_node_code`
- 一旦 launchpad 已经收敛出首个缺口节点,就应直接返回
- 页面、CLI、Codex 不应再分别从 gap rows 中自行挑第一台
- `recommended_recovery_label`
- 是给人看的动作标题,例如:
- `签发接入工单`
- `补执行面接管`
- `执行接管验收`
- `recommended_recovery_summary`
- 是解释“为什么当前默认不是发版,而是先补接管”的正式摘要
- `onboarding_bootstrap_pending_nodes / onboarding_acceptance_ready_nodes`
- 是 launchpad 汇总层面的正式计数
- 允许被 `go-live-summary`、CLI 摘要、Codex brief 直接复用
---
## 7. 发布动作 contract
当前发布相关动作不应再退回“通用发任务”语义,而应正式区分:
- `deploy.release.control`
- `deploy.release.worker`
- `deploy.release.custom`
这三个动作必须共用:
- 同一份 Gate 判断
- 同一份 Release 版本对象
- 同一份 Rollout 编排结果
---
## 8. Artifact 不可变要求
上线前建议把 Release 供应链固定为:
1. 构建产物
2. 生成 `checksum`
3. 生成 `manifest`
4. 上传 artifact
5. 创建 Release
6. 激活 channel
7. 创建 Rollout
Node Agent 侧部署链路要求:
1. 下载 artifact
2. 校验 checksum
3. 解压到 `releases/<version>`
4. 切换 `current`
5. 重启服务
6. 健康检查
7. 失败回滚
---
## 9. Rollout 与 Ops Job 的关系
约束:
- Rollout 是分批推进对象
- Ops Job 是单次动作对象
- Rollout 通过一批或多批 `deploy.release.*` Job 落地
控制面责任:
- 决定下一批是否生成 Job
- 汇总 Job 结果
- 反推 Rollout 状态
- 决定是否暂停、继续或回滚
Node Agent 不负责:
- 推进下一批
- 修改 Rollout 策略
- 修改 Release 状态
---
## 10. 页面 / Codex 共同消费约束
以下对象必须作为稳定后端 contract 存在:
- `default_rollout_gate`
- `default_rollout_execution`
- `launchpad_status`
- `worker_rollout_preview`
- `control_rollout_preview`
页面只负责展示和少量交互兜底。
Codex 只负责消费后端给出的:
- 当前是否可发
- 建议先发哪一侧
- 应该使用什么 mode
- 下一步推荐动作是什么
---
## 11. Artifact Manifest Contract
Release Hub 不能只停在:
- `artifact_url`
- `checksum`
这只能证明“有个包”,还不能证明“这个包会把哪些服务改成什么样”。
建议把 `release.metadata.manifest` 固定为正式对象。
最小结构:
```json
{
"artifact_kind": "tarball",
"package_name": "domaincheck-2026.04.18+bd6bcb2.tgz",
"package_size_bytes": 186542331,
"checksum": "sha256:...",
"build_id": "build-20260418-001",
"commit_sha": "bd6bcb2",
"built_at": "2026-04-18 05:20:00",
"included_services": [
"domaincheck-api",
"domaincheck-worker",
"domaincheck-sync-agent",
"domaincheck-node-agent"
],
"required_env_keys": [
"NODE_CODE",
"NODE_REGION",
"NODE_ROLE"
],
"health_checks": [
{
"name": "api_health",
"type": "http",
"url": "http://127.0.0.1:8100/health"
}
],
"rollback_hint": "切回上一个 current 并重启对应服务"
}
```
正式要求:
- Release 创建后,`manifest` 不应再被覆盖成另一份语义不同的发布物
- Node Agent、页面、Codex 必须共用这同一份 manifest
- 是否可发、怎么回滚、要验哪些服务,不应再散落在:
- shell 脚本
- 页面表单
- 人工脑补
---
## 12. Operational Readiness Row Contract
`default_rollout_gate.operational_readiness.rows[]` 不应只是“几行提醒文案”,而应成为逐节点门禁对象。
最小结构:
```json
{
"node_code": "mainland-worker-01",
"region": "mainland",
"role": "worker",
"agent_managed": true,
"execution_mode_ready": true,
"execution_mode": "remote-agent",
"execution_mode_label": "Node Agent",
"inspection_status": "healthy",
"inspection_status_label": "已通过",
"current_release_version": "2026.04.11+1921318",
"desired_release_version": "2026.04.18+bd6bcb2",
"risk_level": "low",
"blocking_reasons": [],
"warning_reasons": [],
"recommended_action_code": "",
"focus_ref": {
"kind": "release_hub",
"release_id": 1,
"release_version": "2026.04.18+bd6bcb2",
"channel": "stable",
"rollout_id": 0,
"rollout_code": "",
"section": "default_rollout_gate"
}
}
```
正式要求:
- `rows[]` 应能直接回答:
- 这台节点能不能进下一轮 rollout
- 不能的话卡在哪
- 只是 warning 还是 hard block
- 页面、CLI、Codex 不应再从:
- inspection
- runtime
- nodes
三处数据手工拼门禁结论
推荐风险分级:
- `low`
- `medium`
- `high`
- `blocked`
---
## 13. Rollout Preview Contract
真正创建 Rollout 之前,还应保留一层正式 preview而不是由页面自己预估批次和风险。
建议入口:
- `POST /api/v1/ops/releases/{id}/rollouts/preview`
最小请求体:
```json
{
"release_id": 1,
"target_node_codes": [
"mainland-worker-01",
"mainland-controller-01"
],
"policy": {
"batch_size": 1,
"require_approval_between_batches": true,
"rollback_on_failure": true
},
"execution_mode": "remote-agent"
}
```
最小返回体:
```json
{
"release": {},
"execution_mode": "remote-agent",
"execution_mode_label": "Node Agent",
"target_nodes_total": 2,
"target_node_codes": [
"mainland-worker-01",
"mainland-controller-01"
],
"expected_batches_total": 2,
"expected_jobs_total": 2,
"gate": {},
"batch_plan": [
{
"batch_no": 1,
"node_codes": [
"mainland-worker-01"
],
"risk_level": "low"
},
{
"batch_no": 2,
"node_codes": [
"mainland-controller-01"
],
"risk_level": "medium"
}
],
"summary": "建议先灰度 1 台 Worker再推进 Controller。",
"summary_text": "建议先灰度 1 台 Worker再推进 Controller。",
"focus_ref": {
"kind": "release_hub",
"release_id": 1,
"release_version": "2026.04.18+bd6bcb2",
"channel": "stable",
"rollout_id": 0,
"rollout_code": "",
"section": "rollout_preview"
}
}
```
正式要求:
- preview 是:
- 页面发 rollout 前的统一预检
- Codex 自动驾驶发 rollout 前的统一预检
- CLI 批量发布前的统一预检
- 不允许前端重新自己算:
- 该分几批
- 哪台应该先发
- 哪台属于高风险
只有这样Release Hub 才是真正的发布控制面,而不是“能看版本的页面”。