Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 7d971da

Browse filesBrowse files
Trottdanielleadams
authored andcommitted
tools,meta: update README and tools to reflect changes in TSC charter
Ref: nodejs/TSC#1350 PR-URL: #47126 Refs: nodejs/TSC#1350 Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: Darshan Sen <raisinten@gmail.com>
1 parent 0edcfed commit 7d971da
Copy full SHA for 7d971da

File tree

Expand file treeCollapse file tree

3 files changed

+79
-120
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

3 files changed

+79
-120
lines changed
Open diff view settings
Collapse file

‎.github/workflows/find-inactive-tsc.yml‎

Copy file name to clipboardExpand all lines: .github/workflows/find-inactive-tsc.yml
+4-4Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Find inactive TSC members
1+
name: Find inactive TSC voting members
22

33
on:
44
schedule:
@@ -38,7 +38,7 @@ jobs:
3838
with:
3939
node-version: ${{ env.NODE_VERSION }}
4040

41-
- name: Find inactive TSC members
41+
- name: Find inactive TSC voting members
4242
run: tools/find-inactive-tsc.mjs >> $GITHUB_ENV
4343

4444
- name: Open pull request
@@ -56,6 +56,6 @@ jobs:
5656
@nodejs/tsc ${{ env.INACTIVE_TSC_HANDLES }}
5757
5858
${{ env.DETAILS_FOR_COMMIT_BODY }}
59-
commit-message: 'meta: move one or more TSC members to emeritus'
59+
commit-message: 'meta: move TSC voting member(s) to regular member(s)'
6060
labels: meta
61-
title: 'meta: move one or more TSC members to emeritus'
61+
title: 'meta: move TSC voting member(s) to regular member(s)'
Collapse file

‎README.md‎

Copy file name to clipboardExpand all lines: README.md
+22-17Lines changed: 22 additions & 17 deletions
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,8 @@ For information about the governance of the Node.js project, see
158158

159159
### TSC (Technical Steering Committee)
160160

161+
#### TSC voting members
162+
161163
<!--lint disable prohibited-strings-->
162164

163165
* [aduh95](https://github.com/aduh95) -
@@ -205,28 +207,39 @@ For information about the governance of the Node.js project, see
205207
* [Trott](https://github.com/Trott) -
206208
**Rich Trott** <<rtrott@gmail.com>> (he/him)
207209

208-
<details>
209-
210-
<summary>Emeriti</summary>
211-
212-
### TSC emeriti
210+
#### TSC regular members
213211

214212
* [addaleax](https://github.com/addaleax) -
215213
**Anna Henningsen** <<anna@addaleax.net>> (she/her)
216214
* [bnoordhuis](https://github.com/bnoordhuis) -
217215
**Ben Noordhuis** <<info@bnoordhuis.nl>>
218-
* [chrisdickinson](https://github.com/chrisdickinson) -
219-
**Chris Dickinson** <<christopher.s.dickinson@gmail.com>>
220216
* [codebytere](https://github.com/codebytere) -
221217
**Shelley Vohr** <<shelley.vohr@gmail.com>> (she/her)
222218
* [danbev](https://github.com/danbev) -
223219
**Daniel Bevenius** <<daniel.bevenius@gmail.com>> (he/him)
220+
* [gabrielschulhof](https://github.com/gabrielschulhof) -
221+
**Gabriel Schulhof** <<gabrielschulhof@gmail.com>>
222+
* [mscdex](https://github.com/mscdex) -
223+
**Brian White** <<mscdex@mscdex.net>>
224+
* [MylesBorins](https://github.com/MylesBorins) -
225+
**Myles Borins** <<myles.borins@gmail.com>> (he/him)
226+
* [rvagg](https://github.com/rvagg) -
227+
**Rod Vagg** <<r@va.gg>>
228+
* [TimothyGu](https://github.com/TimothyGu) -
229+
**Tiancheng "Timothy" Gu** <<timothygu99@gmail.com>> (he/him)
230+
231+
<details>
232+
233+
<summary>TSC emeriti members</summary>
234+
235+
#### TSC emeriti members
236+
237+
* [chrisdickinson](https://github.com/chrisdickinson) -
238+
**Chris Dickinson** <<christopher.s.dickinson@gmail.com>>
224239
* [evanlucas](https://github.com/evanlucas) -
225240
**Evan Lucas** <<evanlucas@me.com>> (he/him)
226241
* [Fishrock123](https://github.com/Fishrock123) -
227242
**Jeremiah Senkpiel** <<fishrock123@rocketmail.com>> (he/they)
228-
* [gabrielschulhof](https://github.com/gabrielschulhof) -
229-
**Gabriel Schulhof** <<gabrielschulhof@gmail.com>>
230243
* [gibfahn](https://github.com/gibfahn) -
231244
**Gibson Fahnestock** <<gibfahn@gmail.com>> (he/him)
232245
* [indutny](https://github.com/indutny) -
@@ -237,10 +250,6 @@ For information about the governance of the Node.js project, see
237250
**Josh Gavant** <<josh.gavant@outlook.com>>
238251
* [mmarchini](https://github.com/mmarchini) -
239252
**Mary Marchini** <<oss@mmarchini.me>> (she/her)
240-
* [mscdex](https://github.com/mscdex) -
241-
**Brian White** <<mscdex@mscdex.net>>
242-
* [MylesBorins](https://github.com/MylesBorins) -
243-
**Myles Borins** <<myles.borins@gmail.com>> (he/him)
244253
* [nebrius](https://github.com/nebrius) -
245254
**Bryan Hughes** <<bryan@nebri.us>>
246255
* [ofrobots](https://github.com/ofrobots) -
@@ -249,16 +258,12 @@ For information about the governance of the Node.js project, see
249258
**Alexis Campailla** <<orangemocha@nodejs.org>>
250259
* [piscisaureus](https://github.com/piscisaureus) -
251260
**Bert Belder** <<bertbelder@gmail.com>>
252-
* [rvagg](https://github.com/rvagg) -
253-
**Rod Vagg** <<r@va.gg>>
254261
* [sam-github](https://github.com/sam-github) -
255262
**Sam Roberts** <<vieuxtech@gmail.com>>
256263
* [shigeki](https://github.com/shigeki) -
257264
**Shigeki Ohtsu** <<ohtsu@ohtsu.org>> (he/him)
258265
* [thefourtheye](https://github.com/thefourtheye) -
259266
**Sakthipriyan Vairamani** <<thechargingvolcano@gmail.com>> (he/him)
260-
* [TimothyGu](https://github.com/TimothyGu) -
261-
**Tiancheng "Timothy" Gu** <<timothygu99@gmail.com>> (he/him)
262267
* [trevnorris](https://github.com/trevnorris) -
263268
**Trevor Norris** <<trev.norris@gmail.com>>
264269

Collapse file

‎tools/find-inactive-tsc.mjs‎

Copy file name to clipboard
+53-99Lines changed: 53 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
#!/usr/bin/env node
22

3-
// Identify inactive TSC members.
3+
// Identify inactive TSC voting members.
44

55
// From the TSC Charter:
6-
// A TSC member is automatically removed from the TSC if, during a 3-month
7-
// period, all of the following are true:
8-
// * They attend fewer than 25% of the regularly scheduled meetings.
9-
// * They do not participate in any TSC votes.
6+
// A TSC voting member is automatically converted to a TSC regular member if
7+
// they do not participate in three consecutive TSC votes.
108

119
import cp from 'node:child_process';
1210
import fs from 'node:fs';
@@ -20,9 +18,8 @@ const args = parseArgs({
2018
});
2119

2220
const verbose = args.values.verbose;
23-
const SINCE = args.positionals[0] || '3 months ago';
2421

25-
async function runGitCommand(cmd, options = {}) {
22+
async function runShellCommand(cmd, options = {}) {
2623
const childProcess = cp.spawn('/bin/sh', ['-c', cmd], {
2724
cwd: options.cwd ?? new URL('..', import.meta.url),
2825
encoding: 'utf8',
@@ -34,17 +31,14 @@ async function runGitCommand(cmd, options = {}) {
3431
const errorHandler = new Promise(
3532
(_, reject) => childProcess.on('error', reject),
3633
);
37-
let returnValue = options.mapFn ? new Set() : '';
34+
let returnValue = options.returnAsArray ? [] : '';
3835
await Promise.race([errorHandler, Promise.resolve()]);
3936
// If no mapFn, return the value. If there is a mapFn, use it to make a Set to
4037
// return.
4138
for await (const line of lines) {
4239
await Promise.race([errorHandler, Promise.resolve()]);
43-
if (options.mapFn) {
44-
const val = options.mapFn(line);
45-
if (val) {
46-
returnValue.add(val);
47-
}
40+
if (options.returnAsArray) {
41+
returnValue.push(line);
4842
} else {
4943
returnValue += line;
5044
}
@@ -60,6 +54,13 @@ async function getTscFromReadme() {
6054
const returnedArray = [];
6155
let foundTscHeading = false;
6256
for await (const line of readmeText) {
57+
// Until three votes have passed from March 16, 2023, we will need this.
58+
// After that point, we can use this for setting `foundTscHeading` below
59+
// and remove this.
60+
if (line === '#### TSC voting members') {
61+
continue;
62+
}
63+
6364
// If we've found the TSC heading already, stop processing at the next
6465
// heading.
6566
if (foundTscHeading && line.startsWith('#')) {
@@ -84,36 +85,6 @@ async function getTscFromReadme() {
8485
return returnedArray;
8586
}
8687

87-
async function getAttendance(tscMembers, meetings) {
88-
const attendance = {};
89-
for (const member of tscMembers) {
90-
attendance[member] = 0;
91-
}
92-
for (const meeting of meetings) {
93-
// Get the file contents.
94-
const meetingFile =
95-
await fs.promises.readFile(path.join('.tmp', meeting), 'utf8');
96-
// Extract the attendee list.
97-
const startMarker = '## Present';
98-
const start = meetingFile.indexOf(startMarker) + startMarker.length;
99-
const end = meetingFile.indexOf('## Agenda');
100-
meetingFile.substring(start, end).trim().split('\n')
101-
.map((line) => {
102-
const match = line.match(/@(\S+)/);
103-
if (match) {
104-
return match[1];
105-
}
106-
// Using `console.warn` so that stdout output is not generated.
107-
// The stdout output is consumed in find-inactive-tsc.yml.
108-
console.warn(`Attendee entry does not contain GitHub handle: ${line}`);
109-
return '';
110-
})
111-
.filter((handle) => tscMembers.includes(handle))
112-
.forEach((handle) => { attendance[handle]++; });
113-
}
114-
return attendance;
115-
}
116-
11788
async function getVotingRecords(tscMembers, votes) {
11889
const votingRecords = {};
11990
for (const member of tscMembers) {
@@ -122,7 +93,7 @@ async function getVotingRecords(tscMembers, votes) {
12293
for (const vote of votes) {
12394
// Get the vote data.
12495
const voteData = JSON.parse(
125-
await fs.promises.readFile(path.join('.tmp', vote), 'utf8'),
96+
await fs.promises.readFile(path.join('.tmp/votes', vote), 'utf8'),
12697
);
12798
for (const member in voteData.votes) {
12899
if (tscMembers.includes(member)) {
@@ -133,22 +104,22 @@ async function getVotingRecords(tscMembers, votes) {
133104
return votingRecords;
134105
}
135106

136-
async function moveTscToEmeritus(peopleToMove) {
107+
async function moveVotingToRegular(peopleToMove) {
137108
const readmeText = readline.createInterface({
138109
input: fs.createReadStream(new URL('../README.md', import.meta.url)),
139110
crlfDelay: Infinity,
140111
});
141112
let fileContents = '';
142-
let inTscSection = false;
143-
let inTscEmeritusSection = false;
113+
let inTscVotingSection = false;
114+
let inTscRegularSection = false;
144115
let memberFirstLine = '';
145116
const textToMove = [];
146117
let moveToInactive = false;
147118
for await (const line of readmeText) {
148-
// If we've been processing TSC emeriti and we reach the end of
119+
// If we've been processing TSC regular members and we reach the end of
149120
// the list, print out the remaining entries to be moved because they come
150121
// alphabetically after the last item.
151-
if (inTscEmeritusSection && line === '' &&
122+
if (inTscRegularSection && line === '' &&
152123
fileContents.endsWith('>\n')) {
153124
while (textToMove.length) {
154125
fileContents += textToMove.pop();
@@ -158,21 +129,21 @@ async function moveTscToEmeritus(peopleToMove) {
158129
// If we've found the TSC heading already, stop processing at the
159130
// next heading.
160131
if (line.startsWith('#')) {
161-
inTscSection = false;
162-
inTscEmeritusSection = false;
132+
inTscVotingSection = false;
133+
inTscRegularSection = false;
163134
}
164135

165-
const isTsc = inTscSection && line.length;
166-
const isTscEmeritus = inTscEmeritusSection && line.length;
136+
const isTscVoting = inTscVotingSection && line.length;
137+
const isTscRegular = inTscRegularSection && line.length;
167138

168-
if (line === '### TSC (Technical Steering Committee)') {
169-
inTscSection = true;
139+
if (line === '#### TSC voting members') {
140+
inTscVotingSection = true;
170141
}
171-
if (line === '### TSC emeriti') {
172-
inTscEmeritusSection = true;
142+
if (line === '#### TSC regular members') {
143+
inTscRegularSection = true;
173144
}
174145

175-
if (isTsc) {
146+
if (isTscVoting) {
176147
if (line.startsWith('* ')) {
177148
memberFirstLine = line;
178149
const match = line.match(/^\* \[([^\]]+)/);
@@ -191,7 +162,7 @@ async function moveTscToEmeritus(peopleToMove) {
191162
}
192163
}
193164

194-
if (isTscEmeritus) {
165+
if (isTscRegular) {
195166
if (line.startsWith('* ')) {
196167
memberFirstLine = line;
197168
} else if (line.startsWith(' **')) {
@@ -207,79 +178,62 @@ async function moveTscToEmeritus(peopleToMove) {
207178
}
208179
}
209180

210-
if (!isTsc && !isTscEmeritus) {
181+
if (!isTscVoting && !isTscRegular) {
211182
fileContents += `${line}\n`;
212183
}
213184
}
214185

215186
return fileContents;
216187
}
217188

218-
// Get current TSC members, then get TSC members at start of period. Only check
219-
// TSC members who are on both lists. This way, we don't flag someone who has
220-
// only been on the TSC for a week and therefore hasn't attended any meetings.
189+
// Get current TSC voting members, then get TSC voting members at start of
190+
// period. Only check TSC voting members who are on both lists. This way, we
191+
// don't flag someone who hasn't been on the TSC long enough to have missed 3
192+
// consecutive votes.
221193
const tscMembersAtEnd = await getTscFromReadme();
222194

223-
const startCommit = await runGitCommand(`git rev-list -1 --before '${SINCE}' HEAD`);
224-
await runGitCommand(`git checkout ${startCommit} -- README.md`);
225-
const tscMembersAtStart = await getTscFromReadme();
226-
await runGitCommand('git reset HEAD README.md');
227-
await runGitCommand('git checkout -- README.md');
228-
229-
const tscMembers = tscMembersAtEnd.filter(
230-
(memberAtEnd) => tscMembersAtStart.includes(memberAtEnd),
231-
);
232-
233-
// Get all meetings since SINCE.
195+
// Get the last three votes.
234196
// Assumes that the TSC repo is cloned in the .tmp dir.
235-
const meetings = await runGitCommand(
236-
`git whatchanged --since '${SINCE}' --name-only --pretty=format: meetings`,
237-
{ cwd: '.tmp', mapFn: (line) => line },
197+
const votes = await runShellCommand(
198+
'ls *.json | sort -rn | head -3',
199+
{ cwd: '.tmp/votes', returnAsArray: true },
238200
);
239201

240-
// Get TSC meeting attendance.
241-
const attendance = await getAttendance(tscMembers, meetings);
242-
const lightAttendance = tscMembers.filter(
243-
(member) => attendance[member] < meetings.size * 0.25,
244-
);
202+
// Reverse the votes list so the oldest of the three votes is first.
203+
votes.reverse();
245204

246-
// Get all votes since SINCE.
247-
// Assumes that the TSC repo is cloned in the .tmp dir.
248-
const votes = await runGitCommand(
249-
`git whatchanged --since '${SINCE}' --name-only --pretty=format: votes/*.json`,
250-
{ cwd: '.tmp', mapFn: (line) => line },
205+
const startCommit = await runShellCommand(`git rev-list -1 --before '${votes[0]}' HEAD`);
206+
await runShellCommand(`git checkout ${startCommit} -- README.md`);
207+
const tscMembersAtStart = await getTscFromReadme();
208+
await runShellCommand('git reset HEAD README.md');
209+
await runShellCommand('git checkout -- README.md');
210+
211+
const tscMembers = tscMembersAtEnd.filter(
212+
(memberAtEnd) => tscMembersAtStart.includes(memberAtEnd),
251213
);
252214

253215
// Check voting record.
254216
const votingRecords = await getVotingRecords(tscMembers, votes);
255-
const noVotes = tscMembers.filter(
217+
const inactive = tscMembers.filter(
256218
(member) => votingRecords[member] === 0,
257219
);
258220

259-
const inactive = lightAttendance.filter((member) => noVotes.includes(member));
260-
261221
if (inactive.length) {
262222
// The stdout output is consumed in find-inactive-tsc.yml. If format of output
263223
// changes, find-inactive-tsc.yml may need to be updated.
264224
console.log(`INACTIVE_TSC_HANDLES=${inactive.map((entry) => '@' + entry).join(' ')}`);
265-
const commitDetails = inactive.map((entry) => {
266-
let details = `Since ${SINCE}, `;
267-
details += `${entry} attended ${attendance[entry]} out of ${meetings.size} meetings`;
268-
details += ` and voted in ${votingRecords[entry]} of ${votes.size} votes.`;
269-
return details;
270-
});
271-
console.log(`DETAILS_FOR_COMMIT_BODY=${commitDetails.join(' ')}`);
225+
const commitDetails = `${inactive.join(' ')} did not participate in three consecutive TSC votes: ${votes.join(' ')}`;
226+
console.log(`DETAILS_FOR_COMMIT_BODY=${commitDetails}`);
272227

273228
if (process.env.GITHUB_ACTIONS) {
274229
// Using console.warn() to avoid messing with find-inactive-tsc which
275230
// consumes stdout.
276231
console.warn('Generating new README.md file...');
277-
const newReadmeText = await moveTscToEmeritus(inactive);
232+
const newReadmeText = await moveVotingToRegular(inactive);
278233
fs.writeFileSync(new URL('../README.md', import.meta.url), newReadmeText);
279234
}
280235
}
281236

282237
if (verbose) {
283-
console.log(attendance);
284238
console.log(votingRecords);
285239
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.