Handle credential-embedded GitHub URLs in parse_github_owner_repo

URLs like https://x-access-token:TOKEN@github.com/owner/repo.git are
used by Daytona sandboxes. Strip the credentials before matching the
github.com prefix so pr_create and other callers work in those envs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Bryan Helmkamp 2026-03-14 17:47:55 -04:00
parent 9dedaa9e39
commit 01e855608c

View file

@ -50,7 +50,14 @@ pub struct GitHubAppCredentials {
/// - `https://github.com/owner/repo.git`
/// - `https://github.com/owner/repo`
/// - `https://github.com/owner/repo/`
/// - `https://x-access-token:TOKEN@github.com/owner/repo.git`
pub fn parse_github_owner_repo(url: &str) -> Result<(String, String), String> {
// Strip credentials from URLs like https://x-access-token:TOKEN@github.com/...
let stripped = url.strip_prefix("https://").and_then(|rest| {
rest.split_once('@')
.map(|(_, after)| format!("https://{after}"))
});
let url = stripped.as_deref().unwrap_or(url);
let path = url
.strip_prefix("https://github.com/")
.ok_or_else(|| format!("Not a GitHub HTTPS URL: {url}"))?;
@ -1192,6 +1199,31 @@ mod tests {
);
}
#[test]
fn parse_github_url_with_credentials() {
let (owner, repo) = parse_github_owner_repo(
"https://x-access-token:ghs_abc123@github.com/acme/widgets.git",
)
.unwrap();
assert_eq!(owner, "acme");
assert_eq!(repo, "widgets");
}
#[test]
fn parse_github_url_with_credentials_no_password() {
let (owner, repo) =
parse_github_owner_repo("https://token@github.com/acme/widgets.git").unwrap();
assert_eq!(owner, "acme");
assert_eq!(repo, "widgets");
}
#[test]
fn parse_credentials_non_github_still_errors() {
let result = parse_github_owner_repo("https://user:pass@gitlab.com/owner/repo");
assert!(result.is_err());
assert!(result.unwrap_err().contains("Not a GitHub HTTPS URL"));
}
#[test]
fn parse_non_github_url_errors() {
let result = parse_github_owner_repo("https://gitlab.com/owner/repo");