Skip to content

Commit 68f244e

Browse files
committed
chore: parse individual default reviewers from CODEOWNERS for load-balancing
1 parent 2edfdff commit 68f244e

2 files changed

Lines changed: 38 additions & 32 deletions

File tree

.github/CODEOWNERS

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
# https://help.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners#codeowners-syntax
66

77

8-
# The yoshi-nodejs team is the default owner for nodejs repositories.
9-
* @googleapis/cloud-sdk-nodejs-team
8+
# The cloud sdk nodejs team is the default owner for nodejs repositories.
9+
* @pearigee @feywind @djbruce @shivanee-p
1010
/handwritten/bigquery @googleapis/bigquery-team
1111
/handwritten/cloud-profiler @googleapis/cloud-profiler-team
1212
/handwritten/storage @googleapis/gcs-team

.github/workflows/assign-reviewers.yml

Lines changed: 36 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -101,19 +101,39 @@ jobs:
101101
team_reviewers: teamReviewers,
102102
});
103103
} else {
104-
// Route to cloud-sdk-nodejs-team members with load balancing
105-
console.log("Requesting review from a member of cloud-sdk-nodejs-team using load balancing.");
104+
console.log("Fetching .github/CODEOWNERS to identify default reviewers...");
105+
let defaultReviewers = [];
106106
try {
107-
const { data: members } = await github.rest.teams.listMembersInOrg({
108-
org: 'googleapis',
109-
team_slug: 'cloud-sdk-nodejs-team',
107+
const { data: codeownersData } = await github.rest.repos.getContent({
108+
owner: context.repo.owner,
109+
repo: context.repo.repo,
110+
path: '.github/CODEOWNERS',
110111
});
111-
112-
const memberLogins = members
113-
.map(m => m.login)
114-
.filter(login => login !== author);
112+
const content = Buffer.from(codeownersData.content, 'base64').toString('utf-8');
113+
const lines = content.split('\n');
114+
for (const line of lines) {
115+
const commentIdx = line.indexOf('#');
116+
const cleanLine = (commentIdx !== -1 ? line.substring(0, commentIdx) : line).trim();
117+
if (!cleanLine) continue;
118+
119+
const parts = cleanLine.split(/\s+/);
120+
const pattern = parts[0];
121+
if (pattern === '*') {
122+
const owners = parts.slice(1);
123+
defaultReviewers = owners
124+
.filter(p => p.startsWith('@') && !p.includes('/'))
125+
.map(p => p.substring(1))
126+
.filter(login => login !== author);
127+
break;
128+
}
129+
}
130+
} catch (err) {
131+
console.error("Failed to read or parse CODEOWNERS:", err);
132+
}
115133
116-
if (memberLogins.length > 0) {
134+
if (defaultReviewers.length > 0) {
135+
console.log(`Found default reviewers: ${defaultReviewers.join(', ')}. Load balancing among them.`);
136+
try {
117137
// Retrieve active open PRs to calculate load
118138
const { data: openPRs } = await github.rest.pulls.list({
119139
owner: context.repo.owner,
@@ -123,7 +143,7 @@ jobs:
123143
});
124144
125145
const loadMap = {};
126-
for (const member of memberLogins) {
146+
for (const member of defaultReviewers) {
127147
loadMap[member] = 0;
128148
}
129149
@@ -151,7 +171,7 @@ jobs:
151171
// Find members with the minimum load
152172
let minLoad = Infinity;
153173
let selectedReviewers = [];
154-
for (const member of memberLogins) {
174+
for (const member of defaultReviewers) {
155175
const load = loadMap[member];
156176
if (load < minLoad) {
157177
minLoad = load;
@@ -169,25 +189,11 @@ jobs:
169189
repo: context.repo.repo,
170190
pull_number: context.payload.pull_request.number,
171191
reviewers: [leastLoadedReviewer],
172-
team_reviewers: ['cloud-sdk-nodejs-team'],
173-
});
174-
} else {
175-
console.log("No other members found in cloud-sdk-nodejs-team. Requesting team review only.");
176-
await github.rest.pulls.requestReviewers({
177-
owner: context.repo.owner,
178-
repo: context.repo.repo,
179-
pull_number: context.payload.pull_request.number,
180-
team_reviewers: ['cloud-sdk-nodejs-team'],
181192
});
193+
} catch (err) {
194+
console.error("Failed to assign reviewers using load balancing:", err);
182195
}
183-
} catch (err) {
184-
console.error("Failed to fetch team members or assign reviewers:", err);
185-
// Fallback to just requesting the team review
186-
await github.rest.pulls.requestReviewers({
187-
owner: context.repo.owner,
188-
repo: context.repo.repo,
189-
pull_number: context.payload.pull_request.number,
190-
team_reviewers: ['cloud-sdk-nodejs-team'],
191-
});
196+
} else {
197+
console.warn("No default reviewers found in CODEOWNERS (or they only contained teams/author).");
192198
}
193199
}

0 commit comments

Comments
 (0)