From 69be3b353403848a8b0c38b1b612c2c10703e803 Mon Sep 17 00:00:00 2001 From: Bruno Bergher Date: Tue, 4 Nov 2025 15:04:05 +0000 Subject: [PATCH] Ensures the Create PR button is only shown for Github repos --- src/core/webview/ClineProvider.ts | 7 +++- .../webview/__tests__/ClineProvider.spec.ts | 1 + src/shared/ExtensionMessage.ts | 1 + src/utils/__tests__/git.spec.ts | 33 +++++++++++++++++++ src/utils/git.ts | 18 ++++++++++ webview-ui/src/components/chat/ChatView.tsx | 5 +-- 6 files changed, 62 insertions(+), 3 deletions(-) diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts index 8d690e208e..f97ca2577b 100644 --- a/src/core/webview/ClineProvider.ts +++ b/src/core/webview/ClineProvider.ts @@ -74,7 +74,7 @@ import { MdmService } from "../../services/mdm/MdmService" import { fileExistsAtPath } from "../../utils/fs" import { setTtsEnabled, setTtsSpeed } from "../../utils/tts" -import { getWorkspaceGitInfo } from "../../utils/git" +import { getWorkspaceGitInfo, isGitHubRepository } from "../../utils/git" import { getWorkspacePath } from "../../utils/path" import { OrganizationAllowListViolationError } from "../../utils/errors" @@ -1892,6 +1892,9 @@ export class ClineProvider // This includes defaultBranch, which is populated even for worktrees. const isGitRepository = Object.keys(gitInfo).length > 0 + // Check if the repository is specifically a GitHub repository + const isGithubRepository = isGitHubRepository(gitInfo.repositoryUrl) + return { version: this.context.extension?.packageJSON?.version ?? "", apiConfiguration, @@ -2023,6 +2026,7 @@ export class ClineProvider openRouterUseMiddleOutTransform, featureRoomoteControlEnabled, isGitRepository, + isGithubRepository, } } @@ -2258,6 +2262,7 @@ export class ClineProvider } })(), isGitRepository: false, // Will be computed in getStateToPostToWebview + isGithubRepository: false, // Will be computed in getStateToPostToWebview } } diff --git a/src/core/webview/__tests__/ClineProvider.spec.ts b/src/core/webview/__tests__/ClineProvider.spec.ts index f44fec74b4..b7293da02f 100644 --- a/src/core/webview/__tests__/ClineProvider.spec.ts +++ b/src/core/webview/__tests__/ClineProvider.spec.ts @@ -563,6 +563,7 @@ describe("ClineProvider", () => { featureRoomoteControlEnabled: false, checkpointTimeout: DEFAULT_CHECKPOINT_TIMEOUT_SECONDS, isGitRepository: false, + isGithubRepository: false, } const message: ExtensionMessage = { diff --git a/src/shared/ExtensionMessage.ts b/src/shared/ExtensionMessage.ts index 4bcf8b9f0b..336c5c8997 100644 --- a/src/shared/ExtensionMessage.ts +++ b/src/shared/ExtensionMessage.ts @@ -363,6 +363,7 @@ export type ExtensionState = Pick< taskSyncEnabled: boolean featureRoomoteControlEnabled: boolean isGitRepository: boolean + isGithubRepository: boolean } export interface ClineSayTool { diff --git a/src/utils/__tests__/git.spec.ts b/src/utils/__tests__/git.spec.ts index 5b10d51787..7afb6b6665 100644 --- a/src/utils/__tests__/git.spec.ts +++ b/src/utils/__tests__/git.spec.ts @@ -12,6 +12,7 @@ import { extractRepositoryName, getWorkspaceGitInfo, convertGitUrlToHttps, + isGitHubRepository, } from "../git" import { truncateOutput } from "../../integrations/misc/extract-text" @@ -898,6 +899,38 @@ describe("extractRepositoryName", () => { }) }) +describe("isGitHubRepository", () => { + it("should return true for github.com HTTPS URLs", () => { + expect(isGitHubRepository("https://github.com/user/repo.git")).toBe(true) + expect(isGitHubRepository("https://github.com/user/repo")).toBe(true) + }) + + it("should return true for github.com SSH URLs", () => { + expect(isGitHubRepository("git@github.com:user/repo.git")).toBe(true) + expect(isGitHubRepository("ssh://git@github.com/user/repo.git")).toBe(true) + }) + + it("should return true for GitHub URLs with different casing", () => { + expect(isGitHubRepository("https://GitHub.com/user/repo.git")).toBe(true) + expect(isGitHubRepository("https://GITHUB.COM/user/repo.git")).toBe(true) + }) + + it("should return false for non-GitHub URLs", () => { + expect(isGitHubRepository("https://gitlab.com/user/repo.git")).toBe(false) + expect(isGitHubRepository("https://bitbucket.org/user/repo.git")).toBe(false) + expect(isGitHubRepository("git@gitlab.com:user/repo.git")).toBe(false) + }) + + it("should return false for undefined or empty URLs", () => { + expect(isGitHubRepository(undefined)).toBe(false) + expect(isGitHubRepository("")).toBe(false) + }) + + it("should handle sanitized GitHub URLs", () => { + expect(isGitHubRepository("https://github.com/user/repo")).toBe(true) + }) +}) + describe("getWorkspaceGitInfo", () => { const workspaceRoot = "/test/workspace" diff --git a/src/utils/git.ts b/src/utils/git.ts index d1bb719ce6..ff10c181ef 100644 --- a/src/utils/git.ts +++ b/src/utils/git.ts @@ -211,6 +211,24 @@ export function extractRepositoryName(url: string): string { } } +/** + * Checks if a git repository URL is from GitHub + * @param repositoryUrl The repository URL to check + * @returns true if the URL is from GitHub, false otherwise + */ +export function isGitHubRepository(repositoryUrl?: string): boolean { + if (!repositoryUrl) { + return false + } + + try { + // Check if the URL contains github.com + return repositoryUrl.toLowerCase().includes("github.com") + } catch { + return false + } +} + /** * Gets git repository information for the current VSCode workspace * @returns Git repository information or empty object if not available diff --git a/webview-ui/src/components/chat/ChatView.tsx b/webview-ui/src/components/chat/ChatView.tsx index 31e841b6cb..c3b06e05e0 100644 --- a/webview-ui/src/components/chat/ChatView.tsx +++ b/webview-ui/src/components/chat/ChatView.tsx @@ -125,6 +125,7 @@ const ChatViewComponent: React.ForwardRefRenderFunction