Community编程与开发github.com

Agent2API/agent2api

Agent2API(workbuddy)仓库的协作与发版规范 —— 分支落脚点、合并 PR 与回复 Issue 的署名、版本号递增、正式版与 beta 预发布流程、发版验收与排错。凡是涉及切分支、给 PR 选 base、合并 PR、回 Issue/PR、改版本号、写更新日志、打 tag、挂 GitHub Release、发 beta 版、发版后验收,或排查发版失败时,都先按本 Skill 执行 —— 即使对方没提「发版」「分支」这类字眼。

agent2api 是什么?

agent2api is a Claude Code agent skill that agent2API(workbuddy)仓库的协作与发版规范 —— 分支落脚点、合并 PR 与回复 Issue 的署名、版本号递增、正式版与 beta 预发布流程、发版验收与排错。凡是涉及切分支、给 PR 选 base、合并 PR、回 Issue/PR、改版本号、写更新日志、打 tag、挂 GitHub Release、发 beta 版、发版后验收,或排查发版失败时,都先按本 Skill 执行 —— 即使对方没提「发版」「分支」这类字眼。.

兼容平台✓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 Collaboration & Release Standards

Covers two categories: Daily Collaboration (branch placement, PR attribution, Issue sign-offs, Sections 1–3) and Releasing (version numbers, changelog, tags, Release, verification, Sections 4–7). Troubleshooting is in Section 8.

0. Two Human Red Lines (Must Stop and Wait for Confirmation)

The following two things must first be reviewed and explicitly approved by a human before the agent can proceed; you may prepare drafts and list evidence, but you cannot make the final call:

  1. Releasing: Before entering the release process (changing version numbers, creating the release commit, pushing to main/beta, creating tags, creating a Release), first clearly state the version number and "what is being released this time," and wait for user confirmation. Do not push any branch or tag without confirmation — once a tag is pushed, it triggers builds that produce public installation packages and images, and cannot be undone.
  2. Changelog: The written changelog (the release commit message, which is also the GitHub Release body) must first be reviewed line by line by the user. If the user requests changes to wording, additions/deletions of items, or adjustment of category prefixes, confirm again after making the changes according to feedback; do not commit directly just because "the changes are minor."

During a single release, both red lines apply simultaneously: you need both version number confirmation and changelog confirmation. Only proceed after the user says "continue."

1. Branch Placement: Daily Work Only on beta, Only Touch main for Releases

BranchRoleWhen to Touch It
betaIntegration branch (default landing point)Daily modifications, merging PRs, resolving conflicts — always start here first
mainRelease branchOnly during release builds: switch to main, merge beta in, create tags
  • When merging a PR, select beta as the base, not main. Merging into main prematurely injects unreleased changes into the release branch; afterwards you would have to merge main back into beta, creating an extra merge commit and an opportunity for conflicts. If a PR has already been opened with base=main, change the base to beta on the PR page before merging.
  • Local changes should also be committed to beta (code writing, documentation changes, conflict resolution all count), push to origin/beta; perform merge result verification and build self-checks on beta.
  • Only switch to main for a stable release: git switch main → merge beta in → write the release commit, push main, create a tag; the tag must land on main. After the release, merge main back into beta to keep them in sync.
  • Do not decide the landing branch on your own: If the user hasn't mentioned a release, do not commit/push to main, and do not change the base of a PR to main.
  • Beta versions (pre-releases) are the only exception: do not switch to main, and the tag lands directly on the beta branch itself (see Section 6).

2. Merging Pull Requests: Preserve Contributor Attribution

When merging a contributor's PR, the commit author must remain the contributor themselves — this directly determines whether they appear on the repository's Contributors list and whether the contribution is reflected in the contribution graph. Attribution is something a contributor deserves and should not be lost due to the merge method.

GitHub's attribution rule is simple: if the author email in the commit header appears in a verified email list for an account, that commit counts towards that account; otherwise, it is recorded as an anonymous entry and does not count toward Contributors. Two additional points: statistics only count the default branch (main for this repository), merge commits and empty commits are not counted.

  • Use GitHub's web merge buttons by default (Merge pull request / Squash and merge / Rebase and merge): All three preserve the original author. When squashing, multiple authors from the PR are included in the co-author list.
  • Do not "cherry-pick locally and recommit": Copying the contributor's changes and committing them yourself (e.g., git merge --squash locally then committing yourself, rewriting the changes, or changing the author before committing) is not allowed — this makes the author the merger, and the contributor's attribution becomes completely invisible on GitHub's side. This repository has experienced this issue in the past; do not repeat it.
  • If you genuinely need to handle things locally (e.g., resolving conflicts, making accompanying adjustments), you must carry the attribution: for a single original author, use git commit --author="Original Author <original_author_email>"; if a commit contains work from multiple people, add a trailer at the end of the commit message: Co-authored-by: Name <email>.
  • Remove AI co-author trailers: Any Co-Authored-By: Claude Code <…> or similar AI trailers at the end of a contributor's commit message must be deleted upon merging — GitHub renders them as co-authors, and they would appear on the Contributors list once on main, but AI is not a contributor. Only delete the trailer lines themselves; preserve the author and all other commit message text verbatim. Technical mentions of AI products within the body (e.g., "supports Claude Code client," "Claude-compatible endpoint") are unrelated and should not be touched. Removing these trailers modifies committed history, so do it as early as possible after merging but before the release (e.g., git filter-branch --msg-filter to remove the lines, then force-push). Delaying until after the release would require rewriting main.
  • The email must match an account: Use an address that is verified in the contributor's GitHub account; if they prefer privacy, use GitHub's provided [email protected] (find it in the Emails settings of their account). Internal network addresses, user@hostname style emails, etc., will never be associated with an account, and the commit will be recorded as anonymous.
  • After merging, perform a quick check: git log --format='%an <%ae>' -1 <merge commit>, or check on the PR page whether the avatar next to the commit points to the original author.

3. Replying to Issues / PRs: Indicate AI Source

Every Issue/PR reply issued (including ghostwritten) by an AI agent must have a single line at the end clearly stating the source. The recipient has the right to know who they are talking to — the same principle as Section 2 on attribution: state who said it.

Use this fixed sign-off line, verbatim (do not change it to vague terms like "robot" or "assistant"):

🤖 This reply was generated by an AI Agent

  • Placement: The very last line of the entire reply, on its own paragraph (with a blank line before and after). Do not embed it within body paragraphs, list items, quotes, or code blocks — when quoting someone else's words, the sign-off goes after your own words.
  • English context (PRs/Issues from external contributors): Add a line Generated by an AI agent. below the Chinese line. Both lines describe the same thing; neither should be omitted in this context.
  • If the agent creates a new Issue/PR itself, add the sign-off at the end of the body as well.
  • Ghostwriting counts: Even if a human dictates a message verbatim for the agent to relay, the sign-off must still be added — it describes "who sent this reply," not "who composed it."
  • This only applies to Issue/PR replies (comments, review opinions, closing/merging messages). Do not append this line to commit messages; attribution rules for commits are in Section 2.

4. Version Numbers

  • Version numbers follow the format X.Y.Z (e.g., 2.7.2). A routine minor version increment of "increase by 0.01" means incrementing the last digit by 1 (e.g., 2.7.8 → 2.7.9).
  • Increment amount is determined by user requirements: The default is "increase by 0.01" as above. If the user specifies something different (e.g., "increase by 0.1 this time"), always follow the user's instruction and calculate the new version number according to their specified increment; do not unilaterally apply the default increment.
  • The version number must be updated in 5 places simultaneously (missing one will cause mismatches between the installation package and the displayed version):
    1. package.json (root)
    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
  • The in-app "About" and update checker read env!("CARGO_PKG_VERSION") (location 5). After modifying, run cargo check once to update Cargo.lock accordingly.
  • Review the installation documentation as well: The installation instructions have been moved from the README to docs/install.md (the README only contains a quick reference table + a link). There are also 5 translations: docs/install.{en,zh-Hant,ja,ko,pt-BR}.md. All six files must have identical content. If this release touches installation/upgrade/uninstallation steps, product names, default ports, environment variables, or installation script parameters, all six files must be updated synchronously; update the README quick reference table if affected.

5. Stable Release Process

Execute in order; the two red lines from Section 0 apply throughout.

# 1. Clean up the working tree (the code in the tag is what gets released)
git status --short        # Must be empty; if there are changes, commit or clean them first
cargo check               # Or do a build self-check if there are frontend changes

# 2. Switch to main and merge beta in
git switch main && git pull
git merge beta

# 3. Update all five version numbers together (default: increment the last digit by 1, but follow user's specified increment); refresh Cargo.lock after changes
cargo check

# 4. Write the release commit: commit message = changelog
git commit -am "…changelog…"

# 5. Push main, create tag, push tag (a v* tag triggers all builds)
git push origin main
git tag vX.Y.Z
git push origin vX.Y.Z

# 6. After both workflows finish, create the GitHub Release
gh run list --limit 4       # Set proxy before manually running gh; see Section 8
bash scripts/release.sh vX.Y.Z

The release commit message is the changelog, because the release finalization script creates/updates the Release using the commit message of the commit the tag points to (git log -1 --format=%B).

  • Follow the format of historical version changelogs: an itemized list, one item per line, with category prefixes: New: / Optimize: / Fix: / Update: / Remove:. The last item is always Version: X.Y.Z → X.Y.Z+1.
  • Content is synthesized from all commits since the last tag (git log vX.Y.Z..HEAD --oneline). Pure CI/temporary debug commits can be consolidated into a single procedural description.
  • If there are no code changes this release, use an empty commit: git commit --allow-empty -F changelog.txt.
  • Draft changelogs and historical release notes are uniformly stored in docs/release-notes/<version>.md (e.g., docs/release-notes/2.9.2.md). Do not create .release-notes-*.md files in the project root — docs/release-notes/ is already in the ignore list (only this directory is ignored; other documents under docs/ are normally tracked), so no additional ignore rules are needed for new files.

Pushing a v* tag simultaneously triggers two workflows (.github/workflows/):

WorkflowOutputDescription
build.yml (build)Desktop installation packages for 3 platforms + Linux server packageFour jobs: macos (dmg) / windows (NSIS exe) / linux-desktop (deb + AppImage) / linux-server (tar.gz for in-container updates). macOS and Linux desktop artifacts can only be built on their respective platforms; cross-compilation from Windows is not possible. All artifacts are only uploaded as artifacts; the local script attaches them to the GitHub Release.
docker.yml (docker)Docker Hub aimodcc/agent2api:<version> + :latest (amd64 / arm64 dual architecture)Manual workflow_dispatch only produces a :dev test tag, does not touch official tags. Beta tags (versions containing -) only produce <version>, and do not move :latest.

Track progress:

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

Release Finalization: The GitHub Release is not created by CI (Releases are not automatically created). A local script performs this in one step:

bash scripts/release.sh vX.Y.Z            # Automatically finds the successful build run for this tag
bash scripts/release.sh vX.Y.Z <run-id>   # Or specify the run explicitly

The script does three things: download the build installation package artifacts to dist/ → create/update the GitHub Release using the tag's commit message (= changelog) and attach the files → print a verification prompt. It is idempotent and can be rerun (--clobber overwrites attachments).

6. Beta Version (Pre-release)

The application has a "Settings → Software Update → Update Settings → Join Beta" switch: people who turn it on receive beta updates; people who leave it off only see stable releases.

A beta version is not a separate pipeline, but a variation on the Section 5 process — the only structural difference is "create a tag with a pre-release suffix on the beta branch". The commit, tag, Release, and verification steps are identical verbatim. The two red lines from Section 0 apply equally.

# 1. Work on the beta branch (beta version does not touch main)
git switch beta && git pull
git status --short          # Must be empty

# 2. Update all five version numbers to match the tag verbatim:
#    Tag is v3.1.0-beta.1 → all five locations write 3.1.0-beta.1 (list in Section 4)
cargo check                 # Also refreshes Cargo.lock

# 3. Commit and push the beta branch (commit message = this beta's changelog, format same as Section 5)
git commit -am "…beta changelog…"
git push origin beta

# 4. Create tag and push: tag lands on the commit on the beta branch
git tag v3.1.0-beta.1
git push origin v3.1.0-beta.1

# 5. After both workflows finish, create the Release (the script automatically marks it as pre-release based on the `-` in the tag)
gh run list --limit 4
bash scripts/release.sh v3.1.0-beta.1

Verification has three criteria: Release shows Prerelease, exe/dmg/deb/AppImage attachments are all present, and Docker Hub's :latest Pushed time has not changed (full checklist in Section 7).

Three things that must not go wrong, each with a clear symptom:

  1. Version numbers missing the suffix (written as 3.1.0): Comparison is semver-based. The running version 3.1.0 against the online tag 3.1.0-beta.1 would be judged as "current version is newer than the online one," and beta users would never receive the update. All five files accept version numbers with suffixes (Cargo/npm/tauri.conf.json all do), so just copy from the tag.
  2. Release missing the pre-release marker: The marker is the dividing line — the stable channel uses GitHub's /releases/latest, which excludes pre-releases; only users who turned on the switch see beta versions from the /releases list. Missing the marker means beta versions are received by all stable users as a stable update. scripts/release.sh automatically marks based on the - in the tag; rerunning the finalization script will also correct the marker, so using the script eliminates this concern.
  3. Tag created on main: Beta is the integration branch, and the beta version needs its snapshot. Creating the tag on main either excludes the new changes on the beta branch (essentially testing nothing useful) or prematurely pushes unreleased changes into main.

Docker's :latest is not moved by a beta tag (.github/workflows/docker.yml). The image is still produced as the version tag 3.1.0-beta.1; users who want to try it can pull by that version number.

Three common subsequent actions:

  • Release another beta: Keep the core version number, increment the sequence number (3.1.0-beta.2, update all five locations, run the same steps as above). Pre-release sequence numbers are ordered (beta.2 > beta.1), so users already on the beta will still receive the update — hence, maintain the "tag and version number match verbatim" rule between betas as well.
  • Graduate to stable (release 3.1.0 stable): Follow Section 5 on main, remove the suffix from all five version numbers. Beta users will not automatically switch back to stable: users who have the switch turned on only see pre-releases (the filtering is by "whether the current running version is a beta version" via pick_listed_release). The graduated 3.1.0 is not an update for them — users who want to stay on the beta channel will get the next beta (3.2.0-beta.1 once it appears). Users who want to return to the stable channel can turn off the switch themselves. After turning it off, they will only receive updates when a stable version is released with a version number higher than the beta they currently have (3.1.0 > 3.1.0-beta.1, but an earlier 3.0.9 would not downgrade them).
  • "It doesn't work after turning on the switch": If there are no pre-release Releases in the repository at all, turning on the switch will still only show stable versions — it only takes effect after the first beta is released.

7. Verification Checklist

  • GitHub Release: gh release view vX.Y.Z (set proxy before manually running gh; see Section 8) — the body contains the complete changelog, and all four desktop attachments are present: Windows Agent2API_<version>_x64-setup.exe, macOS Agent2API_<version>_universal.dmg, Linux Agent2API_<version>_amd64.deb and Agent2API_<version>_amd64.AppImage (plus two agent2api-server-linux-*.tar.gz + .sha256 files, which are the in-container update packages; see Section 5).
  • Linux desktop: Installing the deb (or running chmod +x and executing the AppImage) allows the app to launch, and the panel "Settings → Software Update" can detect the version and provide the correct installation entry for the package type (deb → system installer, AppImage → replace file).
  • Docker Hub: The Tags page for aimodcc/agent2api shows <version> and latest, with matching Pushed times.
  • The "About" page in the installation package shows a version number matching the tag.
  • The installation documentation matches the actual artifacts: docs/install.md and the 5 translations have artifact names, ports, commands, and environment variables consistent with this Release (the quick reference tables in the README should be checked similarly).
  • One additional check for beta versions: The Release shows Prerelease, and Docker Hub's latest has not moved.

8. Known Pitfalls and Troubleshooting

  • New GHCR packages are private by default: If the image is later pushed to GHCR, the first push requires manually changing the package settings to Public (currently pushing to Docker Hub, so this is not an issue).

  • gh does not read git's proxy configuration; set the proxy environment variable before running gh: gh is a Go program and does not read http(s).proxy from ~/.gitconfig, nor the Windows system proxy (WinINET). It only recognizes the HTTPS_PROXY / HTTP_PROXY environment variables. If direct GitHub access from your machine is intermittent, set the proxy before executing gh commands manually:

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

    Setting only HTTPS_PROXY is sufficient (gh only makes HTTPS requests; it has been verified that it does not read HTTP_PROXY in practice). scripts/release.sh already has this step built-in (it reads from the git configuration and passes it to gh), so using the script for releases eliminates the need to set it manually. If the proxy is not running, gh will immediately report proxyconnect tcp: ... connection refused without falling back to a direct connection — this is consistent with git push behavior.

相关技能