From 32b9167e8c4ab1a182d9f26b4b62972398795e5b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 12 May 2026 13:56:45 +0000 Subject: [PATCH 1/2] Initial plan From 6f1f83885af4d462964c727b5bdfa2cf68f44556 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 12 May 2026 14:06:57 +0000 Subject: [PATCH 2/2] Deduplicate owner lookup and repo ID field parsing in rust guard backend --- .../rust-guard/src/labels/backend.rs | 69 +++++++++++-------- 1 file changed, 42 insertions(+), 27 deletions(-) diff --git a/guards/github-guard/rust-guard/src/labels/backend.rs b/guards/github-guard/rust-guard/src/labels/backend.rs index 4166e0db..95df03fa 100644 --- a/guards/github-guard/rust-guard/src/labels/backend.rs +++ b/guards/github-guard/rust-guard/src/labels/backend.rs @@ -1243,6 +1243,28 @@ mod tests { }); assert_eq!(extract_owner_is_org(&response, "myorg/myrepo"), None); } + + #[test] + fn test_extract_owner_is_org_plain_array_response() { + let response = serde_json::json!([{ + "full_name": "myorg/myrepo", + "private": false, + "owner": { "login": "myorg", "type": "Organization" } + }]); + assert_eq!(extract_owner_is_org(&response, "myorg/myrepo"), Some(true)); + } + + #[test] + fn test_repo_id_from_repo_object_full_name_camel_case() { + let item = serde_json::json!({ + "fullName": "myorg/myrepo", + "owner": { "login": "myorg", "type": "Organization" } + }); + assert_eq!( + repo_id_from_repo_object(&item), + Some("myorg/myrepo".to_string()) + ); + } } fn repo_visibility_from_items(value: &Value, repo_id: &str) -> Option { @@ -1336,29 +1358,15 @@ fn extract_owner_is_org(response: &Value, repo_id: &str) -> Option { fn owner_is_org_from_items(value: &Value, repo_id: &str) -> Option { // search_repositories shape: { items: [...] } if let Some(items) = value.get("items").and_then(|v| v.as_array()) { - for item in items { - let item_repo_id = repo_id_from_repo_object(item); - if item_repo_id - .as_deref() - .map(|id| id.eq_ignore_ascii_case(repo_id)) - .unwrap_or(false) - { - return owner_type_from_repo_object(item); - } + if let Some(is_org) = find_org_in_items(items, repo_id) { + return Some(is_org); } } // Plain array response if let Some(items) = value.as_array() { - for item in items { - let item_repo_id = repo_id_from_repo_object(item); - if item_repo_id - .as_deref() - .map(|id| id.eq_ignore_ascii_case(repo_id)) - .unwrap_or(false) - { - return owner_type_from_repo_object(item); - } + if let Some(is_org) = find_org_in_items(items, repo_id) { + return Some(is_org); } } @@ -1375,6 +1383,17 @@ fn owner_is_org_from_items(value: &Value, repo_id: &str) -> Option { None } +fn find_org_in_items(items: &[Value], repo_id: &str) -> Option { + items.iter().find_map(|item| { + let item_repo_id = repo_id_from_repo_object(item)?; + if item_repo_id.eq_ignore_ascii_case(repo_id) { + owner_type_from_repo_object(item) + } else { + None + } + }) +} + /// Extract owner type from a repository object. /// GitHub API returns owner.type as "Organization" or "User". fn owner_type_from_repo_object(item: &Value) -> Option { @@ -1387,15 +1406,11 @@ fn owner_type_from_repo_object(item: &Value) -> Option { } fn repo_id_from_repo_object(item: &Value) -> Option { - if let Some(full_name) = item.get("full_name").and_then(|v| v.as_str()) { - if !full_name.is_empty() { - return Some(full_name.to_string()); - } - } - - if let Some(full_name) = item.get("fullName").and_then(|v| v.as_str()) { - if !full_name.is_empty() { - return Some(full_name.to_string()); + for field in ["full_name", "fullName"] { + if let Some(full_name) = item.get(field).and_then(|v| v.as_str()) { + if !full_name.is_empty() { + return Some(full_name.to_string()); + } } }