Skip to content

Commit b4e1173

Browse files
authored
Merge pull request #2 from pemamian/pr-rules-engine
feat: Pr rules engine - introducing rule based labeling for triage and validation merging to main so we can test the labeling functionality
2 parents 98a2e4c + c4d4c25 commit b4e1173

14 files changed

Lines changed: 1720 additions & 140 deletions

.github/labels.yml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,32 @@
3939
- name: gov:approved
4040
color: 'C2E0C6'
4141
description: Triggers the final code ownership checks
42+
43+
# ==============================================================================
44+
# PROPOSED DYNAMIC & DOMAIN TRIAGE LABELS (For Team Review)
45+
# ==============================================================================
46+
- name: gov:gc-approved
47+
color: 'B5D9F2'
48+
description: Signifies Governance Council approved
49+
50+
- name: gov:tc-approved
51+
color: 'C2E0C6'
52+
description: Signifies Technical Council approved
53+
54+
- name: gov:maintainer-approved
55+
color: 'D4C5F9'
56+
description: Signifies Domain Expert / Maintainer approved
57+
58+
- name: status:review-needed-maintainers
59+
color: 'FBCA04'
60+
description: Missing standard maintainer reviews
61+
62+
- name: status:review-needed-payments-maintainers
63+
color: 'FBCA04'
64+
description: Missing Payments domain maintainer reviews
65+
66+
- name: status:payments-approved
67+
color: 'D4E5FF'
68+
description: Payments domain approvals met
69+
70+

.github/workflows/pr-cron-stale-abandon.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ jobs:
2323
uses: astral-sh/setup-uv@v5
2424

2525
- name: Trace and Mark Stale PRs
26-
run: uv run .github/workflows/scripts/pr-cron-stale-abandon.py
26+
run: uv run .github/workflows/scripts/routing/pr-cron-stale-abandon.py
2727
env:
2828
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
29+
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
---
2+
name: PR Triage Automation
3+
4+
on:
5+
pull_request:
6+
types: [opened, ready_for_review, synchronize, labeled]
7+
issue_comment:
8+
types: [created]
9+
check_suite:
10+
types: [completed]
11+
12+
permissions:
13+
pull-requests: write
14+
issues: write
15+
contents: read
16+
17+
jobs:
18+
triage_realtime:
19+
runs-on: ubuntu-latest
20+
timeout-minutes: 10
21+
if: github.event.pull_request.draft == false
22+
steps:
23+
- name: Checkout repository
24+
uses: actions/checkout@v4
25+
26+
- name: Set up uv
27+
uses: astral-sh/setup-uv@v5
28+
29+
- name: Validate Routing Configurations
30+
run: uv run .github/workflows/scripts/routing/validate-routing.py
31+
env:
32+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
33+
34+
- name: Check and Update PR Labels
35+
run: uv run .github/workflows/scripts/routing/pr-triage-automation.py
36+
env:
37+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
38+

.github/workflows/scripts/pr-cron-stale-abandon.py

Lines changed: 0 additions & 139 deletions
This file was deleted.
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
# UCP PR Triage & Review Routing Automation
2+
3+
This directory houses the modular, configuration-driven Python rules engine designed to automate pull request ingestion triage, blocked/resume lifecycles, dynamically scoped organizational reviews verification, and inactivity stale-PR scans.
4+
5+
---
6+
7+
## Directory Directory Tree Layout
8+
9+
```
10+
scripts/routing/
11+
├── UCP_PR_REVIEW_ROUTING.yml # Centralized rules configuration mapping
12+
├── pr-triage-automation.py # Real-time webhook trigger runner (run by GHA workflow)
13+
├── pr-cron-stale-abandon.py # Daily stale/abandon inactivity scan runner (run by cron GHA workflow)
14+
├── validate-routing.py # Pretty CLI validation tool checking YAML syntax and org group existence
15+
├── test_routing.py # Pretty unit test suite executing mocked verifications locally
16+
└── triage/
17+
├── github_api.py # Encapsulates dynamic PyGithub API calls and organization caching
18+
├── models.py # Standard shared dataclasses and strict LABEL_ Constants
19+
└── rules.py # Core abstract BaseRule class and concrete check implementations
20+
```
21+
22+
---
23+
24+
## 1. Centralized Review Routing Configuration
25+
26+
All folder-to-reviewer-mappings and label states are decoupled completely from the execution codebase and stored in [**`UCP_PR_REVIEW_ROUTING.yml`**](./UCP_PR_REVIEW_ROUTING.yml). This allows developers to flexibly configure or update rules without editing Python modules.
27+
28+
### Configuration Rule Structure:
29+
```yaml
30+
routing_rules:
31+
- name: "Core Protocol & Spec"
32+
patterns:
33+
- "schemas/**/*.json"
34+
- "spec/**/*.md"
35+
review_requirements:
36+
# Maps fully qualified GitHub team handles to approval thresholds and status labels:
37+
"@Universal-Commerce-Protocol/tech-council":
38+
threshold: "majority" # Require TC majority approval or status:tc-majority-approved
39+
needs_review_label: "gov:needs-tc-review"
40+
approved_label: "gov:tc-approved"
41+
"@Universal-Commerce-Protocol/maintainers":
42+
threshold: 1
43+
needs_review_label: "status:review-needed-maintainers"
44+
approved_label: "gov:maintainer-approved"
45+
```
46+
47+
* **`patterns`**: List of path glob filters determining if modifications in the PR match this rule.
48+
* **`review_requirements`**: Maps dynamic, fully qualified organization team handles to:
49+
* `threshold`: Integer count (e.g. `1`, `2`) or `"majority"`.
50+
* `needs_review_label`: Staging label applied when approvals are below the threshold.
51+
* `approved_label`: Calming tint approval label applied dynamically once approvals are satisfied.
52+
53+
---
54+
55+
## 2. Core Rules Scaffolding (`triage/rules.py`)
56+
57+
Triage logic is organized into specialized rule subclasses inheriting from `BaseRule`:
58+
59+
1. **`FileRoutingRule`**: Compiles modified files against the configuration and dynamically applies the corresponding `needs_review_label` and removes the `approved_label`.
60+
2. **`ReviewerApprovalRule`**: Tracks active `pygithub` approvals against the resolved organization team members list:
61+
* **Superpower Override**: If a designated superpower user (like Amit `amithanda`) approves, all TC and GC rules are satisfied instantly, transitioning the PR to `gov:approved` / `status:ready-to-merge`.
62+
* **Label Security Guardrail**: Restricts `gov:tc-approved` and `status:tc-majority-approved` application. If applied by an unauthorized user outside Tech Council or DevOps, the script revokes the label with an automated warning comment.
63+
* **SDK Relaxed Mode**: Repositories matching `sdk` or `meeting-minutes` automatically default team thresholds to `1` to expedite SDK review cycles.
64+
3. **`LabelLifecycleRule`**: Resolves blocked feedback loops. Clears `Label.LABEL_BLOCKED` and restores `Label.LABEL_UNDER_REVIEW` when the author pushes a new commit or comments on the PR.
65+
4. **`StalePRRule`**: Scans active timestamps:
66+
* Under-review PRs inactive for 30 days are labeled `status:stale-review` and `status:needs-triage`.
67+
* Blocked PRs inactive for 37 days are labeled `status:abandon-candidate`.
68+
69+
---
70+
71+
## 3. Local Dry-Run & Validation Utilities
72+
73+
### YAML and Taxonomy Validation:
74+
Developers making changes to `UCP_PR_REVIEW_ROUTING.yml` can test and validate their configurations locally using:
75+
```bash
76+
export GH_TOKEN="your_github_personal_access_token"
77+
uv run .github/workflows/scripts/routing/validate-routing.py
78+
```
79+
This utility checks:
80+
1. **YAML Syntax**: Verifies structure correctness.
81+
2. **Taxonomy Matcher**: Cross-references labels with `.github/labels.yml` to prevent styling typos.
82+
3. **Dynamic Org Team Check**: Dynamically calls the API to verify that all configured dynamic handles actually exist in the active organization (gracefully skipped with a warning on local forks).
83+
84+
### Triage dry-runs:
85+
You can evaluate the rules engine output on any PR locally without committing live updates to GitHub by appending the `--dry-run` option flag:
86+
```bash
87+
export GH_TOKEN="your_token"
88+
uv run .github/workflows/scripts/routing/pr-triage-automation.py --dry-run
89+
```
90+
91+
---
92+
93+
## 4. Local Unit Testing
94+
95+
The rules engine is backed by a mock-based unit test suite verifying all edge conditions. Execute tests locally using:
96+
```bash
97+
export GH_TOKEN="your_token"
98+
uv run .github/workflows/scripts/routing/test_routing.py
99+
```
100+
This outputs high-visibility boxed **Test Run Summary Results** with counts of executed, passed, failed, and errored test cases.
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# UCP PR Review Routing Configuration
2+
# This file acts as the configuration map for pr-triage-automation script.
3+
# It defines glob patterns for changed files and associates them with required reviewer sets and label states.
4+
5+
routing_rules:
6+
- name: "Governance Files"
7+
patterns:
8+
- "LICENSE"
9+
- "GOVERNANCE.md"
10+
- "CONTRIBUTING.md"
11+
- ".github/CODEOWNERS"
12+
review_requirements:
13+
"@Universal-Commerce-Protocol/pemamian":
14+
threshold: 1
15+
needs_review_label: "gov:needs-gc-review"
16+
approved_label: "gov:gc-approved"
17+
18+
- name: "Core Protocol & Spec"
19+
patterns:
20+
- "schemas/**/*.json"
21+
- "spec/**/*.md"
22+
review_requirements:
23+
"@Universal-Commerce-Protocol/tech-council":
24+
threshold: "majority"
25+
needs_review_label: "gov:needs-tc-review"
26+
approved_label: "gov:tc-approved"
27+
"@Universal-Commerce-Protocol/maintainers":
28+
threshold: 1
29+
needs_review_label: "status:review-needed-maintainers"
30+
approved_label: "gov:maintainer-approved"
31+
32+
- name: "Infrastructure & Tooling"
33+
patterns:
34+
- ".github/workflows/**"
35+
- ".gitignore"
36+
- ".pre-commit-config.yaml"
37+
- "pyproject.toml"
38+
- "uv.lock"
39+
review_requirements:
40+
"@Universal-Commerce-Protocol/devops-maintainers":
41+
threshold: 1
42+
needs_review_label: "status:needs-triage"
43+
approved_label: "status:under-review"
44+
45+
- name: "SDK Code & Maintenance"
46+
patterns:
47+
- "src/**"
48+
- "templates/**"
49+
review_requirements:
50+
"@Universal-Commerce-Protocol/maintainers":
51+
threshold: 1
52+
needs_review_label: "status:needs-triage"
53+
approved_label: "status:under-review"
54+
55+
- name: "Payments Custom Review Rules"
56+
patterns:
57+
- "src/components/payments/**"
58+
review_requirements:
59+
"@Universal-Commerce-Protocol/maintainers":
60+
threshold: 1
61+
needs_review_label: "status:review-needed-payments-maintainers"
62+
approved_label: "status:payments-approved"
63+
"@Universal-Commerce-Protocol/tech-council":
64+
threshold: 1
65+
needs_review_label: "gov:needs-tc-review"
66+
approved_label: "gov:tc-approved"

0 commit comments

Comments
 (0)