| 432 | } |
| 433 | |
| 434 | func (g *githubProvider) fetchDiff( |
| 435 | ctx context.Context, |
| 436 | requestURL string, |
| 437 | token string, |
| 438 | ) (string, error) { |
| 439 | req, err := http.NewRequestWithContext(ctx, http.MethodGet, requestURL, nil) |
| 440 | if err != nil { |
| 441 | return "", xerrors.Errorf("create github diff request: %w", err) |
| 442 | } |
| 443 | req.Header.Set("Accept", "application/vnd.github.diff") |
| 444 | req.Header.Set("X-GitHub-Api-Version", "2022-11-28") |
| 445 | req.Header.Set("User-Agent", "coder-chat-diff") |
| 446 | if token != "" { |
| 447 | req.Header.Set("Authorization", "Bearer "+token) |
| 448 | } |
| 449 | |
| 450 | resp, err := g.httpClient.Do(req) |
| 451 | if err != nil { |
| 452 | return "", xerrors.Errorf("execute github diff request: %w", err) |
| 453 | } |
| 454 | defer resp.Body.Close() |
| 455 | |
| 456 | if resp.StatusCode != http.StatusOK { |
| 457 | if rlErr := checkRateLimitError(resp, g.clock, "X-Ratelimit-Reset"); rlErr != nil { |
| 458 | return "", rlErr |
| 459 | } |
| 460 | body, readErr := io.ReadAll(io.LimitReader(resp.Body, 8192)) |
| 461 | if readErr != nil { |
| 462 | return "", xerrors.Errorf("github diff request failed with status %d", resp.StatusCode) |
| 463 | } |
| 464 | return "", xerrors.Errorf( |
| 465 | "github diff request failed with status %d: %s", |
| 466 | resp.StatusCode, |
| 467 | strings.TrimSpace(string(body)), |
| 468 | ) |
| 469 | } |
| 470 | |
| 471 | // Read one extra byte beyond MaxDiffSize so we can detect |
| 472 | // whether the diff exceeds the limit. LimitReader stops us |
| 473 | // allocating an arbitrarily large buffer by accident. |
| 474 | buf, err := io.ReadAll(io.LimitReader(resp.Body, MaxDiffSize+1)) |
| 475 | if err != nil { |
| 476 | return "", xerrors.Errorf("read github diff response: %w", err) |
| 477 | } |
| 478 | if len(buf) > MaxDiffSize { |
| 479 | return "", ErrDiffTooLarge |
| 480 | } |
| 481 | return string(buf), nil |
| 482 | } |
| 483 | |
| 484 | // reviewStats holds aggregated review statistics for a PR. |
| 485 | type reviewStats struct { |