Skip to content

[ops] 记录发布流水线在 PyPI 成功后创建 GitHub Release 失败的脆弱点 #359

@liujuanjuan1984

Description

@liujuanjuan1984

背景

当前 Publish workflow 由 tag push 触发,也支持 workflow_dispatch 手工执行。当前执行顺序是:

  1. 回归与依赖审计
  2. 构建 wheel / sdist
  3. smoke test
  4. 发布到 PyPI
  5. 创建 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 发布。
  • 发布流水线对外呈现的结论与真实发布状态更一致。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions