PCL2 icon indicating copy to clipboard operation
PCL2 copied to clipboard

Bot 适配 Close as Duplicate

Open Deep-Dark-Forest opened this issue 11 months ago • 25 comments

检查项

描述

在 Issue 上弃用 “新功能” “Bug” “优化” 标签,用对应的 Issue type 代替,@HexDragon-Bot 适配新的 Issue close as duplicate 功能

原因

或许能提高处理 Issue 的效率

Deep-Dark-Forest avatar Jan 24 '25 09:01 Deep-Dark-Forest

Image 似乎 API 尚未支持? 或者也许有了只是文档还没更新

WorldHim avatar Jan 24 '25 10:01 WorldHim

Image 似乎 API 尚未支持? 或者也许有了只是文档还没更新

检查一个功能是否支持的最好办法就是自己测一次

wuliaodexiaoluo avatar Jan 24 '25 12:01 wuliaodexiaoluo

等待 API 更新

LTCatt avatar Jan 24 '25 12:01 LTCatt

Image

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"

Light-Beacon avatar Jan 24 '25 17:01 Light-Beacon

但它不支持传入某个 issue 编号,那去修改就意义不大了(

LTCatt avatar Jan 24 '25 18:01 LTCatt

我看看能不能车 workflow。

allMagicNB avatar Jan 25 '25 01:01 allMagicNB

但它不支持传入某个 issue 编号,那去修改就意义不大了(

看后续会不会有变动,但现在应该是可以根据这个来处理 Bot 自动改标签的时候是加 忽略 还是 重复 了?

MoYuan-CN avatar Jan 25 '25 01:01 MoYuan-CN

我看看能不能车 workflow。

https://github.com/Light-Beacon/PCL-Action-Test

Light-Beacon avatar Jan 25 '25 05:01 Light-Beacon

在 github 的 timeline 和 event api 里边甚至标的是 "state_reason": "completed"...

Light-Beacon avatar Jan 25 '25 05:01 Light-Beacon

workflow 貌似没有问题,但是 @HexDragon-Bot 用的不是 workflow……

Deep-Dark-Forest avatar Jan 25 '25 13:01 Deep-Dark-Forest

bot 用的是 graphQL api…… edit:修正笔误

LTCatt avatar Jan 25 '25 14:01 LTCatt

GraphQL API……吧?

MoYuan-CN avatar Jan 25 '25 14:01 MoYuan-CN

Type 字段可以在组织设置里面自定义,参见

  • https://github.com/orgs/community/discussions/148715

中的 Customizing default issue types > Organization settings page 现在可以将类型从 Label 中分离出去了,只需要在 Issue Form 那边使用 type: "类型名" 就可以自动添加了

MoYuan-CN avatar Jan 28 '25 15:01 MoYuan-CN

……@LTcatt 要不弃用 “优化” “Bug” “新功能” 标签?

Deep-Dark-Forest avatar Jan 29 '25 03:01 Deep-Dark-Forest

……要不弃用 “优化” “Bug” “新功能” 标签?

额,为啥?

LTCatt avatar Jan 29 '25 09:01 LTCatt

……要不弃用 “优化” “Bug” “新功能” 标签?

额,为啥?

GitHub 新出的 Type 功能已经可以把它们取代了……留着有点多余

Deep-Dark-Forest avatar Jan 29 '25 09:01 Deep-Dark-Forest

其实没啥必要就是了,还容易闹误会啥的,机器人的代码逻辑也得为此做出更改

wuliaodexiaoluo avatar Jan 29 '25 09:01 wuliaodexiaoluo

我也建议龙猫换用 Type,个人感觉观感会好很多。

效果可以看下隔壁 CE:https://github.com/PCL-Community/PCL2-CE/issues?q=is%3Aissue%20

3gf8jv4dv avatar Jan 29 '25 14:01 3gf8jv4dv

写了一篇讲述新的 Issue 系统好处的文章: https://www.yuque.com/jim.lin/yuns-lab/github-issue-next

MoYuan-CN avatar Jan 29 '25 21:01 MoYuan-CN

但是 “优化” “Bug” “新功能” 标签也不能完全弃用,因为 PR 目前还不支持 Type……最多在 Issue 中弃用吧

Deep-Dark-Forest avatar Jan 30 '25 01:01 Deep-Dark-Forest

~~不如同时存在。~~

allMagicNB avatar Jan 30 '25 01:01 allMagicNB

umm 除非它允许在 PR 里设置 type,不然暂时就不考虑弃用这几个标签。 等到 API 支持 Close as Dumplicate 的时候,整下这个倒是 OK 的。

LTCatt avatar Feb 12 '25 12:02 LTCatt

@LTCatt Dumplicate → duplicate

Deep-Dark-Forest avatar Feb 12 '25 14:02 Deep-Dark-Forest

https://github.blog/changelog/2025-03-18-github-issues-projects-rest-api-support-for-issue-types/

今天看新闻说 API 支持类型了,但没看到正式支持 Close as Duplicate 的文档

MoYuan-CN avatar Mar 21 '25 16:03 MoYuan-CN

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 的操作

WorldHim avatar Mar 22 '25 08:03 WorldHim

等到 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

copytiao avatar Jun 24 '25 10:06 copytiao

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()

Deep-Dark-Forest avatar Jul 27 '25 12:07 Deep-Dark-Forest

REST API 也已经支持

附:一键将之前所有 close as not planned 的重复 issue close as duplicate 的脚本,龙猫可以试试(

现在有一个问题,挂上重复标签以后 Bot 会自动 close as not planned,跟忽略标签的行为一样,先考虑解决这个再使用那个脚本

hongggggv avatar Jul 27 '25 19:07 hongggggv

REST API 也已经支持

附:一键将之前所有 close as not planned 的重复 issue close as duplicate 的脚本,龙猫可以试试(

现在有一个问题,挂上重复标签以后 Bot 会自动 close as not planned,跟忽略标签的行为一样,先考虑解决这个再使用那个脚本

其实并不会,因为使用这个脚本后没有 Issue 标签的更改,Bot 就不会生效。

Deep-Dark-Forest avatar Jul 28 '25 01:07 Deep-Dark-Forest

这个过程需要有人手动标记重复的 Issue(在 comment 发一个 Duplicate of xxx(大小写敏感))

使用 REST API 可以不设置与哪个 Issue 重复,直接 close as duplicate 这样的话只需要 Collaborator 说一句意思与“与 #xxxx 重复”相似的话就行了,更灵活

Deep-Dark-Forest avatar Jul 28 '25 01:07 Deep-Dark-Forest