Skip to content
Draft
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
5 changes: 4 additions & 1 deletion docs/safe-outputs.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ safe-outputs:
squash-merge: true
reviewers:
- "user@example.com"
allow-agent-reviewers: true # allow the model to select additional reviewers
labels:
- automated
- agent-created
Expand Down Expand Up @@ -1099,6 +1100,7 @@ This hybrid approach combines:
- `description` - PR description in markdown (required, 10+ characters)
- `repository` - Repository to create PR in: "self" for pipeline repo, or alias from `checkout:` list (default: "self")
- `labels` - Labels to add to the PR (optional; validated against `allowed-labels` when configured)
- `reviewers` - Reviewers to add by email, display name, or Azure DevOps user ID (optional; requires `allow-agent-reviewers: true`)

Note: The source branch name is auto-generated from a sanitized version of the PR title plus a unique suffix (e.g., `agent/fix-bug-in-parser-a1b2c3`). This format is human-readable while preventing injection attacks.

Expand Down Expand Up @@ -1146,7 +1148,8 @@ Note: The source branch name is auto-generated from a sanitized version of the P
- `protected-files` - Controls whether manifest/CI files (e.g., `package-lock.json`, `.github/`, `*.lock`) can be modified: `"blocked"` (default, reject changes to these files) or `"allowed"` (permit all files)
- `excluded-files` - Glob patterns for files to strip from the patch before applying (e.g., `["*.lock", "dist/**"]`)
- `allowed-labels` - Allowlist of labels the agent is permitted to apply. If empty (default), any labels are accepted.
- `reviewers` - List of reviewer emails to add
- `reviewers` - List of reviewer emails or Azure DevOps user IDs to add
- `allow-agent-reviewers` - Allow the model to select additional reviewers in its `create-pull-request` call (default: false). Agent-selected reviewers are merged with and deduplicated against `reviewers`.
- `labels` - List of labels to apply
- `work-items` - List of work item IDs to link
- `fallback-record-branch` - When PR creation fails, record the pushed branch name and target branch in the failure response so operators can manually create the PR (default: true)
Expand Down
18 changes: 18 additions & 0 deletions src/mcp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1140,6 +1140,7 @@ Use 'self' for the pipeline's own repository, or a repository alias from the che
patch_file: patch_filename,
repository: repository.to_string(),
agent_labels: sanitized.labels,
agent_reviewers: sanitized.reviewers,
base_commit: Some(merge_base),
patch_sha256,
};
Expand Down Expand Up @@ -2592,6 +2593,23 @@ safe-outputs:
assert!(!properties.contains_key("temporary_id"));
}

#[tokio::test]
async fn test_create_pr_schema_accepts_reviewers() {
let temp_dir = tempfile::tempdir().unwrap();
let enabled = vec!["create-pull-request".to_string()];
let so = SafeOutputs::new(temp_dir.path(), temp_dir.path(), Some(&enabled), None)
.await
.unwrap();
let tools = so.tool_router.list_all();
let tool = tools
.iter()
.find(|tool| tool.name.as_ref() == "create-pull-request")
.expect("create-pull-request should be enabled");
let schema = serde_json::to_value(&tool.input_schema).unwrap();
let properties = schema["properties"].as_object().unwrap();
assert!(properties.contains_key("reviewers"));
}

#[tokio::test]
async fn test_github_queue_propagates_ndjson_write_failures() {
let temp_dir = tempfile::tempdir().unwrap();
Expand Down
Loading