Skip to content

feat: add GitLab git provider - #25396

Closed
johnstcn wants to merge 27 commits into
mainfrom
cj/gitsync-gitlab
Closed

feat: add GitLab git provider#25396
johnstcn wants to merge 27 commits into
mainfrom
cj/gitsync-gitlab

Conversation

@johnstcn

@johnstcn johnstcn commented May 15, 2026

Copy link
Copy Markdown
Member

Fixes CODAGT-146

Adds a GitLab provider implementation for coderd/externalauth/gitprovider, enabling gitsync (chatd PR sync) to work with GitLab repositories.

Note: while this is a 2.7K line PR, a significant portion of this is tests and fixtures.

Still TODO

  • Testing with gitlab.com and self-hosted GitLab instances.

Changes

  • Implement Provider interface for GitLab using the official gitlab.com/gitlab-org/api/client-go library
  • Handle GitLab-specific concepts: nested groups/subgroups, merge requests (vs pull requests), SCP-style SSH remotes
  • Add go-vcr integration tests with recorded cassettes for replay without network/tokens
  • Add edge-case unit tests for fallback paths (HeadSHA, unparsable WebURL, trailing newlines)
  • Use OAuthToken (Bearer) auth, matching Coder's external auth flow
  • Return error from New() constructor instead of panicking on invalid URLs
  • Check CompareTimeout flag in FetchBranchDiff to avoid silently returning incomplete diffs

Known limitations

Approved, ChangesRequested, and ReviewerCount have semantic gaps vs the GitHub provider due to GitLab API differences. Tracked in CODAGT-440.

Review-driven changes

Changes made after deep review:

  • P1: Fixed token type from PrivateToken to OAuthToken (would have caused 401s for all OAuth-configured GitLab integrations)
  • P2: Converted panic in constructor to proper error return, propagated through New() and Config.Git()
  • P2: Added CompareTimeout check to prevent silent incomplete diffs
  • P3: Moved RateLimitPadding to gitprovider.go for discoverability
  • P3: Pre-allocated strings.Builder in FetchBranchDiff
  • Nits: cmp.Or, strings.CutPrefix, newGitLab casing, contextaction param rename

Note

This PR was authored by a human with assistance from Coder Agents.

@johnstcn johnstcn self-assigned this May 15, 2026
@johnstcn johnstcn changed the title feat: add GitLab support to externalauth/gitprovider feat(coderd/externalauth/gitprovider): add GitLab provider May 15, 2026
@johnstcn

Copy link
Copy Markdown
Member Author

/coder-agents-review

@coder-agents-review coder-agents-review 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.

Well-structured GitLab provider with strong VCR-based testing infrastructure, clean nested-group handling, and correct SCP remote parsing. The implementation is proportional to the problem and the test-to-code ratio is solid. Pariston tried to build a case that the wrong framing was chosen and couldn't: "Framing #1 (missing implementation) is correct."

Severity count: 1 P2, 8 P3, 5 Nit.

The P2 is a memory safety gap: FetchPullRequestDiff reads the entire HTTP response body into memory before the MaxDiffSize check runs, while the GitHub provider bounds reads with io.LimitReader. This is a library constraint, not a logic error, but it removes the memory cap that the package contract implies.

Several findings converge on silent error handling: resolveExternalAuth swallows Config.Git() constructor errors (9 reviewers flagged this independently), and three zero-valued fields (Additions, Deletions, Commits) are stored as known-valid in the database without being tracked in CODAGT-440.

Two test gaps: CompareTimeout (added as a P2 review fix) has no test, and the FetchBranchDiff integration test has a leniency guard that silently passes in VCR replay mode.

🤖 This review was automatically generated with Coder Agents.

Comment thread coderd/externalauth/gitprovider/gitlab.go Outdated
Comment thread coderd/externalauth/gitprovider/gitlab.go
Comment thread coderd/exp_chats.go Outdated
Comment thread coderd/externalauth/gitprovider/gitlab.go Outdated
// be incorrect. To fix this, this function would need
// access to the external auth configs.
gp := gitprovider.New("github", "", nil)
gp, _ := gitprovider.New("github", "", nil)

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.

P3 [DEREM-7] This hardcodes "github" as the fallback provider. With GitLab now supported, any GitLab-hosted GitRemoteOrigin stored in ChatDiffStatus will fail ParseRepositoryOrigin (host mismatch) and produce no branch URL. The pre-existing TODO acknowledges the GitHub Enterprise gap; GitLab widens it.

This needs a human decision: either accept the gap and document it, or iterate over configured providers. The fix requires access to external auth configs at the db2sdk layer, which is a broader refactor.

(Mafuuu P3, Ryosuke P3)

🤖

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Acknowledged. This is pre-existing behavior unrelated to the GitLab provider addition; the db2sdk.go fallback to "github" needs a broader refactor (iterating over configured providers). Out of scope for this PR.

🤖 Generated with Coder Agents

Comment thread coderd/externalauth/gitprovider/gitlab.go Outdated
Comment thread coderd/externalauth/gitprovider/gitlab.go Outdated
Comment thread coderd/externalauth/gitprovider/gitlab_test.go Outdated
Comment thread coderd/externalauth/gitprovider/gitlab_test.go Outdated
Comment thread coderd/externalauth/gitprovider/gitlab.go Outdated
@johnstcn johnstcn changed the title feat(coderd/externalauth/gitprovider): add GitLab provider feat(coderd/externalauth): add GitLab git provider May 18, 2026
@johnstcn johnstcn changed the title feat(coderd/externalauth): add GitLab git provider feat: add GitLab git provider May 18, 2026
@johnstcn

Copy link
Copy Markdown
Member Author

/coder-agents-review

@coder-agents-review coder-agents-review 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.

Strong progress. 11 of 13 R1 posted findings addressed, all fixes verified by the panel. The P2 unbounded-read fix (DEREM-3) is correct and matches the GitHub pattern. The commit stats population (DEREM-6) is a genuine improvement. The error logging (DEREM-5) makes misconfiguration diagnosable. Chopper on the fix quality: "Error handling is thorough. Every library call goes through wrapError."

Severity count (new this round): 1 P2, 2 P3, 2 Nit.

The P2 is a regression from the DEREM-3 fix: switching to raw HTTP for FetchPullRequestDiff lost the library's *gitlab.ErrorResponse wrapping, so wrapError can no longer detect 429/403 rate limits on that path. The gitsync worker relies on *RateLimitError to back off; without it, a rate-limited GitLab instance gets hammered. Kite independently confirmed this and provided a concrete fix.

R1 contested findings: DEREM-7 (hardcoded "github" in db2sdk) was closed by the panel (4/7 accept), though 3 reviewers noted that a deferral without a ticket is a drop. This needs a human decision: file a ticket or explicitly accept the gap. DEREM-15 (context.Background) was closed 7/7; the author's defense was verified.

🤖 This review was automatically generated with Coder Agents.

Comment thread coderd/externalauth/gitprovider/gitlab.go
Comment thread coderd/externalauth/gitprovider/gitlab_test.go Outdated
Comment thread coderd/externalauth/gitprovider/gitlab_test.go
Comment thread coderd/externalauth/gitprovider/gitlab_test.go Outdated
Comment thread coderd/exp_chats.go
@johnstcn
johnstcn marked this pull request as ready for review May 18, 2026 20:40
Copilot AI review requested due to automatic review settings May 18, 2026 20:40
@johnstcn

Copy link
Copy Markdown
Member Author

/coder-agents-review

Comment thread coderd/externalauth/gitprovider/gitlab_integration_test.go

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.

Pull request overview

Adds a GitLab implementation for coderd/externalauth/gitprovider so chat diff/gitsync flows can resolve GitLab repositories, merge requests, and diffs.

Changes:

  • Introduces GitLab provider logic for MR status, diff fetching, branch-to-MR resolution, and URL parsing/building.
  • Updates provider construction to return errors and threads context through gitsync provider resolution.
  • Adds GitLab unit/integration tests with go-vcr cassettes and supporting dependency/config updates.

Reviewed changes

Copilot reviewed 29 out of 30 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
.gitattributes Marks GitLab cassette YAML as generated.
.github/workflows/typos.toml Excludes GitLab testdata from typo checks.
go.mod Adds GitLab client and go-vcr dependencies.
go.sum Updates dependency checksums.
coderd/database/db2sdk/db2sdk.go Adapts to new gitprovider.New signature.
coderd/exp_chats.go Updates chat diff provider resolution and missing-token handling.
coderd/externalauth/externalauth.go Changes Config.Git to return provider construction errors.
coderd/externalauth/gitprovider/gitprovider.go Adds GitLab provider dispatch and shared rate-limit padding.
coderd/externalauth/gitprovider/github.go Moves shared rate-limit constant out of GitHub provider.
coderd/externalauth/gitprovider/github_test.go Updates tests for new constructor return values.
coderd/externalauth/gitprovider/gitlab.go Implements GitLab git provider.
coderd/externalauth/gitprovider/gitlab_test.go Adds GitLab unit tests.
coderd/externalauth/gitprovider/gitlab_integration_test.go Adds VCR-backed GitLab integration tests.
coderd/externalauth/gitprovider/testdata/gitlab_cassettes/** Adds recorded GitLab API fixtures.
coderd/x/gitsync/gitsync.go Passes context into provider resolution.
coderd/x/gitsync/gitsync_test.go Updates resolver mocks for context-aware signature.
coderd/x/gitsync/worker_test.go Updates worker test resolver mocks.
Comments suppressed due to low confidence (1)

coderd/externalauth/gitprovider/gitlab.go:400

  • This has the same self-hosted subpath problem as repository-origin parsing: if the GitLab instance is served under a path prefix, the prefix remains in u.Path and becomes part of the parsed owner. For a PR like https://gitlab.example.com/gitlab/group/repo/-/merge_requests/1, the provider would return owner gitlab/group, causing follow-up API calls and generated URLs to target the wrong project path.
	path := strings.TrimPrefix(u.Path, "/")
	path = strings.TrimSuffix(path, "/")

	// Find "-/merge_requests/NUMBER" in the path.
	const mrMarker = "-/merge_requests/"
	idx := strings.Index(path, mrMarker)
	if idx < 0 {
		return PRRef{}, false
	}

	// Everything before the marker (minus trailing slash) is the project path.
	projPath := path[:idx]

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread coderd/externalauth/gitprovider/gitlab.go
Comment thread coderd/externalauth/externalauth.go
Comment thread coderd/externalauth/gitprovider/gitlab.go Outdated
Comment thread coderd/externalauth/gitprovider/gitlab.go
Comment thread coderd/externalauth/gitprovider/gitlab_integration_test.go
Comment thread coderd/externalauth/gitprovider/gitlab.go
Comment thread coderd/externalauth/gitprovider/gitlab_integration_test.go
Comment thread coderd/externalauth/gitprovider/gitlab.go
Comment thread coderd/externalauth/gitprovider/gitlab.go Outdated

@coder-agents-review coder-agents-review 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.

All prior findings addressed. The P2 rate-limit regression (DEREM-25) is fixed correctly: FetchPullRequestDiff now checks 403/429 status codes and parses retry headers before the generic error path, matching the GitHub provider's pattern. The oversize test gap (DEREM-28) is filled. The duplicate test (DEREM-26) is removed. Clock injection (DEREM-27) is applied to the existing rate limit tests. Kite on the overall quality: "Well-decomposed PR. The constructor error propagation fix is the right structural change; it forces every caller to handle failure explicitly."

Severity count (new this round): 1 P3, 1 Nit.

The P3 is a test coverage gap in the approval/review-state mapping. The Nit is the same time.Now() pattern in the newly-added 429OnRawDiffEndpoint test that DEREM-27 fixed in its siblings.

Across three rounds, 18 findings were posted, 16 fixed, 2 contested and closed by panel vote. The implementation is solid, well-tested, and proportional to the problem. Chopper: "Error handling and diagnostic signal are solid across the new GitLab provider."

🤖 This review was automatically generated with Coder Agents.

Comment thread coderd/externalauth/gitprovider/gitlab_integration_test.go
Comment thread coderd/externalauth/gitprovider/gitlab_test.go Outdated
@coderagents

coderagents Bot commented May 19, 2026

Copy link
Copy Markdown
Contributor

Documentation Check

Updates Needed

  • docs/ai-coder/agents/platform-controls/git-providers.md - This page explicitly states "Only github type external auth providers are supported today." This must be updated now that GitLab is supported. The note should be removed or rewritten to list both GitHub and GitLab as supported providers.
  • docs/ai-coder/agents/platform-controls/git-providers.md - Add a GitLab configuration section (parallel to the existing "GitHub Enterprise configuration" section) documenting self-hosted GitLab setup for the diff viewer. Self-hosted instances need API_BASE_URL set (the code strips /api/v4 and defaults to https://gitlab.com).
  • docs/ai-coder/agents/platform-controls/git-providers.md - Document known limitations: Approved, ChangesRequested, and ReviewerCount have semantic gaps vs the GitHub provider due to GitLab API differences (tracked in CODAGT-440).

Automated review via Coder Agents

Copy link
Copy Markdown
Member Author

Third item addressed in 2eafcbaa41: added a "Known limitations" section documenting the Approved, ChangesRequested, and ReviewerCount semantic gaps with a reference to CODAGT-440.

Generated by Coder Agent

Comment thread docs/ai-coder/agents/platform-controls/git-providers.md Outdated
@johnstcn

Copy link
Copy Markdown
Member Author

/coder-agents-review

@coder-agents-review

coder-agents-review Bot commented May 25, 2026

Copy link
Copy Markdown
Contributor

Review posted | Chat
Requested: 2026-05-25 14:53 UTC by @johnstcn
Spend: $134.14 / $158.90

Review history
  • R4 (2026-05-25), 7 Nit, 2 P2, 13 P3, COMMENT. Review
  • R5 (2026-05-25): 4 reviewers, 7 Nit, 2 P2, 15 P3, APPROVE. Review

deep-review v0.5.0 | Round 5 | a4afb9d..f642982

Last posted: Round 5, 24 findings (2 P2, 15 P3, 7 Nit), APPROVE. Review

Finding inventory

Findings

# Sev Status Location Summary Round Reviewer Posted
DEREM-1 P3 Author fixed (0977b25) gitlab_integration_test.go:740 Vacuous test path when expectNil=false and ref is nil R1 Netero Yes
DEREM-2 Nit Author fixed (0977b25) gitlab.go:41 fmt.Errorf instead of xerrors.Errorf R1 Netero, Ryosuke Yes
DEREM-3 P2 Author fixed (afe59a5) gitlab.go:193 FetchPullRequestDiff reads unbounded response body before MaxDiffSize check R1 Chopper P2, Hisoka P2, Kurapika P2, Pariston P2, Razor P2, Zoro P2, Kite P3, Knov P3, Killua Note Yes
DEREM-4 P3 Author fixed (0a19642) gitlab.go:245 FetchBranchDiff builds full oversize string before rejecting R1 Hisoka P3, Meruem P3, Killua P3 Yes
DEREM-5 P3 Author fixed (afe59a5) exp_chats.go:4158 resolveExternalAuth silently swallows Git() constructor errors R1 Chopper P3, Hisoka P3, Kite P3, Knov P3, Leorio P3, Mafuuu P3, Meruem P3, Razor P3, Ryosuke P2 Yes
DEREM-6 P3 Author fixed (c85b9eb) gitlab.go:131 Additions/Deletions/Commits hardcoded to 0, not tracked in CODAGT-440 R1 Kite P2, Luffy P2, Mafuuu P2, Knov P3, Razor P3, Ryosuke P3, Zoro Note Yes
DEREM-7 P3 Author contested; panel closed R2 (4/7 accept, human decision needed) db2sdk.go:1956 ChatDiffStatus hardcodes "github" provider, GitLab origins get no branch URL R1 Mafuuu P3, Ryosuke P3 Yes
DEREM-8 P3 Author fixed (0a19642) gitlab.go:235 CompareTimeout error path has no test R1 Bisky P3, Chopper P3 Yes
DEREM-9 P3 Author fixed (0a19642) gitlab_integration_test.go:803 FetchBranchDiff test leniency guard silent-pass in VCR replay R1 Bisky P2 Yes
DEREM-10 P3 Author fixed (0977b25) gitprovider.go:175 New() doc comment stale after signature change R1 Leorio P3 Yes
DEREM-11 P3 Author fixed (0977b25) externalauth.go:120 Config.Git() doc comment omits error return R1 Leorio P3, Razor Nit Yes
DEREM-12 P3 Author fixed (afe59a5) gitlab.go:416 xerrors.As pattern: use errors.AsType (Go 1.26) R1 Ging-Go P3 Yes
DEREM-13 Nit Author fixed (0977b25) gitlab.go:373 NormalizePullRequestURL trim set missing semicolon R1 Gon Nit, Pariston Nit, Robin P3, Razor Nit, Zoro Nit Yes
DEREM-14 P4 Dropped by orchestrator (short functions, providers may diverge) gitlab.go:433 parseGitLabRetryAfter duplicates ParseRetryAfter R1 Razor P4, Robin P3, Zoro Note No
DEREM-15 Nit Author contested; panel closed R2 (7/7 accept) gitlab_test.go:43 Unit tests use context.Background() instead of t.Context() R1 Ging-Go P3 Yes
DEREM-16 Nit Author fixed (afe59a5) gitlab_test.go:213 var+errors.As should use errors.AsType in tests R1 Ging-Go P3 Yes
DEREM-17 Note Dropped by orchestrator (naming preference, no functional impact) gitlab.go:454 mapGitLabState has redundant GitLab prefix R1 Gon No
DEREM-18 Nit Dropped by orchestrator (calculation visible 3 lines below) gitlab.go:243 Magic number 20 in pre-allocation estimate R1 Gon No
DEREM-19 Nit Dropped by orchestrator (context makes meaning clear) gitlab.go:71 Comment says "pid" without defining it R1 Gon No
DEREM-20 P4 Dropped by orchestrator (theoretical, GitLab name restrictions prevent) gitlab.go:386 URL-building methods don't path-escape owner/repo R1 Kurapika P3 No
DEREM-21 Nit Dropped by orchestrator (package-private helper, both branches visible in-file) gitlab.go:414 wrapError doc comment vague R1 Leorio No
DEREM-22 Nit Dropped by orchestrator (empty token unreachable in production) gitlab.go:62 reqOpts doc doesn't mention empty-token behavior R1 Leorio No
DEREM-23 Nit Dropped by orchestrator (5-line function, pure organization) github.go:161 escapePathPreserveSlashes belongs in gitprovider.go R1 Zoro No
DEREM-24 Nit Dropped by orchestrator (existing TODO covers broader issue) db2sdk.go:1956 Error from gitprovider.New discarded with blank identifier R1 Meruem No
DEREM-25 P2 Author fixed (15892bd) gitlab.go:241 FetchPullRequestDiff raw HTTP path does not detect rate limits on 429/403 R2 Netero, Kite P2 Yes
DEREM-26 P3 Author fixed (15892bd) gitlab_test.go:348 Duplicate test: TestGitLabCompareTimeout duplicates TestGitLabFetchBranchDiff/CompareTimeout R2 Netero, Bisky Note, Kite P3 Yes
DEREM-27 Nit Author fixed (15892bd) gitlab_test.go:251 Rate limit tests use time.Now() instead of injected quartz clock R2 Netero Yes
DEREM-28 P3 Author fixed (15892bd) gitlab_test.go:43 FetchBranchDiff has no oversize test (estimation guard and post-build check both untested) R2 Bisky P3 Yes
DEREM-29 Nit Author fixed (15892bd) exp_chats.go:4145 resolveExternalAuth doc comment omits error/nil-provider return paths R2 Razor Yes
DEREM-30 Nit Author fixed (85e3d3b) gitlab_test.go:347 429OnRawDiffEndpoint test uses time.Now() instead of quartz mock (incomplete DEREM-27 fix) R3 Netero, Mafu-san P2 Yes
DEREM-31 P3 Author fixed (f642982) gitlab_integration_test.go:595 FetchPullRequestStatus tests never assert Approved, ReviewerCount, or ChangesRequested R3 Bisky P3 Yes
DEREM-32 P3 Dropped by orchestrator (scope creep, token resolution code not changed in PR) exp_chats.go:3959 Token resolution conflates no-token with nil-token from any cause R3 Mafuuu P3 No
CRF-1 P3 Open gitlab.go:120 ListMergeRequestDiffs fetches at most 100 entries without pagination, silently undercounting additions/deletions for 100+ file MRs R5 Mafuuu P3 Yes
CRF-2 P3 Open gitlab.go:342 FetchBranchDiff omits response body on non-200 errors, unlike FetchPullRequestDiff R5 Mafuuu P3, Chopper P3 Yes

Contested and acknowledged

DEREM-7 (P3, db2sdk.go:1956) - ChatDiffStatus hardcodes "github" provider

  • Finding: With GitLab now supported, GitLab-hosted origins in ChatDiffStatus will fail ParseRepositoryOrigin (host mismatch) and produce no branch URL. The fix requires iterating over configured providers.
  • Author defense: Pre-existing behavior unrelated to the GitLab provider addition. The fix requires a broader refactor (iterating over configured providers at the db2sdk layer) and is out of scope for this PR.
  • Panel closure (R2, 4/7 accept): Four reviewers (Chopper, Hisoka, Kite, Pariston) accept the defense: the code predates this PR, the consequence is cosmetic (missing branch URL, not data loss), and the fix requires threading configs into a different layer. Three reviewers (Mafuuu, Meruem, Razor) accept the scope argument but note that a deferral without a ticket is indistinguishable from a drop. This needs a human decision: either file a ticket or explicitly accept the gap.

DEREM-15 (Nit, gitlab_test.go:43) - context.Background() instead of t.Context()

  • Finding: Nine occurrences of context.Background() in unit tests.
  • Author defense: The current code already uses t.Context() throughout. The finding targeted stale diff lines.
  • Panel closure (R2, 7/7 accept): All seven reviewers verified the current code uses t.Context() at every call site. Zero occurrences of context.Background(). Finding targeted stale R1 diff lines.

Round log

Round 1

Panel. 1 P2, 8 P3, 5 Nit new. 10 dropped. Reviewed against 6d7fb07..37ed044.

Round 2

Panel. R1: 11 addressed, 2 contested (DEREM-7 closed 4/7, DEREM-15 closed 7/7). 1 P2, 1 P3, 1 Nit (Netero) + 1 P3, 1 Nit (panel) new. Reviewed against 6d7fb07..afe59a5.

Round 3

Panel. R2: 5 addressed. 1 P3, 1 Nit new. 1 dropped (scope creep). Reviewed against 2732378..b7d5be2.

Round 4

BLOCKED. DEREM-31 silent. No review.

Round 5

Panel. R3: DEREM-31 addressed, DEREM-30 addressed. 2 P3 new. Reviewed against a4afb9d..f642982.

About deep-review

CRF = Coder Review Finding (P0-P4, Nit, Note)

Reviewer Focus
Bisky tests
Chopper ops/errors
Churn-guard change verification
Ging language modernization
Gon naming
Hisoka edge cases
Killua perf
Kite change integrity
Knov contracts
Knuckle SQL
Kurapika security
Leorio docs
Luffy product
Mafu-san process
Mafuuu contracts
Melody dispatch/pairing
Meruem structural
Nami frontend
Netero mechanical checks
Pariston premise testing
Pen-botter product gaps
Razor verification
Robin duplication
Ryosuke Go arch
Takumi concurrency
Zoro shape

🤖 Managed by Coder Agents.

@coder-agents-review coder-agents-review 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 blocked. DEREM-31 (P3, FetchPullRequestStatus tests never assert Approved, ReviewerCount, or ChangesRequested) has not been addressed or responded to. The thread was resolved in the GitHub UI without a reply or code change.

DEREM-30 (Nit, time.Now in 429OnRawDiffEndpoint) was fixed in 85e3d3b.

Further review is blocked until DEREM-31 receives a response: fix the test gap, contest the finding with a technical defense, or acknowledge it with a reason.

🤖 This review was automatically generated with Coder Agents.

@johnstcn

Copy link
Copy Markdown
Member Author

Review blocked. DEREM-31 (P3, FetchPullRequestStatus tests never assert Approved, ReviewerCount, or ChangesRequested) has not been addressed or responded to. The thread was resolved in the GitHub UI without a reply or code change.

DEREM-30 (Nit, time.Now in 429OnRawDiffEndpoint) was fixed in 85e3d3b.

Further review is blocked until DEREM-31 receives a response: fix the test gap, contest the finding with a technical defense, or acknowledge it with a reason.

🤖 This review was automatically generated with Coder Agents.

f642982

@johnstcn
johnstcn marked this pull request as draft May 25, 2026 14:52
@johnstcn

Copy link
Copy Markdown
Member Author

/coder-agents-review

@coder-agents-review coder-agents-review 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.

All prior findings addressed across five rounds. DEREM-31 (approval test assertions) fixed in f642982. The test suite is comprehensive: ~1,400 lines of tests against ~750 lines of implementation, covering edge cases (HeadSHA fallback, oversize diffs, compare timeout, rate limits on both library and raw HTTP paths, self-hosted URL routing), VCR integration tests against four fixture MRs, and newly-added approval field assertions. Mafu-san: "The pattern repeated with DEREM-3, where the fix propagated to FetchBranchDiff too, not just the cited location."

Severity count (new this round): 2 P3.

Both are minor gaps in the new code. CRF-1: ListMergeRequestDiffs fetches one page (100 entries) without pagination, so MRs with 100+ files get undercounted additions/deletions while ChangedFiles is correct. CRF-2: FetchBranchDiff drops the response body on non-200 errors while its sibling FetchPullRequestDiff includes up to 8 KiB of the body for diagnostics.

Across 5 rounds: 20 findings posted, 18 fixed, 2 contested/closed by panel. The implementation is solid and well-tested.

🤖 This review was automatically generated with Coder Agents.

// The commits endpoint does not return per-commit stats, so we
// count +/- lines from the unified diff returned by this endpoint.
var additions, deletions int32
diffs, _, err := g.client.MergeRequests.ListMergeRequestDiffs(

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.

P3 [CRF-1] ListMergeRequestDiffs fetches with PerPage: 100 but does not paginate. For MRs with 100+ files, Additions and Deletions are summed from only the first page, while ChangedFiles (from mr.ChangesCount) is correct. This creates an inconsistency: "150 files changed, +200/-50" when the real totals could be higher.

The GitHub provider reads additions/deletions directly from the pull request API response (no pagination needed). Here, the MR API does not expose aggregate counts, so file diffs must be iterated. Fix: either paginate until resp.NextPage == 0, or add a comment documenting the 100-file cap so future readers know it is intentional.

(Mafuuu P3)

🤖

if rlErr := checkRateLimitError(resp, g.clock, "RateLimit-Reset"); rlErr != nil {
return "", rlErr
}
return "", g.wrapError(

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.

P3 [CRF-2] Non-200 errors from the compare endpoint produce "unexpected status 404" with no response body. The sibling FetchPullRequestDiff (line 253) reads up to 8 KiB of the body and includes it: "unexpected status 404: Branch not found". GitLab's error bodies contain actionable information (project not found, branch not found, insufficient permissions). The asymmetry makes branch-diff failures harder to diagnose.

Fix: mirror the pattern from FetchPullRequestDiff:

body, _ := io.ReadAll(io.LimitReader(resp.Body, 8192))
return "", g.wrapError(
    xerrors.Errorf("unexpected status %d: %s", resp.StatusCode, strings.TrimSpace(string(body))),
    "compare branches",
)

(Mafuuu P3, Chopper P3)

🤖

@johnstcn

Copy link
Copy Markdown
Member Author

Broke this out into a stack for review:

1 #25651 main Refactor: shared helpers + signature changes (12 files, +340/-170)
2 #25652 cj/gitsync-gitlab-1 GitLab provider + unit tests + docs (7 files, +1206/-9)
3 #25653 cj/gitsync-gitlab-2 VCR integration tests + cassettes (19 files, +2600)

@johnstcn johnstcn closed this May 25, 2026
@github-actions github-actions Bot locked and limited conversation to collaborators May 25, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants