Skip to content

Commit 990c385

Browse files
committed
Enhance PR automation with expanded event types and add reviewer configuration
Signed-off-by: Daniel Ntege <danientege785@gmail.com>
1 parent 28c465f commit 990c385

2 files changed

Lines changed: 124 additions & 1 deletion

File tree

.github/reviewers.json

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
{
2+
"default_reviewers": [],
3+
"path_reviewers": [
4+
{
5+
"glob": "/**",
6+
"reviewers": [
7+
"danielmarv",
8+
"hendrikebbers",
9+
"Jexsie",
10+
"sebtiem",
11+
"Ndacyayisenga-droid"
12+
]
13+
},
14+
{
15+
"glob": ".github/**",
16+
"reviewers": [
17+
"danielmarv",
18+
"hendrikebbers",
19+
"Jexsie",
20+
"sebtiem",
21+
"Ndacyayisenga-droid"
22+
]
23+
},
24+
{
25+
"glob": "docs/**",
26+
"reviewers": [
27+
"danielmarv",
28+
"hendrikebbers",
29+
"Jexsie",
30+
"sebtiem",
31+
"Ndacyayisenga-droid"
32+
]
33+
}
34+
]
35+
}

.github/workflows/pr-automation.yml

Lines changed: 89 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,12 @@ name: PR Automation
22

33
on:
44
pull_request:
5-
types: [opened, synchronize]
5+
types: [opened, reopened, ready_for_review, synchronize]
6+
7+
permissions:
8+
pull-requests: write
9+
issues: write
10+
contents: read
611

712
jobs:
813
auto-label-and-assign:
@@ -66,3 +71,86 @@ jobs:
6671
}).catch(err => {
6772
console.log('Could not assign author: ' + err.message);
6873
})
74+
75+
- name: Auto-request reviewers from JSON config
76+
uses: actions/github-script@v7
77+
with:
78+
script: |
79+
const fs = require('fs');
80+
81+
function toRegex(glob) {
82+
const escaped = glob
83+
.replace(/[.+^${}()|[\]\\]/g, '\\$&')
84+
.replace(/\*\*/g, '::DOUBLE_STAR::')
85+
.replace(/\*/g, '[^/]*')
86+
.replace(/::DOUBLE_STAR::/g, '.*');
87+
return new RegExp(`^${escaped}$`);
88+
}
89+
90+
const configPath = '.github/reviewers.json';
91+
if (!fs.existsSync(configPath)) {
92+
core.info('No .github/reviewers.json found. Skipping reviewer requests.');
93+
return;
94+
}
95+
96+
let config;
97+
try {
98+
config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
99+
} catch (e) {
100+
core.setFailed(`Invalid JSON in ${configPath}: ${e.message}`);
101+
return;
102+
}
103+
104+
const defaultReviewers = Array.isArray(config.default_reviewers) ? config.default_reviewers : [];
105+
const pathRules = Array.isArray(config.path_reviewers) ? config.path_reviewers : [];
106+
107+
const files = await github.paginate(github.rest.pulls.listFiles, {
108+
owner: context.repo.owner,
109+
repo: context.repo.repo,
110+
pull_number: context.issue.number,
111+
per_page: 100
112+
});
113+
const changed = files.map(f => f.filename);
114+
115+
const collected = new Set(defaultReviewers.filter(Boolean));
116+
for (const rule of pathRules) {
117+
if (!rule || !rule.glob || !Array.isArray(rule.reviewers)) continue;
118+
const re = toRegex(String(rule.glob));
119+
if (changed.some(f => re.test(f))) {
120+
for (const reviewer of rule.reviewers) {
121+
if (reviewer) collected.add(reviewer);
122+
}
123+
}
124+
}
125+
126+
const pr = await github.rest.pulls.get({
127+
owner: context.repo.owner,
128+
repo: context.repo.repo,
129+
pull_number: context.issue.number
130+
});
131+
132+
const author = pr.data.user?.login;
133+
const alreadyRequested = new Set((pr.data.requested_reviewers || []).map(r => r.login));
134+
const reviewers = Array.from(collected)
135+
.map(r => String(r).trim())
136+
.filter(Boolean)
137+
.filter(r => r !== author)
138+
.filter(r => !alreadyRequested.has(r))
139+
.slice(0, 15);
140+
141+
if (reviewers.length === 0) {
142+
core.info('No new reviewers to request.');
143+
return;
144+
}
145+
146+
try {
147+
await github.rest.pulls.requestReviewers({
148+
owner: context.repo.owner,
149+
repo: context.repo.repo,
150+
pull_number: context.issue.number,
151+
reviewers
152+
});
153+
core.info(`Requested reviewers: ${reviewers.join(', ')}`);
154+
} catch (e) {
155+
core.warning(`Could not request reviewers: ${e.message}`);
156+
}

0 commit comments

Comments
 (0)