Repository navigation
Conversation
Count PRs/issues/reviews in apache/cloudstack* repos and name mentions on lists.apache.org Signed-off-by: Abhishek Kumar <[email protected]>
|
Thanks @shwstppr , I'll give these a go soon. |
There was a problem hiding this comment.
Warning
Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.
Copilot review overview
6 open issues
Thenot r.content.strip()check runs beforeraise_for_status(), which can misclassify… · New This loads the entire monthly mbox into memory (r.content) before writing it. Mbox archives can… · New This loads the entire monthly mbox into memory (r.content) before writing it. Mbox archives can… · New This error message loses important context when multiple users are processed. Include the login in… · Newparseaddris imported but not used anywhere in this file. Please remove it to keep the script… · New The implementation yields half-open ranges (start < to_dtandend = min(..., to_dt)), so the… · New
What changed in this PR
Adds tooling to quantify contributor activity across GitHub and Apache mailing lists to support committer/PMC nomination discussions.
Changes:
- Add a GitHub GraphQL script to count PRs/issues/reviews per user within org repos matching a pattern.
- Add a lists.apache.org mbox-based script to count name/alias mentions with local caching.
- Add documentation describing usage, options, and caveats for both scripts.
| File | Description |
|---|---|
| tools/contribution/github_org_contributions.py | New CLI to query GitHub GraphQL and aggregate per-user contribution counters over a date window. |
| tools/contribution/apache_list_mentions.py | New CLI to download/cache mbox archives and count name mentions in message bodies. |
| tools/contribution/README.md | New README documenting required setup and usage for the contribution evaluation scripts. |
Review effort: Lite
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #14509 +/- ##
============================================
+ Coverage 19.91% 20.69% +0.78%
- Complexity 20194 21770 +1576
============================================
Files 6373 6492 +119
Lines 577230 590805 +13575
Branches 70696 72461 +1765
============================================
+ Hits 114942 122262 +7320
- Misses 449722 455263 +5541
- Partials 12566 13280 +714
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Signed-off-by: Abhishek Kumar <[email protected]>
There was a problem hiding this comment.
Warning
Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.
Copilot review overview
11 open issues
The GitHub script also has a hard per-counter per-year cap due tomaxRepositories(100), and it… · New If the names file contains the same canonical name more than once,orderedwill contain… · New This scales as O(messages × names) full-text regex scans (eachfindallre-scans the entire body).… · New When the user passes a date-only--to,to_dtis intentionally advanced by one day… · New This error message loses important context when multiple users are processed. Include the login in… This loads the entire monthly mbox into memory (r.content) before writing it. Mbox archives can… This loads the entire monthly mbox into memory (r.content) before writing it. Mbox archives can… Thenot r.content.strip()check runs beforeraise_for_status(), which can misclassify… GivenmaxRepositoriesis set toMAX_REPOSITORIES, the returned list length cannot exceed that… · New The implementation yields half-open ranges (start < to_dtandend = min(..., to_dt)), so the…parseaddris imported but not used anywhere in this file. Please remove it to keep the script…
Review effort: Lite
| - Dates without a time are in UTC; `--from` starts at the beginning of that day | ||
| and `--to` includes the whole day. | ||
| - GitHub limits a query to one year, so longer windows are split into yearly | ||
| chunks and summed. |
| ordered.append(canon) | ||
| aliases_map[canon] = variants |
| for canon in ordered_names: | ||
| mentions[canon] += len(mention_rx[canon].findall(body)) |
| return " ".join(("" if r[h] is None else str(r[h])).ljust(colw[h]) for h in headers).rstrip() | ||
|
|
||
| print(f"Org: {org['login']} (repos matching: {args.repo_pattern})") | ||
| print(f"Window (UTC): {from_dt.isoformat()} -> {to_dt.isoformat()}") |
| cc = user["contributionsCollection"] | ||
| for key, field in COUNTERS.items(): | ||
| entries = cc[field] | ||
| if len(entries) >= MAX_REPOSITORIES: |
Signed-off-by: Abhishek Kumar <[email protected]>
There was a problem hiding this comment.
Warning
Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.
Copilot review overview
16 open issues
The mbox URL is constructed via string formatting with user-provided--list/--domain. For… · New The mbox URL is constructed via string formatting with user-provided--list/--domain. For… · New If the names file contains the same canonical name more than once,orderedwill contain… · New This is O(messages × names) regex scans, which can become slow for large name lists and/or large… · New When the user passes a date-only--to,to_dtis intentionally advanced by one day… This scales as O(messages × names) full-text regex scans (eachfindallre-scans the entire body).… If the names file contains the same canonical name more than once,orderedwill contain… The GitHub script also has a hard per-counter per-year cap due tomaxRepositories(100), and it… This error message loses important context when multiple users are processed. Include the login in… This loads the entire monthly mbox into memory (r.content) before writing it. Mbox archives can… This loads the entire monthly mbox into memory (r.content) before writing it. Mbox archives can… Thenot r.content.strip()check runs beforeraise_for_status(), which can misclassify… When--tois provided as a date-only value, the implementation intentionally converts it to an… · New GivenmaxRepositoriesis set toMAX_REPOSITORIES, the returned list length cannot exceed that… The implementation yields half-open ranges (start < to_dtandend = min(..., to_dt)), so the…parseaddris imported but not used anywhere in this file. Please remove it to keep the script…
Review effort: Lite
| """ | ||
| Download a single YYYY-MM mbox archive from lists.apache.org and save to out_dir. | ||
| """ | ||
| url = MBOX_API.format(list=list_name, domain=domain, ym=ym) |
| headers = {"User-Agent": "apache-list-mentions/1.0"} | ||
| with requests.get(url, headers=headers, timeout=120, stream=True) as r: |
| ordered.append(canon) | ||
| aliases_map[canon] = variants |
| for canon in ordered_names: | ||
| mentions[canon] += len(mention_rx[canon].findall(body)) |
| return " ".join(("" if r[h] is None else str(r[h])).ljust(colw[h]) for h in headers).rstrip() | ||
|
|
||
| print(f"Org: {org['login']} (repos matching: {args.repo_pattern})") | ||
| print(f"Window (UTC): {from_dt.isoformat()} -> {to_dt.isoformat()}") |


Description
Count PRs/issues/reviews in apache/cloudstack* repos and name mentions on lists.apache.org
Types of changes
Feature/Enhancement Scale or Bug Severity
Feature/Enhancement Scale
Bug Severity
Screenshots (if appropriate):
How Has This Been Tested?
How did you try to break this feature and the system with this change?