Skip to content

refactor: migrate from github3.py to PyGithub#789

Merged
jmeridth merged 4 commits into
mainfrom
migrate-to-pygithub
Jul 6, 2026
Merged

refactor: migrate from github3.py to PyGithub#789
jmeridth merged 4 commits into
mainfrom
migrate-to-pygithub

Conversation

@jmeridth

@jmeridth jmeridth commented Jul 4, 2026

Copy link
Copy Markdown
Collaborator

What/Why

Migrate from github3-py to PyGithub>=2.6.0, aligning with the 6 sibling OSPO repos (cleanowners, measure-innersource, pr-conflict-detector, evergreen, contributors, stale-repos) that have already completed this migration.

Proof it works

  • 194 tests pass with 100% coverage
  • All pre-commit hooks pass

Risk + AI role

Medium -- touches auth, search, and all metric calculation modules. All code AI-assisted (Claude Opus 4.6) following established patterns from sibling repo PRs.

Review focus

  • Auth module changes (App auth, token auth, GHE paths)
  • PyGithub object access patterns (NamedUser.login vs dict, Label.name vs dict, native datetime handling)

Readiness Checklist

Author/Contributor

  • If documentation is needed for this change, has that been included in this pull request
  • run make lint and fix any issues that you have introduced
  • run make test and ensure you have test coverage for the lines you are introducing

## What/Why

Replace github3-py with PyGithub>=2.6.0 to align with the 6 sibling OSPO
repos (cleanowners, measure-innersource, pr-conflict-detector, evergreen,
contributors, stale-repos) that have already migrated.

## Proof it works

- 194 tests pass with 100% coverage
- All pre-commit hooks pass (secrets, end-of-file, trailing whitespace,
  flake8, isort, pylint, mypy, black)

## Risk + AI role

Medium -- touches auth, search, and all metric calculation modules.
All code AI-generated (Claude Opus 4.6) following established patterns
from sibling repo PRs.

## Review focus

- Auth module changes (App auth, token auth, GHE paths)
- PyGithub object access patterns (NamedUser.login vs dict, Label.name
  vs dict, native datetime handling)

Signed-off-by: jmeridth <jmeridth@gmail.com>
@jmeridth jmeridth added the Mark Ready When Ready Automatically mark draft PR ready when checks pass label Jul 4, 2026
@jmeridth jmeridth self-assigned this Jul 4, 2026
@jmeridth
jmeridth requested a review from Copilot July 4, 2026 22:06
@github-actions
github-actions Bot marked this pull request as ready for review July 4, 2026 22:09
@github-actions
github-actions Bot requested a review from zkoppert as a code owner July 4, 2026 22:09
@github-actions github-actions Bot removed the Mark Ready When Ready Automatically mark draft PR ready when checks pass label Jul 4, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 migrates the action’s GitHub API client from github3.py to PyGithub>=2.6.0, updating the authentication flow, search layer, and metric-calculation modules to use PyGithub’s object model and datetime handling.

Changes:

  • Replace github3.py usage with PyGithub types and access patterns across auth, search, and metric modules.
  • Update metric logic to use native datetime fields from PyGithub objects instead of ISO string parsing.
  • Refresh unit tests and dependency locks to reflect the new client library and object shapes.

Reviewed changes

Copilot reviewed 25 out of 27 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
uv.lock Removes github3-py and locks pygithub (+ transitive deps like pynacl).
pyproject.toml Swaps runtime dependency from github3-py to PyGithub>=2.6.0 and drops direct requests / types-requests.
auth.py Reworks PAT + GitHub App auth to use PyGithub Auth / GithubIntegration.
search.py Ports issue search and exception handling to GithubException.
issue_metrics.py Updates per-issue metric extraction to PyGithub issue/PR fields and helpers.
labels.py Updates label event parsing (event.label.name) and datetime arithmetic.
pr_comments.py Updates comment/review-comment retrieval to PyGithub APIs (get_comments, get_review_comments).
most_active_mentors.py Ports comment/review iteration to PyGithub and adds explicit max-eval limiting.
time_to_ready_for_review.py Uses Issue.get_events() for ready-for-review event detection.
time_to_merge.py Switches to PyGithub PullRequest and native datetime fields.
time_to_first_review.py Uses PullRequest.get_reviews() and PyGithub user objects.
time_to_first_response.py Uses Issue.get_comments() / PullRequest.get_reviews() and native datetime fields.
time_to_close.py Uses native datetime fields for issue close duration calculation.
time_in_draft.py Ports PR draft tracking logic to PyGithub (as_pull_request, get_events).
test_auth.py Updates auth tests to mock PyGithub Auth, Github, and GithubIntegration behavior.
test_search.py Updates search tests to use GithubException and new search return shapes.
test_issue_metrics.py Updates issue/PR mocks to match PyGithub field shapes and datetime types.
test_time_to_ready_for_review.py Updates event access to get_events().
test_time_to_first_review.py Updates review access to get_reviews() and datetime inputs.
test_time_to_first_response.py Updates comment/review accessors and user shapes for PyGithub.
test_time_to_close.py Updates to use datetime objects for created/closed timestamps.
test_time_in_draft.py Updates mocks to use get_events() / as_pull_request() and PyGithub-like issue shape.
test_labels.py Updates label mocks to .name attribute objects and datetime fields.
test_pr_comments.py Updates to PyGithub comment/review-comment accessors.
test_most_active_mentors.py Updates comment/review accessors and adds review limit branch coverage.
.github/linters/.python-lint Removes suggestion-mode setting from pylint config.
.coveragerc Formatting-only change (no behavioral change).

Comment thread search.py
Comment thread auth.py
Comment thread time_to_merge.py Outdated
## What/Why

Fix issues identified by PR review and agent analysis: ConnectionError
class hierarchy bug, dropped per_page parameter, docstring mismatches,
and a test relying on MagicMock auto-attribute behavior.

## Proof it works

- 195 tests pass with 100% coverage
- All pre-commit hooks pass

## Risk + AI role

Low -- targeted fixes to exception handling, pagination, docs, and tests.
All code AI-assisted (Claude Opus 4.6).

## Review focus

- ConnectionError catch broadened to include OSError (search.py:68)
- per_page=100 restored on search_issues call (search.py:39)

Signed-off-by: jmeridth <jmeridth@gmail.com>

@zkoppert zkoppert left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

A few follow-ups from a closer look at the migration, mostly around the search rate-limit handling and dependency declarations. I left the specifics inline.

Comment thread search.py Outdated
Comment thread search.py
Comment thread pyproject.toml
Comment thread pyproject.toml Outdated
Comment thread auth.py Outdated
…prove error handling

- Remove rate_limit_bypass parameter entirely (unused since PyGithub migration)
- Catch RateLimitExceededException before GithubException for clearer errors
- Re-add requests as explicit dependency (used by discussions.py)
- Pin PyGithub==2.9.1 for consistency with other pinned deps
- Add types-requests back to dev dependencies
- Remove dead None guard in auth_to_github (PyGithub never returns None)
- Remove corresponding test_auth_to_github_invalid_credentials test

Signed-off-by: jmeridth <jmeridth@gmail.com>
Comment thread time_to_first_response.py
PyGithub returns comment.user as None for ghost (deleted) accounts.
Both ignore_comment functions now return True for None users to prevent
AttributeError on .login/.type access. Added tests covering the ghost
user path in both time_to_first_response and most_active_mentors.

Signed-off-by: jmeridth <jmeridth@gmail.com>
@jmeridth
jmeridth requested a review from zkoppert July 6, 2026 17:07

@zkoppert zkoppert left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

🚀

@jmeridth
jmeridth merged commit df8c49d into main Jul 6, 2026
39 checks passed
@jmeridth
jmeridth deleted the migrate-to-pygithub branch July 6, 2026 23:55
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