From 4f3ba9c8d35b9c13eb0b74cc7ba1327480c621a7 Mon Sep 17 00:00:00 2001 From: Jeffery Date: Tue, 25 Aug 2026 12:08:11 +0800 Subject: [PATCH] =?UTF-8?q?feat(pr-status,pr-comments):=20=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=20PR=20=E7=8B=80=E6=85=8B=E8=88=87=E7=95=99=E8=A8=80?= =?UTF-8?q?=E6=9F=A5=E8=A9=A2=E5=AD=90=E6=8C=87=E4=BB=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5 (1M context) --- tools/gitea.sh | 49 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/tools/gitea.sh b/tools/gitea.sh index 3502852..45bf432 100755 --- a/tools/gitea.sh +++ b/tools/gitea.sh @@ -12,14 +12,17 @@ # gitea.sh wiki-list / # 列出 wiki 頁名 # gitea.sh wiki-get / # 印出 wiki 頁 markdown;不存在時 exit 4 # gitea.sh wiki-put / # 建立或更新 wiki 頁(內容取自檔案) +# gitea.sh wiki-url / # 印出 wiki 頁絕對網址(取自 API 的 html_url);跨存取庫連結用 # gitea.sh pr-create / <body-file> # 建立 PR,印出 PR URL +# gitea.sh pr-status <owner>/<repo> <pr-index> # 印出「{state} {merged} {mergeable}」 +# gitea.sh pr-comments <owner>/<repo> <pr-index> # 印出所有留言(issue 留言、審查評語、行內留言),依時間排序 # gitea.sh pr-depend <owner>/<repo> <pr-index> <dep-owner>/<dep-repo> <dep-index> # 把 PR 掛上前置 PR 依賴;依賴未關閉前 Gitea 會阻擋合併 # gitea.sh repo-set <owner>/<repo> <description> [website] # 設定 repo 描述與網頁 # gitea.sh api <METHOD> <path> [json-file] # 原始 API 呼叫(path 以 /repos/... 起始) # 環境變數: GITEA_HOST(例 https://gitea.jsc.idv.tw)、GITEA_TOKEN # GITEA_TOKEN 未設定,或請求遇 401/403 時,自動退回 tea CLI 的登入 token -# (~/.config/tea/config.yml,優先取 default: true 的登入);兩者皆無才失敗。 +# (~/.config/tea/config.yml,優先取 url 與 GITEA_HOST 同主機的登入,其次 default: true);兩者皆無才失敗。 set -eu script_dir=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd) @@ -204,6 +207,50 @@ print(json.dumps({"head":sys.argv[1],"base":sys.argv[2],"title":sys.argv[3], ' "$head" "$base" "$title" "$body_file" > "$tmp" req POST "/repos/$or/pulls" "$tmp" | json_field html_url rm -f "$tmp" ;; + pr-status) + # 印出「{state} {merged} {mergeable}」,供呼叫端判斷 PR 是否已合併。 + or="${1:?owner/repo required}"; idx="${2:?pr index required}" + req GET "/repos/$or/pulls/$idx" | python3 -c ' +import json,sys +p=json.load(sys.stdin) +print("%s %s %s" % (p.get("state","?"), str(p.get("merged")).lower(), str(p.get("mergeable")).lower())) +' ;; + pr-comments) + # 印出 PR 的所有留言,每行「{時間}<TAB>{作者}<TAB>{類型}<TAB>{內容單行化}」。 + # 三個來源都要讀:issue 留言、review 本體的評語、review 內逐行的程式碼留言。 + # 只讀 issue 留言會漏掉真正的審查意見,那正是需要修正的部分。 + or="${1:?owner/repo required}"; idx="${2:?pr index required}" + { req GET "/repos/$or/issues/$idx/comments?limit=100" | python3 -c ' +import json,sys +for c in json.load(sys.stdin): + body=" ".join((c.get("body") or "").split()) + if body: print("%s\t%s\t留言\t%s" % (c.get("created_at",""), (c.get("user") or {}).get("login","?"), body)) +' + reviews=$(req GET "/repos/$or/pulls/$idx/reviews?limit=100") + printf '%s' "$reviews" | python3 -c ' +import json,sys +for r in json.load(sys.stdin): + body=" ".join((r.get("body") or "").split()) + st=r.get("state","") + # 沒有評語的審查照樣要印:APPROVED 代表可以合併,REQUEST_CHANGES 代表被要求修改, + # 兩者都是呼叫端要據以決策的事實,過濾掉會看不見 PR 真正的狀態。 + print("%s\t%s\t審查(%s)\t%s" % (r.get("submitted_at",""), (r.get("user") or {}).get("login","?"), st, body or "(無評語)")) +' + for rid in $(printf '%s' "$reviews" | python3 -c ' +import json,sys +for r in json.load(sys.stdin): + if r.get("comments_count", 0) or r.get("id"): print(r["id"]) +'); do + req GET "/repos/$or/pulls/$idx/reviews/$rid/comments" 2>/dev/null | python3 -c ' +import json,sys +try: d=json.load(sys.stdin) +except Exception: raise SystemExit +for c in d: + body=" ".join((c.get("body") or "").split()) + if body: print("%s\t%s\t行內(%s:%s)\t%s" % (c.get("created_at",""), (c.get("user") or {}).get("login","?"), c.get("path",""), c.get("original_position") or c.get("position") or "", body)) +' || true + done + } | sort ;; pr-depend) or="${1:?owner/repo required}"; idx="${2:?pr index required}" dep_or="${3:?dep owner/repo required}"; dep_idx="${4:?dep index required}"