如何通过GitHub Workflow阻止关联主分支代码的Issue被关闭?
问题背景
我有一个GitHub Workflow,用于检查提交代码中的TODO:注释,强制要求所有注释关联开放的Issue,比如TODO: #123 - handle symlinks。这个Workflow能有效防止提交者遗留未完成代码,确保所有在做的工作都被追踪。
但现在遇到问题:如果关联的Issue被作者或维护者关闭,后续任何提交的无关内容都会触发检查失败。
我希望阻止那些在main分支代码中被提及的Issue被关闭,确保关闭前先移除关联或更换为其他Issue。我复制了现有Workflow并修改触发事件,但没找到阻止Issue关闭的方法,当前失败的检查不起作用:
name: Todo on: issues: types: closed jobs: todo: runs-on: ubuntu-latest - uses: actions/checkout@v4 - run: .github/workflows/todo.py env: GH_TOKEN: ${{ SECRETS.GITHUB_TOKEN }} - run: echo "Please don't close" if: failed()
想请教:有没有可调用的API阻止Issue被关闭?还是只能立即重新打开Issue并添加注释?
解决方案说明
GitHub没有直接提供“阻止Issue关闭”的API或内置功能,你只能通过事后补救+引导规范的方式处理,具体方案如下:
检测违规后自动重新打开Issue并提示
调整现有Workflow逻辑:当检测到被关闭的Issue仍在main分支的TODO注释中被引用时,调用GitHub API重新打开该Issue,并添加注释说明原因(比如“该Issue仍被main分支的TODO注释关联,请先移除代码中的引用后再关闭”)。- 改造
todo.py脚本,在检测到匹配后,利用GH_TOKEN调用GitHub REST API:- 重新打开Issue:
PATCH /repos/{owner}/{repo}/issues/{issue_number},设置state: "open" - 添加注释:
POST /repos/{owner}/{repo}/issues/{issue_number}/comments,传入提示内容
- 重新打开Issue:
- 注意:默认的
Secrets.GITHUB_TOKEN在触发issues事件时已拥有issues: write权限,无需额外配置。
- 改造
通过分支保护规则从源头规避
配置main分支的保护规则,强制要求合并PR前必须移除所有关联已关闭Issue的TODO注释。从提交环节卡住违规操作,避免后续出现代码引用已关闭Issue的情况。添加规范提示到模板
在Issue关闭模板、PR描述模板中添加明确提示:关闭Issue前,请先检查代码中是否有引用该Issue的TODO注释,确保已移除或更新引用。通过规范引导减少误操作。
调整后的Workflow示例(核心逻辑)
name: Prevent Closing Referenced Issues on: issues: types: [closed] jobs: check-todo-references: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Check if Issue is referenced in main branch TODOs id: check-todo run: | # 调用todo.py检测main分支是否存在引用当前关闭Issue的TODO # 脚本需返回检测结果,比如输出"true"或"false" RESULT=$(python .github/workflows/todo.py ${{ github.event.issue.number }}) echo "has_reference=$RESULT" >> $GITHUB_OUTPUT env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Reopen Issue and add comment if: steps.check-todo.outputs.has_reference == 'true' run: | # 重新打开Issue gh issue reopen ${{ github.event.issue.number }} # 添加提示注释 gh issue comment ${{ github.event.issue.number }} --body "该Issue仍被main分支的TODO注释关联,请先移除代码中的引用后再关闭。" env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
内容的提问来源于stack exchange,提问作者Dominik Kaszewski

