feat(membership): add inactive member detection#1061
feat(membership): add inactive member detection#1061avivkeller wants to merge 2 commits intonodejs:mainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
Adds an automated “inactive member” monitor for the org by running a scheduled GitHub Actions workflow that scans org membership/team data and posts (or updates) a report issue in this repository.
Changes:
- Added a new Node.js script to fetch org members/teams, check recent activity, and render a Markdown report.
- Added a daily scheduled GitHub Actions workflow to run the script using a user token.
- Updated the access-token registry documentation to include the new secret entry.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 10 comments.
| File | Description |
|---|---|
tools/get-inactive-members.mjs |
Implements org member/team fetch, activity classification, report rendering, and issue upsert logic. |
.github/workflows/get-inactive-members.yml |
Schedules and runs the new script via actions/github-script using GH_USER_TOKEN. |
request-an-access-token.md |
Documents the new GH_USER_TOKEN usage/registry entry for nodejs/admin. |
Comments suppressed due to low confidence (1)
tools/get-inactive-members.mjs:513
- The report issue is only created/updated when
inactive.length > 0. This means (1) the rendered “No inactive members found” state is never posted, and (2) an existing report issue won’t be updated if the org becomes fully active—leaving stale results in the issue body. Upsert the issue unconditionally so the report always reflects the latest scan.
core.info(`Report available at: ${html_url}`);
}
}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| [`nodejs/require-in-the-middle`]: https://github.com/nodejs/require-in-the-middle | ||
| [`nodejs/wasm-builder`]: https://github.com/nodejs/wasm-builder | ||
| [`nodejs/doc-kit`]: https://github.com/nodejs/doc-kit | ||
| [`nodejs/admin`][]: https://github.com/nodejs/admin No newline at end of file |
There was a problem hiding this comment.
The reference-style link definition is malformed: [nodejs/admin][]: ... won’t define the [nodejs/admin][] reference used in the table. It should match the existing pattern used for other entries (definition without the trailing []).
| [`nodejs/admin`][]: https://github.com/nodejs/admin | |
| [`nodejs/admin`]: https://github.com/nodejs/admin |
| jobs: | ||
| cull-inactive-members: | ||
| runs-on: ubuntu-latest |
There was a problem hiding this comment.
This workflow updates/creates issues via the REST API, but the job name ("cull-inactive-members") and the workflow name imply unrelated behavior. Consider renaming the job to reflect that it generates/updates a report (to avoid confusion when scanning Actions logs/history).
| `Starting inactive-members scan for org "${org}" (cutoff: ${cutoffISO}, rate limit: ${RATE_LIMIT_PER_MINUTE}/min).`, | ||
| ); | ||
|
|
||
| const startedAt = Date.now(); | ||
|
|
||
| const { members, memberTeams } = await fetchMembersAndTeams( | ||
| github, |
There was a problem hiding this comment.
The JSDoc says this function returns Promise<string>, but it currently doesn’t return anything. Either return a meaningful value (e.g., the rendered report body or issue URL) or update the JSDoc to Promise<void> to match behavior.
| @@ -0,0 +1,24 @@ | |||
| name: Linters | |||
There was a problem hiding this comment.
Workflow name is set to "Linters", which duplicates the existing linters workflow name and makes scheduled runs hard to distinguish in the Actions UI. Rename this workflow to something specific to its purpose (e.g., inactive member report).
| name: Linters | |
| name: Inactive member report |
| per_page: 1, | ||
| }), | ||
| ); | ||
|
|
||
| const existing = searchResult.data.items.find( |
There was a problem hiding this comment.
issues and page are declared but never used, and the comment about wrapping Octokit pagination doesn’t match the current implementation (which does a single search request). Remove the unused variables and update the comment to reflect the actual approach, or implement pagination if that was intended.
|
Thanks Aviv! I was gonna write out the details tomorrow with a couple options. Are you familiar with the consensus reached? |
I am not, I've been away, can you summarize? |
|
Yeah, I shall do tomorrow 🙂 |
|
I think the "no activity" criteria should be adjusted:
The rest is a wishlist. What is here now is a good With the new team-based setup for Core, that will need some special handling because there are 1–2 repos that need to be checked ( It would ideally also check meeting minutes for attendees; facilitating that check may require meeting minutes to adhere to a partially prescribed/standard format, and them to be stored in a standard place (eg For the report, it would ideally break down to which team(s) the member is inactive, as well as call out when the member is completely inactive across the whole org. The reports would ideally also specify how long each member has been inactive (in a human-friendly way, like I think it would be good to open:
|
@JakobJingleheimer mentioned that during the collaborator's summit, it was discussed that we should be more wary of the size of the organization. This adds a daily workflow to keep a constant "activity monitor" issue open.
It requires that a
public_repo,read:orgtoken be made for this repository.An example issue that this workflow generates is below (Note: In a real issue, these users would be pinged):
Workflow Output
Inactive Members Report
Generated on 2026-04-24 for organization
nodejsAn inactive member is defined as any organization member who meets at least one of the following criteria:
Summary
Inactive Members
@agnataddon-api,coreworkinggroups,all-members@ahmadawaisnext-10,all-members@aixtools@aks-http,core,all-members@alexcfyungplatforms,core,platform-zos,all-members@alexeykuzmindelivery-channels,embedders,all-members@alexweej@amiller-ghcommit-queue,all-members@anandsureshplatform-freebsd,platforms,core,all-members@AnnaMagv8,vm,core,all-members@ashishkurmisecurity-wg,all-members@bahamat@bajtoswintercg,all-members@BethGriggscollaborators,lts,platform-s390,platform-aix,platform-ppc,platform-macos,backporters,platforms,coreworkinggroups,core,release,package-maintenance,next-10,all-members@bradleythughesplatform-freebsd,platforms,core,all-members@charlespierce@davidmarkclementsdiagnostics,post-mortem,coreworkinggroups,all-members@deiansecurity-wg,all-members@designMoreWebelectron-installer,next-10,all-members@dgonzalezsecurity-wg,all-members@ebraminiov8,core,all-members@ehsanspidernode,all-members@esarafianousecurity-wg,all-members@evocateurtooling,all-members@fed135web-server-frameworks,all-members@gareth-ellisbenchmarking,performance,coreworkinggroups,core,all-members@GnorTechdelivery-channels,embedders,all-members@gsathyav8,core,all-members@HinataKah0@hmalphettes@IgorTodorovskiIBMplatforms,platform-zos,core,all-members@imyllerplatform-macos,platforms,core,all-members@jBarzv8,core,all-members@JckXianode-api,all-members@JiaLiPassionasync_hooks,core,all-members@jkleinscdelivery-channels,embedders,all-members@jlenon7loaders,all-members@JoeDoyle23electron-installer,all-members@JungMinucollaborators,all-members@karenyavinesecurity-wg,all-members@kjindiagnostics,coreworkinggroups,core,perfetto,all-members@kunalspathakbenchmarking,coreworkinggroups,all-members@lanceplatform-macos,platforms,core,all-members@larson-carter@lucamaraschidiagnostics,post-mortem,coreworkinggroups,all-members@MarcinHoppesecurity-wg,all-members@mattpocock@MayaLekovav8,core,all-members@mgalexandersecurity-wg,all-members@MoonBallstreams,http-parser,http,coreworkinggroups,core,all-members@natorionv8,core,all-members@nitsakhdelivery-channels,embedders,all-members@niyas-saitplatforms,platform-windows-arm,platform-windows-arm-testing,core,all-members@node-forward-buildbuild,jenkins-release-admins,coreworkinggroups,jenkins-admins,all-members@nodejs-crowdinbots@nullivexversion-management,delivery-channels,all-members@o-v8,core,all-members@obensourcei18n-api,i18n,all-members@pxlpnksecurity-wg,all-members@rexagodstreams,http,testing,coreworkinggroups,core,all-members@rogerwangdelivery-channels,embedders,all-members@ronperrissecurity-wg,all-members@rubysdocumentation,core,repl,all-members@shanpriyan@SomeoneWeirdsecurity-wg,all-members@uttampawarbenchmarking,coreworkinggroups,all-members@vvalderrvlinuxit-infra-temp,all-members@yhwangtesting,all-members@yunongdiagnostics,post-mortem,coreworkinggroups,all-membersThis report was generated automatically.