Skip to content

Restructure github_async into a lazy-loaded package#23685

Merged
AAraKKe merged 1 commit into
masterfrom
aarakke/async-github-refactor
May 13, 2026
Merged

Restructure github_async into a lazy-loaded package#23685
AAraKKe merged 1 commit into
masterfrom
aarakke/async-github-refactor

Conversation

@AAraKKe
Copy link
Copy Markdown
Contributor

@AAraKKe AAraKKe commented May 13, 2026

What does this PR do?

Restructures ddev.utils.github_async from a single file into a package with the client in client.py and one model per submodule under models/. Both __init__.py files use PEP 562 __getattr__, so e.g. from ddev.utils.github_async.models import PullRequest only loads pull_request.py (plus its user/label dependencies), not every model.

Adds two new endpoints needed by upcoming work, expands the PullRequest model with the fields you typically need when inspecting a PR (state, draft, title/body, user/assignees, labels, branches, timestamps), and introduces a FakeAsyncGitHubClient test helper with a mock_response API supporting sticky replies, one-shot FIFO queues, partial-kwarg matching, and exception responses.

Motivation

Sets up the async-client surface and test infrastructure that a stacked PR on top will use to add a new ddev release port-commit command. Lands the refactor on its own so review can focus on the client/test-fixture shape independent of feature code.

Review checklist (to be filled by reviewers)

  • Feature or bugfix MUST have appropriate tests (unit, integration, e2e)
  • Add the qa/skip-qa label if the PR doesn't need to be tested during QA.
  • If you need to backport this PR to another branch, you can add the backport/<branch-name> label to the PR and it will automatically open a backport PR once this one is merged

@AAraKKe AAraKKe added the qa/skip-qa Automatically skip this PR for the next QA label May 13, 2026
@dd-octo-sts dd-octo-sts Bot added the ddev label May 13, 2026
@AAraKKe AAraKKe force-pushed the aarakke/async-github-refactor branch from cbef667 to e33bd03 Compare May 13, 2026 07:38
Copy link
Copy Markdown
Contributor Author

AAraKKe commented May 13, 2026

This stack of pull requests is managed by Graphite. Learn more about stacking.

@AAraKKe AAraKKe force-pushed the aarakke/async-github-refactor branch from e33bd03 to 579edab Compare May 13, 2026 07:41
@AAraKKe AAraKKe marked this pull request as ready for review May 13, 2026 07:48
@AAraKKe AAraKKe requested a review from a team as a code owner May 13, 2026 07:48
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 579edabe87

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +36 to +43
_MODULE_BY_NAME: dict[str, str] = {
'AsyncGitHubClient': 'client',
'async_github_client': 'client',
'GITHUB_API_VERSION': 'client',
'DEFAULT_BASE_URL': 'client',
'GitHubResponse': 'client',
'PaginationData': 'client',
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Restore top-level model re-exports

This map now omits the model classes that were exported by the old ddev.utils.github_async module, so existing callers using imports such as from ddev.utils.github_async import WorkflowRun or ArtifactsList will fail with ImportError after this refactor even though the changelog describes a package restructure rather than a breaking API change. Add the model names here (pointing at the appropriate models.* modules) or otherwise preserve the old top-level imports while keeping the lazy loading behavior.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

There are no existing callers yet, that is the point of moving it now. This was just introduced and we want to set it in a way that we can maintain it for easy imports without too long import lines while doing it lazily so we only import what is needed.

@AAraKKe AAraKKe force-pushed the aarakke/async-github-refactor branch from 579edab to 5729ee2 Compare May 13, 2026 07:58
@codecov
Copy link
Copy Markdown

codecov Bot commented May 13, 2026

Codecov Report

❌ Patch coverage is 96.93654% with 14 lines in your changes missing coverage. Please review.
✅ Project coverage is 90.92%. Comparing base (94059a2) to head (1c9e7d3).

Additional details and impacted files
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@datadog-prod-us1-3
Copy link
Copy Markdown

datadog-prod-us1-3 Bot commented May 13, 2026

Tests

🎉 All green!

❄️ No new flaky tests detected
🧪 All tests passed

🎯 Code Coverage (details)
Patch Coverage: 96.94%
Overall Coverage: 87.46% (-0.49%)

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: 1c9e7d3 | Docs | Datadog PR Page | Give us feedback!

@AAraKKe AAraKKe force-pushed the aarakke/async-github-refactor branch 6 times, most recently from 99fa9d0 to 2a381c6 Compare May 13, 2026 09:47
Splits the single-file `ddev/utils/github_async.py` into a package with the
client and HTTP-shape primitives in `client.py` and one model per submodule
under `models/`. Both `__init__.py` files use PEP 562 module-level
`__getattr__` so importing one symbol only loads the submodule that defines
it -- in particular `from ddev.utils.github_async.models import PullRequest`
does not pull in the workflow or comment models.

Adds two new endpoints used by upcoming work:
  - `AsyncGitHubClient.create_pull_request(owner, repo, title, head, base, body, draft)`
  - `AsyncGitHubClient.add_labels_to_issue(owner, repo, issue_number, labels)`

Expands the `PullRequest` model with the typical fields callers need (id,
state, draft, title, body, user, assignees, requested_reviewers, labels,
created_at/updated_at/closed_at/merged_at, head, base) plus three small
sub-models (`GitHubUser`, `Label`, `PullRequestRef`). Only `number` and
`html_url` are required; the rest default to None/[] so partial payloads
parse fine and `extra='ignore'` keeps the schema forward-compatible.

Adds `FakeAsyncGitHubClient` and the `fake_async_github` pytest fixture in
`tests/helpers/github_async.py`. The fake records every call and offers
`mock_response(method, response, /, *, once=False, **match_kwargs)` for
stubbing replies. Responses can be `BaseException` instances (raised),
`GitHubResponse` instances (passed through), or inner data (auto-wrapped).
`once=True` adds to a per-method FIFO queue so tests can model retry
sequences. Sticky mocks (no `once`) match the most-recent registration.
`assert_called_with` / `assert_called_once_with` perform strict-equality
checks on kwargs; `assert_all_responses_consumed()` asserts the one-shot
queue was drained.
@AAraKKe AAraKKe force-pushed the aarakke/async-github-refactor branch from 2a381c6 to 1c9e7d3 Compare May 13, 2026 10:42
@dd-octo-sts
Copy link
Copy Markdown
Contributor

dd-octo-sts Bot commented May 13, 2026

Validation Report

All 20 validations passed.

Show details
Validation Description Status
agent-reqs Verify check versions match the Agent requirements file
ci Validate CI configuration and Codecov settings
codeowners Validate every integration has a CODEOWNERS entry
config Validate default configuration files against spec.yaml
dep Verify dependency pins are consistent and Agent-compatible
http Validate integrations use the HTTP wrapper correctly
imports Validate check imports do not use deprecated modules
integration-style Validate check code style conventions
jmx-metrics Validate JMX metrics definition files and config
labeler Validate PR labeler config matches integration directories
legacy-signature Validate no integration uses the legacy Agent check signature
license-headers Validate Python files have proper license headers
licenses Validate third-party license attribution list
metadata Validate metadata.csv metric definitions
models Validate configuration data models match spec.yaml
openmetrics Validate OpenMetrics integrations disable the metric limit
package Validate Python package metadata and naming
readmes Validate README files have required sections
saved-views Validate saved view JSON file structure and fields
version Validate version consistency between package and changelog

View full run

@AAraKKe AAraKKe added this pull request to the merge queue May 13, 2026
Merged via the queue into master with commit aeda997 May 13, 2026
365 checks passed
@AAraKKe AAraKKe deleted the aarakke/async-github-refactor branch May 13, 2026 11:20
@dd-octo-sts dd-octo-sts Bot added this to the 7.79.0 milestone May 13, 2026
HadhemiDD pushed a commit that referenced this pull request May 13, 2026
Splits the single-file `ddev/utils/github_async.py` into a package with the
client and HTTP-shape primitives in `client.py` and one model per submodule
under `models/`. Both `__init__.py` files use PEP 562 module-level
`__getattr__` so importing one symbol only loads the submodule that defines
it -- in particular `from ddev.utils.github_async.models import PullRequest`
does not pull in the workflow or comment models.

Adds two new endpoints used by upcoming work:
  - `AsyncGitHubClient.create_pull_request(owner, repo, title, head, base, body, draft)`
  - `AsyncGitHubClient.add_labels_to_issue(owner, repo, issue_number, labels)`

Expands the `PullRequest` model with the typical fields callers need (id,
state, draft, title, body, user, assignees, requested_reviewers, labels,
created_at/updated_at/closed_at/merged_at, head, base) plus three small
sub-models (`GitHubUser`, `Label`, `PullRequestRef`). Only `number` and
`html_url` are required; the rest default to None/[] so partial payloads
parse fine and `extra='ignore'` keeps the schema forward-compatible.

Adds `FakeAsyncGitHubClient` and the `fake_async_github` pytest fixture in
`tests/helpers/github_async.py`. The fake records every call and offers
`mock_response(method, response, /, *, once=False, **match_kwargs)` for
stubbing replies. Responses can be `BaseException` instances (raised),
`GitHubResponse` instances (passed through), or inner data (auto-wrapped).
`once=True` adds to a per-method FIFO queue so tests can model retry
sequences. Sticky mocks (no `once`) match the most-recent registration.
`assert_called_with` / `assert_called_once_with` perform strict-equality
checks on kwargs; `assert_all_responses_consumed()` asserts the one-shot
queue was drained.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ddev qa/skip-qa Automatically skip this PR for the next QA team/agent-integrations

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants