Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 3 additions & 19 deletions guards/github-guard/rust-guard/src/labels/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ pub fn is_forked_pull_request_with_callback(

let response_str = std::str::from_utf8(&result_buffer[..len]).ok()?;
let response = serde_json::from_str::<Value>(response_str).ok()?;
let pr = extract_mcp_payload_json(&response);
let pr = super::extract_mcp_response(&response);

let base_full_name = pr
Comment on lines 336 to 340
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot apply changes based on this feedback downgrade the extraction logs to debug

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 83876b4 — all crate::log_info calls in extract_mcp_response are now crate::log_debug.

.get("base")
Expand Down Expand Up @@ -384,7 +384,7 @@ pub fn get_pull_request_facts_with_callback(

let response_str = std::str::from_utf8(&result_buffer[..len]).ok()?;
let response = serde_json::from_str::<Value>(response_str).ok()?;
let pr = extract_mcp_payload_json(&response);
let pr = super::extract_mcp_response(&response);

let base_full_name = pr
.get("base")
Expand Down Expand Up @@ -451,7 +451,7 @@ pub fn get_issue_author_association_with_callback(

let response_str = std::str::from_utf8(&result_buffer[..len]).ok()?;
let response = serde_json::from_str::<Value>(response_str).ok()?;
let issue = extract_mcp_payload_json(&response);
let issue = super::extract_mcp_response(&response);

issue
.get("author_association")
Expand Down Expand Up @@ -496,22 +496,6 @@ fn extract_repo_private_flag(response: &Value, repo_id: &str) -> Option<bool> {
repo_visibility_from_items(&parsed, repo_id)
}

fn extract_mcp_payload_json(response: &Value) -> Value {
if let Some(content) = response.get("content").and_then(|v| v.as_array()) {
if let Some(text) = content
.first()
.and_then(|item| item.get("text"))
.and_then(|v| v.as_str())
{
if let Ok(parsed) = serde_json::from_str::<Value>(text) {
return parsed;
}
}
}

response.clone()
}

fn extract_backend_error_text(response: &Value) -> Option<&str> {
if response.get("isError").and_then(|v| v.as_bool()) != Some(true) {
return None;
Expand Down
18 changes: 9 additions & 9 deletions guards/github-guard/rust-guard/src/labels/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,9 @@ pub(crate) fn extract_mcp_response(response: &Value) -> Value {
// Log the top-level keys to understand the structure
if let Some(obj) = response.as_object() {
let keys: Vec<&str> = obj.keys().map(|s| s.as_str()).collect();
crate::log_info(&format!("extract_mcp_response: top-level keys={:?}", keys));
crate::log_debug(&format!("extract_mcp_response: top-level keys={:?}", keys));
} else {
crate::log_info(&format!(
crate::log_debug(&format!(
"extract_mcp_response: response is not an object, type={}",
if response.is_array() {
"array"
Expand All @@ -110,34 +110,34 @@ pub(crate) fn extract_mcp_response(response: &Value) -> Value {

// Try to extract content[0].text and parse it as JSON
if let Some(content) = response.get("content").and_then(|v| v.as_array()) {
crate::log_info(&format!(
crate::log_debug(&format!(
"extract_mcp_response: found content array with {} items",
content.len()
));
if let Some(first) = content.first() {
if let Some(text) = first.get("text").and_then(|v| v.as_str()) {
crate::log_info(&format!(
crate::log_debug(&format!(
"extract_mcp_response: found text field, len={}",
text.len()
));
// Try to parse the text as JSON
if let Ok(parsed) = serde_json::from_str::<Value>(text) {
crate::log_info("extract_mcp_response: parsed content[0].text as JSON");
crate::log_debug("extract_mcp_response: parsed content[0].text as JSON");
return parsed;
} else {
crate::log_info("extract_mcp_response: failed to parse text as JSON");
crate::log_debug("extract_mcp_response: failed to parse text as JSON");
}
} else {
crate::log_info("extract_mcp_response: no text field in content[0]");
crate::log_debug("extract_mcp_response: no text field in content[0]");
}
}
} else {
crate::log_info("extract_mcp_response: no content array found");
crate::log_debug("extract_mcp_response: no content array found");
}

// If we can't extract from MCP wrapper, return the original response
// (it might already be unwrapped or in a different format)
crate::log_info("extract_mcp_response: using response as-is");
crate::log_debug("extract_mcp_response: using response as-is");
response.clone()
}

Expand Down
23 changes: 2 additions & 21 deletions guards/github-guard/rust-guard/src/permissions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@
//! using the backend MCP server. This enables dynamic integrity
//! labeling based on actual GitHub permissions.

#![allow(dead_code)]

use crate::labels::{constants::label_constants, is_bot, MEDIUM_BUFFER_SIZE};
use crate::labels::{constants::label_constants, MEDIUM_BUFFER_SIZE};
use serde_json::Value;

/// Repository permission level from GitHub
Expand Down Expand Up @@ -301,15 +299,6 @@ pub fn get_author_integrity_tags(author: &str, owner: &str, repo: &str) -> Vec<S
vec![format!("{}{}", label_constants::READER_PREFIX, repo_id)]
}

/// Check if a user is likely a bot account
///
/// This is a re-export of `labels::is_bot` for backwards compatibility.
/// Use `labels::is_bot` directly in new code.
#[deprecated(since = "0.2.0", note = "Use `labels::is_bot` instead")]
pub fn is_bot_account(username: &str) -> bool {
is_bot(username)
}

/// Get integrity tags for a bot account
///
/// Bots typically have approved-level integrity for their automated actions.
Expand Down Expand Up @@ -344,6 +333,7 @@ pub fn get_bot_integrity_tags(bot_name: &str, owner: &str, repo: &str) -> Vec<St
#[cfg(test)]
mod tests {
use super::*;
use crate::labels::is_bot;

#[test]
fn test_permission_level_parsing() {
Expand Down Expand Up @@ -373,15 +363,6 @@ mod tests {

#[test]
fn test_bot_detection() {
// Test the re-exported function
#[allow(deprecated)]
{
assert!(is_bot_account("dependabot[bot]"));
assert!(is_bot_account("renovate-bot"));
assert!(is_bot_account("github-actions"));
assert!(!is_bot_account("octocat"));
}

// Test the canonical function from labels module
assert!(is_bot("dependabot[bot]"));
assert!(is_bot("renovate-bot"));
Expand Down
Loading