diff --git a/.github/workflows/linters.yml b/.github/workflows/linters.yml index bfc1cd66785..dd1f9ee1ae6 100644 --- a/.github/workflows/linters.yml +++ b/.github/workflows/linters.yml @@ -179,3 +179,10 @@ jobs: persist-credentials: false # GH Actions squashes all PR commits, HEAD^ refers to the base branch. - run: git diff HEAD^ HEAD -G"pr-url:" -- "*.md" | ./tools/lint-pr-url.mjs ${{ github.event.pull_request.html_url }} + lint-readme: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + persist-credentials: false + - run: tools/lint-readme-lists.mjs diff --git a/README.md b/README.md index a3ee8b7444b..04df77247f8 100644 --- a/README.md +++ b/README.md @@ -343,10 +343,10 @@ For information about the governance of the Node.js project, see **Erick Wendel** <> (he/him) * [Ethan-Arrowood](https://github.com/Ethan-Arrowood) - **Ethan Arrowood** <> (he/him) -* [fhinkel](https://github.com/fhinkel) - - **Franziska Hinkelmann** <> (she/her) * [F3n67u](https://github.com/F3n67u) - **Feng Yu** <> (he/him) +* [fhinkel](https://github.com/fhinkel) - + **Franziska Hinkelmann** <> (she/her) * [Flarna](https://github.com/Flarna) - **Gerhard Stöbich** <> (he/they) * [gabrielschulhof](https://github.com/gabrielschulhof) - @@ -429,12 +429,12 @@ For information about the governance of the Node.js project, see **Stephen Belanger** <> (he/him) * [RafaelGSS](https://github.com/RafaelGSS) - **Rafael Gonzaga** <> (he/him) -* [rluvaton](https://github.com/rluvaton) - - **Raz Luvaton** <> (he/him) * [richardlau](https://github.com/richardlau) - **Richard Lau** <> * [rickyes](https://github.com/rickyes) - **Ricky Zhou** <<0x19951125@gmail.com>> (he/him) +* [rluvaton](https://github.com/rluvaton) - + **Raz Luvaton** <> (he/him) * [ronag](https://github.com/ronag) - **Robert Nagy** <> * [ruyadorno](https://github.com/ruyadorno) - @@ -477,10 +477,10 @@ For information about the governance of the Node.js project, see **Khaidi Chu** <> (he/him) * [yashLadha](https://github.com/yashLadha) - **Yash Ladha** <> (he/him) -* [ZYSzys](https://github.com/ZYSzys) - - **Yongsheng Zhang** <> (he/him) * [zcbenz](https://github.com/zcbenz) - **Cheng Zhao** <> (he/him) +* [ZYSzys](https://github.com/ZYSzys) - + **Yongsheng Zhang** <> (he/him)
@@ -495,10 +495,10 @@ For information about the governance of the Node.js project, see **Aleksei Koziatinskii** <> * [andrasq](https://github.com/andrasq) - **Andras** <> -* [AnnaMag](https://github.com/AnnaMag) - - **Anna M. Kedzierska** <> * [AndreasMadsen](https://github.com/AndreasMadsen) - **Andreas Madsen** <> (he/him) +* [AnnaMag](https://github.com/AnnaMag) - + **Anna M. Kedzierska** <> * [aqrln](https://github.com/aqrln) - **Alexey Orlenko** <> (he/him) * [bcoe](https://github.com/bcoe) - @@ -741,10 +741,10 @@ maintaining the Node.js project. **Mert Can Altin** <> * [Mesteery](https://github.com/Mesteery) - **Mestery** <> (he/him) -* [preveen-stack](https://github.com/preveen-stack) - - **Preveen Padmanabhan** <> (he/him) * [PoojaDurgad](https://github.com/PoojaDurgad) - **Pooja Durgad** <> +* [preveen-stack](https://github.com/preveen-stack) - + **Preveen Padmanabhan** <> (he/him) * [VoltrexKeyva](https://github.com/VoltrexKeyva) - **Mohammed Keyvanzadeh** <> (he/him) diff --git a/tools/lint-readme-lists.mjs b/tools/lint-readme-lists.mjs new file mode 100755 index 00000000000..8859d2097c4 --- /dev/null +++ b/tools/lint-readme-lists.mjs @@ -0,0 +1,48 @@ +#!/usr/bin/env node + +// Validates the list in the README are in the correct order. + +import { open } from 'node:fs/promises'; + +const lists = [ + 'TSC voting members', + 'TSC regular members', + 'TSC emeriti members', + 'Collaborators', + 'Collaborator emeriti', + 'Triagers', +]; +const tscMembers = new Set(); + +const readme = await open(new URL('../README.md', import.meta.url), 'r'); + +let currentList = null; +let previousGithubHandle; +let lineNumber = 0; + +for await (const line of readme.readLines()) { + lineNumber++; + if (line.startsWith('### ')) { + currentList = lists[lists.indexOf(line.slice(4))]; + previousGithubHandle = null; + } else if (line.startsWith('#### ')) { + currentList = lists[lists.indexOf(line.slice(5))]; + previousGithubHandle = null; + } else if (currentList && line.startsWith('* [')) { + const currentGithubHandle = line.slice(3, line.indexOf(']')).toLowerCase(); + if (previousGithubHandle && previousGithubHandle >= currentGithubHandle) { + throw new Error(`${currentGithubHandle} should be listed before ${previousGithubHandle} in the ${currentList} list (README.md:${lineNumber})`); + } + + if (currentList === 'TSC voting members' || currentList === 'TSC regular members') { + tscMembers.add(currentGithubHandle); + } else if (currentList === 'Collaborators') { + tscMembers.delete(currentGithubHandle); + } + previousGithubHandle = currentGithubHandle; + } +} + +if (tscMembers.size !== 0) { + throw new Error(`Some TSC members are not listed as Collaborators: ${Array.from(tscMembers)}`); +}