--- name: spec-git-push description: JSC plugins 共用「git push 憑證選擇規範」:push 分支前依序嘗試認證管理器(既有 git credential helper)→ token(環境變數組帶 token 遠端 URL,全程遮蔽、用完即棄不落地)→ 詢問使用者三段式,前者失敗才退到下一個;與 `/jsc-shared:spec-gitea`「token 解析優先序」(API 呼叫用、多來源逐一驗證取優)不同,本規範專講 `git push` 本身的憑證選擇順序。當其他 skill 內文引用 spec-git-push 或 /jsc-shared:spec-git-push、或執行任何會 `git push` 的 JSC skill 時載入此 skill。單獨被使用者呼叫時,直接說明本規範內容。 --- # spec-git-push — 共用 git push 憑證選擇規範 機密保護的總則(不 echo、遮蔽、不落地)沿用 `/jsc-shared:spec-gitea`「Token 機密保護」章節;本規範只補 `git push` 情境特有的三段式憑證選擇順序,不重複該章節已涵蓋的內容。 ## 與 spec-gitea「token 解析優先序」的差異 兩者都在講「憑證怎麼決定」,但用途與判定方式不同,**不可互相取代**: | | `/jsc-shared:spec-gitea`「token 解析優先序」 | 本規範(`spec-git-push`) | | --- | --- | --- | | 用途 | Gitea REST API 呼叫(GET/POST 等) | `git push` 本身取得推送權限 | | 選擇單位 | 多個「token 來源」 | 多種「推送方式」(不只 token) | | 判定方式 | 每個候選以輕量 API 請求**實際驗證**(HTTP 200 才採用),失敗就換下一個候選 | 直接嘗試該推送方式,**push 本身失敗**才換下一個 | | 候選順序 | 專用變數 → `$GITEA_TOKEN` → tea 設定檔 → `~/.git-credentials` | 認證管理器 → token → 詢問使用者 | | 最終手段 | 全部候選驗證失敗 → 回報錯誤並停止 | 前兩段都失敗 → **詢問使用者**如何 push,不猜測其他憑證 | 同一個 skill 可以先用 spec-gitea 的順序決定 API 呼叫要用哪個 token,再於 push 時套用本規範的三段式;兩套順序彼此獨立,不共用判定結果。 ## 三段式流程 push 前先確認目前分支是否有領先遠端的 commit;**無 commit 可推就跳過整段,不需要嘗試任何憑證**: ```bash source_branch="$(git rev-parse --abbrev-ref HEAD)" git rev-parse --verify "origin/${source_branch}" 2>/dev/null # 遠端無此分支視為全部要推 git log --oneline "origin/${source_branch}..${source_branch}" 2>/dev/null # 領先遠端的 commit ``` 確認有 commit 需要 push 後,依序嘗試以下三段,**前者失敗才退到下一個**,任一段成功即停止: | 順序 | 方式 | 適用條件 | | --- | --- | --- | | 1 | 認證管理器(優先) | git 既有的 credential helper 可用(如 Windows 的 `manager-core`) | | 2 | token push | 環境變數已提供 token(如 `GITEA_TOKEN`) | | 3 | 詢問使用者 | 前兩段都失敗 | ### 1. 認證管理器 不預先判斷有沒有 credential helper,直接嘗試,讓 git 自己走既有認證流程: ```bash git push -u origin "$(git rev-parse --abbrev-ref HEAD)" ``` ### 2. token push 失敗才進入此段。從環境變數讀 token,組帶 token 的遠端 URL 推送: ```bash # GITEA_TOKEN 來自環境變數;host/owner/repo 解析自 origin git push "https://oauth2:${GITEA_TOKEN}@//.git" \ "$(git rev-parse --abbrev-ref HEAD)" ``` - token 一律用變數帶入組出遠端 URL,**指令與輸出全程不可印出含 token 的字串**。 - token 用完即棄:**不寫進 `git remote set-url`/`.git/config`、不落地**——這個帶 token 的 URL 只用於這一次 push,用完即丟,不留存、不設回 remote。 - 若 push 之外的流程(例如 clone)曾把帶 token 的 URL 設進 remote,還原成乾淨 URL 屬於 clone/remote 憑證管理範疇,做法見 `/jsc-shared:spec-gitea`「Token 機密保護」章節,不在本規範重複。 ### 3. 詢問使用者 兩段都失敗才進入此步:列出兩段各自的失敗原因(**先遮蔽 token**),請使用者指示要如何推送,**不可自行猜測**其他憑證或來源;排程情境(無人可即時回應)改為寫入 log 並結束,等使用者事後處理。 ## 全程遮蔽 token 三段流程中任何會印出指令、URL、錯誤訊息,或寫進 log 的地方,一律套用 `/jsc-shared:spec-gitea`「機密遮蔽實作」章節的規則過濾後才輸出,不得只遮蔽字面 token 值。 ## 適用情境 供任何會執行 `git push` 的 JSC skill 引用,例如 `/jsc-code:review-resolve` push 當前分支的階段、`/jsc-code:target` push `develop` 的階段。**clone 時組裝帶 token 的 URL 與 `remote set-url origin` 還原乾淨 URL**(例如 `/jsc-code:sync` 建立資料夾並 clone 的階段)屬於 clone/remote 憑證管理,已由 `/jsc-shared:spec-gitea`「Token 機密保護」章節涵蓋,不屬本規範範疇。