Community程式設計與開發github.com

Agent2API 協作與發版規範

定義 Agent2API(workbuddy)倉庫的日常協作與發版流程,包含分支管理、PR 合併、版本號遞增、正式版與 beta 預發布流程,以及發版驗收與排錯。

Agent2API 協作與發版規範 是什麼?

此技能定義了 Agent2API 專案的完整協作與發佈流程,適用於 Claude Code、Cursor 等 AI 代理工具。它涵蓋兩個主要工作領域:日常協作(分支策略、PR 合併署名、Issue/PR 回覆標示)與發版管理(版本號更新、更新日誌撰寫、tag 推送、GitHub Release 建立、驗收檢查)。技能強制要求兩條人工紅線:發版前必須獲得用戶對版本號與更新日誌的明確確認,未經確認不得推送任何分支或 tag。它詳細說明了 beta 分支作為預設集成分支、main 僅用於正式發版的規範,以及如何正確保留貢獻者署名(避免 AI 被列為共同作者)。此外,還包含了 beta 預發布版的特殊流程、跨平台構建工作流程(build.yml 與 docker.yml)、驗收清單,以及常見問題排解(如 gh 代理設定)。

相容平台✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/Agent2API/agent2api/tree/HEAD/.agents/skills/release-flow

Installed? Explore more 程式設計與開發 skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

Agent2API 協作與發版規範 是做什麼的?

涵蓋兩類工作:日常協作(分支落腳點、PR 署名、Issue 落款,第 1–3 節)與發版(版本號、更新日誌、tag、Release、驗收,第 4–7 節),排錯見第 8 節。

0. 兩條人工紅線(必須停下等確認)

下列兩件事必須由人先審過、明確點頭,代理才能繼續;可以準備草稿、可以列依據,不能自己拍板往下走:

  1. 發版:進入發版流程(改版本號、建立發布提交、推 main / beta、打 tag、掛 Release)之前,先把版本號與「這次要發什麼」講清楚,等用戶確認。未經確認不得推任何分支或 tag —— tag 一旦推出去就會觸發構建、產出公開的安裝包與映像檔,收不回來。
  2. 更新日誌:寫好的日誌(發布提交的提交資訊,同時也是 GitHub Release 正文)必須先給用戶逐條過目。用戶要求改措辭、增刪條目、調整分類前綴時,按回饋改完要再確認一次,不能因為「改得不多」就直接提交。

一次發版裡兩條同時適用:既要有版本號的確認,也要有日誌的確認;用戶說「繼續」之後才動手。

1. 分支落腳點:日常只碰 beta,發版才動 main

分支角色什麼時候動它
beta集成分支(預設落腳點)日常修改、合併 PR、解衝突 —— 一律先到這裡
main發版分支只在構建發版時:切 main、把 beta 合進來、打 tag
  • 合併 PR 時 base 選 beta,不要選 main。合進 main 等於把還沒發布的改動提前塞進發版分支;之後還得反過來把 main 合回 beta,平白多一次合併提交、多一次衝突機會。已經把 PR 開成 base=main 的,先在 PR 頁面把 base 改成 beta 再合。
  • 本地改動也提交到 beta(寫程式碼、改文件、解衝突都算),推 origin/beta;合併結果的核對、構建自檢都在 beta 上做完。
  • 只有正式發版才切 main:git switch main → 把 beta 合進來 → 寫發布提交、推 main、打 tag;tag 必須落在 main 上。發完版 beta 再把 main 合回來,兩邊保持一致。
  • 不要自作主張選落腳分支:用戶沒說要發版,就不要往 main 提交 / 推送,也不要把 PR 的 base 改成 main。
  • beta 版(預發布)是唯一例外:不切 main,tag 直接落在 beta 分支自己身上(見第 6 節)。

2. 合併 PR:保留貢獻者署名

合併貢獻者的 PR 時,提交作者(author)必須還是貢獻者本人 —— 這直接決定對方能不能進倉庫首頁 Contributors 名單、貢獻圖裡有沒有這一筆。署名是貢獻者應得的東西,不該因為合併方式丟掉。

GitHub 的歸屬規則只有一條:提交頭裡的 author 郵箱出現在某個帳號已驗證的郵箱列表裡,這次提交就算那個帳號的;否則記成匿名條目,不進 Contributors。另有兩條口徑:統計只認預設分支(本倉庫 main),合併提交與空提交不計入。

  • 預設用 GitHub 網頁上的合併按鈕(Merge pull request / Squash and merge / Rebase and merge):三種都會保留原作者為 author;squash 時 PR 裡的多位作者會一併進 co-author 名單。
  • 禁止「本地摘取重提」:把對方的改動拷過來自己提交(本地 git merge --squash 後自己 commit、重抄一遍改動、或改了 author 再提交)都不行 —— 這樣 author 是合併者,貢獻者的署名在 GitHub 側完全不可見。本倉庫歷史上出現過這種情況,別再來一次。
  • 確實要在本地處理時(有衝突要解、要順帶調整),必須把署名帶上:單一原作者用 git commit --author="原作者 <原作者郵箱>";一個提交裡有多個人的工作,在提交資訊末尾加 trailer Co-authored-by: 名字 <郵箱>。
  • 摘除 AI 的 co-author trailer:貢獻者提交資訊末尾的 Co-Authored-By: Claude Code <…> 這類 AI trailer,合併時一律刪除 —— GitHub 會把它渲染成共同作者,進了 main 就出現在 Contributors 名單裡,而 AI 不是貢獻者。只刪 trailer 行本身,author 與其餘提交資訊逐字保留;正文裡對 AI 產品的技術性提及(「支援 Claude Code 用戶端」「Claude 相容端點」之類)與此無關,不動。摘除動的是已合入分支的歷史,趁合併後、發版前盡早做(git filter-branch --msg-filter 摘行後 force-push),拖到發版後就得重寫 main。
  • 郵箱必須能對上帳號:用對方 GitHub 帳號裡已驗證的地址;對方想保密就用 GitHub 給的 ID+使用者名稱@users.noreply.github.com(在對方帳號的 Emails 設定裡查)。內網地址、user@機器名 這類郵箱永遠關聯不上帳號,提交會被記成匿名。
  • 合併後順手核對一次:git log --format='%an <%ae>' -1 <合併提交>,或在 PR 頁面看 commit 旁的頭像是否指向原作者。

3. 回覆 Issue / PR:標明 AI 來源

由 AI 代理發出(含代筆)的每一條 Issue / PR 回覆,末尾都要單獨一行寫明來源。 收件人有權知道自己在跟誰說話 —— 與第 2 節的署名是同一條道理:誰說的寫誰。

固定落款,逐字照用(別改寫成「機器人」「助手」這類含糊說法):

🤖 本條回覆由 AI Agent 生成

  • 位置:整條回覆的最後一行,單獨成段(前後各留一個空行);不要塞進正文段落、列表項、引用區塊或程式碼區塊裡 —— 引用別人的話時,落款落在自己的話之後。
  • 英文場合(外部貢獻者的 PR / Issue)在中文那行下面再補一行 Generated by an AI agent.,說的是同一件事,兩邊都不省。
  • 代理自己新建的 Issue / PR,正文末尾同樣加。
  • 代筆也算:人在對話裡讓代理轉達(哪怕逐字)一段話,落款照加 —— 它描述的是「這條回覆是誰發出去的」,不是「誰構思的」。
  • 只約束 Issue / PR 回覆(評論、review 意見、關閉 / 合併說明)。提交資訊不追加這一行,署名口徑見第 2 節。

4. 版本號

  • 版本號形如 X.Y.Z(如 2.7.2),日常小版本「遞增 0.01」= 末位 +1(如 2.7.8 → 2.7.9)。
  • 遞增幅度以用戶要求為準:預設用上面的「遞增 0.01」;用戶另有要求時(如「這次遞增 0.1」)一律聽用戶的,按用戶指定的幅度算出新版本號,不要自作主張套用預設幅度。
  • 版本號要同步改 5 處(缺一處會導致安裝包與顯示版本對不上):
    1. package.json(根)
    2. desktop-tauri/package.json
    3. desktop-tauri/src-tauri/Cargo.toml
    4. desktop-tauri/src-tauri/tauri.conf.json
    5. desktop-tauri/src-tauri/server/Cargo.toml
  • 應用內「關於」與更新檢查讀的是 env!("CARGO_PKG_VERSION")(第 5 處),改完跑一次 cargo check 讓 Cargo.lock 跟著刷新。
  • 順手過一遍安裝文件:安裝說明已經從 README 搬進 docs/install.md(README 只留速查表 + 一個連結),另有 5 份譯文 docs/install.{en,zh-Hant,ja,ko,pt-BR}.md,六份內容一一對應。凡是這次改動碰到了安裝 / 升級 / 卸載步驟、產物體名、預設連接埠、環境變數、安裝腳本參數,六份都要同步改;README 速查表受影響時也一起改。

5. 正式版發版流程

按順序執行;第 0 節的兩條紅線貫穿全程。

# 1. 收乾淨工作區(tag 裡的程式碼就是發出去的程式碼)
git status --short        # 必須為空;有改動就先提交或清理
cargo check               # 或前端有改動時做一次構建自檢

# 2. 切到 main 並把 beta 合進來
git switch main && git pull
git merge beta

# 3. 五處版本號一起改(預設末位 +1,幅度聽用戶);改完刷新 Cargo.lock
cargo check

# 4. 寫發布提交:提交資訊 = 更新日誌
git commit -am "…更新日誌…"

# 5. 推 main、打 tag、推 tag(一條 v* tag 觸發全部構建)
git push origin main
git tag vX.Y.Z
git push origin vX.Y.Z

# 6. 兩個工作流跑完後掛 GitHub Release
gh run list --limit 4       # 手動跑 gh 前先設代理,見第 8 節
bash scripts/release.sh vX.Y.Z

發布提交的提交資訊 = 更新日誌,因為發版收尾腳本建立 / 更新 Release 時,正文取「tag 所指提交的提交資訊」(git log -1 --format=%B)。

  • 格式沿用歷史版本的編號清單,每行一條,帶分類前綴:新增: / 最佳化: / 修復: / 更新: / 移除:,最後一條固定 版本:X.Y.Z → X.Y.Z+1;
  • 內容取「上個 tag 以來的全部提交」綜合整理(git log vX.Y.Z..HEAD --oneline),純 CI / 臨時的偵錯提交歸併成一條流程性描述即可;
  • 本次沒有程式碼改動時用空提交承載:git commit --allow-empty -F 更新日誌.txt;
  • 更新日誌草稿與歷史發布說明統一寫在 docs/release-notes/<版本號>.md(如 docs/release-notes/2.9.2.md),不要在專案根目錄新建 .release-notes-*.md —— docs/release-notes/ 已在忽略清單裡(只忽略這個目錄,docs/ 下其它文件正常入庫),新增檔案不必再加忽略規則。

推 v* tag 會同時觸發兩個工作流(.github/workflows/):

工作流產出說明
build.yml(build)桌面端三平台安裝包 + Linux 服務端包四個 job:macos(dmg)/ windows(NSIS exe)/ linux-desktop(deb + AppImage)/ linux-server(容器內更新用的 tar.gz)。macOS 與 Linux 桌面端的產物只能在各自平台上構建,無法從 Windows 交叉編譯;所有產物只掛 artifact,GitHub Release 由本地腳本掛載
docker.yml(docker)Docker Hub aimodcc/agent2api:<版本> + :latest(amd64 / arm64 雙架構)手動 workflow_dispatch 觸發時只出 :dev 測試 tag,不碰正式 tag;beta tag(版本號帶 -)只出 <版本>,不移動 :latest

跟蹤進度:

gh run list --limit 4
gh run watch <run-id> --exit-status

發版收尾:GitHub Release 不由 CI 發布(Release 本來就不會自動建立),由本地腳本一步掛載:

bash scripts/release.sh vX.Y.Z            # 自動找該 tag 的成功 build run
bash scripts/release.sh vX.Y.Z <run-id>   # 或明確指定 run

腳本做三件事:下載 build 的安裝包 artifact 到 dist/ → 按 tag 提交資訊(= 更新日誌)建立 / 更新 GitHub Release 並掛附件 → 列印驗收提示。冪等可重跑(--clobber 覆蓋附件)。

6. beta 版(預發布)

應用裡有「設定 → 軟體更新 → 更新設定 → 加入 beta 版」開關:打開的人才收到 beta 更新,沒打開的人只看正式發布。

beta 版不是另一條流水線,而是第 5 節流程的一個變體 —— 唯一結構差別是「從 beta 分支打帶預發布後綴的 tag」,提交、tag、Release、驗收逐字照舊。第 0 節的兩條紅線同樣適用。

# 1. 在 beta 分支上動手(beta 版不碰 main)
git switch beta && git pull
git status --short          # 必須為空

# 2. 五處版本號一起改成「與 tag 逐字一致」的型態:
#    tag 打 v3.1.0-beta.1 → 五處都寫 3.1.0-beta.1(清單見第 4 節)
cargo check                 # 順帶重新整理 Cargo.lock

# 3. 提交並推 beta 分支(提交資訊 = 這次的 beta 更新日誌,格式同第 5 節)
git commit -am "…beta 版日誌…"
git push origin beta

# 4. 打 tag 並推:tag 落在 beta 分支的提交上
git tag v3.1.0-beta.1
git push origin v3.1.0-beta.1

# 5. 兩個工作流跑完後掛 Release(腳本按 tag 裡的 `-` 自動標 pre-release)
gh run list --limit 4
bash scripts/release.sh v3.1.0-beta.1

驗收就三條:Release 顯示 Prerelease、exe / dmg / deb / AppImage 附件齊全、Docker Hub 上 :latest 的 Pushed 時間沒有跟著變(完整清單見第 7 節)。

三處不能錯,每處錯了都有明確症狀:

  1. 五處版本號漏了後綴(寫成 3.1.0):比較是按 semver 做的,執行版本 3.1.0 對線上 tag 3.1.0-beta.1 會判成「目前比線上新」,beta 用戶永遠收不到更新。五個檔案都接受帶後綴的版本號(Cargo / npm / tauri.conf.json 都認),照 tag 抄即可。
  2. Release 漏標 pre-release:標記就是開關的分界線 —— 正式通道走 GitHub 的 /releases/latest,它排除預發布,只有開了開關的人從 /releases 列表裡看到 beta。漏標 = beta 被所有正式版用戶當成正式更新收到。 scripts/release.sh 已按「tag 裡帶 -」自動標記,重跑收尾時也會把標記糾正回來,走腳本就不用操心。
  3. tag 打在 main 上:beta 是集成分支,beta 版要的是它的快照。打在 main 上要麼不含 beta 分支的新改動(白測一場),要麼等於把還沒發布的改動提前推進 main。

docker 的 :latest 不會被 beta tag 移動(.github/workflows/docker.yml),映像檔仍出 3.1.0-beta.1 那個版本 tag,想嚐鮮的按版本號拉。

後續常見三件事:

  • 再發一個 beta:核心號不變、遞增序號(3.1.0-beta.2,五處一起改,上面那套命令照走)。預發布序號能分出先後(beta.2 > beta.1),已經在 beta 上的人照樣收到更新 —— 所以 beta 之間也要保持「tag 與版本號逐字一致」。
  • 轉正(發 3.1.0 正式版):按第 5 節在 main 上走,五處版本號去掉後綴。beta 用戶不會自動接回正式版:開關開著的人只看預發布版(pick_listed_release 按「目前跑的是不是 beta 版」篩),轉正的 3.1.0 對他們不算更新 —— 要留在 beta 頻道的人等下一個 beta(3.2.0-beta.1 一出現就收得到);想回正式版由用戶自己關開關,關掉後只在版本號高於他手上那個 beta 的正式版發布時才收到更新(3.1.0 > 3.1.0-beta.1,但更早的 3.0.9 不會把他降級)。
  • 「打開了卻沒有反應」:倉庫裡一個預發布 Release 都沒有時,打開這個開關也只會看到正式版 —— 第一次 beta 發出去之後才有效果。

7. 驗收清單

  • GitHub Release:gh release view vX.Y.Z(手動跑 gh 前先設代理,見第 8 節)—— 正文日誌齊全,四個桌面端附件都在:Windows Agent2API_<版本>_x64-setup.exe、macOS Agent2API_<版本>_universal.dmg、Linux Agent2API_<版本>_amd64.deb 與 Agent2API_<版本>_amd64.AppImage(另有兩個 agent2api-server-linux-*.tar.gz + .sha256,那是容器內更新包,見第 5 節);
  • Linux 桌面端:裝 deb(或 chmod +x 後跑 AppImage)能啟動,且面板「設定 → 軟體更新」能檢查到版本、給出對應包型的安裝入口(deb → 系統安裝器,AppImage → 換檔案);
  • Docker Hub:aimodcc/agent2api 的 Tags 頁出現 <版本> 與 latest,Pushed 時間一致;
  • 安裝包「關於」頁版本號與 tag 一致;
  • 安裝文件對得上實際產物:docs/install.md 與 5 份譯文的產物名、連接埠、命令、環境變數跟這次 Release 一致(README 裡那幾張速查表同理);
  • beta 版多一條:Release 顯示 Prerelease,且 Docker Hub 上 latest 沒有跟著動。

8. 已知坑與排查

  • GHCR 新包預設私有:若以後映像檔改推 GHCR,首次推送後需到包設定手動改 Public(目前推的是 Docker Hub,無此問題)。

  • gh 不讀 git 的代理設定,跑 gh 前要先設代理環境變數:gh 是 Go 程式,不讀 ~/.gitconfig 裡的 http(s).proxy,也不讀 Windows 系統代理(WinINET),只認 HTTPS_PROXY / HTTP_PROXY 環境變數。本機 GitHub 直連時通時不通,手動執行 gh 命令前先設:

    export HTTPS_PROXY=$(git config --get-urlmatch http.proxy https://github.com || git config --get https.proxy)
    

    只設 HTTPS_PROXY 就夠(gh 的請求全是 HTTPS,實測不讀 HTTP_PROXY)。scripts/release.sh 已內建這一步(從 git 設定讀取後透傳給 gh),用腳本發版無需手動設。代理沒開時 gh 會立刻報 proxyconnect tcp: ... connection refused 而不回退直連 —— 與 git push 的表現一致。

相關技能