Auto-generate sponsors buttons with eligibility verification#20
Auto-generate sponsors buttons with eligibility verification#20
Conversation
…ith GitHub Sponsors Agent-Logs-Url: https://github.com/NextCommunity/.github/sessions/8613061b-8c11-4e16-89d7-5759a7ccd445 Co-authored-by: jbampton <418747+jbampton@users.noreply.github.com>
Agent-Logs-Url: https://github.com/NextCommunity/.github/sessions/8613061b-8c11-4e16-89d7-5759a7ccd445 Co-authored-by: jbampton <418747+jbampton@users.noreply.github.com>
Agent-Logs-Url: https://github.com/NextCommunity/.github/sessions/e4ad3af6-c5a9-4090-99cf-f370542e65ae Co-authored-by: jbampton <418747+jbampton@users.noreply.github.com>
Agent-Logs-Url: https://github.com/NextCommunity/.github/sessions/1e75a0a8-c562-404b-ad1f-7960cddaf3aa Co-authored-by: jbampton <418747+jbampton@users.noreply.github.com>
- Add generate_sponsors_html() to build shields.io sponsor buttons from the ranked contributor list (top 5 by default) - Add SPONSORS_START/SPONSORS_END markers and _replace_section() helper so update_readme() can update both sponsors and leaderboard sections - Add _badge_escape() for proper shields.io URL encoding (hyphens, underscores) - Wrap existing static sponsors HTML in markers for auto-replacement - Rotating color pairs give each sponsor button a distinct look Agent-Logs-Url: https://github.com/NextCommunity/.github/sessions/7b5057d0-b79a-4769-81c8-88469f1460bf Co-authored-by: jbampton <418747+jbampton@users.noreply.github.com>
generate_sponsors_html() now verifies each contributor has an active GitHub Sponsors page (has_sponsors_listing field) before including them. Contributors without sponsors are silently skipped, and the function continues until MAX_SPONSOR_BUTTONS sponsorable users are found. Badges preserve the contributor's actual leaderboard rank (e.g. Rank 5, Rank 15) rather than sequential numbering. Agent-Logs-Url: https://github.com/NextCommunity/.github/sessions/d3768b57-d91c-42f3-820d-f6478f2ee1ba Co-authored-by: jbampton <418747+jbampton@users.noreply.github.com>
Agent-Logs-Url: https://github.com/NextCommunity/.github/sessions/d3768b57-d91c-42f3-820d-f6478f2ee1ba Co-authored-by: jbampton <418747+jbampton@users.noreply.github.com>
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request adds a 'Featured Leaderboard Sponsors Showcase' to the profile README, highlighting the top five contributors with active GitHub Sponsors profiles. It updates the leaderboard data and refactors scripts/leaderboard.py to include automated sponsor status checks and dynamic badge generation. Feedback was provided to limit the search depth for sponsorable contributors to prevent potential API rate limiting and to implement proper URL encoding for emojis in badge links to ensure they render correctly.
There was a problem hiding this comment.
Pull request overview
This PR automates the “Featured Leaderboard Sponsors Showcase” section so sponsor buttons are generated from the leaderboard and only include contributors with an active GitHub Sponsors listing.
Changes:
- Added Sponsors eligibility checks and HTML generation for up to 5 sponsor buttons in
scripts/leaderboard.py. - Refactored README updating to support generic marker-based section replacement and update both Sponsors + Leaderboard sections in one run.
- Wrapped the sponsors section in
profile/README.mdwith<!-- SPONSORS:START/END -->markers and updated the rendered sponsor buttons.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
scripts/leaderboard.py |
Adds sponsor eligibility lookup + badge HTML generation; refactors README section replacement to update Sponsors and Leaderboard markers. |
profile/README.md |
Introduces Sponsors start/end markers and updates the sponsor showcase HTML to the new generated format. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…ator, add sponsors cache - Cap contributor scan to top 50 (MAX_SPONSOR_SCAN_DEPTH) to prevent excessive API calls (addresses Gemini high-priority + Copilot review) - URL-encode emoji label/message in shields.io badge URLs with urllib.parse.quote (addresses Gemini medium-priority + Copilot review) - Fix <br> separator logic: insert between items instead of after each, so no trailing <br> when fewer than MAX_SPONSOR_BUTTONS found - Update docstring to reflect that inclusion/skip decisions are logged - Add JSON cache (.sponsors_cache.json) for sponsors eligibility to avoid redundant API calls across runs - Add 0.25s delay between uncached API requests to be polite - Add .sponsors_cache.json to .gitignore Agent-Logs-Url: https://github.com/NextCommunity/.github/sessions/f41d12df-5dcf-4f8f-952b-0d9b34296165 Co-authored-by: jbampton <418747+jbampton@users.noreply.github.com>
…ng emojis Agent-Logs-Url: https://github.com/NextCommunity/.github/sessions/f41d12df-5dcf-4f8f-952b-0d9b34296165 Co-authored-by: jbampton <418747+jbampton@users.noreply.github.com>
|
/gemini review |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 3 changed files in this pull request and generated 4 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Code Review
This pull request introduces a GitHub Sponsors showcase to the profile README, featuring top contributors who have active sponsor profiles. The scripts/leaderboard.py script was updated to fetch this data from the GitHub API, with a local cache implemented to minimize redundant requests. Additionally, the leaderboard statistics were refreshed. Feedback suggests that the sponsors generation logic should be modified to return an empty string if no eligible sponsors are found, preventing an empty header from appearing in the README.
There was a problem hiding this comment.
Code Review
This pull request adds a "Featured Leaderboard Sponsors Showcase" to the profile README, displaying badges for top contributors with active GitHub Sponsors profiles. The changes include new logic in scripts/leaderboard.py to fetch and cache sponsor status from the GitHub API, along with a refactored README update process. Review feedback suggests improving the robustness of the sponsor check by distinguishing between definitive 404 errors and transient API failures to prevent caching incorrect data. Additionally, it is recommended to handle potential exceptions in the main loop, omit the sponsors section if no eligible contributors are found, and implement a cache expiration mechanism to periodically re-verify contributor status.
…ty sponsors, README URLs - SPONSORS_CACHE_PATH: use RUNNER_TEMP in GitHub Actions (per-run temp); repo-local path for local runs only - _load_sponsors_cache(): filter to bool-typed entries only; drops corrupted or manually edited non-bool values - has_sponsors_page(): re-raise non-404 URLError so transient errors (rate limits, network failures) propagate to caller instead of silently returning False - generate_sponsors_html(): only cache True (confirmed sponsorable) results; negative and error results are re-checked on each run; wrap has_sponsors_page() in try/except and log warning on transient error without crashing; return empty string when no sponsors found within scan depth - profile/README.md: update badge URLs to percent-encoded form matching what the script now generates; update separator to new between-items <br> format Agent-Logs-Url: https://github.com/NextCommunity/.github/sessions/f560c572-6199-4946-92f5-38c2ed9424b3 Co-authored-by: jbampton <418747+jbampton@users.noreply.github.com>
Agent-Logs-Url: https://github.com/NextCommunity/.github/sessions/f560c572-6199-4946-92f5-38c2ed9424b3 Co-authored-by: jbampton <418747+jbampton@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 3 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| def _load_sponsors_cache(): | ||
| """Load the sponsors eligibility cache from disk. | ||
|
|
||
| Returns a dict mapping GitHub login to a cached boolean result. | ||
| Only entries with a string key and a boolean value are kept; corrupted | ||
| or invalid entries are silently dropped. | ||
| Returns an empty dict if the cache file does not exist or is invalid. | ||
| """ | ||
| try: | ||
| with open(SPONSORS_CACHE_PATH, "r", encoding="utf-8") as fh: | ||
| data = json.load(fh) | ||
| if isinstance(data, dict): | ||
| return { | ||
| login: eligible | ||
| for login, eligible in data.items() | ||
| if isinstance(login, str) and isinstance(eligible, bool) | ||
| } |
There was a problem hiding this comment.
_load_sponsors_cache() currently retains cached entries where the value is False (it filters for isinstance(eligible, bool)), but generate_sponsors_html() assumes negative results are never cached and skips API re-checks when login in cache. If an older cache file (or manual edit) contains false, those users will never be rechecked and can never become eligible. Consider dropping False entries on load (keep only eligible is True) or treating cached False as a cache miss in generate_sponsors_html().
| if login in cache: | ||
| eligible = cache[login] | ||
| else: | ||
| try: | ||
| eligible = has_sponsors_page(login, token) | ||
| # Only cache confirmed positive results. Negative results are | ||
| # re-checked on every run so that users who later enable Sponsors | ||
| # are picked up automatically. Errors are never cached so that | ||
| # a transient failure doesn't permanently suppress a sponsor. | ||
| if eligible: | ||
| cache[login] = eligible | ||
| # Brief pause between uncached API calls to be polite. |
There was a problem hiding this comment.
generate_sponsors_html() permanently trusts cached True eligibility results (if login in cache: eligible = cache[login]) and never re-validates them. If a user disables GitHub Sponsors later, the README will keep showing their sponsor button indefinitely until the cache is deleted. Consider adding a TTL (store timestamp) and occasionally rechecking cached True values, or cache both states with an expiry window.
Uh oh!
There was an error while loading. Please reload this page.