From 9ec147db6751ec60d0a80578f8ef01767fc0db69 Mon Sep 17 00:00:00 2001 From: Moritz Bitsch Date: Tue, 16 Dec 2025 09:48:20 +0000 Subject: [PATCH] Update Copilot sign-up URL based on verification domain (#44085) Use the url crate to extract the domain from the verification URI and construct the appropriate Copilot sign-up URL for GitHub or GitHub Enterprise. Release Notes: - Improved github enterprise (ghe) copilot sign in --- Cargo.lock | 1 + crates/copilot/Cargo.toml | 1 + crates/copilot/src/sign_in.rs | 44 ++++++++++++++++++++++++++++++++--- 3 files changed, 43 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b43be6986b89bcd121416ded247e5bd944628cca..4858c4ae01c7bdea2eaf46fba87707d3a2e0af24 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3672,6 +3672,7 @@ dependencies = [ "task", "theme", "ui", + "url", "util", "workspace", "zlog", diff --git a/crates/copilot/Cargo.toml b/crates/copilot/Cargo.toml index 459abda17573d66287e2c8ca0b995292acaf163b..3a1706a7a679fbc14eafbeac953d842cda9f65c8 100644 --- a/crates/copilot/Cargo.toml +++ b/crates/copilot/Cargo.toml @@ -52,6 +52,7 @@ ui.workspace = true util.workspace = true workspace.workspace = true itertools.workspace = true +url.workspace = true [target.'cfg(windows)'.dependencies] async-std = { version = "1.12.0", features = ["unstable"] } diff --git a/crates/copilot/src/sign_in.rs b/crates/copilot/src/sign_in.rs index 0bcb11e18be1994ea92703973ad1278c5d5aa4f8..20e31525a8fdb09fce04934d3445d51ba4226a2e 100644 --- a/crates/copilot/src/sign_in.rs +++ b/crates/copilot/src/sign_in.rs @@ -6,6 +6,7 @@ use gpui::{ Subscription, Window, WindowBounds, WindowOptions, div, point, }; use ui::{ButtonLike, CommonAnimationExt, ConfiguredApiCard, Vector, VectorName, prelude::*}; +use url::Url; use util::ResultExt as _; use workspace::{Toast, Workspace, notifications::NotificationId}; @@ -152,6 +153,7 @@ pub struct CopilotCodeVerification { focus_handle: FocusHandle, copilot: Entity, _subscription: Subscription, + sign_up_url: Option, } impl Focusable for CopilotCodeVerification { @@ -183,11 +185,22 @@ impl CopilotCodeVerification { .detach(); let status = copilot.read(cx).status(); + // Determine sign-up URL based on verification_uri domain if available + let sign_up_url = if let Status::SigningIn { + prompt: Some(ref prompt), + } = status + { + // Extract domain from verification_uri to construct sign-up URL + Self::get_sign_up_url_from_verification(&prompt.verification_uri) + } else { + None + }; Self { status, connect_clicked: false, focus_handle: cx.focus_handle(), copilot: copilot.clone(), + sign_up_url, _subscription: cx.observe(copilot, |this, copilot, cx| { let status = copilot.read(cx).status(); match status { @@ -201,10 +214,30 @@ impl CopilotCodeVerification { } pub fn set_status(&mut self, status: Status, cx: &mut Context) { + // Update sign-up URL if we have a new verification URI + if let Status::SigningIn { + prompt: Some(ref prompt), + } = status + { + self.sign_up_url = Self::get_sign_up_url_from_verification(&prompt.verification_uri); + } self.status = status; cx.notify(); } + fn get_sign_up_url_from_verification(verification_uri: &str) -> Option { + // Extract domain from verification URI using url crate + if let Ok(url) = Url::parse(verification_uri) + && let Some(host) = url.host_str() + && !host.contains("github.com") + { + // For GHE, construct URL from domain + Some(format!("https://{}/features/copilot", host)) + } else { + None + } + } + fn render_device_code(data: &PromptUserDeviceFlow, cx: &mut Context) -> impl IntoElement { let copied = cx .read_from_clipboard() @@ -302,7 +335,12 @@ impl CopilotCodeVerification { ) } - fn render_unauthorized_modal(cx: &mut Context) -> impl Element { + fn render_unauthorized_modal(&self, cx: &mut Context) -> impl Element { + let sign_up_url = self + .sign_up_url + .as_deref() + .unwrap_or(COPILOT_SIGN_UP_URL) + .to_owned(); let description = "Enable Copilot by connecting your existing license once you have subscribed or renewed your subscription."; v_flex() @@ -319,7 +357,7 @@ impl CopilotCodeVerification { .full_width() .style(ButtonStyle::Outlined) .size(ButtonSize::Medium) - .on_click(|_, _, cx| cx.open_url(COPILOT_SIGN_UP_URL)), + .on_click(move |_, _, cx| cx.open_url(&sign_up_url)), ) .child( Button::new("copilot-subscribe-cancel-button", "Cancel") @@ -374,7 +412,7 @@ impl Render for CopilotCodeVerification { } => Self::render_prompting_modal(self.connect_clicked, prompt, cx).into_any_element(), Status::Unauthorized => { self.connect_clicked = false; - Self::render_unauthorized_modal(cx).into_any_element() + self.render_unauthorized_modal(cx).into_any_element() } Status::Authorized => { self.connect_clicked = false;