dyro 采用 GitHub Actions 与 PyPI Trusted Publishing 发布。GitHub 不保存长期 PyPI Token;PyPI 仅在受信工作流运行时发放短期 OIDC 凭据。
- 已完成:MIT
LICENSE、PyPI 包元数据、构建与测试、.github/workflows/pypi-publish.yml,以及 PyPI 正式发布链路。 - 已完成:PyPI pending publisher 与 GitHub
pypiEnvironment。 - 每次新版本仍需创建严格匹配的 Git tag、GitHub Release,并在
pypiEnvironment 审批发布。
- 注册并验证 PyPI 账号。
- 进入 PyPI 的 Publishing 页面,添加 GitHub Actions 的 pending publisher:
- PyPI project name:
dyro - Owner:
DandreYang - Repository:
DyroEngineeringFlow - Workflow:
pypi-publish.yml - Environment:
pypi
- PyPI project name:
- 在 GitHub 仓库 Settings → Environments 创建
pypi,并设置至少一名不等于发起人的 required reviewer;关闭管理员绕过,限制为受保护的 release tag。仓库还应对main启用 required pull request review 与 required CI checks。
PyPI Trusted Publishing 将 GitHub Actions 的 OIDC 身份绑定到这个仓库、工作流和 Environment;不要为该工作流创建或保存长期 PYPI_TOKEN。
-
确认
pyproject.toml的project.version是未发布的新版本,例如X.Y.Z。 -
在创建 tag 前,将
CHANGELOG.md中对应版本的标题从Unreleased改为实际发布日期,并确认其内容准确。例如:## X.Y.Z - 2026-08-01发布工作流会验证这一状态;不要等到发布后再修改 changelog。
-
在本地使用锁定环境运行(不要临时
pip install --upgrade构建工具):uv lock --check uv sync --locked --all-extras --dev uv run python -m unittest discover -s tests -t . -v uv run ruff check src tests experiments uv run python -m build uv run python -m twine check --strict dist/dyro-*.whl dist/dyro-*.tar.gz
Release 工作流还会通过 GitHub Actions API 查询
ci.yml,严格要求当前 tag SHA 对应的 main push run 已completed + success;缺失、仍在运行、 失败、取消或 SHA 不匹配都会阻止发布。制品冒烟会确认 wheel/sdist 含 Codex Skill 资产,且不再提供dyro-bridge/dyro-mcp入口。 -
提交并推送版本变更,创建与版本严格匹配的 tag,例如
vX.Y.Z。 -
在 GitHub 基于该 tag 创建并发布 Release。工作流会验证 checkout 恰为该 tag、tag commit 是
origin/main的祖先、同一 SHA 的完整 CI 成功、uv.lock未漂移,再测试、构建、检查 metadata;通过pypiEnvironment 的人工批准后才上传 PyPI。 -
发布完成后验证:
pipx install dyro dyro --version
Git tag、GitHub Release、PyPI 版本和 changelog 必须指向同一版本。不要用 下一版的发布来掩盖上一版的状态;若旧版本被 yank 或不再可下载,应保留其 tag/Release,并在 changelog 或事故记录中写明状态与升级目标。
PyPI 不允许覆盖同一个版本号。发布失败后,如需修改分发文件或 metadata,必须递增版本号并重新创建 Release。
若 GitHub 的 release 事件没有自动生成工作流运行,可在 Actions 页面选择 Publish to PyPI → Run workflow,输入既有 tag(例如 vX.Y.Z)。手动入口会 checkout 该 tag,并严格校验 tag 必须等于 pyproject.toml 的版本且位于受信 main 历史上;它不会构建后续 main 提交。
先在 TestPyPI 用独立账号和 pending publisher 演练,可降低首次正式发布风险。TestPyPI 与 PyPI 的账号、项目和包文件相互独立;测试安装时使用 --index-url https://test.pypi.org/simple/ --no-deps。
发布包一旦发现安全、完整性或关键功能问题,发布负责人先停止后续 Release 和推广;不要删除 tag、GitHub Release 或 PyPI 文件来掩盖事件,它们是取证所需的不可变指针。
- 0–5 分钟: 项目所有者在 PyPI 项目管理页对受影响的整个版本执行 yank,并写明简洁、无机密的原因;在 GitHub Release 标题和正文标记
YANKED,记录版本、tag commit、发现时间和负责人。 - 5–15 分钟: 创建限制可见度的事故记录,保存测试失败、制品 SHA-256、受影响范围与缓解建议;公开说明必须提示用户,精确
==/===约束仍可能安装已 yank 版本。 - 15–60 分钟: 判断是否需要撤销 Trusted Publisher、轮换凭据或收紧 Environment;修复后递增版本、重新走完整锁定验证和人工批准,绝不复用或覆盖旧版本。
- 恢复: 使用 TestPyPI 先演练安装和 yank 通告;仅在修复版可安装、回归测试通过且事故记录写清升级路径后恢复推荐安装。
单人维护者无法自行提供独立审批:每次正式发布前必须在 Release/PR 留下版本、tag SHA、锁文件检查和风险接受记录,并启用 MFA 与可恢复的项目所有者账户。PyPI 的 yank 是可逆的索引标记,不会撤回已经下载的制品;具体操作和约束以 PyPI 官方 yanking 文档 为准。