Bot 适配 Close as Duplicate
检查项
- [x] 我已在 Issues 页面 和 常见&难检反馈及问题列表 中搜索,确认了这一建议未被提交过。
- [x] 我已查看 功能投票页面,确认了这一建议未在投票列表中。
描述
在 Issue 上弃用 “新功能” “Bug” “优化” 标签,用对应的 Issue type 代替,@HexDragon-Bot 适配新的 Issue close as duplicate 功能
原因
或许能提高处理 Issue 的效率
似乎 API 尚未支持?
或者也许有了只是文档还没更新
似乎 API 尚未支持? 或者也许有了只是文档还没更新
检查一个功能是否支持的最好办法就是自己测一次
等待 API 更新
API是支持的
示例
gh api -H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2022-11-28" /repos/Hex-Dragon/PCL2/issues/5492 | jq | grep state_reason
返回
"state_reason": "duplicate"
但它不支持传入某个 issue 编号,那去修改就意义不大了(
我看看能不能车 workflow。
但它不支持传入某个 issue 编号,那去修改就意义不大了(
看后续会不会有变动,但现在应该是可以根据这个来处理 Bot 自动改标签的时候是加 忽略 还是 重复 了?
我看看能不能车 workflow。
https://github.com/Light-Beacon/PCL-Action-Test
在 github 的 timeline 和 event api 里边甚至标的是 "state_reason": "completed"...
workflow 貌似没有问题,但是 @HexDragon-Bot 用的不是 workflow……
bot 用的是 graphQL api…… edit:修正笔误
GraphQL API……吧?
Type 字段可以在组织设置里面自定义,参见
- https://github.com/orgs/community/discussions/148715
中的 Customizing default issue types > Organization settings page
现在可以将类型从 Label 中分离出去了,只需要在 Issue Form 那边使用 type: "类型名" 就可以自动添加了
……@LTcatt 要不弃用 “优化” “Bug” “新功能” 标签?
……要不弃用 “优化” “Bug” “新功能” 标签?
额,为啥?
……要不弃用 “优化” “Bug” “新功能” 标签?
额,为啥?
GitHub 新出的 Type 功能已经可以把它们取代了……留着有点多余
其实没啥必要就是了,还容易闹误会啥的,机器人的代码逻辑也得为此做出更改
我也建议龙猫换用 Type,个人感觉观感会好很多。
效果可以看下隔壁 CE:https://github.com/PCL-Community/PCL2-CE/issues?q=is%3Aissue%20
写了一篇讲述新的 Issue 系统好处的文章: https://www.yuque.com/jim.lin/yuns-lab/github-issue-next
但是 “优化” “Bug” “新功能” 标签也不能完全弃用,因为 PR 目前还不支持 Type……最多在 Issue 中弃用吧
~~不如同时存在。~~
umm 除非它允许在 PR 里设置 type,不然暂时就不考虑弃用这几个标签。 等到 API 支持 Close as Dumplicate 的时候,整下这个倒是 OK 的。
@LTCatt Dumplicate → duplicate
https://github.blog/changelog/2025-03-18-github-issues-projects-rest-api-support-for-issue-types/
今天看新闻说 API 支持类型了,但没看到正式支持 Close as Duplicate 的文档
https://github.blog/changelog/2025-03-18-github-issues-projects-rest-api-support-for-issue-types/
今天看新闻说 API 支持类型了,但没看到正式支持 Close as Duplicate 的文档
state_reason 倒是有 duplicate 了,但是没有重复的 issue 编号
不知道 api 支不支持 close as duplicate 的操作
等到 API 支持 Close as Dumplicate 的时候,整下这个倒是 OK 的。
翻了翻 GitHub Docs,然后手动验证了一下,GraphQL API 是支持将议题关闭为 DUPLICATE 的
这个过程需要有人手动标记重复的 Issue(在 comment 发一个 Duplicate of xxx(大小写敏感))
然后机器人无脑发一个查询请求来标记为重复就行(可能需要扫 timelines 来找标记,以此确定这个 Issue 是被标记为重复的)
mutation {
closeIssue(input: {
issueId: "",
stateReason: DUPLICATE
}) {
issue {
number
state
stateReason
}
}
}
效果可以参考这个
https://github.com/shimoranla/shimoranla/issues/4
REST API 也已经支持
附:一键将之前所有 close as not planned 的重复 issue close as duplicate 的脚本,龙猫可以试试(
import os
import requests
import time
import json
TOKEN = 替换我
REPO_OWNER = "Meloong-Git"
REPO_NAME = "PCL"
GITHUB_GRAPHQL_URL = "https://api.github.com/graphql"
DUPLICATE_LABEL = "重复"
def fetch_issues(cursor=None):
query = """
query ($owner: String!, $name: String!, $cursor: String) {
repository(owner: $owner, name: $name) {
issues(
first: 100
states: CLOSED
after: $cursor
) {
nodes {
id
number
title
stateReason
labels(first: 10) {
nodes {
name
}
}
}
pageInfo {
endCursor
hasNextPage
}
}
}
}
"""
variables = {"owner": REPO_OWNER, "name": REPO_NAME, "cursor": cursor}
return make_request(query, variables)
def has_duplicate_label(issue):
labels = [label["name"] for label in issue["labels"]["nodes"]]
return DUPLICATE_LABEL in labels
def mark_as_duplicate(issue_id, issue_number):
rest_url = f"https://api.github.com/repos/{REPO_OWNER}/{REPO_NAME}/issues/{issue_number}"
headers = {
"Authorization": f"Bearer {TOKEN}",
"Accept": "application/vnd.github.v3+json",
"X-GitHub-Api-Version": "2022-11-28"
}
data = {
"state": "closed",
"state_reason": "duplicate"
}
response = requests.patch(rest_url, json=data, headers=headers)
return response.status_code == 200
def make_request(query, variables):
headers = {
"Authorization": f"Bearer {TOKEN}",
"Content-Type": "application/json",
"Accept": "application/vnd.github.v4.idl"
}
payload = {"query": query, "variables": variables}
try:
response = requests.post(GITHUB_GRAPHQL_URL, json=payload, headers=headers)
response.raise_for_status()
result = response.json()
if "errors" in result:
raise Exception(f"GraphQL error: {json.dumps(result['errors'], indent=2)}")
if "data" not in result:
raise Exception("Missing 'data' field in response")
return result
except Exception as e:
raise Exception(f"Request failed: {str(e)}")
def main():
cursor = None
has_next_page = True
processed_count = 0
while has_next_page:
result = fetch_issues(cursor)
issues_data = result["data"]["repository"]["issues"]
issues = issues_data["nodes"]
page_info = issues_data["pageInfo"]
has_next_page = page_info["hasNextPage"]
cursor = page_info["endCursor"]
for issue in issues:
if issue.get("stateReason") != "NOT_PLANNED":
continue
if has_duplicate_label(issue):
mark_as_duplicate(issue["id"], issue["number"])
processed_count += 1
time.sleep(1)
if has_next_page:
time.sleep(2)
if __name__ == "__main__":
main()
REST API 也已经支持
附:一键将之前所有 close as not planned 的重复 issue close as duplicate 的脚本,龙猫可以试试(
现在有一个问题,挂上重复标签以后 Bot 会自动 close as not planned,跟忽略标签的行为一样,先考虑解决这个再使用那个脚本
REST API 也已经支持
附:一键将之前所有 close as not planned 的重复 issue close as duplicate 的脚本,龙猫可以试试(
现在有一个问题,挂上重复标签以后 Bot 会自动 close as not planned,跟忽略标签的行为一样,先考虑解决这个再使用那个脚本
其实并不会,因为使用这个脚本后没有 Issue 标签的更改,Bot 就不会生效。
这个过程需要有人手动标记重复的 Issue(在 comment 发一个 Duplicate of xxx(大小写敏感))
使用 REST API 可以不设置与哪个 Issue 重复,直接 close as duplicate 这样的话只需要 Collaborator 说一句意思与“与 #xxxx 重复”相似的话就行了,更灵活