feat(github): implement PRReader + FileReader client (#80) #93
@@ -225,7 +225,7 @@ func (c *Client) doRequest(ctx context.Context, method, reqURL string, accept st
|
||||
timer := time.NewTimer(delay)
|
||||
select {
|
||||
case <-timer.C:
|
||||
timer.Stop() // no-op after fire, releases runtime resources promptly
|
||||
timer.Stop() // no-op after fire; kept for symmetry with the ctx.Done case
|
||||
case <-ctx.Done():
|
||||
timer.Stop()
|
||||
|
|
||||
return nil, ctx.Err()
|
||||
|
||||
@@ -81,7 +81,7 @@ func (c *Client) ListContents(ctx context.Context, owner, repo, path string) ([]
|
||||
if err := json.Unmarshal(body, &entries); err != nil {
|
||||
var single entry
|
||||
if err2 := json.Unmarshal(body, &single); err2 != nil {
|
||||
return nil, fmt.Errorf("parse contents JSON: %w", err2)
|
||||
return nil, fmt.Errorf("parse contents JSON: as array: %v; as object: %w", err, err2)
|
||||
}
|
||||
// Guard against empty objects ({}) or unexpected shapes that
|
||||
// unmarshal successfully but carry no useful data.
|
||||
|
||||
@@ -127,6 +127,9 @@ func (c *Client) GetPullRequestFiles(ctx context.Context, owner, repo string, nu
|
||||
// Returns nil (not an empty slice) when there are no statuses or check runs.
|
||||
// If the commit statuses endpoint fails (e.g. 404 for an unknown SHA), the
|
||||
// function returns immediately without attempting the check-runs endpoint.
|
||||
// If the check-runs endpoint fails after statuses were fetched successfully,
|
||||
// the function returns an error (not a partial result) so callers always get
|
||||
|
sonnet-review-bot
commented
[NIT] The **[NIT]** The `GetPullRequestFiles` comment says 'Returns nil (not an empty slice) when the PR has no changed files' but if the first page returns an empty array, `allFiles` remains nil — this is correct. However the GitHub API actually returns an empty array for PRs with 0 changed files (valid edge case), so the nil vs empty distinction in the doc comment is accurate but subtle. No code change needed.
|
||||
// either a complete view or a clear error signal.
|
||||
func (c *Client) GetCommitStatuses(ctx context.Context, owner, repo, sha string) ([]vcs.CommitStatus, error) {
|
||||
var result []vcs.CommitStatus
|
||||
|
||||
@@ -192,7 +195,7 @@ func mapCheckRunStatus(conclusion *string) string {
|
||||
case "failure", "action_required", "timed_out":
|
||||
|
sonnet-review-bot
commented
[MINOR] The **[MINOR]** The `mapCheckRunStatus` mapping treats `cancelled`, `skipped`, and `neutral` as `"success"` (non-blocking). This is a policy decision that should be documented more prominently — `cancelled` in particular could reasonably be mapped to `failure` in some contexts. The comment `// non-blocking` is brief; a note explaining the design rationale (e.g. 'these do not indicate a blocking failure per GitHub's check suite semantics') would help future maintainers.
|
||||
return "failure"
|
||||
case "cancelled", "skipped", "neutral":
|
||||
return "success" // non-blocking
|
||||
return "success" // non-blocking: these do not indicate a blocking failure per GitHub check suite semantics
|
||||
case "stale", "waiting":
|
||||
return "pending"
|
||||
default:
|
||||
|
||||
[MINOR] After
resp.Body.Close()is called for a successful response, ifio.ReadAllreturns an error, the body is already closed which is correct, but the success path reads up tomaxResponseBytes+1bytes viaio.LimitReader. This is the intentional over-read trick to detect exceeding the limit, which is correct. However, on the error path for non-2xx responses (line 245),errBody, _ := io.ReadAll(...)silently discards the read error. While acceptable in practice since it's for error body capture, the convention in this codebase is to check all error returns. This is minor since the worst case is an empty error body.