From a157012178f54c911ca83fdb2f47ca87da9cd141 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 7 Apr 2026 15:01:03 +0000 Subject: [PATCH 1/9] Initial plan From 53e1e638ac246fc2d22b7102a7f209a753735afd Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 7 Apr 2026 15:21:28 +0000 Subject: [PATCH 2/9] feat: rename agency_params to copilot_params and replace agency CLI references with copilot Agent-Logs-Url: https://github.com/githubnext/ado-aw/sessions/6de925b5-b695-4ace-ace7-292d6f1896a2 Co-authored-by: jamesadevine <4742697+jamesadevine@users.noreply.github.com> --- AGENTS.md | 22 +++++++++++----------- src/compile/common.rs | 4 ++-- src/compile/onees.rs | 4 ++-- src/compile/standalone.rs | 12 ++++++------ src/mcp_metadata.rs | 6 +++--- templates/1es-base.yml | 6 +++--- templates/base.yml | 15 ++------------- tests/EXAMPLES.md | 4 ++-- tests/README.md | 6 +++--- tests/SUMMARY.md | 6 +++--- tests/VERIFICATION.md | 2 +- tests/compiler_tests.rs | 4 ++-- 12 files changed, 40 insertions(+), 51 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 6d7cecde..373e29b6 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -366,7 +366,7 @@ The compiler transforms the input into valid Azure DevOps pipeline YAML based on - **Standalone**: Uses `templates/base.yml` - **1ES**: Uses `templates/1es-base.yml` -Explicit markings are embedded in these templates that the compiler is allowed to replace e.g. `{{ agency_params }}` denotes parameters which are passed to the agency command line tool. The compiler should not replace sections denoted by `${{ some content }}`. What follows is a mapping of markings to responsibilities (primarily for the standalone template). +Explicit markings are embedded in these templates that the compiler is allowed to replace e.g. `{{ copilot_params }}` denotes parameters which are passed to the copilot command line tool. The compiler should not replace sections denoted by `${{ some content }}`. What follows is a mapping of markings to responsibilities (primarily for the standalone template). ## {{ repositories }} For each additional repository specified in the front matter append: @@ -435,9 +435,9 @@ This distinction allows resources (like templates) to be available as pipeline r Should be replaced with the human-readable name from the front matter (e.g., "Daily Code Review"). This is used for display purposes like stage names. -## {{ agency_params }} +## {{ copilot_params }} -Additional params provided to agency CLI. The compiler generates: +Additional params provided to copilot CLI. The compiler generates: - `--model ` - AI model from `engine` front matter field (default: claude-opus-4.5) - `--disable-builtin-mcps` - Disables all built-in MCPs initially - `--no-ask-user` - Prevents interactive prompts @@ -514,7 +514,7 @@ Should be replaced with the appropriate working directory based on the effective - `root`: `$(Build.SourcesDirectory)` - the checkout root directory - `repo`: `$(Build.SourcesDirectory)/$(Build.Repository.Name)` - the repository's subfolder -This is used for the `workingDirectory` property of the agency copilot task. +This is used for the `workingDirectory` property of the copilot task. ## {{ source_path }} @@ -1286,11 +1286,11 @@ When agents are configured with multiple MCPs (e.g., `ado`, `kusto`, `icm`), the ``` ┌─────────────┐ ┌──────────────────┐ ┌─────────────────┐ │ │ │ │ │ ado MCP │ -│ Agent │────▶│ MCP Firewall │────▶│ (agency mcp ado)│ +│ Agent │────▶│ MCP Firewall │────▶│ (copilot mcp ado)│ │ (Agency) │ │ │ └─────────────────┘ │ │ │ - Policy check │ ┌─────────────────┐ └─────────────┘ │ - Tool routing │────▶│ icm MCP │ - │ - Audit logging │ │ (agency mcp icm)│ + │ - Audit logging │ │ (copilot mcp icm)│ └──────────────────┘ └─────────────────┘ ┌─────────────────┐ ────▶│ custom MCP │ @@ -1306,19 +1306,19 @@ The firewall reads a JSON configuration file at runtime: { "upstreams": { "ado": { - "command": "agency", + "command": "copilot", "args": ["mcp", "ado"], "env": {}, "allowed": ["*"] }, "icm": { - "command": "agency", + "command": "copilot", "args": ["mcp", "icm"], "env": {}, "allowed": ["create_incident", "get_incident"] }, "kusto": { - "command": "agency", + "command": "copilot", "args": ["mcp", "kusto"], "env": {}, "allowed": ["query"] @@ -1378,8 +1378,8 @@ ado-aw mcp-firewall --config /path/to/config.json The firewall is automatically configured in generated pipelines: 1. **Config Generation**: The compiler generates `mcp-firewall-config.json` from the agent's `mcp-servers:` front matter -2. **MCP Registration**: The firewall is registered in the agency MCP config as `mcp-firewall` -3. **Runtime Launch**: When agency starts, it launches the firewall which spawns upstream MCPs +2. **MCP Registration**: The firewall is registered in the copilot MCP config as `mcp-firewall` +3. **Runtime Launch**: When copilot starts, it launches the firewall which spawns upstream MCPs The firewall config is written to `$(Agent.TempDirectory)/staging/mcp-firewall-config.json` in its own pipeline step, making it easy to inspect and debug. diff --git a/src/compile/common.rs b/src/compile/common.rs index 26c1d33a..3fb7917d 100644 --- a/src/compile/common.rs +++ b/src/compile/common.rs @@ -6,7 +6,7 @@ use super::types::{FrontMatter, McpConfig, Repository, TriggerConfig}; use crate::fuzzy_schedule; use crate::mcp_metadata::McpMetadataFile; -/// Check if an MCP name is a built-in (launched via agency mcp) +/// Check if an MCP name is a built-in (launched via copilot mcp) pub fn is_builtin_mcp(name: &str) -> bool { let metadata = McpMetadataFile::bundled(); metadata.get(name).map(|m| m.builtin).unwrap_or(false) @@ -315,7 +315,7 @@ pub fn generate_copilot_params(front_matter: &FrontMatter) -> String { for tool in allowed_tools { if tool.contains('(') || tool.contains(')') || tool.contains(' ') { - // Use double quotes - the agency_params are embedded inside a single-quoted + // Use double quotes - the copilot_params are embedded inside a single-quoted // bash string in the AWF command, so single quotes would break quoting. params.push(format!("--allow-tool \"{}\"", tool)); } else { diff --git a/src/compile/onees.rs b/src/compile/onees.rs index 93de9d5a..e557112d 100644 --- a/src/compile/onees.rs +++ b/src/compile/onees.rs @@ -58,7 +58,7 @@ impl Compiler for OneESCompiler { let repositories = generate_repositories(&front_matter.repositories); let checkout_steps = generate_checkout_steps(&front_matter.checkout); let checkout_self = generate_checkout_self(); - let agency_params = generate_copilot_params(front_matter); + let copilot_params = generate_copilot_params(front_matter); let effective_workspace = compute_effective_workspace( &front_matter.workspace, @@ -169,7 +169,7 @@ displayName: "Finalize""#, ("{{ pipeline_path }}", &pipeline_path), ("{{ working_directory }}", &working_directory), ("{{ workspace }}", &working_directory), - ("{{ agency_params }}", &agency_params), + ("{{ copilot_params }}", &copilot_params), ("{{ acquire_ado_token }}", &acquire_read_token), ("{{ copilot_ado_env }}", &copilot_ado_env), ("{{ acquire_write_token }}", &acquire_write_token), diff --git a/src/compile/standalone.rs b/src/compile/standalone.rs index 2fde3739..b2806e06 100644 --- a/src/compile/standalone.rs +++ b/src/compile/standalone.rs @@ -59,7 +59,7 @@ impl Compiler for StandaloneCompiler { let repositories = generate_repositories(&front_matter.repositories); let checkout_steps = generate_checkout_steps(&front_matter.checkout); let checkout_self = generate_checkout_self(); - let agency_params = generate_copilot_params(front_matter); + let copilot_params = generate_copilot_params(front_matter); let agent_name = sanitize_filename(&front_matter.name); // Compute effective workspace @@ -163,7 +163,7 @@ impl Compiler for StandaloneCompiler { ("{{ agent }}", &agent_name), ("{{ agent_name }}", &front_matter.name), ("{{ agent_description }}", &front_matter.description), - ("{{ agency_params }}", &agency_params), + ("{{ copilot_params }}", &copilot_params), ("{{ source_path }}", &source_path), ("{{ pipeline_path }}", &pipeline_path), ("{{ working_directory }}", &working_directory), @@ -393,7 +393,7 @@ pub fn generate_firewall_config(front_matter: &FrontMatter) -> FirewallConfig { args.extend(opts.args.clone()); UpstreamConfig { - command: "agency".to_string(), + command: "copilot".to_string(), args, env: opts.env.clone(), allowed: if opts.allowed.is_empty() { @@ -413,7 +413,7 @@ pub fn generate_firewall_config(front_matter: &FrontMatter) -> FirewallConfig { } else if common::is_builtin_mcp(name) { // Built-in MCP with simple enablement UpstreamConfig { - command: "agency".to_string(), + command: "copilot".to_string(), args: vec!["mcp".to_string(), name.clone()], env: HashMap::new(), allowed: vec!["*".to_string()], @@ -507,7 +507,7 @@ mod tests { .insert("ado".to_string(), McpConfig::Enabled(true)); let config = generate_firewall_config(&fm); let upstream = config.upstreams.get("ado").unwrap(); - assert_eq!(upstream.command, "agency"); + assert_eq!(upstream.command, "copilot"); assert_eq!(upstream.args, vec!["mcp", "ado"]); assert_eq!(upstream.allowed, vec!["*"]); } @@ -524,7 +524,7 @@ mod tests { ); let config = generate_firewall_config(&fm); let upstream = config.upstreams.get("icm").unwrap(); - assert_eq!(upstream.command, "agency"); + assert_eq!(upstream.command, "copilot"); assert_eq!(upstream.args, vec!["mcp", "icm"]); assert_eq!( upstream.allowed, diff --git a/src/mcp_metadata.rs b/src/mcp_metadata.rs index f917c8d6..1ce12a1e 100644 --- a/src/mcp_metadata.rs +++ b/src/mcp_metadata.rs @@ -1,4 +1,4 @@ -//! MCP Metadata - Bundled tool definitions for agency MCPs +//! MCP Metadata - Bundled tool definitions for copilot MCPs //! //! This module provides access to pre-discovered MCP tool metadata that is //! embedded at compile time. The metadata is refreshed by running: @@ -11,7 +11,7 @@ //! ./refresh-mcp-metadata.sh //! ``` //! -//! The scripts query each built-in agency MCP and save the tool definitions +//! The scripts query each built-in copilot MCP and save the tool definitions //! to `mcp-metadata.json`, which is then embedded into the binary. use serde::{Deserialize, Serialize}; @@ -38,7 +38,7 @@ pub struct ToolMetadata { pub struct McpMetadata { /// Server name/identifier pub name: String, - /// Whether this is a built-in agency MCP + /// Whether this is a built-in copilot MCP #[serde(default)] pub builtin: bool, /// Available tools diff --git a/templates/1es-base.yml b/templates/1es-base.yml index 024ff0cc..beaf756d 100644 --- a/templates/1es-base.yml +++ b/templates/1es-base.yml @@ -128,9 +128,9 @@ extends: postAgentSteps: {{ finalize_steps }} globalOptions: '--log-dir $(Agency_LogPath) {{ global_options }}' - commandOptions: '{{ agency_params }}' + commandOptions: '{{ copilot_params }}' logLevel: '{{ log_level }}' - logPath: '$(Build.StagingDirectory)/agency-logs' + logPath: '$(Build.StagingDirectory)/copilot-logs' createArtifact: true mcpConfiguration: {{ mcp_configuration }} @@ -230,7 +230,7 @@ extends: THREAT_OUTPUT_FILE="$(Agent.TempDirectory)/threat-analysis-output.txt" # Use $(cat file) like gh-aw does - the command is executed directly, not via a variable - copilot --prompt "$(cat $(Agent.TempDirectory)/threat-analysis-prompt.md)" {{ agency_params }} > "$THREAT_OUTPUT_FILE" 2>&1 + copilot --prompt "$(cat $(Agent.TempDirectory)/threat-analysis-prompt.md)" {{ copilot_params }} > "$THREAT_OUTPUT_FILE" 2>&1 AGENT_EXIT_CODE=$? echo "=== Threat Analysis Output (sanitized) ===" diff --git a/templates/base.yml b/templates/base.yml index 5d39b135..efa4b7e6 100644 --- a/templates/base.yml +++ b/templates/base.yml @@ -223,7 +223,7 @@ jobs: --container-workdir "{{ working_directory }}" \ --log-level info \ --proxy-logs-dir "$(Agent.TempDirectory)/staging/logs/firewall" \ - -- '/tmp/awf-tools/copilot --prompt "$(cat /tmp/awf-tools/agent-prompt.md)" --additional-mcp-config @/tmp/awf-tools/mcp-config.json {{ agency_params }}' \ + -- '/tmp/awf-tools/copilot --prompt "$(cat /tmp/awf-tools/agent-prompt.md)" --additional-mcp-config @/tmp/awf-tools/mcp-config.json {{ copilot_params }}' \ > "$AGENT_OUTPUT_FILE" 2>&1 \ && AGENT_EXIT_CODE=0 || AGENT_EXIT_CODE=$? @@ -263,9 +263,6 @@ jobs: if [ -d ~/.copilot/logs ]; then cp -r ~/.copilot/logs/* "$(Agent.TempDirectory)/staging/logs/" 2>/dev/null || true fi - if [ -d ~/.agency/logs ]; then - cp -r ~/.agency/logs/* "$(Agent.TempDirectory)/staging/logs/" 2>/dev/null || true - fi if [ -d ~/.ado-aw/logs ]; then cp -r ~/.ado-aw/logs/* "$(Agent.TempDirectory)/staging/logs/" 2>/dev/null || true fi @@ -395,7 +392,7 @@ jobs: --container-workdir "{{ working_directory }}" \ --log-level info \ --proxy-logs-dir "$(Agent.TempDirectory)/threat-analysis-logs/firewall" \ - -- '/tmp/awf-tools/copilot --prompt "$(cat /tmp/awf-tools/threat-analysis-prompt.md)" {{ agency_params }}' \ + -- '/tmp/awf-tools/copilot --prompt "$(cat /tmp/awf-tools/threat-analysis-prompt.md)" {{ copilot_params }}' \ > "$THREAT_OUTPUT_FILE" 2>&1 AGENT_EXIT_CODE=$? @@ -480,10 +477,6 @@ jobs: mkdir -p "$(Agent.TempDirectory)/analyzed_outputs/logs/copilot" cp -r ~/.copilot/logs/* "$(Agent.TempDirectory)/analyzed_outputs/logs/copilot/" 2>/dev/null || true fi - if [ -d ~/.agency/logs ]; then - mkdir -p "$(Agent.TempDirectory)/analyzed_outputs/logs/agency" - cp -r ~/.agency/logs/* "$(Agent.TempDirectory)/analyzed_outputs/logs/agency/" 2>/dev/null || true - fi if [ -d ~/.ado-aw/logs ]; then mkdir -p "$(Agent.TempDirectory)/analyzed_outputs/logs/ado-aw" cp -r ~/.ado-aw/logs/* "$(Agent.TempDirectory)/analyzed_outputs/logs/ado-aw/" 2>/dev/null || true @@ -555,10 +548,6 @@ jobs: mkdir -p "$(Agent.TempDirectory)/staging/logs/copilot" cp -r ~/.copilot/logs/* "$(Agent.TempDirectory)/staging/logs/copilot/" 2>/dev/null || true fi - if [ -d ~/.agency/logs ]; then - mkdir -p "$(Agent.TempDirectory)/staging/logs/agency" - cp -r ~/.agency/logs/* "$(Agent.TempDirectory)/staging/logs/agency/" 2>/dev/null || true - fi if [ -d ~/.ado-aw/logs ]; then mkdir -p "$(Agent.TempDirectory)/staging/logs/ado-aw" cp -r ~/.ado-aw/logs/* "$(Agent.TempDirectory)/staging/logs/ado-aw/" 2>/dev/null || true diff --git a/tests/EXAMPLES.md b/tests/EXAMPLES.md index dfa694b0..5cdbc33d 100644 --- a/tests/EXAMPLES.md +++ b/tests/EXAMPLES.md @@ -78,7 +78,7 @@ fn test_with_hashmap() { mcps.insert("ado".to_string(), McpConfig::Enabled(true)); mcps.insert("es-chat".to_string(), McpConfig::Enabled(true)); - let result = generate_agency_params(&mcps); + let result = generate_copilot_params(&mcps); assert!(result.contains("--prompt")); assert!(result.contains("--mcp ado") || result.contains("--mcp es-chat")); @@ -101,7 +101,7 @@ fn test_with_options() { }), ); - let result = generate_agency_params(&mcps); + let result = generate_copilot_params(&mcps); assert!(!result.contains("--mcp custom-tool")); } diff --git a/tests/README.md b/tests/README.md index 4b5e3bf0..861ca982 100644 --- a/tests/README.md +++ b/tests/README.md @@ -68,8 +68,8 @@ Tests checkout step generation for: - Empty repository list - Multiple repositories -### `test_generate_agency_params_*` (3 tests) -Tests agency parameter generation for: +### `test_generate_copilot_params_*` (3 tests) +Tests copilot parameter generation for: - Built-in MCPs (enabled) - Built-in MCPs (disabled) - Custom MCPs (should be skipped) @@ -101,7 +101,7 @@ Verifies that the base template contains all required markers: - `{{ checkout_repositories }}` - `{{ agent }}` - `{{ agent_name }}` -- `{{ agency_params }}` +- `{{ copilot_params }}` ### `test_example_file_structure` Validates the example file (`examples/sample-agent.md`) to ensure: diff --git a/tests/SUMMARY.md b/tests/SUMMARY.md index bf14ee3c..f9958d39 100644 --- a/tests/SUMMARY.md +++ b/tests/SUMMARY.md @@ -28,9 +28,9 @@ Added 18 comprehensive unit tests in the `tests` module at the end of `main.rs`: - `test_generate_checkout_steps_multiple` - Tests multiple checkout steps #### Agency Parameters (3 tests) -- `test_generate_agency_params_builtin_enabled` - Tests enabled built-in MCPs -- `test_generate_agency_params_builtin_disabled` - Tests disabled MCPs -- `test_generate_agency_params_custom_mcp_skipped` - Verifies custom MCPs are skipped +- `test_generate_copilot_params_builtin_enabled` - Tests enabled built-in MCPs +- `test_generate_copilot_params_builtin_disabled` - Tests disabled MCPs +- `test_generate_copilot_params_custom_mcp_skipped` - Verifies custom MCPs are skipped #### Markdown Parsing (4 tests) - `test_parse_markdown_valid` - Tests valid markdown with front matter diff --git a/tests/VERIFICATION.md b/tests/VERIFICATION.md index 56e73a02..6b8473bd 100644 --- a/tests/VERIFICATION.md +++ b/tests/VERIFICATION.md @@ -136,7 +136,7 @@ fn test_compile_pipeline_basic() { - `test_generate_schedule_*` - verifies schedule generation - `test_generate_repositories_*` - verifies repository YAML generation - `test_generate_checkout_steps_*` - verifies checkout step generation - - `test_generate_agency_params_*` - verifies parameter generation + - `test_generate_copilot_params_*` - verifies parameter generation - `test_parse_markdown_*` - verifies markdown parsing including error cases - Template and structure validation tests diff --git a/tests/compiler_tests.rs b/tests/compiler_tests.rs index d6eadb79..8908288d 100644 --- a/tests/compiler_tests.rs +++ b/tests/compiler_tests.rs @@ -104,8 +104,8 @@ fn test_compiled_yaml_structure() { "Template should contain agent_name marker" ); assert!( - template_content.contains("{{ agency_params }}"), - "Template should contain agency_params marker" + template_content.contains("{{ copilot_params }}"), + "Template should contain copilot_params marker" ); assert!( template_content.contains("{{ compiler_version }}"), From 5850571762665d76840140f1ea830e3e4c0dbdbd Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 8 Apr 2026 09:52:38 +0000 Subject: [PATCH 3/9] feat: remove built-in MCP spawning via copilot mcp subcommand Agent-Logs-Url: https://github.com/githubnext/ado-aw/sessions/d23028c8-f3ae-424f-a2cc-6adb95730353 Co-authored-by: jamesadevine <4742697+jamesadevine@users.noreply.github.com> --- src/compile/standalone.rs | 73 +++++++-------------------------------- 1 file changed, 13 insertions(+), 60 deletions(-) diff --git a/src/compile/standalone.rs b/src/compile/standalone.rs index b2806e06..174d634c 100644 --- a/src/compile/standalone.rs +++ b/src/compile/standalone.rs @@ -387,41 +387,16 @@ pub fn generate_firewall_config(front_matter: &FrontMatter) -> FirewallConfig { }, spawn_timeout_secs: 30, } - } else if common::is_builtin_mcp(name) { - // Built-in MCP with options - let mut args = vec!["mcp".to_string(), name.clone()]; - args.extend(opts.args.clone()); - - UpstreamConfig { - command: "copilot".to_string(), - args, - env: opts.env.clone(), - allowed: if opts.allowed.is_empty() { - vec!["*".to_string()] - } else { - opts.allowed.clone() - }, - spawn_timeout_secs: 30, - } } else { log::warn!( - "MCP '{}' has no command and is not a built-in - skipping", + "MCP '{}' has no command - skipping", name ); continue; } - } else if common::is_builtin_mcp(name) { - // Built-in MCP with simple enablement - UpstreamConfig { - command: "copilot".to_string(), - args: vec!["mcp".to_string(), name.clone()], - env: HashMap::new(), - allowed: vec!["*".to_string()], - spawn_timeout_secs: 30, - } } else { log::warn!( - "MCP '{}' is not a built-in and has no command - skipping", + "MCP '{}' has no command - skipping", name ); continue; @@ -500,38 +475,6 @@ mod tests { fm } - #[test] - fn test_generate_firewall_config_builtin_simple_enabled() { - let mut fm = minimal_front_matter(); - fm.mcp_servers - .insert("ado".to_string(), McpConfig::Enabled(true)); - let config = generate_firewall_config(&fm); - let upstream = config.upstreams.get("ado").unwrap(); - assert_eq!(upstream.command, "copilot"); - assert_eq!(upstream.args, vec!["mcp", "ado"]); - assert_eq!(upstream.allowed, vec!["*"]); - } - - #[test] - fn test_generate_firewall_config_builtin_with_allowed_list() { - let mut fm = minimal_front_matter(); - fm.mcp_servers.insert( - "icm".to_string(), - McpConfig::WithOptions(McpOptions { - allowed: vec!["create_incident".to_string(), "get_incident".to_string()], - ..Default::default() - }), - ); - let config = generate_firewall_config(&fm); - let upstream = config.upstreams.get("icm").unwrap(); - assert_eq!(upstream.command, "copilot"); - assert_eq!(upstream.args, vec!["mcp", "icm"]); - assert_eq!( - upstream.allowed, - vec!["create_incident".to_string(), "get_incident".to_string()] - ); - } - #[test] fn test_generate_firewall_config_custom_mcp() { let mut fm = minimal_front_matter(); @@ -569,7 +512,7 @@ mod tests { #[test] fn test_generate_firewall_config_unknown_non_builtin_skipped() { - // An MCP that is neither built-in nor has a command should be skipped + // An MCP with no command should be skipped let mut fm = minimal_front_matter(); fm.mcp_servers .insert("phantom".to_string(), McpConfig::Enabled(true)); @@ -577,6 +520,16 @@ mod tests { assert!(!config.upstreams.contains_key("phantom")); } + #[test] + fn test_generate_firewall_config_builtin_without_command_skipped() { + // A built-in MCP enabled without a custom command should be skipped + let mut fm = minimal_front_matter(); + fm.mcp_servers + .insert("ado".to_string(), McpConfig::Enabled(true)); + let config = generate_firewall_config(&fm); + assert!(!config.upstreams.contains_key("ado")); + } + #[test] fn test_generate_firewall_config_disabled_mcp_skipped() { let mut fm = minimal_front_matter(); From f1c229a2067dd9bbdbd3e878ababeef2c4e70914 Mon Sep 17 00:00:00 2001 From: James Devine Date: Wed, 8 Apr 2026 10:53:29 +0100 Subject: [PATCH 4/9] feat: add COPILOT_CLI_VERSION to dependency version updater workflow Expand the update-awf-version workflow to also check for new releases of github/copilot-cli and open PRs to update the COPILOT_CLI_VERSION constant. Bumps max PRs from 1 to 2 to allow both dependencies to be updated in a single run. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/update-awf-version.lock.yml | 64 ++++++------- .github/workflows/update-awf-version.md | 91 +++++++++++++------ 2 files changed, 93 insertions(+), 62 deletions(-) diff --git a/.github/workflows/update-awf-version.lock.yml b/.github/workflows/update-awf-version.lock.yml index 45fe2b95..f259c527 100644 --- a/.github/workflows/update-awf-version.lock.yml +++ b/.github/workflows/update-awf-version.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"b991f6b4afcb78c714c46ba2984d6e655428d74b54b3a0c69db5b59f869562fc","compiler_version":"v0.67.1","strict":true,"agent_id":"copilot"} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"1a67f7d6519b4cb5693bc9f57a290b6af80255a98e046ffde1a394b4adc50186","compiler_version":"v0.67.1","strict":true,"agent_id":"copilot"} # ___ _ _ # / _ \ | | (_) # | |_| | __ _ ___ _ __ | |_ _ ___ @@ -21,7 +21,7 @@ # # For more information: https://github.github.com/gh-aw/introduction/overview/ # -# Checks for new releases of gh-aw-firewall and opens a PR to update the AWF_VERSION constant +# Checks for new releases of gh-aw-firewall and copilot-cli, and opens PRs to update pinned version constants # # Secrets used: # - COPILOT_GITHUB_TOKEN @@ -37,7 +37,7 @@ # - actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7 # - github/gh-aw-actions/setup@80471a493be8c528dd27daf73cd644242a7965e0 # v0.67.1 -name: "AWF Version Updater" +name: "Dependency Version Updater" "on": schedule: - cron: "19 11 * * *" @@ -55,7 +55,7 @@ permissions: {} concurrency: group: "gh-aw-${{ github.workflow }}" -run-name: "AWF Version Updater" +run-name: "Dependency Version Updater" jobs: activation: @@ -85,7 +85,7 @@ jobs: GH_AW_INFO_VERSION: "latest" GH_AW_INFO_AGENT_VERSION: "latest" GH_AW_INFO_CLI_VERSION: "v0.67.1" - GH_AW_INFO_WORKFLOW_NAME: "AWF Version Updater" + GH_AW_INFO_WORKFLOW_NAME: "Dependency Version Updater" GH_AW_INFO_EXPERIMENTAL: "false" GH_AW_INFO_SUPPORTS_TOOLS_ALLOWLIST: "true" GH_AW_INFO_STAGED: "false" @@ -153,19 +153,19 @@ jobs: run: | bash ${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh { - cat << 'GH_AW_PROMPT_3461ee08f79e2cfb_EOF' + cat << 'GH_AW_PROMPT_e64d693612e00cf8_EOF' - GH_AW_PROMPT_3461ee08f79e2cfb_EOF + GH_AW_PROMPT_e64d693612e00cf8_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_3461ee08f79e2cfb_EOF' + cat << 'GH_AW_PROMPT_e64d693612e00cf8_EOF' - Tools: create_pull_request, missing_tool, missing_data, noop - GH_AW_PROMPT_3461ee08f79e2cfb_EOF + Tools: create_pull_request(max:2), missing_tool, missing_data, noop + GH_AW_PROMPT_e64d693612e00cf8_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_create_pull_request.md" - cat << 'GH_AW_PROMPT_3461ee08f79e2cfb_EOF' + cat << 'GH_AW_PROMPT_e64d693612e00cf8_EOF' The following GitHub context information is available for this workflow: @@ -195,12 +195,12 @@ jobs: {{/if}} - GH_AW_PROMPT_3461ee08f79e2cfb_EOF + GH_AW_PROMPT_e64d693612e00cf8_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_3461ee08f79e2cfb_EOF' + cat << 'GH_AW_PROMPT_e64d693612e00cf8_EOF' {{#runtime-import .github/workflows/update-awf-version.md}} - GH_AW_PROMPT_3461ee08f79e2cfb_EOF + GH_AW_PROMPT_e64d693612e00cf8_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 @@ -366,21 +366,21 @@ jobs: mkdir -p ${RUNNER_TEMP}/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs - cat > ${RUNNER_TEMP}/gh-aw/safeoutputs/config.json << 'GH_AW_SAFE_OUTPUTS_CONFIG_388b6606edb43e2b_EOF' - {"create_pull_request":{"max":1,"max_patch_size":1024,"protected_files":["package.json","bun.lockb","bunfig.toml","deno.json","deno.jsonc","deno.lock","global.json","NuGet.Config","Directory.Packages.props","mix.exs","mix.lock","go.mod","go.sum","stack.yaml","stack.yaml.lock","pom.xml","build.gradle","build.gradle.kts","settings.gradle","settings.gradle.kts","gradle.properties","package-lock.json","yarn.lock","pnpm-lock.yaml","npm-shrinkwrap.json","requirements.txt","Pipfile","Pipfile.lock","pyproject.toml","setup.py","setup.cfg","Gemfile","Gemfile.lock","uv.lock","CODEOWNERS"],"protected_path_prefixes":[".github/",".agents/"]},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{}} - GH_AW_SAFE_OUTPUTS_CONFIG_388b6606edb43e2b_EOF + cat > ${RUNNER_TEMP}/gh-aw/safeoutputs/config.json << 'GH_AW_SAFE_OUTPUTS_CONFIG_7e514d4d02d45859_EOF' + {"create_pull_request":{"max":2,"max_patch_size":1024,"protected_files":["package.json","bun.lockb","bunfig.toml","deno.json","deno.jsonc","deno.lock","global.json","NuGet.Config","Directory.Packages.props","mix.exs","mix.lock","go.mod","go.sum","stack.yaml","stack.yaml.lock","pom.xml","build.gradle","build.gradle.kts","settings.gradle","settings.gradle.kts","gradle.properties","package-lock.json","yarn.lock","pnpm-lock.yaml","npm-shrinkwrap.json","requirements.txt","Pipfile","Pipfile.lock","pyproject.toml","setup.py","setup.cfg","Gemfile","Gemfile.lock","uv.lock","CODEOWNERS"],"protected_path_prefixes":[".github/",".agents/"]},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{}} + GH_AW_SAFE_OUTPUTS_CONFIG_7e514d4d02d45859_EOF - name: Write Safe Outputs Tools run: | - cat > ${RUNNER_TEMP}/gh-aw/safeoutputs/tools_meta.json << 'GH_AW_SAFE_OUTPUTS_TOOLS_META_3037a36620314c99_EOF' + cat > ${RUNNER_TEMP}/gh-aw/safeoutputs/tools_meta.json << 'GH_AW_SAFE_OUTPUTS_TOOLS_META_70ec49d4354263d0_EOF' { "description_suffixes": { - "create_pull_request": " CONSTRAINTS: Maximum 1 pull request(s) can be created." + "create_pull_request": " CONSTRAINTS: Maximum 2 pull request(s) can be created." }, "repo_params": {}, "dynamic_tools": [] } - GH_AW_SAFE_OUTPUTS_TOOLS_META_3037a36620314c99_EOF - cat > ${RUNNER_TEMP}/gh-aw/safeoutputs/validation.json << 'GH_AW_SAFE_OUTPUTS_VALIDATION_ac0d2846f06392ec_EOF' + GH_AW_SAFE_OUTPUTS_TOOLS_META_70ec49d4354263d0_EOF + cat > ${RUNNER_TEMP}/gh-aw/safeoutputs/validation.json << 'GH_AW_SAFE_OUTPUTS_VALIDATION_18cef1809d034527_EOF' { "create_pull_request": { "defaultMax": 1, @@ -492,7 +492,7 @@ jobs: } } } - GH_AW_SAFE_OUTPUTS_VALIDATION_ac0d2846f06392ec_EOF + GH_AW_SAFE_OUTPUTS_VALIDATION_18cef1809d034527_EOF node ${RUNNER_TEMP}/gh-aw/actions/generate_safe_outputs_tools.cjs - name: Generate Safe Outputs MCP Server Config id: safe-outputs-config @@ -562,7 +562,7 @@ jobs: export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host -v /var/run/docker.sock:/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_API_KEY -e MCP_GATEWAY_PAYLOAD_DIR -e MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -e DEBUG -e MCP_GATEWAY_LOG_DIR -e GH_AW_MCP_LOG_DIR -e GH_AW_SAFE_OUTPUTS -e GH_AW_SAFE_OUTPUTS_CONFIG_PATH -e GH_AW_SAFE_OUTPUTS_TOOLS_PATH -e GH_AW_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.2.14' mkdir -p /home/runner/.copilot - cat << GH_AW_MCP_CONFIG_8450003ef118a360_EOF | bash ${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.sh + cat << GH_AW_MCP_CONFIG_3df14ab9d8aea843_EOF | bash ${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.sh { "mcpServers": { "github": { @@ -603,7 +603,7 @@ jobs: "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" } } - GH_AW_MCP_CONFIG_8450003ef118a360_EOF + GH_AW_MCP_CONFIG_3df14ab9d8aea843_EOF - name: Download activation artifact uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: @@ -846,7 +846,7 @@ jobs: env: GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} GH_AW_NOOP_MAX: "1" - GH_AW_WORKFLOW_NAME: "AWF Version Updater" + GH_AW_WORKFLOW_NAME: "Dependency Version Updater" GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }} GH_AW_NOOP_REPORT_AS_ISSUE: "true" @@ -863,7 +863,7 @@ jobs: env: GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} GH_AW_MISSING_TOOL_CREATE_ISSUE: "true" - GH_AW_WORKFLOW_NAME: "AWF Version Updater" + GH_AW_WORKFLOW_NAME: "Dependency Version Updater" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | @@ -877,7 +877,7 @@ jobs: env: GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} GH_AW_REPORT_INCOMPLETE_CREATE_ISSUE: "true" - GH_AW_WORKFLOW_NAME: "AWF Version Updater" + GH_AW_WORKFLOW_NAME: "Dependency Version Updater" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | @@ -891,7 +891,7 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} - GH_AW_WORKFLOW_NAME: "AWF Version Updater" + GH_AW_WORKFLOW_NAME: "Dependency Version Updater" GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }} GH_AW_WORKFLOW_ID: "update-awf-version" @@ -993,8 +993,8 @@ jobs: if: always() && steps.detection_guard.outputs.run_detection == 'true' uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: - WORKFLOW_NAME: "AWF Version Updater" - WORKFLOW_DESCRIPTION: "Checks for new releases of gh-aw-firewall and opens a PR to update the AWF_VERSION constant" + WORKFLOW_NAME: "Dependency Version Updater" + WORKFLOW_DESCRIPTION: "Checks for new releases of gh-aw-firewall and copilot-cli, and opens PRs to update pinned version constants" HAS_PATCH: ${{ needs.agent.outputs.has_patch }} with: script: | @@ -1081,7 +1081,7 @@ jobs: GH_AW_ENGINE_ID: "copilot" GH_AW_ENGINE_MODEL: ${{ needs.agent.outputs.model }} GH_AW_WORKFLOW_ID: "update-awf-version" - GH_AW_WORKFLOW_NAME: "AWF Version Updater" + GH_AW_WORKFLOW_NAME: "Dependency Version Updater" outputs: code_push_failure_count: ${{ steps.process_safe_outputs.outputs.code_push_failure_count }} code_push_failure_errors: ${{ steps.process_safe_outputs.outputs.code_push_failure_errors }} @@ -1158,7 +1158,7 @@ jobs: GH_AW_ALLOWED_DOMAINS: "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_pull_request\":{\"max\":1,\"max_patch_size\":1024,\"protected_files\":[\"package.json\",\"bun.lockb\",\"bunfig.toml\",\"deno.json\",\"deno.jsonc\",\"deno.lock\",\"global.json\",\"NuGet.Config\",\"Directory.Packages.props\",\"mix.exs\",\"mix.lock\",\"go.mod\",\"go.sum\",\"stack.yaml\",\"stack.yaml.lock\",\"pom.xml\",\"build.gradle\",\"build.gradle.kts\",\"settings.gradle\",\"settings.gradle.kts\",\"gradle.properties\",\"package-lock.json\",\"yarn.lock\",\"pnpm-lock.yaml\",\"npm-shrinkwrap.json\",\"requirements.txt\",\"Pipfile\",\"Pipfile.lock\",\"pyproject.toml\",\"setup.py\",\"setup.cfg\",\"Gemfile\",\"Gemfile.lock\",\"uv.lock\",\"CODEOWNERS\",\"AGENTS.md\"],\"protected_path_prefixes\":[\".github/\",\".agents/\"]},\"create_report_incomplete_issue\":{},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"true\"},\"report_incomplete\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_pull_request\":{\"max\":2,\"max_patch_size\":1024,\"protected_files\":[\"package.json\",\"bun.lockb\",\"bunfig.toml\",\"deno.json\",\"deno.jsonc\",\"deno.lock\",\"global.json\",\"NuGet.Config\",\"Directory.Packages.props\",\"mix.exs\",\"mix.lock\",\"go.mod\",\"go.sum\",\"stack.yaml\",\"stack.yaml.lock\",\"pom.xml\",\"build.gradle\",\"build.gradle.kts\",\"settings.gradle\",\"settings.gradle.kts\",\"gradle.properties\",\"package-lock.json\",\"yarn.lock\",\"pnpm-lock.yaml\",\"npm-shrinkwrap.json\",\"requirements.txt\",\"Pipfile\",\"Pipfile.lock\",\"pyproject.toml\",\"setup.py\",\"setup.cfg\",\"Gemfile\",\"Gemfile.lock\",\"uv.lock\",\"CODEOWNERS\",\"AGENTS.md\"],\"protected_path_prefixes\":[\".github/\",\".agents/\"]},\"create_report_incomplete_issue\":{},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"true\"},\"report_incomplete\":{}}" GH_AW_CI_TRIGGER_TOKEN: ${{ secrets.GH_AW_CI_TRIGGER_TOKEN }} with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/update-awf-version.md b/.github/workflows/update-awf-version.md index b03f7f1e..a7d28ec9 100644 --- a/.github/workflows/update-awf-version.md +++ b/.github/workflows/update-awf-version.md @@ -1,7 +1,7 @@ --- on: schedule: daily -description: Checks for new releases of gh-aw-firewall and opens a PR to update the AWF_VERSION constant +description: Checks for new releases of gh-aw-firewall and copilot-cli, and opens PRs to update pinned version constants permissions: contents: read issues: read @@ -13,56 +13,87 @@ network: allowed: [defaults] safe-outputs: create-pull-request: - max: 1 + max: 2 --- -# AWF Version Updater +# Dependency Version Updater You are a dependency maintenance bot for the **ado-aw** project — a Rust CLI compiler that transforms markdown agent definitions into Azure DevOps pipeline YAML. ## Your Task -Check whether the `AWF_VERSION` constant in `src/compile/common.rs` is up to date with the latest release of [gh-aw-firewall](https://github.com/github/gh-aw-firewall). If a newer version is available, open a PR to update it. +Check whether pinned version constants in `src/compile/common.rs` are up to date with the latest releases of their upstream dependencies. For each outdated constant, open a PR to update it. -## Step 1: Get the Latest gh-aw-firewall Release +There are two dependencies to check: -Fetch the latest release of the `github/gh-aw-firewall` repository. Record the tag name, stripping any leading `v` prefix to get the bare version number (e.g. `v0.24.0` → `0.24.0`). +| Constant | Upstream Repository | Example value | +|----------|-------------------|---------------| +| `AWF_VERSION` | [github/gh-aw-firewall](https://github.com/github/gh-aw-firewall) | `0.25.14` | +| `COPILOT_CLI_VERSION` | [github/copilot-cli](https://github.com/github/copilot-cli) | `1.0.6` | -## Step 2: Read the Current AWF_VERSION +Run the following steps **independently for each dependency**. One may be up to date while the other is not. -Read the file `src/compile/common.rs` in this repository and find the line: +--- + +## For each dependency: + +### Step 1: Get the Latest Release + +Fetch the latest release of the upstream repository. Record the tag name, stripping any leading `v` prefix to get the bare version number (e.g. `v0.24.0` → `0.24.0`). + +### Step 2: Read the Current Version + +Read the file `src/compile/common.rs` in this repository and find the corresponding constant: + +- `pub const AWF_VERSION: &str = "...";` +- `pub const COPILOT_CLI_VERSION: &str = "...";` + +Extract the version string. + +### Step 3: Compare Versions + +If the current constant already matches the latest release, **skip this dependency** — it is up to date. + +Before proceeding, also check whether a PR already exists with a title matching the expected PR title (see Step 4). If one is already open, **skip this dependency** to avoid duplicates. + +### Step 4: Create an Update PR + +If the latest version is newer than the current constant: -```rust -pub const AWF_VERSION: &str = "..."; -``` +1. Edit `src/compile/common.rs` — update **only** the relevant version string literal. Do not modify anything else in the file. -Extract the version string from that line. +2. Create a pull request: -## Step 3: Compare Versions +**For AWF_VERSION:** +- **Title**: `chore: update AWF_VERSION to ` +- **Body**: + ```markdown + ## Dependency Update -If the current `AWF_VERSION` already matches the latest release, **do nothing and stop**. The dependency is up to date. + Updates the pinned `AWF_VERSION` constant in `src/compile/common.rs` from `` to ``. -Before proceeding, also check whether a PR already exists with a title matching `chore: update AWF_VERSION to `. If one is already open, **do nothing and stop** to avoid duplicates. + ### Release -## Step 4: Create an Update PR + See the [gh-aw-firewall release notes](https://github.com/github/gh-aw-firewall/releases/tag/v) for details. -If the latest version is newer than `AWF_VERSION`: + --- + *This PR was opened automatically by the dependency version updater workflow.* + ``` -1. Edit `src/compile/common.rs` — update the `AWF_VERSION` string literal to the new version. Change only that single string value; do not modify anything else in the file. +**For COPILOT_CLI_VERSION:** +- **Title**: `chore: update COPILOT_CLI_VERSION to ` +- **Body**: + ```markdown + ## Dependency Update -2. Create a pull request with: - - **Title**: `chore: update AWF_VERSION to ` - - **Body**: - ```markdown - ## Dependency Update + Updates the pinned `COPILOT_CLI_VERSION` constant in `src/compile/common.rs` from `` to ``. - Updates the pinned `AWF_VERSION` constant in `src/compile/common.rs` from `` to ``. + ### Release - ### Release + See the [copilot-cli release notes](https://github.com/github/copilot-cli/releases/tag/v) for details. - See the [gh-aw-firewall release notes](https://github.com/github/gh-aw-firewall/releases/tag/v) for details. + --- + *This PR was opened automatically by the dependency version updater workflow.* + ``` - --- - *This PR was opened automatically by the AWF version updater workflow.* - ``` - - **Base branch**: `main` +- **Base branch**: `main` From 4c814112502124399aafa8dd979286f3e83a9755 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 8 Apr 2026 10:11:23 +0000 Subject: [PATCH 5/9] docs: remove agency-style built-in MCP references from AGENTS.md Agent-Logs-Url: https://github.com/githubnext/ado-aw/sessions/b1199267-7b57-4f8e-b88f-9241078a80c7 Co-authored-by: jamesadevine <4742697+jamesadevine@users.noreply.github.com> --- AGENTS.md | 109 ++++++++++++++---------------------------------------- 1 file changed, 28 insertions(+), 81 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 373e29b6..baba175f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -439,13 +439,13 @@ Should be replaced with the human-readable name from the front matter (e.g., "Da Additional params provided to copilot CLI. The compiler generates: - `--model ` - AI model from `engine` front matter field (default: claude-opus-4.5) -- `--disable-builtin-mcps` - Disables all built-in MCPs initially +- `--disable-builtin-mcps` - Disables all of the Copilot CLI's built-in MCPs initially - `--no-ask-user` - Prevents interactive prompts - `--allow-tool ` - Explicitly allows specific tools (github, safeoutputs, write, shell commands like cat, date, echo, grep, head, ls, pwd, sort, tail, uniq, wc, yq) -- `--disable-mcp-server ` - Disables specific MCPs (all built-in MCPs are disabled by default and must be explicitly enabled via mcp-servers config) -- `--mcp ` - Enables MCPs specified in front matter +- `--disable-mcp-server ` - Disables specific Copilot CLI MCPs +- `--mcp ` - Re-enables specific Copilot CLI MCPs listed in `mcp-servers:` (without a `command:` field) -Only built-in MCPs are passed via params. Custom MCPs (with command field) are handled separately. +Custom MCPs (with `command:` field) are handled separately via the MCP firewall config. ## {{ pool }} @@ -688,16 +688,16 @@ Should be replaced with the agent context root for 1ES Agency jobs. This determi ## {{ mcp_configuration }} -Should be replaced with the MCP server configuration for 1ES templates. For each enabled built-in MCP, generates service connection references: +Should be replaced with the MCP server configuration for 1ES templates. For each `mcp-servers:` entry without a `command:` field, generates a service connection reference using the entry name: ```yaml -ado: - serviceConnection: mcp-ado-service-connection -kusto: - serviceConnection: mcp-kusto-service-connection +my-mcp: + serviceConnection: mcp-my-mcp-service-connection +other-mcp: + serviceConnection: mcp-other-mcp-service-connection ``` -Custom MCP servers (with `command:` field) are not supported in 1ES target. Only built-in MCPs with corresponding service connections are supported. +Custom MCP servers (with `command:` field) are not supported in 1ES target. Only entries without a `command:` (which have a corresponding service connection) are supported. ## {{ global_options }} @@ -1081,30 +1081,7 @@ cargo add ## MCP Configuration -The `mcp-servers:` field provides a unified way to configure both built-in and custom MCP (Model Context Protocol) servers. The compiler distinguishes between them by checking for the `command:` field—if present, it's a custom server; otherwise, it's a built-in. - -### Built-in MCP Servers - -Enable built-in servers with `true` or configure them with options: - -```yaml -mcp-servers: - ado: true # enabled with all default functions - ado-ext: true # Extended ADO functionality - asa: true # Azure Stream Analytics MCP - bluebird: true # Bluebird MCP - calculator: true # Calculator MCP - es-chat: true - icm: # enabled with restricted functions - allowed: - - create_incident - - get_incident - kusto: - allowed: - - query - msft-learn: true - stack: true # Stack MCP -``` +The `mcp-servers:` field configures custom MCP (Model Context Protocol) servers that the agent can use. Each entry must include a `command:` field specifying the executable to spawn. ### Custom MCP Servers @@ -1122,28 +1099,16 @@ mcp-servers: ### Configuration Properties -**For built-in MCPs:** -- `true` - Enable with all default functions -- `allowed:` - Array of function names to restrict available tools -- `service-connection:` - (1ES target only) Override the service connection name used for this MCP. If not specified, defaults to `mcp--service-connection` (e.g., `mcp-ado-service-connection` for the `ado` MCP) - -**For custom MCPs (requires `command:`):** - `command:` - The executable to run (e.g., `"node"`, `"python"`, `"dotnet"`) - `args:` - Array of command-line arguments passed to the command - `allowed:` - Array of function names agents are permitted to call (required for security) - `env:` - Optional environment variables for the MCP server process +- `service-connection:` - (1ES target only) Override the service connection name used for this MCP. If not specified, defaults to `mcp--service-connection` -### Example: Mixed Configuration +### Example: Multiple Custom MCP Servers ```yaml mcp-servers: - # Built-in servers - ado: true - ado-ext: true - es-chat: true - icm: - allowed: [create_incident, get_incident] - # Custom Python MCP server data-processor: command: "python" @@ -1169,7 +1134,6 @@ mcp-servers: 2. **Command Validation**: The compiler validates that commands are from a trusted set 3. **Argument Sanitization**: Arguments are validated to prevent injection attacks 4. **Environment Isolation**: MCP servers run in the same isolated sandbox as the pipeline -5. **Built-in Trust**: Built-in MCPs are pre-vetted; custom MCPs require explicit `allowed:` list ## Network Isolation (AWF) @@ -1285,17 +1249,13 @@ When agents are configured with multiple MCPs (e.g., `ado`, `kusto`, `icm`), the ``` ┌─────────────┐ ┌──────────────────┐ ┌─────────────────┐ -│ │ │ │ │ ado MCP │ -│ Agent │────▶│ MCP Firewall │────▶│ (copilot mcp ado)│ -│ (Agency) │ │ │ └─────────────────┘ +│ │ │ │ │ custom MCP │ +│ Agent │────▶│ MCP Firewall │────▶│ (node server.js)│ +│ (Copilot) │ │ │ └─────────────────┘ │ │ │ - Policy check │ ┌─────────────────┐ -└─────────────┘ │ - Tool routing │────▶│ icm MCP │ - │ - Audit logging │ │ (copilot mcp icm)│ +└─────────────┘ │ - Tool routing │────▶│ custom MCP │ + │ - Audit logging │ │ (python -m ...) │ └──────────────────┘ └─────────────────┘ - ┌─────────────────┐ - ────▶│ custom MCP │ - │ (node server.js)│ - └─────────────────┘ ``` ### Configuration File Format @@ -1305,23 +1265,11 @@ The firewall reads a JSON configuration file at runtime: ```json { "upstreams": { - "ado": { - "command": "copilot", - "args": ["mcp", "ado"], - "env": {}, - "allowed": ["*"] - }, - "icm": { - "command": "copilot", - "args": ["mcp", "icm"], - "env": {}, - "allowed": ["create_incident", "get_incident"] - }, - "kusto": { - "command": "copilot", - "args": ["mcp", "kusto"], - "env": {}, - "allowed": ["query"] + "data-processor": { + "command": "python", + "args": ["-m", "my_mcp_server"], + "env": { "DATA_DIR": "/data" }, + "allowed": ["process_data", "query_database"] }, "custom-tool": { "command": "node", @@ -1360,9 +1308,8 @@ The `allowed` field supports several patterns: All tools exposed by the firewall are namespaced with their upstream name: -- `ado:create-work-item` - from the `ado` upstream -- `icm:create_incident` - from the `icm` upstream -- `kusto:query` - from the `kusto` upstream +- `data-processor:process_data` - from the `data-processor` upstream +- `custom-tool:get_status` - from the `custom-tool` upstream This prevents tool name collisions and makes it clear which upstream handles each call. @@ -1388,9 +1335,9 @@ The firewall config is written to `$(Agent.TempDirectory)/staging/mcp-firewall-c All tool call attempts are logged to the centralized log file at `$HOME/.ado-aw/logs/YYYY-MM-DD.log`: ``` -[2026-01-29T10:15:32Z] [INFO] [firewall] ALLOWED icm:create_incident (args: {"title": "...", "severity": 3}) -[2026-01-29T10:15:45Z] [INFO] [firewall] BLOCKED icm:delete_incident (not in allowlist) -[2026-01-29T10:16:01Z] [INFO] [firewall] ALLOWED kusto:query (args: {"cluster": "...", "query": "..."}) +[2026-01-29T10:15:32Z] [INFO] [firewall] ALLOWED custom-tool:process_data (args: {"input": "..."}) +[2026-01-29T10:15:45Z] [INFO] [firewall] BLOCKED custom-tool:delete_all (not in allowlist) +[2026-01-29T10:16:01Z] [INFO] [firewall] ALLOWED data-processor:query_database (args: {"query": "..."}) ``` This provides a complete audit trail of agent actions for security review. From ad38bc9364858e327c0c016c555c6acef94f490c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 8 Apr 2026 10:23:23 +0000 Subject: [PATCH 6/9] fix: remove --mcp flag generation from generate_copilot_params; Copilot CLI has no mcp subcommand Agent-Logs-Url: https://github.com/githubnext/ado-aw/sessions/5780d9cc-3b6e-4640-bd7b-df37f2acb416 Co-authored-by: jamesadevine <4742697+jamesadevine@users.noreply.github.com> --- AGENTS.md | 1 - src/compile/common.rs | 31 +++---------------------------- 2 files changed, 3 insertions(+), 29 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index baba175f..0f797f98 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -443,7 +443,6 @@ Additional params provided to copilot CLI. The compiler generates: - `--no-ask-user` - Prevents interactive prompts - `--allow-tool ` - Explicitly allows specific tools (github, safeoutputs, write, shell commands like cat, date, echo, grep, head, ls, pwd, sort, tail, uniq, wc, yq) - `--disable-mcp-server ` - Disables specific Copilot CLI MCPs -- `--mcp ` - Re-enables specific Copilot CLI MCPs listed in `mcp-servers:` (without a `command:` field) Custom MCPs (with `command:` field) are handled separately via the MCP firewall config. diff --git a/src/compile/common.rs b/src/compile/common.rs index 3fb7917d..388ac479 100644 --- a/src/compile/common.rs +++ b/src/compile/common.rs @@ -2,11 +2,11 @@ use anyhow::{Context, Result}; -use super::types::{FrontMatter, McpConfig, Repository, TriggerConfig}; +use super::types::{FrontMatter, Repository, TriggerConfig}; use crate::fuzzy_schedule; use crate::mcp_metadata::McpMetadataFile; -/// Check if an MCP name is a built-in (launched via copilot mcp) +/// Check if an MCP name is a built-in (known to the Copilot CLI via mcp-metadata.json) pub fn is_builtin_mcp(name: &str) -> bool { let metadata = McpMetadataFile::bundled(); metadata.get(name).map(|m| m.builtin).unwrap_or(false) @@ -327,22 +327,6 @@ pub fn generate_copilot_params(front_matter: &FrontMatter) -> String { params.push(format!("--disable-mcp-server {}", mcp)); } - for (name, config) in &front_matter.mcp_servers { - let is_custom = matches!(config, McpConfig::WithOptions(opts) if opts.command.is_some()); - if is_custom { - continue; - } - - let is_enabled = match config { - McpConfig::Enabled(enabled) => *enabled, - McpConfig::WithOptions(_) => true, - }; - - if is_enabled { - params.push(format!("--mcp {}", name)); - } - } - params.join(" ") } @@ -871,7 +855,7 @@ mod tests { } #[test] - fn test_copilot_params_custom_mcp_not_added_with_mcp_flag() { + fn test_copilot_params_custom_mcp_no_mcp_flag() { let mut fm = minimal_front_matter(); fm.mcp_servers.insert( "my-tool".to_string(), @@ -885,15 +869,6 @@ mod tests { assert!(!params.contains("--mcp my-tool")); } - #[test] - fn test_copilot_params_builtin_mcp_added_with_mcp_flag() { - let mut fm = minimal_front_matter(); - fm.mcp_servers - .insert("ado".to_string(), McpConfig::Enabled(true)); - let params = generate_copilot_params(&fm); - assert!(params.contains("--mcp ado")); - } - // ─── sanitize_filename ──────────────────────────────────────────────────── #[test] From ecc15f188ae1e344e3276f123e4aa9af8d355859 Mon Sep 17 00:00:00 2001 From: James Devine Date: Wed, 8 Apr 2026 12:37:52 +0100 Subject: [PATCH 7/9] fix: restore builtin MCP --mcp flag generation in copilot params The MCP server iteration that adds --mcp flags for enabled built-in MCPs was accidentally removed during the agency rename refactor. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/compile/common.rs | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/compile/common.rs b/src/compile/common.rs index 6828900f..858d2ab3 100644 --- a/src/compile/common.rs +++ b/src/compile/common.rs @@ -2,7 +2,7 @@ use anyhow::{Context, Result}; -use super::types::{FrontMatter, Repository, TriggerConfig}; +use super::types::{FrontMatter, McpConfig, Repository, TriggerConfig}; use crate::fuzzy_schedule; use crate::mcp_metadata::McpMetadataFile; @@ -349,6 +349,23 @@ pub fn generate_copilot_params(front_matter: &FrontMatter) -> String { params.push(format!("--disable-mcp-server {}", mcp)); } + // Enable built-in MCPs that are configured in front matter + for (name, config) in &front_matter.mcp_servers { + let is_custom = matches!(config, McpConfig::WithOptions(opts) if opts.command.is_some()); + if is_custom { + continue; + } + + let is_enabled = match config { + McpConfig::Enabled(enabled) => *enabled, + McpConfig::WithOptions(_) => true, + }; + + if is_enabled { + params.push(format!("--mcp {}", name)); + } + } + params.join(" ") } From b271dfce3baf5bde0436065e2c2f22559ee0c191 Mon Sep 17 00:00:00 2001 From: James Devine Date: Wed, 8 Apr 2026 12:39:08 +0100 Subject: [PATCH 8/9] fix: remove --mcp flag generation for builtin MCPs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Copilot CLI has no built-in MCPs — all MCPs are handled via the MCP firewall. Update the test to assert --mcp flags are not generated. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/compile/common.rs | 25 ++++--------------------- 1 file changed, 4 insertions(+), 21 deletions(-) diff --git a/src/compile/common.rs b/src/compile/common.rs index 858d2ab3..891f48de 100644 --- a/src/compile/common.rs +++ b/src/compile/common.rs @@ -2,7 +2,7 @@ use anyhow::{Context, Result}; -use super::types::{FrontMatter, McpConfig, Repository, TriggerConfig}; +use super::types::{FrontMatter, Repository, TriggerConfig}; use crate::fuzzy_schedule; use crate::mcp_metadata::McpMetadataFile; @@ -349,23 +349,6 @@ pub fn generate_copilot_params(front_matter: &FrontMatter) -> String { params.push(format!("--disable-mcp-server {}", mcp)); } - // Enable built-in MCPs that are configured in front matter - for (name, config) in &front_matter.mcp_servers { - let is_custom = matches!(config, McpConfig::WithOptions(opts) if opts.command.is_some()); - if is_custom { - continue; - } - - let is_enabled = match config { - McpConfig::Enabled(enabled) => *enabled, - McpConfig::WithOptions(_) => true, - }; - - if is_enabled { - params.push(format!("--mcp {}", name)); - } - } - params.join(" ") } @@ -900,17 +883,17 @@ mod tests { }), ); let params = generate_copilot_params(&fm); - // Custom MCPs (with command) should NOT appear as --mcp flags assert!(!params.contains("--mcp my-tool")); } #[test] - fn test_copilot_params_builtin_mcp_added_with_mcp_flag() { + fn test_copilot_params_builtin_mcp_no_mcp_flag() { let mut fm = minimal_front_matter(); fm.mcp_servers .insert("ado".to_string(), McpConfig::Enabled(true)); let params = generate_copilot_params(&fm); - assert!(params.contains("--mcp ado")); + // Copilot CLI has no built-in MCPs — all MCPs are handled via the MCP firewall + assert!(!params.contains("--mcp ado")); } #[test] From 8496590620e747fdf8ddbbd66efd71a9169edc0b Mon Sep 17 00:00:00 2001 From: James Devine Date: Wed, 8 Apr 2026 12:43:33 +0100 Subject: [PATCH 9/9] docs: update docs to reflect removal of --mcp flag generation All MCPs are now handled via the MCP firewall, not --mcp CLI flags. Renamed 'Agency parameters' to 'Copilot parameters' in test docs. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- AGENTS.md | 4 +--- tests/EXAMPLES.md | 4 +++- tests/QUICKREF.md | 2 +- tests/README.md | 2 +- tests/SUMMARY.md | 8 ++++---- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 8ce67970..0e4e3bbb 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -482,14 +482,12 @@ Should be replaced with the human-readable name from the front matter (e.g., "Da Additional params provided to copilot CLI. The compiler generates: - `--model ` - AI model from `engine` front matter field (default: claude-opus-4.5) -- `--max-turns ` - Maximum agentic turns from `engine.max-turns` (omitted when not set) -- `--max-timeout ` - Workflow timeout in minutes from `engine.timeout-minutes` (omitted when not set) - `--disable-builtin-mcps` - Disables all built-in MCPs initially - `--no-ask-user` - Prevents interactive prompts - `--allow-tool ` - Explicitly allows specific tools (github, safeoutputs, write, shell commands like cat, date, echo, grep, head, ls, pwd, sort, tail, uniq, wc, yq) - `--disable-mcp-server ` - Disables specific Copilot CLI MCPs -Custom MCPs (with `command:` field) are handled separately via the MCP firewall config. +All MCPs (both built-in and custom) are handled via the MCP firewall config, not via `--mcp` flags. ## {{ pool }} diff --git a/tests/EXAMPLES.md b/tests/EXAMPLES.md index 5cdbc33d..8fb0e037 100644 --- a/tests/EXAMPLES.md +++ b/tests/EXAMPLES.md @@ -81,7 +81,9 @@ fn test_with_hashmap() { let result = generate_copilot_params(&mcps); assert!(result.contains("--prompt")); - assert!(result.contains("--mcp ado") || result.contains("--mcp es-chat")); + // MCPs are handled via the MCP firewall, not --mcp flags + assert!(!result.contains("--mcp ado")); + assert!(!result.contains("--mcp es-chat")); } ``` diff --git a/tests/QUICKREF.md b/tests/QUICKREF.md index 5b9a0231..186f3b0b 100644 --- a/tests/QUICKREF.md +++ b/tests/QUICKREF.md @@ -49,7 +49,7 @@ ado-aw/ ✅ Schedule generation (hourly/daily) ✅ Repository configuration ✅ Checkout steps -✅ Agency parameters +✅ Copilot parameters ✅ Markdown parsing ✅ Error handling ✅ Edge cases diff --git a/tests/README.md b/tests/README.md index 861ca982..ac53fc6b 100644 --- a/tests/README.md +++ b/tests/README.md @@ -126,7 +126,7 @@ The current test suite provides coverage for: - ✅ Schedule generation - ✅ Repository configuration generation - ✅ Checkout step generation -- ✅ Agency parameter generation +- ✅ Copilot parameter generation - ✅ Markdown parsing - ✅ Template structure validation - ✅ Example file validation diff --git a/tests/SUMMARY.md b/tests/SUMMARY.md index f9958d39..13e775b2 100644 --- a/tests/SUMMARY.md +++ b/tests/SUMMARY.md @@ -27,9 +27,9 @@ Added 18 comprehensive unit tests in the `tests` module at the end of `main.rs`: - `test_generate_checkout_steps_empty` - Tests empty checkout list - `test_generate_checkout_steps_multiple` - Tests multiple checkout steps -#### Agency Parameters (3 tests) -- `test_generate_copilot_params_builtin_enabled` - Tests enabled built-in MCPs -- `test_generate_copilot_params_builtin_disabled` - Tests disabled MCPs +#### Copilot Parameters (3 tests) +- `test_copilot_params_custom_mcp_no_mcp_flag` - Verifies custom MCPs don't generate --mcp flags +- `test_copilot_params_builtin_mcp_no_mcp_flag` - Verifies built-in MCPs don't generate --mcp flags (all MCPs handled via firewall) - `test_generate_copilot_params_custom_mcp_skipped` - Verifies custom MCPs are skipped #### Markdown Parsing (4 tests) @@ -78,7 +78,7 @@ The test suite provides comprehensive coverage for: - Schedule generation (hourly/daily, deterministic) - Repository configuration generation - Checkout step generation -- Agency parameter generation +- Copilot parameter generation ✅ **Error Handling** - Missing front matter