Commit and PR writer
將一組變更轉換為清晰的提交訊息和可供審查者採取行動的 Pull Request 說明。其價值在於說明為何存在這個變更、以及可能出什麼問題,而不是重述 diff。
安全規則(請先閱讀)
- 除非使用者明確要求,否則不要提交、推送或開啟 PR。 僅提出建議的命令,讓使用者自行執行。提交和推送對他人可見且難以復原。
- 絕不將機密值寫入訊息或 PR。 如果掃描發現可能的機密,請先停止並告知使用者:必須輪換該機密,僅從下一次提交中移除是不夠的。
- 不要捏造事實。 不編寫你未看到的 issue 編號、測試結果、基準數據或動機。如果變更的原因不明確,請提出一個簡短問題或說明你的假設。
工作流程
1. 收集變更
如果你可以在使用者的儲存庫中執行命令,請先使用內建的掃描器,再讀取實際的 diff:
python scripts/scan_diff.py # 暫存的變更(若無則回退到未暫存)
python scripts/scan_diff.py main...HEAD # 整個分支,用於 PR
git diff --staged # 讀取實際 diff(若內容較大,先使用 --stat)
git log --oneline main..HEAD # 分支上已有的提交,用於 PR
scripts/scan_diff.py 會按區域(程式碼、測試、遷移、依賴、配置、CI、文件)對檔案進行分組,並標記可能的機密、除錯遺留物、缺少測試、遷移、安全敏感路徑、可能的 API 變更以及過大的變更。這是一個啟發式方法,因此請對照 diff 確認每個標記。
如果你無法執行命令,請要求使用者貼上 git diff --staged(或用於 PR 的 git diff main...HEAD),以及相關的 issue 或工單內容。如果程式碼執行可用,你仍然可以將貼上的文字通過 python scripts/scan_diff.py - 傳遞給掃描器。
2. 理解意圖
弄清楚哪些行為發生了變化以及原因。證據的優先順序:分支名稱和 ticket ID、分支上已有的提交訊息、新的或變更的測試、變更附近的註解,然後是使用者所述內容。請參閱 references/guidelines.md 第 4 節。
3. 檢查範圍
如果 diff 混合了不相關的關注點(功能加上重構加上格式化,或不相關的模組),請提議拆分而不是撰寫一條含糊的訊息:列出各組、每組包含的檔案、每組的訊息以及對應的 git add -p 步驟。每次提交保持一個邏輯變更。如果已經是一個邏輯變更,則撰寫一條提交。
4. 撰寫提交訊息
格式:類型(範疇): 主旨,然後是可選的主體,最後是可選的頁尾。
- 類型:
feat,fix,docs,style,refactor,perf,test,build,ci,chore,revert。 - 主旨: 祈使語氣("add", "fix")、全小寫、句尾無句號、約 50 字元且絕不超過 72 字元。描述行為變更,而非檔案。
- 主體: 僅在原因不明顯時使用。主旨後留一空行,解釋原因,並在大約 72 字元處換行。
- 頁尾:
Closes #123(僅用於你已知的編號)和當客戶端或部署將受影響時的BREAKING CHANGE: ...。類型或範疇後加上!也表示破壞性變更。
然後進行檢查。將訊息儲存到暫存檔案並執行:
python scripts/lint_commit_message.py message.txt
在向使用者顯示之前,修復所有錯誤以及合理的警告。
5. 撰寫 PR 說明(當被要求撰寫 PR 時)
從 assets/pr-template.md 開始。填寫 What、Why、How to test,然後僅保留適用的 Backend impact 行(資料庫與遷移、API 變更、安全性與授權、效能、配置與標誌、部署與回滾),並刪除其餘部分。規則:
- 標題: 與提交標頭格式相同,因為使用 squash-merge 時它會成為
main分支上的提交。 - How to test: 從儲存庫中你能證明是正確的準確命令(例如你看到有變更的測試檔案)。與其暗示測試已通過,不如說 "tests not run"。
- Breaking changes: 說明受影響的人員、他們必須做什麼以及時間表。
- Migrations: 說明在部署期間舊程式碼是否仍能運作,以及如何回滾。
- 保持比例。 一行修復只需兩行 PR,而不需要完整的範本。
6. 呈現結果
依次回覆以下內容:
- 警示(僅當掃描發現真實問題時):機密、除錯程式碼、缺少測試、非常大的 diff、有風險的遷移。
- 提交訊息(放在程式碼區塊中,或每個提交一條訊息的拆分計畫)。
- PR 標題與說明(放在 Markdown 程式碼區塊中,可直接貼上。如果主體包含程式碼柵欄,請在其周圍使用四個反引號)。
- 可選的命令,供使用者執行,例如
git commit -F message.txt或gh pr create --title "..." --body-file pr.md。以建議形式呈現。
保持回覆簡短。不要複述 diff。
根據變更調整輸出規模
- 錯字、文件或配置調整:一行提交,無主體,兩行 PR。
- 一般變更:標頭加簡短主體,包含 What / Why / How to test 的 PR。
- 大型或有風險的變更(遷移、認證、公開 API):包含相關後端影響區段的完整 PR,如果掃描認為變更過大,則建議拆分。
範例
輸入摘要:暫存的 diff 變更 app/auth.py 以在解碼 token 時驗證 exp、iss、aud,新增 tests/test_auth.py::test_expired_token,分支為 fix/42-expired-tokens。
輸出:
fix(auth): reject expired refresh tokens
Tokens were accepted after expiry because exp was decoded but never
validated. Validate exp, iss and aud on every decode and return 401.
Closes #42
PR 標題為 fix(auth): reject expired refresh tokens,Why 部分說明該錯誤,How to test 指向 pytest tests/test_auth.py::test_expired_token,Security / authorization 行說明先前有效的過期 token 現在會返回 401。
附帶檔案
scripts/scan_diff.py:總結 diff 並標記風險。用法:python scripts/scan_diff.py [git-diff-args | -]。回傳碼 1 表示發現可能的機密。scripts/lint_commit_message.py:根據 Conventional Commits 格式檢查訊息。用法:python scripts/lint_commit_message.py message.txt(或-表示從標準輸入讀取)。回傳碼 1 表示錯誤。assets/pr-template.md:待填寫的 PR 說明骨架。如果使用者希望在其儲存庫中設定預設範本,也可以將其複製到.github/pull_request_template.md。references/guidelines.md:包含類型範例、好與壞的訊息、破壞性變更、如何拆分 diff、PR 規模、後端 PR 區段、issue 關聯關鍵字以及不該撰寫的內容。當上述內容未涵蓋某種情況時,請參考該文件。