mirror of
https://github.com/openai/codex.git
synced 2026-11-10 21:00:47 +00:00
Start cloud threads with the local GitHub project (#60007)
## What changed Pass the local project's GitHub origin to cloud prewarming so new cloud threads can provision a repository checkout. Preserve the attached local project when switching backends and resolve its origin for each thread start. Normalize supported GitHub origins to credential-free HTTPS URLs and select a repository-specific cloud working directory. Unsupported origins retain the blank environment behavior. Keep project metadata outside the app-server wire protocol, and fix HTTP Git URL parsing so query strings and fragments cannot be mistaken for authority text. ## Testing Add coverage for project routing, origin normalization and rejection, managed environment encoding, local project retention, and Git URL credential stripping. GitOrigin-RevId: 5859769965faf060461ccc1cbb3fd48f8e2f2155
This commit is contained in:
committed by
copyberry
parent
df769889c0
commit
7de8a0afc0
@@ -77,9 +77,13 @@ impl TryFrom<&str> for SanitizedGitUrl {
|
||||
// `file://` authority as its host and does not expose its userinfo.
|
||||
// Rebuilding only this part also preserves escaped repository paths.
|
||||
if let Some((scheme, authority_and_path)) = value.split_once("://") {
|
||||
let authority_end = authority_and_path
|
||||
.find('/')
|
||||
.unwrap_or(authority_and_path.len());
|
||||
// Git treats '?' and '#' as authority text on non-HTTP transports.
|
||||
let authority_end = if matches!(scheme, "http" | "https") {
|
||||
authority_and_path.find(['/', '?', '#'])
|
||||
} else {
|
||||
authority_and_path.find('/')
|
||||
}
|
||||
.unwrap_or(authority_and_path.len());
|
||||
let (authority, path) = authority_and_path.split_at(authority_end);
|
||||
let Some((_, host)) = authority.rsplit_once('@') else {
|
||||
return Ok(Self(original.to_owned()));
|
||||
|
||||
@@ -15,6 +15,30 @@ fn removes_https_username_and_password() {
|
||||
assert_eq!(url.as_str(), "https://github.com/org/repo.git");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn http_query_and_fragment_are_outside_the_authority() {
|
||||
for (scheme, suffix) in [("http", "?@github.com/a/b"), ("https", "#@github.com/a/b")] {
|
||||
let expected = format!("{scheme}://example.com{suffix}");
|
||||
for authority in ["example.com", "user:password@example.com"] {
|
||||
let remote = format!("{scheme}://{authority}{suffix}");
|
||||
let sanitized = SanitizedGitUrl::try_from(remote.as_str()).expect("parse remote URL");
|
||||
assert_eq!(sanitized.as_str(), expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn non_http_credentials_can_contain_query_and_fragment_delimiters() {
|
||||
for scheme in ["ssh", "git", "file"] {
|
||||
let expected = format!("{scheme}://example.com/org/repo");
|
||||
for password in ["synthetic?value", "synthetic#value"] {
|
||||
let remote = format!("{scheme}://user:{password}@example.com/org/repo");
|
||||
let sanitized = SanitizedGitUrl::try_from(remote.as_str()).expect("parse remote URL");
|
||||
assert_eq!(sanitized.as_str(), expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Tokens placed in the username field are credentials too.
|
||||
#[test]
|
||||
fn removes_https_username_without_password() {
|
||||
|
||||
Reference in New Issue
Block a user