背景
当前 Publish workflow 由 tag push 触发,也支持 workflow_dispatch 手工执行。当前执行顺序是:
- 回归与依赖审计
- 构建 wheel / sdist
- smoke test
- 发布到 PyPI
- 创建 GitHub Release 并上传构件
主干快照:1271d5c5e745792b50f54e256df34c6dad94b00a
相关实现:
.github/workflows/publish.yml:81-90
.github/workflows/publish.yml:3-7
现状观察
当前 workflow 与一些常见的单 job 发布流类似,但存在一个相似的恢复脆弱点:
- 如果第 4 步
Publish to PyPI 成功,而第 5 步调用 GitHub Releases API 失败(例如 GitHub API 瞬时 5xx、release action 瞬时失败、资产上传失败),workflow 会留下“tag 已存在、PyPI 已发布、GitHub Release 缺失”的半完成状态。
- 当前没有显式的“只补 GitHub Release”补偿入口;虽然 workflow 支持
workflow_dispatch,但没有输入开关来跳过 PyPI,因此手工重跑默认仍会尝试再次发布 PyPI。
- 当前也没有在仓库文档中明确说明当 PyPI 已成功而 GitHub Release 缺失时,维护者应如何安全补建 release。
实际结果
- 可能出现 PyPI 已成功、GitHub Release 缺失、workflow 失败的状态。
- 维护者若想补建 release,需要自行判断当前发布状态,并承担重复 PyPI 发布风险。
- 发布结果与 workflow 最终结论可能不一致,不利于发布审计与恢复操作。
预期结果
- GitHub Release 创建失败时,不应轻易留下难以安全补偿的半完成状态。
- 维护者应具备清晰、文档化、幂等的 GitHub Release 补建路径。
- 对 GitHub API 的瞬时失败应具备有限重试或明确补偿步骤。
建议方向
- 为 GitHub Release 创建 / 资产上传增加有限重试,降低 GitHub API 瞬时失败带来的误报。
- 为
workflow_dispatch 增加显式输入,例如 publish_to_pypi=false,使手工补建 GitHub Release 时不会默认重发 PyPI。
- 将 GitHub Release 创建收敛为可幂等补偿的步骤,例如先检查 release 是否存在,再只补缺失资产,避免破坏式覆盖。
- 在维护者文档中补充“PyPI 已成功、GitHub Release 缺失”时的恢复步骤。
验收标准
- 出现 GitHub Releases API 瞬时失败时,workflow 不会轻易留下不可安全重试的半完成状态。
- 维护者可以通过清晰、可重复执行的流程补建 GitHub Release,而不会默认触发重复 PyPI 发布。
- 发布流水线对外呈现的结论与真实发布状态更一致。
背景
当前
Publishworkflow 由 tag push 触发,也支持workflow_dispatch手工执行。当前执行顺序是:主干快照:
1271d5c5e745792b50f54e256df34c6dad94b00a相关实现:
.github/workflows/publish.yml:81-90.github/workflows/publish.yml:3-7现状观察
当前 workflow 与一些常见的单 job 发布流类似,但存在一个相似的恢复脆弱点:
Publish to PyPI成功,而第 5 步调用 GitHub Releases API 失败(例如 GitHub API 瞬时 5xx、release action 瞬时失败、资产上传失败),workflow 会留下“tag 已存在、PyPI 已发布、GitHub Release 缺失”的半完成状态。workflow_dispatch,但没有输入开关来跳过 PyPI,因此手工重跑默认仍会尝试再次发布 PyPI。实际结果
预期结果
建议方向
workflow_dispatch增加显式输入,例如publish_to_pypi=false,使手工补建 GitHub Release 时不会默认重发 PyPI。验收标准