name: pull-request-automation description: 自动化拉取请求工作流程,通过模板、检查清单、自动合并规则和审查分配来减少手动工作量,提高一致性。
拉取请求自动化
概览
实施拉取请求自动化,以简化代码审查流程,执行质量标准,并通过模板化工作流程和智能分配规则减少手动工作量。
何时使用
- 代码审查标准化
- 质量门禁执行
- 贡献者指导
- 审查分配自动化
- 合并自动化
- PR标签和组织
实施示例
1. GitHub 拉取请求模板
# .github/pull_request_template.md
## 描述
简要描述此PR所做的更改。
## 变更类型
- [ ] 错误修复(不破坏性更改,修复问题)
- [ ] 新功能(不破坏性更改,增加功能)
- [ ] 破坏性更改(修复或功能,会导致现有功能变化)
- [ ] 文档更新
## 相关问题
关闭 #(问题编号)
## 变更内容
- 更改1
- 更改2
## 测试
- [ ] 单元测试添加/更新
- [ ] 集成测试通过
- [ ] 手动测试完成
## 检查清单
- [ ] 代码遵循风格指南
- [ ] 自我审查完成
- [ ] 对复杂逻辑添加注释
- [ ] 文档更新
- [ ] 未生成新警告
- [ ] 本地测试通过
## 截图(如适用)
为UI更改添加截图
## 性能影响
- [ ] 无性能影响
- [ ] 性能提升
- [ ] 潜在性能影响(描述)
## 依赖项
列出任何新依赖项或版本变化
2. GitHub Actions: 自动审查分配
# .github/workflows/auto-assign.yml
name: 自动分配PR
on:
pull_request:
types: [opened, reopened]
jobs:
assign:
runs-on: ubuntu-latest
steps:
- name: 分配审查者
uses: actions/github-script@v7
with:
script: |
const pr = context.payload.pull_request;
const reviewers = ['reviewer1', 'reviewer2', 'reviewer3'];
// 选择随机审查者
const selected = reviewers.sort(() => 0.5 - Math.random()).slice(0, 2);
await github.rest.pulls.requestReviewers({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: pr.number,
reviewers: selected
});
- name: 添加标签
uses: actions/github-script@v7
with:
script: |
const pr = context.payload.pull_request;
const labels = [];
if (pr.title.startsWith('feat:')) labels.push('feature');
if (pr.title.startsWith('fix:')) labels.push('bugfix');
if (pr.title.startsWith('docs:')) labels.push('documentation');
if (labels.length > 0) {
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: pr.number,
labels: labels
});
}
3. GitHub Actions: 批准后自动合并
# .github/workflows/auto-merge.yml
name: 自动合并PR
on:
pull_request_review:
types: [submitted]
check_suite:
types: [completed]
jobs:
auto-merge:
runs-on: ubuntu-latest
if: github.event.review.state == 'approved'
steps:
- name: 检查PR状态
uses: actions/github-script@v7
with:
script: |
const pr = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.issue.number
});
// 检查所有必需的检查是否通过
const checkRuns = await github.rest.checks.listForRef({
owner: context.repo.owner,
repo: context.repo.repo,
ref: pr.data.head.ref
});
const allPassed = checkRuns.data.check_runs.every(
run => run.status === 'completed' && run.conclusion === 'success'
);
if (allPassed && pr.data.approved_reviews_count >= 2) {
// 自动合并使用squash策略
await github.rest.pulls.merge({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.issue.number,
merge_method: 'squash'
});
}
4. GitLab 合并请求自动化
# .gitlab/merge_request_templates/default.md
## 描述
<!-- 简要描述此MR的作用 -->
## 相关问题
关闭 #(问题编号)
## 检查清单
- [ ] 测试添加/更新
- [ ] 文档更新
- [ ] 代码审查自检完成
- [ ] 无新控制台错误/警告
## 变更类型
- [ ] 错误修复
- [ ] 功能
- [ ] 破坏性更改
- [ ] 文档
5. Bors: 合并自动化配置
# bors.toml
status = [
"continuous-integration/travis-ci/pr",
"continuous-integration/circleci",
"codecov/project/overall"
]
# 审查者
reviewers = ["reviewer1", "reviewer2"]
# 如果状态检查失败则阻止合并
block_labels = ["blocked", "no-merge"]
# 如果所有检查通过则自动合并
timeout_sec = 3600
# 合并后删除分支
delete_merged_branches = true
# 合并时压缩提交
squash_commits = true
6. 约定提交验证
#!/bin/bash
# commit-msg验证脚本
COMMIT_MSG=$(<"$1")
# 模式:type(scope): subject
PATTERN="^(feat|fix|docs|style|refactor|test|chore)(\([a-z\-]+\))?: .{1,50}$"
if ! [[ $COMMIT_MSG =~ $PATTERN ]]; then
echo "❌ 提交消息不遵循约定提交格式"
echo "格式:type(scope): subject"
echo "类型:feat, fix, docs, style, refactor, test, chore"
exit 1
fi
echo "✅ 提交消息格式有效"
exit 0
7. PR标题验证工作流
# .github/workflows/validate-pr-title.yml
name: 验证PR标题
on:
pull_request:
types: [opened, reopened, edited]
jobs:
validate:
runs-on: ubuntu-latest
steps:
- name: 验证PR标题格式
uses: actions/github-script@v7
with:
script: |
const pr = context.payload.pull_request;
const title = pr.title;
// 模式:type: description
const pattern = /^(feat|fix|docs|style|refactor|test|chore|perf)(\(.+\))?: .{1,80}$/;
if (!pattern.test(title)) {
core.setFailed(
'PR标题必须遵循:type: description
' +
'类型:feat, fix, docs, style, refactor, test, chore, perf'
);
}
8. 代码覆盖率要求
# .github/workflows/coverage-check.yml
name: 覆盖率检查
on: [pull_request]
jobs:
coverage:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '18'
- name: 运行测试并生成覆盖率报告
run: npm run test:coverage
- name: 上传覆盖率
uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./coverage/lcov.info
fail_ci_if_error: true
minimum-coverage: 80
最佳实践
✅ DO
- 使用PR模板以保持一致性
- 在合并前要求代码审查
- 强制CI/CD检查通过
- 根据代码所有权自动分配审查者
- 为组织标记PR
- 验证提交消息
- 使用压缩提交以保持历史清洁
- 设置最小覆盖率要求
- 提供详细的PR描述
❌ DON’T
- 未经审查即批准
- 合并失败的CI检查
- 使用模糊的PR标题
- 跳过自动化检查
- 未经审查即合并到受保护的分支
- 忽略代码覆盖率下降
- 强制推送到共享分支
- 直接合并而无需PR
CODEOWNERS配置
# .github/CODEOWNERS
# 全局所有者
* @owner1 @owner2
# 文档
/docs/ @doc-owner
*.md @doc-owner
# 后端
/backend/ @backend-lead @backend-team
/src/api/ @api-team
# 前端
/frontend/ @frontend-lead @frontend-team
/src/components/ @component-team
# DevOps
/infra/ @devops-team
/.github/workflows/ @devops-team