github-pr-workflow

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

GitHub Pull Request Workflow

GitHub Pull Request 工作流

Complete guide for managing the PR lifecycle. Each section shows the
gh
way first, then the
git
+
curl
fallback for machines without
gh
.
管理PR生命周期的完整指南。每个章节先展示使用
gh
的方式,再展示针对未安装
gh
的机器,使用
git
+
curl
的替代方案。

Prerequisites

前置条件

  • Authenticated with GitHub (see
    github-auth
    skill)
  • Inside a git repository with a GitHub remote
  • 已通过GitHub认证(参考
    github-auth
    技能)
  • 处于包含GitHub远程仓库的git仓库目录中

Quick Auth Detection

快速认证检测

bash
undefined
bash
undefined

Determine which method to use throughout this workflow

Determine which method to use throughout this workflow

if command -v gh &>/dev/null && gh auth status &>/dev/null; then AUTH="gh" else AUTH="git"

Ensure we have a token for API calls

if [ -z "$GITHUB_TOKEN" ]; then GITHUB_TOKEN=$(grep "github.com" ~/.git-credentials 2>/dev/null | head -1 | sed 's|https://[^:]:([^@])@.*|\1|') fi fi echo "Using: $AUTH"
undefined
if command -v gh &>/dev/null && gh auth status &>/dev/null; then AUTH="gh" else AUTH="git"

Ensure we have a token for API calls

if [ -z "$GITHUB_TOKEN" ]; then GITHUB_TOKEN=$(grep "github.com" ~/.git-credentials 2>/dev/null | head -1 | sed 's|https://[^:]:([^@])@.*|\1|') fi fi echo "Using: $AUTH"
undefined

Extracting Owner/Repo from the Git Remote

从Git远程仓库提取所有者/仓库信息

Many
curl
commands need
owner/repo
. Extract it from the git remote:
bash
undefined
许多
curl
命令需要
owner/repo
信息。从git远程仓库中提取:
bash
undefined

Works for both HTTPS and SSH remote URLs

Works for both HTTPS and SSH remote URLs

REMOTE_URL=$(git remote get-url origin) OWNER_REPO=$(echo "$REMOTE_URL" | sed -E 's|.*github.com[:/]||; s|.git$||') OWNER=$(echo "$OWNER_REPO" | cut -d/ -f1) REPO=$(echo "$OWNER_REPO" | cut -d/ -f2) echo "Owner: $OWNER, Repo: $REPO"

---
REMOTE_URL=$(git remote get-url origin) OWNER_REPO=$(echo "$REMOTE_URL" | sed -E 's|.*github.com[:/]||; s|.git$||') OWNER=$(echo "$OWNER_REPO" | cut -d/ -f1) REPO=$(echo "$OWNER_REPO" | cut -d/ -f2) echo "Owner: $OWNER, Repo: $REPO"

---

1. Branch Creation

1. 分支创建

This part is pure
git
— identical either way:
bash
undefined
这部分完全使用
git
——两种方式操作一致:
bash
undefined

Make sure you're up to date

Make sure you're up to date

git fetch origin git checkout main && git pull origin main
git fetch origin git checkout main && git pull origin main

Create and switch to a new branch

Create and switch to a new branch

git checkout -b feat/add-user-authentication

Branch naming conventions:
- `feat/description` — new features
- `fix/description` — bug fixes
- `refactor/description` — code restructuring
- `docs/description` — documentation
- `ci/description` — CI/CD changes
git checkout -b feat/add-user-authentication

分支命名规范:
- `feat/description` — 新功能
- `fix/description` — Bug修复
- `refactor/description` — 代码重构
- `docs/description` — 文档更新
- `ci/description` — CI/CD变更

2. Making Commits

2. 提交变更

Use the agent's file tools (
write_file
,
patch
) to make changes, then commit:
bash
undefined
使用Agent的文件工具(
write_file
patch
)修改代码,然后提交:
bash
undefined

Stage specific files

Stage specific files

git add src/auth.py src/models/user.py tests/test_auth.py
git add src/auth.py src/models/user.py tests/test_auth.py

Commit with a conventional commit message

Commit with a conventional commit message

git commit -m "feat: add JWT-based user authentication
  • Add login/register endpoints
  • Add User model with password hashing
  • Add auth middleware for protected routes
  • Add unit tests for auth flow"

Commit message format (Conventional Commits):
type(scope): short description
Longer explanation if needed. Wrap at 72 characters.

Types: `feat`, `fix`, `refactor`, `docs`, `test`, `ci`, `chore`, `perf`
git commit -m "feat: add JWT-based user authentication
  • Add login/register endpoints
  • Add User model with password hashing
  • Add auth middleware for protected routes
  • Add unit tests for auth flow"

提交消息格式(Conventional Commits):
type(scope): short description
Longer explanation if needed. Wrap at 72 characters.

类型:`feat`, `fix`, `refactor`, `docs`, `test`, `ci`, `chore`, `perf`

3. Pushing and Creating a PR

3. 推送分支并创建PR

Push the Branch (same either way)

推送分支(两种方式一致)

bash
git push -u origin HEAD
bash
git push -u origin HEAD

Create the PR

创建PR

With gh:
bash
gh pr create \
  --title "feat: add JWT-based user authentication" \
  --body "## Summary
- Adds login and register API endpoints
- JWT token generation and validation
使用gh:
bash
gh pr create \
  --title "feat: add JWT-based user authentication" \
  --body "## Summary
- Adds login and register API endpoints
- JWT token generation and validation

Test Plan

Test Plan

  • Unit tests pass
Closes #42"

Options: `--draft`, `--reviewer user1,user2`, `--label "enhancement"`, `--base develop`

**With git + curl:**

```bash
BRANCH=$(git branch --show-current)

curl -s -X POST \
  -H "Authorization: token $GITHUB_TOKEN" \
  -H "Accept: application/vnd.github.v3+json" \
  https://api.github.com/repos/$OWNER/$REPO/pulls \
  -d "{
    \"title\": \"feat: add JWT-based user authentication\",
    \"body\": \"## Summary\nAdds login and register API endpoints.\n\nCloses #42\",
    \"head\": \"$BRANCH\",
    \"base\": \"main\"
  }"
The response JSON includes the PR
number
— save it for later commands.
To create as a draft, add
"draft": true
to the JSON body.
  • Unit tests pass
Closes #42"

可选参数:`--draft`, `--reviewer user1,user2`, `--label "enhancement"`, `--base develop`

**使用git + curl:**

```bash
BRANCH=$(git branch --show-current)

curl -s -X POST \
  -H "Authorization: token $GITHUB_TOKEN" \
  -H "Accept: application/vnd.github.v3+json" \
  https://api.github.com/repos/$OWNER/$REPO/pulls \
  -d "{
    \"title\": \"feat: add JWT-based user authentication\",
    \"body\": \"## Summary\nAdds login and register API endpoints.\n\nCloses #42\",
    \"head\": \"$BRANCH\",
    \"base\": \"main\"
  }"
返回的JSON包含PR的
number
——保存该值用于后续命令。
若要创建草稿PR,在JSON体中添加
"draft": true

4. Monitoring CI Status

4. 监控CI状态

Check CI Status

检查CI状态

With gh:
bash
undefined
使用gh:
bash
undefined

One-shot check

One-shot check

gh pr checks
gh pr checks

Watch until all checks finish (polls every 10s)

Watch until all checks finish (polls every 10s)

gh pr checks --watch

**With git + curl:**

```bash
gh pr checks --watch

**使用git + curl:**

```bash

Get the latest commit SHA on the current branch

Get the latest commit SHA on the current branch

SHA=$(git rev-parse HEAD)
SHA=$(git rev-parse HEAD)

Query the combined status

Query the combined status

curl -s
-H "Authorization: token $GITHUB_TOKEN"
https://api.github.com/repos/$OWNER/$REPO/commits/$SHA/status
| python3 -c " import sys, json data = json.load(sys.stdin) print(f"Overall: {data['state']}") for s in data.get('statuses', []): print(f" {s['context']}: {s['state']} - {s.get('description', '')}")"
curl -s
-H "Authorization: token $GITHUB_TOKEN"
https://api.github.com/repos/$OWNER/$REPO/commits/$SHA/status
| python3 -c " import sys, json data = json.load(sys.stdin) print(f"Overall: {data['state']}") for s in data.get('statuses', []): print(f" {s['context']}: {s['state']} - {s.get('description', '')}")"

Also check GitHub Actions check runs (separate endpoint)

Also check GitHub Actions check runs (separate endpoint)

curl -s
-H "Authorization: token $GITHUB_TOKEN"
https://api.github.com/repos/$OWNER/$REPO/commits/$SHA/check-runs
| python3 -c " import sys, json data = json.load(sys.stdin) for cr in data.get('check_runs', []): print(f" {cr['name']}: {cr['status']} / {cr['conclusion'] or 'pending'}")"
undefined
curl -s
-H "Authorization: token $GITHUB_TOKEN"
https://api.github.com/repos/$OWNER/$REPO/commits/$SHA/check-runs
| python3 -c " import sys, json data = json.load(sys.stdin) for cr in data.get('check_runs', []): print(f" {cr['name']}: {cr['status']} / {cr['conclusion'] or 'pending'}")"
undefined

Poll Until Complete (git + curl)

轮询直至完成(git + curl)

bash
undefined
bash
undefined

Simple polling loop — check every 30 seconds, up to 10 minutes

Simple polling loop — check every 30 seconds, up to 10 minutes

SHA=$(git rev-parse HEAD) for i in $(seq 1 20); do STATUS=$(curl -s
-H "Authorization: token $GITHUB_TOKEN"
https://api.github.com/repos/$OWNER/$REPO/commits/$SHA/status
| python3 -c "import sys,json; print(json.load(sys.stdin)['state'])") echo "Check $i: $STATUS" if [ "$STATUS" = "success" ] || [ "$STATUS" = "failure" ] || [ "$STATUS" = "error" ]; then break fi sleep 30 done
undefined
SHA=$(git rev-parse HEAD) for i in $(seq 1 20); do STATUS=$(curl -s
-H "Authorization: token $GITHUB_TOKEN"
https://api.github.com/repos/$OWNER/$REPO/commits/$SHA/status
| python3 -c "import sys,json; print(json.load(sys.stdin)['state'])") echo "Check $i: $STATUS" if [ "$STATUS" = "success" ] || [ "$STATUS" = "failure" ] || [ "$STATUS" = "error" ]; then break fi sleep 30 done
undefined

5. Auto-Fixing CI Failures

5. 自动修复CI失败

When CI fails, diagnose and fix. This loop works with either auth method.
当CI失败时,诊断并修复问题。以下流程适用于两种认证方式。

Step 1: Get Failure Details

步骤1:获取失败详情

With gh:
bash
undefined
使用gh:
bash
undefined

List recent workflow runs on this branch

List recent workflow runs on this branch

gh run list --branch $(git branch --show-current) --limit 5
gh run list --branch $(git branch --show-current) --limit 5

View failed logs

View failed logs

gh run view <RUN_ID> --log-failed

**With git + curl:**

```bash
BRANCH=$(git branch --show-current)
gh run view <RUN_ID> --log-failed

**使用git + curl:**

```bash
BRANCH=$(git branch --show-current)

List workflow runs on this branch

List workflow runs on this branch

curl -s
-H "Authorization: token $GITHUB_TOKEN"
"https://api.github.com/repos/$OWNER/$REPO/actions/runs?branch=$BRANCH&per_page=5"
| python3 -c " import sys, json runs = json.load(sys.stdin)['workflow_runs'] for r in runs: print(f"Run {r['id']}: {r['name']} - {r['conclusion'] or r['status']}")"
curl -s
-H "Authorization: token $GITHUB_TOKEN"
"https://api.github.com/repos/$OWNER/$REPO/actions/runs?branch=$BRANCH&per_page=5"
| python3 -c " import sys, json runs = json.load(sys.stdin)['workflow_runs'] for r in runs: print(f"Run {r['id']}: {r['name']} - {r['conclusion'] or r['status']}")"

Get failed job logs (download as zip, extract, read)

Get failed job logs (download as zip, extract, read)

RUN_ID=<run_id> curl -s -L
-H "Authorization: token $GITHUB_TOKEN"
https://api.github.com/repos/$OWNER/$REPO/actions/runs/$RUN_ID/logs
-o /tmp/ci-logs.zip cd /tmp && unzip -o ci-logs.zip -d ci-logs && cat ci-logs/*.txt
undefined
RUN_ID=<run_id> curl -s -L
-H "Authorization: token $GITHUB_TOKEN"
https://api.github.com/repos/$OWNER/$REPO/actions/runs/$RUN_ID/logs
-o /tmp/ci-logs.zip cd /tmp && unzip -o ci-logs.zip -d ci-logs && cat ci-logs/*.txt
undefined

Step 2: Fix and Push

步骤2:修复并推送

After identifying the issue, use file tools (
patch
,
write_file
) to fix it:
bash
git add <fixed_files>
git commit -m "fix: resolve CI failure in <check_name>"
git push
定位问题后,使用文件工具(
patch
write_file
)修复代码:
bash
git add <fixed_files>
git commit -m "fix: resolve CI failure in <check_name>"
git push

Step 3: Verify

步骤3:验证

Re-check CI status using the commands from Section 4 above.
使用第4节中的命令重新检查CI状态。

Auto-Fix Loop Pattern

自动修复循环模式

When asked to auto-fix CI, follow this loop:
  1. Check CI status → identify failures
  2. Read failure logs → understand the error
  3. Use
    read_file
    +
    patch
    /
    write_file
    → fix the code
  4. git add . && git commit -m "fix: ..." && git push
  5. Wait for CI → re-check status
  6. Repeat if still failing (up to 3 attempts, then ask the user)
当需要自动修复CI时,遵循以下循环:
  1. 检查CI状态 → 定位失败项
  2. 查看失败日志 → 理解错误原因
  3. 使用
    read_file
    +
    patch
    /
    write_file
    → 修复代码
  4. git add . && git commit -m "fix: ..." && git push
  5. 等待CI执行 → 重新检查状态
  6. 若仍失败则重复(最多3次,之后询问用户)

6. Merging

6. 合并PR

With gh:
bash
undefined
使用gh:
bash
undefined

Squash merge + delete branch (cleanest for feature branches)

Squash merge + delete branch (cleanest for feature branches)

gh pr merge --squash --delete-branch
gh pr merge --squash --delete-branch

Enable auto-merge (merges when all checks pass)

Enable auto-merge (merges when all checks pass)

gh pr merge --auto --squash --delete-branch

**With git + curl:**

```bash
PR_NUMBER=<number>
gh pr merge --auto --squash --delete-branch

**使用git + curl:**

```bash
PR_NUMBER=<number>

Merge the PR via API (squash)

Merge the PR via API (squash)

curl -s -X PUT
-H "Authorization: token $GITHUB_TOKEN"
https://api.github.com/repos/$OWNER/$REPO/pulls/$PR_NUMBER/merge
-d "{ "merge_method": "squash", "commit_title": "feat: add user authentication (#$PR_NUMBER)" }"
curl -s -X PUT
-H "Authorization: token $GITHUB_TOKEN"
https://api.github.com/repos/$OWNER/$REPO/pulls/$PR_NUMBER/merge
-d "{ "merge_method": "squash", "commit_title": "feat: add user authentication (#$PR_NUMBER)" }"

Delete the remote branch after merge

Delete the remote branch after merge

BRANCH=$(git branch --show-current) git push origin --delete $BRANCH
BRANCH=$(git branch --show-current) git push origin --delete $BRANCH

Switch back to main locally

Switch back to main locally

git checkout main && git pull origin main git branch -d $BRANCH

Merge methods: `"merge"` (merge commit), `"squash"`, `"rebase"`
git checkout main && git pull origin main git branch -d $BRANCH

合并方式:`"merge"`(合并提交)、`"squash"`(压缩合并)、`"rebase"`(变基合并)

Enable Auto-Merge (curl)

启用自动合并(curl)

bash
undefined
bash
undefined

Auto-merge requires the repo to have it enabled in settings.

Auto-merge requires the repo to have it enabled in settings.

This uses the GraphQL API since REST doesn't support auto-merge.

This uses the GraphQL API since REST doesn't support auto-merge.

PR_NODE_ID=$(curl -s
-H "Authorization: token $GITHUB_TOKEN"
https://api.github.com/repos/$OWNER/$REPO/pulls/$PR_NUMBER
| python3 -c "import sys,json; print(json.load(sys.stdin)['node_id'])")
curl -s -X POST
-H "Authorization: token $GITHUB_TOKEN"
https://api.github.com/graphql
-d "{"query": "mutation { enablePullRequestAutoMerge(input: {pullRequestId: \"$PR_NODE_ID\", mergeMethod: SQUASH}) { clientMutationId } }"}"
undefined
PR_NODE_ID=$(curl -s
-H "Authorization: token $GITHUB_TOKEN"
https://api.github.com/repos/$OWNER/$REPO/pulls/$PR_NUMBER
| python3 -c "import sys,json; print(json.load(sys.stdin)['node_id'])")
curl -s -X POST
-H "Authorization: token $GITHUB_TOKEN"
https://api.github.com/graphql
-d "{"query": "mutation { enablePullRequestAutoMerge(input: {pullRequestId: \"$PR_NODE_ID\", mergeMethod: SQUASH}) { clientMutationId } }"}"
undefined

7. Complete Workflow Example

7. 完整工作流示例

bash
undefined
bash
undefined

1. Start from clean main

1. Start from clean main

git checkout main && git pull origin main
git checkout main && git pull origin main

2. Branch

2. Branch

git checkout -b fix/login-redirect-bug
git checkout -b fix/login-redirect-bug

3. (Agent makes code changes with file tools)

3. (Agent makes code changes with file tools)

4. Commit

4. Commit

git add src/auth/login.py tests/test_login.py git commit -m "fix: correct redirect URL after login
Preserves the ?next= parameter instead of always redirecting to /dashboard."
git add src/auth/login.py tests/test_login.py git commit -m "fix: correct redirect URL after login
Preserves the ?next= parameter instead of always redirecting to /dashboard."

5. Push

5. Push

git push -u origin HEAD
git push -u origin HEAD

6. Create PR (picks gh or curl based on what's available)

6. Create PR (picks gh or curl based on what's available)

... (see Section 3)

... (see Section 3)

7. Monitor CI (see Section 4)

7. Monitor CI (see Section 4)

8. Merge when green (see Section 6)

8. Merge when green (see Section 6)

undefined
undefined

Useful PR Commands Reference

实用PR命令参考

Actionghgit + curl
List my PRs
gh pr list --author @me
curl -s -H "Authorization: token $GITHUB_TOKEN" "https://api.github.com/repos/$OWNER/$REPO/pulls?state=open"
View PR diff
gh pr diff
git diff main...HEAD
(local) or
curl -H "Accept: application/vnd.github.diff" ...
Add comment
gh pr comment N --body "..."
curl -X POST .../issues/N/comments -d '{"body":"..."}'
Request review
gh pr edit N --add-reviewer user
curl -X POST .../pulls/N/requested_reviewers -d '{"reviewers":["user"]}'
Close PR
gh pr close N
curl -X PATCH .../pulls/N -d '{"state":"closed"}'
Check out someone's PR
gh pr checkout N
git fetch origin pull/N/head:pr-N && git checkout pr-N
操作ghgit + curl
列出我的PR
gh pr list --author @me
curl -s -H "Authorization: token $GITHUB_TOKEN" "https://api.github.com/repos/$OWNER/$REPO/pulls?state=open"
查看PR差异
gh pr diff
git diff main...HEAD
(本地)或
curl -H "Accept: application/vnd.github.diff" ...
添加评论
gh pr comment N --body "..."
curl -X POST .../issues/N/comments -d '{"body":"..."}'
请求评审
gh pr edit N --add-reviewer user
curl -X POST .../pulls/N/requested_reviewers -d '{"reviewers":["user"]}'
关闭PR
gh pr close N
curl -X PATCH .../pulls/N -d '{"state":"closed"}'
检出他人的PR
gh pr checkout N
git fetch origin pull/N/head:pr-N && git checkout pr-N