feat(#60): 一键部署编排与回滚引擎
纯标准库实现,对齐 PRD 5.6「⑥ 部署底座」(不真执行 k8s/helm,模拟编排): - deploy_plan.py:DeployStep(4 类:pre_check/deploy/health_check/post_check) + DeployPlan(顺序约束自动校验,default_helm_release 默认 4 步计划)+ DeployOrchestrator(按序执行,必需步骤失败即中止并标记 needs_rollback, deploy/health_check 为回滚检查点,pre_check 失败无需回滚)+ HealthCheckContract(对齐 deploy/k8s/healthz 99.8% 目标)。 - rollback.py:RollbackPoint(部署前快照,values_hash SHA1 检测漂移)+ RollbackManager(快照栈 + rollback_to_latest/rollback(n),失败压回栈顶 保持一致性,FIFO 淘汰,支持回滚后健康检查)+ RollbackResult(4 状态)。 - tests:30 用例覆盖计划构造/顺序约束、全成功/各类失败、回滚检查点判定、 action 异常、dry_run、空计划、快照压栈/FIFO、回滚成功/失败/多版本/空栈/ 异常、健康检查契约、values 漂移、报告序列化。 - _sanity_check.py:冒烟验证快照→部署成功→部署失败→回滚全流程。
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""部署编排 + 回滚冒烟脚本(Issue #60)。
|
||||
|
||||
直接运行 ``python _sanity_check.py`` 验证:默认 Helm 计划全成功部署、
|
||||
快照压栈、模拟部署失败触发回滚到上一稳定版本。零第三方依赖。
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
|
||||
HERE = os.path.dirname(os.path.abspath(__file__))
|
||||
sys.path.insert(0, HERE)
|
||||
|
||||
from deploy_plan import ( # noqa: E402
|
||||
DeployOrchestrator, DeployPlan, DeployStepKind)
|
||||
from rollback import RollbackManager # noqa: E402
|
||||
|
||||
|
||||
def main() -> int:
|
||||
# 1) 部署前快照(当前稳定版本 v1.0.0)
|
||||
mgr = RollbackManager()
|
||||
stable = DeployPlan.default_helm_release(version="v1.0.0")
|
||||
mgr.snapshot(stable, reason="部署 v1.1.0 前的稳定版本")
|
||||
print(f"[OK] 快照压栈:稳定版本 {mgr.latest().version}")
|
||||
|
||||
# 2) 部署 v1.1.0 全成功
|
||||
new_plan = DeployPlan.default_helm_release(version="v1.1.0")
|
||||
report = DeployOrchestrator(new_plan).execute()
|
||||
assert report.succeeded, report.outcome.reason
|
||||
mgr.snapshot(new_plan, reason="v1.1.0 部署成功")
|
||||
print(f"[OK] 部署 v1.1.0 成功:{len(report.results)} 步,无需回滚")
|
||||
|
||||
# 3) 模拟 v1.2.0 部署失败(health_check 失败)→ 触发回滚
|
||||
def _bad_health(ctx):
|
||||
return False, "/health 503(服务未就绪)"
|
||||
bad_plan = DeployPlan.default_helm_release(
|
||||
version="v1.2.0",
|
||||
step_actions={DeployStepKind.HEALTH_CHECK: _bad_health})
|
||||
bad_report = DeployOrchestrator(bad_plan).execute()
|
||||
assert not bad_report.succeeded
|
||||
assert bad_report.outcome.needs_rollback
|
||||
print(f"[OK] v1.2.0 部署失败:{bad_report.outcome.reason}")
|
||||
|
||||
result = mgr.rollback_to_latest(reason="v1.2.0 健康检查失败")
|
||||
assert result.succeeded, result.detail
|
||||
print(f"[OK] 回滚到 {result.target.version}:{result.detail}")
|
||||
print("部署编排 + 回滚冒烟通过 ✅")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in New Issue
Block a user