last30days-skill:Towncrier 变更日志分片 + 自动化 Lockstep 发布 PR 的工程实践 last30days-skillTowncrier 变更日志分片 自动化 Lockstep 发布 PR 的工程实践【免费下载链接】last30days-skillAI agent skill that researches any topic across Reddit, X, YouTube, HN, Polymarket, and the web - then synthesizes a grounded summary项目地址: https://gitcode.com/GitHub_Trending/la/last30days-skill本文围绕 towncrier-lockstep-release.md 这一解决方案文档展开讲解 last30days-skill 如何用 towncrier 变更日志分片changelog fragments加一套 GitHub Actions 工作流彻底消除CHANGELOG.md的合并冲突并把一次版本发布需要同步的十余个lockstep 版本面skill 元数据、pyproject、各插件与市场 manifest收敛成一条可复现的自动化流水线。读完本文你能理解多 Agent 协作仓库中谁来写 changelog、谁不能动版本号、发布 PR 如何自动生成与打标的完整机制并掌握可直接迁移到同类项目的配置与脚本设计。问题背景两条发布痛点该文档frontmatter 中applies_when列出的适用场景描述了三类典型症状正是本方案要解决的问题多 PR 同改## [Unreleased]造成合并冲突早期每个功能 PR 都直接编辑CHANGELOG.md的 Unreleased 小节每次发布列车合并时都会冲突手工发布漏改 marketplace JSON 版本号一次正确发布必须让同一个semver 同时出现在 skill frontmatter H1、pyproject.toml、uv.lock、Claude/Codex/Grok/Gemini 插件 manifest、以及两个 marketplace JSON 文件中——这些一致性由 tests/test_plugin_contract.py 的 lockstep 测试强制校验Agent 自由发挥发布步骤导致漂移该仓库的功能 PR 主要由 AI Agent 而非人类撰写如果发布规则不明确Agent 会发明出与test_plugin_contractlockstep 约定不一致的发布步骤。文档给出的根因分类是missing_workflow_step缺失工作流步骤解决类型是workflow_change流程变更。一个值得注意的权衡记录在文档中release-please 并非不能做但它要求维护一大片extra-files配置面并依赖 conventional-commit 纪律而 Agent 提交流量并不能可靠地提供这种纪律——因此项目选择了自写脚本 强守卫的路线。解决方案总览五个组件文档给出的方案由五个组件构成下面逐一结合仓库中的真实实现展开。1. towncrierPR 只加分片CHANGELOG 只在发布时生成PR 不再触碰CHANGELOG.md而是向changelog.d/目录添加编号.类型.md分片CHANGELOG.md只在发布时刻由 towncrier 汇总写入。贡献者指南见 changelog.d/README.md其核心规则不需要安装 towncrier CLI 即可贡献分片就是普通 Markdown 文件towncrier 只在发布准备时运行命名约定优先用 PR 或 issue 编号——changelog.d/number.type.md尚无关联 issue/PR 时用孤儿命名——changelog.d/.type.md或changelog.d/short-slug.type.md类型表Keep a Changelog后缀章节securitySecurityremovedRemoveddeprecatedDeprecatedaddedAddedchangedChangedfixedFixed内容要求一到两句使用者会在 release notes 里关心的话行为、文档或安装层面的影响分片正文可链接 issuetowncrier 也会自动从文件名链接编号。跳过规则纯杂务注释错字、无 release notes 价值的 CI 版本 pin 更新可以不加分片改为在 PR 模板勾选Skip changelog或添加skip-changelog标签。towncrier 的完整配置在 pyproject.toml 的[tool.towncrier]段[tool.towncrier] name last30days-skill directory changelog.d filename CHANGELOG.md start_string !-- towncrier release notes start --\n underlines [, , ] title_format ## [{version}] - {project_date} issue_format [#{issue}](https://github.com/mvanhorn/last30days-skill/issues/{issue})其后依次为security、removed、deprecated、added、changed、fixed六个[[tool.towncrier.type]]段每个都设置showcontent true。towncrier 本身放在 dev 依赖组中towncrier25.8.0,26即日常开发不引入、发布准备时由uv sync --group dev提供。start_string机制意味着CHANGELOG.md只在!-- towncrier release notes start --标记之后被 towncrier 管理历史内容不会被重写。2..github/scripts/prepare_release.py一次 towncrier build 全部版本面 bump发布准备脚本 .github/scripts/prepare_release.py 的职责是先运行towncrier build再把所有 lockstep 路径上的版本号统一抬升。用法仓库根目录执行python3 .github/scripts/prepare_release.py --bump patch python3 .github/scripts/prepare_release.py --version 3.19.0 python3 .github/scripts/prepare_release.py --bump minor --dry-run从源码可以确认它的行为细节参数--bump major|minor|patch与--version X.Y.Z二选一互斥组必选其一--dry-run只打印目标版本和 towncrier 草稿加--draft不写任何文件--skip-towncrier表示 changelog 已准备好、只 bump 版本面见 prepare_release.py#L168-L183安全闸拒绝把版本降级Refusing to downgrade拒绝在非 dry-run 下同版本重发Refusing to re-release见 prepare_release.py#L188-L197版本面清单JSON_VERSION_FILES覆盖.claude-plugin/plugin.json、.codex-plugin/plugin.json、.grok-plugin/plugin.json、gemini-extension.jsonMARKETPLACE_FILES覆盖.claude-plugin/marketplace.json、.grok-plugin/marketplace.json加上pyproject.toml、skills/last30days/SKILL.mdfrontmatterversion:与# last30days vX.Y.Z:H1 两处、uv.lock中name last30days-skill的 package 段共9 个文件见 prepare_release.py#L28-L38 与 bump_all#L151-L165精确替换SKILL.md 的 frontmatter 版本与 H1 版本各要求恰好一次匹配uv.lock要求恰好一个 last30days-skill package stanza任何多于一次或零次匹配都会SystemExit失败——这种 fail-closed 设计避免正则误伤见 bump_skill_md#L97-L108。3. GitHub Actions 三段式Prepare release → Tag release → Release发布链路由三个工作流串成对应文档中opens the release PR → createsvX.Y.Zon merge → existing Release workflow attaches artifactsaPrepare release.github/workflows/prepare-release.yml由workflow_dispatch手动触发输入为bumpchoicepatch/minor/major默认 patch与可选的显式version。流程为uv python install 3.12uv sync --group dev装好 towncrier运行prepare_release.py显式 version 优先于 bump并从pyproject.toml读回新版本号创建release/vX.Y.Z分支若远端已存在同名分支则中止防止覆盖git add白名单内的 12 个发布相关文件CHANGELOG.md、changelog.d、pyproject.toml、uv.lock、SKILL.md、各 plugin/marketplace JSON、gemini-extension.json暂存区为空则报错退出提示changelog.d 可能是空的以chore(release): bump version to X.Y.Z提交并推送用gh pr create建 PR打release标签PR 描述中自带测试计划含uv run pytest与tests/test_plugin_contract.py::test_versions_match_across_manifests检查项。bTag release.github/workflows/tag-release.yml监听 main 分支 push但只处理提交信息含chore(release): bump version to的 commit注意if:表达式必须整体加引号并用contains而非startsWith——裸冒号会让 YAML 解析失败且 merge commit 把 PR 标题放在 body 里需要逐行扫描。其内部校验链值得注意从提交信息中提取 VERSION 后再与pyproject.toml实际版本比对不一致则拒打 tag反查该 commit 对应的 PR要求 PR 携带仓库管控的release标签——仅有匹配的标题不能铸出 tag打 annotated tagvX.Y.Z并推送随后显式gh workflow run release.yml -f tagvX.Y.Z派发 Release 工作流因为GITHUB_TOKEN触发的 tag push 不会自动启动其他 workflow。cRelease.github/workflows/release.yml现有工作流在 tag 就位后附加.skill/.mcpb等发布产物。4. changelog-guardCI 层面的双向守卫.github/workflows/changelog-guard.yml 在每个 PR 的 opened/synchronize/reopened/labeled/unlabeled 事件上执行落实非发布 PR 不许动 CHANGELOG 和版本串这条规则。从 workflow 脚本可确认四条逻辑带release标签的 PR 直接放行版本与 CHANGELOG 编辑均允许非 release PR 修改CHANGELOG.md→ 失败报错提示Add changelog.d/n.type.md instead。有一个历史豁免一次性 towncrier 迁移用 start marker 替换旧的## [Unreleased]且未新增###小节被允许版本串比对对 9 个版本面文件pyproject.toml、uv.lock、SKILL.md、4 个 plugin JSON、2 个 marketplace JSON、gemini-extension.json用辅助脚本 .github/scripts/read_manifest_version.py 分别解析 base 与 head 两侧的版本任何差异即报Non-release PRs must not bump lockstep version strings。脚本注释里记录了一个真实教训此前内联的python3 -c版本解析块因缩进到 0 列导致 Actions 拒绝解析整个 workflow每次运行都是空 jobs 失败解析逻辑因此被抽到独立脚本引擎改动必须有分片当改动触及skills/last30days/scripts/*、skills/last30days/SKILL.md或mcp/*引擎/技能代码而 PR 既没有changelog.d/*.md分片README.md 除外也没有skip-changelog标签时守卫失败。5. PR 模板changelog 检查单 Agent 披露.github/PULL_REQUEST_TEMPLATE.md 把上述规则固化进每个 PR 的表单Changelog 小节明确要出现在下次 release notes 就在changelog.d/加分片不要编辑CHANGELOG.md或在功能 PR 中 bump 版本/manifest并提供两个勾选项——加changelog.d/pr-or-issue.type.md列出全部 6 种类型或勾选 Skip changelog纯杂务同时加skip-changelog标签Agent disclosure 小节要求总结编码 Agent 做了哪次 review查了哪些风险、标记了什么、据此改了什么以及安全审查项输入处理、命令执行、路径处理、认证、密钥、依赖风险无则写N/ARelationship to this change要求披露雇佣/合同/股权等与被集成厂商或产品的付费关联例如你在被集成的 API 厂商任职。Agent 规则文档原文核心逐条继承文档给出的Agent rules (short)是整套方案对 Agent 的契约原文三条必须原样执行写分片不写CHANGELOG.mdWrite fragments, notCHANGELOG.md功能 PR 中不许 bump 版本Do not bump versions in feature PRs通过 Prepare release 发布而不是手工编辑十个文件Cut releases via Prepare release, not by editing ten files。AGENTS.md 的 Changelog and releases (agents) 一节把这三条扩展为可操作的五步规范功能/修复 PR 在变更属于下次 release notes 时加changelog.d/pr-or-issue.type.md永不在功能 PR 中编辑CHANGELOG.md或在pyproject.toml、SKILL.md、plugin/marketplace JSON、uv.lock中 bump 版本CI 的 changelog-guard 会拦截无 release notes 内容时加分片豁免 skip-changelog标签发布走 Actions →Prepare releasepatch/minor/major合并后 Tag release 推送vX.Y.Z、既有 Release 工作流发布产物不要手编十个版本文件lockstep 闸门是tests/test_plugin_contract.py::test_versions_match_across_manifests工作流契约由tests/test_changelog_workflow.py锁定。本地等价命令为uv run python .github/scripts/prepare_release.py --bump patch需 Python 3.12环境用uv管理venv 在.venv/。契约测试把发布流程本身当成被测对象tests/test_changelog_workflow.py 是这套工作流的契约测试它证明了上述组件不是文档声明而是被持续验证的事实test_towncrier_config_present校验[tool.towncrier]段、分片目录、输出文件与 6 种分片类型齐备test_changelog_has_towncrier_start_marker要求CHANGELOG.md含 start marker 且不再包含## [Unreleased]旧冲突源被彻底移除;test_release_workflows_exist断言三个 workflow 文件存在test_tag_release_workflow_yaml_parses/test_tag_release_workflow_version_extraction直接回放 tag-release.yml 里的 sed 表达式验证它能同时解析直接 push与merge commit标题在 body两种提交信息形态test_changelog_guard_run_blocks_stay_indented用_assert_run_blocks_indented断言所有run: |块内不存在 0 列或欠缩进的行——这正是 workflow 脚本注释中提到的那次空 jobs 失败事故的回归防护test_next_version_bumps3.18.1 patch/minor/major → 3.18.2/3.19.0/4.0.0、test_main_refuses_equal_version_outside_dry_run、test_bump_all_updates_lockstep_surfaces在临时目录里搭出完整的 lockstep 布局bump 到 9.9.9 后逐一断言 9 个文件全部到位。小结与参考这套方案的设计要点可以概括为把 changelog 写入权收敛到单一发布时刻towncrier把版本号写入权收敛到单一自动化 PRprepare_release.py release 标签再用 CI 守卫changelog-guard与契约测试test_changelog_workflow.py把两条收敛线变成不可绕过的规则——在多 Agent 贡献的仓库里这比依赖 Agent 自觉遵守纪律可靠得多。延伸阅读文档 See also 一节指向的仓库内资源均为仓库根目录相对路径AGENTS.md § Changelog and releases (agents) —— Agent 视角的五步发布规范changelog.d/README.md —— 分片命名、类型表与 skip 规则tests/test_changelog_workflow.py —— 工作流契约测试相关配套.github/scripts/prepare_release.py、.github/scripts/read_manifest_version.py、.github/workflows/prepare-release.yml、.github/workflows/tag-release.yml、.github/workflows/changelog-guard.yml、.github/PULL_REQUEST_TEMPLATE.md、pyproject.toml[tool.towncrier]配置段、tests/test_plugin_contract.py版本 lockstep 测试。【免费下载链接】last30days-skillAI agent skill that researches any topic across Reddit, X, YouTube, HN, Polymarket, and the web - then synthesizes a grounded summary项目地址: https://gitcode.com/GitHub_Trending/la/last30days-skill创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考