pull-request-automation
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChinesePull Request Automation
Pull Request 自动化
Overview
概述
Implement pull request automation to streamline code review processes, enforce quality standards, and reduce manual overhead through templated workflows and intelligent assignment rules.
通过模板化工作流和智能分配规则实现Pull Request自动化,以简化代码评审流程、执行质量标准并减少手动工作量。
When to Use
适用场景
- Code review standardization
- Quality gate enforcement
- Contributor guidance
- Review assignment automation
- Merge automation
- PR labeling and organization
- 代码评审标准化
- 质量关卡执行
- 贡献者指导
- 评审分配自动化
- 合并自动化
- PR标签与分类
Implementation Examples
实现示例
1. GitHub Pull Request Template
1. GitHub Pull Request 模板
markdown
undefinedmarkdown
undefined.github/pull_request_template.md
.github/pull_request_template.md
Description
Description
Briefly describe the changes made in this PR.
Briefly describe the changes made in this PR.
Type of Change
Type of Change
- Bug fix (non-breaking change that fixes an issue)
- New feature (non-breaking change that adds functionality)
- Breaking change (fix or feature that would cause existing functionality to change)
- Documentation update
- Bug fix (non-breaking change that fixes an issue)
- New feature (non-breaking change that adds functionality)
- Breaking change (fix or feature that would cause existing functionality to change)
- Documentation update
Related Issues
Related Issues
Closes #(issue number)
Closes #(issue number)
Changes Made
Changes Made
- Change 1
- Change 2
- Change 1
- Change 2
Testing
Testing
- Unit tests added/updated
- Integration tests pass
- Manual testing completed
- Unit tests added/updated
- Integration tests pass
- Manual testing completed
Checklist
Checklist
- Code follows style guidelines
- Self-review completed
- Comments added for complex logic
- Documentation updated
- No new warnings generated
- Tests pass locally
- Code follows style guidelines
- Self-review completed
- Comments added for complex logic
- Documentation updated
- No new warnings generated
- Tests pass locally
Screenshots (if applicable)
Screenshots (if applicable)
Add screenshots for UI changes
Add screenshots for UI changes
Performance Impact
Performance Impact
- No performance impact
- Performance improved
- Potential performance implications (describe)
- No performance impact
- Performance improved
- Potential performance implications (describe)
Dependencies
Dependencies
List any new dependencies or version changes
undefinedList any new dependencies or version changes
undefined2. GitHub Actions: Auto Review Assignment
2. GitHub Actions:自动分配评审人
yaml
undefinedyaml
undefined.github/workflows/auto-assign.yml
.github/workflows/auto-assign.yml
name: Auto Assign PR
on:
pull_request:
types: [opened, reopened]
jobs:
assign:
runs-on: ubuntu-latest
steps:
- name: Assign reviewers
uses: actions/github-script@v7
with:
script: |
const pr = context.payload.pull_request;
const reviewers = ['reviewer1', 'reviewer2', 'reviewer3'];
// Select random reviewers
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: Add labels
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
});
}undefinedname: Auto Assign PR
on:
pull_request:
types: [opened, reopened]
jobs:
assign:
runs-on: ubuntu-latest
steps:
- name: Assign reviewers
uses: actions/github-script@v7
with:
script: |
const pr = context.payload.pull_request;
const reviewers = ['reviewer1', 'reviewer2', 'reviewer3'];
// Select random reviewers
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: Add labels
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
});
}undefined3. GitHub Actions: Auto Merge on Approval
3. GitHub Actions:评审通过后自动合并
yaml
undefinedyaml
undefined.github/workflows/auto-merge.yml
.github/workflows/auto-merge.yml
name: Auto Merge 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: Check PR status
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
});
// Check if all required checks passed
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) {
// Auto merge with squash strategy
await github.rest.pulls.merge({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.issue.number,
merge_method: 'squash'
});
}undefinedname: Auto Merge 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: Check PR status
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
});
// Check if all required checks passed
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) {
// Auto merge with squash strategy
await github.rest.pulls.merge({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.issue.number,
merge_method: 'squash'
});
}undefined4. GitLab Merge Request Automation
4. GitLab 合并请求自动化
yaml
undefinedyaml
undefined.gitlab/merge_request_templates/default.md
.gitlab/merge_request_templates/default.md
Description
Description
<!-- Briefly describe what this MR does -->
<!-- Briefly describe what this MR does -->
Related Issue
Related Issue
Closes #(issue number)
Closes #(issue number)
Checklist
Checklist
- Tests added/updated
- Documentation updated
- Code review self-check completed
- No new console errors/warnings
- Tests added/updated
- Documentation updated
- Code review self-check completed
- No new console errors/warnings
Type of Change
Type of Change
- Bug fix
- Feature
- Breaking change
- Documentation
undefined- Bug fix
- Feature
- Breaking change
- Documentation
undefined5. Bors: Merge Automation Configuration
5. Bors:合并自动化配置
toml
undefinedtoml
undefinedbors.toml
bors.toml
status = [
"continuous-integration/travis-ci/pr",
"continuous-integration/circleci",
"codecov/project/overall"
]
status = [
"continuous-integration/travis-ci/pr",
"continuous-integration/circleci",
"codecov/project/overall"
]
Reviewers
Reviewers
reviewers = ["reviewer1", "reviewer2"]
reviewers = ["reviewer1", "reviewer2"]
Block merge if status checks fail
Block merge if status checks fail
block_labels = ["blocked", "no-merge"]
block_labels = ["blocked", "no-merge"]
Automatically merge if all checks pass
Automatically merge if all checks pass
timeout_sec = 3600
timeout_sec = 3600
Delete branch after merge
Delete branch after merge
delete_merged_branches = true
delete_merged_branches = true
Squash commits on merge
Squash commits on merge
squash_commits = true
undefinedsquash_commits = true
undefined6. Conventional Commit Validation
6. 规范提交验证
bash
#!/bin/bashbash
#!/bin/bashcommit-msg validation script
commit-msg validation script
COMMIT_MSG=$(<"$1")
COMMIT_MSG=$(<"$1")
Pattern: type(scope): subject
Pattern: type(scope): subject
PATTERN="^(feat|fix|docs|style|refactor|test|chore)(([a-z-]+))?: .{1,50}$"
if ! [[ $COMMIT_MSG =~ $PATTERN ]]; then
echo "❌ Commit message does not follow Conventional Commits format"
echo "Format: type(scope): subject"
echo "Types: feat, fix, docs, style, refactor, test, chore"
exit 1
fi
echo "✅ Commit message format is valid"
exit 0
undefinedPATTERN="^(feat|fix|docs|style|refactor|test|chore)(([a-z-]+))?: .{1,50}$"
if ! [[ $COMMIT_MSG =~ $PATTERN ]]; then
echo "❌ Commit message does not follow Conventional Commits format"
echo "Format: type(scope): subject"
echo "Types: feat, fix, docs, style, refactor, test, chore"
exit 1
fi
echo "✅ Commit message format is valid"
exit 0
undefined7. PR Title Validation Workflow
7. PR标题验证工作流
yaml
undefinedyaml
undefined.github/workflows/validate-pr-title.yml
.github/workflows/validate-pr-title.yml
name: Validate PR Title
on:
pull_request:
types: [opened, reopened, edited]
jobs:
validate:
runs-on: ubuntu-latest
steps:
- name: Validate PR title format
uses: actions/github-script@v7
with:
script: |
const pr = context.payload.pull_request;
const title = pr.title;
// Pattern: type: description
const pattern = /^(feat|fix|docs|style|refactor|test|chore|perf)(\(.+\))?: .{1,80}$/;
if (!pattern.test(title)) {
core.setFailed(
'PR title must follow: type: description\n' +
'Types: feat, fix, docs, style, refactor, test, chore, perf'
);
}undefinedname: Validate PR Title
on:
pull_request:
types: [opened, reopened, edited]
jobs:
validate:
runs-on: ubuntu-latest
steps:
- name: Validate PR title format
uses: actions/github-script@v7
with:
script: |
const pr = context.payload.pull_request;
const title = pr.title;
// Pattern: type: description
const pattern = /^(feat|fix|docs|style|refactor|test|chore|perf)(\(.+\))?: .{1,80}$/;
if (!pattern.test(title)) {
core.setFailed(
'PR title must follow: type: description\n' +
'Types: feat, fix, docs, style, refactor, test, chore, perf'
);
}undefined8. Code Coverage Requirement
8. 代码覆盖率要求
yaml
undefinedyaml
undefined.github/workflows/coverage-check.yml
.github/workflows/coverage-check.yml
name: Coverage Check
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 tests with coverage
run: npm run test:coverage
- name: Upload coverage
uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./coverage/lcov.info
fail_ci_if_error: true
minimum-coverage: 80undefinedname: Coverage Check
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 tests with coverage
run: npm run test:coverage
- name: Upload coverage
uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./coverage/lcov.info
fail_ci_if_error: true
minimum-coverage: 80undefinedBest Practices
最佳实践
✅ DO
✅ 建议做法
- Use PR templates for consistency
- Require code reviews before merge
- Enforce CI/CD checks pass
- Auto-assign reviewers based on code ownership
- Label PRs for organization
- Validate commit messages
- Use squash commits for cleaner history
- Set minimum coverage requirements
- Provide detailed PR descriptions
- 使用PR模板确保一致性
- 合并前要求代码评审
- 强制执行CI/CD检查通过
- 根据代码归属自动分配评审人
- 为PR添加标签以便分类
- 验证提交消息格式
- 使用压缩提交保持清晰的提交历史
- 设置最低覆盖率要求
- 提供详细的PR描述
❌ DON'T
❌ 避免做法
- Approve without reviewing code
- Merge failing CI checks
- Use vague PR titles
- Skip automated checks
- Merge to protected branches without review
- Ignore code coverage drops
- Force push to shared branches
- Merge directly without PR
- 未评审代码就批准
- 合并未通过CI检查的PR
- 使用模糊的PR标题
- 跳过自动化检查
- 未经过评审就合并到受保护分支
- 忽略代码覆盖率下降
- 强制推送到共享分支
- 不通过PR直接合并
CODEOWNERS Configuration
CODEOWNERS 配置
bash
undefinedbash
undefined.github/CODEOWNERS
.github/CODEOWNERS
Global owners
Global owners
- @owner1 @owner2
- @owner1 @owner2
Documentation
Documentation
/docs/ @doc-owner
*.md @doc-owner
/docs/ @doc-owner
*.md @doc-owner
Backend
Backend
/backend/ @backend-lead @backend-team
/src/api/ @api-team
/backend/ @backend-lead @backend-team
/src/api/ @api-team
Frontend
Frontend
/frontend/ @frontend-lead @frontend-team
/src/components/ @component-team
/frontend/ @frontend-lead @frontend-team
/src/components/ @component-team
DevOps
DevOps
/infra/ @devops-team
/.github/workflows/ @devops-team
undefined/infra/ @devops-team
/.github/workflows/ @devops-team
undefined