Skip to content

Commit c2a0f77

Browse files
committed
feat: check teams
Check team membership. Fixes #13
1 parent deaa910 commit c2a0f77

File tree

3 files changed

+42
-6
lines changed

3 files changed

+42
-6
lines changed

.github/CODEOWNERS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ packages/documentation/copy/ja/**/*.ts @sasurau4 @Quramy @Naturalclar @Takepepe
1515
# Collaborators for Portuguese Translation of the Website
1616
packages/playground-examples/copy/pt/**/*.md @khaosdoctor @danilofuchs @orta
1717
packages/playground-examples/copy/pt/**/*.ts @khaosdoctor @danilofuchs @orta
18-
packages/tsconfig-reference/copy/pt/**/*.md @khaosdoctor @danilofuchs @orta
18+
packages/tsconfig-reference/copy/pt/**/*.md @khaosdoctor @danilofuchs @orta @teamA
1919
packages/typescriptlang-org/src/copy/pt/**/*.ts @khaosdoctor @danilofuchs @orta
2020
packages/documentation/copy/pt/**/*.ts @khaosdoctor @danilofuchs @orta
2121

index.js

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -239,13 +239,23 @@ class Actor {
239239
function getFilesNotOwnedByCodeOwner(owner, files, cwd) {
240240
const filesWhichArentOwned = []
241241
const codeowners = new Codeowners(cwd);
242+
const octokit = getOctokit(process.env.GITHUB_TOKEN)
242243

243244
for (const file of files) {
244245
const relative = file.startsWith("/") ? file.slice(1) : file
245246
let owners = codeowners.getOwner(relative);
246-
if (!owners.includes(owner)) {
247-
filesWhichArentOwned.push(file)
247+
if (owners.includes(owner)) {
248+
continue
249+
}
250+
251+
if (owners
252+
.filter(owner => owner.startsWith("@"))
253+
.some(teamowner => getTeamMembers(octokit, teamowner).then(result => result.includes(owner)))
254+
) {
255+
continue
248256
}
257+
258+
filesWhichArentOwned.push(file)
249259
}
250260

251261
return filesWhichArentOwned
@@ -263,7 +273,21 @@ function getFilesNotOwnedByCodeOwner(owner, files, cwd) {
263273
const codeowners = new Codeowners(cwd);
264274
const contents = readFileSync(codeowners.codeownersFilePath, "utf8").toLowerCase()
265275

266-
return contents.includes("@" + login.toLowerCase() + " ") || contents.includes("@" + login.toLowerCase() + "\n")
276+
if (contents.includes("@" + login.toLowerCase() + " ") || contents.includes("@" + login.toLowerCase() + "\n")) {
277+
return true
278+
}
279+
280+
const regex = /\@[a-zA-Z0-9]+\/[a-zA-Z0-9]+ /g;
281+
const potentialTeams = contents.match(regex);
282+
if (potentialTeams == null || potentialTeams.length == 0) {
283+
return false
284+
}
285+
286+
const octokit = getOctokit(process.env.GITHUB_TOKEN)
287+
288+
return potentialTeams.some(team =>
289+
getTeamMembers(octokit, team.replace(" ","")).then(result => result.includes(login.toLowerCase()))
290+
)
267291
}
268292

269293

@@ -314,6 +338,12 @@ async function getPRChangedFiles(octokit, repoDeets, prNumber) {
314338
return fileStrings
315339
}
316340

341+
async function getTeamMembers(octokit, teamname) {
342+
const components = teamname.replace("@","").split("/")
343+
const teamMembers = await octokit.paginate('GET /orgs/:org/teams/:team/members', {org: components[0], team: components[1]})
344+
return teamMembers.map(teammember => teammember.login)
345+
}
346+
317347
async function createOrAddLabel(octokit, repoDeets, labelConfig) {
318348
let label = null
319349
const existingLabels = await octokit.paginate('GET /repos/:owner/:repo/labels', { owner: repoDeets.owner, repo: repoDeets.repo })

index.test.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,16 @@ test("determine who owns a set of files", () => {
99
});
1010

1111
test("real world", () => {
12+
// Stoovon is a member of teamA.
1213
const changed = ["/packages/tsconfig-reference/copy/pt/options/files.md"];
1314
const filesNotInCodeowners = findCodeOwnersForChangedFiles(changed, ".");
14-
expect(filesNotInCodeowners.users).toEqual(["@khaosdoctor", "@danilofuchs", "@orta"]);
15+
expect(filesNotInCodeowners.users).toEqual(["@khaosdoctor", "@danilofuchs", "@orta", "@stoovon"]);
1516
});
1617

1718
test("real world 2", () => {
1819
const changed = ["/packages/typescriptlang-org/src/copy/pt/index.ts", "/packages/typescriptlang-org/src/copy/pt/nav.ts"];
1920
const filesNotInCodeowners = findCodeOwnersForChangedFiles(changed, ".");
20-
expect(filesNotInCodeowners.users).toEqual(["@khaosdoctor", "@danilofuchs", "@orta"]);
21+
expect(filesNotInCodeowners.users).toEqual(["@khaosdoctor", "@danilofuchs", "@orta", "@stoovon"]);
2122
});
2223

2324
test("real world with labels", () => {
@@ -40,6 +41,11 @@ describe(githubLoginIsInCodeowners, () => {
4041
const ortaIn = githubLoginIsInCodeowners("orta", ".");
4142
expect(ortaIn).toEqual(true);
4243
});
44+
test("allows folks in teams found in the codeowners", () => {
45+
// Stoovon is a member of teamA.
46+
const stoovonIn = githubLoginIsInCodeowners("stoovon", ".");
47+
expect(stoovonIn).toEqual(true);
48+
});
4349
test("ignores case", () => {
4450
const ortaIn = githubLoginIsInCodeowners("OrTa", ".");
4551
expect(ortaIn).toEqual(true);

0 commit comments

Comments
 (0)