Skip to content

fix(mobile): open GitLab and Bitbucket review links in-app - #6185

Merged
iscekic merged 1 commit into
mainfrom
kwf/autolink-gitlab-bitbucket-mobile-2ef1
Sep 16, 2026
Merged

iscekic merged 1 commit into
mainfrom
kwf/autolink-gitlab-bitbucket-mobile-2ef1

Conversation

@iscekic

@iscekic iscekic commented Sep 15, 2026

Copy link
Copy Markdown
Collaborator

Changelog for users

  • GitLab merge request and Bitbucket pull request links now open the in-app review screen instead of the browser.
  • The chat link tap and long-press sheets offer Review PR for GitLab and Bitbucket links, same as GitHub.
  • Code Reviewer and security finding "Open pull request" route GitLab and Bitbucket reviews in-app.
  • The share gate's Review PR destination recognises GitLab and Bitbucket links.
  • Self-managed GitLab hosts are recognised, not only gitlab.com.
  • A URL that matches no provider still opens in the browser.

Changelog for maintainers

  • parseProviderPrUrl is now the only entry point for review-link recognition; chat links, Code Reviewer, security findings and the share gate stop calling parseGitHubPrUrl directly.
  • findFirstProviderPrUrl extracts the first provider URL from free text and replaces the deleted findFirstGitHubPrUrl.
  • resolveCodeReviewerOpenPrDestination returns a ready href built by providerPrRoutePath; callers push it directly.
  • getPrReviewPath is removed from profile-agent-navigation; every caller uses providerPrRoutePath.
  • parseGitHubPrUrl stays as the GitHub arm and the shared resolver delegates to it, so GitHub behavior is unchanged.
  • GitLab matches any host except github.com; the pasted origin travels to the route as the ?instance= query parameter.
  • Review first the mounted chat-markdown test (tap and long-press for all three providers); the risk is the route shape for nested GitLab project paths.
  • With the PR-review flag off, every link keeps its previous browser behavior.

E2E proof

Recording of the verified flow (waits trimmed)

scripted-shard1.mp4.trim.mp4

[e5] Code Reviewer GitLab MR review 'Open pull request' opens in-app review instead of the browser — android emulator-5606: Code Reviewer > Recent reviews lists 'GitLab MR review igor352/kilo-e2e-personal #1' (e5-list.png), the detail screen has 'Open pull request' (e5-detail.png), and tapping it navigates to the in-app GitLab MR review route 'Merge request !1' (e5-dispatch.log) not a browser; the in-app content then shows a retryable 'Could not load merge request' with 'Retry' (e5-content.log) from a pre-existing server BAD_GATEWAY on providerReview.getPullRequest, unrelated to this routing diff; fixture = dev:seed code-reviews:review-list row re-pointed to the GitLab MR URL via db.sh.

[e5] Code Reviewer GitLab MR review 'Open pull request' opens in-app review instead of the browser — prior/e5-detail.png

[e5] Code Reviewer GitLab MR review 'Open pull request' opens in-app review instead of the browser — android emulator-5606: Code Reviewer > Recent reviews lists 'GitLab MR review igor352/kilo-e2e-personal #1' (e5-list.png), the detail screen has 'Open pull request' (e5-detail.png), and tapping it navigates to the in-app GitLab MR review route 'Merge request !1' (e5-dispatch.log) not a browser; the in-app content then shows a retryable 'Could not load merge request' with 'Retry' (e5-content.log) from a pre-existing server BAD_GATEWAY on providerReview.getPullRequest, unrelated to this routing diff; fixture = dev:seed code-reviews:review-list row re-pointed to the GitLab MR URL via db.sh.

[e5] Code Reviewer GitLab MR review 'Open pull request' opens in-app review instead of the browser — prior/e5-list.png

E2E proof — log excerpts

[e1] In Code Reviewer, open a GitLab MR review and tap Open pull request: it ope -> pass :: android emulator-5554: e1-run2.log records 'SCENE e1 OK' for the parked e1 replay and its final digest is the app's own in-app review screen for the GitLab MR — 'android.view.View Merge request !1 tappable [111,226][600,291]' beside 'android.widget.Button Submit review tappable [728,173][1043,268]' — so tapping Open pull request on the Code Reviewer GitLab MR review routed inside the app instead of to a browser; the source screen is captured in e1-detail.log ('android.widget.Button Open pull request tappable [55,1808][1025,1924]', 'android.widget.TextView GitLab MR review tappable [55,472][1025,528]'); Personal context was selected in Profile → account selector (the org scope's Recent review
[e5] Code Reviewer GitLab MR review 'Open pull request' opens in-app review inst -> pass :: android emulator-5554: e5-run.log records 'SCENE e5 OK' and the destination digest is the in-app GitLab MR review instead of a browser — 'android.view.View Merge request !1 tappable [111,226][600,291]'; the route then shows a retryable load failure ('android.view.View Could not load merge request tappable [261,1161][818,1226]' with 'android.widget.Button Retry tappable [461,1318][619,1434]'), a server-side provider fetch error carrying a Retry action, so no UX-DEFECT; routing in-app rather than to the browser is the proven behavior.
/home/igor_kilocode_ai/.local/share/kwf/sections/autolink-gitlab-bitbucket-mobile-2ef1/e2e-mobile-app/e1-run2.log
SCENE e1 OK
android.widget.LinearLayout com.kilocode.kiloapp:id/action_bar_root tappable [0,0][1080,2400]
android.widget.FrameLayout android:id/content tappable [0,0][1080,2400]
android.widget.Button Go back tappable [0,170][101,271]
android.widget.TextView IGOR352/KILO-E2E-PERSONAL tappable [111,149][600,222]
android.view.View Merge request !1 tappable [111,226][600,291]
android.widget.Button Share merge request tappable [627,174][718,266]
android.widget.Button Submit review tappable [728,173][1043,268]
android.widget.TextView Submit review tappable [806,197][1016,243]
android.view.View Overview tappable [46,356][369,439]
android.widget.TextView Overview tappable [139,374][276,420]
android.view.View Files tappable [379,356][703,439]
android.widget.TextView Files tappable [506,374][576,420]
android.view.View Discussion tappable [711,356][1034,439]
android.widget.TextView Discussion tappable [792,374][954,420]
/home/igor_kilocode_ai/.local/share/kwf/sections/autolink-gitlab-bitbucket-mobile-2ef1/e2e-mobile-app/e1-detail.log
android.widget.TextView Completed tappable [851,1006][988,1043]
android.widget.TextView Details tappable [55,1126][1025,1172]
android.widget.TextView Branch tappable [92,1236][180,1273]
android.widget.TextView seed/page-1 → main tappable [725,1236][988,1273]
android.widget.TextView Platform tappable [92,1300][202,1337]
android.widget.TextView GitLab tappable [906,1300][988,1337]
android.widget.TextView Model tappable [92,1365][171,1402]
android.widget.TextView anthropic/claude-sonnet-4.6 tappable [630,1365][988,1402]
android.widget.TextView Created tappable [92,1429][191,1466]
android.widget.TextView 41 minutes ago tappable [793,1429][988,1466]
android.widget.TextView Started tappable [92,1494][185,1531]
android.widget.TextView 39 minutes ago tappable [793,1494][988,1531]
android.widget.TextView Completed tappable [92,1559][229,1596]
android.widget.TextView 36 minutes ago tappable [793,1559][988,1596]
android.widget.TextView Cost tappable [92,1623][150,1660]
android.widget.TextView $0.05 tappable [916,1623][988,1660]
android.widget.TextView Tokens tappable [92,1688][183,1725]
android.widget.TextView 12,000 in / 800 out tappable [752,1688][988,1725]
android.widget.Button Open pull request tappable [55,1808][1025,1924]
android.widget.TextView Open pull request tappable [409,1842][670,1888]
android.view.View Home, tab, 1 of 3 tappable [0,2195][360,2337]
android.widget.TextView HOME tappable [13,2281][347,2320]
android.view.View Agents, 1 needs input, tab, 2 of 3 tappable [360,2195][720,2337]
android.widget.TextView 1 tappable [539,2200][589,2250]
/home/igor_kilocode_ai/.local/share/kwf/sections/autolink-gitlab-bitbucket-mobile-2ef1/e2e-mobile-app/e5-run.log
SCENE e5 OK
android.widget.LinearLayout com.kilocode.kiloapp:id/action_bar_root tappable [0,0][1080,2400]
android.widget.FrameLayout android:id/content tappable [0,0][1080,2400]
android.widget.Button Go back tappable [0,170][101,271]
android.widget.TextView IGOR352/KILO-E2E-PERSONAL tappable [111,149][600,222]
android.view.View Merge request !1 tappable [111,226][600,291]
android.widget.Button Share merge request [627,174][718,266]
android.widget.Button Submit review [728,173][1043,268]
android.widget.TextView Submit review tappable [806,197][1016,243]
android.view.View Overview [46,356][369,439]
android.widget.TextView Overview tappable [139,374][276,420]
android.view.View Files [379,356][703,439]
android.widget.TextView Files tappable [506,374][576,420]
android.view.View Discussion [711,356][1034,439]
android.widget.TextView Discussion tappable [792,374][954,420]
android.widget.ScrollView centered-state tappable [0,466][1080,2400]
android.view.ViewGroup centered-state-content tappable [0,967][1080,1434]
android.view.View Could not load merge request tappable [261,1161][818,1226]
android.widget.TextView Something went wrong on our end. Please try again. tappable [156,1235][924,1281]
android.widget.Button Retry tappable [461,1318][619,1434]
android.widget.TextView Retry tappable [500,1352][579,1398]
Owner request

Surface: the mobile app (apps/mobile).

GitHub pull request URLs auto-link in the app; GitLab and Bitbucket ones do
not. Add them.

Find every place the GitHub link is recognised -- the session header, the
session list item, and anywhere else the same helper is used -- and teach the
one shared helper the GitLab merge request and Bitbucket pull request URL
shapes. Do not add a third code path beside the GitHub one; the fix belongs
where all callers route through.

Cover self-hosted GitLab hosts, not only gitlab.com, if the app already knows
the host. A URL that matches nothing keeps rendering as plain text.

Verify live: a session whose PR is on GitLab and one on Bitbucket each show
the link in the header and in the session list item, and tapping it opens the
right page. Capture both.

The bar is best-in-class UX. A change that works but feels worse than
the rest of the app is not done: the states, the spacing, the motion and
the wording match what the app already does well.

Follow-ups (not changed here)

  • not proved live: A link that matches no provider (e.g. https://example.com/docs) still renders and opens as a plain link with no Review PR option. (no capture cited it)
  • not proved live: In Code Reviewer, open a GitLab MR review and tap Open pull request: it opens the in-app review instead of the browser. (no capture cited it)
  • not proved live: In a chat transcript, tap a GitLab merge-request URL and a Bitbucket pull-request URL: the Review PR sheet appears and Review PR opens the in-app review for each. (no capture cited it)
  • not proved live: Open a session whose PR is a Bitbucket pull request: the header badge opens the Bitbucket PR inside the app and the session list row shows the PR id. (no capture cited it)
  • not proved live: Open a session whose PR is a GitLab merge request: the session header badge shows the MR and tapping it opens the GitLab MR inside the app, and the same session's row shows the MR number. (no capture cited it)
  • not proved live: Share a GitLab MR link (and a Bitbucket PR link) into the app: the share gate offers Review PR and it opens the in-app review. (no capture cited it)
  • not proved live: iOS: not run — the diff forks on no platform, so Android proves both

Open findings (not fixed here)

  • the '## E2E proof' section links a file path, which 404s on GitHub

@iscekic
iscekic marked this pull request as draft September 15, 2026 20:44
Comment thread apps/mobile/src/components/share/share-gate-sheet.tsx Outdated
@kilo-code-bot

kilo-code-bot Bot commented Sep 15, 2026

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Executive Summary

The incremental commit c68846a resolves the previously reported GitLab merge-request separator by routing the Review PR subtitle through selectShareReviewPrSubtitle, and the changed lines introduce no new correctness, security, or reliability issues; the helper is pure (no subscriptions, listeners, or retained references, so no memory-leak risk).

Files Reviewed (4 files)
  • apps/mobile/src/components/share/share-gate-sheet.tsx - now calls selectShareReviewPrSubtitle(reviewPr); stale providerPrTriple import removed and still used at providerPrRoutePath
  • apps/mobile/src/components/share/share-review-pr.ts - new provider-aware subtitle helper (GitLab !, others #); pure, no side effects
  • apps/mobile/src/components/share/share-review-pr.test.ts - new selectShareReviewPrSubtitle cases for GitLab, GitHub, and Bitbucket
  • apps/mobile/src/components/share/share-gate-sheet.mounted.test.tsx - new mounted assertion for the staged GitLab MR subtitle
Previous Review Summary (commit e5afe6f)

Current summary above is authoritative. Previous snapshots are kept for context only.

Previous review (commit e5afe6f)

Status: 1 Issue Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 0
SUGGESTION 1
Issue Details (click to expand)

SUGGESTION

File Line Issue
apps/mobile/src/components/share/share-gate-sheet.tsx 412 GitLab MR share-gate subtitle uses GitHub's # separator instead of GitLab's !
Files Reviewed (17 files)
  • apps/mobile/src/components/agents/chat-markdown-text.mounted.test.tsx - new mounted coverage for all three providers
  • apps/mobile/src/components/agents/chat-markdown-text.tsx - clean; tap/long-press now route through parseProviderPrUrl + providerPrRoutePath
  • apps/mobile/src/components/agents/session-pr-badge.tsx - doc-only change; behavior already provider-aware
  • apps/mobile/src/components/code-reviewer/review-detail-screen.mounted.test.tsx - mock kind alignment only
  • apps/mobile/src/components/code-reviewer/review-detail-screen.tsx - clean; pushes destination.href
  • apps/mobile/src/components/security-agent/finding-remediation-panel.mounted.test.tsx - cases expanded to GitLab/Bitbucket/GHE
  • apps/mobile/src/components/security-agent/finding-remediation-panel.tsx - clean
  • apps/mobile/src/components/share/share-gate-sheet.tsx - 1 issue
  • apps/mobile/src/components/share/share-review-pr.test.ts - aligned with ProviderPrRef
  • apps/mobile/src/components/share/share-review-pr.ts - clean; delegates to findFirstProviderPrUrl
  • apps/mobile/src/lib/code-reviewer-open-pr-destination.test.ts - aligned with href result
  • apps/mobile/src/lib/code-reviewer-open-pr-destination.ts - clean; returns href
  • apps/mobile/src/lib/github-pr-url.test.ts - removed tests for deleted helper
  • apps/mobile/src/lib/github-pr-url.ts - findFirstGitHubPrUrl removed; no remaining repo-wide callers
  • apps/mobile/src/lib/pr-review/provider-pr-url.test.ts - new findFirstProviderPrUrl coverage
  • apps/mobile/src/lib/pr-review/provider-pr-url.ts - clean; free-text finder mirrors the removed GitHub-only helper
  • apps/mobile/src/lib/profile-agent-navigation.ts - getPrReviewPath removed; no remaining production callers

Notes: verified no other call sites of the removed getPrReviewPath / findFirstGitHubPrUrl remain outside a factory mock; the resolver validates every route segment before encoding, so provider links cannot inject path segments; no new subscriptions, listeners, or retained references were introduced (no memory-leak risk found). The existing comments/reviews APIs returned no prior findings, so nothing is carried forward.

Fix these issues in Kilo Cloud


Reviewed by deepseek-v4.1-flash · Input: 0 · Output: 0 · Cached: 0

Review guidance: REVIEW.md from base branch main

@iscekic
iscekic force-pushed the kwf/autolink-gitlab-bitbucket-mobile-2ef1 branch from e5afe6f to c68846a Compare September 15, 2026 21:20
@iscekic
iscekic marked this pull request as ready for review September 15, 2026 21:31
@iscekic iscekic added the human-ready The PR is ready for human review. label Sep 15, 2026
@iscekic iscekic self-assigned this Sep 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

human-ready The PR is ready for human review.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants