# fix\(gitlab\): accept merge request URLs from self-hosted hosts · PR \#23848 · pingdotgg/t3code

[View on GitCafe](https://git.cafe/pingdotgg/t3code/pull/23848)

Repository: [pingdotgg/t3code](https://git.cafe/pingdotgg/t3code)

Visibility: public

State: open

Source repository: Unavailable fork

Source branch: r13/a125-accept-merge-request-urls-from-self-host

Target branch: main

Head commit: c52430b51673d79baf739fa3bddc787934192632

[Discussion and reviews](https://git.cafe/pingdotgg/t3code/pull/23848)

[Commits](https://git.cafe/pingdotgg/t3code/pull/23848/commits?format=markdown)

[Files changed](https://git.cafe/pingdotgg/t3code/pull/23848/diffs?format=markdown)

## Description

---

## Problem

A merge request URL from a self-hosted GitLab isn't recognized when the host name doesn't contain "gitlab" or the instance serves plain `http`. Take `https://code.example.com/group/project/-/merge_requests/42`:

- In a new thread's branch picker, there is no "Checkout" row for it. The picker only offers to create a branch named after the URL.
- In the "Checkout change request" dialog, it is rejected as invalid input: "Use a change request URL, checkout command, 123, or #123."

The cause is the GitLab client's reference pattern in `packages/source-control-gitlab/src/client/definition.ts`. It requires `https` and the word `gitlab` in the host name, so `parsePullRequestReference` returns `null` for these URLs, and both the picker and the dialog only act on a non-null result.

The rest of the app already handles these hosts. `parseChangeRequestUrl` in `@t3tools/shared` matches the `/-/merge_requests/<n>` path on any host, and the GitLab provider marks self-hosted remotes as GitLab when `glab` is signed in to them (#15395).

## Change

One regex. It now accepts `http` or `https` and any host, and still requires the `/-/merge_requests/<n>` path:

```diff
-const CHANGE_REQUEST_REFERENCE =
-  /^https:\/\/[^/\s]*gitlab[^/\s]*\/.+\/-\/merge_requests\/(\d+)(?:[/?#].*)?$/i;
+const CHANGE_REQUEST_REFERENCE = /^https?:\/\/[^/\s]+\/.+\/-\/merge_requests\/(\d+)(?:[/?#].*)?$/i;
```

The `/-/merge_requests/` path is GitLab's own, and no other host definition matches it. The Forgejo definition already accepts `https?` on any host the same way. Which provider then resolves the URL is still decided by the project's repository identity on the server. This change doesn't touch that.

## Scope and approval

A focused parsing fix with no prior issue. It touches one client definition and adds one test. No server, contract or settings changes.

## Verification

New test in `packages/client-runtime/src/pullRequestLinkInput.test.ts`: `parsePullRequestReference` returns `https://code.example.com/group/project/-/merge_requests/42` and `http://git.internal/group/sub/project/-/merge_requests/7` unchanged.

- With main's `definition.ts`, both cases fail (`expected null to be '...'`). The other 14 tests in the file pass.
- On this branch, all 16 pass.
- `tsc-rs --noEmit` passes in `packages/source-control-gitlab` and `packages/client-runtime`. `vp lint` and `vp fmt --check` pass on both changed files.

![The two new cases failing with main's definition.ts](https://gist.githubusercontent.com/only21mil/5af3a839c31d61be0bd7be9195094758/raw/08e349cd7ee310606ca5429d7123d04040d12e52/test-fails-on-main.png)

![All 16 tests in the file passing on this branch](https://gist.githubusercontent.com/only21mil/5af3a839c31d61be0bd7be9195094758/raw/08e349cd7ee310606ca5429d7123d04040d12e52/test-passes-on-branch.png)

Real app: production builds of main and this branch (`vp build` for web, `vp pack` for the server) on Linux, each with fresh state, in Chrome. The project is a local repository whose `origin` is `https://code.example.com/group/demo-project.git`. Nothing contacts that host. In a new thread I open the branch picker and paste the URL. Then I open the dialog through `#1` and paste the URL into its field.

Main: the picker offers only "Create new ref".

![Main: the branch picker offers only to create a ref named after the URL](https://gist.githubusercontent.com/only21mil/5af3a839c31d61be0bd7be9195094758/raw/08e349cd7ee310606ca5429d7123d04040d12e52/picker-before.png)

This branch: the picker offers "Checkout change request" for the URL.

![This branch: the branch picker offers Checkout change request for the URL](https://gist.githubusercontent.com/only21mil/5af3a839c31d61be0bd7be9195094758/raw/08e349cd7ee310606ca5429d7123d04040d12e52/picker-after.png)

Main: the dialog rejects the URL as invalid input.

![Main: the dialog says to use a change request URL, checkout command, 123 or #123](https://gist.githubusercontent.com/only21mil/5af3a839c31d61be0bd7be9195094758/raw/08e349cd7ee310606ca5429d7123d04040d12e52/dialog-before.png)

This branch: the dialog accepts the URL and asks the server to resolve it. No `glab` is installed or signed in on this machine, so the project's provider is "unknown" and the lookup fails with that error.

![This branch: the dialog sends the URL to the server, which has no provider for this project](https://gist.githubusercontent.com/only21mil/5af3a839c31d61be0bd7be9195094758/raw/08e349cd7ee310606ca5429d7123d04040d12e52/dialog-after.png)

Not checked:

- A real self-hosted GitLab with `glab` signed in. On such a host #15395 marks the project as GitLab, and the server resolves the URL with `glab mr view -- <url>`. I could not run that without an account.
- An `http` URL in the app. The test covers it.
- The desktop app, macOS, Windows and mobile. The changed code is a shared client regex.

## Prior PRs

#13246 by @Luca-Lucidera made the same two changes, any host and plain `http`, when this regex still lived in `apps/web/src/pullRequestReference.ts`. It was closed on 2026-10-14 for size: 546 lines across 16 files, including shared remote parsing and this URL handling. The maintainer asked for a much smaller fix limited to its SSH custom-port bug. This PR carries forward only the regex change, now in the GitLab client definition. It leaves out that PR's stricter path check, which also rejects `/-/merge_requests/` inside a query string.

#15395 by @TonybynMp4 (issue #15390) made bare numbers resolve on self-hosted GitLab hosts whose name lacks "gitlab". This PR fixes the same host-name assumption for pasted URLs. #13351 by @Mnigos changes another line of the same file and does not touch this hunk.

Production fix, tests, PR description and images written with Claude Opus 5.5 in T3 Code Nightly.

🤖 Generated with Claude Opus 5.5 in T3 Code Nightly

