2024-04-13 17:03:43 +02:00
|
|
|
#!/usr/bin/env node
|
|
|
|
|
2024-08-06 15:50:27 +02:00
|
|
|
// Validates the list in the README are in the correct order, and consistent with the actual GitHub teams.
|
2024-04-13 17:03:43 +02:00
|
|
|
|
2024-08-06 15:50:27 +02:00
|
|
|
import assert from 'node:assert';
|
2024-04-13 17:03:43 +02:00
|
|
|
import { open } from 'node:fs/promises';
|
2024-08-06 15:50:27 +02:00
|
|
|
import { argv } from 'node:process';
|
2024-04-13 17:03:43 +02:00
|
|
|
|
2024-11-02 15:14:40 +01:00
|
|
|
const ghHandleLine = /^\* \[(.+)\]\(https:\/\/github\.com\/\1\) -$/;
|
|
|
|
const memberInfoLine = /^ {2}\*\*[^*]+\*\* <<[^@]+@.+\.[a-z]+>>( \(\w+(\/[^)/]+)+\))?( - \[Support me\]\(.+\))?$/;
|
|
|
|
|
2024-08-06 15:50:27 +02:00
|
|
|
const lists = {
|
|
|
|
'__proto__': null,
|
|
|
|
|
|
|
|
'TSC voting members': 'tsc',
|
|
|
|
'TSC regular members': null,
|
|
|
|
'TSC emeriti members': null,
|
|
|
|
'Collaborators': 'collaborators',
|
|
|
|
'Collaborator emeriti': null,
|
|
|
|
'Triagers': 'issue-triage',
|
|
|
|
};
|
|
|
|
const actualMembers = {
|
|
|
|
__proto__: null,
|
|
|
|
// The bot is part of `@nodejs/collaborators`, but is not listed in the README.
|
|
|
|
collaborators: new Set().add('nodejs-github-bot'),
|
|
|
|
};
|
2024-04-13 17:03:43 +02:00
|
|
|
const tscMembers = new Set();
|
|
|
|
|
|
|
|
const readme = await open(new URL('../README.md', import.meta.url), 'r');
|
|
|
|
|
|
|
|
let currentList = null;
|
2024-11-02 15:14:40 +01:00
|
|
|
let previousGithubHandleInfoRequired;
|
2024-04-13 17:03:43 +02:00
|
|
|
let previousGithubHandle;
|
|
|
|
let lineNumber = 0;
|
|
|
|
|
|
|
|
for await (const line of readme.readLines()) {
|
|
|
|
lineNumber++;
|
2024-11-02 15:14:40 +01:00
|
|
|
if (previousGithubHandleInfoRequired) {
|
|
|
|
if (!memberInfoLine.test(line)) {
|
|
|
|
throw new Error(`${previousGithubHandleInfoRequired} info are not formatted correctly (README.md:${lineNumber})`);
|
|
|
|
}
|
|
|
|
previousGithubHandle = previousGithubHandleInfoRequired;
|
|
|
|
previousGithubHandleInfoRequired = null;
|
|
|
|
} else if (line.startsWith('### ')) {
|
2024-08-06 15:50:27 +02:00
|
|
|
currentList = line.slice(4);
|
2024-04-13 17:03:43 +02:00
|
|
|
previousGithubHandle = null;
|
|
|
|
} else if (line.startsWith('#### ')) {
|
2024-08-06 15:50:27 +02:00
|
|
|
currentList = line.slice(5);
|
2024-04-13 17:03:43 +02:00
|
|
|
previousGithubHandle = null;
|
2024-08-06 15:50:27 +02:00
|
|
|
} else if (currentList in lists && line.startsWith('* [')) {
|
|
|
|
const currentGithubHandle = line.slice(3, line.indexOf(']'));
|
|
|
|
const currentGithubHandleLowerCase = currentGithubHandle.toLowerCase();
|
|
|
|
if (
|
|
|
|
previousGithubHandle &&
|
|
|
|
previousGithubHandle >= currentGithubHandleLowerCase
|
|
|
|
) {
|
|
|
|
throw new Error(
|
|
|
|
`${currentGithubHandle} should be listed before ${previousGithubHandle} in the ${currentList} list (README.md:${lineNumber})`,
|
|
|
|
);
|
2024-04-13 17:03:43 +02:00
|
|
|
}
|
|
|
|
|
2024-11-02 15:14:40 +01:00
|
|
|
if (!ghHandleLine.test(line)) {
|
|
|
|
throw new Error(`${currentGithubHandle} is not formatted correctly (README.md:${lineNumber})`);
|
|
|
|
}
|
|
|
|
|
2024-08-06 15:50:27 +02:00
|
|
|
if (
|
|
|
|
currentList === 'TSC voting members' ||
|
|
|
|
currentList === 'TSC regular members'
|
|
|
|
) {
|
2024-04-13 17:03:43 +02:00
|
|
|
tscMembers.add(currentGithubHandle);
|
|
|
|
} else if (currentList === 'Collaborators') {
|
|
|
|
tscMembers.delete(currentGithubHandle);
|
|
|
|
}
|
2024-08-06 15:50:27 +02:00
|
|
|
if (lists[currentList]) {
|
|
|
|
(actualMembers[lists[currentList]] ??= new Set()).add(currentGithubHandle);
|
|
|
|
}
|
2024-11-02 15:14:40 +01:00
|
|
|
previousGithubHandleInfoRequired = currentGithubHandleLowerCase;
|
2024-04-13 17:03:43 +02:00
|
|
|
}
|
|
|
|
}
|
2024-08-06 15:50:27 +02:00
|
|
|
console.info('Lists are in the alphabetical order.');
|
|
|
|
|
|
|
|
assert.deepStrictEqual(tscMembers, new Set(), 'Some TSC members are not listed as Collaborators');
|
2024-04-13 17:03:43 +02:00
|
|
|
|
2024-08-06 15:50:27 +02:00
|
|
|
if (argv[2] && argv[2] !== '{}') {
|
|
|
|
const reviver = (_, value) =>
|
|
|
|
(typeof value === 'string' && value[0] === '[' && value.at(-1) === ']' ?
|
|
|
|
new Set(JSON.parse(value)) :
|
|
|
|
value);
|
|
|
|
assert.deepStrictEqual(JSON.parse(argv[2], reviver), { ...actualMembers });
|
|
|
|
} else {
|
|
|
|
console.warn('Skipping the check of GitHub teams membership.');
|
2024-04-13 17:03:43 +02:00
|
|
|
}
|