Priority-Based Rules

← Back to Features

When multiple rules match a PR, priority determines which rules are enforced. Create emergency fast-tracks, layer policies by specificity, and override defaults.


Overview

Without priorities, rule conflicts are ambiguous:

  • “Small changes” rule requires 1 approval
  • “Infrastructure” rule requires 2 approvals
  • PR is both small AND touches infrastructure—which applies?

MergeGuard’s priority system:

  • Each rule has a priority (lower number = higher priority)
  • Default priority is 100
  • When multiple rules match, only rules with the highest priority (lowest number) are enforced
  • Multiple rules with the same priority are all enforced

How Priority Works

Rule Evaluation Flow

  1. All rules are evaluated against PR context
  2. Matching rules are identified (conditions satisfied)
  3. Highest priority is selected (lowest priority number among matches)
  4. Only rules with that priority are enforced

Example Scenario

rules:
  - name: "Emergency hotfix"
    priority: 10
    if:
      labels: ["hotfix"]
    require:
      approvals: 1

  - name: "Small changes"
    priority: 50
    if:
      maxLocChanged: 10
    require:
      approvals: 1

  - name: "Default policy"
    priority: 100
    require:
      approvals: 2

PR has hotfix label and 8 LOC changed:

Rule Matched? Priority Enforced?
Emergency hotfix ✅ Yes 10 Yes
Small changes ✅ Yes 50 ❌ No (lower priority)
Default policy ✅ Yes (always) 100 ❌ No (lower priority)

Result: Only “Emergency hotfix” enforced (1 approval needed).


Configuration

Setting Priority

- name: "Rule name"
  priority: 10  # Lower number = higher priority

Default Priority

If omitted, priority defaults to 100:

- name: "Default rule"
  # priority: 100 (implicit)

Priority Range

  • Minimum: 0 (highest priority)
  • Maximum: No limit (but keep reasonable, e.g., <1000)
  • Typical range: 0-100

Use Cases with Examples

1. Emergency Override

Fast-track urgent fixes with highest priority:

rules:
  - name: "Emergency hotfix"
    priority: 1
    if:
      labels: ["hotfix", "urgent"]
    require:
      approvals: 1
      users: ["incident-commander"]
    action:
      autoMerge:
        requireChecks: true
        mergeMethod: "merge"

  - name: "Default policy"
    priority: 100
    require:
      approvals: 2
      teams: ["engineering"]

Result: PRs with hotfix label bypass normal 2-approval process.


2. Layered Policy by Path

Different priorities for different code areas:

rules:
  - name: "Critical infrastructure"
    priority: 10
    if:
      paths: ["infra/**", ".github/workflows/**"]
    require:
      approvals: 3
      teams: ["platform-team", "security-team"]

  - name: "Backend changes"
    priority: 50
    if:
      paths: ["src/backend/**"]
    require:
      approvals: 2
      teams: ["backend-team"]

  - name: "Frontend changes"
    priority: 50
    if:
      paths: ["src/frontend/**"]
    require:
      approvals: 1
      teams: ["frontend-team"]

  - name: "Default"
    priority: 100
    require:
      approvals: 1

Behavior:

  • Infrastructure PR → priority 10 → 3 approvals (overrides backend rule even if backend files change)
  • Backend-only PR → priority 50 → 2 approvals
  • Frontend-only PR → priority 50 → 1 approval
  • Other files → priority 100 → 1 approval

3. Bot vs. Human Differentiation

Bots get different treatment than humans:

rules:
  - name: "Dependabot automation"
    priority: 20
    if:
      author: "dependabot[bot]"
      semverLevel: ["patch", "minor"]
    require:
      checks: ["security-scan"]
    action:
      autoApprove: true
      autoMerge:
        requireChecks: true

  - name: "Human small changes"
    priority: 50
    if:
      maxLocChanged: 10
    require:
      approvals: 1

  - name: "Human default"
    priority: 100
    require:
      approvals: 2

Result:

  • Dependabot patches → auto-merge (priority 20)
  • Human small changes → 1 approval (priority 50)
  • Human large changes → 2 approvals (priority 100)

4. Size-Based Tiers

Scale requirements with PR size using priorities:

rules:
  - name: "Tiny changes"
    priority: 40
    if:
      maxLocChanged: 10
      excludePaths: ["infra/**"]
    require:
      approvals: 1
    action:
      autoApprove: true

  - name: "Small changes"
    priority: 50
    if:
      maxLocChanged: 100
    require:
      approvals: 1

  - name: "Medium changes"
    priority: 60
    if:
      maxLocChanged: 500
    require:
      approvals: 2

  - name: "Large changes"
    priority: 70
    require:
      approvals: 3

Result:

  • ≤10 LOC (non-infra) → auto-approve (priority 40)
  • ≤100 LOC → 1 approval (priority 50)
  • ≤500 LOC → 2 approvals (priority 60)
  • >500 LOC → 3 approvals (priority 70)

5. Same Priority = Multiple Rules Enforced

Combine requirements from multiple rules:

rules:
  - name: "Backend team needed"
    priority: 50
    if:
      paths: ["src/backend/**"]
    require:
      teams: ["backend-team"]

  - name: "Platform team needed"
    priority: 50
    if:
      paths: ["infra/**"]
    require:
      teams: ["platform-team"]

PR touches both src/backend/ and infra/:

  • Both rules match with priority 50
  • Both enforced: need backend-team AND platform-team approval

6. Documentation Fast-Track

Docs skip expensive requirements:

rules:
  - name: "Docs only"
    priority: 10
    if:
      paths: ["docs/**"]
      excludePaths: ["src/**"]
    require:
      approvals: 1
    # No checks required

  - name: "Code changes"
    priority: 100
    require:
      approvals: 2
      checks: ["unit-tests", "integration-tests"]

Result: Docs-only PRs skip CI checks (priority 10 overrides priority 100).


Priority Selection Logic

Single Match

rules:
  - name: "Rule A"
    priority: 10
    if: { ... }

  - name: "Rule B"
    priority: 50
    if: { ... }

If only Rule A matches: Priority 10 enforced.

Multiple Matches, Different Priorities

rules:
  - name: "Rule A"
    priority: 10
  - name: "Rule B"
    priority: 50
  - name: "Rule C"
    priority: 100

If all match: Only Rule A (priority 10) enforced.

Multiple Matches, Same Priority

rules:
  - name: "Rule A"
    priority: 50
  - name: "Rule B"
    priority: 50
  - name: "Rule C"
    priority: 100

If A and B match: Both A and B enforced (priority 50), C ignored.

No Matches

If no rules match (possible if all rules have conditions):

  • ⚠️ MergeGuard Check Run shows “No matching rules”
  • ⚠️ PR is not blocked but has no specific requirements

Best practice: Always have a catch-all default rule with no conditions.


Best Practices

1. Always Have a Default

Include a catch-all rule with no conditions:

- name: "Default policy"
  priority: 100
  require:
    approvals: 2

Ensures every PR has some requirement.

2. Use Round Numbers

Space priorities by 10s for easy insertion:

- priority: 10   # Critical overrides
- priority: 20   # Bot automation
- priority: 30   # Path-specific
- priority: 50   # Size tiers
- priority: 100  # Default

Later, you can insert priority 15 between 10 and 20 without renumbering.

3. Document Priority Intent

Use descriptions to explain priority choices:

- name: "Emergency hotfix"
  description: "Highest priority - overrides all other rules for urgent fixes"
  priority: 1
# Priority 0-20: Critical overrides
# Priority 30-50: Path-based rules
# Priority 60-80: Size-based rules
# Priority 100+: Defaults

Keeps config organized.

5. Test Priority Logic

When adding new rules, test with sample PRs:

  1. Create test PR matching multiple rules
  2. Check MergeGuard Check Run—which rule was enforced?
  3. Adjust priorities if needed

Troubleshooting

Wrong Rule Enforced

Check:

  1. Which rules actually matched? (Check MergeGuard Check Run)
  2. What are their priorities?
  3. Is the highest-priority rule the one you expected?

Debug: Look at Check Run details—shows all matched rules and which were enforced.

Multiple Rules Enforced Unexpectedly

Likely cause: Rules have the same priority.

Fix: Adjust priorities to establish clear precedence:

- name: "Rule A"
  priority: 10  # Should take precedence

- name: "Rule B"
  priority: 20  # Lower precedence

No Rules Match

Symptoms:

  • Check Run says “No matching rules”
  • PR not blocked but has no requirements

Fix: Add a default rule with no conditions:

- name: "Default"
  priority: 100
  require:
    approvals: 1

Advanced: Priority + Auto-Merge

Priorities control which auto-merge behavior applies:

rules:
  - name: "Dependabot full auto"
    priority: 10
    if:
      author: "dependabot[bot]"
    action:
      autoApprove: true
      autoMerge:
        requireChecks: true

  - name: "Human manual merge"
    priority: 100
    require:
      approvals: 2
    # No auto-merge

Result:

  • Dependabot PRs → auto-merge (priority 10)
  • Human PRs → manual merge (priority 100)

Common Priority Patterns

Emergency → Specific → Default

- priority: 1    # Emergency overrides
- priority: 10   # Path-specific overrides
- priority: 50   # Size-based tiers
- priority: 100  # Default catch-all

Bot → Human

- priority: 20   # Bot automation
- priority: 100  # Human requirements

Critical → Normal → Trivial

- priority: 10   # Critical paths (infra, security)
- priority: 50   # Normal code changes
- priority: 90   # Trivial (docs, comments)


← Back to Features