diff --git a/src/main.rs b/src/main.rs index 43ba366d..64147f83 100644 --- a/src/main.rs +++ b/src/main.rs @@ -245,8 +245,16 @@ async fn build_execution_context( .collect(); let mut ctx = crate::safeoutputs::ExecutionContext::default(); - ctx.ado_org_url = ado_org_url; - ctx.ado_project = ado_project; + // Only override env-derived values when CLI args are explicitly provided; + // otherwise keep the defaults from SYSTEM_TEAMFOUNDATIONCOLLECTIONURI / + // SYSTEM_TEAMPROJECT that ExecutionContext::default() already resolved. + if let Some(url) = ado_org_url { + ctx.ado_organization = crate::safeoutputs::org_from_url(&url); + ctx.ado_org_url = Some(url); + } + if let Some(project) = ado_project { + ctx.ado_project = Some(project); + } ctx.working_directory = safe_output_dir.clone(); ctx.tool_configs = front_matter.safe_outputs.clone(); ctx.allowed_repositories = allowed_repositories; diff --git a/src/safeoutputs/mod.rs b/src/safeoutputs/mod.rs index fccfacd3..deb37ad7 100644 --- a/src/safeoutputs/mod.rs +++ b/src/safeoutputs/mod.rs @@ -288,6 +288,7 @@ pub use report_incomplete::*; pub use resolve_pr_thread::*; pub use result::{ ExecutionContext, ExecutionResult, Executor, ToolResult, Validate, anyhow_to_mcp_error, + org_from_url, }; pub use submit_pr_review::*; pub use update_pr::*; diff --git a/src/safeoutputs/result.rs b/src/safeoutputs/result.rs index b9ffb57a..d01cd2e2 100644 --- a/src/safeoutputs/result.rs +++ b/src/safeoutputs/result.rs @@ -129,6 +129,20 @@ impl ExecutionContext { } } +/// Extract the organization name from an Azure DevOps org URL. +/// +/// Handles both hosted (`https://dev.azure.com/myorg`) and on-prem +/// (`https://server/tfs/myorg`) URLs, with or without a trailing slash. +/// +/// Returns `None` if the URL is empty or has no meaningful last segment. +pub fn org_from_url(url: &str) -> Option { + url.trim_end_matches('/') + .rsplit('/') + .next() + .filter(|s| !s.is_empty()) + .map(|s| s.to_string()) +} + impl ExecutionContext { /// Build an `ExecutionContext` from an arbitrary env-var lookup function. /// @@ -144,13 +158,7 @@ impl ExecutionContext { .or_else(|| env("SYSTEM_TEAMFOUNDATIONCOLLECTIONURI")); // Extract organization name from URL (e.g., "https://dev.azure.com/myorg/" -> "myorg") - let ado_organization = ado_org_url.as_ref().and_then(|url| { - url.trim_end_matches('/') - .rsplit('/') - .next() - .filter(|s| !s.is_empty()) - .map(|s| s.to_string()) - }); + let ado_organization = ado_org_url.as_ref().and_then(|url| org_from_url(url)); // Source directory is where git repos are checked out (BUILD_SOURCESDIRECTORY) let source_directory = env("BUILD_SOURCESDIRECTORY")