Conditional Approvals
Require different reviewers based on PR context: files changed, lines of code, author, labels, and more.
Overview
GitHub’s native CODEOWNERS provides static file-to-owner mapping, but lacks flexibility:
- Can’t require “at least one from team A AND team B”
- Can’t scale approvals based on change size
- Can’t adjust requirements by label or author
MergeGuard’s conditional approvals solve this with dynamic, context-aware rules.
Configuration Options
Approval Count
Require a specific number of approvals:
require:
approvals: 2
Team-Based Approvals
Require at least one member from each listed team to approve:
require:
teams:
- "platform-team"
- "security-team"
Behavior:
- ✅ At least one member from
platform-teammust approve - ✅ At least one member from
security-teammust approve - ✅ Team membership checked automatically via GitHub API
User-Based Approvals
Require all listed users to approve:
require:
users:
- "tech-lead"
- "security-expert"
Behavior:
- ✅
tech-leadmust approve - ✅
security-expertmust approve - ✅ All users in the list are required
Combined Requirements
You can combine approval types:
require:
approvals: 3 # Total approvals needed
teams: ["platform-team"] # Including one from platform
users: ["tech-lead"] # And tech-lead specifically
Behavior:
- ✅ At least 3 total approvals
- ✅ At least one from
platform-team - ✅
tech-leadmust approve (counts toward the 3)
Use Cases with Examples
1. Two Teams Must Both Approve
Require cross-functional review for critical areas:
- name: "Infrastructure changes"
if:
paths:
- "infra/**"
- "k8s/**"
- ".github/workflows/**"
require:
approvals: 2
teams:
- "platform-team" # one member must approve
- "security-team" # one member must approve
Result: Infrastructure changes need platform AND security team eyes, plus 2 total approvals.
2. Scale Approvals by PR Size
Require more reviewers for larger changes:
rules:
- name: "Tiny changes"
priority: 50
if:
maxLocChanged: 10
require:
approvals: 1
- name: "Medium changes"
priority: 60
if:
maxLocChanged: 300
require:
approvals: 2
- name: "Large changes"
priority: 70
require:
approvals: 3
Result:
- ≤10 LOC → 1 approval
- ≤300 LOC → 2 approvals
- >300 LOC → 3 approvals
3. Emergency Label Triggers On-Call Team
Use labels to route to specific teams:
- name: "Emergency on-call gate"
priority: 5
if:
labels: ["emergency"]
require:
approvals: 1
teams:
- "on-call-team"
users:
- "incident-commander"
Result: PRs with emergency label need on-call team + incident commander approval, bypassing normal 2-approval default.
4. Path-Based Team Routing
Different teams for different code areas:
rules:
- name: "Frontend changes"
if:
paths: ["web/**", "src/frontend/**"]
require:
approvals: 1
teams: ["frontend-team"]
- name: "Backend changes"
if:
paths: ["api/**", "src/backend/**"]
require:
approvals: 2
teams: ["backend-team"]
- name: "Database migrations"
if:
paths: ["db/migrations/**"]
require:
approvals: 2
teams: ["backend-team", "platform-team"]
users: ["dba-lead"]
Result: Different teams review different areas, with database migrations requiring extra oversight.
5. Author-Based Requirements
Different rules for bots vs. humans:
rules:
- name: "Bot PRs"
priority: 10
if:
author: "renovate[bot]"
require:
approvals: 1
action:
autoApprove: true
- name: "Human PRs"
priority: 100
require:
approvals: 2
Result: Bot PRs auto-approved with 1 approval; human PRs need 2.
6. Specific User for Releases
Require release manager for version bumps:
- name: "Release PRs"
if:
labels: ["release"]
paths: ["package.json", "VERSION"]
require:
approvals: 2
users: ["release-manager"]
teams: ["engineering-leads"]
Result: Release PRs need release manager + one engineering lead.
7. Exclude Paths for Fast-Track
Require fewer approvals when sensitive paths aren’t touched:
- name: "Fast-track safe changes"
priority: 20
if:
maxLocChanged: 20
excludePaths:
- "infra/**"
- "secrets/**"
- ".github/workflows/**"
require:
approvals: 1
action:
autoApprove: true
Result: Small changes outside critical paths get auto-approved.
How It Works
1. PR Context Built
When a PR is opened/updated, MergeGuard collects:
- Existing approvals (who has approved)
- Team memberships (via GitHub API)
- PR metadata (files, LOC, labels, author)
2. Rules Evaluated
For each rule that matches:
- Check if required users have approved
- Check if at least one member from each required team has approved
- Count total approvals
3. Check Run Updated
GitHub Check shows:
- ✅ Teams satisfied (e.g., “platform-team: @alice approved”)
- ❌ Teams unsatisfied (e.g., “security-team: awaiting approval”)
- ✅ Users satisfied (e.g., “tech-lead: approved”)
- ❌ Users unsatisfied (e.g., “dba-lead: awaiting approval”)
- Approval count (e.g., “2/3 approvals received”)
4. Merge Blocked or Allowed
- ❌ If any requirement unmet → Check fails, merge blocked
- ✅ If all requirements met → Check passes, merge allowed
Best Practices
Start Conservative
Begin with higher approval counts and relax over time:
- name: "Default"
require:
approvals: 2
Use Exclusions for Fast-Track
Combine positive and negative conditions:
- name: "Fast-track"
priority: 10
if:
maxLocChanged: 10
excludePaths: ["infra/**"]
require:
approvals: 1
Layer by Specificity
High-priority rules for specific cases, lower priority for defaults:
- name: "Critical paths"
priority: 10
if:
paths: ["infra/**"]
require:
approvals: 3
- name: "Default"
priority: 100
require:
approvals: 1
Document Intent
Use descriptions to explain complex rules:
- name: "Database migrations"
description: "Migrations affect production data and need DBA review"
require:
users: ["dba-lead"]
Troubleshooting
Team Approvals Not Satisfied
Check:
- Reviewer is actually a member of the required team (GitHub API sync may lag)
- Review is “Approved” not just “Commented”
- All required teams have at least one approval
Debug: Check the MergeGuard Check Run details—it shows which teams are satisfied/unsatisfied.
User Approvals Not Counted
Check:
- Username matches exactly (case-sensitive)
- User has actually submitted an approval (not just commented)
- Approval wasn’t dismissed after submission
Related Features
- Context-Aware Checks - Conditionally require GitHub checks
- Priority Rules - Override approvals with priority
- Auto-Approval - Automatically approve trusted changes
| ← Back to Features | Next: Context-Aware Checks → |