| name | team-issue-publish-github |
| description | 将本地工程 issue 草稿发布到 GitHub Issues,并回写发布结果。Publish local engineering issue drafts to GitHub Issues and write back publication status. |
| license | MIT |
| metadata | {"author":"coolbeevip","version":"1.0"} |
| triggers | ["发布到 GitHub","发布 issue 到 GitHub","批量创建 GitHub Issues","把 issue 草稿发布到 GitHub","发布单个 issue 到 GitHub","帮我发 GitHub issue","publish to GitHub","publish issue to GitHub","create GitHub issues from drafts","create GitHub issue from draft","batch publish issues to GitHub","publish issue drafts to GitHub"] |
发布 GitHub Issue
这个技能用于把 team-prd-to-issues 生成的本地 issue 草稿发布到 GitHub Issues。默认会按依赖顺序发布整个 slug 下的所有 issue;如果用户指定单个 issue,则只发布那一个。它关注“可重复执行、可追踪、可恢复”,避免重复创建和依赖顺序错误。
v1 仅支持 GitHub。不要在同一个技能中混合 GitHub 与 GitLab 发布逻辑;GitLab 请使用独立技能。
触发边界
- 适合触发:本地 issue 草稿已生成,目标远端是 GitHub Issues,需要发布并回写状态。
- 不适合触发:目标远端是 GitLab 时,转交
team-issue-publish-gitlab;用户要实现 issue 时,转交 team-issue-implement 或 team-issue-batch-implement。
运行时配置
统一读取目标项目根目录 team-spec/config.yml:
language: zh-CN
version_control:
system: git
trunk_branch: main
contribution_model: fork-pull
source_remote: origin
target_remote: upstream
access_policy:
mode: default-readonly
directory_file: team-spec/access_policy/default.md
user_file_template: team-spec/access_policy/{user_name}.md
语言优先级:用户本轮明确指定或脚本 --language > team-spec/config.yml > en-US 兜底。若配置不存在,技能执行时应先按团队规范询问语言偏好并创建配置;固定脚本独立运行时不交互,使用 en-US 兜底。
远端 GitHub Issue 正文模板标题、兜底文案和检查项必须使用 language;本地草稿已有内容保持原文。
仓库定位优先级:用户显式参数 > team-spec/config.yml 的 version_control > git 命令推断 > 询问用户。若 version_control 缺失,先用 git remote -v、git branch --show-current、git config --get branch.{branch}.remote 和 remote URL 推断;无法唯一判断时再询问用户,并在用户确认后回写 team-spec/config.yml。
- 在读取 issue 草稿、仓库内容或远端发布前,先读取
team-spec/config.yml;如果存在 access_policy,先应用目录访问边界,再进入任何发布流程。
固定脚本
发布 GitHub issue 时,优先使用本技能目录下的固定脚本,不要临时重写 GitHub API 调用代码:
./scripts/publish_github_issues.py
脚本依赖同目录下的公共辅助模块 ./scripts/_team_common.py(vendored copy,与仓库根目录 scripts/_team_common.py 保持同步)。复制本技能目录时需一并复制该文件。
脚本能力:
- 读取
team-spec/active/{slug}/issues/ 或显式 --issues-dir,并兼容旧布局 team-spec/active/issues/{slug}/。
- 默认发布该目录下全部 issue;也可以通过
--issue 只发布指定的单个 issue。
- 按
Blocked by 生成依赖顺序。
- 使用
./scripts/templates/issue_body.md.tpl 按 language 渲染 GitHub 友好的 issue 正文,固定包含摘要、验收清单和实现备注;正文只保留对协作有用的摘要字段,不直接发布完整草稿原文。
- 发布前会校验 issue 标题是否足够清晰:必须来自明确的
# 标题或 Title 段,不能回退到文件名;标题过短、过泛或缺少对象时会拒绝发布。
- 从显式
--repo、team-spec/config.yml 或 git remote 推断 GitHub 仓库,多个 remote 时按配置优先,其次优先 upstream。
- 默认 dry-run,只输出发布计划。
--execute 时创建 GitHub Issues,并把发布结果回写到本地 issue 草稿。
- 使用
Local-Issue-Key 做幂等检查,避免重复创建。
推荐 dry-run:
python3 {skill_dir}/scripts/publish_github_issues.py --slug {slug}
用户确认后正式发布:
GITHUB_TOKEN=... python3 {skill_dir}/scripts/publish_github_issues.py --slug {slug} --execute
其中 {skill_dir} 是当前技能目录。技能内部定位脚本时应使用相对 SKILL.md 的路径 ./scripts/publish_github_issues.py,执行命令时再解析成实际文件路径。
常用参数:
--issue 001-add-export-filter.md:只发布指定的单个 issue,可传入文件名、文件路径或草稿标识。
--github-url https://github.example.com:GitHub Enterprise。
--repo owner/repo:显式指定仓库,优先级高于 remote 推断。
--remote upstream:显式指定用于推断仓库的 remote;不传时优先参考 team-spec/config.yml 的 version_control.target_remote。
--label label-name:可重复传入多个 label。
--milestone 123:指定 milestone number。
--assignee octocat:可重复传入多个 assignee login。
--force:忽略本地 Publish Status,重新检查 GitHub;仍会使用远端 Local-Issue-Key 做幂等检查,不应直接重复创建。
--language zh-CN:显式覆盖远端 issue 正文模板语言;不传时读取 team-spec/config.yml。
--json:输出机器可读 JSON。
标题规则:
- 优先使用 issue 草稿里的
# 标题,其次使用 Title 段的首行。
- 不允许退回到文件名作为标题来源。
- 标题建议至少包含动作、对象和范围,不要只写
Fix、Update、Refactor 这类泛化词。
- 标题过短、过长或缺少足够语义时,脚本会停止发布并提示修正。
正文模板规则:
- 远端 GitHub Issue 正文应面向人类协作阅读,不要把本地草稿 Markdown 原样作为正文。
What to build 映射为 Summary / 摘要。
Acceptance criteria 转换为适合人类阅读的可勾选验收清单;本地草稿里的 Given/When/Then 验收场景不得原样发布到远端正文。
Notes 映射为 Implementation notes / 实现备注。
Parent、Type 和 Blocked by 不进入远端 issue 正文;Blocked by 仅用于发布排序、循环依赖检查和 dry-run 汇总。
Local-Issue-Key 仅作为隐藏 HTML 注释写入远端正文,用于幂等检查;不得显示 Source / 来源 章节。
输入物
主输入:
team-spec/active/{slug}/issues/ 下的 issue 草稿文件。
--issue 可选参数:只发布指定的单个 issue 草稿。
必须参数:
- 平台地址(默认
https://github.com;GitHub Enterprise 必须提供自定义地址)。
- 仓库定位:
owner/repo;如果用户未显式提供,可按下面“仓库定位规则”从 git remote 推断。
- 认证 token(必须通过环境变量提供,不写入任何文件)。
- 目标 slug 或明确的 issue 目录路径(如
team-spec/active/{slug}/issues/)。
建议参数:
- 默认 labels。
- milestone。
- assignee 映射规则。
dry-run 开关(默认建议先开)。
前置条件:
- 如团队需要人类对齐,建议先使用
team-prd-to-alignment 生成 team-spec/active/{slug}/prd/alignment.md 并完成评审讨论。
team-prd-to-issues 已产出可发布草稿;如果只发单个 issue,则该 issue 草稿已存在。
- 需要有效 token 且具备 GitHub Issues 写权限(常见为
repo 或等效最小权限)。
如果无法唯一确定 slug、仓库或 token 来源,必须停止并向用户确认,不得猜测。
仓库定位规则
当用户没有显式提供 GitHub 仓库 owner/repo 时,先读取 team-spec/config.yml 和当前仓库的 git remote:
- 如果
version_control.target_remote 已配置,默认使用该 remote 对应的上游仓库创建 issue。
- 如果
version_control.contribution_model: fork-pull 且未配置 target_remote,优先使用名为 upstream 的 GitHub remote。
- 如果不存在明确上游 remote,但当前分支配置了唯一的 upstream tracking remote,使用该 tracking remote。
- 如果只有一个 GitHub remote,使用这个 remote。
- 如果存在多个 GitHub remote 且无法按以上规则唯一判断,停止并要求用户指定仓库,不要默认使用
origin。
从 remote URL 提取仓库时,兼容 HTTPS 与 SSH 格式,例如:
https://github.com/owner/repo.git -> owner/repo
git@github.com:owner/repo.git -> owner/repo
GitHub Enterprise 场景下,remote host 必须与平台地址一致;如果不一致,应要求用户确认平台地址和目标仓库。
多 Remote 模式
当仓库中存在多个 remote 时,先结合 remote 名称判断工作模式:
- fork-pull 模式:通常会同时存在
origin 和 upstream,并且 origin 指向开发者 fork、upstream 指向上游仓库。此时 issue 应默认创建到 upstream 对应的上游仓库。
- 单仓模式:如果只有一个远端或无法判断 fork-pull,则按仓库定位规则继续推断。
- 如果
team-spec/config.yml 已声明 contribution_model、source_remote 或 target_remote,以配置为准;如果配置缺失但 git remote 能唯一推断,应在 dry-run 中说明推断依据,并在用户确认后回写配置。
无论是哪种模式,真正执行 --execute 之前,都必须先输出 dry-run 结果,并由人类确认目标仓库、issue 列表和发布计划没有问题。
输出物
- GitHub Issue 或 GitHub Issues(默认按依赖顺序批量创建;指定单个 issue 时只创建一个)。
- 本地回写结果(每个 issue 草稿都应记录):
- Issue 生命周期状态:成功创建或幂等命中远端 issue 后写为
published。
- 远端 issue 编号。
- 远端 issue URL。
- 发布操作状态(
created / skipped / failed),保留在 Publish Status 章节用于重试与诊断,不替代 issue 生命周期状态。
- 错误原因(如失败)。
- 发布时间戳。
- 批量发布汇总:
- 总数、成功数、跳过数、失败数。
- 失败清单与重试建议。
优先回写原 issue 草稿;若原文件结构不便回写,再在同目录新增发布结果文件。
发布规则
- 默认按依赖顺序发布:先 blocker,再依赖它的 issue。
- 如果用户通过
--issue 指定单个 issue,则只发布该 issue,不会发布同 slug 下其它草稿。
- 先做参数与权限检查,再执行真正发布。
- 默认先执行
dry-run 预览发布计划,用户确认后再正式发布。
- 幂等优先:重复执行时,不应重复创建同一 issue。
- 出现部分失败时继续处理可执行项,并保留失败清单用于补偿重试。
幂等策略
每个本地 issue 在发布前必须做唯一性检查。推荐组合键:
- 本地 issue 文件名(
team-prd-to-issues 已生成的 {local-seq}-{short-issue-slug}.md 格式,其中 local-seq 直接取自现有文件名前缀,用作本地唯一标识,不是远端 GitHub issue 编号)。
- issue 标题(
Title)。
若远端已存在匹配项,则标记为 skipped 并回写现有 issue URL,不重复创建。
发布时必须把本地唯一键持久化到远端 issue 描述的隐藏 HTML 注释中,例如:<!-- Local-Issue-Key: {local-seq}-{short-issue-slug}.md -->。
推荐匹配逻辑:
- 第一步:读取本地草稿
## Publish Status。如果 Status 为 created 或 skipped,且已有 GitHub URL 或 GitHub Number,默认标记为 skipped,不再创建远端 issue。
- 第二步:如果用户显式传入
--force,或本地没有有效发布记录,则按远端 issue 描述中的 Local-Issue-Key 精确匹配(完全一致)。
- 第三步:在同一
Local-Issue-Key 候选内按标题精确匹配(去除首尾空白后比较)。
- 第四步:若仍有多个候选,停止自动发布该条并标记为
failed,要求人工确认,避免误关联。
建议流程
- 确认 slug、仓库、平台地址、token 来源与权限范围;若仓库来自 git remote,按“仓库定位规则”优先选择上游仓库。
- 读取
team-spec/active/{slug}/issues/ 下所有待发布 issue 草稿。
- 解析
Blocked by 关系并生成依赖有向图。
- 检查循环依赖;若存在循环依赖,停止并输出冲突清单。
- 使用固定脚本生成拓扑顺序发布计划。
- 先执行固定脚本的默认
dry-run,输出将创建/跳过的完整清单。
- 用户确认后用固定脚本追加
--execute 执行正式发布。
- 每创建一个 issue 即刻回写本地结果,避免中断后丢失进度。
- 对失败项按可配置策略重试;重试后仍失败则保留失败状态并汇总。
- 输出批量发布报告和有序号的“下一步可选”列表,方便用户直接回复序号继续推进。若本次只是
dry-run 且发布计划可执行,选项 1 必须是“立即发布”,即使用相同参数追加 --execute 正式创建 GitHub Issues;后续再列继续实现、补充权限、修复依赖或手动处理失败项。
推荐格式:
## 下一步可选
1. 立即发布:确认 dry-run 计划无误后,用相同参数追加 `--execute` 创建 GitHub Issues。
2. `team-issue-batch-implement`:发布完成且存在多个可执行 `AFK` issue 时,按依赖顺序连续实现并逐个验证。
3. `team-issue-implement`:只处理一个明确的 `AFK` issue。
4. 修复失败项:如果有失败或跳过异常,先处理报告中的失败原因后重试发布。
错误与恢复策略
- 认证失败:立即停止,不执行发布。
- 权限不足:立即停止,并提示所需权限范围。
- 单条数据错误(标题缺失、格式不合法等):标记该条失败,继续其余可执行项。
- 网络或临时 API 错误:按重试策略处理,超过上限后标记失败。
- 已发布部分不回滚;使用回写状态与汇总清单做后续补偿。
安全要求
- token 只能从环境变量读取。
- 不记录、不回显 token。
- 不将 token 写入
team-spec/ 或任何仓库文件。
完成标准
- 目标 slug 下 issue 已按依赖顺序处理完成,或指定的单个 issue 已处理完成(创建/跳过/失败均有记录)。
- 每个本地 issue 草稿都有可追踪的回写状态。
- 输出了可执行的失败重试清单。
- 结果可重复执行,且不会产生重复 issue。
最终回复
必须包含:
- dry-run 或 execute 状态、目标 GitHub 仓库和处理范围。
- 创建、幂等跳过和失败的 issue 数量及对应 URL。
- 本地 issue 的
published 生命周期状态和 Publish Status 操作结果。
- 失败清单、失败原因和可重试入口。
- 有序号的下一步选项,通常为批量实现或单 issue 实现。