diff --git a/.github/aw/actions-lock.json b/.github/aw/actions-lock.json new file mode 100644 index 0000000..5722fb8 --- /dev/null +++ b/.github/aw/actions-lock.json @@ -0,0 +1,29 @@ +{ + "entries": { + "actions/checkout@v6.0.2": { + "repo": "actions/checkout", + "version": "v6.0.2", + "sha": "de0fac2e4500dabe0009e67214ff5f5447ce83dd" + }, + "actions/download-artifact@v6.0.0": { + "repo": "actions/download-artifact", + "version": "v6.0.0", + "sha": "018cc2cf5baa6db3ef3c5f8a56943fffe632ef53" + }, + "actions/github-script@v8": { + "repo": "actions/github-script", + "version": "v8", + "sha": "ed597411d8f924073f98dfc5c65a23a2325f34cd" + }, + "actions/upload-artifact@v6.0.0": { + "repo": "actions/upload-artifact", + "version": "v6.0.0", + "sha": "b7c566a772e6b6bfb58ed0dc250532a479d7789f" + }, + "github/gh-aw/actions/setup@v0.45.7": { + "repo": "github/gh-aw/actions/setup", + "version": "v0.45.7", + "sha": "5d8900eb6f6230c9d41a3c30af320150a2361285" + } + } +} diff --git a/.github/aw/logs/.gitignore b/.github/aw/logs/.gitignore new file mode 100644 index 0000000..986a321 --- /dev/null +++ b/.github/aw/logs/.gitignore @@ -0,0 +1,5 @@ +# Ignore all downloaded workflow logs +* + +# But keep the .gitignore file itself +!.gitignore diff --git a/.github/workflows/coding-agent-dispatcher.lock.yml b/.github/workflows/coding-agent-dispatcher.lock.yml index 904e0ea..b686435 100644 --- a/.github/workflows/coding-agent-dispatcher.lock.yml +++ b/.github/workflows/coding-agent-dispatcher.lock.yml @@ -13,7 +13,7 @@ # \ /\ / (_) | | | | ( | | | | (_) \ V V /\__ \ # \/ \/ \___/|_| |_|\_\|_| |_|\___/ \_/\_/ |___/ # -# This file was automatically generated by gh-aw (v0.45.3). DO NOT EDIT. +# This file was automatically generated by gh-aw (v0.45.7). DO NOT EDIT. # # To update this file, edit the corresponding .md file and run: # gh aw compile @@ -21,11 +21,11 @@ # # For more information: https://github.github.com/gh-aw/introduction/overview/ # -# Context-aware dispatcher that assigns custom Copilot coding agents to issues, notifies requesters on completion, and orchestrates cross-repo workflows. +# Assigns the github-config custom Copilot coding agent to issues and notifies requesters on completion. # -# frontmatter-hash: 855d1250c91451d559899fc27ce7ef4d4ca08aeb7431760d0d44f06e6b48034b +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"79e767eaa6a5c3b0a8c52591f28115f96145f7458df22033a73055bf62acd151"} -name: "Coding Agent Dispatcher" +name: "GitHub Config Dispatcher" "on": issues: types: @@ -37,7 +37,7 @@ permissions: {} concurrency: group: "gh-aw-${{ github.workflow }}-${{ github.event.issue.number }}" -run-name: "Coding Agent Dispatcher" +run-name: "GitHub Config Dispatcher" jobs: activation: @@ -47,11 +47,14 @@ jobs: permissions: contents: read outputs: + body: ${{ steps.sanitized.outputs.body }} comment_id: "" comment_repo: "" + text: ${{ steps.sanitized.outputs.text }} + title: ${{ steps.sanitized.outputs.title }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@de12ba797dda93d15a84e32976c64b0c45ab27c8 # v0.45.3 + uses: github/gh-aw/actions/setup@5d8900eb6f6230c9d41a3c30af320150a2361285 # v0.45.7 with: destination: /opt/gh-aw/actions - name: Checkout .github and .agents folders @@ -65,13 +68,22 @@ jobs: - name: Check workflow file timestamps uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: - GH_AW_WORKFLOW_FILE: "coding-agent-dispatcher.lock.yml" + GH_AW_WORKFLOW_FILE: "github-config-dispatcher.lock.yml" with: script: | const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); setupGlobals(core, github, context, exec, io); const { main } = require('/opt/gh-aw/actions/check_workflow_timestamp_api.cjs'); await main(); + - name: Compute current body text + id: sanitized + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + with: + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/compute_text.cjs'); + await main(); - name: Create prompt with built-in context env: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt @@ -155,7 +167,7 @@ jobs: GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - {{#runtime-import .github/workflows/coding-agent-dispatcher.md}} + {{#runtime-import .github/workflows/github-config-dispatcher.md}} GH_AW_PROMPT_EOF - name: Interpolate variables and render templates uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 @@ -183,6 +195,8 @@ jobs: GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} + GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED: ${{ needs.pre_activation.outputs.activated }} + GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_MATCHED_COMMAND: ${{ needs.pre_activation.outputs.matched_command }} with: script: | const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); @@ -202,7 +216,9 @@ jobs: GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: process.env.GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER, GH_AW_GITHUB_REPOSITORY: process.env.GH_AW_GITHUB_REPOSITORY, GH_AW_GITHUB_RUN_ID: process.env.GH_AW_GITHUB_RUN_ID, - GH_AW_GITHUB_WORKSPACE: process.env.GH_AW_GITHUB_WORKSPACE + GH_AW_GITHUB_WORKSPACE: process.env.GH_AW_GITHUB_WORKSPACE, + GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED: process.env.GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED, + GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_MATCHED_COMMAND: process.env.GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_MATCHED_COMMAND } }); - name: Validate prompt placeholders @@ -237,7 +253,7 @@ jobs: GH_AW_SAFE_OUTPUTS: /opt/gh-aw/safeoutputs/outputs.jsonl GH_AW_SAFE_OUTPUTS_CONFIG_PATH: /opt/gh-aw/safeoutputs/config.json GH_AW_SAFE_OUTPUTS_TOOLS_PATH: /opt/gh-aw/safeoutputs/tools.json - GH_AW_WORKFLOW_ID_SANITIZED: codingagentdispatcher + GH_AW_WORKFLOW_ID_SANITIZED: githubconfigdispatcher outputs: checkout_pr_success: ${{ steps.checkout-pr.outputs.checkout_pr_success || 'true' }} has_patch: ${{ steps.collect_output.outputs.has_patch }} @@ -247,7 +263,7 @@ jobs: secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@de12ba797dda93d15a84e32976c64b0c45ab27c8 # v0.45.3 + uses: github/gh-aw/actions/setup@5d8900eb6f6230c9d41a3c30af320150a2361285 # v0.45.7 with: destination: /opt/gh-aw/actions - name: Checkout repository @@ -294,8 +310,8 @@ jobs: model: process.env.GH_AW_MODEL_AGENT_COPILOT || "", version: "", agent_version: "0.0.410", - cli_version: "v0.45.3", - workflow_name: "Coding Agent Dispatcher", + cli_version: "v0.45.7", + workflow_name: "GitHub Config Dispatcher", experimental: false, supports_tools_allowlist: true, run_id: context.runId, @@ -309,7 +325,7 @@ jobs: staged: false, allowed_domains: ["defaults","github"], firewall_enabled: true, - awf_version: "v0.19.1", + awf_version: "v0.20.0", awmg_version: "v0.1.4", steps: { firewall: "squid" @@ -333,7 +349,7 @@ jobs: - name: Install GitHub Copilot CLI run: /opt/gh-aw/actions/install_copilot_cli.sh 0.0.410 - name: Install awf binary - run: bash /opt/gh-aw/actions/install_awf_binary.sh v0.19.1 + run: bash /opt/gh-aw/actions/install_awf_binary.sh v0.20.0 - name: Determine automatic lockdown mode for GitHub MCP Server id: determine-automatic-lockdown uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 @@ -346,58 +362,17 @@ jobs: const determineAutomaticLockdown = require('/opt/gh-aw/actions/determine_automatic_lockdown.cjs'); await determineAutomaticLockdown(github, context, core); - name: Download container images - run: bash /opt/gh-aw/actions/download_docker_images.sh ghcr.io/github/gh-aw-firewall/agent:0.19.1 ghcr.io/github/gh-aw-firewall/squid:0.19.1 ghcr.io/github/gh-aw-mcpg:v0.1.4 ghcr.io/github/github-mcp-server:v0.30.3 node:lts-alpine + run: bash /opt/gh-aw/actions/download_docker_images.sh ghcr.io/github/gh-aw-firewall/agent:0.20.0 ghcr.io/github/gh-aw-firewall/api-proxy:0.20.0 ghcr.io/github/gh-aw-firewall/squid:0.20.0 ghcr.io/github/gh-aw-mcpg:v0.1.4 ghcr.io/github/github-mcp-server:v0.30.3 node:lts-alpine - name: Write Safe Outputs Config run: | mkdir -p /opt/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs cat > /opt/gh-aw/safeoutputs/config.json << 'GH_AW_SAFE_OUTPUTS_CONFIG_EOF' - {"add_comment":{"max":1,"target":"triggering"},"assign_to_agent":{"allowed":["alz-vending","github-config"],"max":1,"target":"triggering"},"create_issue":{"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1}} + {"add_comment":{"max":1,"target":"triggering"},"assign_to_agent":{"default_agent":"copilot","max":1,"target":"triggering"},"missing_data":{},"missing_tool":{},"noop":{"max":1}} GH_AW_SAFE_OUTPUTS_CONFIG_EOF cat > /opt/gh-aw/safeoutputs/tools.json << 'GH_AW_SAFE_OUTPUTS_TOOLS_EOF' [ - { - "description": "Create a new GitHub issue for tracking bugs, feature requests, or tasks. Use this for actionable work items that need assignment, labeling, and status tracking. For reports, announcements, or status updates that don't require task tracking, use create_discussion instead. CONSTRAINTS: Maximum 1 issue(s) can be created. Title will be prefixed with \"feat: \". Labels [automation github-config] will be automatically added. Issues will be created in repository \"nathlan/github-config\".", - "inputSchema": { - "additionalProperties": false, - "properties": { - "body": { - "description": "Detailed issue description in Markdown. Do NOT repeat the title as a heading since it already appears as the issue's h1. Include context, reproduction steps, or acceptance criteria as appropriate.", - "type": "string" - }, - "labels": { - "description": "Labels to categorize the issue (e.g., 'bug', 'enhancement'). Labels must exist in the repository.", - "items": { - "type": "string" - }, - "type": "array" - }, - "parent": { - "description": "Parent issue number for creating sub-issues. This is the numeric ID from the GitHub URL (e.g., 42 in github.com/owner/repo/issues/42). Can also be a temporary_id (e.g., 'aw_abc123', 'aw_Test123') from a previously created issue in the same workflow run.", - "type": [ - "number", - "string" - ] - }, - "temporary_id": { - "description": "Unique temporary identifier for referencing this issue before it's created. Format: 'aw_' followed by 3 to 8 alphanumeric characters (e.g., 'aw_abc1', 'aw_Test123'). Use '#aw_ID' in body text to reference other issues by their temporary_id; these are replaced with actual issue numbers after creation.", - "pattern": "^aw_[A-Za-z0-9]{3,8}$", - "type": "string" - }, - "title": { - "description": "Concise issue title summarizing the bug, feature, or task. The title appears as the main heading, so keep it brief and descriptive.", - "type": "string" - } - }, - "required": [ - "title", - "body" - ], - "type": "object" - }, - "name": "create_issue" - }, { "description": "Add a comment to an existing GitHub issue, pull request, or discussion. Use this to provide feedback, answer questions, or add information to an existing conversation. For creating new items, use create_issue, create_discussion, or create_pull_request instead. IMPORTANT: Comments are subject to validation constraints enforced by the MCP server - maximum 65536 characters for the complete comment (including footer which is added automatically), 10 mentions (@username), and 50 links. Exceeding these limits will result in an immediate error with specific guidance. CONSTRAINTS: Maximum 1 comment(s) can be added. Target: triggering.", "inputSchema": { @@ -420,7 +395,7 @@ jobs: "name": "add_comment" }, { - "description": "Assign the GitHub Copilot coding agent to work on an issue or pull request. The agent will analyze the issue/PR and attempt to implement a solution, creating a pull request when complete. Use this to delegate coding tasks to Copilot. Example usage: assign_to_agent(issue_number=123, agent=\"copilot\") or assign_to_agent(pull_number=456, agent=\"copilot\") CONSTRAINTS: Maximum 1 issue(s) can be assigned to agent.", + "description": "Assign the GitHub Copilot coding agent to work on an issue or pull request. The agent will analyze the issue/PR and attempt to implement a solution, creating a pull request when complete. Use this to delegate coding tasks to Copilot. Example usage: assign_to_agent(issue_number=123, agent=\"copilot\") or assign_to_agent(pull_number=456, agent=\"copilot\", pull_request_repo=\"owner/repo\") CONSTRAINTS: Maximum 1 issue(s) can be assigned to agent.", "inputSchema": { "additionalProperties": false, "properties": { @@ -429,18 +404,22 @@ jobs: "type": "string" }, "issue_number": { - "description": "Issue number to assign the Copilot agent to. This is the numeric ID from the GitHub URL (e.g., 234 in github.com/owner/repo/issues/234). Can also be a temporary_id (e.g., 'aw_abc123', 'aw_Test123') from an issue created earlier in the same workflow run. The issue should contain clear, actionable requirements. Either issue_number or pull_number must be provided, but not both.", + "description": "Issue number to assign the Copilot coding agent to. This is the numeric ID from the GitHub URL (e.g., 234 in github.com/owner/repo/issues/234). Can also be a temporary_id (e.g., 'aw_abc123', 'aw_Test123') from an issue created earlier in the same workflow run. The issue should contain clear, actionable requirements. Either issue_number or pull_number must be provided, but not both.", "type": [ "number", "string" ] }, "pull_number": { - "description": "Pull request number to assign the Copilot agent to. This is the numeric ID from the GitHub URL (e.g., 456 in github.com/owner/repo/pull/456). Either issue_number or pull_number must be provided, but not both.", + "description": "Pull request number to assign the Copilot coding agent to. This is the numeric ID from the GitHub URL (e.g., 456 in github.com/owner/repo/pull/456). Either issue_number or pull_number must be provided, but not both.", "type": [ "number", "string" ] + }, + "pull_request_repo": { + "description": "Target repository where the pull request should be created, in 'owner/repo' format. If omitted, the PR will be created in the same repository as the issue. This allows issues and code to live in different repositories. The global pull-request-repo configuration (if set) is automatically allowed; additional repositories must be listed in allowed-pull-request-repos.", + "type": "string" } }, "type": "object" @@ -551,39 +530,6 @@ jobs: }, "customValidation": "requiresOneOf:issue_number,pull_number" }, - "create_issue": { - "defaultMax": 1, - "fields": { - "body": { - "required": true, - "type": "string", - "sanitize": true, - "maxLength": 65000 - }, - "labels": { - "type": "array", - "itemType": "string", - "itemSanitize": true, - "itemMaxLength": 128 - }, - "parent": { - "issueOrPRNumber": true - }, - "repo": { - "type": "string", - "maxLength": 256 - }, - "temporary_id": { - "type": "string" - }, - "title": { - "required": true, - "type": "string", - "sanitize": true, - "maxLength": 128 - } - } - }, "missing_tool": { "defaultMax": 20, "fields": { @@ -730,7 +676,7 @@ jobs: timeout-minutes: 20 run: | set -o pipefail - sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --allow-domains '*.githubusercontent.com,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,codeload.github.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-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,lfs.github.com,objects.githubusercontent.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' --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.19.1 --skip-pull \ + sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --allow-domains '*.githubusercontent.com,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,codeload.github.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-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,lfs.github.com,objects.githubusercontent.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' --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.20.0 --skip-pull --enable-api-proxy \ -- /bin/bash -c '/usr/local/bin/copilot --add-dir /tmp/gh-aw/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --add-dir "${GITHUB_WORKSPACE}" --disable-builtin-mcps --allow-all-tools --allow-all-paths --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"${GH_AW_MODEL_AGENT_COPILOT:+ --model "$GH_AW_MODEL_AGENT_COPILOT"}' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE @@ -902,7 +848,7 @@ jobs: total_count: ${{ steps.missing_tool.outputs.total_count }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@de12ba797dda93d15a84e32976c64b0c45ab27c8 # v0.45.3 + uses: github/gh-aw/actions/setup@5d8900eb6f6230c9d41a3c30af320150a2361285 # v0.45.7 with: destination: /opt/gh-aw/actions - name: Download agent output artifact @@ -922,7 +868,7 @@ jobs: env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} GH_AW_NOOP_MAX: 1 - GH_AW_WORKFLOW_NAME: "Coding Agent Dispatcher" + GH_AW_WORKFLOW_NAME: "GitHub Config Dispatcher" with: github-token: ${{ secrets.GH_AW_AGENT_TOKEN }} script: | @@ -935,7 +881,7 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_WORKFLOW_NAME: "Coding Agent Dispatcher" + GH_AW_WORKFLOW_NAME: "GitHub Config Dispatcher" with: github-token: ${{ secrets.GH_AW_AGENT_TOKEN }} script: | @@ -948,10 +894,10 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_WORKFLOW_NAME: "Coding Agent Dispatcher" + GH_AW_WORKFLOW_NAME: "GitHub Config Dispatcher" 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: "coding-agent-dispatcher" + GH_AW_WORKFLOW_ID: "github-config-dispatcher" GH_AW_SECRET_VERIFICATION_RESULT: ${{ needs.agent.outputs.secret_verification_result }} GH_AW_CHECKOUT_PR_SUCCESS: ${{ needs.agent.outputs.checkout_pr_success }} GH_AW_ASSIGNMENT_ERRORS: ${{ needs.safe_outputs.outputs.assign_to_agent_assignment_errors }} @@ -968,7 +914,7 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_WORKFLOW_NAME: "Coding Agent Dispatcher" + GH_AW_WORKFLOW_NAME: "GitHub Config Dispatcher" GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }} GH_AW_NOOP_MESSAGE: ${{ steps.noop.outputs.noop_message }} @@ -991,7 +937,7 @@ jobs: success: ${{ steps.parse_results.outputs.success }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@de12ba797dda93d15a84e32976c64b0c45ab27c8 # v0.45.3 + uses: github/gh-aw/actions/setup@5d8900eb6f6230c9d41a3c30af320150a2361285 # v0.45.7 with: destination: /opt/gh-aw/actions - name: Download agent artifacts @@ -1014,8 +960,8 @@ jobs: - name: Setup threat detection uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: - WORKFLOW_NAME: "Coding Agent Dispatcher" - WORKFLOW_DESCRIPTION: "Context-aware dispatcher that assigns custom Copilot coding agents to issues, notifies requesters on completion, and orchestrates cross-repo workflows." + WORKFLOW_NAME: "GitHub Config Dispatcher" + WORKFLOW_DESCRIPTION: "Assigns the github-config custom Copilot coding agent to issues and notifies requesters on completion." HAS_PATCH: ${{ needs.agent.outputs.has_patch }} with: script: | @@ -1086,7 +1032,7 @@ jobs: activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@de12ba797dda93d15a84e32976c64b0c45ab27c8 # v0.45.3 + uses: github/gh-aw/actions/setup@5d8900eb6f6230c9d41a3c30af320150a2361285 # v0.45.7 with: destination: /opt/gh-aw/actions - name: Check team membership for workflow @@ -1116,8 +1062,8 @@ jobs: timeout-minutes: 15 env: GH_AW_ENGINE_ID: "copilot" - GH_AW_WORKFLOW_ID: "coding-agent-dispatcher" - GH_AW_WORKFLOW_NAME: "Coding Agent Dispatcher" + GH_AW_WORKFLOW_ID: "github-config-dispatcher" + GH_AW_WORKFLOW_NAME: "GitHub Config Dispatcher" outputs: assign_to_agent_assigned: ${{ steps.assign_to_agent.outputs.assigned }} assign_to_agent_assignment_error_count: ${{ steps.assign_to_agent.outputs.assignment_error_count }} @@ -1128,7 +1074,7 @@ jobs: process_safe_outputs_temporary_id_map: ${{ steps.process_safe_outputs.outputs.temporary_id_map }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@de12ba797dda93d15a84e32976c64b0c45ab27c8 # v0.45.3 + uses: github/gh-aw/actions/setup@5d8900eb6f6230c9d41a3c30af320150a2361285 # v0.45.7 with: destination: /opt/gh-aw/actions - name: Download agent output artifact @@ -1147,7 +1093,7 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_comment\":{\"max\":1,\"target\":\"triggering\"},\"create_issue\":{\"labels\":[\"automation\",\"github-config\"],\"max\":1,\"target-repo\":\"nathlan/github-config\",\"title_prefix\":\"feat: \"},\"missing_data\":{},\"missing_tool\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_comment\":{\"max\":1,\"target\":\"triggering\"},\"missing_data\":{},\"missing_tool\":{}}" with: github-token: ${{ secrets.GH_AW_AGENT_TOKEN }} script: | @@ -1162,9 +1108,9 @@ jobs: env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} GH_AW_AGENT_MAX_COUNT: 1 + GH_AW_AGENT_DEFAULT: "copilot" + GH_AW_AGENT_DEFAULT_CUSTOM_AGENT: "github-config" GH_AW_AGENT_TARGET: "triggering" - GH_AW_AGENT_ALLOWED: "alz-vending,github-config" - GH_AW_TEMPORARY_ID_MAP: ${{ steps.process_safe_outputs.outputs.temporary_id_map }} with: github-token: ${{ secrets.GH_AW_AGENT_TOKEN }} script: | diff --git a/.github/workflows/coding-agent-dispatcher.md b/.github/workflows/coding-agent-dispatcher.md index 9887f84..ba3cb71 100644 --- a/.github/workflows/coding-agent-dispatcher.md +++ b/.github/workflows/coding-agent-dispatcher.md @@ -1,6 +1,6 @@ --- -name: Coding Agent Dispatcher -description: Context-aware dispatcher that assigns custom Copilot coding agents to issues, notifies requesters on completion, and orchestrates cross-repo workflows. +name: GitHub Config Dispatcher +description: Assigns the github-config custom Copilot coding agent to issues and notifies requesters on completion. on: issues: types: [opened, closed] @@ -21,22 +21,18 @@ engine: safe-outputs: github-token: ${{ secrets.GH_AW_AGENT_TOKEN }} assign-to-agent: - allowed: [alz-vending, github-config] + name: "copilot" + custom-agent: "github-config" target: "triggering" max: 1 add-comment: target: "triggering" max: 1 - create-issue: - target-repo: "nathlan/github-config" - title-prefix: "feat: " - labels: [automation, github-config] - max: 1 --- -# Coding Agent Dispatcher +# GitHub Config Dispatcher -You are a context-aware dispatcher that handles agent assignment on issue open and orchestration on issue close. Your behaviour changes based on which repository you are running in. +You are a dispatcher that handles Copilot agent assignment for GitHub configuration issues. You assign the `github-config` custom agent on issue open and notify the requester on issue close. This is the end of the orchestration chain — no cross-repo issues are created from here. ## Tool Usage @@ -59,22 +55,12 @@ These tools are provided by the GitHub MCP server (from the `issues` and `repos` - `get_file_contents` — Read file contents from a repository. - `list_commits` — List commits on a branch. -**Example — reading the triggering issue:** -``` -Call: issue_read - owner: "" - repo: "" - issue_number: ${{ github.event.issue.number }} - method: "get" -``` - ### Phase 2 — Write with Safe-Output Tools -These tools are injected by the safe-outputs runtime. They are the ONLY way to perform write operations (comments, issue creation, agent assignment). +These tools are injected by the safe-outputs runtime. They are the ONLY way to perform write operations. -- `assign_to_agent` — Assign a Copilot coding agent to an issue. Provide `agent` (the agent name) and `issue_number`. +- `assign_to_agent` — Assign the `github-config` Copilot coding agent to an issue. Provide `issue_number`. - `add_comment` — Post a comment on the triggering issue. Provide `body` (markdown text). Omit `item_number` to target the triggering issue. -- `create_issue` — Create a new issue (configured to target `nathlan/github-config`). Provide `title` and `body`. - `noop` — Log a transparency message when no action is needed. Provide `message`. ### Important @@ -91,30 +77,23 @@ These tools are injected by the safe-outputs runtime. They are the ONLY way to p - **Issue**: #${{ github.event.issue.number }} - **Repository**: ${{ github.repository }} -## Label-to-Agent Routing Rules +## Scope -Use the following deterministic mapping. Each label corresponds to exactly one custom agent name: - -| Issue Label | Agent Name | Repository Context | Description | -|-------------------|------------------|------------------------------|------------------------------------------------------| -| `alz-vending` | `alz-vending` | `nathlan/alz-subscriptions` | Azure Landing Zone provisioning agent | -| `github-config` | `github-config` | `nathlan/github-config` | GitHub configuration management agent | - -**The label must be an exact match.** Only labels listed in the routing table above should trigger any action. +This workflow ONLY handles issues with the `github-config` label. If the triggering issue does not have the `github-config` label, use `noop` to log that no action was taken and stop. --- ## Behaviour: Issue Opened (`${{ github.event.issue.state }}` is `open`) -This is the same regardless of which repository this workflow runs in. +### Assign Copilot Agent + +1. **Read the issue**: Call `issue_read` to get the labels on issue #${{ github.event.issue.number }}. +2. **Check for `github-config` label**: If the issue does NOT have the `github-config` label, use `noop` to log: `"Issue # does not have the github-config label. Skipping."` — **Stop here.** +3. **Assign Copilot agent**: Call `assign_to_agent` with: + - `agent`: `copilot` + - `issue_number`: The triggering issue number -1. **Read the issue**: Call the `issue_read` tool to get the labels on issue #${{ github.event.issue.number }}. -2. **Match labels against routing rules**: Check if any of the issue's labels match a label in the routing table above. -3. **Assign the agent**: If exactly one matching label is found, call the `assign_to_agent` tool with: - - `agent_name`: The corresponding agent name from the routing table - - Let the target resolve automatically from the triggering issue context -4. **No match**: If none of the issue's labels match any routing rule, use the `noop` tool to log: `"No routing rule matched for issue #. Labels: []. No agent assigned."` -5. **Multiple matches**: If more than one label matches different agents, use the `noop` tool to log: `"Multiple agent labels found on issue #: []. Skipping assignment — resolve manually."` + The `github-config` custom agent is configured in frontmatter — Copilot will automatically route to the [github-config.agent.md](https://github.com/nathlan/github-config/blob/main/.github/agents/github-config.agent.md) agent file in the target repository. **Do NOT create issues or post comments on opened events.** @@ -122,80 +101,154 @@ This is the same regardless of which repository this workflow runs in. ## Behaviour: Issue Closed (`${{ github.event.issue.state }}` is `closed`) -On close, behaviour depends on which repository this workflow is running in. +**Purpose:** Notify the requester that their workload repository has been provisioned. This is the end of the chain. -### Step 1: Common — Read and Validate +### Step 1: Validation -1. **Read the issue**: Call the `issue_read` tool to get the full details of issue #${{ github.event.issue.number }}, including labels, body, and the original author. -2. **Check labels**: If the issue does NOT have any label matching the routing table, use the `noop` tool to log that this issue is not managed by the dispatcher. **Stop here.** +1. **Read the issue**: Call `issue_read` to get the full details of issue #${{ github.event.issue.number }}, including labels, body, and the original author. +2. **Check label**: If the issue does NOT have the `github-config` label, use `noop` to log: `"Issue # is not a github-config issue (missing github-config label). Skipping."` — **Stop here.** 3. **Identify the requester**: The original issue author is the person to notify. -4. **Check for a linked PR**: Use the `search_pull_requests` or `list_pull_requests` tool to look for a pull request that closed this issue. You can also check the issue body/timeline for PR references. +4. **Check for a linked PR**: Use `search_pull_requests` or `list_pull_requests` to look for a pull request that closed this issue. -### Step 2: Context-Specific Actions +### Step 2: Notify -#### When running in `nathlan/alz-subscriptions` (label: `alz-vending`) - -The `alz-vending` agent has created a PR that has now been merged, closing this issue. The landing zone is being deployed to Azure. Now we need to hand off to `github-config` to create the workload repository. - -1. **Post a completion comment** using the `add_comment` tool: +1. **Post a completion comment** using `add_comment`: ``` -👋 @{original_author} — your landing zone request has been completed. +👋 @{original_author} — your workload repository has been provisioned. {If a linked PR exists: "Merged via #PR_NUMBER."} -Your Azure Landing Zone is now being deployed. A workload repository will be provisioned automatically in `nathlan/github-config` — you'll be notified there once it's ready. +The Terraform configuration for your repository has been applied. Your new repo should now be available in the `nathlan` organization. ``` -2. **Extract landing zone details from the closed issue body**. The issue body (created by the `alz-vending` agent) contains structured data. Extract: - - **workload name** (the workload identifier, e.g., `payments-api`) - - **team** (the owning team slug, e.g., `payments-team`) - - **repository name** (from federated credentials / OIDC config, e.g., `payments-api`) - - **environment** (e.g., `Production (prod)`) - - **location** (e.g., `uksouth`) +**Do NOT create any cross-repo issues.** This is the end of the orchestration chain. -3. **Create an issue in `nathlan/github-config`** using the `create_issue` tool with: +--- - **Title**: `Create workload repository — {repository_name}` +## Important Rules - **Body**: +- Do NOT assign an agent on `closed` events. Assignment only happens on `opened`. +- Do NOT post a comment on `opened` events. Notification only happens on `closed`. +- Do NOT edit or close any existing issues. Your jobs are: agent assignment and notification. +- Only act on issues with the `github-config` label. Ignore all other issues. +- Do NOT create cross-repo issues. This workflow is the terminal step in the chain. +- This workflow is intentionally deterministic. Do not use heuristics or infer intent beyond reading the issue labels and body. +--- +name: GitHub Config Dispatcher +description: Assigns the github-config custom Copilot coding agent to issues and notifies requesters on completion. +on: + issues: + types: [opened, closed] +permissions: + actions: read + contents: read + issues: read +network: + allowed: + - defaults + - github +tools: + github: + github-token: ${{ secrets.GH_AW_AGENT_TOKEN }} + toolsets: [issues, repos] +engine: + id: copilot +safe-outputs: + github-token: ${{ secrets.GH_AW_AGENT_TOKEN }} + assign-to-agent: + name: "copilot" + custom-agent: "github-config" + target: "triggering" + max: 1 + add-comment: + target: "triggering" + max: 1 +--- - ``` - ## Workload Repository Request +# GitHub Config Dispatcher - This issue was automatically created by the coding-agent-dispatcher after a landing zone was provisioned in `nathlan/alz-subscriptions`. +You are a dispatcher that handles Copilot agent assignment for GitHub configuration issues. You assign the `github-config` custom agent on issue open and notify the requester on issue close. This is the end of the orchestration chain — no cross-repo issues are created from here. - ## Configuration Details +## Tool Usage - | Field | Value | - |---|---| - | **Repository Name** | {repository_name} | - | **Description** | ALZ workload repository for {workload} ({environment}) | - | **Visibility** | internal | - | **Team** | {team} | - | **Workload** | {workload} | - | **Environment** | {environment} | - | **Required Approving Reviews** | 1 | - | **Source Issue** | nathlan/alz-subscriptions#{issue_number} | +You have two sets of tools. **Use ONLY these tools.** Do NOT use the `gh` CLI, `curl`, direct API calls, or any other method. - ## Instructions +### Phase 1 — Read with GitHub MCP Server Tools - Add a new entry to the `template_repositories` list in `terraform/terraform.tfvars`. Follow the existing entry format in the file. Do NOT create new Terraform module files — the module structure already exists. +These tools are provided by the GitHub MCP server (from the `issues` and `repos` toolsets). Use them to gather all context before taking action. - The entry should include: - - Team access: `{team}` with `maintain` permission, `platform-engineering` with `admin` permission - - All other settings derived from the Configuration Details table above +**Reading issues:** +- `issue_read` — Get issue details (labels, body, author). Call with `owner`, `repo`, `issue_number`, and `method: "get"`. To get labels specifically, use `method: "get_labels"`. +- `list_issues` — List issues in a repository. +- `search_issues` — Search issues across repositories. + +**Finding linked pull requests:** +- `list_pull_requests` — List PRs in a repository. +- `search_pull_requests` — Search for PRs (e.g., to find the PR that closed an issue). + +**Other read tools available if needed:** +- `get_file_contents` — Read file contents from a repository. +- `list_commits` — List commits on a branch. + +### Phase 2 — Write with Safe-Output Tools + +These tools are injected by the safe-outputs runtime. They are the ONLY way to perform write operations. + +- `assign_to_agent` — Assign the `github-config` Copilot coding agent to an issue. Provide `issue_number`. +- `add_comment` — Post a comment on the triggering issue. Provide `body` (markdown text). Omit `item_number` to target the triggering issue. +- `noop` — Log a transparency message when no action is needed. Provide `message`. + +### Important + +1. **Always use `issue_read` to read issue data** — do not try to parse context variables or call APIs directly. +2. **Always use the safe-output tools for writes** — do not use `issue_write`, `add_issue_comment`, `assign_copilot_to_issue`, or any other GitHub MCP write tool. Those are available in the MCP server but writes MUST go through safe-outputs. +3. **If a tool call fails**, use `noop` to report the issue. Never fall back to CLI commands. + +--- + +## Context + +- **Issue state**: `${{ github.event.issue.state }}` +- **Issue**: #${{ github.event.issue.number }} +- **Repository**: ${{ github.repository }} + +## Scope + +This workflow ONLY handles issues with the `github-config` label. If the triggering issue does not have the `github-config` label, use `noop` to log that no action was taken and stop. + +--- + +## Behaviour: Issue Opened (`${{ github.event.issue.state }}` is `open`) + +### Assign Copilot Agent - Create a draft PR with the change. - ``` +1. **Read the issue**: Call `issue_read` to get the labels on issue #${{ github.event.issue.number }}. +2. **Check for `github-config` label**: If the issue does NOT have the `github-config` label, use `noop` to log: `"Issue # does not have the github-config label. Skipping."` — **Stop here.** +3. **Assign Copilot agent**: Call `assign_to_agent` with: + - `agent`: `copilot` + - `issue_number`: The triggering issue number - If you cannot extract the required details from the issue body, **do not create the issue**. Instead, post a comment on the triggering issue explaining what was missing. + The `github-config` custom agent is configured in frontmatter — Copilot will automatically route to the [github-config.agent.md](https://github.com/nathlan/github-config/blob/main/.github/agents/github-config.agent.md) agent file in the target repository. -#### When running in `nathlan/github-config` (label: `github-config`) +**Do NOT create issues or post comments on opened events.** + +--- + +## Behaviour: Issue Closed (`${{ github.event.issue.state }}` is `closed`) + +**Purpose:** Notify the requester that their workload repository has been provisioned. This is the end of the chain. -The `github-config` agent has created a PR that has now been merged, closing this issue. The workload repository is being deployed. +### Step 1: Validation -1. **Post a completion comment** using the `add_comment` tool: +1. **Read the issue**: Call `issue_read` to get the full details of issue #${{ github.event.issue.number }}, including labels, body, and the original author. +2. **Check label**: If the issue does NOT have the `github-config` label, use `noop` to log: `"Issue # is not a github-config issue (missing github-config label). Skipping."` — **Stop here.** +3. **Identify the requester**: The original issue author is the person to notify. +4. **Check for a linked PR**: Use `search_pull_requests` or `list_pull_requests` to look for a pull request that closed this issue. + +### Step 2: Notify + +1. **Post a completion comment** using `add_comment`: ``` 👋 @{original_author} — your workload repository has been provisioned. @@ -205,21 +258,15 @@ The `github-config` agent has created a PR that has now been merged, closing thi The Terraform configuration for your repository has been applied. Your new repo should now be available in the `nathlan` organization. ``` - **Do NOT create any cross-repo issues from this context.** This is the end of the chain. - -#### When running in any other repository - -Use the `noop` tool to log: `"Issue # closed in unsupported repository . No action taken."` - -**Do NOT post comments or create cross-repo issues.** +**Do NOT create any cross-repo issues.** This is the end of the orchestration chain. --- ## Important Rules - Do NOT assign an agent on `closed` events. Assignment only happens on `opened`. -- Do NOT post a comment or create issues on `opened` events. Orchestration only happens on `closed`. -- Do NOT edit or close any existing issues. Your jobs are: agent assignment, notification, and cross-repo issue creation. -- Only act on issues that have labels matching the routing table. Ignore all other issues. -- Only create a cross-repo issue in `nathlan/github-config` when running in `nathlan/alz-subscriptions` and the `alz-vending` label is present. +- Do NOT post a comment on `opened` events. Notification only happens on `closed`. +- Do NOT edit or close any existing issues. Your jobs are: agent assignment and notification. +- Only act on issues with the `github-config` label. Ignore all other issues. +- Do NOT create cross-repo issues. This workflow is the terminal step in the chain. - This workflow is intentionally deterministic. Do not use heuristics or infer intent beyond reading the issue labels and body. diff --git a/.github/workflows/copilot-setup-steps.yml b/.github/workflows/copilot-setup-steps.yml index ccd90ce..30dfc49 100644 --- a/.github/workflows/copilot-setup-steps.yml +++ b/.github/workflows/copilot-setup-steps.yml @@ -1,26 +1,18 @@ -name: "Copilot Setup Steps" - -# This workflow configures the environment for GitHub Copilot Agent with gh-aw MCP server -on: - workflow_dispatch: +name: Copilot Setup Steps +"on": push: paths: - - .github/workflows/copilot-setup-steps.yml - + - .github/workflows/copilot-setup-steps.yml + workflow_dispatch: null jobs: - # The job MUST be called 'copilot-setup-steps' to be recognized by GitHub Copilot Agent copilot-setup-steps: runs-on: ubuntu-latest - - # Set minimal permissions for setup steps - # Copilot Agent receives its own token with appropriate permissions permissions: contents: read - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - name: Install gh-aw extension - uses: github/gh-aw/actions/setup-cli@v0.45.3 - with: - version: v0.45.3 + - name: Checkout repository + uses: actions/checkout@v4 + - name: Install gh-aw extension + uses: github/gh-aw/actions/setup-cli@v0.45.7 + with: + version: v0.45.7