Skip to content

feat(membership): add inactive member detection#1061

Open
avivkeller wants to merge 2 commits intonodejs:mainfrom
avivkeller:get-inactive-members
Open

feat(membership): add inactive member detection#1061
avivkeller wants to merge 2 commits intonodejs:mainfrom
avivkeller:get-inactive-members

Conversation

@avivkeller
Copy link
Copy Markdown
Member

@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:org token 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 nodejs

An inactive member is defined as any organization member who meets at least one of the following criteria:

  1. Belongs to no teams in the organization
  2. Has had no interaction with any organization repository since 2025-04-29 (12 months)

Summary

  • Total org members: 346
  • Inactive members: 69
  • Active members: 277

Inactive Members

Member Reason(s) Teams
@agnat no repo activity in 12 months addon-api, coreworkinggroups, all-members
@ahmadawais no repo activity in 12 months next-10, all-members
@aixtools no team membership none
@aks- no repo activity in 12 months http, core, all-members
@alexcfyung no repo activity in 12 months platforms, core, platform-zos, all-members
@alexeykuzmin no repo activity in 12 months delivery-channels, embedders, all-members
@alexweej no team membership none
@amiller-gh no repo activity in 12 months commit-queue, all-members
@anandsuresh no repo activity in 12 months platform-freebsd, platforms, core, all-members
@AnnaMag no repo activity in 12 months v8, vm, core, all-members
@ashishkurmi no repo activity in 12 months security-wg, all-members
@bahamat no team membership none
@bajtos no repo activity in 12 months wintercg, all-members
@BethGriggs no repo activity in 12 months collaborators, lts, platform-s390, platform-aix, platform-ppc, platform-macos, backporters, platforms, coreworkinggroups, core, release, package-maintenance, next-10, all-members
@bradleythughes no repo activity in 12 months platform-freebsd, platforms, core, all-members
@charlespierce no team membership none
@davidmarkclements no repo activity in 12 months diagnostics, post-mortem, coreworkinggroups, all-members
@deian no repo activity in 12 months security-wg, all-members
@designMoreWeb no repo activity in 12 months electron-installer, next-10, all-members
@dgonzalez no repo activity in 12 months security-wg, all-members
@ebraminio no repo activity in 12 months v8, core, all-members
@ehsan no repo activity in 12 months spidernode, all-members
@esarafianou no repo activity in 12 months security-wg, all-members
@evocateur no repo activity in 12 months tooling, all-members
@fed135 no repo activity in 12 months web-server-frameworks, all-members
@gareth-ellis no repo activity in 12 months benchmarking, performance, coreworkinggroups, core, all-members
@GnorTech no repo activity in 12 months delivery-channels, embedders, all-members
@gsathya no repo activity in 12 months v8, core, all-members
@HinataKah0 no team membership none
@hmalphettes no team membership none
@IgorTodorovskiIBM no repo activity in 12 months platforms, platform-zos, core, all-members
@imyller no repo activity in 12 months platform-macos, platforms, core, all-members
@jBarz no repo activity in 12 months v8, core, all-members
@JckXia no repo activity in 12 months node-api, all-members
@JiaLiPassion no repo activity in 12 months async_hooks, core, all-members
@jkleinsc no repo activity in 12 months delivery-channels, embedders, all-members
@jlenon7 no repo activity in 12 months loaders, all-members
@JoeDoyle23 no repo activity in 12 months electron-installer, all-members
@JungMinu no repo activity in 12 months collaborators, all-members
@karenyavine no repo activity in 12 months security-wg, all-members
@kjin no repo activity in 12 months diagnostics, coreworkinggroups, core, perfetto, all-members
@kunalspathak no repo activity in 12 months benchmarking, coreworkinggroups, all-members
@lance no repo activity in 12 months platform-macos, platforms, core, all-members
@larson-carter no team membership none
@lucamaraschi no repo activity in 12 months diagnostics, post-mortem, coreworkinggroups, all-members
@MarcinHoppe no repo activity in 12 months security-wg, all-members
@mattpocock no team membership none
@MayaLekova no repo activity in 12 months v8, core, all-members
@mgalexander no repo activity in 12 months security-wg, all-members
@MoonBall no repo activity in 12 months streams, http-parser, http, coreworkinggroups, core, all-members
@natorion no repo activity in 12 months v8, core, all-members
@nitsakh no repo activity in 12 months delivery-channels, embedders, all-members
@niyas-sait no repo activity in 12 months platforms, platform-windows-arm, platform-windows-arm-testing, core, all-members
@node-forward-build no repo activity in 12 months build, jenkins-release-admins, coreworkinggroups, jenkins-admins, all-members
@nodejs-crowdin no repo activity in 12 months bots
@nullivex no repo activity in 12 months version-management, delivery-channels, all-members
@o- no repo activity in 12 months v8, core, all-members
@obensource no repo activity in 12 months i18n-api, i18n, all-members
@pxlpnk no repo activity in 12 months security-wg, all-members
@rexagod no repo activity in 12 months streams, http, testing, coreworkinggroups, core, all-members
@rogerwang no repo activity in 12 months delivery-channels, embedders, all-members
@ronperris no repo activity in 12 months security-wg, all-members
@rubys no repo activity in 12 months documentation, core, repl, all-members
@shanpriyan no team membership none
@SomeoneWeird no repo activity in 12 months security-wg, all-members
@uttampawar no repo activity in 12 months benchmarking, coreworkinggroups, all-members
@vvalderrv no repo activity in 12 months linuxit-infra-temp, all-members
@yhwang no repo activity in 12 months testing, all-members
@yunong no repo activity in 12 months diagnostics, post-mortem, coreworkinggroups, all-members

This report was generated automatically.

Copilot AI review requested due to automatic review settings April 24, 2026 19:07
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread request-an-access-token.md
[`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
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 []).

Suggested change
[`nodejs/admin`][]: https://github.com/nodejs/admin
[`nodejs/admin`]: https://github.com/nodejs/admin

Copilot uses AI. Check for mistakes.
Comment on lines +11 to +13
jobs:
cull-inactive-members:
runs-on: ubuntu-latest
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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).

Copilot uses AI. Check for mistakes.
Comment thread tools/get-inactive-members.mjs
Comment thread tools/get-inactive-members.mjs
Comment on lines +448 to +454
`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,
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment thread tools/get-inactive-members.mjs
@@ -0,0 +1,24 @@
name: Linters
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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).

Suggested change
name: Linters
name: Inactive member report

Copilot uses AI. Check for mistakes.
Comment thread .github/workflows/get-inactive-members.yml
Comment on lines +397 to +401
per_page: 1,
}),
);

const existing = searchResult.data.items.find(
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
@JakobJingleheimer
Copy link
Copy Markdown
Member

Thanks Aviv! I was gonna write out the details tomorrow with a couple options.

Are you familiar with the consensus reached?

@avivkeller
Copy link
Copy Markdown
Member Author

Are you familiar with the consensus reached?

I am not, I've been away, can you summarize?

@JakobJingleheimer
Copy link
Copy Markdown
Member

Yeah, I shall do tomorrow 🙂

@JakobJingleheimer
Copy link
Copy Markdown
Member

I think the "no activity" criteria should be adjusted:

  • 3 months instead of 12
    • 6 months to remove, but the 3 months so there's a "warning"
  • exclude collaborators (that's a different check), soon to be called "maintainers".

The rest is a wishlist. What is here now is a good v1.0.0.

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 (nodejs/node and the relevant team's repo); for Core activity, the check should be narrowed to issues & PRs labeled with that subsystem's label (activity for team A doesn't count for team B).

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 nodejs/test-runner/tree/main/minutes).

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 3.5 months).

I think it would be good to open:

  • a "parent" issue on nodejs/admin with the full report
    • TSC would remove fully inactive members from the org
    • probably tag @nodejs/tsc? (up to them—that could maybe get annoying?)
  • a team issue on each team's repo when it has inactive members
    • teams are tasked with managing their members (so the issue alerts them to cull their inactive member(s))
    • probably tag the team's maintainer sub-team (eg @nodejs/core/test-runner/maintainers); all maintainer sub-teams will have the same suffix (eg …/maintainers)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants