
🎯 学 gstack 的代码冻结工作流:不是简单的"不许改代码",而是自动创建 release 分支、锁定 main 分支的变更窗口、在冻结期间管理 hotfix 例外、最终 unfreeze 时验证一切归位——让"大促封网"从微信群通知变成自动化工程流程。 ⏱️ 预计时间:25 分钟
[!quote]- 📖 原Skill精要 技能名称:freeze / unfreeze 核心功能:代码冻结——将会话中的文件编辑限制在指定目录,阻止越界修改。解锁后恢复正常编辑权限。用于调试时防止意外"修复"无关代码,或将修改范围锁定在单个模块内。本课程将其概念扩展为完整的发布冻结工作流(release 分支锁定 + hotfix 例外管理)。 所属体系:gstack 虚拟工程团队 协作关系:大促封网场景下配合 [[L6-25-发布上线管理|ship]] 的发布流程使用
§1 课程概览
freeze/unfreeze 将"大促封网"从微信群喊话升级为自动化工程流程。freeze 的四个步骤:确认冻结意图(原因、时长、hotfix 审批策略)→ 创建 release 分支(安全快照)→ 在 CLAUDE.md 中标记 FROZEN 状态 → 可选添加 CI 门禁(workflow 层面硬性阻止非 hotfix PR)。hotfix 例外通道通过 [HOTFIX] PR 标题前缀 + 审批链 + 审计日志,确保紧急修复不影响封网纪律。unfreeze 时的 git diff release/vX.Y.Z main 一致性验证是防止"幽灵合入"的最后防线。关键设计包括:gstack-upgrade 在冻结期间也被阻止(工具版本变更也是变更)、exclude-paths(docs/、feature-flags/)允许非代码变更。
[!tip] 白话小课堂 你有没有经历过"封网"——领导在群里喊"从今天起不许合代码",然后总有人"不小心"合了,理由千奇百怪。freeze 就是把这个口头约定变成代码层面的硬约束——CI 自动检测冻结状态,不是 [HOTFIX] 的 PR 直接拒绝,谁也"不小心"不了。
§2 代码冻结解决什么问题?
为什么需要 Freeze?
真实场景: → "双11前一周开始封网,只允许修复 P0 级别的 bug" → "APP 审核提交后的 3 天内冻结主分支" → "合规审计期间不允许任何代码变更"
传统做法: → 在 Slack/微信群里发通知 "从明天起封网!别合代码了!" → 有人忘了 → 合了 → 发布被打乱 → 群里吵架 → hotfix 需要特批 → 流程靠人记 → 容易出错
gstack freeze 的做法: → 自动创建 release 分支 → 在 main 上设置保护(通过 CLAUDE.md 标记 + CI 检查) → hotfix 有明确的例外通道 → unfreeze 时自动验证一切归位
💡 白话小课堂:你有没有经历过"封网"——领导在群里喊"从今天起不许合代码",然后你发现总有人"不小心"合了,理由千奇百怪:"我以为只是不许上新功能"、"这个 patch 很小不会有影响"、"运维让我改的配置"。
§3 Freeze 工作流——创建冻结
/freeze 的执行步骤
Step 1: 确认冻结意图
→ 询问冻结原因(大促封网 / 审核提交 / 合规审计 / 其他) → 询问冻结时长(到何时自动解冻,或手动 unfreeze) → 询问 hotfix 审批策略(谁可以批准 hotfix?)
Step 2: 创建 release 分支
→ git checkout -b release/vX.Y.Z main → git push origin release/vX.Y.Z → 这个分支是冻结期间的"安全快照"——如果生产出问题可以对比
Step 3: 标记冻结状态
→ 在 CLAUDE.md 中添加冻结标记:
markdown ## Freeze Status - Status: FROZEN - Since: 2026-05-03T12:00:00Z - Until: 2026-05-10T12:00:00Z(或手动 unfreeze) - Reason: 双11大促封网 - Hotfix approval: CEO review required
Step 4: 可选——添加 CI 门禁
→ 在 .github/workflows/ 中添加 freeze check job
→ 检查当前日期是否在冻结窗口内
→ 如果在冻结窗口内且不是 hotfix → 阻止合入
→ hotfix PR 必须包含 [HOTFIX] 标签才能通过
§4 Hotfix 例外通道——紧急修复不是封网漏洞
Hotfix 的设计哲学
封网不是为了阻止 fix,而是为了阻止不必要的变更。
Hotfix 的审批流程
- 开发者创建 hotfix 分支:git checkout -b hotfix/critical-bug
- PR 标题以 [HOTFIX] 开头
- PR 描述包含: → 为什么这个修复必须在封网期间进行 → 影响范围(多少用户受影响) → 风险等级(低/中/高) → 回退方案(如果修复引入新问题)
- 自动检查(如果配置了 CI 门禁): → 检查 PR 标题格式 → 检查是否已获得审批
- 获得审批后合入
gstack 的 hotfix 合规检查
→ /ship 和 /land-and-deploy 在冻结期间检测 CLAUDE.md 的 Freeze Status → 如果 FROZEN + PR 标题没有 [HOTFIX] → 阻止合入 → 如果 FROZEN + [HOTFIX] → 允许合入但记录审计日志 → 审计日志: ~/.gstack/projects/$SLUG/freeze-audit.jsonl
Hotfix 后的追踪
→ 每个 hotfix 记录: - PR 编号 - 合入时间 - 审批人 - 影响说明 → unfreeze 时汇总所有 hotfix 供回顾
⚠️ 避坑指南: hotfix 通道最大的风险不是"有人滥用",而是"定义不清晰导致该修的没修"。你需要提前明确:什么是 P0?
§5 Unfreeze 工作流——解冻与验证
/unfreeze 的执行步骤
Step 1: 确认解冻意图
→ 显示冻结信息:冻结开始时间、原因、时长 → 显示冻结期间的 hotfix 列表 → 确认是否解冻
Step 2: 验证一致性
→ git diff release/vX.Y.Z main → 查看冻结期间的变更 → 如果 main 上有不在 hotfix 列表中的变更: → WARNING: 冻结期间有未授权的合并 → 列出变更 → 需要确认是合法的还是违规的
Step 3: 同步 release 分支
→ git checkout release/vX.Y.Z → git merge main(将 hotfix 合并回 release 分支) → git push origin release/vX.Y.Z
Step 4: 清除冻结标记
→ 从 CLAUDE.md 中移除 Freeze Status 章节
→ 或更新为:
markdown ## Freeze Status - Status: UNFROZEN - Last freeze: 2026-05-03 to 2026-05-10 - Hotfixes during freeze: 3 (PR #142, #145, #147)
Step 5: 生成解冻报告
→ 冻结期间统计: - 冻结时长 - Hotfix 数量 - 违规合入数量(如有) - Release 分支与 main 的 diff 统计 → 报告写入 ~/.gstack/projects/$SLUG/freeze-reports/
§6 与 CI/CD 的深度集成
CI 冻结门禁工作流
# .github/workflows/freeze-gate.yml # CI 冻结门禁工作流
name: Freeze Gate # 冻结门禁
on:
pull_request: # PR 事件触发
branches: [main] # 目标分支为 main
jobs:
check-freeze: # 检查冻结状态的任务
runs-on: ubuntu-latest # 运行在 Ubuntu 最新版
steps:
- uses: actions/checkout@v4 # 检出代码
- name: Check freeze status # 检查冻结状态
run: |
if grep -q "Status: FROZEN" CLAUDE.md; then # 检测 CLAUDE.md 中的冻结标记
if [[ "${{ github.event.pull_request.title }}" != *"[HOTFIX]"* ]]; then # 非热修复 PR
echo "❌ Repository is FROZEN. Only [HOTFIX] PRs are allowed." # 仓库已冻结,仅允许热修复
exit 1
else
echo "⚠️ Hotfix PR detected during freeze. Proceeding with caution." # 冻结期间检测到热修复,谨慎放行
fi
else
echo "✅ Repository is not frozen. Normal PR flow." # 仓库未冻结,正常 PR 流程
fi
翻译:此 GitHub Actions 工作流作为 CI 冻结门禁,在每次向 main 分支提交 PR 时自动执行。它检查仓库的 CLAUDE.md 文件中是否标记了
Status: FROZEN。如果已冻结,则仅允许标题包含[HOTFIX]的 PR 通过,其余一律拒绝并退出;如果未冻结,则正常放行所有 PR。
gstack freeze 命令的 CI 集成点
→ /freeze: 添加 freeze check job 到 workflow → /ship: 检测冻结状态 → 阻止普通 PR → /land-and-deploy: 检测冻结状态 → 阻止普通合入 → gstack-upgrade: 不自动升级冻结仓库
🔑 核心秘诀:gstack-upgrade(gstack 自升级)在冻结期间也被阻止——这不是 bug,是有意设计的。
§7 电商 Skill 案例:双11大促代码冻结策略
🛒 实战案例:某电商平台(日均GMV 5000万)在双11前10天启动代码冻结。往年封网期的痛点:CTO在群里喊“封网了!”但运营要改文案开了特批、产品要调配置也开了特批、后端说“就改一行性能优化”凌晨偷偷合了代码、双11当天上午出现支付模块异常——“谁把支付模块改了?!”。用gstack freeze/unfreeze将封网自动化、例外通道透明化、解冻验证严格化。
- 冻结创建(/freeze):
/freeze --reason “双11大促封网” --until “2026-11-12T00:00:00+08:00” --hotfix-approval “CTO + 2 senior engineers” --exclude-paths “docs/**, config/feature-flags/**”。执行结果:创建release/v2026.11.01快照分支、CLAUDE.md标记FROZEN状态、CI添加freeze-gate check job(阻止非[HOTFIX]前缀的PR合入)、排除路径docs/config不受封网影响。- 封网期间统计(10天):总合入请求31个→自动阻止23个(普通feature PR)→Hotfix通过8个——[HOTFIX]修复支付回调超时(P0,影响所有用户)、[HOTFIX]修复商品搜索ES索引不同步(P1)、[HOTFIX]修复优惠券面额计算精度损失¥0.01(P1)、[HOTFIX]修复物流状态推送延迟(P1)、[HOTFIX]修复首页banner图片CDN 404(P2)、[HOTFIX]修复Redis连接池泄漏导致慢查询(P0)、[HOTFIX]修复订单状态机PENDING→CONFIRMED转换丢失(P0)、[HOTFIX]修复运费模板边界值0元商品(P2)。审批分级:P0只需CTO一人批准(2个)、P1需CTO+1位senior(4个)、P2需团队讨论(2个,其中有1个被推迟到解冻后)。
- 解冻验证(/unfreeze):双11结束后执行
/unfreeze→验证项——main上8个hotfix全部合规([HOTFIX]前缀+审批链完整)、0违规合入、release快照分支已同步所有hotfix、git diff release/v2026.11.01 main一致、清除CLAUDE.md FROZEN标记→生成Freeze Report归档。
- 电商封网最佳实践:排除路径设置为docs/、config/feature-flags/、.github/(不影响生产运行的非代码变更不冻结)。Hotfix分级——P0立即修(影响支付/下单,审批CTO 1人)、P1 24小时内修(影响体验但非阻断)、P2讨论是否等到解冻(非紧急)。每个hotfix必须有revert plan(万一修出问题怎么回退)。CI门禁在/ship和/land-and-deploy中内嵌freeze检查(冻结期间拒绝非hotfix部署)。
🔑 启示:代码冻结不是为了“阻止一切变更”——而是为了让变更从“默默无闻的合入”变为“透明的、有审批链的、有回退预案的例外”。往年封网期23个违规合入→使用freeze后0违规合入——不是写代码的人变谨慎了,是系统让违规合入变得不可能。
[!info] 参考来源 此案例参考了电商行业封网最佳实践,CI门禁模式参考了 GitHub Actions deployment protection rules 的设计理念。
§8 结构拆解
freeze/unfreeze 结构模板
核心特征
- 管理对象: main 分支在特定时间窗口内的变更权限
- 核心原则: 封网不是为了阻止 fix,而是为了阻止不必要的变更——hotfix 有明确的例外通道和审批链
- 关键设计: CLAUDE.md 标记 + CI 门禁双重锁定 + [HOTFIX] 前缀例外 + unfreeze 一致性验证
通用结构
- 冻结创建层 (/freeze): 确认意图(原因/时长/审批策略)→ 创建 release 分支(安全快照)→ CLAUDE.md 标记 FROZEN → 可选 CI 门禁
- 例外管理层 (hotfix): [HOTFIX] 标题前缀 → 审批链验证(P0/P1/P2 分级)→ 审计日志记录(freeze-audit.jsonl)
- 解冻验证层 (/unfreeze): git diff release/vX.Y.Z main 一致性检查 → 同步 release 分支 → 清除 FROZEN 标记 → 生成解冻报告
- CI 集成层: freeze-gate.yml → /ship 检测 → /land-and-deploy 检测 → gstack-upgrade 阻止
- 排除路径: docs/, config/feature-flags/(允许非代码变更在冻结期间继续)
§9 掌握检验
Q1:freeze 的四个关键步骤的正确顺序是什么?
- A) 创建 release 分支 → 标记冻结状态 → 确认冻结意图 → 添加 CI 门禁
- B) 确认冻结意图 → 创建 release 分支 → 标记冻结状态 → 添加 CI 门禁
- C) 标记冻结状态 → 创建 release 分支 → 添加 CI 门禁 → 确认冻结意图
- D) 添加 CI 门禁 → 创建 release 分支 → 确认冻结意图 → 标记冻结状态
Q2:hotfix 例外通道中,CI 门禁对 [HOTFIX] PR 的判断逻辑是什么?
- A) 只要标题包含 [HOTFIX] 就自动合入,不需要审查
- B) 检测 CLAUDE.md 的 Freeze Status:FROZEN + [HOTFIX] 标签 → 允许合入但记录审计日志;FROZEN + 无 [HOTFIX] → 阻止
- C) [HOTFIX] PR 绕过所有 CI 检查直接部署到生产
- D) hotfix 只在工作时间允许,非工作时间自动阻止
Q3:hotfix 定义不清晰是封网最大的管理风险。请给出 P0(系统完全不可用 / 数据丢失 / 资金损失)、P1(核心功能受影响但系统仍可用)、P2(边缘情况、可等到解冻)的具体区分标准。然后分析:如果 P0 定义太窄("只有数据库挂了才算 P0")会导致什么工程后果?如果 P0 定义太宽("任何影响用户的 bug 都是 P0")又会导致什么管理后果?
Q4:unfreeze 时的一致性验证中,如果 git diff release/vX.Y.Z main 发现 main 上有不在 hotfix 列表中的变更,这意味着什么?请列出可能的三种情况(从"完全合规"到"严重违规"),以及每种情况应该如何处理。
Q5:gstack-upgrade(gstack 自升级)在冻结期间也被阻止——这不是 bug,是有意设计的。请从"工具版本变更带来的行为差异"角度,解释为什么"写代码的工具"本身在封网期间也应该冻结。给出一个具体场景:gstack 的一个自升级可能如何间接导致生产问题。
Q6:电商封网场景中,为什么要把 docs/ 和 config/feature-flags/ 设为排除路径?这种排除策略虽然合理但并非零风险——请分析:如果 feature-flags 被排除在封网之外,一个不当的 feature flag 变更如何可能绕过封网导致生产事故?如何设计 feature-flags 的变更审批机制来弥补这个风险?
§10 答案
点击查看答案
Q1:B —— 正确顺序:确认冻结意图(原因、时长、hotfix 审批策略)→ 创建 release 分支(安全快照)→ 标记冻结状态(CLAUDE.md 中写入 FROZEN 标记)→ 添加 CI 门禁(workflow 层面硬性阻止)。
Q2:B —— CI 门禁检测 CLAUDE.md 的 Freeze Status:如果 FROZEN + PR 标题没有 [HOTFIX] → 阻止合入;如果 FROZEN + [HOTFIX] → 允许合入但记录审计日志。
Q3:P0 定义:系统完全不可用(所有用户无法访问 / 支付完全中断)、数据丢失(订单数据丢失 / 用户数据丢失)、资金损失(正在发生的金额错误)。P1 定义:核心功能受影响但系统仍可用(搜索功能不可用但浏览可以 / 优惠券失效但原价下单可以)。P2 定义:边缘情况(某浏览器版本样式错乱 / 极少触发的非核心 bug)。P0 太窄的后果:真正影响用户体验但没有"挂掉"的 bug(如支付成功但订单状态不更新——用户钱扣了但没订单)得不到修复——用户投诉爆炸。P0 太宽的后果:封网成了摆设——"这个文案不对"也成了 P0,特批通道被挤爆——7 天封网期间 18 个 bug 全部被标为 P0,封网失去了减少变更的核心目的。
Q4:三种情况:①完全合规——main 上所有变更都在 hotfix 列表中(每个变更都能追溯到审批记录)→ 直接解冻。②部分合规——有一个不在列表中的变更,但它是合法的(如运维通过 CI 自动化推送的配置更新)→ 需要确认来源后记录到审计日志中。③严重违规——有人绕过了 CI 门禁(直接 git push 到受保护的分支 / 用了 admin 权限)→ 立即调查、确认变更内容、评估是否需要回退、将违规记录上报。对于违规变更,即使它本身是无害的(如只是改了 README),也需要处理——因为违规行为比违规内容更严重(它打破了流程信任)。
Q5:具体场景:gstack 的一个自升级修改了 /review 的代码审查清单——增加了一个新的规则"检查所有 API 端点是否有 rate limiting"。一个新人在封网期间合入 hotfix 时,/review 按新规则扫描——发现"这个 hotfix 修改的端点没有 rate limiting",标记为 WARNING。但这是误报——原来的代码也没有 rate limiting,这不是这次 hotfix 引入的问题。封网团队被这个 WARNING 分散了注意力,花时间调查这个"问题",延误了真正的 hotfix。教训:工具行为本身的变更也是一种"变更"——在封网期间,即使工具体验的微小变化也可能干扰已经建立的审查流程。
Q6:排除 docs/ 和 config/feature-flags/ 的合理性:文档变更不涉及生产代码(README 更新不会让用户报错);feature flag 变更是配置操作(打开/关闭功能开关),不改变代码执行逻辑。风险场景:假设一个团队在封网期间通过 feature flag 关闭了一个有 bug 的新功能→这个 flag 变更绕过了封网的 CI 门禁。但关闭 flag 后,另一个依赖该功能的模块(代码中假设 flag 为 ON)触发了一个未测试的代码路径→导致订单处理流程的部分数据丢失。弥补措施:feature flag 的变更应该有独立的审计日志(谁在何时改了什么 flag);feature flag 的变更应该触发 canary 监控(确认变更后系统仍然健康);关键 feature flag 的变更应该有二次确认机制(不是一个人能独立操作的)。封网应该封住代码变更——但 feature flag 是运行时配置,需要不同的治理机制而非简单的"也封住"。
(5/6 通过)
延伸阅读
- 下一步:[[L6-29-发布文档同步|发布文档自动同步]] —— 解冻后恢复正常发布,确保每次发版文档自动跟上
- [[L6-27-金丝雀监控|金丝雀监控]] —— 封网期间的 hotfix 部署后需要 canary 持续监控
- [[L6-25-发布上线管理|发布上线管理]] —— /ship 在冻结期间自动检测 FROZEN 状态

评论区
共 0 条评论