Skip to content

Consolidate public GitHub API GET fallback transport - #71893

Merged
pelikhan merged 6 commits into
mainfrom
copilot/duplicate-code-fix-github-api-get-fallback
Oct 25, 2026
Merged

pelikhan merged 6 commits into
mainfrom
copilot/duplicate-code-fix-github-api-get-fallback

Conversation

Copilot AI commented Oct 25, 2026 •

Copy link
Copy Markdown
Contributor

Three CLI and parser fallbacks duplicate unauthenticated GitHub GET handling, creating opportunities for response and cancellation behavior to diverge.

  • Shared transport: Add githubapi.GetPublic(ctx, client, endpointURL) for context-aware requests, the GitHub JSON Accept header, body reading and closure, and HTTP 200 validation.
  • Error compatibility: Return typed HTTPStatusError values while preserving existing caller-specific messages and debug logging.
  • Caller boundaries: Keep operation timing, URL escaping, fallback eligibility, client timeouts, and SHA parsing in the callers.
body, err := githubapi.GetPublic(ctx, client, endpointURL)
…vior

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title [WIP] Refactor duplicate GitHub API GET fallback code Oct 25, 2026
Copilot AI requested a review from pelikhan October 25, 2026 13:10
@pelikhan
pelikhan marked this pull request as ready for review October 25, 2026 13:20
Copilot AI max review requested due to automatic review settings October 25, 2026 13:20
@github-actions

github-actions Bot commented Oct 25, 2026 •

Copy link
Copy Markdown
Contributor

🧠 Matt Pocock Skills Reviewer has completed the skills-based review. ✅

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer

@github-actions

github-actions Bot commented Oct 25, 2026 •

Copy link
Copy Markdown
Contributor

✅ PR Code Quality Reviewer completed the code quality review.

🔎 Code quality review by PR Code Quality Reviewer

@github-actions

github-actions Bot commented Oct 25, 2026 •

Copy link
Copy Markdown
Contributor

✅ Ponytail Reviewer completed successfully!

Ponytail Reviewer

Outcome: reported_no_action

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.

Generated from Ponytail Reviewer · gpt56 · ~7 AIC · ⌖ ~6 AIC · ⊞ 14.8K · ◷

Generated by Ponytail Reviewer for #71893

@github-actions

github-actions Bot commented Oct 25, 2026 •

Copy link
Copy Markdown
Contributor

✅ Test Quality Sentinel completed test quality analysis.

Test Quality Sentinel

Outcome: reported_no_action

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.

Generated from Test Quality Sentinel · haiku45 · ~6 AIC · ⌖ ~14 AIC · ◇ ~5 AIC · ⊞ 9.2K · ◷

🧪 Test quality analysis by Test Quality Sentinel

@github-actions

github-actions Bot commented Oct 25, 2026 •

Copy link
Copy Markdown
Contributor

✅ Design Decision Gate 🏗️ completed the design decision gate check. See the comment below for the result and any generated ADR draft.

Commit pushed: 672c4d5

🏗️ ADR gate enforced by Design Decision Gate 🏗️

@github-actions

Copy link
Copy Markdown
Contributor

Comment Memory

Peek at saved memory (pr-code-quality-reviewer)
reviewed_at: 2026-10-25T13:24:31Z
review_event: COMMENT
top_themes:
  - unbounded public API response buffering
files_reviewed:
  - pkg/githubapi/public_get.go
  - pkg/cli/update_workflows.go
  - pkg/parser/remote_client.go
  - pkg/parser/remote_resolve_sha.go
comment_count: 1

Note

This comment is managed by comment memory.

Expand the saved memory block to view or edit the persistent context for this thread.
Edit only the text inside the backtick fences; workflow metadata and the footer are regenerated automatically.

Learn more about comment memory

🔎 Code quality review by PR Code Quality Reviewer · copilot · gpt50 · ~2 AIC · ⌖ ~1 AIC · ⊞ 1.6K · ◷
Comment /review to run again

@github-actions github-actions Bot 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.

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

Comment thread pkg/githubapi/public_get.go Outdated
}
}()

body, err := io.ReadAll(resp.Body)

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.

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.

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.

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.

@github-actions

Copy link
Copy Markdown
Contributor

🏗️ Design Decision Gate — ADR Required

This PR makes significant changes to core business logic (368 new lines in pkg/) but does not link an Architecture Decision Record (ADR).

📄 Draft ADR committed: docs/adr/71893-centralize-public-github-api-get-transport.md. Review and complete it before merging. Also correct its Date field; the draft shows 2026-05-14.

Decision found in the diff: add a shared githubapi.GetPublic(ctx, client, endpointURL) helper that returns a typed *HTTPStatusError. It replaces three copies of the unauthenticated GET code in pkg/cli/update_workflows.go, pkg/parser/remote_client.go and pkg/parser/remote_resolve_sha.go. URL escaping, timing, client timeouts and response parsing stay in the callers.

🔒 This PR cannot merge until an ADR is linked in the PR body.

📋 What to do next
  1. Review the draft ADR committed to your branch. It was generated from the PR diff.
  2. Complete the missing sections: add context the AI couldn't infer, refine the decision rationale, and check the alternatives (keep the per-caller copies, build a full public-API client, or return a plain string error).
  3. Commit the finalized ADR to docs/adr/ on your branch.
  4. Reference the ADR in this PR body by adding a line such as:

    ADR: ADR-71893: Centralize Public GitHub API GET Transport in githubapi Package

Once an ADR is linked in the PR body, this gate will re-run and verify the implementation matches the decision.

❓ Why ADRs Matter

"AI made me procrastinate on key design decisions. Because refactoring was cheap, I could always say 'I'll deal with this later.' Deferring decisions corroded my ability to think clearly."

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 Reference

An ADR must contain these four sections to be considered complete:

  • Context: What is the problem? What forces are at play?
  • Decision: What did you decide? Why?
  • Alternatives Considered: What else could have been done?
  • Consequences: What are the trade-offs (positive and negative)?

All ADRs are stored in docs/adr/ as Markdown files numbered by PR number.

🏗️ ADR gate enforced by Design Decision Gate 🏗️ · pi · opus55 · ~26 AIC · ⌖ ~36 AIC · ⊞ 1.9K · ◷
Comment /review to run again

@github-actions github-actions Bot 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.

Skills-Based Review 🧠

Applied /codebase-design (triage: refactor_cleanup) — clean, behavior-preserving extraction. Approving.

📋 Key Themes & Highlights

Verification performed

  • Confirmed go build/go vet succeed 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 recover StatusCode/Body via errors.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 to return body, err.
  • GetPublic closes 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 HTTPStatusError preserves backward-compatible string formatting while giving callers that need it structured access to StatusCode/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 in public_get.go isn't exercised by any test. Trivial and not worth blocking on, but a quick io.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

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.

🟢 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

@gh-aw-bot

Copy link
Copy Markdown
Collaborator

@copilot address the following outstanding work in one pass:

  1. Update this branch with the latest main using make merge-main, resolving any conflicts and preserving the intended changes.
  2. Review (pkg/githubapi/public_get.go:44): 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. - Consolidate public GitHub API GET fallback transport #71893 (comment)

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
Sous-chef work: eb850618a070d2bacd6cc5c9e294ab862d014eea7e7d97ee8c91b24fd04f1821
Sous-chef state: 0f7d1b8cc854ad05a048791e0b575339a912a9c2e924852a5b31285e71314206

Generated by 👨‍🍳 PR Sous Chef · pi · haiku45 · ~8 AIC · ⌖ ~8 AIC · ⊞ 1.1K · ◷
Comment /souschef to run again

Copilot AI and others added 3 commits October 25, 2026 14:06
…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>

Copilot AI commented Oct 25, 2026

Copy link
Copy Markdown
Contributor Author

@copilot address the following outstanding work in one pass:

  1. Update this branch with the latest main using make merge-main, resolving any conflicts and preserving the intended changes....

Merged latest main with make merge-main and pushed the fixes in 6ba63dc and 5bf3450. The inline size-limit thread has been addressed; local validation passed. As requested, I did not retrigger CI.

Copilot AI requested a review from gh-aw-bot October 25, 2026 14:37
@pelikhan
pelikhan merged commit 832e65a into main Oct 25, 2026
35 checks passed
@pelikhan
pelikhan deleted the copilot/duplicate-code-fix-github-api-get-fallback branch October 25, 2026 16:24
@github-actions

Copy link
Copy Markdown
Contributor

🎉 This pull request is included in a new release.

Release: v0.93.5

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

4 participants