Skip to content

feat&perf(base): minor QoL improvements#22

Open
ferferga wants to merge 5 commits intogh-metrics:masterfrom
ferferga:better-base
Open

feat&perf(base): minor QoL improvements#22
ferferga wants to merge 5 commits intogh-metrics:masterfrom
ferferga:better-base

Conversation

@ferferga
Copy link

@ferferga ferferga commented Jan 30, 2026

This pull request introduces a new configuration option to control whether a user's own repositories are included in the "Contributed to X repositories" count, and refactors how contribution and repository data are queried and aggregated. The changes improve flexibility and accuracy in reporting user contributions, especially for in-depth statistics.

New Feature: Repository Ownership Option

  • Added a new input parameter repositories_owned to both action.yml and metadata.yml, allowing users to specify whether their own repositories should be included in the contributed repositories count. [1] [2]

Refactoring and Improvements to Data Queries

  • Refactored the contributions aggregation logic to fetch all relevant fields at once, instead of doing it per field and per date.
    • This change alone reduced the time my workflows takes from 16 min to 10 min.
  • Aggregate the total repository and storage count in a single GraphQL query

Merged flags in the same query

Signed-off-by: GitHub <[email protected]>
…ion in indepth mode

- By default, GitHub repositoriesContributedTo just shows data from last year. When indepth is enabled, we fetch data since the beginning of the times. See https://github.com/orgs/community/discussions/24350 for full info

Signed-off-by: GitHub <[email protected]>
- Reduces 2 queries in 1

Signed-off-by: GitHub <[email protected]>
Copy link

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

This PR adds a configuration option to control whether a user's own repositories are counted in “Contributed to X repositories” and refactors the base plugin’s contribution/repository queries to fetch more data per request for better performance.

Changes:

  • Introduces a repositories_owned input (action and plugin metadata) wired through to the base plugin as repositories.owned to toggle inclusion of the user’s own repositories in contributed-repositories statistics.
  • Updates field.repositories.graphql and contributions.graphql to fetch repository counts/disk usage and all contribution totals (plus optional indepth fields) in a single query.
  • Refactors source/plugins/base/index.mjs to (a) use the new ownership flag in both unit queries and indepth aggregation, and (b) aggregate repositories and contributions over the account lifetime using fewer GraphQL calls.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
source/plugins/base/queries/field.repositories.graphql Simplifies the repositories field query to return totalCount and totalDiskUsage in one call, used by the base plugin’s fallback path.
source/plugins/base/queries/contributions.graphql Expands the contributions query to fetch all total contribution counts and optional indepth-by-repository fields in a single contributionsCollection query.
source/plugins/base/metadata.yml Adds the repositories_owned plugin input (default yes) to control whether own repositories are included in the contributed-repositories count.
source/plugins/base/index.mjs Wires repositories.owned through to GraphQL calls, uses it to filter contributed repositories, refactors repository stats and contributions fetching, and introduces indepth lifetime aggregation logic (with some issues noted in comments).
action.yml Exposes the new repositories_owned input at the GitHub Action level so users can configure the ownership behavior in workflows.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

}
catch {
console.debug(`metrics/compute/${login}/base > failed to retrieve contributionsCollection`)
data.user.contributionsCollection[field] = NaN
Copy link

Copilot AI Jan 30, 2026

Choose a reason for hiding this comment

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

In this catch block, field is not defined in this scope anymore (the surrounding for (const field of fields) loop was removed), so data.user.contributionsCollection[field] = NaN will throw a ReferenceError the first time this path is hit and prevent the fallback from completing. Instead of using an undefined loop variable, either initialize data.user.contributionsCollection as a whole or explicitly set each expected property on it when the contributions query fails.

Suggested change
data.user.contributionsCollection[field] = NaN
data.user.contributionsCollection = data.user.contributionsCollection ?? {}

Copilot uses AI. Check for mistakes.
Comment on lines +121 to +132
for (const contribution of contributions) {
for (const field in contribution) {
if (indepthExtraFields.includes(field)) {
for (const repo of contribution[field]) {
const nameWithOwner = repo.repository.nameWithOwner
if (!_owned && nameWithOwner.split('/')[0] === login) continue
totalReposContributed.add(nameWithOwner)
}
} else {
data.user.contributionsCollection[field] ??= 0
data.user.contributionsCollection[field] += contribution[field]
}
Copy link

Copilot AI Jan 30, 2026

Choose a reason for hiding this comment

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

In the indepth lifetime aggregation, you accumulate each range's numeric fields into data.user.contributionsCollection[field] using +=, but this object has already been populated earlier from the bulk or fallback contributions query, so totals like totalCommitContributions and totalIssueContributions will be double-counted (once from the initial query, again from the lifetime ranges). To avoid inflated statistics, either base the lifetime totals on a fresh accumulator and assign them at the end, or overwrite the existing values (or use a Math.max-style comparison as in the previous implementation) rather than incrementing them on top of the last-year snapshot.

Copilot uses AI. Check for mistakes.
Copy link

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

Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

data.user.contributionsCollection[field] ?? 0
)
}

Copy link

Copilot AI Feb 3, 2026

Choose a reason for hiding this comment

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

data.user.repositoriesContributedTo may be undefined when this indepth lifetime contributions path runs, because postprocess.user does not initialise this property and both the bulk BaseUserX query and the fallback unit repositoriesContributedTo query can fail. In that case, assigning to data.user.repositoriesContributedTo.totalCount will throw at runtime; consider initialising data.user.repositoriesContributedTo to a safe default (for example mirroring the structure used in postprocess.organization/postprocess.skip) before writing totalCount.

Suggested change
data.user.repositoriesContributedTo ??= { totalCount: 0 }

Copilot uses AI. Check for mistakes.
Comment on lines +43 to 44
user: ["packages", "starredRepositories", "watching", "sponsorshipsAsSponsor", "sponsorshipsAsMaintainer", "followers", "following", "issueComments", "organizations", `repositoriesContributedTo(includeUserRepositories: ${_owned})`],
organization: ["packages", "sponsorshipsAsSponsor", "sponsorshipsAsMaintainer", "membersWithRole"],
Copy link

Copilot AI Feb 3, 2026

Choose a reason for hiding this comment

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

The new repositories.owned input is used here to control includeUserRepositories in unit field queries and in the indepth lifetime aggregation, but the bulk BaseUserX query (source/plugins/base/queries/user.x.graphql:30) still hardcodes repositoriesContributedTo(includeUserRepositories: true). This means that when indepth mode is disabled and the bulk query succeeds, toggling repositories_owned has no effect on the "Contributed to X repositories" count; to align behaviour with the option description, the bulk query should also be parameterised to respect _owned.

Copilot uses AI. Check for mistakes.
Comment on lines +37 to +39
repositories_owned:
description: Include your own repositories in the "Contributed to X repositories" count
default: <default-value>
Copy link

Copilot AI Feb 3, 2026

Choose a reason for hiding this comment

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

action.yml is treated as an auto-generated file in the test suite (tests/ci.test.js:16-21 asserts that it must not appear as modified in diffs). With these manual changes, CI will fail unless the generator and/or the test expectations are updated accordingly, so please ensure this file is regenerated from its source or the tests are adjusted in tandem.

Copilot uses AI. Check for mistakes.
Comment on lines +94 to +98
repositories_owned:
description: |
Include your own repositories in the "Contributed to X repositories" count
type: boolean
default: yes
Copy link

Copilot AI Feb 3, 2026

Choose a reason for hiding this comment

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

The new repositories_owned input is defined here but does not yet appear in the base plugin README options table (which currently documents neighbouring inputs such as repositories_forks and repositories_affiliations). To keep user-facing configuration documentation in sync with available inputs, consider adding a README entry or regenerating the plugin docs from this metadata.

Copilot uses AI. Check for mistakes.
Copy link
Member

@lishaduck lishaduck left a comment

Choose a reason for hiding this comment

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

LGTM pending lint fixes.

I'll wait to merge this until after #24 to ensure that lands cleanly, though 👍🏻

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants