Repository navigation
Consolidate public GitHub API GET fallback transport - #71893
Conversation
…vior Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
|
🧠 Matt Pocock Skills Reviewer has completed the skills-based review. ✅
|
|
✅ PR Code Quality Reviewer completed the code quality review.
|
|
✅ Ponytail Reviewer completed successfully! Ponytail ReviewerOutcome: The agent completed and reported no action. A no-op output alone does not verify that all required work was completed or that publication was possible. Agent messages are omitted from this comment. The category uses structured run status, not interpretation of agent prose.
|
|
✅ Test Quality Sentinel completed test quality analysis. Test Quality SentinelOutcome: The agent completed and reported no action. A no-op output alone does not verify that all required work was completed or that publication was possible. Agent messages are omitted from this comment. The category uses structured run status, not interpretation of agent prose.
|
|
✅ Design Decision Gate 🏗️ completed the design decision gate check. See the comment below for the result and any generated ADR draft. Commit pushed:
|
Comment MemoryPeek at saved memory (pr-code-quality-reviewer)Note This comment is managed by comment memory.Expand the saved memory block to view or edit the persistent context for this thread.
|
There was a problem hiding this comment.
Review summary
One non-blocking concern is noted inline: the shared helper buffers the complete response without a size limit.
Details
The consolidation preserves the prior callers' behavior, but the new common boundary should ideally protect all callers from unexpectedly large public API responses.
🔎 Code quality review by PR Code Quality Reviewer · copilot · gpt50 · ~2 AIC · ⌖ ~1 AIC · ⊞ 1.6K
Comment /review to run again
| } | ||
| }() | ||
|
|
||
| body, err := io.ReadAll(resp.Body) |
There was a problem hiding this comment.
Reading the entire public response with io.ReadAll leaves every caller exposed to unbounded memory use if GitHub (or a test/custom transport) returns a very large body.
💡 Cap the response size
Wrap the body in an io.LimitReader with an explicit API response limit and return a distinct error when the limit is exceeded. This keeps the shared helper from turning a large remote response into a process-wide memory spike while preserving the existing caller behavior for normal responses.
There was a problem hiding this comment.
Bound GetPublic to 10 MiB and return *ResponseTooLargeError after reading at most limit+1 bytes; the regression test also verifies the body is closed. Implemented in 6ba63dc.
🏗️ Design Decision Gate — ADR RequiredThis PR makes significant changes to core business logic (368 new lines in 📄 Draft ADR committed: Decision found in the diff: add a shared
📋 What to do next
Once an ADR is linked in the PR body, this gate will re-run and verify the implementation matches the decision. ❓ Why ADRs Matter
ADRs create a searchable, permanent record of why the codebase looks the way it does. Future contributors (and your future self) will thank you. 📋 Michael Nygard ADR Format ReferenceAn ADR must contain these four sections to be considered complete:
All ADRs are stored in
|
There was a problem hiding this comment.
Skills-Based Review 🧠
Applied /codebase-design (triage: refactor_cleanup) — clean, behavior-preserving extraction. Approving.
📋 Key Themes & Highlights
Verification performed
- Confirmed
go build/go vetsucceed and all new/changed tests pass (TestGetPublicResponse,TestGetPublicInvalidURL,TestGetPublicRequestFailure,TestGetPublicCancellation,TestFetchPublicGitHubAPI,TestPublicAPIFallbackResponses). - Traced error-message parity:
HTTPStatusError.Error()reproduces the exact pre-refactor"GitHub API returned %d: %s"text, so callers that don't type-assert (release tags pagination, default-branch fallback, branch-commit fallback) see unchanged error strings. - Confirmed callers needing structured info (
remote_resolve_sha.go,remote_client.go) correctly recoverStatusCode/Bodyviaerrors.As(err, &statusErr)and still produce the original caller-specific wrapped messages. - Confirmed
errorutil.IsNotFoundError's substring-based 404 detection still matches, since the formatted error string retains"404". - Confirmed named-return
resultErr/defer finish(resultErr)wiring in both refactored call sites still captures the correct error after the switch toreturn body, err. GetPubliccloses the response body on every path (success, read error, status error) — correctly consolidates three previously-duplicated close/read/validate blocks into one deep, simple interface.
Positive Highlights
- ✅ Strong interface:
GetPublic(ctx, client, url) ([]byte, error)hides header-setting, body handling, and status validation behind a single call — a good example of a deep module per/codebase-design. - ✅ Typed
HTTPStatusErrorpreserves backward-compatible string formatting while giving callers that need it structured access toStatusCode/Body. - ✅ Comprehensive new test coverage, including edge cases often missed (cancellation, invalid URL, body-read failure before/after status validation).
Minor, non-blocking note
- The
resp.Body.Close()error-logging branch inpublic_get.goisn't exercised by any test. Trivial and not worth blocking on, but a quickio.Reader+ close-erroring body test would close the last coverage gap.
🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · copilot · sonnet50 · ~64 AIC · ⌖ ~15 AIC · ⊞ 10.2K
Comment /matt to run again
There was a problem hiding this comment.
🟢 Approval recommended
The bounded refactor preserves existing caller behavior and adds focused regression coverage, with no blocking issues identified.
No open issues 🎉
What changed in this PR
Consolidates unauthenticated GitHub GET handling in pkg/githubapi for CLI update and parser fallbacks, addressing #71713 while keeping caller-specific behavior in place.
Changes:
- Adds a shared, context-aware GET helper with response cleanup and typed HTTP status errors.
- Migrates three fallbacks while preserving error messages, logging, URL construction, and parsing.
- Adds transport and caller regression coverage and updates package documentation.
| File | Description |
|---|---|
pkg/parser/remote_resolve_sha.go |
Uses shared transport while retaining SHA parsing and contextual errors. |
pkg/parser/remote_public_api_test.go |
Covers parser fallback responses, URLs, and operation reporting. |
pkg/parser/remote_client.go |
Delegates contents requests while preserving status logging. |
pkg/githubapi/README.md |
Documents the shared helper and response contract. |
pkg/githubapi/public_get.go |
Implements shared request, body, and status handling. |
pkg/githubapi/public_get_test.go |
Covers success, failures, cancellation, and body closure. |
pkg/cli/update_workflows.go |
Delegates public GET transport while retaining operation timing. |
pkg/cli/update_public_api_test.go |
Checks CLI fallback responses and operation reporting. |
Review effort: Max
|
@copilot address the following outstanding work in one pass:
Push the necessary fixes, reply to each listed review thread and resolve it when addressed. Ignore feedback already answered or resolved. Use the pr-finisher skill and stop when only human review or CI remains; do not trigger CI. Sous-chef head: 672c4d5
|
…e-fix-github-api-get-fallback Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>
Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>
Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>
Merged latest |
|
🎉 This pull request is included in a new release. Release: |
Three CLI and parser fallbacks duplicate unauthenticated GitHub GET handling, creating opportunities for response and cancellation behavior to diverge.
githubapi.GetPublic(ctx, client, endpointURL)for context-aware requests, the GitHub JSON Accept header, body reading and closure, and HTTP 200 validation.HTTPStatusErrorvalues while preserving existing caller-specific messages and debug logging.