fix(clients): default GitLab clones to HTTPS#24612

open6
main
takeover/pr-13351
opened21d agobyJJulius Marminge
View on GitHubTwo-way sync enabledPR last imported 2d ago

GitLab repositories selected through Add Project → Clone now start with the host’s HTTPS/web URL. Explicit SSH URLs remain available through Git URL; other forge defaults are unchanged. Updated servers already recover some SSH failures through HTTPS fallback; this skips that first SSH attempt and supports older servers without the fallback. SSH-only private repositories require the explicit SSH path. Self-hosted HTTP URLs remain HTTP.

Fixes #13350.

Original description by @Mnigos

Fixes #13350.

Choosing a GitLab repository through Add Project → Clone used SSH even after signing in with glab over HTTPS. Without a registered SSH key, lookup succeeded but cloning failed.

GitLab's host definition now defaults to HTTPS, using the same shared clone-selection path as other HTTPS hosts. Web, desktop, and mobile inherit that choice; pasted URLs and other providers keep their existing behavior. Self-hosted GitLab still needs credentials configured for its host.

The existing shared regression test uses GitLab's actual web-URL shape. It fails with the SSH default and passes with the fix; all 18 project-operation tests pass. Client-runtime and GitLab package typechecks and targeted lint also pass. Private-repository credential-helper authentication was not exercised; this change only selects the clone URL.

Original fix and reproduction by @Mnigos in #13351. Maintainer takeover by Claude Opus 5.5 and Claude Fable 5.1 through T3 Code, independently reviewed by Claude Opus 5.5 and GPT-6.1-Sol through the Codex harness.

Takeover

Original fix and reproduction by @Mnigos in #13351. Rebuilt on current main because the forge definition moved to shared/; the one-field implementation is retained, and the tests use current shared clone selection. No GitLab special cases were added outside the forge package. No scratch scripts or captures are committed. Pixel-diff amplification driver is uploaded separately.

Evidence

Full fixture matrix · capture index, traces and all drivers · reproduction recipe · proof audit

Matrix rowsVerification
G1/G2Real GitLab picker: before SSH rejection → HTTPS fallback success; after direct HTTPS success
C1Real GitHub picker: HTTPS success on both
C2Explicit GitLab SSH submitted unchanged on both; real SSH rejection/fallback, after DNS failure and recorded Retry success
P1Tracked clone exercised, including Retry
G3/G4/C3/C4/S2Helper fixtures, focused tests and source; nested/custom-host URLs and exact HTTP scheme disclosed
P2/E1/S1Older-server path, additional entry/gate paths and direct-service protocols source-only
M1/M2Native iOS and Android unverified

Recordings: enter repository → lookup → choose destination → clone → terminal outcome. Timestamped steps and actual submitted URLs are narrated in the linked clips; complete timeline. GitLab’s official SSH endpoint on port 443 was used because port 22 hangs on this VM.

FlowBeforeAfterSettled / recovery
G1-G2BeforeAfterBefore settled / After settled
C1BeforeAfter—
C2BeforeAfterReal Retry

Environment: real web app, Chromium 148 / Playwright 1.60, Xvfb, 1280×900, DPR 1, dark, reduced motion, fixed relative-time clock, DejaVu Sans fallback. Fresh sandbox home, seeding disabled; live userdata untouched.

What else changed in the captures: original GitLab interaction clips ended with stale Git metadata; the separate settled clips and primary images supersede those endpoints. Corrected GitLab and GitHub frames are pixel-identical. C2 input has a faint blurred background label difference (1,427 pixels, max channel delta 9/255); its after outcome shows a real DNS failure, retained with separate successful Retry. No private-authentication or successful SSH-authentication claim is made.

Verification log
  • Tests: project-operation file 6 → 7; GitLab regression fails with SSH and passes with HTTPS. 48 focused tests across projects, forge definition and registry passed. Targeted lint/format, GitLab and client-runtime typechecks passed.
  • Reviews: round 1 MERGE / FIX_FIRST; SSH-only picker objection resolved against the authorized HTTPS default and explicit SSH path. Round 2 MERGE / MERGE. No added regex/parser or dependencies.
  • Proof audit: SUFFICIENT; inspected all primary images, 27 diffs and 15 recordings. Independent real HTTPS clone succeeded; reproduced input delta 681 pixels, max 2/255, none above 16.
  • Final head / main integration: e8f29cc13c merges 843f4e3529 without rebasing. All 48 scoped tests pass on this head. The captured web, shared clone runtime, GitLab package and mobile project-flow blobs are unchanged from captured after revision; main additions are outside those paths.
  • CI: At handoff, 8 checks successful, 19 pending, 0 failing on final head; no bot comments yet. CI/review monitoring returns to the dispatcher because this is a delegated child task. Original-fork checks are not claimed for this replacement.
  • Unverified: native iOS/Android, separate Electron shell, light/narrow viewports, private-repository authentication, authenticated SSH, older-server blocking clone, direct service/MCP protocols, relay/tunnel and multiple environments. Only the web capture and source/shared tests are claimed.
  • All owned capture/audit processes stopped; temporary worktree and scratch removed before handoff.
  • Implementation/tests: Claude Opus 5.5 through T3 Code; independent review: GPT-6.1-Sol (Codex) and Claude Opus 5.5; capture/proof audit: GPT-6.1-Sol through Codex.

Fixes pingdotgg/t3code#13350

Checks

20 successful · 13 skipped
All checks passed
19d07ef

Added 3 commits

  • fix(gitlab): GitLab projects clone over HTTPS by default589c618
  • test(client-runtime): GitLab clones default to HTTPS while SSH hosts keep SSH9d6eb27
  • Merge main into takeover/pr-13351e8f29cc
Synced from GitHub

Approvability

Verdict: Approved at 19d07ef

Macroscope's review found this PR approvable — The specified revisions have no net changes. GitLab cloning still defaults to SSH, so this comparison introduces no product-default change or additional risk.

Notes:

  • No code objects were reviewed. Approvability was decided on eligibility alone.

You can add or adjust custom eligibility rules. Learn more.

Synced from GitHub

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

ProviderMetricMain baselineThis PRImpactPR ceiling
CodexTotal thread wire5.0 KiB5.0 KiB0 B (0.0%)6.8 KiB✅
CodexThread snapshot wire3.8 KiB3.8 KiB0 B (0.0%)4.9 KiB✅
CodexLive turn WebSocket wire1.2 KiB1.2 KiB0 B (0.0%)2.0 KiB✅
CodexLive turn WebSocket decoded21.5 KiB21.5 KiB0 B (0.0%)24.4 KiB✅
CodexLive turn messages110 (0.0%)8✅
ClaudeTotal thread wire5.0 KiB5.0 KiB0 B (0.0%)6.8 KiB✅
ClaudeThread snapshot wire3.8 KiB3.8 KiB0 B (0.0%)4.9 KiB✅
ClaudeLive turn WebSocket wire1.2 KiB1.2 KiB0 B (0.0%)2.0 KiB✅
ClaudeLive turn WebSocket decoded21.9 KiB21.9 KiB0 B (0.0%)24.4 KiB✅
ClaudeLive turn messages110 (0.0%)8✅

Other scenarios

All 64 scenario measurements match main.

All 64 scenario measurements
ProviderScenarioMetricMain baselineThis PRImpactPR ceiling
Codexshort turn resumeWebSocket decoded10.5 KiB10.5 KiB0 B (0.0%)12.7 KiB✅
Codexshort turn resumeWebSocket messages220 (0.0%)2✅
Codexlong turn running, cold openHTTP decoded281.7 KiB281.7 KiB0 B (0.0%)302.7 KiB✅
Codexlong turn running, cold openrows75750 (0.0%)75✅
Codexlong turn running, history pageHTTP decoded92.4 KiB92.4 KiB0 B (0.0%)107.4 KiB✅
Codexlong turn running, history pagerows75750 (0.0%)75✅
Codexlong turn finished, cold openHTTP decoded381.5 KiB381.5 KiB0 B (0.0%)410.2 KiB✅
Codexlong turn finished, cold openrows1511510 (0.0%)151✅
Codexlong turn finished, socket cold openWebSocket decoded381.6 KiB381.6 KiB0 B (0.0%)410.2 KiB✅
Codexlong turn finished, socket cold openWebSocket messages220 (0.0%)2✅
Codexlong turn finished, socket cold openrows1511510 (0.0%)151✅
Codexlong turn finished, work pageHTTP decoded186.2 KiB186.2 KiB0 B (0.0%)200.2 KiB✅
Codexlong turn finished, work pagerows1501500 (0.0%)150✅
Codexidle thread resumeWebSocket decoded65 B65 B0 B (0.0%)200 B✅
Codexidle thread resumeWebSocket messages110 (0.0%)1✅
Codexfleet shell snapshotHTTP decoded42.4 KiB42.4 KiB0 B (0.0%)53.7 KiB✅
Codexfleet shell snapshotrows27270 (0.0%)27✅
Codexfleet shell subscribeWebSocket decoded65 B65 B0 B (0.0%)200 B✅
Codexfleet shell subscribeWebSocket messages110 (0.0%)1✅
Codexfleet shell resume checkHTTP decoded18 B18 B0 B (0.0%)100 B✅
Codexfleet shell resume checkrows0000✅
Codexstale shell reloadHTTP decoded42.4 KiB42.4 KiB0 B (0.0%)53.7 KiB✅
Codexstale shell reloadrows27270 (0.0%)27✅
Codexstale shell resumeWebSocket decoded140 B140 B0 B (0.0%)400 B✅
Codexstale shell resumeWebSocket messages220 (0.0%)2✅
Codexstale todo list cold openHTTP decoded72.4 KiB72.4 KiB0 B (0.0%)83.0 KiB✅
Codexstale todo list cold openrows75750 (0.0%)75✅
Codexstale todo list cold opennodes220 (0.0%)4✅
Codexstale todo list cold opensubagents220 (0.0%)4✅
Codexstale todo list cold openplans110 (0.0%)2✅
Codexstale todo list cold openproviderTurns110 (0.0%)2✅
Codexstale todo list cold opencheckpoints110 (0.0%)2✅
Claudeshort turn resumeWebSocket decoded10.6 KiB10.6 KiB0 B (0.0%)12.7 KiB✅
Claudeshort turn resumeWebSocket messages220 (0.0%)2✅
Claudelong turn running, cold openHTTP decoded283.3 KiB283.3 KiB0 B (0.0%)302.7 KiB✅
Claudelong turn running, cold openrows75750 (0.0%)75✅
Claudelong turn running, history pageHTTP decoded93.4 KiB93.4 KiB0 B (0.0%)107.4 KiB✅
Claudelong turn running, history pagerows75750 (0.0%)75✅
Claudelong turn finished, cold openHTTP decoded384.2 KiB384.2 KiB0 B (0.0%)410.2 KiB✅
Claudelong turn finished, cold openrows1511510 (0.0%)151✅
Claudelong turn finished, socket cold openWebSocket decoded384.3 KiB384.3 KiB0 B (0.0%)410.2 KiB✅
Claudelong turn finished, socket cold openWebSocket messages220 (0.0%)2✅
Claudelong turn finished, socket cold openrows1511510 (0.0%)151✅
Claudelong turn finished, work pageHTTP decoded188.1 KiB188.1 KiB0 B (0.0%)200.2 KiB✅
Claudelong turn finished, work pagerows1501500 (0.0%)150✅
Claudeidle thread resumeWebSocket decoded66 B66 B0 B (0.0%)200 B✅
Claudeidle thread resumeWebSocket messages110 (0.0%)1✅
Claudefleet shell snapshotHTTP decoded42.9 KiB42.9 KiB0 B (0.0%)53.7 KiB✅
Claudefleet shell snapshotrows27270 (0.0%)27✅
Claudefleet shell subscribeWebSocket decoded66 B66 B0 B (0.0%)200 B✅
Claudefleet shell subscribeWebSocket messages110 (0.0%)1✅
Claudefleet shell resume checkHTTP decoded18 B18 B0 B (0.0%)100 B✅
Claudefleet shell resume checkrows0000✅
Claudestale shell reloadHTTP decoded42.9 KiB42.9 KiB0 B (0.0%)53.7 KiB✅
Claudestale shell reloadrows27270 (0.0%)27✅
Claudestale shell resumeWebSocket decoded140 B140 B0 B (0.0%)400 B✅
Claudestale shell resumeWebSocket messages220 (0.0%)2✅
Claudestale todo list cold openHTTP decoded73.4 KiB73.4 KiB0 B (0.0%)83.0 KiB✅
Claudestale todo list cold openrows75750 (0.0%)75✅
Claudestale todo list cold opennodes220 (0.0%)4✅
Claudestale todo list cold opensubagents220 (0.0%)4✅
Claudestale todo list cold openplans110 (0.0%)2✅
Claudestale todo list cold openproviderTurns110 (0.0%)2✅
Claudestale todo list cold opencheckpoints110 (0.0%)2✅

Baseline: 0bc993a · PR result: c6f8a19 · Source CI: success

Scenario and decoded snapshot size

10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.

  • Codex decoded thread snapshot: 108.5 KiB
  • Claude decoded thread snapshot: 108.8 KiB

Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.

Synced from GitHub

Explain Change →

Walkthrough

GitLab’s default clone transport changes from SSH to HTTPS. A test checks that getDefaultCloneUrl returns the GitLab HTTPS URL when an SSH URL is also supplied.

Changes: Clone transport selection

Layer / File(s)Summary
GitLab default and URL selection tests
packages/source-control-gitlab/src/shared/definition.ts, packages/client-runtime/src/operations/projects.test.ts
GitLab’s default clone transport changes to HTTPS. A test checks that GitLab URL selection returns HTTPS when an SSH URL is also supplied.

Estimated code review effort: 2 (Simple) | ~8 minutes

Change: Bug fix · Severity of issue fixed: Medium

Suggested reviewers: macroscopeapp

Merge Risk: External image Low · previous review c6f8a

GitLab clones through Add Project → Clone now default to the project's web URL over HTTPS. This is the intended behavior and should work on standard GitLab hosts. There is a small residual risk on instances that expose a separate HTTP clone endpoint, so the author should confirm the behavior on one such instance.

Pre-merge checks: Passed 4

Check nameStatusExplanation
Title checkPassedThe title names the main change: GitLab clones made through Add Project → Clone now default to HTTPS. It uses a conventional commit prefix and is specific to the changeset. The title is short, single-…
Description checkPassedThe description follows the repository template. It has a clear problem statement, a change explanation, a scope section that links issue #13350 and states the bug, and a verification section with tes…
Linked Issues checkPassedThe only direct linked issue is #13350. Its coding requirement is that GitLab clones selected through Add Project → Clone use HTTPS, so the glab credential helper can authenticate without an SSH key. …
Out of Scope Changes checkPassedThe whole-PR diff touches two files. definition.ts changes one GitLab field and adds a comment explaining the HTTPS credential-helper rationale. projects.test.ts adds one GitLab regression asserti…
Full details: Title check

Explanation

The title names the main change: GitLab clones made through Add Project → Clone now default to HTTPS. It uses a conventional commit prefix and is specific to the changeset. The title is short, single-sentence, and not vague.

Full details: Description check

Explanation

The description follows the repository template. It has a clear problem statement, a change explanation, a scope section that links issue #13350 and states the bug, and a verification section with tests, typechecks, lint, and recordings. The template's Problem section is only implied by the opening paragraph and the original description, and the Scope section does not explicitly justify the absence of an issue, but the issue is linked. The description is mostly complete and is lengthy, with heavy media content and an unusually large evidence section. The template asks for concise verification and the description spends most of its length on evidence links and image tables, but the required information is present.

Full details: Linked Issues check

Explanation

The only direct linked issue is #13350. Its coding requirement is that GitLab clones selected through Add Project → Clone use HTTPS, so the glab credential helper can authenticate without an SSH key. The whole-PR diff (base to head) changes defaultCloneTransport in packages/source-control-gitlab/src/shared/definition.ts from "ssh" to "https". The shared getDefaultCloneUrl in packages/client-runtime/src/operations/projects.ts then selects repository.url for GitLab. The added assertion in projects.test.ts checks that a GitLab provider with url: "https://gitlab.com/group/subgroup/project" and an SSH URL returns the HTTPS URL. This covers the issue's suggested minimum fix (include GitLab in the HTTPS default). The issue's optional git_protocol discovery is not implemented, and the issue does not require it as a minimum. Private-repository authentication is not tested, which the issue does not require as a coding test. The apps/mobile impact is covered by the shared clone-selection path, which the PR does not modify separately.

Full details: Out of Scope Changes check

Explanation

The whole-PR diff touches two files. definition.ts changes one GitLab field and adds a comment explaining the HTTPS credential-helper rationale. projects.test.ts adds one GitLab regression assertion to the existing shared clone-selection test. Both changes implement #13350. No unrelated source, configuration, or dependency changes appear in the diff. The PR description's claims about self-hosted HTTP URLs and explicit SSH entry through Git URL concern existing behavior that the diff does not alter.

Finishing Touches

Generate unit tests (beta)

  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Added 3 commits

  • Merge remote-tracking branch 'origin/main' into takeover/pr-133517838ad0
  • test(client-runtime): drop the SSH-default case that only restates configc6f8a19
  • revert(gitlab): keep SSH as the GitLab clone default19d07ef
CcoderabbitaiBotreviewed2d ago
Synced from GitHub
External image Additional comments: 1

packages/source-control-gitlab/src/shared/definition.ts-46-46: 1

46-46: External image Major · Data Integrity & Integration · Heavy lift

External image Unverified finding Verification ran but could not confirm this finding. It is shown for review, not as a verified issue.

Use GitLab’s HTTP clone URL

This change selects repository.url, but GitLabCli.ts maps that field from web_url and discards http_url_to_repo. GitLab supports a separate HTTP(S) clone endpoint. If only that endpoint accepts Git traffic, provider-selected clones now fail. Preserve the clone URL through the repository contract and select it here. (raw.githubusercontent.com)

External image Review info

External image Run configuration

External image Commits

Reviewing files that changed from the base of the PR and between e8f29cc13cd2d5b493eb9ef66170fdb2fc139777 and c6f8a19a7312be3a303c1f6af8b6ca59f65735c8.

External image Files selected for processing: 2

  • packages/client-runtime/src/operations/projects.test.ts
  • packages/source-control-gitlab/src/shared/definition.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 4 remain after this review.

The automated pipeline stopped on this pull request and will not merge it:

in the real app the problem is still there, and the rework changed nothing:

No code change: the proof result shows the reported bug is already fixed. On both commits, with glab set up for HTTPS and no SSH key (the setup in issue #13350), the GitLab picker sent the SSH URL and the clone finished with an HTTPS origin. The issue was that the clone failed; it now succeeds because main's clone fallback (#30142) retries a refused SSH key or untrusted host key over HTTPS with the glab credential helper. The proof treats the SSH-first request as the problem, but HTTPS-first is exactly what the previous review rejected as worse than main: clones run with terminal prompts off and nothing retries HTTPS as SSH, so users with only SSH access would break. Keeping SSH first is deliberate. The pasted git@ URL staying unchanged is the intended behavior on both commits and was never in scope. The branch has no net diff against main and should be closed as superseded, with #13350 marked fixed by #30142. Making GitLab HTTPS-first anyway would need an HTTPS-to-SSH retry in the same change, and that is a maintainer decision.

It stays open for a person to finish or close.