diff --git a/.github/workflows/find-inactive-tsc.yml b/.github/workflows/find-inactive-tsc.yml index 978da55dc5c389..76190f1deb6943 100644 --- a/.github/workflows/find-inactive-tsc.yml +++ b/.github/workflows/find-inactive-tsc.yml @@ -32,7 +32,7 @@ jobs: node-version: ${{ env.NODE_VERSION }} - name: Find inactive TSC members - run: tools/find-inactive-tsc.mjs + run: tools/find-inactive-tsc.mjs >> $GITHUB_ENV - name: Open pull request uses: gr2m/create-or-update-pull-request-action@v1 @@ -41,7 +41,12 @@ jobs: with: author: Node.js GitHub Bot branch: actions/inactive-tsc - body: This PR was generated by tools/find-inactive-tsc.yml. + body: | + This PR was generated by tools/find-inactive-tsc.yml. + + @nodejs/tsc ${{ env.INACTIVE_TSC_HANDLES }} + + ${{ env.DETAILS_FOR_COMMIT_BODY }} commit-message: "meta: move one or more TSC members to emeritus" labels: meta title: "meta: move one or more TSC members to emeritus" diff --git a/tools/find-inactive-tsc.mjs b/tools/find-inactive-tsc.mjs index c141e9026bb306..98400d77855227 100755 --- a/tools/find-inactive-tsc.mjs +++ b/tools/find-inactive-tsc.mjs @@ -96,6 +96,8 @@ async function getAttendance(tscMembers, meetings) { if (match) { return match[1]; } + // Using `console.warn` so that stdout output is not generated. + // The stdout output is consumed in find-inactive-tsc.yml. console.warn(`Attendee entry does not contain GitHub handle: ${line}`); return ''; }) @@ -111,10 +113,6 @@ async function getVotingRecords(tscMembers, votes) { votingRecords[member] = 0; } for (const vote of votes) { - // Skip if not a .json file, such as README.md. - if (!vote.endsWith('.json')) { - continue; - } // Get the vote data. const voteData = JSON.parse( await fs.promises.readFile(path.join('.tmp', vote), 'utf8') @@ -238,7 +236,7 @@ const lightAttendance = tscMembers.filter( // Get all votes since SINCE. // Assumes that the TSC repo is cloned in the .tmp dir. const votes = await runGitCommand( - `git whatchanged --since '${SINCE}' --name-only --pretty=format: votes`, + `git whatchanged --since '${SINCE}' --name-only --pretty=format: votes/*.json`, { cwd: '.tmp', mapFn: (line) => line } ); @@ -251,10 +249,21 @@ const noVotes = tscMembers.filter( const inactive = lightAttendance.filter((member) => noVotes.includes(member)); if (inactive.length) { - console.log('\nInactive TSC members:\n'); - console.log(inactive.map((entry) => `* ${entry}`).join('\n')); - console.log('\nGenerating new README.md file...'); + // The stdout output is consumed in find-inactive-tsc.yml. If format of output + // changes, find-inactive-tsc.yml may need to be updated. + console.log(`INACTIVE_TSC_HANDLES="${inactive.map((entry) => '@' + entry).join(' ')}"`); + const commitDetails = inactive.map((entry) => { + let details = `Since ${SINCE}, `; + details += `${entry} attended ${attendance[entry]} out of ${meetings.size} meetings`; + details += ` and voted in ${votingRecords[entry]} of ${votes.size} votes.`; + return details; + }); + console.log(`DETAILS_FOR_COMMIT_BODY="${commitDetails.join(' ')}"`); + + // Using console.warn() to avoid messing with find-inactive-tsc which consumes + // stdout. + console.warn('Generating new README.md file...'); const newReadmeText = await moveTscToEmeritus(inactive); fs.writeFileSync(new URL('../README.md', import.meta.url), newReadmeText); - console.log('Updated README.md generated. Please commit these changes.'); + console.warn('Updated README.md generated. Please commit these changes.'); }