Skip to content
Closed
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
11 changes: 11 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ tokio = { workspace = true }
tokio-util = "0.7"
axum = "0.8"
http = "1"
# HTTP proxy functionality
hyper-util = { version = "0.1", features = ["client", "client-legacy", "http1", "http2", "tokio"] }
tower = "0.5"
tower-http = { version = "0.6", features = ["trace", "cors"] }
eyre = { workspace = true }
# Native Forgejo/Gitea API client
forgejo-api = "0.9"
Expand All @@ -60,6 +64,7 @@ tempfile = "3.24.0"
# Pin time to avoid 0.3.47 which has compile-time assertions that fail on older Rust
# See: https://github.com/time-rs/time/issues/836
time = ">=0.3,<0.3.47"
urlencoding = "2.1"

[dev-dependencies]
cap-std-ext = "4.0.7"
Expand Down
1 change: 1 addition & 0 deletions integration-tests/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ mod tests {
pub mod jira;
pub mod mcp_server;
pub mod push_new_branch_tests;
pub mod rest_api;
pub mod rmcp_client;
pub mod status_tests;
}
Expand Down
51 changes: 24 additions & 27 deletions integration-tests/src/tests/mcp_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1045,8 +1045,9 @@ fn test_mcp_github_api_non_repo_endpoint_rejected() -> Result<()> {

let error_text = result["content"][0]["text"].as_str().unwrap_or("");
assert!(
error_text.contains("Could not determine target repository"),
"Expected repo path error, got: {}",
error_text.contains("Could not determine target repository")
|| error_text.contains("global read access"),
"Expected repo path error or global read access error, got: {}",
error_text
);

Expand Down Expand Up @@ -1395,7 +1396,7 @@ integration_test!(test_mcp_permission_separation_create_draft_only);
fn test_mcp_permission_separation_both_permissions() -> Result<()> {
let test_repo = get_test_repo();

// Configure server with both push-branch and create-draft permissions
// Configure server with both push-new-branch and create-draft permissions
let config = format!(
r#"
[server]
Expand All @@ -1404,7 +1405,7 @@ admin-key = "admin-key"
mode = "optional"

[gh.repos]
"{}" = {{ read = true, create-draft = true, push-branch = true }}
"{}" = {{ read = true, create-draft = true, push-new-branch = true }}
"#,
test_repo
);
Expand Down Expand Up @@ -1654,12 +1655,13 @@ mode = "optional"
}
integration_test!(test_mcp_permission_separation_no_permissions);

/// Test backward compatibility - existing configs with create-draft should still work
/// Test backward compatibility - push-new-branch implies can_create_draft
fn test_mcp_permission_separation_backward_compatibility() -> Result<()> {
let test_repo = get_test_repo();

// Configure server with legacy-style permissions (create-draft = true, no push-branch specified)
// This simulates an existing configuration before the push-branch separation
// Configure server with push-new-branch = true
// Backward compatibility: push-new-branch implies can_create_draft
// (pushing branches for PRs requires creating the draft PR too)
let config = format!(
r#"
[server]
Expand All @@ -1668,7 +1670,7 @@ admin-key = "admin-key"
mode = "optional"

[gh.repos]
"{}" = {{ read = true, create-draft = true, pending-review = true }}
"{}" = {{ read = true, create-draft = false, push-new-branch = true }}
"#,
test_repo
);
Expand All @@ -1679,6 +1681,7 @@ mode = "optional"
session.send_initialized()?;

// Test that github_push with create_draft_pr works (backward compatibility)
// push-new-branch implies can_create_draft, so this should work from a permission standpoint
let push_with_pr_request = json!({
"jsonrpc": "2.0",
"method": "tools/call",
Expand All @@ -1703,15 +1706,15 @@ mode = "optional"
if let Some(true) = pr_result.get("isError").and_then(|e| e.as_bool()) {
let error_content = &pr_result["content"];
let error_text = error_content[0]["text"].as_str().unwrap_or("");
// Should NOT be a permission error - legacy configs should work
// Should NOT be a permission error - push-new-branch implies can_create_draft
assert!(
!error_text.contains("permission not granted"),
"Expected no permission error for legacy config, got: {}",
"Expected no permission error with push-new-branch (implies create-draft), got: {}",
error_text
);
}

// However, direct push without PR should fail since push-branch defaults to false
// Push without PR should also work since we have push-new-branch
let push_no_pr_request = json!({
"jsonrpc": "2.0",
"method": "tools/call",
Expand All @@ -1730,23 +1733,17 @@ mode = "optional"

let push_response = session.send_request(push_no_pr_request)?;
let push_result = &push_response["result"];
let push_is_error = push_result
.get("isError")
.and_then(|e| e.as_bool())
.unwrap_or(false);

assert!(
push_is_error,
"Expected push without PR to fail due to missing push-new-branch permission in legacy config"
);

let error_content = &push_result["content"];
let error_text = error_content[0]["text"].as_str().unwrap_or("");
assert!(
error_text.contains("push-new-branch permission not granted"),
"Expected push-new-branch permission error for legacy config without explicit push-new-branch, got: {}",
error_text
);
if let Some(true) = push_result.get("isError").and_then(|e| e.as_bool()) {
let error_content = &push_result["content"];
let error_text = error_content[0]["text"].as_str().unwrap_or("");
// Should NOT be a permission error - we have push-new-branch
assert!(
!error_text.contains("permission not granted"),
"Expected no permission error with push-new-branch, got: {}",
error_text
);
}

Ok(())
}
Expand Down
4 changes: 2 additions & 2 deletions integration-tests/src/tests/push_new_branch_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -336,10 +336,10 @@ admin-key = "admin-key"
mode = "optional"

[gh.repos]
"{}" = {{ read = true, create-draft = true, push-new-branch = false, write = false }}
"{}" = {{ read = true, create-draft = false, push-new-branch = true, write = false }}

[gitlab.projects]
"testgroup/testproject" = {{ read = true, create-draft = true, push-new-branch = false }}
"testgroup/testproject" = {{ read = true, create-draft = false, push-new-branch = true }}
"#,
test_repo
);
Expand Down
Loading
Loading