diff --git a/.github/aw/actions-lock.json b/.github/aw/actions-lock.json index 33c867fa..dd616012 100644 --- a/.github/aw/actions-lock.json +++ b/.github/aw/actions-lock.json @@ -59,6 +59,11 @@ "repo": "github/gh-aw/actions/setup", "version": "v0.47.4", "sha": "da463a765059a5eed4cc345a003ecfc71c45ec49" + }, + "github/gh-aw/actions/setup@v0.48.1": { + "repo": "github/gh-aw/actions/setup", + "version": "v0.48.1", + "sha": "26b6572ae210580303087bc3142fe58d140bf65c" } } } diff --git a/.github/workflows/agentics-maintenance.yml b/.github/workflows/agentics-maintenance.yml index 025f2b52..928d335d 100644 --- a/.github/workflows/agentics-maintenance.yml +++ b/.github/workflows/agentics-maintenance.yml @@ -49,7 +49,7 @@ jobs: pull-requests: write steps: - name: Setup Scripts - uses: ./actions/setup + uses: github/gh-aw/actions/setup@v0.48.1 with: destination: /opt/gh-aw/actions diff --git a/.github/workflows/gh-aw-downstream-users.lock.yml b/.github/workflows/downstream-users.lock.yml similarity index 94% rename from .github/workflows/gh-aw-downstream-users.lock.yml rename to .github/workflows/downstream-users.lock.yml index 9fd759d9..b06ebbc2 100644 --- a/.github/workflows/gh-aw-downstream-users.lock.yml +++ b/.github/workflows/downstream-users.lock.yml @@ -34,41 +34,22 @@ # - gh-aw-fragments/safe-output-create-pr.md # - gh-aw-fragments/workflow-edit-guardrails.md # -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"cd94e39458afefa85e1384a6a852a0160f06272a94e7d279a0fb457661d8885f"} +# inlined-imports: true +# +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"4baa7d5cf4b9f13fad6ee198ebc939209bbae3becc62bd261b65b063c4013491"} name: "Downstream Users" "on": # bots: # Bots processed as bot check in pre-activation job - # - ${{ inputs.allowed-bot-users }} # Bots processed as bot check in pre-activation job + # - github-actions[bot] # Bots processed as bot check in pre-activation job # roles: # Roles processed as role check in pre-activation job # - admin # Roles processed as role check in pre-activation job # - maintainer # Roles processed as role check in pre-activation job # - write # Roles processed as role check in pre-activation job - workflow_call: - inputs: - additional-instructions: - default: "" - description: Repo-specific instructions appended to the agent prompt - required: false - type: string - allowed-bot-users: - default: github-actions[bot] - description: Allowlisted bot actor usernames (comma-separated) - required: false - type: string - messages-footer: - default: "" - description: Footer appended to all agent comments and reviews - required: false - type: string - setup-commands: - default: "" - description: Shell commands to run before the agent starts (dependency install, build, etc.) - required: false - type: string - secrets: - COPILOT_GITHUB_TOKEN: - required: true + schedule: + - cron: "4 9 * * 1" + # Friendly format: weekly on Monday around 10:00 (scattered) + workflow_dispatch: permissions: {} @@ -80,8 +61,6 @@ run-name: "Downstream Users" jobs: activation: - needs: pre_activation - if: needs.pre_activation.outputs.activated == 'true' runs-on: ubuntu-slim permissions: contents: read @@ -90,7 +69,7 @@ jobs: comment_repo: "" steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Validate context variables @@ -112,7 +91,7 @@ jobs: - name: Check workflow file timestamps uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: - GH_AW_WORKFLOW_FILE: "gh-aw-downstream-users.lock.yml" + GH_AW_WORKFLOW_FILE: "downstream-users.lock.yml" with: script: | const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); @@ -123,7 +102,6 @@ jobs: env: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} GH_AW_GITHUB_ACTOR: ${{ github.actor }} GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} @@ -167,6 +145,30 @@ jobs: **Critical**: Tool calls write structured data that downstream jobs process. Without tool calls, follow-up actions will be skipped. **Note**: If you made no other safe output tool calls during this workflow execution, call the "noop" tool to provide a status message indicating completion or that no actions were needed. + + --- + + ## Creating a Pull Request, Reporting Missing Tools or Functionality, Reporting Missing Data + + **IMPORTANT**: To perform the actions listed above, use the **safeoutputs** tools. Do NOT use `gh`, do NOT call the GitHub API directly. You do not have write access to the GitHub repository. + + **Creating a Pull Request** + + To create a pull request: + 1. Make any file changes directly in the working directory. + 2. If you haven't done so already, create a local branch using an appropriate unique name. + 3. Add and commit your changes to the branch. Be careful to add exactly the files you intend, and check there are no extra files left un-added. Verify you haven't deleted or changed any files you didn't intend to. + 4. Do not push your changes. That will be done by the tool. + 5. Create the pull request with the create_pull_request tool from safeoutputs. + + **Reporting Missing Tools or Functionality** + + To report a missing tool or capability, use the missing_tool tool from safeoutputs. + + **Reporting Missing Data** + + To report missing data required to achieve a goal, use the missing_data tool from safeoutputs. + @@ -368,15 +370,12 @@ jobs: - The search query used - Any exclusions (self repo, archived/forks if excluded) - __GH_AW_EXPR_49B959F1__ - GH_AW_PROMPT_EOF - name: Interpolate variables and render templates uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} - GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} with: script: | const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); @@ -387,7 +386,6 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} GH_AW_GITHUB_ACTOR: ${{ github.actor }} GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} @@ -409,7 +407,6 @@ jobs: return await substitutePlaceholders({ file: process.env.GH_AW_PROMPT, substitutions: { - GH_AW_EXPR_49B959F1: process.env.GH_AW_EXPR_49B959F1, GH_AW_GITHUB_ACTOR: process.env.GH_AW_GITHUB_ACTOR, GH_AW_GITHUB_EVENT_COMMENT_ID: process.env.GH_AW_GITHUB_EVENT_COMMENT_ID, GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: process.env.GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER, @@ -456,7 +453,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: ghawdownstreamusers + GH_AW_WORKFLOW_ID_SANITIZED: downstreamusers outputs: checkout_pr_success: ${{ steps.checkout-pr.outputs.checkout_pr_success || 'true' }} has_patch: ${{ steps.collect_output.outputs.has_patch }} @@ -466,7 +463,7 @@ jobs: secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Checkout repository @@ -519,11 +516,6 @@ jobs: chmod +x "$install_dir/uv" echo "$install_dir" >> "$GITHUB_PATH" shell: bash - - env: - SETUP_COMMANDS: ${{ inputs.setup-commands }} - if: ${{ inputs.setup-commands != '' }} - name: Repo-specific setup - run: eval "$SETUP_COMMANDS" - name: Configure Git credentials env: @@ -620,7 +612,7 @@ jobs: 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' - {"create_pull_request":{},"missing_data":{},"missing_tool":{},"noop":{"max":1}} + {"create_pull_request":{"max":1},"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' [ @@ -637,6 +629,10 @@ jobs: "description": "Source branch name containing the changes. If omitted, uses the current working branch.", "type": "string" }, + "draft": { + "description": "Whether to create the PR as a draft. Draft PRs cannot be merged until marked as ready for review. Use mark_pull_request_as_ready_for_review to convert a draft PR. Default: true.", + "type": "boolean" + }, "labels": { "description": "Labels to categorize the PR (e.g., 'enhancement', 'bugfix'). Labels must exist in the repository.", "items": { @@ -745,12 +741,19 @@ jobs: "sanitize": true, "maxLength": 256 }, + "draft": { + "type": "boolean" + }, "labels": { "type": "array", "itemType": "string", "itemSanitize": true, "itemMaxLength": 128 }, + "repo": { + "type": "string", + "maxLength": 256 + }, "title": { "required": true, "type": "string", @@ -759,6 +762,31 @@ jobs: } } }, + "missing_data": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "context": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "data_type": { + "type": "string", + "sanitize": true, + "maxLength": 128 + }, + "reason": { + "type": "string", + "sanitize": true, + "maxLength": 256 + } + } + }, "missing_tool": { "defaultMax": 20, "fields": { @@ -1017,10 +1045,11 @@ jobs: run: | set -o pipefail sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --allow-domains '*.githubusercontent.com,*.jsr.io,*.pythonhosted.org,*.rvm.io,agents-md-generator.fastmcp.app,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.rubygems.org,api.snapcraft.io,archive.ubuntu.com,artifacts.elastic.co,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,bun.sh,bundler.rubygems.org,cache.ruby-lang.org,cdn.jsdelivr.net,cloud.elastic.co,codeload.github.com,conda.anaconda.org,conda.binstar.org,crates.io,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,deb.nodesource.com,deno.land,ela.st,elastic.co,esm.sh,files.pythonhosted.org,gems.rubyforge.org,gems.rubyonrails.org,get.pnpm.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,host.docker.internal,index.crates.io,index.rubygems.org,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,lfs.github.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,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,pip.pypa.io,pkg.go.dev,ppa.launchpad.net,proxy.golang.org,public-code-search.fastmcp.app,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.bower.io,registry.npmjs.com,registry.npmjs.org,registry.yarnpkg.com,repo.anaconda.com,repo.continuum.io,repo.yarnpkg.com,rubygems.org,rubygems.pkg.github.com,s.symcb.com,s.symcd.com,security.ubuntu.com,skimdb.npmjs.com,static.crates.io,storage.googleapis.com,sum.golang.org,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.elastic.co,www.npmjs.com,www.npmjs.org,yarnpkg.com' --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.20.2 --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 --model gpt-5.3-codex --allow-all-tools --allow-all-paths --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log + -- /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 --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: gpt-5.3-codex GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} @@ -1177,7 +1206,7 @@ jobs: /tmp/gh-aw/sandbox/firewall/logs/ /tmp/gh-aw/agent-stdio.log /tmp/gh-aw/agent/ - /tmp/gh-aw/aw.patch + /tmp/gh-aw/aw-*.patch if-no-files-found: ignore conclusion: @@ -1198,7 +1227,7 @@ jobs: total_count: ${{ steps.missing_tool.outputs.total_count }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent output artifact @@ -1247,7 +1276,7 @@ jobs: GH_AW_WORKFLOW_NAME: "Downstream Users" 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: "gh-aw-downstream-users" + GH_AW_WORKFLOW_ID: "downstream-users" GH_AW_SECRET_VERIFICATION_RESULT: ${{ needs.agent.outputs.secret_verification_result }} GH_AW_CHECKOUT_PR_SUCCESS: ${{ needs.agent.outputs.checkout_pr_success }} GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\"}" @@ -1303,7 +1332,7 @@ jobs: success: ${{ steps.parse_results.outputs.success }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent artifacts @@ -1364,10 +1393,11 @@ jobs: mkdir -p /tmp/gh-aw/ mkdir -p /tmp/gh-aw/agent/ mkdir -p /tmp/gh-aw/sandbox/agent/logs/ - copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --model gpt-5.3-codex --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log + copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: gpt-5.3-codex GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_REF_NAME: ${{ github.ref_name }} @@ -1391,29 +1421,6 @@ jobs: path: /tmp/gh-aw/threat-detection/detection.log if-no-files-found: ignore - pre_activation: - runs-on: ubuntu-slim - outputs: - activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} - steps: - - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 - with: - destination: /opt/gh-aw/actions - - name: Check team membership for workflow - id: check_membership - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_REQUIRED_ROLES: admin,maintainer,write - GH_AW_ALLOWED_BOTS: ${{ inputs.allowed-bot-users }} - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - 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_membership.cjs'); - await main(); - safe_outputs: needs: - activation @@ -1430,7 +1437,7 @@ jobs: GH_AW_ENGINE_ID: "copilot" GH_AW_ENGINE_MODEL: "gpt-5.3-codex" GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\"}" - GH_AW_WORKFLOW_ID: "gh-aw-downstream-users" + GH_AW_WORKFLOW_ID: "downstream-users" GH_AW_WORKFLOW_NAME: "Downstream Users" outputs: create_discussion_error_count: ${{ steps.process_safe_outputs.outputs.create_discussion_error_count }} @@ -1439,7 +1446,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@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent output artifact @@ -1463,7 +1470,7 @@ jobs: if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: - ref: ${{ github.ref_name }} + ref: ${{ github.base_ref || github.ref_name }} token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} persist-credentials: false fetch-depth: 1 @@ -1485,7 +1492,7 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_pull_request\":{\"base_branch\":\"${{ github.ref_name }}\",\"max\":1,\"max_patch_size\":1024},\"missing_data\":{},\"missing_tool\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_pull_request\":{\"base_branch\":\"${{ github.base_ref || github.ref_name }}\",\"max\":1,\"max_patch_size\":1024},\"missing_data\":{},\"missing_tool\":{}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/gh-aw-downstream-users.md b/.github/workflows/downstream-users.md similarity index 76% rename from .github/workflows/gh-aw-downstream-users.md rename to .github/workflows/downstream-users.md index 6eee7050..ef7d7353 100644 --- a/.github/workflows/gh-aw-downstream-users.md +++ b/.github/workflows/downstream-users.md @@ -1,4 +1,5 @@ --- +inlined-imports: true name: "Downstream Users" description: "Track downstream public repo usage of elastic/ai-github-actions and update data" imports: @@ -14,34 +15,12 @@ engine: id: copilot model: gpt-5.3-codex on: - workflow_call: - inputs: - additional-instructions: - description: "Repo-specific instructions appended to the agent prompt" - type: string - required: false - default: "" - setup-commands: - description: "Shell commands to run before the agent starts (dependency install, build, etc.)" - type: string - required: false - default: "" - allowed-bot-users: - description: "Allowlisted bot actor usernames (comma-separated)" - type: string - required: false - default: "github-actions[bot]" - messages-footer: - description: "Footer appended to all agent comments and reviews" - type: string - required: false - default: "" - secrets: - COPILOT_GITHUB_TOKEN: - required: true + schedule: + - cron: "weekly on Monday around 10:00" + workflow_dispatch: roles: [admin, maintainer, write] bots: - - "${{ inputs.allowed-bot-users }}" + - "github-actions[bot]" concurrency: group: downstream-users cancel-in-progress: true @@ -66,12 +45,6 @@ strict: false safe-outputs: noop: timeout-minutes: 90 -steps: - - name: Repo-specific setup - if: ${{ inputs.setup-commands != '' }} - env: - SETUP_COMMANDS: ${{ inputs.setup-commands }} - run: eval "$SETUP_COMMANDS" --- # Downstream Users Tracking @@ -147,4 +120,3 @@ Guidelines: - The search query used - Any exclusions (self repo, archived/forks if excluded) -${{ inputs.additional-instructions }} diff --git a/.github/workflows/gh-aw-agent-efficiency.lock.yml b/.github/workflows/gh-aw-agent-efficiency.lock.yml index eae08947..90f80fee 100644 --- a/.github/workflows/gh-aw-agent-efficiency.lock.yml +++ b/.github/workflows/gh-aw-agent-efficiency.lock.yml @@ -32,9 +32,11 @@ # - gh-aw-fragments/rigor.md # - gh-aw-fragments/runtime-setup.md # - gh-aw-fragments/safe-output-create-issue.md -# - gh-aw-fragments/scheduled-report.md +# - gh-aw-fragments/scheduled-audit.md # -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"c0996131bb2124751616641d9e670037633a0e4aa7c93c25a90f02bc03cdc2fe"} +# inlined-imports: true +# +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"98bd99c723dfc9296e6756c3d30a0dc5e0ac3b4cf2c71f79281d8e011c201cc8"} name: "Agent Efficiency" "on": @@ -61,6 +63,11 @@ name: "Agent Efficiency" description: Footer appended to all agent comments and reviews required: false type: string + model: + default: gpt-5.3-codex + description: AI model to use + required: false + type: string setup-commands: default: "" description: Shell commands to run before the agent starts (dependency install, build, etc.) @@ -90,7 +97,7 @@ jobs: comment_repo: "" steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Validate context variables @@ -167,6 +174,25 @@ jobs: **Critical**: Tool calls write structured data that downstream jobs process. Without tool calls, follow-up actions will be skipped. **Note**: If you made no other safe output tool calls during this workflow execution, call the "noop" tool to provide a status message indicating completion or that no actions were needed. + + --- + + ## Creating an Issue, Reporting Missing Tools or Functionality, Reporting Missing Data + + **IMPORTANT**: To perform the actions listed above, use the **safeoutputs** tools. Do NOT use `gh`, do NOT call the GitHub API directly. You do not have write access to the GitHub repository. + + **Creating an Issue** + + To create an issue, use the create_issue tool from safeoutputs. + + **Reporting Missing Tools or Functionality** + + To report a missing tool or capability, use the missing_tool tool from safeoutputs. + + **Reporting Missing Data** + + To report missing data required to achieve a goal, use the missing_data tool from safeoutputs. + @@ -284,9 +310,7 @@ jobs: - **Mentions**: `@mentions` in the body are neutralized (backticked) by default. GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - # Scheduled Report Agent - - You are a report agent for __GH_AW_GITHUB_REPOSITORY__. You run on a schedule to investigate the repository and file an issue when something needs attention. Your specific assignment is described in the **Report Assignment** section below. + You are an agent for __GH_AW_GITHUB_REPOSITORY__. You run on a schedule to investigate the repository and file an issue when something needs attention. Your specific assignment is described in the **Report Assignment** section below. ## Context @@ -350,7 +374,7 @@ jobs: - Make suggested actions concrete enough to act on without re-investigating - If a finding is ambiguous, it does not pass the quality gate — drop it - ## Report Assignment + **Report Assignment:** GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" @@ -534,7 +558,7 @@ jobs: secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Checkout repository @@ -628,7 +652,7 @@ jobs: const awInfo = { engine_id: "copilot", engine_name: "GitHub Copilot CLI", - model: "gpt-5.3-codex", + model: "${{ inputs.model }}", version: "", agent_version: "0.0.412", workflow_name: "Agent Efficiency", @@ -839,6 +863,31 @@ jobs: } } }, + "missing_data": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "context": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "data_type": { + "type": "string", + "sanitize": true, + "maxLength": 128 + }, + "reason": { + "type": "string", + "sanitize": true, + "maxLength": 256 + } + } + }, "missing_tool": { "defaultMax": 20, "fields": { @@ -1000,10 +1049,11 @@ jobs: run: | set -o pipefail sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --allow-domains '*.githubusercontent.com,*.jsr.io,*.pythonhosted.org,*.rvm.io,agents-md-generator.fastmcp.app,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.rubygems.org,api.snapcraft.io,archive.ubuntu.com,artifacts.elastic.co,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,bun.sh,bundler.rubygems.org,cache.ruby-lang.org,cdn.jsdelivr.net,cloud.elastic.co,codeload.github.com,conda.anaconda.org,conda.binstar.org,crates.io,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,deb.nodesource.com,deno.land,ela.st,elastic.co,esm.sh,files.pythonhosted.org,gems.rubyforge.org,gems.rubyonrails.org,get.pnpm.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,host.docker.internal,index.crates.io,index.rubygems.org,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,lfs.github.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,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,pip.pypa.io,pkg.go.dev,ppa.launchpad.net,proxy.golang.org,public-code-search.fastmcp.app,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.bower.io,registry.npmjs.com,registry.npmjs.org,registry.yarnpkg.com,repo.anaconda.com,repo.continuum.io,repo.yarnpkg.com,rubygems.org,rubygems.pkg.github.com,s.symcb.com,s.symcd.com,security.ubuntu.com,skimdb.npmjs.com,static.crates.io,storage.googleapis.com,sum.golang.org,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.elastic.co,www.npmjs.com,www.npmjs.org,yarnpkg.com' --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.20.2 --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 --model gpt-5.3-codex --allow-all-tools --allow-all-paths --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log + -- /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 --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} @@ -1169,7 +1219,7 @@ jobs: total_count: ${{ steps.missing_tool.outputs.total_count }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent output artifact @@ -1260,7 +1310,7 @@ jobs: success: ${{ steps.parse_results.outputs.success }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent artifacts @@ -1321,10 +1371,11 @@ jobs: mkdir -p /tmp/gh-aw/ mkdir -p /tmp/gh-aw/agent/ mkdir -p /tmp/gh-aw/sandbox/agent/logs/ - copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --model gpt-5.3-codex --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log + copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_REF_NAME: ${{ github.ref_name }} @@ -1354,7 +1405,7 @@ jobs: activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Check team membership for workflow @@ -1383,7 +1434,7 @@ jobs: timeout-minutes: 15 env: GH_AW_ENGINE_ID: "copilot" - GH_AW_ENGINE_MODEL: "gpt-5.3-codex" + GH_AW_ENGINE_MODEL: "${{ inputs.model }}" GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\"}" GH_AW_WORKFLOW_ID: "gh-aw-agent-efficiency" GH_AW_WORKFLOW_NAME: "Agent Efficiency" @@ -1394,7 +1445,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@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent output artifact diff --git a/.github/workflows/gh-aw-agent-efficiency.md b/.github/workflows/gh-aw-agent-efficiency.md index 28c2a2b7..7d024587 100644 --- a/.github/workflows/gh-aw-agent-efficiency.md +++ b/.github/workflows/gh-aw-agent-efficiency.md @@ -1,4 +1,5 @@ --- +inlined-imports: true name: "Agent Efficiency" description: "Analyze agent workflow logs for inefficiencies, errors, and prompt improvement opportunities" imports: @@ -9,13 +10,18 @@ imports: - gh-aw-fragments/mcp-pagination.md - gh-aw-fragments/messages-footer.md - gh-aw-fragments/safe-output-create-issue.md - - gh-aw-fragments/scheduled-report.md + - gh-aw-fragments/scheduled-audit.md engine: id: copilot - model: gpt-5.3-codex + model: ${{ inputs.model }} on: workflow_call: inputs: + model: + description: "AI model to use" + type: string + required: false + default: "gpt-5.3-codex" additional-instructions: description: "Repo-specific instructions appended to the agent prompt" type: string diff --git a/.github/workflows/gh-aw-agent-suggestions.lock.yml b/.github/workflows/gh-aw-agent-suggestions.lock.yml index 62ff02b1..3f266419 100644 --- a/.github/workflows/gh-aw-agent-suggestions.lock.yml +++ b/.github/workflows/gh-aw-agent-suggestions.lock.yml @@ -32,9 +32,11 @@ # - gh-aw-fragments/rigor.md # - gh-aw-fragments/runtime-setup.md # - gh-aw-fragments/safe-output-create-issue.md -# - gh-aw-fragments/scheduled-report.md +# - gh-aw-fragments/scheduled-audit.md # -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"22d036923781edbda7b143495f0551d25c4efffaaeb593a638e534b96365eda4"} +# inlined-imports: true +# +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"05a8222ed64c0e2d7bdadf1a38c9d5810bdc5c3cc558ddb2c333f8650ee7c6a4"} name: "Agent Suggestions" "on": @@ -61,6 +63,11 @@ name: "Agent Suggestions" description: Footer appended to all agent comments and reviews required: false type: string + model: + default: gpt-5.3-codex + description: AI model to use + required: false + type: string setup-commands: default: "" description: Shell commands to run before the agent starts (dependency install, build, etc.) @@ -90,7 +97,7 @@ jobs: comment_repo: "" steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Validate context variables @@ -167,6 +174,25 @@ jobs: **Critical**: Tool calls write structured data that downstream jobs process. Without tool calls, follow-up actions will be skipped. **Note**: If you made no other safe output tool calls during this workflow execution, call the "noop" tool to provide a status message indicating completion or that no actions were needed. + + --- + + ## Creating an Issue, Reporting Missing Tools or Functionality, Reporting Missing Data + + **IMPORTANT**: To perform the actions listed above, use the **safeoutputs** tools. Do NOT use `gh`, do NOT call the GitHub API directly. You do not have write access to the GitHub repository. + + **Creating an Issue** + + To create an issue, use the create_issue tool from safeoutputs. + + **Reporting Missing Tools or Functionality** + + To report a missing tool or capability, use the missing_tool tool from safeoutputs. + + **Reporting Missing Data** + + To report missing data required to achieve a goal, use the missing_data tool from safeoutputs. + @@ -284,9 +310,7 @@ jobs: - **Mentions**: `@mentions` in the body are neutralized (backticked) by default. GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - # Scheduled Report Agent - - You are a report agent for __GH_AW_GITHUB_REPOSITORY__. You run on a schedule to investigate the repository and file an issue when something needs attention. Your specific assignment is described in the **Report Assignment** section below. + You are an agent for __GH_AW_GITHUB_REPOSITORY__. You run on a schedule to investigate the repository and file an issue when something needs attention. Your specific assignment is described in the **Report Assignment** section below. ## Context @@ -350,7 +374,7 @@ jobs: - Make suggested actions concrete enough to act on without re-investigating - If a finding is ambiguous, it does not pass the quality gate — drop it - ## Report Assignment + **Report Assignment:** GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" @@ -520,7 +544,7 @@ jobs: secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Checkout repository @@ -614,7 +638,7 @@ jobs: const awInfo = { engine_id: "copilot", engine_name: "GitHub Copilot CLI", - model: "gpt-5.3-codex", + model: "${{ inputs.model }}", version: "", agent_version: "0.0.412", workflow_name: "Agent Suggestions", @@ -825,6 +849,31 @@ jobs: } } }, + "missing_data": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "context": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "data_type": { + "type": "string", + "sanitize": true, + "maxLength": 128 + }, + "reason": { + "type": "string", + "sanitize": true, + "maxLength": 256 + } + } + }, "missing_tool": { "defaultMax": 20, "fields": { @@ -986,10 +1035,11 @@ jobs: run: | set -o pipefail sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --allow-domains '*.githubusercontent.com,*.jsr.io,*.pythonhosted.org,*.rvm.io,agents-md-generator.fastmcp.app,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.rubygems.org,api.snapcraft.io,archive.ubuntu.com,artifacts.elastic.co,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,bun.sh,bundler.rubygems.org,cache.ruby-lang.org,cdn.jsdelivr.net,cloud.elastic.co,codeload.github.com,conda.anaconda.org,conda.binstar.org,crates.io,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,deb.nodesource.com,deno.land,ela.st,elastic.co,esm.sh,files.pythonhosted.org,gems.rubyforge.org,gems.rubyonrails.org,get.pnpm.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,host.docker.internal,index.crates.io,index.rubygems.org,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,lfs.github.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,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,pip.pypa.io,pkg.go.dev,ppa.launchpad.net,proxy.golang.org,public-code-search.fastmcp.app,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.bower.io,registry.npmjs.com,registry.npmjs.org,registry.yarnpkg.com,repo.anaconda.com,repo.continuum.io,repo.yarnpkg.com,rubygems.org,rubygems.pkg.github.com,s.symcb.com,s.symcd.com,security.ubuntu.com,skimdb.npmjs.com,static.crates.io,storage.googleapis.com,sum.golang.org,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.elastic.co,www.npmjs.com,www.npmjs.org,yarnpkg.com' --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.20.2 --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 --model gpt-5.3-codex --allow-all-tools --allow-all-paths --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log + -- /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 --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} @@ -1155,7 +1205,7 @@ jobs: total_count: ${{ steps.missing_tool.outputs.total_count }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent output artifact @@ -1246,7 +1296,7 @@ jobs: success: ${{ steps.parse_results.outputs.success }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent artifacts @@ -1307,10 +1357,11 @@ jobs: mkdir -p /tmp/gh-aw/ mkdir -p /tmp/gh-aw/agent/ mkdir -p /tmp/gh-aw/sandbox/agent/logs/ - copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --model gpt-5.3-codex --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log + copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_REF_NAME: ${{ github.ref_name }} @@ -1340,7 +1391,7 @@ jobs: activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Check team membership for workflow @@ -1369,7 +1420,7 @@ jobs: timeout-minutes: 15 env: GH_AW_ENGINE_ID: "copilot" - GH_AW_ENGINE_MODEL: "gpt-5.3-codex" + GH_AW_ENGINE_MODEL: "${{ inputs.model }}" GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\"}" GH_AW_WORKFLOW_ID: "gh-aw-agent-suggestions" GH_AW_WORKFLOW_NAME: "Agent Suggestions" @@ -1380,7 +1431,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@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent output artifact diff --git a/.github/workflows/gh-aw-agent-suggestions.md b/.github/workflows/gh-aw-agent-suggestions.md index 4acc06ca..97e8ed66 100644 --- a/.github/workflows/gh-aw-agent-suggestions.md +++ b/.github/workflows/gh-aw-agent-suggestions.md @@ -1,4 +1,5 @@ --- +inlined-imports: true name: "Agent Suggestions" description: "Suggest new agent workflows based on repo needs and downstream activity" imports: @@ -9,13 +10,18 @@ imports: - gh-aw-fragments/mcp-pagination.md - gh-aw-fragments/messages-footer.md - gh-aw-fragments/safe-output-create-issue.md - - gh-aw-fragments/scheduled-report.md + - gh-aw-fragments/scheduled-audit.md engine: id: copilot - model: gpt-5.3-codex + model: ${{ inputs.model }} on: workflow_call: inputs: + model: + description: "AI model to use" + type: string + required: false + default: "gpt-5.3-codex" additional-instructions: description: "Repo-specific instructions appended to the agent prompt" type: string diff --git a/.github/workflows/gh-aw-breaking-change-detect.lock.yml b/.github/workflows/gh-aw-breaking-change-detect.lock.yml deleted file mode 100644 index cf05188f..00000000 --- a/.github/workflows/gh-aw-breaking-change-detect.lock.yml +++ /dev/null @@ -1,1430 +0,0 @@ -# -# ___ _ _ -# / _ \ | | (_) -# | |_| | __ _ ___ _ __ | |_ _ ___ -# | _ |/ _` |/ _ \ '_ \| __| |/ __| -# | | | | (_| | __/ | | | |_| | (__ -# \_| |_/\__, |\___|_| |_|\__|_|\___| -# __/ | -# _ _ |___/ -# | | | | / _| | -# | | | | ___ _ __ _ __| |_| | _____ ____ -# | |/\| |/ _ \ '__| |/ /| _| |/ _ \ \ /\ / / ___| -# \ /\ / (_) | | | | ( | | | | (_) \ V V /\__ \ -# \/ \/ \___/|_| |_|\_\|_| |_|\___/ \_/\_/ |___/ -# -# This file was automatically generated by gh-aw. DO NOT EDIT. -# -# To update this file, edit the corresponding .md file and run: -# gh aw compile -# Not all edits will cause changes to this file. -# -# For more information: https://github.github.com/gh-aw/introduction/overview/ -# -# Detect undocumented breaking changes in public interfaces -# -# Resolved workflow manifest: -# Imports: -# - gh-aw-fragments/elastic-tools.md -# - gh-aw-fragments/ensure-full-history.md -# - gh-aw-fragments/formatting.md -# - gh-aw-fragments/mcp-pagination.md -# - gh-aw-fragments/messages-footer.md -# - gh-aw-fragments/rigor.md -# - gh-aw-fragments/runtime-setup.md -# - gh-aw-fragments/safe-output-create-issue.md -# - gh-aw-fragments/scheduled-report.md -# -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"3edb9530565a9b30a6134be1cf366c862a1cf980db072dc2d6ece5814830bfb0"} - -name: "Breaking Change Detect" -"on": - # bots: # Bots processed as bot check in pre-activation job - # - ${{ inputs.allowed-bot-users }} # Bots processed as bot check in pre-activation job - # roles: # Roles processed as role check in pre-activation job - # - admin # Roles processed as role check in pre-activation job - # - maintainer # Roles processed as role check in pre-activation job - # - write # Roles processed as role check in pre-activation job - workflow_call: - inputs: - additional-instructions: - default: "" - description: Repo-specific instructions appended to the agent prompt - required: false - type: string - allowed-bot-users: - default: github-actions[bot] - description: Allowlisted bot actor usernames (comma-separated) - required: false - type: string - messages-footer: - default: "" - description: Footer appended to all agent comments and reviews - required: false - type: string - setup-commands: - default: "" - description: Shell commands to run before the agent starts (dependency install, build, etc.) - required: false - type: string - secrets: - COPILOT_GITHUB_TOKEN: - required: true - -permissions: {} - -concurrency: - cancel-in-progress: true - group: breaking-change-detect - -run-name: "Breaking Change Detect" - -jobs: - activation: - needs: pre_activation - if: needs.pre_activation.outputs.activated == 'true' - runs-on: ubuntu-slim - permissions: - contents: read - outputs: - comment_id: "" - comment_repo: "" - steps: - - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 - with: - destination: /opt/gh-aw/actions - - name: Validate context variables - 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/validate_context_variables.cjs'); - await main(); - - name: Checkout .github and .agents folders - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - sparse-checkout: | - .github - .agents - fetch-depth: 1 - persist-credentials: false - - name: Check workflow file timestamps - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_WORKFLOW_FILE: "gh-aw-breaking-change-detect.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: Create prompt with built-in context - env: - GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} - GH_AW_GITHUB_ACTOR: ${{ github.actor }} - GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} - GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} - GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} - GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} - GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} - GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} - GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} - run: | - bash /opt/gh-aw/actions/create_prompt_first.sh - cat << 'GH_AW_PROMPT_EOF' > "$GH_AW_PROMPT" - - GH_AW_PROMPT_EOF - cat "/opt/gh-aw/prompts/xpia.md" >> "$GH_AW_PROMPT" - cat "/opt/gh-aw/prompts/temp_folder_prompt.md" >> "$GH_AW_PROMPT" - cat "/opt/gh-aw/prompts/markdown.md" >> "$GH_AW_PROMPT" - cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - - GitHub API Access Instructions - - The gh CLI is NOT authenticated. Do NOT use gh commands for GitHub operations. - - - To create or modify GitHub resources (issues, discussions, pull requests, etc.), you MUST call the appropriate safe output tool. Simply writing content will NOT work - the workflow requires actual tool calls. - - Temporary IDs: Some safe output tools support a temporary ID field (usually named temporary_id) so you can reference newly-created items elsewhere in the SAME agent output (for example, using #aw_abc1 in a later body). - - **IMPORTANT - temporary_id format rules:** - - If you DON'T need to reference the item later, OMIT the temporary_id field entirely (it will be auto-generated if needed) - - If you DO need cross-references/chaining, you MUST match this EXACT validation regex: /^aw_[A-Za-z0-9]{3,8}$/i - - Format: aw_ prefix followed by 3 to 8 alphanumeric characters (A-Z, a-z, 0-9, case-insensitive) - - Valid alphanumeric characters: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 - - INVALID examples: aw_ab (too short), aw_123456789 (too long), aw_test-id (contains hyphen), aw_id_123 (contains underscore) - - VALID examples: aw_abc, aw_abc1, aw_Test123, aw_A1B2C3D4, aw_12345678 - - To generate valid IDs: use 3-8 random alphanumeric characters or omit the field to let the system auto-generate - - Do NOT invent other aw_* formats — downstream steps will reject them with validation errors matching against /^aw_[A-Za-z0-9]{3,8}$/i. - - Discover available tools from the safeoutputs MCP server. - - **Critical**: Tool calls write structured data that downstream jobs process. Without tool calls, follow-up actions will be skipped. - - **Note**: If you made no other safe output tool calls during this workflow execution, call the "noop" tool to provide a status message indicating completion or that no actions were needed. - - - - The following GitHub context information is available for this workflow: - {{#if __GH_AW_GITHUB_ACTOR__ }} - - **actor**: __GH_AW_GITHUB_ACTOR__ - {{/if}} - {{#if __GH_AW_GITHUB_REPOSITORY__ }} - - **repository**: __GH_AW_GITHUB_REPOSITORY__ - {{/if}} - {{#if __GH_AW_GITHUB_WORKSPACE__ }} - - **workspace**: __GH_AW_GITHUB_WORKSPACE__ - {{/if}} - {{#if __GH_AW_GITHUB_EVENT_ISSUE_NUMBER__ }} - - **issue-number**: #__GH_AW_GITHUB_EVENT_ISSUE_NUMBER__ - {{/if}} - {{#if __GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__ }} - - **discussion-number**: #__GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__ - {{/if}} - {{#if __GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__ }} - - **pull-request-number**: #__GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__ - {{/if}} - {{#if __GH_AW_GITHUB_EVENT_COMMENT_ID__ }} - - **comment-id**: __GH_AW_GITHUB_EVENT_COMMENT_ID__ - {{/if}} - {{#if __GH_AW_GITHUB_RUN_ID__ }} - - **workflow-run-id**: __GH_AW_GITHUB_RUN_ID__ - {{/if}} - - - GH_AW_PROMPT_EOF - cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - - GH_AW_PROMPT_EOF - cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - ## MCP Servers - - - **`generate_agents_md`** — generates a summary of the repository's structure, conventions, and coding guidelines from AGENTS.md and related files. Call at the start of every workflow to get repo context. - - **`search_code`** — grep-style search across public GitHub repositories. Use for finding usage patterns in upstream libraries, reference implementations, or examples in open-source projects. This searches *public GitHub repos*, not the local codebase — if available you can use `grep` and file reading for local code. - GH_AW_PROMPT_EOF - cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - - GH_AW_PROMPT_EOF - cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - - GH_AW_PROMPT_EOF - cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - ## Formatting Guidelines - - - Lead with the most important information — your first sentence should be the key takeaway - - Be concise and actionable — no filler or praise - - Use `
` and `` tags for long sections to keep responses scannable - - Wrap branch names and @-references in backticks to avoid pinging users - - Include code snippets with file paths and line numbers when referencing the codebase - - GH_AW_PROMPT_EOF - cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - ## Rigor - - **Silence is better than noise. A false positive wastes a human's time and erodes trust in every future report.** - - - If you claim something is missing or broken, show the exact evidence in the code — file path, line number, and what you observed. - - If a conclusion depends on assumptions you haven't confirmed, do not assert it. Verify first; if you cannot verify, do not report. - - "I don't know" is better than a wrong answer. `noop` is better than a speculative finding. - - It's worth the time to verify now versus guessing and forcing someone else to verify later. - - Before filing any issue or opening any PR, re-read your own output as a skeptical reviewer. Ask: "Would a senior engineer on this team find this useful, or would they close it immediately?" If the answer is "close," call `noop` instead. - - Only report findings you would confidently defend in a code review. If you feel the need to hedge with "might," "could," or "possibly," the finding is not ready to file. - - GH_AW_PROMPT_EOF - cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - ## MCP Pagination - - MCP tool responses have a **25,000 token limit**. When responses exceed this limit, the call fails and you must retry with pagination — wasting turns and tokens. Use proactive pagination to stay under the limit. - - ### Recommended `perPage` Values - - - **5-10**: For detailed items (PR diffs, files with patches, issues with comments) - - **20-30**: For medium-detail lists (commits, review comments, issue lists) - - **50-100**: For simple list operations (branches, labels, tags) - - ### Pagination Pattern - - When you need all results from a paginated API: - - 1. Fetch the first page with a conservative `perPage` value - 2. Process the results before fetching the next page - 3. Continue fetching pages until you receive fewer results than `perPage` (indicating the last page) - - ### Error Recovery - - If you see an error like: - - `MCP tool response exceeds maximum allowed tokens (25000)` - - `Response too large for tool [tool_name]` - - Retry the same call with a smaller `perPage` value (halve it). - - ### Tips - - - **Start small**: It's better to make multiple small requests than one that fails - - **Fetch incrementally**: Get an overview first, then details for specific items - - **Use filters**: Combine `perPage` with state, label, or date filters to reduce result size - - **Process as you go**: Don't accumulate all pages before acting — process each batch immediately - - GH_AW_PROMPT_EOF - cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - ## Message Footer - - A footer is automatically appended to all comments and reviews. Do not add your own footer or sign-off — the runtime handles this. - GH_AW_PROMPT_EOF - cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - ## create-issue Limitations - - - **Title**: Max 128 characters. Sanitized (special characters escaped). - - **Labels**: Max 10 labels per issue. Each label max 64 characters. Labels containing only `-` are rejected. - - **Assignees**: Max 5 assignees per issue. - - **Body**: No strict character limit beyond GitHub's API limit (~65,536 characters), but fields over 16,000 tokens are written to a file reference instead of inlined. - - **Bot triggers**: References like `fixes #123` or `closes #456` in the body are neutralized to prevent unintended issue closures. - - **Mentions**: `@mentions` in the body are neutralized (backticked) by default. - GH_AW_PROMPT_EOF - cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - # Scheduled Report Agent - - You are a report agent for __GH_AW_GITHUB_REPOSITORY__. You run on a schedule to investigate the repository and file an issue when something needs attention. Your specific assignment is described in the **Report Assignment** section below. - - ## Context - - - **Repository**: __GH_AW_GITHUB_REPOSITORY__ - - ## Constraints - - This workflow is for detection and reporting only. You can read files, search code, run commands, and read PR/issue details — but your only output is either a single issue or a noop. - - ## Process - - Follow these steps in order. - - ### Step 1: Gather Context - - 1. Call `generate_agents_md` to get the repository's coding guidelines and conventions. If this fails, continue without it. - 2. Follow the data gathering instructions in the **Report Assignment** section. - - ### Step 2: Analyze - - Follow the analysis instructions in the **Report Assignment** section to determine whether an issue should be filed. The Report Assignment defines: - - What data to gather and how - - What to look for - - What constitutes a finding worth reporting - - What to skip or ignore - - ### Step 3: Self-Review (Quality Gate) - - Before filing anything, critically evaluate every finding against these criteria: - - 1. **Evidence is concrete** — you can point to exact file paths, line numbers, commit SHAs, or command outputs. No "I believe" or "it seems." - 2. **Finding is actionable** — a maintainer reading the issue can act on it without re-investigating from scratch. - 3. **Finding is not already tracked** — you checked open issues and recent PRs for duplicates. - 4. **Finding is worth a human's time** — the issue is material enough that a maintainer would thank you for filing it, not close it as noise. - - If zero findings pass all four criteria, call `noop` with a brief reason and stop. **Noop is the expected outcome most days.** Filing nothing is a success when there is nothing worth filing. - - ### Step 4: Report - - If there are findings that pass the quality gate, call `create_issue` with a structured report. Use the issue format specified in the Report Assignment if one is provided, otherwise use this default format: - - **Issue title:** Brief summary of findings - - **Issue body:** - - > ## Findings - > - > ### 1. [Brief description] - > - > **Evidence:** [Links, references, or data supporting the finding] - > **Action needed:** [What should be done] - > - > ## Suggested Actions - > - > - [ ] [Actionable checkbox for each finding] - - **Guidelines:** - - Group related findings together - - Be specific about what needs to happen - - Include links and references where possible - - Make suggested actions concrete enough to act on without re-investigating - - If a finding is ambiguous, it does not pass the quality gate — drop it - - ## Report Assignment - - GH_AW_PROMPT_EOF - cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - Detect unintended breaking changes introduced in the last day that were not documented in PR descriptions, release notes, or repo documentation. - - ### Data Gathering - - Determine the lookback window based on the current day of the week: - - **Monday**: Use `--since="3 days ago"` to capture Friday, Saturday, and Sunday - - **Tuesday through Friday**: Use `--since="1 day ago"` to capture the previous day - - **Manual trigger** (`workflow_dispatch`): Use `--since="1 day ago"` - - Run `git log --since="" --oneline --stat` to get a summary of recent commits. If there are no commits in the lookback window, call `noop` and stop. - - For each commit (or cluster of related commits): - - Review the full diff (`git show ` or `git diff ^!`) to understand what changed. - - Map commits to PRs using `github-search_pull_requests` with query `repo:elastic/ai-github-actions sha:`. - - Read the PR body and related discussion for documentation or migration notes. - - Check for documentation updates in README, DEVELOPING, RELEASE, gh-agent-workflows/README, or any `CHANGELOG*` files (if present). - - ### What to Look For - - Focus on clearly public interface or behavior breaks, such as: - 1. **Workflow interface changes** — removed/renamed workflows, inputs, outputs, triggers, permissions, or schedules used by downstream repos. - 2. **Composite action changes** — removed/renamed inputs/outputs, changed required env vars, altered default behavior. - 3. **Documented guarantees** — changes that contradict or break behavior explicitly described in README/DEVELOPING/RELEASE. - - ### How to Decide "Undocumented" - - A breaking change is **undocumented** if none of the following mention the break or migration steps: - - PR title/body or linked discussion - - RELEASE.md or any release notes in the lookback window - - README/DEVELOPING or other documentation updated in the same PR/commit set - - ### What to Skip - - - Internal refactors with no public impact - - Changes that already include documentation or migration notes - - Test-only changes - - Changes already tracked by an open issue or PR - - Additive changes that don't break existing consumers (new optional inputs with defaults, new workflows, new outputs) - - Changes to internal/private interfaces not consumed by downstream repos - - ### Quality Gate — When to Noop - - **Noop is the expected outcome most days.** Only file an issue when you can demonstrate a concrete break: - - A downstream consumer using the documented interface would **fail or get wrong results** after this change. - - You can identify the **specific interface contract** that was broken (removed input, changed type, renamed workflow, etc.). - - The break is **not documented** anywhere in the PR, release notes, or repo docs. - - Do not file for: speculative breaks ("this might affect someone"), internal restructuring, or changes where backward compatibility is maintained (even if the approach changed). - - ### Issue Format - - **Issue title:** Undocumented breaking changes detected (date) - - **Issue body:** - - > Recent commits introduced breaking changes that appear undocumented. - > - > ## Breaking Changes - > - > ### 1. [Brief description] - > **Commit(s):** [SHA(s) with links] - > **PR:** [Link] - > **What broke:** [Concise description] - > **Evidence:** [Diff or file references] - > **Why undocumented:** [Where documentation is missing] - > **Suggested fix:** [Docs update or migration note] - > - > ## Suggested Actions - > - [ ] Document each breaking change (README/DEVELOPING/RELEASE or release notes) - > - [ ] Add migration guidance where needed - - __GH_AW_EXPR_49B959F1__ - - GH_AW_PROMPT_EOF - - name: Interpolate variables and render templates - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} - GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} - 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/interpolate_prompt.cjs'); - await main(); - - name: Substitute placeholders - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} - GH_AW_GITHUB_ACTOR: ${{ github.actor }} - GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} - GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} - GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} - GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} - 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'); - setupGlobals(core, github, context, exec, io); - - const substitutePlaceholders = require('/opt/gh-aw/actions/substitute_placeholders.cjs'); - - // Call the substitution function - return await substitutePlaceholders({ - file: process.env.GH_AW_PROMPT, - substitutions: { - GH_AW_EXPR_49B959F1: process.env.GH_AW_EXPR_49B959F1, - GH_AW_GITHUB_ACTOR: process.env.GH_AW_GITHUB_ACTOR, - GH_AW_GITHUB_EVENT_COMMENT_ID: process.env.GH_AW_GITHUB_EVENT_COMMENT_ID, - GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: process.env.GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER, - GH_AW_GITHUB_EVENT_ISSUE_NUMBER: process.env.GH_AW_GITHUB_EVENT_ISSUE_NUMBER, - 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_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 - env: - GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - run: bash /opt/gh-aw/actions/validate_prompt_placeholders.sh - - name: Print prompt - env: - GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - run: bash /opt/gh-aw/actions/print_prompt_summary.sh - - name: Upload prompt artifact - if: success() - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 - with: - name: prompt - path: /tmp/gh-aw/aw-prompts/prompt.txt - retention-days: 1 - - agent: - needs: activation - runs-on: ubuntu-latest - permissions: - contents: read - issues: read - pull-requests: read - concurrency: - group: "gh-aw-copilot-${{ github.workflow }}" - env: - DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} - GH_AW_ASSETS_ALLOWED_EXTS: "" - GH_AW_ASSETS_BRANCH: "" - GH_AW_ASSETS_MAX_SIZE_KB: 0 - GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs - 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: ghawbreakingchangedetect - outputs: - checkout_pr_success: ${{ steps.checkout-pr.outputs.checkout_pr_success || 'true' }} - has_patch: ${{ steps.collect_output.outputs.has_patch }} - model: ${{ steps.generate_aw_info.outputs.model }} - output: ${{ steps.collect_output.outputs.output }} - output_types: ${{ steps.collect_output.outputs.output_types }} - secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} - steps: - - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 - with: - destination: /opt/gh-aw/actions - - name: Checkout repository - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - persist-credentials: false - - name: Create gh-aw temp directory - run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh - - if: hashFiles('go.mod') != '' - name: Setup Go - uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5 - with: - cache: true - go-version-file: go.mod - - if: hashFiles('.python-version') != '' - name: Setup Python - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 - with: - python-version-file: .python-version - - if: hashFiles('.node-version') != '' - name: Setup Node.js (.node-version) - uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6 - with: - node-version-file: .node-version - - if: hashFiles('.node-version') == '' && hashFiles('.nvmrc') != '' - name: Setup Node.js (.nvmrc) - uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6 - with: - node-version-file: .nvmrc - - if: hashFiles('.ruby-version') != '' - name: Setup Ruby - uses: ruby/setup-ruby@09a7688d3b55cf0e976497ff046b70949eeaccfd # v1 - with: - bundler-cache: true - ruby-version: .ruby-version - - id: setup-uv - if: hashFiles('pyproject.toml', 'uv.lock') != '' - name: Setup uv - uses: astral-sh/setup-uv@e58605a9b6da7c637471fab8847a5e5a6b8df081 # v5 - - env: - UV_PATH: ${{ steps.setup-uv.outputs.uv-path }} - WORKSPACE: ${{ github.workspace }} - if: hashFiles('pyproject.toml', 'uv.lock') != '' - name: Expose uv in workspace - run: |- - set -euo pipefail - install_dir="$WORKSPACE/.gh-aw-tools/bin" - mkdir -p "$install_dir" - cp "$UV_PATH" "$install_dir/uv" - chmod +x "$install_dir/uv" - echo "$install_dir" >> "$GITHUB_PATH" - shell: bash - - env: - GITHUB_TOKEN: ${{ github.token }} - REPO_NAME: ${{ github.repository }} - SERVER_URL: ${{ github.server_url }} - name: Ensure full history - run: "if git rev-parse --is-shallow-repository | grep -q true; then\n SERVER_URL_STRIPPED=\"${SERVER_URL#https://}\"\n git remote set-url origin \"https://x-access-token:${GITHUB_TOKEN}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git\"\n git fetch --unshallow --quiet\nfi" - - env: - SETUP_COMMANDS: ${{ inputs.setup-commands }} - if: ${{ inputs.setup-commands != '' }} - name: Repo-specific setup - run: eval "$SETUP_COMMANDS" - - - name: Configure Git credentials - env: - REPO_NAME: ${{ github.repository }} - SERVER_URL: ${{ github.server_url }} - run: | - git config --global user.email "github-actions[bot]@users.noreply.github.com" - git config --global user.name "github-actions[bot]" - # Re-authenticate git with GitHub token - SERVER_URL_STRIPPED="${SERVER_URL#https://}" - git remote set-url origin "https://x-access-token:${{ github.token }}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" - echo "Git configured with standard GitHub Actions identity" - - name: Checkout PR branch - id: checkout-pr - if: | - github.event.pull_request - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - with: - github-token: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - script: | - const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io); - const { main } = require('/opt/gh-aw/actions/checkout_pr_branch.cjs'); - await main(); - - name: Generate agentic run info - id: generate_aw_info - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - with: - script: | - const fs = require('fs'); - - const awInfo = { - engine_id: "copilot", - engine_name: "GitHub Copilot CLI", - model: "gpt-5.3-codex", - version: "", - agent_version: "0.0.412", - workflow_name: "Breaking Change Detect", - experimental: false, - supports_tools_allowlist: true, - run_id: context.runId, - run_number: context.runNumber, - run_attempt: process.env.GITHUB_RUN_ATTEMPT, - repository: context.repo.owner + '/' + context.repo.repo, - ref: context.ref, - sha: context.sha, - actor: context.actor, - event_name: context.eventName, - staged: false, - allowed_domains: ["agents-md-generator.fastmcp.app","artifacts.elastic.co","cloud.elastic.co","defaults","ela.st","elastic.co","github","go","node","public-code-search.fastmcp.app","python","ruby","www.elastic.co"], - firewall_enabled: true, - awf_version: "v0.20.2", - awmg_version: "v0.1.4", - steps: { - firewall: "squid" - }, - created_at: new Date().toISOString() - }; - - // Write to /tmp/gh-aw directory to avoid inclusion in PR - const tmpPath = '/tmp/gh-aw/aw_info.json'; - fs.writeFileSync(tmpPath, JSON.stringify(awInfo, null, 2)); - console.log('Generated aw_info.json at:', tmpPath); - console.log(JSON.stringify(awInfo, null, 2)); - - // Set model as output for reuse in other steps/jobs - core.setOutput('model', awInfo.model); - - name: Validate COPILOT_GITHUB_TOKEN secret - id: validate-secret - run: /opt/gh-aw/actions/validate_multi_secret.sh COPILOT_GITHUB_TOKEN 'GitHub Copilot CLI' https://github.github.com/gh-aw/reference/engines/#github-copilot-default - env: - COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} - - name: Install GitHub Copilot CLI - run: /opt/gh-aw/actions/install_copilot_cli.sh 0.0.412 - - name: Install awf binary - run: bash /opt/gh-aw/actions/install_awf_binary.sh v0.20.2 - - name: Determine automatic lockdown mode for GitHub MCP Server - id: determine-automatic-lockdown - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} - GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} - with: - script: | - 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.20.2 ghcr.io/github/gh-aw-firewall/api-proxy:0.20.2 ghcr.io/github/gh-aw-firewall/squid:0.20.2 ghcr.io/github/gh-aw-mcpg:v0.1.4 ghcr.io/github/github-mcp-server:v0.31.0 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' - {"create_issue":{"expires":168,"max":1},"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 \"[breaking-change] \".", - "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": "Report that a tool or capability needed to complete the task is not available, or share any information you deem important about missing functionality or limitations. Use this when you cannot accomplish what was requested because the required functionality is missing or access is restricted.", - "inputSchema": { - "additionalProperties": false, - "properties": { - "alternatives": { - "description": "Any workarounds, manual steps, or alternative approaches the user could take (max 256 characters).", - "type": "string" - }, - "reason": { - "description": "Explanation of why this tool is needed or what information you want to share about the limitation (max 256 characters).", - "type": "string" - }, - "tool": { - "description": "Optional: Name or description of the missing tool or capability (max 128 characters). Be specific about what functionality is needed.", - "type": "string" - } - }, - "required": [ - "reason" - ], - "type": "object" - }, - "name": "missing_tool" - }, - { - "description": "Log a transparency message when no significant actions are needed. Use this to confirm workflow completion and provide visibility when analysis is complete but no changes or outputs are required (e.g., 'No issues found', 'All checks passed'). This ensures the workflow produces human-visible output even when no other actions are taken.", - "inputSchema": { - "additionalProperties": false, - "properties": { - "message": { - "description": "Status or completion message to log. Should explain what was analyzed and the outcome (e.g., 'Code review complete - no issues found', 'Analysis complete - all tests passing').", - "type": "string" - } - }, - "required": [ - "message" - ], - "type": "object" - }, - "name": "noop" - }, - { - "description": "Report that data or information needed to complete the task is not available. Use this when you cannot accomplish what was requested because required data, context, or information is missing.", - "inputSchema": { - "additionalProperties": false, - "properties": { - "alternatives": { - "description": "Any workarounds, manual steps, or alternative approaches the user could take (max 256 characters).", - "type": "string" - }, - "context": { - "description": "Additional context about the missing data or where it should come from (max 256 characters).", - "type": "string" - }, - "data_type": { - "description": "Type or description of the missing data or information (max 128 characters). Be specific about what data is needed.", - "type": "string" - }, - "reason": { - "description": "Explanation of why this data is needed to complete the task (max 256 characters).", - "type": "string" - } - }, - "required": [], - "type": "object" - }, - "name": "missing_data" - } - ] - GH_AW_SAFE_OUTPUTS_TOOLS_EOF - cat > /opt/gh-aw/safeoutputs/validation.json << 'GH_AW_SAFE_OUTPUTS_VALIDATION_EOF' - { - "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": { - "alternatives": { - "type": "string", - "sanitize": true, - "maxLength": 512 - }, - "reason": { - "required": true, - "type": "string", - "sanitize": true, - "maxLength": 256 - }, - "tool": { - "type": "string", - "sanitize": true, - "maxLength": 128 - } - } - }, - "noop": { - "defaultMax": 1, - "fields": { - "message": { - "required": true, - "type": "string", - "sanitize": true, - "maxLength": 65000 - } - } - } - } - GH_AW_SAFE_OUTPUTS_VALIDATION_EOF - - name: Generate Safe Outputs MCP Server Config - id: safe-outputs-config - run: | - # Generate a secure random API key (360 bits of entropy, 40+ chars) - # Mask immediately to prevent timing vulnerabilities - API_KEY=$(openssl rand -base64 45 | tr -d '/+=') - echo "::add-mask::${API_KEY}" - - PORT=3001 - - # Set outputs for next steps - { - echo "safe_outputs_api_key=${API_KEY}" - echo "safe_outputs_port=${PORT}" - } >> "$GITHUB_OUTPUT" - - echo "Safe Outputs MCP server will run on port ${PORT}" - - - name: Start Safe Outputs MCP HTTP Server - id: safe-outputs-start - env: - DEBUG: '*' - GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-config.outputs.safe_outputs_port }} - GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-config.outputs.safe_outputs_api_key }} - GH_AW_SAFE_OUTPUTS_TOOLS_PATH: /opt/gh-aw/safeoutputs/tools.json - GH_AW_SAFE_OUTPUTS_CONFIG_PATH: /opt/gh-aw/safeoutputs/config.json - GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs - run: | - # Environment variables are set above to prevent template injection - export DEBUG - export GH_AW_SAFE_OUTPUTS_PORT - export GH_AW_SAFE_OUTPUTS_API_KEY - export GH_AW_SAFE_OUTPUTS_TOOLS_PATH - export GH_AW_SAFE_OUTPUTS_CONFIG_PATH - export GH_AW_MCP_LOG_DIR - - bash /opt/gh-aw/actions/start_safe_outputs_server.sh - - - name: Start MCP Gateway - id: start-mcp-gateway - env: - GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-start.outputs.api_key }} - GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-start.outputs.port }} - GITHUB_MCP_LOCKDOWN: ${{ steps.determine-automatic-lockdown.outputs.lockdown == 'true' && '1' || '0' }} - GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - run: | - set -eo pipefail - mkdir -p /tmp/gh-aw/mcp-config - - # Export gateway environment variables for MCP config and gateway script - export MCP_GATEWAY_PORT="80" - export MCP_GATEWAY_DOMAIN="host.docker.internal" - MCP_GATEWAY_API_KEY=$(openssl rand -base64 45 | tr -d '/+=') - echo "::add-mask::${MCP_GATEWAY_API_KEY}" - export MCP_GATEWAY_API_KEY - export MCP_GATEWAY_PAYLOAD_DIR="/tmp/gh-aw/mcp-payloads" - mkdir -p "${MCP_GATEWAY_PAYLOAD_DIR}" - export DEBUG="*" - - export GH_AW_ENGINE="copilot" - 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 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_LOCKDOWN -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.1.4' - - mkdir -p /home/runner/.copilot - cat << GH_AW_MCP_CONFIG_EOF | bash /opt/gh-aw/actions/start_mcp_gateway.sh - { - "mcpServers": { - "agents-md-generator": { - "type": "http", - "url": "https://agents-md-generator.fastmcp.app/mcp", - "tools": [ - "generate_agents_md" - ] - }, - "github": { - "type": "stdio", - "container": "ghcr.io/github/github-mcp-server:v0.31.0", - "env": { - "GITHUB_LOCKDOWN_MODE": "$GITHUB_MCP_LOCKDOWN", - "GITHUB_PERSONAL_ACCESS_TOKEN": "\${GITHUB_MCP_SERVER_TOKEN}", - "GITHUB_READ_ONLY": "1", - "GITHUB_TOOLSETS": "repos,issues,pull_requests,search" - } - }, - "public-code-search": { - "type": "http", - "url": "https://public-code-search.fastmcp.app/mcp", - "tools": [ - "search_code" - ] - }, - "safeoutputs": { - "type": "http", - "url": "http://host.docker.internal:$GH_AW_SAFE_OUTPUTS_PORT", - "headers": { - "Authorization": "\${GH_AW_SAFE_OUTPUTS_API_KEY}" - } - } - }, - "gateway": { - "port": $MCP_GATEWAY_PORT, - "domain": "${MCP_GATEWAY_DOMAIN}", - "apiKey": "${MCP_GATEWAY_API_KEY}", - "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" - } - } - GH_AW_MCP_CONFIG_EOF - - name: Generate workflow overview - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - with: - script: | - const { generateWorkflowOverview } = require('/opt/gh-aw/actions/generate_workflow_overview.cjs'); - await generateWorkflowOverview(core); - - name: Download prompt artifact - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 - with: - name: prompt - path: /tmp/gh-aw/aw-prompts - - name: Clean git credentials - run: bash /opt/gh-aw/actions/clean_git_credentials.sh - - name: Execute GitHub Copilot CLI - id: agentic_execution - # Copilot CLI tool arguments (sorted): - timeout-minutes: 90 - run: | - set -o pipefail - sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --allow-domains '*.githubusercontent.com,*.jsr.io,*.pythonhosted.org,*.rvm.io,agents-md-generator.fastmcp.app,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.rubygems.org,api.snapcraft.io,archive.ubuntu.com,artifacts.elastic.co,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,bun.sh,bundler.rubygems.org,cache.ruby-lang.org,cdn.jsdelivr.net,cloud.elastic.co,codeload.github.com,conda.anaconda.org,conda.binstar.org,crates.io,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,deb.nodesource.com,deno.land,ela.st,elastic.co,esm.sh,files.pythonhosted.org,gems.rubyforge.org,gems.rubyonrails.org,get.pnpm.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,host.docker.internal,index.crates.io,index.rubygems.org,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,lfs.github.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,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,pip.pypa.io,pkg.go.dev,ppa.launchpad.net,proxy.golang.org,public-code-search.fastmcp.app,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.bower.io,registry.npmjs.com,registry.npmjs.org,registry.yarnpkg.com,repo.anaconda.com,repo.continuum.io,repo.yarnpkg.com,rubygems.org,rubygems.pkg.github.com,s.symcb.com,s.symcd.com,security.ubuntu.com,skimdb.npmjs.com,static.crates.io,storage.googleapis.com,sum.golang.org,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.elastic.co,www.npmjs.com,www.npmjs.org,yarnpkg.com' --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.20.2 --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 --model gpt-5.3-codex --allow-all-tools --allow-all-paths --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log - env: - COPILOT_AGENT_RUNNER_TYPE: STANDALONE - COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} - GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json - GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GITHUB_HEAD_REF: ${{ github.head_ref }} - GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - GITHUB_REF_NAME: ${{ github.ref_name }} - GITHUB_STEP_SUMMARY: ${{ env.GITHUB_STEP_SUMMARY }} - GITHUB_WORKSPACE: ${{ github.workspace }} - XDG_CONFIG_HOME: /home/runner - - name: Configure Git credentials - env: - REPO_NAME: ${{ github.repository }} - SERVER_URL: ${{ github.server_url }} - run: | - git config --global user.email "github-actions[bot]@users.noreply.github.com" - git config --global user.name "github-actions[bot]" - # Re-authenticate git with GitHub token - SERVER_URL_STRIPPED="${SERVER_URL#https://}" - git remote set-url origin "https://x-access-token:${{ github.token }}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" - echo "Git configured with standard GitHub Actions identity" - - name: Copy Copilot session state files to logs - if: always() - continue-on-error: true - run: | - # Copy Copilot session state files to logs folder for artifact collection - # This ensures they are in /tmp/gh-aw/ where secret redaction can scan them - SESSION_STATE_DIR="$HOME/.copilot/session-state" - LOGS_DIR="/tmp/gh-aw/sandbox/agent/logs" - - if [ -d "$SESSION_STATE_DIR" ]; then - echo "Copying Copilot session state files from $SESSION_STATE_DIR to $LOGS_DIR" - mkdir -p "$LOGS_DIR" - cp -v "$SESSION_STATE_DIR"/*.jsonl "$LOGS_DIR/" 2>/dev/null || true - echo "Session state files copied successfully" - else - echo "No session-state directory found at $SESSION_STATE_DIR" - fi - - name: Stop MCP Gateway - if: always() - continue-on-error: true - env: - MCP_GATEWAY_PORT: ${{ steps.start-mcp-gateway.outputs.gateway-port }} - MCP_GATEWAY_API_KEY: ${{ steps.start-mcp-gateway.outputs.gateway-api-key }} - GATEWAY_PID: ${{ steps.start-mcp-gateway.outputs.gateway-pid }} - run: | - bash /opt/gh-aw/actions/stop_mcp_gateway.sh "$GATEWAY_PID" - - name: Redact secrets in logs - if: always() - 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/redact_secrets.cjs'); - await main(); - env: - GH_AW_SECRET_NAMES: 'COPILOT_GITHUB_TOKEN,GH_AW_GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,GITHUB_TOKEN' - SECRET_COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} - SECRET_GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} - SECRET_GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} - SECRET_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Upload Safe Outputs - if: always() - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 - with: - name: safe-output - path: ${{ env.GH_AW_SAFE_OUTPUTS }} - if-no-files-found: warn - - name: Ingest agent output - id: collect_output - if: always() - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,*.jsr.io,*.pythonhosted.org,*.rvm.io,agents-md-generator.fastmcp.app,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.rubygems.org,api.snapcraft.io,archive.ubuntu.com,artifacts.elastic.co,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,bun.sh,bundler.rubygems.org,cache.ruby-lang.org,cdn.jsdelivr.net,cloud.elastic.co,codeload.github.com,conda.anaconda.org,conda.binstar.org,crates.io,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,deb.nodesource.com,deno.land,ela.st,elastic.co,esm.sh,files.pythonhosted.org,gems.rubyforge.org,gems.rubyonrails.org,get.pnpm.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,host.docker.internal,index.crates.io,index.rubygems.org,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,lfs.github.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,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,pip.pypa.io,pkg.go.dev,ppa.launchpad.net,proxy.golang.org,public-code-search.fastmcp.app,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.bower.io,registry.npmjs.com,registry.npmjs.org,registry.yarnpkg.com,repo.anaconda.com,repo.continuum.io,repo.yarnpkg.com,rubygems.org,rubygems.pkg.github.com,s.symcb.com,s.symcd.com,security.ubuntu.com,skimdb.npmjs.com,static.crates.io,storage.googleapis.com,sum.golang.org,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.elastic.co,www.npmjs.com,www.npmjs.org,yarnpkg.com" - GITHUB_SERVER_URL: ${{ github.server_url }} - GITHUB_API_URL: ${{ github.api_url }} - 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/collect_ndjson_output.cjs'); - await main(); - - name: Upload sanitized agent output - if: always() && env.GH_AW_AGENT_OUTPUT - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 - with: - name: agent-output - path: ${{ env.GH_AW_AGENT_OUTPUT }} - if-no-files-found: warn - - name: Upload engine output files - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 - with: - name: agent_outputs - path: | - /tmp/gh-aw/sandbox/agent/logs/ - /tmp/gh-aw/redacted-urls.log - if-no-files-found: ignore - - name: Parse agent logs for step summary - if: always() - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_AGENT_OUTPUT: /tmp/gh-aw/sandbox/agent/logs/ - 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/parse_copilot_log.cjs'); - await main(); - - name: Parse MCP Gateway logs for step summary - if: always() - 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/parse_mcp_gateway_log.cjs'); - await main(); - - name: Print firewall logs - if: always() - continue-on-error: true - env: - AWF_LOGS_DIR: /tmp/gh-aw/sandbox/firewall/logs - run: | - # Fix permissions on firewall logs so they can be uploaded as artifacts - # AWF runs with sudo, creating files owned by root - sudo chmod -R a+r /tmp/gh-aw/sandbox/firewall/logs 2>/dev/null || true - # Only run awf logs summary if awf command exists (it may not be installed if workflow failed before install step) - if command -v awf &> /dev/null; then - awf logs summary | tee -a "$GITHUB_STEP_SUMMARY" - else - echo 'AWF binary not installed, skipping firewall log summary' - fi - - name: Upload agent artifacts - if: always() - continue-on-error: true - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 - with: - name: agent-artifacts - path: | - /tmp/gh-aw/aw-prompts/prompt.txt - /tmp/gh-aw/aw_info.json - /tmp/gh-aw/mcp-logs/ - /tmp/gh-aw/sandbox/firewall/logs/ - /tmp/gh-aw/agent-stdio.log - /tmp/gh-aw/agent/ - if-no-files-found: ignore - - conclusion: - needs: - - activation - - agent - - detection - - safe_outputs - if: (always()) && (needs.agent.result != 'skipped') - runs-on: ubuntu-slim - permissions: - contents: read - issues: write - outputs: - noop_message: ${{ steps.noop.outputs.noop_message }} - tools_reported: ${{ steps.missing_tool.outputs.tools_reported }} - total_count: ${{ steps.missing_tool.outputs.total_count }} - steps: - - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 - with: - destination: /opt/gh-aw/actions - - name: Download agent output artifact - continue-on-error: true - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 - with: - name: agent-output - path: /tmp/gh-aw/safeoutputs/ - - name: Setup agent output environment variable - run: | - mkdir -p /tmp/gh-aw/safeoutputs/ - find "/tmp/gh-aw/safeoutputs/" -type f -print - echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/safeoutputs/agent_output.json" >> "$GITHUB_ENV" - - name: Process No-Op Messages - id: noop - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_NOOP_MAX: 1 - GH_AW_WORKFLOW_NAME: "Breaking Change Detect" - with: - github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - script: | - const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io); - const { main } = require('/opt/gh-aw/actions/noop.cjs'); - await main(); - - name: Record Missing Tool - id: missing_tool - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_WORKFLOW_NAME: "Breaking Change Detect" - with: - github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - script: | - const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io); - const { main } = require('/opt/gh-aw/actions/missing_tool.cjs'); - await main(); - - name: Handle Agent Failure - id: handle_agent_failure - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_WORKFLOW_NAME: "Breaking Change Detect" - 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: "gh-aw-breaking-change-detect" - GH_AW_SECRET_VERIFICATION_RESULT: ${{ needs.agent.outputs.secret_verification_result }} - GH_AW_CHECKOUT_PR_SUCCESS: ${{ needs.agent.outputs.checkout_pr_success }} - GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\"}" - GH_AW_GROUP_REPORTS: "false" - with: - github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - script: | - const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io); - const { main } = require('/opt/gh-aw/actions/handle_agent_failure.cjs'); - await main(); - - name: Handle No-Op Message - id: handle_noop_message - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_WORKFLOW_NAME: "Breaking Change Detect" - 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 }} - GH_AW_NOOP_REPORT_AS_ISSUE: "true" - with: - github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - script: | - const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io); - const { main } = require('/opt/gh-aw/actions/handle_noop_message.cjs'); - await main(); - - detection: - needs: agent - if: needs.agent.outputs.output_types != '' || needs.agent.outputs.has_patch == 'true' - runs-on: ubuntu-latest - permissions: {} - concurrency: - group: "gh-aw-copilot-${{ github.workflow }}" - timeout-minutes: 10 - outputs: - success: ${{ steps.parse_results.outputs.success }} - steps: - - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 - with: - destination: /opt/gh-aw/actions - - name: Download agent artifacts - continue-on-error: true - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 - with: - name: agent-artifacts - path: /tmp/gh-aw/threat-detection/ - - name: Download agent output artifact - continue-on-error: true - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 - with: - name: agent-output - path: /tmp/gh-aw/threat-detection/ - - name: Print agent output types - env: - AGENT_OUTPUT_TYPES: ${{ needs.agent.outputs.output_types }} - run: | - echo "Agent output-types: $AGENT_OUTPUT_TYPES" - - name: Setup threat detection - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - WORKFLOW_NAME: "Breaking Change Detect" - WORKFLOW_DESCRIPTION: "Detect undocumented breaking changes in public interfaces" - HAS_PATCH: ${{ needs.agent.outputs.has_patch }} - 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/setup_threat_detection.cjs'); - await main(); - - name: Ensure threat-detection directory and log - run: | - mkdir -p /tmp/gh-aw/threat-detection - touch /tmp/gh-aw/threat-detection/detection.log - - name: Validate COPILOT_GITHUB_TOKEN secret - id: validate-secret - run: /opt/gh-aw/actions/validate_multi_secret.sh COPILOT_GITHUB_TOKEN 'GitHub Copilot CLI' https://github.github.com/gh-aw/reference/engines/#github-copilot-default - env: - COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} - - name: Install GitHub Copilot CLI - run: /opt/gh-aw/actions/install_copilot_cli.sh 0.0.412 - - name: Execute GitHub Copilot CLI - id: agentic_execution - # Copilot CLI tool arguments (sorted): - # --allow-tool shell(cat) - # --allow-tool shell(grep) - # --allow-tool shell(head) - # --allow-tool shell(jq) - # --allow-tool shell(ls) - # --allow-tool shell(tail) - # --allow-tool shell(wc) - timeout-minutes: 20 - run: | - set -o pipefail - COPILOT_CLI_INSTRUCTION="$(cat /tmp/gh-aw/aw-prompts/prompt.txt)" - mkdir -p /tmp/ - mkdir -p /tmp/gh-aw/ - mkdir -p /tmp/gh-aw/agent/ - mkdir -p /tmp/gh-aw/sandbox/agent/logs/ - copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --model gpt-5.3-codex --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log - env: - COPILOT_AGENT_RUNNER_TYPE: STANDALONE - COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} - GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - GITHUB_HEAD_REF: ${{ github.head_ref }} - GITHUB_REF_NAME: ${{ github.ref_name }} - GITHUB_STEP_SUMMARY: ${{ env.GITHUB_STEP_SUMMARY }} - GITHUB_WORKSPACE: ${{ github.workspace }} - XDG_CONFIG_HOME: /home/runner - - name: Parse threat detection results - id: parse_results - 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/parse_threat_detection_results.cjs'); - await main(); - - name: Upload threat detection log - if: always() - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 - with: - name: threat-detection.log - path: /tmp/gh-aw/threat-detection/detection.log - if-no-files-found: ignore - - pre_activation: - runs-on: ubuntu-slim - outputs: - activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} - steps: - - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 - with: - destination: /opt/gh-aw/actions - - name: Check team membership for workflow - id: check_membership - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_REQUIRED_ROLES: admin,maintainer,write - GH_AW_ALLOWED_BOTS: ${{ inputs.allowed-bot-users }} - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - 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_membership.cjs'); - await main(); - - safe_outputs: - needs: - - agent - - detection - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (needs.detection.outputs.success == 'true') - runs-on: ubuntu-slim - permissions: - contents: read - issues: write - timeout-minutes: 15 - env: - GH_AW_ENGINE_ID: "copilot" - GH_AW_ENGINE_MODEL: "gpt-5.3-codex" - GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\"}" - GH_AW_WORKFLOW_ID: "gh-aw-breaking-change-detect" - GH_AW_WORKFLOW_NAME: "Breaking Change Detect" - outputs: - create_discussion_error_count: ${{ steps.process_safe_outputs.outputs.create_discussion_error_count }} - create_discussion_errors: ${{ steps.process_safe_outputs.outputs.create_discussion_errors }} - process_safe_outputs_processed_count: ${{ steps.process_safe_outputs.outputs.processed_count }} - process_safe_outputs_temporary_id_map: ${{ steps.process_safe_outputs.outputs.temporary_id_map }} - steps: - - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 - with: - destination: /opt/gh-aw/actions - - name: Download agent output artifact - continue-on-error: true - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 - with: - name: agent-output - path: /tmp/gh-aw/safeoutputs/ - - name: Setup agent output environment variable - run: | - mkdir -p /tmp/gh-aw/safeoutputs/ - find "/tmp/gh-aw/safeoutputs/" -type f -print - echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/safeoutputs/agent_output.json" >> "$GITHUB_ENV" - - name: Process Safe Outputs - id: process_safe_outputs - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_issue\":{\"close_older_issues\":true,\"expires\":168,\"max\":1,\"title_prefix\":\"[breaking-change] \"},\"missing_data\":{},\"missing_tool\":{}}" - with: - github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - script: | - const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io); - const { main } = require('/opt/gh-aw/actions/safe_output_handler_manager.cjs'); - await main(); - - name: Upload safe output items manifest - if: always() - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 - with: - name: safe-output-items - path: /tmp/safe-output-items.jsonl - if-no-files-found: warn - diff --git a/.github/workflows/gh-aw-breaking-change-detect.lock.yml b/.github/workflows/gh-aw-breaking-change-detect.lock.yml new file mode 120000 index 00000000..1d4e27e3 --- /dev/null +++ b/.github/workflows/gh-aw-breaking-change-detect.lock.yml @@ -0,0 +1 @@ +gh-aw-breaking-change-detector.lock.yml \ No newline at end of file diff --git a/.github/workflows/gh-aw-breaking-change-detector.lock.yml b/.github/workflows/gh-aw-breaking-change-detector.lock.yml new file mode 100644 index 00000000..f47347b5 --- /dev/null +++ b/.github/workflows/gh-aw-breaking-change-detector.lock.yml @@ -0,0 +1,1481 @@ +# +# ___ _ _ +# / _ \ | | (_) +# | |_| | __ _ ___ _ __ | |_ _ ___ +# | _ |/ _` |/ _ \ '_ \| __| |/ __| +# | | | | (_| | __/ | | | |_| | (__ +# \_| |_/\__, |\___|_| |_|\__|_|\___| +# __/ | +# _ _ |___/ +# | | | | / _| | +# | | | | ___ _ __ _ __| |_| | _____ ____ +# | |/\| |/ _ \ '__| |/ /| _| |/ _ \ \ /\ / / ___| +# \ /\ / (_) | | | | ( | | | | (_) \ V V /\__ \ +# \/ \/ \___/|_| |_|\_\|_| |_|\___/ \_/\_/ |___/ +# +# This file was automatically generated by gh-aw. DO NOT EDIT. +# +# To update this file, edit the corresponding .md file and run: +# gh aw compile +# Not all edits will cause changes to this file. +# +# For more information: https://github.github.com/gh-aw/introduction/overview/ +# +# Detect undocumented breaking changes in public interfaces +# +# Resolved workflow manifest: +# Imports: +# - gh-aw-fragments/elastic-tools.md +# - gh-aw-fragments/ensure-full-history.md +# - gh-aw-fragments/formatting.md +# - gh-aw-fragments/mcp-pagination.md +# - gh-aw-fragments/messages-footer.md +# - gh-aw-fragments/rigor.md +# - gh-aw-fragments/runtime-setup.md +# - gh-aw-fragments/safe-output-create-issue.md +# - gh-aw-fragments/scheduled-audit.md +# +# inlined-imports: true +# +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"d6a0d77b690516b43b333659ea2bfb1aa15b8dcbf15bc347bb42306cd38ea922"} + +name: "Breaking Change Detector" +"on": + # bots: # Bots processed as bot check in pre-activation job + # - ${{ inputs.allowed-bot-users }} # Bots processed as bot check in pre-activation job + # roles: # Roles processed as role check in pre-activation job + # - admin # Roles processed as role check in pre-activation job + # - maintainer # Roles processed as role check in pre-activation job + # - write # Roles processed as role check in pre-activation job + workflow_call: + inputs: + additional-instructions: + default: "" + description: Repo-specific instructions appended to the agent prompt + required: false + type: string + allowed-bot-users: + default: github-actions[bot] + description: Allowlisted bot actor usernames (comma-separated) + required: false + type: string + messages-footer: + default: "" + description: Footer appended to all agent comments and reviews + required: false + type: string + model: + default: gpt-5.3-codex + description: AI model to use + required: false + type: string + setup-commands: + default: "" + description: Shell commands to run before the agent starts (dependency install, build, etc.) + required: false + type: string + secrets: + COPILOT_GITHUB_TOKEN: + required: true + +permissions: {} + +concurrency: + cancel-in-progress: true + group: breaking-change-detector + +run-name: "Breaking Change Detector" + +jobs: + activation: + needs: pre_activation + if: needs.pre_activation.outputs.activated == 'true' + runs-on: ubuntu-slim + permissions: + contents: read + outputs: + comment_id: "" + comment_repo: "" + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 + with: + destination: /opt/gh-aw/actions + - name: Validate context variables + 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/validate_context_variables.cjs'); + await main(); + - name: Checkout .github and .agents folders + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + sparse-checkout: | + .github + .agents + fetch-depth: 1 + persist-credentials: false + - name: Check workflow file timestamps + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_WORKFLOW_FILE: "gh-aw-breaking-change-detector.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: Create prompt with built-in context + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} + GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} + GH_AW_GITHUB_ACTOR: ${{ github.actor }} + GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} + GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} + GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} + GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} + GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} + GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} + run: | + bash /opt/gh-aw/actions/create_prompt_first.sh + cat << 'GH_AW_PROMPT_EOF' > "$GH_AW_PROMPT" + + GH_AW_PROMPT_EOF + cat "/opt/gh-aw/prompts/xpia.md" >> "$GH_AW_PROMPT" + cat "/opt/gh-aw/prompts/temp_folder_prompt.md" >> "$GH_AW_PROMPT" + cat "/opt/gh-aw/prompts/markdown.md" >> "$GH_AW_PROMPT" + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + + GitHub API Access Instructions + + The gh CLI is NOT authenticated. Do NOT use gh commands for GitHub operations. + + + To create or modify GitHub resources (issues, discussions, pull requests, etc.), you MUST call the appropriate safe output tool. Simply writing content will NOT work - the workflow requires actual tool calls. + + Temporary IDs: Some safe output tools support a temporary ID field (usually named temporary_id) so you can reference newly-created items elsewhere in the SAME agent output (for example, using #aw_abc1 in a later body). + + **IMPORTANT - temporary_id format rules:** + - If you DON'T need to reference the item later, OMIT the temporary_id field entirely (it will be auto-generated if needed) + - If you DO need cross-references/chaining, you MUST match this EXACT validation regex: /^aw_[A-Za-z0-9]{3,8}$/i + - Format: aw_ prefix followed by 3 to 8 alphanumeric characters (A-Z, a-z, 0-9, case-insensitive) + - Valid alphanumeric characters: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 + - INVALID examples: aw_ab (too short), aw_123456789 (too long), aw_test-id (contains hyphen), aw_id_123 (contains underscore) + - VALID examples: aw_abc, aw_abc1, aw_Test123, aw_A1B2C3D4, aw_12345678 + - To generate valid IDs: use 3-8 random alphanumeric characters or omit the field to let the system auto-generate + + Do NOT invent other aw_* formats — downstream steps will reject them with validation errors matching against /^aw_[A-Za-z0-9]{3,8}$/i. + + Discover available tools from the safeoutputs MCP server. + + **Critical**: Tool calls write structured data that downstream jobs process. Without tool calls, follow-up actions will be skipped. + + **Note**: If you made no other safe output tool calls during this workflow execution, call the "noop" tool to provide a status message indicating completion or that no actions were needed. + + --- + + ## Creating an Issue, Reporting Missing Tools or Functionality, Reporting Missing Data + + **IMPORTANT**: To perform the actions listed above, use the **safeoutputs** tools. Do NOT use `gh`, do NOT call the GitHub API directly. You do not have write access to the GitHub repository. + + **Creating an Issue** + + To create an issue, use the create_issue tool from safeoutputs. + + **Reporting Missing Tools or Functionality** + + To report a missing tool or capability, use the missing_tool tool from safeoutputs. + + **Reporting Missing Data** + + To report missing data required to achieve a goal, use the missing_data tool from safeoutputs. + + + + + The following GitHub context information is available for this workflow: + {{#if __GH_AW_GITHUB_ACTOR__ }} + - **actor**: __GH_AW_GITHUB_ACTOR__ + {{/if}} + {{#if __GH_AW_GITHUB_REPOSITORY__ }} + - **repository**: __GH_AW_GITHUB_REPOSITORY__ + {{/if}} + {{#if __GH_AW_GITHUB_WORKSPACE__ }} + - **workspace**: __GH_AW_GITHUB_WORKSPACE__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_ISSUE_NUMBER__ }} + - **issue-number**: #__GH_AW_GITHUB_EVENT_ISSUE_NUMBER__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__ }} + - **discussion-number**: #__GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__ }} + - **pull-request-number**: #__GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_COMMENT_ID__ }} + - **comment-id**: __GH_AW_GITHUB_EVENT_COMMENT_ID__ + {{/if}} + {{#if __GH_AW_GITHUB_RUN_ID__ }} + - **workflow-run-id**: __GH_AW_GITHUB_RUN_ID__ + {{/if}} + + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + ## MCP Servers + + - **`generate_agents_md`** — generates a summary of the repository's structure, conventions, and coding guidelines from AGENTS.md and related files. Call at the start of every workflow to get repo context. + - **`search_code`** — grep-style search across public GitHub repositories. Use for finding usage patterns in upstream libraries, reference implementations, or examples in open-source projects. This searches *public GitHub repos*, not the local codebase — if available you can use `grep` and file reading for local code. + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + ## Formatting Guidelines + + - Lead with the most important information — your first sentence should be the key takeaway + - Be concise and actionable — no filler or praise + - Use `
` and `` tags for long sections to keep responses scannable + - Wrap branch names and @-references in backticks to avoid pinging users + - Include code snippets with file paths and line numbers when referencing the codebase + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + ## Rigor + + **Silence is better than noise. A false positive wastes a human's time and erodes trust in every future report.** + + - If you claim something is missing or broken, show the exact evidence in the code — file path, line number, and what you observed. + - If a conclusion depends on assumptions you haven't confirmed, do not assert it. Verify first; if you cannot verify, do not report. + - "I don't know" is better than a wrong answer. `noop` is better than a speculative finding. + - It's worth the time to verify now versus guessing and forcing someone else to verify later. + - Before filing any issue or opening any PR, re-read your own output as a skeptical reviewer. Ask: "Would a senior engineer on this team find this useful, or would they close it immediately?" If the answer is "close," call `noop` instead. + - Only report findings you would confidently defend in a code review. If you feel the need to hedge with "might," "could," or "possibly," the finding is not ready to file. + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + ## MCP Pagination + + MCP tool responses have a **25,000 token limit**. When responses exceed this limit, the call fails and you must retry with pagination — wasting turns and tokens. Use proactive pagination to stay under the limit. + + ### Recommended `perPage` Values + + - **5-10**: For detailed items (PR diffs, files with patches, issues with comments) + - **20-30**: For medium-detail lists (commits, review comments, issue lists) + - **50-100**: For simple list operations (branches, labels, tags) + + ### Pagination Pattern + + When you need all results from a paginated API: + + 1. Fetch the first page with a conservative `perPage` value + 2. Process the results before fetching the next page + 3. Continue fetching pages until you receive fewer results than `perPage` (indicating the last page) + + ### Error Recovery + + If you see an error like: + - `MCP tool response exceeds maximum allowed tokens (25000)` + - `Response too large for tool [tool_name]` + + Retry the same call with a smaller `perPage` value (halve it). + + ### Tips + + - **Start small**: It's better to make multiple small requests than one that fails + - **Fetch incrementally**: Get an overview first, then details for specific items + - **Use filters**: Combine `perPage` with state, label, or date filters to reduce result size + - **Process as you go**: Don't accumulate all pages before acting — process each batch immediately + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + ## Message Footer + + A footer is automatically appended to all comments and reviews. Do not add your own footer or sign-off — the runtime handles this. + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + ## create-issue Limitations + + - **Title**: Max 128 characters. Sanitized (special characters escaped). + - **Labels**: Max 10 labels per issue. Each label max 64 characters. Labels containing only `-` are rejected. + - **Assignees**: Max 5 assignees per issue. + - **Body**: No strict character limit beyond GitHub's API limit (~65,536 characters), but fields over 16,000 tokens are written to a file reference instead of inlined. + - **Bot triggers**: References like `fixes #123` or `closes #456` in the body are neutralized to prevent unintended issue closures. + - **Mentions**: `@mentions` in the body are neutralized (backticked) by default. + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + You are an agent for __GH_AW_GITHUB_REPOSITORY__. You run on a schedule to investigate the repository and file an issue when something needs attention. Your specific assignment is described in the **Report Assignment** section below. + + ## Context + + - **Repository**: __GH_AW_GITHUB_REPOSITORY__ + + ## Constraints + + This workflow is for detection and reporting only. You can read files, search code, run commands, and read PR/issue details — but your only output is either a single issue or a noop. + + ## Process + + Follow these steps in order. + + ### Step 1: Gather Context + + 1. Call `generate_agents_md` to get the repository's coding guidelines and conventions. If this fails, continue without it. + 2. Follow the data gathering instructions in the **Report Assignment** section. + + ### Step 2: Analyze + + Follow the analysis instructions in the **Report Assignment** section to determine whether an issue should be filed. The Report Assignment defines: + - What data to gather and how + - What to look for + - What constitutes a finding worth reporting + - What to skip or ignore + + ### Step 3: Self-Review (Quality Gate) + + Before filing anything, critically evaluate every finding against these criteria: + + 1. **Evidence is concrete** — you can point to exact file paths, line numbers, commit SHAs, or command outputs. No "I believe" or "it seems." + 2. **Finding is actionable** — a maintainer reading the issue can act on it without re-investigating from scratch. + 3. **Finding is not already tracked** — you checked open issues and recent PRs for duplicates. + 4. **Finding is worth a human's time** — the issue is material enough that a maintainer would thank you for filing it, not close it as noise. + + If zero findings pass all four criteria, call `noop` with a brief reason and stop. **Noop is the expected outcome most days.** Filing nothing is a success when there is nothing worth filing. + + ### Step 4: Report + + If there are findings that pass the quality gate, call `create_issue` with a structured report. Use the issue format specified in the Report Assignment if one is provided, otherwise use this default format: + + **Issue title:** Brief summary of findings + + **Issue body:** + + > ## Findings + > + > ### 1. [Brief description] + > + > **Evidence:** [Links, references, or data supporting the finding] + > **Action needed:** [What should be done] + > + > ## Suggested Actions + > + > - [ ] [Actionable checkbox for each finding] + + **Guidelines:** + - Group related findings together + - Be specific about what needs to happen + - Include links and references where possible + - Make suggested actions concrete enough to act on without re-investigating + - If a finding is ambiguous, it does not pass the quality gate — drop it + + **Report Assignment:** + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + Detect unintended breaking changes introduced in the last day that were not documented in PR descriptions, release notes, or repo documentation. + + ### Data Gathering + + Determine the lookback window based on the current day of the week: + - **Monday**: Use `--since="3 days ago"` to capture Friday, Saturday, and Sunday + - **Tuesday through Friday**: Use `--since="1 day ago"` to capture the previous day + - **Manual trigger** (`workflow_dispatch`): Use `--since="1 day ago"` + + Run `git log --since="" --oneline --stat` to get a summary of recent commits. If there are no commits in the lookback window, call `noop` and stop. + + For each commit (or cluster of related commits): + - Review the full diff (`git show ` or `git diff ^!`) to understand what changed. + - Map commits to PRs using `github-search_pull_requests` with query `repo:elastic/ai-github-actions sha:`. + - Read the PR body and related discussion for documentation or migration notes. + - Check for documentation updates in README, DEVELOPING, RELEASE, gh-agent-workflows/README, or any `CHANGELOG*` files (if present). + + ### What to Look For + + Focus on clearly public interface or behavior breaks, such as: + 1. **Workflow interface changes** — removed/renamed workflows, inputs, outputs, triggers, permissions, or schedules used by downstream repos. + 2. **Composite action changes** — removed/renamed inputs/outputs, changed required env vars, altered default behavior. + 3. **Documented guarantees** — changes that contradict or break behavior explicitly described in README/DEVELOPING/RELEASE. + + ### How to Decide "Undocumented" + + A breaking change is **undocumented** if none of the following mention the break or migration steps: + - PR title/body or linked discussion + - RELEASE.md or any release notes in the lookback window + - README/DEVELOPING or other documentation updated in the same PR/commit set + + ### What to Skip + + - Internal refactors with no public impact + - Changes that already include documentation or migration notes + - Test-only changes + - Changes already tracked by an open issue or PR + - Additive changes that don't break existing consumers (new optional inputs with defaults, new workflows, new outputs) + - Changes to internal/private interfaces not consumed by downstream repos + + ### Quality Gate — When to Noop + + **Noop is the expected outcome most days.** Only file an issue when you can demonstrate a concrete break: + - A downstream consumer using the documented interface would **fail or get wrong results** after this change. + - You can identify the **specific interface contract** that was broken (removed input, changed type, renamed workflow, etc.). + - The break is **not documented** anywhere in the PR, release notes, or repo docs. + + Do not file for: speculative breaks ("this might affect someone"), internal restructuring, or changes where backward compatibility is maintained (even if the approach changed). + + ### Issue Format + + **Issue title:** Undocumented breaking changes detected (date) + + **Issue body:** + + > Recent commits introduced breaking changes that appear undocumented. + > + > ## Breaking Changes + > + > ### 1. [Brief description] + > **Commit(s):** [SHA(s) with links] + > **PR:** [Link] + > **What broke:** [Concise description] + > **Evidence:** [Diff or file references] + > **Why undocumented:** [Where documentation is missing] + > **Suggested fix:** [Docs update or migration note] + > + > ## Suggested Actions + > - [ ] Document each breaking change (README/DEVELOPING/RELEASE or release notes) + > - [ ] Add migration guidance where needed + + __GH_AW_EXPR_49B959F1__ + + GH_AW_PROMPT_EOF + - name: Interpolate variables and render templates + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} + GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} + 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/interpolate_prompt.cjs'); + await main(); + - name: Substitute placeholders + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} + GH_AW_GITHUB_ACTOR: ${{ github.actor }} + GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} + GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} + GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} + 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'); + setupGlobals(core, github, context, exec, io); + + const substitutePlaceholders = require('/opt/gh-aw/actions/substitute_placeholders.cjs'); + + // Call the substitution function + return await substitutePlaceholders({ + file: process.env.GH_AW_PROMPT, + substitutions: { + GH_AW_EXPR_49B959F1: process.env.GH_AW_EXPR_49B959F1, + GH_AW_GITHUB_ACTOR: process.env.GH_AW_GITHUB_ACTOR, + GH_AW_GITHUB_EVENT_COMMENT_ID: process.env.GH_AW_GITHUB_EVENT_COMMENT_ID, + GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: process.env.GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER, + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: process.env.GH_AW_GITHUB_EVENT_ISSUE_NUMBER, + 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_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 + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + run: bash /opt/gh-aw/actions/validate_prompt_placeholders.sh + - name: Print prompt + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + run: bash /opt/gh-aw/actions/print_prompt_summary.sh + - name: Upload prompt artifact + if: success() + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: prompt + path: /tmp/gh-aw/aw-prompts/prompt.txt + retention-days: 1 + + agent: + needs: activation + runs-on: ubuntu-latest + permissions: + contents: read + issues: read + pull-requests: read + concurrency: + group: "gh-aw-copilot-${{ github.workflow }}" + env: + DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} + GH_AW_ASSETS_ALLOWED_EXTS: "" + GH_AW_ASSETS_BRANCH: "" + GH_AW_ASSETS_MAX_SIZE_KB: 0 + GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs + 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: ghawbreakingchangedetector + outputs: + checkout_pr_success: ${{ steps.checkout-pr.outputs.checkout_pr_success || 'true' }} + has_patch: ${{ steps.collect_output.outputs.has_patch }} + model: ${{ steps.generate_aw_info.outputs.model }} + output: ${{ steps.collect_output.outputs.output }} + output_types: ${{ steps.collect_output.outputs.output_types }} + secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 + with: + destination: /opt/gh-aw/actions + - name: Checkout repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + - name: Create gh-aw temp directory + run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh + - if: hashFiles('go.mod') != '' + name: Setup Go + uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5 + with: + cache: true + go-version-file: go.mod + - if: hashFiles('.python-version') != '' + name: Setup Python + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 + with: + python-version-file: .python-version + - if: hashFiles('.node-version') != '' + name: Setup Node.js (.node-version) + uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6 + with: + node-version-file: .node-version + - if: hashFiles('.node-version') == '' && hashFiles('.nvmrc') != '' + name: Setup Node.js (.nvmrc) + uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6 + with: + node-version-file: .nvmrc + - if: hashFiles('.ruby-version') != '' + name: Setup Ruby + uses: ruby/setup-ruby@09a7688d3b55cf0e976497ff046b70949eeaccfd # v1 + with: + bundler-cache: true + ruby-version: .ruby-version + - id: setup-uv + if: hashFiles('pyproject.toml', 'uv.lock') != '' + name: Setup uv + uses: astral-sh/setup-uv@e58605a9b6da7c637471fab8847a5e5a6b8df081 # v5 + - env: + UV_PATH: ${{ steps.setup-uv.outputs.uv-path }} + WORKSPACE: ${{ github.workspace }} + if: hashFiles('pyproject.toml', 'uv.lock') != '' + name: Expose uv in workspace + run: |- + set -euo pipefail + install_dir="$WORKSPACE/.gh-aw-tools/bin" + mkdir -p "$install_dir" + cp "$UV_PATH" "$install_dir/uv" + chmod +x "$install_dir/uv" + echo "$install_dir" >> "$GITHUB_PATH" + shell: bash + - env: + GITHUB_TOKEN: ${{ github.token }} + REPO_NAME: ${{ github.repository }} + SERVER_URL: ${{ github.server_url }} + name: Ensure full history + run: "if git rev-parse --is-shallow-repository | grep -q true; then\n SERVER_URL_STRIPPED=\"${SERVER_URL#https://}\"\n git remote set-url origin \"https://x-access-token:${GITHUB_TOKEN}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git\"\n git fetch --unshallow --quiet\nfi" + - env: + SETUP_COMMANDS: ${{ inputs.setup-commands }} + if: ${{ inputs.setup-commands != '' }} + name: Repo-specific setup + run: eval "$SETUP_COMMANDS" + + - name: Configure Git credentials + env: + REPO_NAME: ${{ github.repository }} + SERVER_URL: ${{ github.server_url }} + run: | + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git config --global user.name "github-actions[bot]" + # Re-authenticate git with GitHub token + SERVER_URL_STRIPPED="${SERVER_URL#https://}" + git remote set-url origin "https://x-access-token:${{ github.token }}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" + echo "Git configured with standard GitHub Actions identity" + - name: Checkout PR branch + id: checkout-pr + if: | + github.event.pull_request + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + with: + github-token: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/checkout_pr_branch.cjs'); + await main(); + - name: Generate agentic run info + id: generate_aw_info + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + with: + script: | + const fs = require('fs'); + + const awInfo = { + engine_id: "copilot", + engine_name: "GitHub Copilot CLI", + model: "${{ inputs.model }}", + version: "", + agent_version: "0.0.412", + workflow_name: "Breaking Change Detector", + experimental: false, + supports_tools_allowlist: true, + run_id: context.runId, + run_number: context.runNumber, + run_attempt: process.env.GITHUB_RUN_ATTEMPT, + repository: context.repo.owner + '/' + context.repo.repo, + ref: context.ref, + sha: context.sha, + actor: context.actor, + event_name: context.eventName, + staged: false, + allowed_domains: ["agents-md-generator.fastmcp.app","artifacts.elastic.co","cloud.elastic.co","defaults","ela.st","elastic.co","github","go","node","public-code-search.fastmcp.app","python","ruby","www.elastic.co"], + firewall_enabled: true, + awf_version: "v0.20.2", + awmg_version: "v0.1.4", + steps: { + firewall: "squid" + }, + created_at: new Date().toISOString() + }; + + // Write to /tmp/gh-aw directory to avoid inclusion in PR + const tmpPath = '/tmp/gh-aw/aw_info.json'; + fs.writeFileSync(tmpPath, JSON.stringify(awInfo, null, 2)); + console.log('Generated aw_info.json at:', tmpPath); + console.log(JSON.stringify(awInfo, null, 2)); + + // Set model as output for reuse in other steps/jobs + core.setOutput('model', awInfo.model); + - name: Validate COPILOT_GITHUB_TOKEN secret + id: validate-secret + run: /opt/gh-aw/actions/validate_multi_secret.sh COPILOT_GITHUB_TOKEN 'GitHub Copilot CLI' https://github.github.com/gh-aw/reference/engines/#github-copilot-default + env: + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + - name: Install GitHub Copilot CLI + run: /opt/gh-aw/actions/install_copilot_cli.sh 0.0.412 + - name: Install awf binary + run: bash /opt/gh-aw/actions/install_awf_binary.sh v0.20.2 + - name: Determine automatic lockdown mode for GitHub MCP Server + id: determine-automatic-lockdown + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} + GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} + with: + script: | + 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.20.2 ghcr.io/github/gh-aw-firewall/api-proxy:0.20.2 ghcr.io/github/gh-aw-firewall/squid:0.20.2 ghcr.io/github/gh-aw-mcpg:v0.1.4 ghcr.io/github/github-mcp-server:v0.31.0 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' + {"create_issue":{"expires":168,"max":1},"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 \"[breaking-change] \".", + "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": "Report that a tool or capability needed to complete the task is not available, or share any information you deem important about missing functionality or limitations. Use this when you cannot accomplish what was requested because the required functionality is missing or access is restricted.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "alternatives": { + "description": "Any workarounds, manual steps, or alternative approaches the user could take (max 256 characters).", + "type": "string" + }, + "reason": { + "description": "Explanation of why this tool is needed or what information you want to share about the limitation (max 256 characters).", + "type": "string" + }, + "tool": { + "description": "Optional: Name or description of the missing tool or capability (max 128 characters). Be specific about what functionality is needed.", + "type": "string" + } + }, + "required": [ + "reason" + ], + "type": "object" + }, + "name": "missing_tool" + }, + { + "description": "Log a transparency message when no significant actions are needed. Use this to confirm workflow completion and provide visibility when analysis is complete but no changes or outputs are required (e.g., 'No issues found', 'All checks passed'). This ensures the workflow produces human-visible output even when no other actions are taken.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "message": { + "description": "Status or completion message to log. Should explain what was analyzed and the outcome (e.g., 'Code review complete - no issues found', 'Analysis complete - all tests passing').", + "type": "string" + } + }, + "required": [ + "message" + ], + "type": "object" + }, + "name": "noop" + }, + { + "description": "Report that data or information needed to complete the task is not available. Use this when you cannot accomplish what was requested because required data, context, or information is missing.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "alternatives": { + "description": "Any workarounds, manual steps, or alternative approaches the user could take (max 256 characters).", + "type": "string" + }, + "context": { + "description": "Additional context about the missing data or where it should come from (max 256 characters).", + "type": "string" + }, + "data_type": { + "description": "Type or description of the missing data or information (max 128 characters). Be specific about what data is needed.", + "type": "string" + }, + "reason": { + "description": "Explanation of why this data is needed to complete the task (max 256 characters).", + "type": "string" + } + }, + "required": [], + "type": "object" + }, + "name": "missing_data" + } + ] + GH_AW_SAFE_OUTPUTS_TOOLS_EOF + cat > /opt/gh-aw/safeoutputs/validation.json << 'GH_AW_SAFE_OUTPUTS_VALIDATION_EOF' + { + "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_data": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "context": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "data_type": { + "type": "string", + "sanitize": true, + "maxLength": 128 + }, + "reason": { + "type": "string", + "sanitize": true, + "maxLength": 256 + } + } + }, + "missing_tool": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 512 + }, + "reason": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "tool": { + "type": "string", + "sanitize": true, + "maxLength": 128 + } + } + }, + "noop": { + "defaultMax": 1, + "fields": { + "message": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + } + } + } + } + GH_AW_SAFE_OUTPUTS_VALIDATION_EOF + - name: Generate Safe Outputs MCP Server Config + id: safe-outputs-config + run: | + # Generate a secure random API key (360 bits of entropy, 40+ chars) + # Mask immediately to prevent timing vulnerabilities + API_KEY=$(openssl rand -base64 45 | tr -d '/+=') + echo "::add-mask::${API_KEY}" + + PORT=3001 + + # Set outputs for next steps + { + echo "safe_outputs_api_key=${API_KEY}" + echo "safe_outputs_port=${PORT}" + } >> "$GITHUB_OUTPUT" + + echo "Safe Outputs MCP server will run on port ${PORT}" + + - name: Start Safe Outputs MCP HTTP Server + id: safe-outputs-start + env: + DEBUG: '*' + GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-config.outputs.safe_outputs_port }} + GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-config.outputs.safe_outputs_api_key }} + GH_AW_SAFE_OUTPUTS_TOOLS_PATH: /opt/gh-aw/safeoutputs/tools.json + GH_AW_SAFE_OUTPUTS_CONFIG_PATH: /opt/gh-aw/safeoutputs/config.json + GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs + run: | + # Environment variables are set above to prevent template injection + export DEBUG + export GH_AW_SAFE_OUTPUTS_PORT + export GH_AW_SAFE_OUTPUTS_API_KEY + export GH_AW_SAFE_OUTPUTS_TOOLS_PATH + export GH_AW_SAFE_OUTPUTS_CONFIG_PATH + export GH_AW_MCP_LOG_DIR + + bash /opt/gh-aw/actions/start_safe_outputs_server.sh + + - name: Start MCP Gateway + id: start-mcp-gateway + env: + GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} + GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-start.outputs.api_key }} + GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-start.outputs.port }} + GITHUB_MCP_LOCKDOWN: ${{ steps.determine-automatic-lockdown.outputs.lockdown == 'true' && '1' || '0' }} + GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + run: | + set -eo pipefail + mkdir -p /tmp/gh-aw/mcp-config + + # Export gateway environment variables for MCP config and gateway script + export MCP_GATEWAY_PORT="80" + export MCP_GATEWAY_DOMAIN="host.docker.internal" + MCP_GATEWAY_API_KEY=$(openssl rand -base64 45 | tr -d '/+=') + echo "::add-mask::${MCP_GATEWAY_API_KEY}" + export MCP_GATEWAY_API_KEY + export MCP_GATEWAY_PAYLOAD_DIR="/tmp/gh-aw/mcp-payloads" + mkdir -p "${MCP_GATEWAY_PAYLOAD_DIR}" + export DEBUG="*" + + export GH_AW_ENGINE="copilot" + 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 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_LOCKDOWN -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.1.4' + + mkdir -p /home/runner/.copilot + cat << GH_AW_MCP_CONFIG_EOF | bash /opt/gh-aw/actions/start_mcp_gateway.sh + { + "mcpServers": { + "agents-md-generator": { + "type": "http", + "url": "https://agents-md-generator.fastmcp.app/mcp", + "tools": [ + "generate_agents_md" + ] + }, + "github": { + "type": "stdio", + "container": "ghcr.io/github/github-mcp-server:v0.31.0", + "env": { + "GITHUB_LOCKDOWN_MODE": "$GITHUB_MCP_LOCKDOWN", + "GITHUB_PERSONAL_ACCESS_TOKEN": "\${GITHUB_MCP_SERVER_TOKEN}", + "GITHUB_READ_ONLY": "1", + "GITHUB_TOOLSETS": "repos,issues,pull_requests,search" + } + }, + "public-code-search": { + "type": "http", + "url": "https://public-code-search.fastmcp.app/mcp", + "tools": [ + "search_code" + ] + }, + "safeoutputs": { + "type": "http", + "url": "http://host.docker.internal:$GH_AW_SAFE_OUTPUTS_PORT", + "headers": { + "Authorization": "\${GH_AW_SAFE_OUTPUTS_API_KEY}" + } + } + }, + "gateway": { + "port": $MCP_GATEWAY_PORT, + "domain": "${MCP_GATEWAY_DOMAIN}", + "apiKey": "${MCP_GATEWAY_API_KEY}", + "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" + } + } + GH_AW_MCP_CONFIG_EOF + - name: Generate workflow overview + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + with: + script: | + const { generateWorkflowOverview } = require('/opt/gh-aw/actions/generate_workflow_overview.cjs'); + await generateWorkflowOverview(core); + - name: Download prompt artifact + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 + with: + name: prompt + path: /tmp/gh-aw/aw-prompts + - name: Clean git credentials + run: bash /opt/gh-aw/actions/clean_git_credentials.sh + - name: Execute GitHub Copilot CLI + id: agentic_execution + # Copilot CLI tool arguments (sorted): + timeout-minutes: 90 + run: | + set -o pipefail + sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --allow-domains '*.githubusercontent.com,*.jsr.io,*.pythonhosted.org,*.rvm.io,agents-md-generator.fastmcp.app,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.rubygems.org,api.snapcraft.io,archive.ubuntu.com,artifacts.elastic.co,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,bun.sh,bundler.rubygems.org,cache.ruby-lang.org,cdn.jsdelivr.net,cloud.elastic.co,codeload.github.com,conda.anaconda.org,conda.binstar.org,crates.io,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,deb.nodesource.com,deno.land,ela.st,elastic.co,esm.sh,files.pythonhosted.org,gems.rubyforge.org,gems.rubyonrails.org,get.pnpm.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,host.docker.internal,index.crates.io,index.rubygems.org,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,lfs.github.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,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,pip.pypa.io,pkg.go.dev,ppa.launchpad.net,proxy.golang.org,public-code-search.fastmcp.app,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.bower.io,registry.npmjs.com,registry.npmjs.org,registry.yarnpkg.com,repo.anaconda.com,repo.continuum.io,repo.yarnpkg.com,rubygems.org,rubygems.pkg.github.com,s.symcb.com,s.symcd.com,security.ubuntu.com,skimdb.npmjs.com,static.crates.io,storage.googleapis.com,sum.golang.org,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.elastic.co,www.npmjs.com,www.npmjs.org,yarnpkg.com' --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.20.2 --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 --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log + env: + COPILOT_AGENT_RUNNER_TYPE: STANDALONE + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} + GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} + GITHUB_HEAD_REF: ${{ github.head_ref }} + GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + GITHUB_REF_NAME: ${{ github.ref_name }} + GITHUB_STEP_SUMMARY: ${{ env.GITHUB_STEP_SUMMARY }} + GITHUB_WORKSPACE: ${{ github.workspace }} + XDG_CONFIG_HOME: /home/runner + - name: Configure Git credentials + env: + REPO_NAME: ${{ github.repository }} + SERVER_URL: ${{ github.server_url }} + run: | + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git config --global user.name "github-actions[bot]" + # Re-authenticate git with GitHub token + SERVER_URL_STRIPPED="${SERVER_URL#https://}" + git remote set-url origin "https://x-access-token:${{ github.token }}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" + echo "Git configured with standard GitHub Actions identity" + - name: Copy Copilot session state files to logs + if: always() + continue-on-error: true + run: | + # Copy Copilot session state files to logs folder for artifact collection + # This ensures they are in /tmp/gh-aw/ where secret redaction can scan them + SESSION_STATE_DIR="$HOME/.copilot/session-state" + LOGS_DIR="/tmp/gh-aw/sandbox/agent/logs" + + if [ -d "$SESSION_STATE_DIR" ]; then + echo "Copying Copilot session state files from $SESSION_STATE_DIR to $LOGS_DIR" + mkdir -p "$LOGS_DIR" + cp -v "$SESSION_STATE_DIR"/*.jsonl "$LOGS_DIR/" 2>/dev/null || true + echo "Session state files copied successfully" + else + echo "No session-state directory found at $SESSION_STATE_DIR" + fi + - name: Stop MCP Gateway + if: always() + continue-on-error: true + env: + MCP_GATEWAY_PORT: ${{ steps.start-mcp-gateway.outputs.gateway-port }} + MCP_GATEWAY_API_KEY: ${{ steps.start-mcp-gateway.outputs.gateway-api-key }} + GATEWAY_PID: ${{ steps.start-mcp-gateway.outputs.gateway-pid }} + run: | + bash /opt/gh-aw/actions/stop_mcp_gateway.sh "$GATEWAY_PID" + - name: Redact secrets in logs + if: always() + 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/redact_secrets.cjs'); + await main(); + env: + GH_AW_SECRET_NAMES: 'COPILOT_GITHUB_TOKEN,GH_AW_GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,GITHUB_TOKEN' + SECRET_COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + SECRET_GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} + SECRET_GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} + SECRET_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Upload Safe Outputs + if: always() + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: safe-output + path: ${{ env.GH_AW_SAFE_OUTPUTS }} + if-no-files-found: warn + - name: Ingest agent output + id: collect_output + if: always() + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} + GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,*.jsr.io,*.pythonhosted.org,*.rvm.io,agents-md-generator.fastmcp.app,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.rubygems.org,api.snapcraft.io,archive.ubuntu.com,artifacts.elastic.co,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,bun.sh,bundler.rubygems.org,cache.ruby-lang.org,cdn.jsdelivr.net,cloud.elastic.co,codeload.github.com,conda.anaconda.org,conda.binstar.org,crates.io,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,deb.nodesource.com,deno.land,ela.st,elastic.co,esm.sh,files.pythonhosted.org,gems.rubyforge.org,gems.rubyonrails.org,get.pnpm.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,host.docker.internal,index.crates.io,index.rubygems.org,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,lfs.github.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,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,pip.pypa.io,pkg.go.dev,ppa.launchpad.net,proxy.golang.org,public-code-search.fastmcp.app,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.bower.io,registry.npmjs.com,registry.npmjs.org,registry.yarnpkg.com,repo.anaconda.com,repo.continuum.io,repo.yarnpkg.com,rubygems.org,rubygems.pkg.github.com,s.symcb.com,s.symcd.com,security.ubuntu.com,skimdb.npmjs.com,static.crates.io,storage.googleapis.com,sum.golang.org,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.elastic.co,www.npmjs.com,www.npmjs.org,yarnpkg.com" + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_API_URL: ${{ github.api_url }} + 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/collect_ndjson_output.cjs'); + await main(); + - name: Upload sanitized agent output + if: always() && env.GH_AW_AGENT_OUTPUT + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: agent-output + path: ${{ env.GH_AW_AGENT_OUTPUT }} + if-no-files-found: warn + - name: Upload engine output files + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: agent_outputs + path: | + /tmp/gh-aw/sandbox/agent/logs/ + /tmp/gh-aw/redacted-urls.log + if-no-files-found: ignore + - name: Parse agent logs for step summary + if: always() + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: /tmp/gh-aw/sandbox/agent/logs/ + 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/parse_copilot_log.cjs'); + await main(); + - name: Parse MCP Gateway logs for step summary + if: always() + 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/parse_mcp_gateway_log.cjs'); + await main(); + - name: Print firewall logs + if: always() + continue-on-error: true + env: + AWF_LOGS_DIR: /tmp/gh-aw/sandbox/firewall/logs + run: | + # Fix permissions on firewall logs so they can be uploaded as artifacts + # AWF runs with sudo, creating files owned by root + sudo chmod -R a+r /tmp/gh-aw/sandbox/firewall/logs 2>/dev/null || true + # Only run awf logs summary if awf command exists (it may not be installed if workflow failed before install step) + if command -v awf &> /dev/null; then + awf logs summary | tee -a "$GITHUB_STEP_SUMMARY" + else + echo 'AWF binary not installed, skipping firewall log summary' + fi + - name: Upload agent artifacts + if: always() + continue-on-error: true + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: agent-artifacts + path: | + /tmp/gh-aw/aw-prompts/prompt.txt + /tmp/gh-aw/aw_info.json + /tmp/gh-aw/mcp-logs/ + /tmp/gh-aw/sandbox/firewall/logs/ + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/agent/ + if-no-files-found: ignore + + conclusion: + needs: + - activation + - agent + - detection + - safe_outputs + if: (always()) && (needs.agent.result != 'skipped') + runs-on: ubuntu-slim + permissions: + contents: read + issues: write + outputs: + noop_message: ${{ steps.noop.outputs.noop_message }} + tools_reported: ${{ steps.missing_tool.outputs.tools_reported }} + total_count: ${{ steps.missing_tool.outputs.total_count }} + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 + with: + destination: /opt/gh-aw/actions + - name: Download agent output artifact + continue-on-error: true + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 + with: + name: agent-output + path: /tmp/gh-aw/safeoutputs/ + - name: Setup agent output environment variable + run: | + mkdir -p /tmp/gh-aw/safeoutputs/ + find "/tmp/gh-aw/safeoutputs/" -type f -print + echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/safeoutputs/agent_output.json" >> "$GITHUB_ENV" + - name: Process No-Op Messages + id: noop + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_NOOP_MAX: 1 + GH_AW_WORKFLOW_NAME: "Breaking Change Detector" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/noop.cjs'); + await main(); + - name: Record Missing Tool + id: missing_tool + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_WORKFLOW_NAME: "Breaking Change Detector" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/missing_tool.cjs'); + await main(); + - name: Handle Agent Failure + id: handle_agent_failure + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_WORKFLOW_NAME: "Breaking Change Detector" + 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: "gh-aw-breaking-change-detector" + GH_AW_SECRET_VERIFICATION_RESULT: ${{ needs.agent.outputs.secret_verification_result }} + GH_AW_CHECKOUT_PR_SUCCESS: ${{ needs.agent.outputs.checkout_pr_success }} + GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\"}" + GH_AW_GROUP_REPORTS: "false" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/handle_agent_failure.cjs'); + await main(); + - name: Handle No-Op Message + id: handle_noop_message + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_WORKFLOW_NAME: "Breaking Change Detector" + 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 }} + GH_AW_NOOP_REPORT_AS_ISSUE: "true" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/handle_noop_message.cjs'); + await main(); + + detection: + needs: agent + if: needs.agent.outputs.output_types != '' || needs.agent.outputs.has_patch == 'true' + runs-on: ubuntu-latest + permissions: {} + concurrency: + group: "gh-aw-copilot-${{ github.workflow }}" + timeout-minutes: 10 + outputs: + success: ${{ steps.parse_results.outputs.success }} + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 + with: + destination: /opt/gh-aw/actions + - name: Download agent artifacts + continue-on-error: true + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 + with: + name: agent-artifacts + path: /tmp/gh-aw/threat-detection/ + - name: Download agent output artifact + continue-on-error: true + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 + with: + name: agent-output + path: /tmp/gh-aw/threat-detection/ + - name: Print agent output types + env: + AGENT_OUTPUT_TYPES: ${{ needs.agent.outputs.output_types }} + run: | + echo "Agent output-types: $AGENT_OUTPUT_TYPES" + - name: Setup threat detection + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + WORKFLOW_NAME: "Breaking Change Detector" + WORKFLOW_DESCRIPTION: "Detect undocumented breaking changes in public interfaces" + HAS_PATCH: ${{ needs.agent.outputs.has_patch }} + 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/setup_threat_detection.cjs'); + await main(); + - name: Ensure threat-detection directory and log + run: | + mkdir -p /tmp/gh-aw/threat-detection + touch /tmp/gh-aw/threat-detection/detection.log + - name: Validate COPILOT_GITHUB_TOKEN secret + id: validate-secret + run: /opt/gh-aw/actions/validate_multi_secret.sh COPILOT_GITHUB_TOKEN 'GitHub Copilot CLI' https://github.github.com/gh-aw/reference/engines/#github-copilot-default + env: + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + - name: Install GitHub Copilot CLI + run: /opt/gh-aw/actions/install_copilot_cli.sh 0.0.412 + - name: Execute GitHub Copilot CLI + id: agentic_execution + # Copilot CLI tool arguments (sorted): + # --allow-tool shell(cat) + # --allow-tool shell(grep) + # --allow-tool shell(head) + # --allow-tool shell(jq) + # --allow-tool shell(ls) + # --allow-tool shell(tail) + # --allow-tool shell(wc) + timeout-minutes: 20 + run: | + set -o pipefail + COPILOT_CLI_INSTRUCTION="$(cat /tmp/gh-aw/aw-prompts/prompt.txt)" + mkdir -p /tmp/ + mkdir -p /tmp/gh-aw/ + mkdir -p /tmp/gh-aw/agent/ + mkdir -p /tmp/gh-aw/sandbox/agent/logs/ + copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log + env: + COPILOT_AGENT_RUNNER_TYPE: STANDALONE + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GITHUB_HEAD_REF: ${{ github.head_ref }} + GITHUB_REF_NAME: ${{ github.ref_name }} + GITHUB_STEP_SUMMARY: ${{ env.GITHUB_STEP_SUMMARY }} + GITHUB_WORKSPACE: ${{ github.workspace }} + XDG_CONFIG_HOME: /home/runner + - name: Parse threat detection results + id: parse_results + 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/parse_threat_detection_results.cjs'); + await main(); + - name: Upload threat detection log + if: always() + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: threat-detection.log + path: /tmp/gh-aw/threat-detection/detection.log + if-no-files-found: ignore + + pre_activation: + runs-on: ubuntu-slim + outputs: + activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 + with: + destination: /opt/gh-aw/actions + - name: Check team membership for workflow + id: check_membership + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_REQUIRED_ROLES: admin,maintainer,write + GH_AW_ALLOWED_BOTS: ${{ inputs.allowed-bot-users }} + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + 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_membership.cjs'); + await main(); + + safe_outputs: + needs: + - agent + - detection + if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (needs.detection.outputs.success == 'true') + runs-on: ubuntu-slim + permissions: + contents: read + issues: write + timeout-minutes: 15 + env: + GH_AW_ENGINE_ID: "copilot" + GH_AW_ENGINE_MODEL: "${{ inputs.model }}" + GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\"}" + GH_AW_WORKFLOW_ID: "gh-aw-breaking-change-detector" + GH_AW_WORKFLOW_NAME: "Breaking Change Detector" + outputs: + create_discussion_error_count: ${{ steps.process_safe_outputs.outputs.create_discussion_error_count }} + create_discussion_errors: ${{ steps.process_safe_outputs.outputs.create_discussion_errors }} + process_safe_outputs_processed_count: ${{ steps.process_safe_outputs.outputs.processed_count }} + process_safe_outputs_temporary_id_map: ${{ steps.process_safe_outputs.outputs.temporary_id_map }} + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 + with: + destination: /opt/gh-aw/actions + - name: Download agent output artifact + continue-on-error: true + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 + with: + name: agent-output + path: /tmp/gh-aw/safeoutputs/ + - name: Setup agent output environment variable + run: | + mkdir -p /tmp/gh-aw/safeoutputs/ + find "/tmp/gh-aw/safeoutputs/" -type f -print + echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/safeoutputs/agent_output.json" >> "$GITHUB_ENV" + - name: Process Safe Outputs + id: process_safe_outputs + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_issue\":{\"close_older_issues\":true,\"expires\":168,\"max\":1,\"title_prefix\":\"[breaking-change] \"},\"missing_data\":{},\"missing_tool\":{}}" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/safe_output_handler_manager.cjs'); + await main(); + - name: Upload safe output items manifest + if: always() + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: safe-output-items + path: /tmp/safe-output-items.jsonl + if-no-files-found: warn + diff --git a/.github/workflows/gh-aw-breaking-change-detect.md b/.github/workflows/gh-aw-breaking-change-detector.md similarity index 95% rename from .github/workflows/gh-aw-breaking-change-detect.md rename to .github/workflows/gh-aw-breaking-change-detector.md index aadaa2d3..2b4b838b 100644 --- a/.github/workflows/gh-aw-breaking-change-detect.md +++ b/.github/workflows/gh-aw-breaking-change-detector.md @@ -1,5 +1,6 @@ --- -name: "Breaking Change Detect" +inlined-imports: true +name: "Breaking Change Detector" description: "Detect undocumented breaking changes in public interfaces" imports: - gh-aw-fragments/elastic-tools.md @@ -10,13 +11,18 @@ imports: - gh-aw-fragments/mcp-pagination.md - gh-aw-fragments/messages-footer.md - gh-aw-fragments/safe-output-create-issue.md - - gh-aw-fragments/scheduled-report.md + - gh-aw-fragments/scheduled-audit.md engine: id: copilot - model: gpt-5.3-codex + model: ${{ inputs.model }} on: workflow_call: inputs: + model: + description: "AI model to use" + type: string + required: false + default: "gpt-5.3-codex" additional-instructions: description: "Repo-specific instructions appended to the agent prompt" type: string @@ -44,7 +50,7 @@ on: bots: - "${{ inputs.allowed-bot-users }}" concurrency: - group: breaking-change-detect + group: breaking-change-detector cancel-in-progress: true permissions: contents: read diff --git a/.github/workflows/gh-aw-bug-exterminator.lock.yml b/.github/workflows/gh-aw-bug-exterminator.lock.yml index bda184d6..f37a89ad 100644 --- a/.github/workflows/gh-aw-bug-exterminator.lock.yml +++ b/.github/workflows/gh-aw-bug-exterminator.lock.yml @@ -32,11 +32,14 @@ # - gh-aw-fragments/rigor.md # - gh-aw-fragments/runtime-setup.md # - gh-aw-fragments/safe-output-create-pr.md +# - gh-aw-fragments/scheduled-fix.md # - gh-aw-fragments/workflow-edit-guardrails.md # -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"0fed8fc6b7cb7f03afac4c55f82e077038c1623c7467d1bdf32bc8c12b363f79"} +# inlined-imports: true +# +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"bc00a8c8f1d0772fb7dd159091be4a348d113116528c926eae3b8731916a57c3"} -name: "Bug Exterminator" +name: "Gh Aw Bug Exterminator" "on": # bots: # Bots processed as bot check in pre-activation job # - ${{ inputs.allowed-bot-users }} # Bots processed as bot check in pre-activation job @@ -61,6 +64,11 @@ name: "Bug Exterminator" description: Footer appended to all agent comments and reviews required: false type: string + model: + default: gpt-5.3-codex + description: AI model to use + required: false + type: string setup-commands: default: "" description: Shell commands to run before the agent starts (dependency install, build, etc.) @@ -76,7 +84,7 @@ concurrency: cancel-in-progress: true group: bug-exterminator -run-name: "Bug Exterminator" +run-name: "Gh Aw Bug Exterminator" jobs: activation: @@ -90,7 +98,7 @@ jobs: comment_repo: "" steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Validate context variables @@ -167,6 +175,30 @@ jobs: **Critical**: Tool calls write structured data that downstream jobs process. Without tool calls, follow-up actions will be skipped. **Note**: If you made no other safe output tool calls during this workflow execution, call the "noop" tool to provide a status message indicating completion or that no actions were needed. + + --- + + ## Creating a Pull Request, Reporting Missing Tools or Functionality, Reporting Missing Data + + **IMPORTANT**: To perform the actions listed above, use the **safeoutputs** tools. Do NOT use `gh`, do NOT call the GitHub API directly. You do not have write access to the GitHub repository. + + **Creating a Pull Request** + + To create a pull request: + 1. Make any file changes directly in the working directory. + 2. If you haven't done so already, create a local branch using an appropriate unique name. + 3. Add and commit your changes to the branch. Be careful to add exactly the files you intend, and check there are no extra files left un-added. Verify you haven't deleted or changed any files you didn't intend to. + 4. Do not push your changes. That will be done by the tool. + 5. Create the pull request with the create_pull_request tool from safeoutputs. + + **Reporting Missing Tools or Functionality** + + To report a missing tool or capability, use the missing_tool tool from safeoutputs. + + **Reporting Missing Data** + + To report missing data required to achieve a goal, use the missing_data tool from safeoutputs. + @@ -295,9 +327,7 @@ jobs: - You may not submit code that modifies files in `.github/workflows/`. Doing so will cause the submission to be rejected. If asked to modify workflow files, propose the change in a copy placed in a `github/` folder (without the leading period) and note in the PR that the file needs to be relocated by someone with workflow write access. GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - # Bug Exterminator - - Fix a reproducible `bug-hunter` issue by opening a single focused PR. + You are an agent for __GH_AW_GITHUB_REPOSITORY__. You run on a schedule to pick up an open issue and create a focused pull request that addresses it. Your specific assignment is described in the **Fix Assignment** section below. ## Context @@ -308,53 +338,75 @@ jobs: - **CAN**: Read files, search code, modify files locally, run tests and commands, create a pull request. - **CANNOT**: Directly push to the repository — use `create_pull_request`. - **Only one PR per run.** - - Only consider issues labeled `bug-hunter` or with `[bug-hunter]` in the title. - - You must reproduce the issue locally before proposing a fix. - - If no suitable issue is found or reproduction fails, call `noop` with a brief reason. + - If no suitable issue is found, call `noop` with a brief reason. - **Most runs should end with `noop`.** Only open a PR when the fix is clearly correct, tested, and small enough for quick review. - ## Step 1: Gather candidates + ## Process - 1. Call `generate_agents_md` to get repository conventions (if it fails, continue). - 2. Search for open Bug Hunter issues: + Follow these steps in order. - ````text - github-search_issues: query="repo:{owner}/{repo} is:issue is:open (label:bug-hunter OR in:title \"[bug-hunter]\") sort:updated-asc" - ```` + ### Step 1: Gather Candidates + 1. Call `generate_agents_md` to get the repository's coding guidelines and conventions. If this fails, continue without it. + 2. Follow the candidate gathering instructions in the **Fix Assignment** section. 3. For each candidate, read the full issue and comments using `issue_read` (methods `get` and `get_comments`). - ## Step 2: Select a target + ### Step 2: Select a Target Choose one issue with: - - Clear reproduction steps - - A small, well-scoped fix - - No active discussion pointing to a larger design change + - Concrete, actionable instructions (file paths, function names, suggested changes) + - A well-scoped fix that doesn't require design decisions + - No active discussion suggesting the fix should go a different direction - Skip any issue that cannot be reproduced locally. + Skip any issue where the suggested fix is ambiguous, controversial, or too large for a single PR. - ## Step 3: Reproduce and fix + ### Step 3: Implement - 1. Reproduce the bug locally with the exact steps from the issue. - 2. Make the smallest safe change that fixes the issue. - 3. Run the most relevant targeted tests. **Tests must pass.** - 4. Commit the changes locally. + Follow the implementation instructions in the **Fix Assignment** section. The Fix Assignment defines: + - What kind of changes to make + - What tools to use + - Any domain-specific constraints - ## Step 4: Quality Gate — Self-Review + ### Step 4: Quality Gate — Self-Review Before creating the PR, verify: - - **Reproduction**: You reproduced the bug before fixing it. - - **Fix correctness**: The change directly addresses the issue. - - **Tests pass**: List the tests and results in the PR body. - - **Scope**: The change is minimal and focused. + 1. **Fix is correct** — the change directly addresses the issue. + 2. **Tests pass** — you ran the most relevant tests and they pass. + 3. **Scope is minimal** — only changes needed for the fix, no scope creep. + 4. **No regressions** — linters pass, no formatting broken, no new warnings. + + If any check fails, call `noop` with a brief reason. + + ### Step 5: Create the PR + + Call `create_pull_request` with: + - A concise summary of the changes + - A link to the source issue (e.g., "Fixes #123") + - The specific tests that were run and passed + - A note on any items from the issue that were skipped (if any) + + **Fix Assignment:** + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + ### Candidate Search + + Search for open Bug Hunter issues: + + ````text + github-search_issues: query="repo:{owner}/{repo} is:issue is:open (label:bug-hunter OR in:title \"[bug-hunter]\") sort:updated-asc" + ```` - If any check fails, call `noop`. + ### Implementation - ## Step 5: Create the PR + You must reproduce the issue locally before proposing a fix. - Call `create_pull_request` with a concise summary, a link to the issue, and the exact tests run. + 1. Reproduce the bug locally with the exact steps from the issue. + 2. Make the smallest safe change that fixes the issue. + 3. Run the most relevant targeted tests. **Tests must pass.** + 4. Commit the changes locally. __GH_AW_EXPR_49B959F1__ @@ -454,7 +506,7 @@ jobs: secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Checkout repository @@ -548,10 +600,10 @@ jobs: const awInfo = { engine_id: "copilot", engine_name: "GitHub Copilot CLI", - model: "gpt-5.3-codex", + model: "${{ inputs.model }}", version: "", agent_version: "0.0.412", - workflow_name: "Bug Exterminator", + workflow_name: "Gh Aw Bug Exterminator", experimental: false, supports_tools_allowlist: true, run_id: context.runId, @@ -608,7 +660,7 @@ jobs: 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' - {"create_pull_request":{},"missing_data":{},"missing_tool":{},"noop":{"max":1}} + {"create_pull_request":{"max":1},"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' [ @@ -625,6 +677,10 @@ jobs: "description": "Source branch name containing the changes. If omitted, uses the current working branch.", "type": "string" }, + "draft": { + "description": "Whether to create the PR as a draft. Draft PRs cannot be merged until marked as ready for review. Use mark_pull_request_as_ready_for_review to convert a draft PR. Default: true.", + "type": "boolean" + }, "labels": { "description": "Labels to categorize the PR (e.g., 'enhancement', 'bugfix'). Labels must exist in the repository.", "items": { @@ -733,12 +789,19 @@ jobs: "sanitize": true, "maxLength": 256 }, + "draft": { + "type": "boolean" + }, "labels": { "type": "array", "itemType": "string", "itemSanitize": true, "itemMaxLength": 128 }, + "repo": { + "type": "string", + "maxLength": 256 + }, "title": { "required": true, "type": "string", @@ -747,6 +810,31 @@ jobs: } } }, + "missing_data": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "context": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "data_type": { + "type": "string", + "sanitize": true, + "maxLength": 128 + }, + "reason": { + "type": "string", + "sanitize": true, + "maxLength": 256 + } + } + }, "missing_tool": { "defaultMax": 20, "fields": { @@ -1005,10 +1093,11 @@ jobs: run: | set -o pipefail sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --allow-domains '*.githubusercontent.com,*.jsr.io,*.pythonhosted.org,*.rvm.io,agents-md-generator.fastmcp.app,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.rubygems.org,api.snapcraft.io,archive.ubuntu.com,artifacts.elastic.co,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,bun.sh,bundler.rubygems.org,cache.ruby-lang.org,cdn.jsdelivr.net,cloud.elastic.co,codeload.github.com,conda.anaconda.org,conda.binstar.org,crates.io,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,deb.nodesource.com,deno.land,ela.st,elastic.co,esm.sh,files.pythonhosted.org,gems.rubyforge.org,gems.rubyonrails.org,get.pnpm.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,host.docker.internal,index.crates.io,index.rubygems.org,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,lfs.github.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,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,pip.pypa.io,pkg.go.dev,ppa.launchpad.net,proxy.golang.org,public-code-search.fastmcp.app,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.bower.io,registry.npmjs.com,registry.npmjs.org,registry.yarnpkg.com,repo.anaconda.com,repo.continuum.io,repo.yarnpkg.com,rubygems.org,rubygems.pkg.github.com,s.symcb.com,s.symcd.com,security.ubuntu.com,skimdb.npmjs.com,static.crates.io,storage.googleapis.com,sum.golang.org,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.elastic.co,www.npmjs.com,www.npmjs.org,yarnpkg.com' --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.20.2 --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 --model gpt-5.3-codex --allow-all-tools --allow-all-paths --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log + -- /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 --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} @@ -1165,7 +1254,7 @@ jobs: /tmp/gh-aw/sandbox/firewall/logs/ /tmp/gh-aw/agent-stdio.log /tmp/gh-aw/agent/ - /tmp/gh-aw/aw.patch + /tmp/gh-aw/aw-*.patch if-no-files-found: ignore conclusion: @@ -1186,7 +1275,7 @@ jobs: total_count: ${{ steps.missing_tool.outputs.total_count }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent output artifact @@ -1206,7 +1295,7 @@ jobs: env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} GH_AW_NOOP_MAX: 1 - GH_AW_WORKFLOW_NAME: "Bug Exterminator" + GH_AW_WORKFLOW_NAME: "Gh Aw Bug Exterminator" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | @@ -1219,7 +1308,7 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_WORKFLOW_NAME: "Bug Exterminator" + GH_AW_WORKFLOW_NAME: "Gh Aw Bug Exterminator" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | @@ -1232,7 +1321,7 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_WORKFLOW_NAME: "Bug Exterminator" + GH_AW_WORKFLOW_NAME: "Gh Aw Bug Exterminator" 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: "gh-aw-bug-exterminator" @@ -1252,7 +1341,7 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_WORKFLOW_NAME: "Bug Exterminator" + GH_AW_WORKFLOW_NAME: "Gh Aw Bug Exterminator" 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 }} @@ -1269,7 +1358,7 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_WORKFLOW_NAME: "Bug Exterminator" + GH_AW_WORKFLOW_NAME: "Gh Aw Bug Exterminator" GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} @@ -1291,7 +1380,7 @@ jobs: success: ${{ steps.parse_results.outputs.success }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent artifacts @@ -1314,7 +1403,7 @@ jobs: - name: Setup threat detection uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: - WORKFLOW_NAME: "Bug Exterminator" + WORKFLOW_NAME: "Gh Aw Bug Exterminator" WORKFLOW_DESCRIPTION: "Fix bug-hunter issues and open a focused PR" HAS_PATCH: ${{ needs.agent.outputs.has_patch }} with: @@ -1352,10 +1441,11 @@ jobs: mkdir -p /tmp/gh-aw/ mkdir -p /tmp/gh-aw/agent/ mkdir -p /tmp/gh-aw/sandbox/agent/logs/ - copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --model gpt-5.3-codex --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log + copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_REF_NAME: ${{ github.ref_name }} @@ -1385,7 +1475,7 @@ jobs: activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Check team membership for workflow @@ -1416,10 +1506,10 @@ jobs: timeout-minutes: 15 env: GH_AW_ENGINE_ID: "copilot" - GH_AW_ENGINE_MODEL: "gpt-5.3-codex" + GH_AW_ENGINE_MODEL: "${{ inputs.model }}" GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\"}" GH_AW_WORKFLOW_ID: "gh-aw-bug-exterminator" - GH_AW_WORKFLOW_NAME: "Bug Exterminator" + GH_AW_WORKFLOW_NAME: "Gh Aw Bug Exterminator" outputs: create_discussion_error_count: ${{ steps.process_safe_outputs.outputs.create_discussion_error_count }} create_discussion_errors: ${{ steps.process_safe_outputs.outputs.create_discussion_errors }} @@ -1427,7 +1517,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@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent output artifact @@ -1451,7 +1541,7 @@ jobs: if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: - ref: ${{ github.ref_name }} + ref: ${{ github.base_ref || github.ref_name }} token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} persist-credentials: false fetch-depth: 1 @@ -1473,7 +1563,7 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_pull_request\":{\"base_branch\":\"${{ github.ref_name }}\",\"max\":1,\"max_patch_size\":1024},\"missing_data\":{},\"missing_tool\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_pull_request\":{\"base_branch\":\"${{ github.base_ref || github.ref_name }}\",\"max\":1,\"max_patch_size\":1024},\"missing_data\":{},\"missing_tool\":{}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/gh-aw-bug-exterminator.md b/.github/workflows/gh-aw-bug-exterminator.md index 0d2823e0..288a17b8 100644 --- a/.github/workflows/gh-aw-bug-exterminator.md +++ b/.github/workflows/gh-aw-bug-exterminator.md @@ -1,4 +1,5 @@ --- +inlined-imports: true description: "Fix bug-hunter issues and open a focused PR" imports: - gh-aw-fragments/elastic-tools.md @@ -9,12 +10,18 @@ imports: - gh-aw-fragments/workflow-edit-guardrails.md - gh-aw-fragments/messages-footer.md - gh-aw-fragments/safe-output-create-pr.md + - gh-aw-fragments/scheduled-fix.md engine: id: copilot - model: gpt-5.3-codex + model: ${{ inputs.model }} on: workflow_call: inputs: + model: + description: "AI model to use" + type: string + required: false + default: "gpt-5.3-codex" additional-instructions: description: "Repo-specific instructions appended to the agent prompt" type: string @@ -73,65 +80,21 @@ steps: run: eval "$SETUP_COMMANDS" --- -# Bug Exterminator - -Fix a reproducible `bug-hunter` issue by opening a single focused PR. - -## Context - -- **Repository**: ${{ github.repository }} +### Candidate Search -## Constraints - -- **CAN**: Read files, search code, modify files locally, run tests and commands, create a pull request. -- **CANNOT**: Directly push to the repository — use `create_pull_request`. -- **Only one PR per run.** -- Only consider issues labeled `bug-hunter` or with `[bug-hunter]` in the title. -- You must reproduce the issue locally before proposing a fix. -- If no suitable issue is found or reproduction fails, call `noop` with a brief reason. -- **Most runs should end with `noop`.** Only open a PR when the fix is clearly correct, tested, and small enough for quick review. - -## Step 1: Gather candidates - -1. Call `generate_agents_md` to get repository conventions (if it fails, continue). -2. Search for open Bug Hunter issues: +Search for open Bug Hunter issues: ````text github-search_issues: query="repo:{owner}/{repo} is:issue is:open (label:bug-hunter OR in:title \"[bug-hunter]\") sort:updated-asc" ```` -3. For each candidate, read the full issue and comments using `issue_read` (methods `get` and `get_comments`). - -## Step 2: Select a target +### Implementation -Choose one issue with: - -- Clear reproduction steps -- A small, well-scoped fix -- No active discussion pointing to a larger design change - -Skip any issue that cannot be reproduced locally. - -## Step 3: Reproduce and fix +You must reproduce the issue locally before proposing a fix. 1. Reproduce the bug locally with the exact steps from the issue. 2. Make the smallest safe change that fixes the issue. 3. Run the most relevant targeted tests. **Tests must pass.** 4. Commit the changes locally. -## Step 4: Quality Gate — Self-Review - -Before creating the PR, verify: - -- **Reproduction**: You reproduced the bug before fixing it. -- **Fix correctness**: The change directly addresses the issue. -- **Tests pass**: List the tests and results in the PR body. -- **Scope**: The change is minimal and focused. - -If any check fails, call `noop`. - -## Step 5: Create the PR - -Call `create_pull_request` with a concise summary, a link to the issue, and the exact tests run. - ${{ inputs.additional-instructions }} diff --git a/.github/workflows/gh-aw-bug-hunter.lock.yml b/.github/workflows/gh-aw-bug-hunter.lock.yml index 0a4a4274..7cda3724 100644 --- a/.github/workflows/gh-aw-bug-hunter.lock.yml +++ b/.github/workflows/gh-aw-bug-hunter.lock.yml @@ -33,9 +33,11 @@ # - gh-aw-fragments/rigor.md # - gh-aw-fragments/runtime-setup.md # - gh-aw-fragments/safe-output-create-issue.md -# - gh-aw-fragments/scheduled-report.md +# - gh-aw-fragments/scheduled-audit.md # -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"da3abb18e40902637ff4d97029bf023b146300fc5448d33ccf3cc51eb13a978d"} +# inlined-imports: true +# +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"760d2c65f08ce2e248d5f20032748d9db3aab3a37b206d946ab1d8f24e5601f3"} name: "Bug Hunter" "on": @@ -62,6 +64,11 @@ name: "Bug Hunter" description: Footer appended to all agent comments and reviews required: false type: string + model: + default: gpt-5.3-codex + description: AI model to use + required: false + type: string setup-commands: default: "" description: Shell commands to run before the agent starts (dependency install, build, etc.) @@ -91,7 +98,7 @@ jobs: comment_repo: "" steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Validate context variables @@ -168,6 +175,25 @@ jobs: **Critical**: Tool calls write structured data that downstream jobs process. Without tool calls, follow-up actions will be skipped. **Note**: If you made no other safe output tool calls during this workflow execution, call the "noop" tool to provide a status message indicating completion or that no actions were needed. + + --- + + ## Creating an Issue, Reporting Missing Tools or Functionality, Reporting Missing Data + + **IMPORTANT**: To perform the actions listed above, use the **safeoutputs** tools. Do NOT use `gh`, do NOT call the GitHub API directly. You do not have write access to the GitHub repository. + + **Creating an Issue** + + To create an issue, use the create_issue tool from safeoutputs. + + **Reporting Missing Tools or Functionality** + + To report a missing tool or capability, use the missing_tool tool from safeoutputs. + + **Reporting Missing Data** + + To report missing data required to achieve a goal, use the missing_data tool from safeoutputs. + @@ -288,9 +314,7 @@ jobs: - **Mentions**: `@mentions` in the body are neutralized (backticked) by default. GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - # Scheduled Report Agent - - You are a report agent for __GH_AW_GITHUB_REPOSITORY__. You run on a schedule to investigate the repository and file an issue when something needs attention. Your specific assignment is described in the **Report Assignment** section below. + You are an agent for __GH_AW_GITHUB_REPOSITORY__. You run on a schedule to investigate the repository and file an issue when something needs attention. Your specific assignment is described in the **Report Assignment** section below. ## Context @@ -354,7 +378,7 @@ jobs: - Make suggested actions concrete enough to act on without re-investigating - If a finding is ambiguous, it does not pass the quality gate — drop it - ## Report Assignment + **Report Assignment:** GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" @@ -525,7 +549,7 @@ jobs: secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Checkout repository @@ -625,7 +649,7 @@ jobs: const awInfo = { engine_id: "copilot", engine_name: "GitHub Copilot CLI", - model: "gpt-5.3-codex", + model: "${{ inputs.model }}", version: "", agent_version: "0.0.412", workflow_name: "Bug Hunter", @@ -836,6 +860,31 @@ jobs: } } }, + "missing_data": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "context": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "data_type": { + "type": "string", + "sanitize": true, + "maxLength": 128 + }, + "reason": { + "type": "string", + "sanitize": true, + "maxLength": 256 + } + } + }, "missing_tool": { "defaultMax": 20, "fields": { @@ -997,10 +1046,11 @@ jobs: run: | set -o pipefail sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --allow-domains '*.githubusercontent.com,*.jsr.io,*.pythonhosted.org,*.rvm.io,agents-md-generator.fastmcp.app,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.rubygems.org,api.snapcraft.io,archive.ubuntu.com,artifacts.elastic.co,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,bun.sh,bundler.rubygems.org,cache.ruby-lang.org,cdn.jsdelivr.net,cloud.elastic.co,codeload.github.com,conda.anaconda.org,conda.binstar.org,crates.io,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,deb.nodesource.com,deno.land,ela.st,elastic.co,esm.sh,files.pythonhosted.org,gems.rubyforge.org,gems.rubyonrails.org,get.pnpm.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,host.docker.internal,index.crates.io,index.rubygems.org,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,lfs.github.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,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,pip.pypa.io,pkg.go.dev,ppa.launchpad.net,proxy.golang.org,public-code-search.fastmcp.app,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.bower.io,registry.npmjs.com,registry.npmjs.org,registry.yarnpkg.com,repo.anaconda.com,repo.continuum.io,repo.yarnpkg.com,rubygems.org,rubygems.pkg.github.com,s.symcb.com,s.symcd.com,security.ubuntu.com,skimdb.npmjs.com,static.crates.io,storage.googleapis.com,sum.golang.org,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.elastic.co,www.npmjs.com,www.npmjs.org,yarnpkg.com' --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.20.2 --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 --model gpt-5.3-codex --allow-all-tools --allow-all-paths --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log + -- /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 --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} @@ -1166,7 +1216,7 @@ jobs: total_count: ${{ steps.missing_tool.outputs.total_count }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent output artifact @@ -1257,7 +1307,7 @@ jobs: success: ${{ steps.parse_results.outputs.success }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent artifacts @@ -1318,10 +1368,11 @@ jobs: mkdir -p /tmp/gh-aw/ mkdir -p /tmp/gh-aw/agent/ mkdir -p /tmp/gh-aw/sandbox/agent/logs/ - copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --model gpt-5.3-codex --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log + copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_REF_NAME: ${{ github.ref_name }} @@ -1351,7 +1402,7 @@ jobs: activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Check team membership for workflow @@ -1380,7 +1431,7 @@ jobs: timeout-minutes: 15 env: GH_AW_ENGINE_ID: "copilot" - GH_AW_ENGINE_MODEL: "gpt-5.3-codex" + GH_AW_ENGINE_MODEL: "${{ inputs.model }}" GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\"}" GH_AW_WORKFLOW_ID: "gh-aw-bug-hunter" GH_AW_WORKFLOW_NAME: "Bug Hunter" @@ -1391,7 +1442,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@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent output artifact diff --git a/.github/workflows/gh-aw-bug-hunter.md b/.github/workflows/gh-aw-bug-hunter.md index b87413db..d7f967e6 100644 --- a/.github/workflows/gh-aw-bug-hunter.md +++ b/.github/workflows/gh-aw-bug-hunter.md @@ -1,4 +1,5 @@ --- +inlined-imports: true name: "Bug Hunter" description: "Find a reproducible, user-impacting bug and file a report issue" imports: @@ -10,13 +11,18 @@ imports: - gh-aw-fragments/mcp-pagination.md - gh-aw-fragments/messages-footer.md - gh-aw-fragments/safe-output-create-issue.md - - gh-aw-fragments/scheduled-report.md + - gh-aw-fragments/scheduled-audit.md engine: id: copilot - model: gpt-5.3-codex + model: ${{ inputs.model }} on: workflow_call: inputs: + model: + description: "AI model to use" + type: string + required: false + default: "gpt-5.3-codex" additional-instructions: description: "Repo-specific instructions appended to the agent prompt" type: string diff --git a/.github/workflows/gh-aw-semantic-function-clustering.lock.yml b/.github/workflows/gh-aw-code-duplication-detector.lock.yml similarity index 94% rename from .github/workflows/gh-aw-semantic-function-clustering.lock.yml rename to .github/workflows/gh-aw-code-duplication-detector.lock.yml index af24fa89..e09c041e 100644 --- a/.github/workflows/gh-aw-semantic-function-clustering.lock.yml +++ b/.github/workflows/gh-aw-code-duplication-detector.lock.yml @@ -21,7 +21,7 @@ # # For more information: https://github.github.com/gh-aw/introduction/overview/ # -# Analyze source code for semantic function clustering and refactoring opportunities +# Analyze source code for duplication patterns and refactoring opportunities # # Resolved workflow manifest: # Imports: @@ -32,11 +32,13 @@ # - gh-aw-fragments/rigor.md # - gh-aw-fragments/runtime-setup.md # - gh-aw-fragments/safe-output-create-issue.md -# - gh-aw-fragments/scheduled-report.md +# - gh-aw-fragments/scheduled-audit.md # -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"ba4518c74cf7b7fc624b500f2a88170acf0643d39754c3b3d5419854f1028b5f"} +# inlined-imports: true +# +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"f668db4d950c191b06eba7c0a26de623d69b3d9d098a23d257f97fc237126a8d"} -name: "Semantic Function Clustering" +name: "Code Duplication Detector" "on": # bots: # Bots processed as bot check in pre-activation job # - ${{ inputs.allowed-bot-users }} # Bots processed as bot check in pre-activation job @@ -71,6 +73,11 @@ name: "Semantic Function Clustering" description: Footer appended to all agent comments and reviews required: false type: string + model: + default: gpt-5.3-codex + description: AI model to use + required: false + type: string setup-commands: default: "" description: Shell commands to run before the agent starts (dependency install, build, etc.) @@ -84,9 +91,9 @@ permissions: {} concurrency: cancel-in-progress: true - group: semantic-function-clustering + group: code-duplication-detector -run-name: "Semantic Function Clustering" +run-name: "Code Duplication Detector" jobs: activation: @@ -100,7 +107,7 @@ jobs: comment_repo: "" steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Validate context variables @@ -122,7 +129,7 @@ jobs: - name: Check workflow file timestamps uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: - GH_AW_WORKFLOW_FILE: "gh-aw-semantic-function-clustering.lock.yml" + GH_AW_WORKFLOW_FILE: "gh-aw-code-duplication-detector.lock.yml" with: script: | const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); @@ -179,6 +186,25 @@ jobs: **Critical**: Tool calls write structured data that downstream jobs process. Without tool calls, follow-up actions will be skipped. **Note**: If you made no other safe output tool calls during this workflow execution, call the "noop" tool to provide a status message indicating completion or that no actions were needed. + + --- + + ## Creating an Issue, Reporting Missing Tools or Functionality, Reporting Missing Data + + **IMPORTANT**: To perform the actions listed above, use the **safeoutputs** tools. Do NOT use `gh`, do NOT call the GitHub API directly. You do not have write access to the GitHub repository. + + **Creating an Issue** + + To create an issue, use the create_issue tool from safeoutputs. + + **Reporting Missing Tools or Functionality** + + To report a missing tool or capability, use the missing_tool tool from safeoutputs. + + **Reporting Missing Data** + + To report missing data required to achieve a goal, use the missing_data tool from safeoutputs. + @@ -296,9 +322,7 @@ jobs: - **Mentions**: `@mentions` in the body are neutralized (backticked) by default. GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - # Scheduled Report Agent - - You are a report agent for __GH_AW_GITHUB_REPOSITORY__. You run on a schedule to investigate the repository and file an issue when something needs attention. Your specific assignment is described in the **Report Assignment** section below. + You are an agent for __GH_AW_GITHUB_REPOSITORY__. You run on a schedule to investigate the repository and file an issue when something needs attention. Your specific assignment is described in the **Report Assignment** section below. ## Context @@ -362,7 +386,7 @@ jobs: - Make suggested actions concrete enough to act on without re-investigating - If a finding is ambiguous, it does not pass the quality gate — drop it - ## Report Assignment + **Report Assignment:** GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" @@ -427,7 +451,7 @@ jobs: ### Issue Format - **Issue title:** Semantic function clustering findings (date) + **Issue title:** Code duplication findings (date) **Issue body:** @@ -558,7 +582,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: ghawsemanticfunctionclustering + GH_AW_WORKFLOW_ID_SANITIZED: ghawcodeduplicationdetector outputs: checkout_pr_success: ${{ steps.checkout-pr.outputs.checkout_pr_success || 'true' }} has_patch: ${{ steps.collect_output.outputs.has_patch }} @@ -568,7 +592,7 @@ jobs: secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Checkout repository @@ -662,10 +686,10 @@ jobs: const awInfo = { engine_id: "copilot", engine_name: "GitHub Copilot CLI", - model: "gpt-5.3-codex", + model: "${{ inputs.model }}", version: "", agent_version: "0.0.412", - workflow_name: "Semantic Function Clustering", + workflow_name: "Code Duplication Detector", experimental: false, supports_tools_allowlist: true, run_id: context.runId, @@ -873,6 +897,31 @@ jobs: } } }, + "missing_data": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "context": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "data_type": { + "type": "string", + "sanitize": true, + "maxLength": 128 + }, + "reason": { + "type": "string", + "sanitize": true, + "maxLength": 256 + } + } + }, "missing_tool": { "defaultMax": 20, "fields": { @@ -1042,10 +1091,11 @@ jobs: run: | set -o pipefail sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --allow-domains '*.githubusercontent.com,*.jsr.io,*.pythonhosted.org,*.rvm.io,agents-md-generator.fastmcp.app,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.rubygems.org,api.snapcraft.io,archive.ubuntu.com,artifacts.elastic.co,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,bun.sh,bundler.rubygems.org,cache.ruby-lang.org,cdn.jsdelivr.net,cloud.elastic.co,codeload.github.com,conda.anaconda.org,conda.binstar.org,crates.io,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,deb.nodesource.com,deno.land,ela.st,elastic.co,esm.sh,files.pythonhosted.org,gems.rubyforge.org,gems.rubyonrails.org,get.pnpm.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,host.docker.internal,index.crates.io,index.rubygems.org,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,lfs.github.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,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,pip.pypa.io,pkg.go.dev,ppa.launchpad.net,proxy.golang.org,public-code-search.fastmcp.app,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.bower.io,registry.npmjs.com,registry.npmjs.org,registry.yarnpkg.com,repo.anaconda.com,repo.continuum.io,repo.yarnpkg.com,rubygems.org,rubygems.pkg.github.com,s.symcb.com,s.symcd.com,security.ubuntu.com,skimdb.npmjs.com,static.crates.io,storage.googleapis.com,sum.golang.org,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.elastic.co,www.npmjs.com,www.npmjs.org,yarnpkg.com' --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.20.2 --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 --model gpt-5.3-codex --allow-all-tools --allow-all-paths --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log + -- /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 --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} @@ -1211,7 +1261,7 @@ jobs: total_count: ${{ steps.missing_tool.outputs.total_count }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent output artifact @@ -1231,7 +1281,7 @@ jobs: env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} GH_AW_NOOP_MAX: 1 - GH_AW_WORKFLOW_NAME: "Semantic Function Clustering" + GH_AW_WORKFLOW_NAME: "Code Duplication Detector" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | @@ -1244,7 +1294,7 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_WORKFLOW_NAME: "Semantic Function Clustering" + GH_AW_WORKFLOW_NAME: "Code Duplication Detector" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | @@ -1257,10 +1307,10 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_WORKFLOW_NAME: "Semantic Function Clustering" + GH_AW_WORKFLOW_NAME: "Code Duplication Detector" 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: "gh-aw-semantic-function-clustering" + GH_AW_WORKFLOW_ID: "gh-aw-code-duplication-detector" GH_AW_SECRET_VERIFICATION_RESULT: ${{ needs.agent.outputs.secret_verification_result }} GH_AW_CHECKOUT_PR_SUCCESS: ${{ needs.agent.outputs.checkout_pr_success }} GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\"}" @@ -1277,7 +1327,7 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_WORKFLOW_NAME: "Semantic Function Clustering" + GH_AW_WORKFLOW_NAME: "Code Duplication Detector" 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 }} @@ -1302,7 +1352,7 @@ jobs: success: ${{ steps.parse_results.outputs.success }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent artifacts @@ -1325,8 +1375,8 @@ jobs: - name: Setup threat detection uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: - WORKFLOW_NAME: "Semantic Function Clustering" - WORKFLOW_DESCRIPTION: "Analyze source code for semantic function clustering and refactoring opportunities" + WORKFLOW_NAME: "Code Duplication Detector" + WORKFLOW_DESCRIPTION: "Analyze source code for duplication patterns and refactoring opportunities" HAS_PATCH: ${{ needs.agent.outputs.has_patch }} with: script: | @@ -1363,10 +1413,11 @@ jobs: mkdir -p /tmp/gh-aw/ mkdir -p /tmp/gh-aw/agent/ mkdir -p /tmp/gh-aw/sandbox/agent/logs/ - copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --model gpt-5.3-codex --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log + copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_REF_NAME: ${{ github.ref_name }} @@ -1396,7 +1447,7 @@ jobs: activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Check team membership for workflow @@ -1425,10 +1476,10 @@ jobs: timeout-minutes: 15 env: GH_AW_ENGINE_ID: "copilot" - GH_AW_ENGINE_MODEL: "gpt-5.3-codex" + GH_AW_ENGINE_MODEL: "${{ inputs.model }}" GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\"}" - GH_AW_WORKFLOW_ID: "gh-aw-semantic-function-clustering" - GH_AW_WORKFLOW_NAME: "Semantic Function Clustering" + GH_AW_WORKFLOW_ID: "gh-aw-code-duplication-detector" + GH_AW_WORKFLOW_NAME: "Code Duplication Detector" outputs: create_discussion_error_count: ${{ steps.process_safe_outputs.outputs.create_discussion_error_count }} create_discussion_errors: ${{ steps.process_safe_outputs.outputs.create_discussion_errors }} @@ -1436,7 +1487,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@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent output artifact diff --git a/.github/workflows/gh-aw-semantic-function-clustering.md b/.github/workflows/gh-aw-code-duplication-detector.md similarity index 93% rename from .github/workflows/gh-aw-semantic-function-clustering.md rename to .github/workflows/gh-aw-code-duplication-detector.md index 41bfb3e4..ae10d38b 100644 --- a/.github/workflows/gh-aw-semantic-function-clustering.md +++ b/.github/workflows/gh-aw-code-duplication-detector.md @@ -1,6 +1,7 @@ --- -name: "Semantic Function Clustering" -description: "Analyze source code for semantic function clustering and refactoring opportunities" +inlined-imports: true +name: "Code Duplication Detector" +description: "Analyze source code for duplication patterns and refactoring opportunities" imports: - gh-aw-fragments/elastic-tools.md - gh-aw-fragments/runtime-setup.md @@ -9,13 +10,18 @@ imports: - gh-aw-fragments/mcp-pagination.md - gh-aw-fragments/messages-footer.md - gh-aw-fragments/safe-output-create-issue.md - - gh-aw-fragments/scheduled-report.md + - gh-aw-fragments/scheduled-audit.md engine: id: copilot - model: gpt-5.3-codex + model: ${{ inputs.model }} on: workflow_call: inputs: + model: + description: "AI model to use" + type: string + required: false + default: "gpt-5.3-codex" languages: description: "Comma-separated languages to analyze (e.g., go,python,typescript). Ignored if file-globs is set." type: string @@ -53,7 +59,7 @@ on: bots: - "${{ inputs.allowed-bot-users }}" concurrency: - group: semantic-function-clustering + group: code-duplication-detector cancel-in-progress: true permissions: contents: read @@ -151,7 +157,7 @@ Analyze source code to identify semantic function clusters, misplaced functions, ### Issue Format -**Issue title:** Semantic function clustering findings (date) +**Issue title:** Code duplication findings (date) **Issue body:** diff --git a/.github/workflows/gh-aw-code-duplication-fixer.lock.yml b/.github/workflows/gh-aw-code-duplication-fixer.lock.yml new file mode 100644 index 00000000..0d98f15c --- /dev/null +++ b/.github/workflows/gh-aw-code-duplication-fixer.lock.yml @@ -0,0 +1,1591 @@ +# +# ___ _ _ +# / _ \ | | (_) +# | |_| | __ _ ___ _ __ | |_ _ ___ +# | _ |/ _` |/ _ \ '_ \| __| |/ __| +# | | | | (_| | __/ | | | |_| | (__ +# \_| |_/\__, |\___|_| |_|\__|_|\___| +# __/ | +# _ _ |___/ +# | | | | / _| | +# | | | | ___ _ __ _ __| |_| | _____ ____ +# | |/\| |/ _ \ '__| |/ /| _| |/ _ \ \ /\ / / ___| +# \ /\ / (_) | | | | ( | | | | (_) \ V V /\__ \ +# \/ \/ \___/|_| |_|\_\|_| |_|\___/ \_/\_/ |___/ +# +# This file was automatically generated by gh-aw. DO NOT EDIT. +# +# To update this file, edit the corresponding .md file and run: +# gh aw compile +# Not all edits will cause changes to this file. +# +# For more information: https://github.github.com/gh-aw/introduction/overview/ +# +# Fix code-duplication-detector issues by consolidating duplicates and opening a focused PR +# +# Resolved workflow manifest: +# Imports: +# - gh-aw-fragments/elastic-tools.md +# - gh-aw-fragments/formatting.md +# - gh-aw-fragments/mcp-pagination.md +# - gh-aw-fragments/messages-footer.md +# - gh-aw-fragments/rigor.md +# - gh-aw-fragments/runtime-setup.md +# - gh-aw-fragments/safe-output-create-pr.md +# - gh-aw-fragments/scheduled-fix.md +# - gh-aw-fragments/workflow-edit-guardrails.md +# +# inlined-imports: true +# +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"76677a5c276b3ec7f97560d70294dd7af17de8154f29a52198de9d8cede0dbaf"} + +name: "Code Duplication Fixer" +"on": + # bots: # Bots processed as bot check in pre-activation job + # - ${{ inputs.allowed-bot-users }} # Bots processed as bot check in pre-activation job + # roles: # Roles processed as role check in pre-activation job + # - admin # Roles processed as role check in pre-activation job + # - maintainer # Roles processed as role check in pre-activation job + # - write # Roles processed as role check in pre-activation job + workflow_call: + inputs: + additional-instructions: + default: "" + description: Repo-specific instructions appended to the agent prompt + required: false + type: string + allowed-bot-users: + default: github-actions[bot] + description: Allowlisted bot actor usernames (comma-separated) + required: false + type: string + messages-footer: + default: "" + description: Footer appended to all agent comments and reviews + required: false + type: string + model: + default: gpt-5.3-codex + description: AI model to use + required: false + type: string + setup-commands: + default: "" + description: Shell commands to run before the agent starts (dependency install, build, etc.) + required: false + type: string + secrets: + COPILOT_GITHUB_TOKEN: + required: true + +permissions: {} + +concurrency: + cancel-in-progress: true + group: code-duplication-fixer + +run-name: "Code Duplication Fixer" + +jobs: + activation: + needs: pre_activation + if: needs.pre_activation.outputs.activated == 'true' + runs-on: ubuntu-slim + permissions: + contents: read + outputs: + comment_id: "" + comment_repo: "" + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 + with: + destination: /opt/gh-aw/actions + - name: Validate context variables + 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/validate_context_variables.cjs'); + await main(); + - name: Checkout .github and .agents folders + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + sparse-checkout: | + .github + .agents + fetch-depth: 1 + persist-credentials: false + - name: Check workflow file timestamps + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_WORKFLOW_FILE: "gh-aw-code-duplication-fixer.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: Create prompt with built-in context + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} + GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} + GH_AW_GITHUB_ACTOR: ${{ github.actor }} + GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} + GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} + GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} + GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} + GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} + GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} + run: | + bash /opt/gh-aw/actions/create_prompt_first.sh + cat << 'GH_AW_PROMPT_EOF' > "$GH_AW_PROMPT" + + GH_AW_PROMPT_EOF + cat "/opt/gh-aw/prompts/xpia.md" >> "$GH_AW_PROMPT" + cat "/opt/gh-aw/prompts/temp_folder_prompt.md" >> "$GH_AW_PROMPT" + cat "/opt/gh-aw/prompts/markdown.md" >> "$GH_AW_PROMPT" + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + + GitHub API Access Instructions + + The gh CLI is NOT authenticated. Do NOT use gh commands for GitHub operations. + + + To create or modify GitHub resources (issues, discussions, pull requests, etc.), you MUST call the appropriate safe output tool. Simply writing content will NOT work - the workflow requires actual tool calls. + + Temporary IDs: Some safe output tools support a temporary ID field (usually named temporary_id) so you can reference newly-created items elsewhere in the SAME agent output (for example, using #aw_abc1 in a later body). + + **IMPORTANT - temporary_id format rules:** + - If you DON'T need to reference the item later, OMIT the temporary_id field entirely (it will be auto-generated if needed) + - If you DO need cross-references/chaining, you MUST match this EXACT validation regex: /^aw_[A-Za-z0-9]{3,8}$/i + - Format: aw_ prefix followed by 3 to 8 alphanumeric characters (A-Z, a-z, 0-9, case-insensitive) + - Valid alphanumeric characters: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 + - INVALID examples: aw_ab (too short), aw_123456789 (too long), aw_test-id (contains hyphen), aw_id_123 (contains underscore) + - VALID examples: aw_abc, aw_abc1, aw_Test123, aw_A1B2C3D4, aw_12345678 + - To generate valid IDs: use 3-8 random alphanumeric characters or omit the field to let the system auto-generate + + Do NOT invent other aw_* formats — downstream steps will reject them with validation errors matching against /^aw_[A-Za-z0-9]{3,8}$/i. + + Discover available tools from the safeoutputs MCP server. + + **Critical**: Tool calls write structured data that downstream jobs process. Without tool calls, follow-up actions will be skipped. + + **Note**: If you made no other safe output tool calls during this workflow execution, call the "noop" tool to provide a status message indicating completion or that no actions were needed. + + --- + + ## Creating a Pull Request, Reporting Missing Tools or Functionality, Reporting Missing Data + + **IMPORTANT**: To perform the actions listed above, use the **safeoutputs** tools. Do NOT use `gh`, do NOT call the GitHub API directly. You do not have write access to the GitHub repository. + + **Creating a Pull Request** + + To create a pull request: + 1. Make any file changes directly in the working directory. + 2. If you haven't done so already, create a local branch using an appropriate unique name. + 3. Add and commit your changes to the branch. Be careful to add exactly the files you intend, and check there are no extra files left un-added. Verify you haven't deleted or changed any files you didn't intend to. + 4. Do not push your changes. That will be done by the tool. + 5. Create the pull request with the create_pull_request tool from safeoutputs. + + **Reporting Missing Tools or Functionality** + + To report a missing tool or capability, use the missing_tool tool from safeoutputs. + + **Reporting Missing Data** + + To report missing data required to achieve a goal, use the missing_data tool from safeoutputs. + + + + + The following GitHub context information is available for this workflow: + {{#if __GH_AW_GITHUB_ACTOR__ }} + - **actor**: __GH_AW_GITHUB_ACTOR__ + {{/if}} + {{#if __GH_AW_GITHUB_REPOSITORY__ }} + - **repository**: __GH_AW_GITHUB_REPOSITORY__ + {{/if}} + {{#if __GH_AW_GITHUB_WORKSPACE__ }} + - **workspace**: __GH_AW_GITHUB_WORKSPACE__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_ISSUE_NUMBER__ }} + - **issue-number**: #__GH_AW_GITHUB_EVENT_ISSUE_NUMBER__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__ }} + - **discussion-number**: #__GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__ }} + - **pull-request-number**: #__GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_COMMENT_ID__ }} + - **comment-id**: __GH_AW_GITHUB_EVENT_COMMENT_ID__ + {{/if}} + {{#if __GH_AW_GITHUB_RUN_ID__ }} + - **workflow-run-id**: __GH_AW_GITHUB_RUN_ID__ + {{/if}} + + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + ## MCP Servers + + - **`generate_agents_md`** — generates a summary of the repository's structure, conventions, and coding guidelines from AGENTS.md and related files. Call at the start of every workflow to get repo context. + - **`search_code`** — grep-style search across public GitHub repositories. Use for finding usage patterns in upstream libraries, reference implementations, or examples in open-source projects. This searches *public GitHub repos*, not the local codebase — if available you can use `grep` and file reading for local code. + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + ## Formatting Guidelines + + - Lead with the most important information — your first sentence should be the key takeaway + - Be concise and actionable — no filler or praise + - Use `
` and `` tags for long sections to keep responses scannable + - Wrap branch names and @-references in backticks to avoid pinging users + - Include code snippets with file paths and line numbers when referencing the codebase + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + ## Rigor + + **Silence is better than noise. A false positive wastes a human's time and erodes trust in every future report.** + + - If you claim something is missing or broken, show the exact evidence in the code — file path, line number, and what you observed. + - If a conclusion depends on assumptions you haven't confirmed, do not assert it. Verify first; if you cannot verify, do not report. + - "I don't know" is better than a wrong answer. `noop` is better than a speculative finding. + - It's worth the time to verify now versus guessing and forcing someone else to verify later. + - Before filing any issue or opening any PR, re-read your own output as a skeptical reviewer. Ask: "Would a senior engineer on this team find this useful, or would they close it immediately?" If the answer is "close," call `noop` instead. + - Only report findings you would confidently defend in a code review. If you feel the need to hedge with "might," "could," or "possibly," the finding is not ready to file. + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + ## MCP Pagination + + MCP tool responses have a **25,000 token limit**. When responses exceed this limit, the call fails and you must retry with pagination — wasting turns and tokens. Use proactive pagination to stay under the limit. + + ### Recommended `perPage` Values + + - **5-10**: For detailed items (PR diffs, files with patches, issues with comments) + - **20-30**: For medium-detail lists (commits, review comments, issue lists) + - **50-100**: For simple list operations (branches, labels, tags) + + ### Pagination Pattern + + When you need all results from a paginated API: + + 1. Fetch the first page with a conservative `perPage` value + 2. Process the results before fetching the next page + 3. Continue fetching pages until you receive fewer results than `perPage` (indicating the last page) + + ### Error Recovery + + If you see an error like: + - `MCP tool response exceeds maximum allowed tokens (25000)` + - `Response too large for tool [tool_name]` + + Retry the same call with a smaller `perPage` value (halve it). + + ### Tips + + - **Start small**: It's better to make multiple small requests than one that fails + - **Fetch incrementally**: Get an overview first, then details for specific items + - **Use filters**: Combine `perPage` with state, label, or date filters to reduce result size + - **Process as you go**: Don't accumulate all pages before acting — process each batch immediately + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + ## Workflow Editing Guardrails + + - Do not modify files under `.github/workflows/`. + - If asked to change workflow files, place a copy under `github/` (no leading dot) and note that a maintainer must relocate it into `.github/workflows/`. + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + ## Message Footer + + A footer is automatically appended to all comments and reviews. Do not add your own footer or sign-off — the runtime handles this. + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + Before calling `create_pull_request`, call `ready_to_make_pr` and apply its checklist. + + ## create-pull-request Limitations + + - **Patch files**: Max 100 files per PR. If changes span more files, split into multiple focused PRs. + - **Patch size**: Max 1,024 KB by default. Keep changes focused. + - **Title**: Max 128 characters. Sanitized. + - **Body**: No explicit mention/link limits, but bot triggers (`fixes #123`, `closes #456`) are neutralized. + - **Committed changes required**: You must have locally committed changes before creating a PR (unless `allow_empty` is configured). + - **Base branch**: Must be configured in the safe-output config. The PR targets this branch. + - **Max per run**: Typically 1 PR creation per workflow run. + - You may not submit code that modifies files in `.github/workflows/`. Doing so will cause the submission to be rejected. If asked to modify workflow files, propose the change in a copy placed in a `github/` folder (without the leading period) and note in the PR that the file needs to be relocated by someone with workflow write access. + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + You are an agent for __GH_AW_GITHUB_REPOSITORY__. You run on a schedule to pick up an open issue and create a focused pull request that addresses it. Your specific assignment is described in the **Fix Assignment** section below. + + ## Context + + - **Repository**: __GH_AW_GITHUB_REPOSITORY__ + + ## Constraints + + - **CAN**: Read files, search code, modify files locally, run tests and commands, create a pull request. + - **CANNOT**: Directly push to the repository — use `create_pull_request`. + - **Only one PR per run.** + - If no suitable issue is found, call `noop` with a brief reason. + - **Most runs should end with `noop`.** Only open a PR when the fix is clearly correct, tested, and small enough for quick review. + + ## Process + + Follow these steps in order. + + ### Step 1: Gather Candidates + + 1. Call `generate_agents_md` to get the repository's coding guidelines and conventions. If this fails, continue without it. + 2. Follow the candidate gathering instructions in the **Fix Assignment** section. + 3. For each candidate, read the full issue and comments using `issue_read` (methods `get` and `get_comments`). + + ### Step 2: Select a Target + + Choose one issue with: + + - Concrete, actionable instructions (file paths, function names, suggested changes) + - A well-scoped fix that doesn't require design decisions + - No active discussion suggesting the fix should go a different direction + + Skip any issue where the suggested fix is ambiguous, controversial, or too large for a single PR. + + ### Step 3: Implement + + Follow the implementation instructions in the **Fix Assignment** section. The Fix Assignment defines: + - What kind of changes to make + - What tools to use + - Any domain-specific constraints + + ### Step 4: Quality Gate — Self-Review + + Before creating the PR, verify: + + 1. **Fix is correct** — the change directly addresses the issue. + 2. **Tests pass** — you ran the most relevant tests and they pass. + 3. **Scope is minimal** — only changes needed for the fix, no scope creep. + 4. **No regressions** — linters pass, no formatting broken, no new warnings. + + If any check fails, call `noop` with a brief reason. + + ### Step 5: Create the PR + + Call `create_pull_request` with: + - A concise summary of the changes + - A link to the source issue (e.g., "Fixes #123") + - The specific tests that were run and passed + - A note on any items from the issue that were skipped (if any) + + **Fix Assignment:** + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + ### Candidate Search + + Search for open Code Duplication Detector issues: + + ````text + github-search_issues: query="repo:{owner}/{repo} is:issue is:open (label:refactor OR in:title \"[refactor]\") sort:updated-asc" + ```` + + ### Implementation + + Each fix must be a safe, behavior-preserving refactor — no functional changes. + + 1. Read the affected files and understand the duplication or misplacement. + 2. Use Serena tools (`find_symbol`, `find_referencing_symbols`, `search_for_pattern`) to find all callers and references. + 3. Consolidate duplicates into a single shared function, or move the misplaced function to its correct home. + 4. Update all callers to use the consolidated/moved function. + 5. Run the most relevant targeted tests. **Tests must pass.** + 6. Commit the changes locally. + + __GH_AW_EXPR_49B959F1__ + + GH_AW_PROMPT_EOF + - name: Interpolate variables and render templates + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} + GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} + 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/interpolate_prompt.cjs'); + await main(); + - name: Substitute placeholders + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} + GH_AW_GITHUB_ACTOR: ${{ github.actor }} + GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} + GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} + GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} + 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'); + setupGlobals(core, github, context, exec, io); + + const substitutePlaceholders = require('/opt/gh-aw/actions/substitute_placeholders.cjs'); + + // Call the substitution function + return await substitutePlaceholders({ + file: process.env.GH_AW_PROMPT, + substitutions: { + GH_AW_EXPR_49B959F1: process.env.GH_AW_EXPR_49B959F1, + GH_AW_GITHUB_ACTOR: process.env.GH_AW_GITHUB_ACTOR, + GH_AW_GITHUB_EVENT_COMMENT_ID: process.env.GH_AW_GITHUB_EVENT_COMMENT_ID, + GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: process.env.GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER, + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: process.env.GH_AW_GITHUB_EVENT_ISSUE_NUMBER, + 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_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 + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + run: bash /opt/gh-aw/actions/validate_prompt_placeholders.sh + - name: Print prompt + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + run: bash /opt/gh-aw/actions/print_prompt_summary.sh + - name: Upload prompt artifact + if: success() + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: prompt + path: /tmp/gh-aw/aw-prompts/prompt.txt + retention-days: 1 + + agent: + needs: activation + runs-on: ubuntu-latest + permissions: + contents: read + issues: read + pull-requests: read + concurrency: + group: "gh-aw-copilot-${{ github.workflow }}" + env: + DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} + GH_AW_ASSETS_ALLOWED_EXTS: "" + GH_AW_ASSETS_BRANCH: "" + GH_AW_ASSETS_MAX_SIZE_KB: 0 + GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs + 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: ghawcodeduplicationfixer + outputs: + checkout_pr_success: ${{ steps.checkout-pr.outputs.checkout_pr_success || 'true' }} + has_patch: ${{ steps.collect_output.outputs.has_patch }} + model: ${{ steps.generate_aw_info.outputs.model }} + output: ${{ steps.collect_output.outputs.output }} + output_types: ${{ steps.collect_output.outputs.output_types }} + secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 + with: + destination: /opt/gh-aw/actions + - name: Checkout repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + - name: Create gh-aw temp directory + run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh + - if: hashFiles('go.mod') != '' + name: Setup Go + uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5 + with: + cache: true + go-version-file: go.mod + - if: hashFiles('.python-version') != '' + name: Setup Python + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 + with: + python-version-file: .python-version + - if: hashFiles('.node-version') != '' + name: Setup Node.js (.node-version) + uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6 + with: + node-version-file: .node-version + - if: hashFiles('.node-version') == '' && hashFiles('.nvmrc') != '' + name: Setup Node.js (.nvmrc) + uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6 + with: + node-version-file: .nvmrc + - if: hashFiles('.ruby-version') != '' + name: Setup Ruby + uses: ruby/setup-ruby@09a7688d3b55cf0e976497ff046b70949eeaccfd # v1 + with: + bundler-cache: true + ruby-version: .ruby-version + - id: setup-uv + if: hashFiles('pyproject.toml', 'uv.lock') != '' + name: Setup uv + uses: astral-sh/setup-uv@e58605a9b6da7c637471fab8847a5e5a6b8df081 # v5 + - env: + UV_PATH: ${{ steps.setup-uv.outputs.uv-path }} + WORKSPACE: ${{ github.workspace }} + if: hashFiles('pyproject.toml', 'uv.lock') != '' + name: Expose uv in workspace + run: |- + set -euo pipefail + install_dir="$WORKSPACE/.gh-aw-tools/bin" + mkdir -p "$install_dir" + cp "$UV_PATH" "$install_dir/uv" + chmod +x "$install_dir/uv" + echo "$install_dir" >> "$GITHUB_PATH" + shell: bash + - env: + SETUP_COMMANDS: ${{ inputs.setup-commands }} + if: ${{ inputs.setup-commands != '' }} + name: Repo-specific setup + run: eval "$SETUP_COMMANDS" + + - name: Configure Git credentials + env: + REPO_NAME: ${{ github.repository }} + SERVER_URL: ${{ github.server_url }} + run: | + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git config --global user.name "github-actions[bot]" + # Re-authenticate git with GitHub token + SERVER_URL_STRIPPED="${SERVER_URL#https://}" + git remote set-url origin "https://x-access-token:${{ github.token }}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" + echo "Git configured with standard GitHub Actions identity" + - name: Checkout PR branch + id: checkout-pr + if: | + github.event.pull_request + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + with: + github-token: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/checkout_pr_branch.cjs'); + await main(); + - name: Generate agentic run info + id: generate_aw_info + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + with: + script: | + const fs = require('fs'); + + const awInfo = { + engine_id: "copilot", + engine_name: "GitHub Copilot CLI", + model: "${{ inputs.model }}", + version: "", + agent_version: "0.0.412", + workflow_name: "Code Duplication Fixer", + experimental: false, + supports_tools_allowlist: true, + run_id: context.runId, + run_number: context.runNumber, + run_attempt: process.env.GITHUB_RUN_ATTEMPT, + repository: context.repo.owner + '/' + context.repo.repo, + ref: context.ref, + sha: context.sha, + actor: context.actor, + event_name: context.eventName, + staged: false, + allowed_domains: ["agents-md-generator.fastmcp.app","artifacts.elastic.co","cloud.elastic.co","defaults","ela.st","elastic.co","github","go","node","public-code-search.fastmcp.app","python","ruby","www.elastic.co"], + firewall_enabled: true, + awf_version: "v0.20.2", + awmg_version: "v0.1.4", + steps: { + firewall: "squid" + }, + created_at: new Date().toISOString() + }; + + // Write to /tmp/gh-aw directory to avoid inclusion in PR + const tmpPath = '/tmp/gh-aw/aw_info.json'; + fs.writeFileSync(tmpPath, JSON.stringify(awInfo, null, 2)); + console.log('Generated aw_info.json at:', tmpPath); + console.log(JSON.stringify(awInfo, null, 2)); + + // Set model as output for reuse in other steps/jobs + core.setOutput('model', awInfo.model); + - name: Validate COPILOT_GITHUB_TOKEN secret + id: validate-secret + run: /opt/gh-aw/actions/validate_multi_secret.sh COPILOT_GITHUB_TOKEN 'GitHub Copilot CLI' https://github.github.com/gh-aw/reference/engines/#github-copilot-default + env: + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + - name: Install GitHub Copilot CLI + run: /opt/gh-aw/actions/install_copilot_cli.sh 0.0.412 + - name: Install awf binary + run: bash /opt/gh-aw/actions/install_awf_binary.sh v0.20.2 + - name: Determine automatic lockdown mode for GitHub MCP Server + id: determine-automatic-lockdown + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} + GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} + with: + script: | + 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.20.2 ghcr.io/github/gh-aw-firewall/api-proxy:0.20.2 ghcr.io/github/gh-aw-firewall/squid:0.20.2 ghcr.io/github/gh-aw-mcpg:v0.1.4 ghcr.io/github/github-mcp-server:v0.31.0 ghcr.io/github/serena-mcp-server:latest 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' + {"create_pull_request":{"max":1},"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 pull request to propose code changes. Use this after making file edits to submit them for review and merging. The PR will be created from the current branch with your committed changes. For code review comments on an existing PR, use create_pull_request_review_comment instead. CONSTRAINTS: Maximum 1 pull request(s) can be created.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "body": { + "description": "Detailed PR description in Markdown. Include what changes were made, why, testing notes, and any breaking changes. Do NOT repeat the title as a heading.", + "type": "string" + }, + "branch": { + "description": "Source branch name containing the changes. If omitted, uses the current working branch.", + "type": "string" + }, + "draft": { + "description": "Whether to create the PR as a draft. Draft PRs cannot be merged until marked as ready for review. Use mark_pull_request_as_ready_for_review to convert a draft PR. Default: true.", + "type": "boolean" + }, + "labels": { + "description": "Labels to categorize the PR (e.g., 'enhancement', 'bugfix'). Labels must exist in the repository.", + "items": { + "type": "string" + }, + "type": "array" + }, + "title": { + "description": "Concise PR title describing the changes. Follow repository conventions (e.g., conventional commits). The title appears as the main heading.", + "type": "string" + } + }, + "required": [ + "title", + "body" + ], + "type": "object" + }, + "name": "create_pull_request" + }, + { + "description": "Report that a tool or capability needed to complete the task is not available, or share any information you deem important about missing functionality or limitations. Use this when you cannot accomplish what was requested because the required functionality is missing or access is restricted.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "alternatives": { + "description": "Any workarounds, manual steps, or alternative approaches the user could take (max 256 characters).", + "type": "string" + }, + "reason": { + "description": "Explanation of why this tool is needed or what information you want to share about the limitation (max 256 characters).", + "type": "string" + }, + "tool": { + "description": "Optional: Name or description of the missing tool or capability (max 128 characters). Be specific about what functionality is needed.", + "type": "string" + } + }, + "required": [ + "reason" + ], + "type": "object" + }, + "name": "missing_tool" + }, + { + "description": "Log a transparency message when no significant actions are needed. Use this to confirm workflow completion and provide visibility when analysis is complete but no changes or outputs are required (e.g., 'No issues found', 'All checks passed'). This ensures the workflow produces human-visible output even when no other actions are taken.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "message": { + "description": "Status or completion message to log. Should explain what was analyzed and the outcome (e.g., 'Code review complete - no issues found', 'Analysis complete - all tests passing').", + "type": "string" + } + }, + "required": [ + "message" + ], + "type": "object" + }, + "name": "noop" + }, + { + "description": "Report that data or information needed to complete the task is not available. Use this when you cannot accomplish what was requested because required data, context, or information is missing.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "alternatives": { + "description": "Any workarounds, manual steps, or alternative approaches the user could take (max 256 characters).", + "type": "string" + }, + "context": { + "description": "Additional context about the missing data or where it should come from (max 256 characters).", + "type": "string" + }, + "data_type": { + "description": "Type or description of the missing data or information (max 128 characters). Be specific about what data is needed.", + "type": "string" + }, + "reason": { + "description": "Explanation of why this data is needed to complete the task (max 256 characters).", + "type": "string" + } + }, + "required": [], + "type": "object" + }, + "name": "missing_data" + } + ] + GH_AW_SAFE_OUTPUTS_TOOLS_EOF + cat > /opt/gh-aw/safeoutputs/validation.json << 'GH_AW_SAFE_OUTPUTS_VALIDATION_EOF' + { + "create_pull_request": { + "defaultMax": 1, + "fields": { + "body": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "branch": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "draft": { + "type": "boolean" + }, + "labels": { + "type": "array", + "itemType": "string", + "itemSanitize": true, + "itemMaxLength": 128 + }, + "repo": { + "type": "string", + "maxLength": 256 + }, + "title": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 128 + } + } + }, + "missing_data": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "context": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "data_type": { + "type": "string", + "sanitize": true, + "maxLength": 128 + }, + "reason": { + "type": "string", + "sanitize": true, + "maxLength": 256 + } + } + }, + "missing_tool": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 512 + }, + "reason": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "tool": { + "type": "string", + "sanitize": true, + "maxLength": 128 + } + } + }, + "noop": { + "defaultMax": 1, + "fields": { + "message": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + } + } + } + } + GH_AW_SAFE_OUTPUTS_VALIDATION_EOF + - name: Generate Safe Outputs MCP Server Config + id: safe-outputs-config + run: | + # Generate a secure random API key (360 bits of entropy, 40+ chars) + # Mask immediately to prevent timing vulnerabilities + API_KEY=$(openssl rand -base64 45 | tr -d '/+=') + echo "::add-mask::${API_KEY}" + + PORT=3001 + + # Set outputs for next steps + { + echo "safe_outputs_api_key=${API_KEY}" + echo "safe_outputs_port=${PORT}" + } >> "$GITHUB_OUTPUT" + + echo "Safe Outputs MCP server will run on port ${PORT}" + + - name: Start Safe Outputs MCP HTTP Server + id: safe-outputs-start + env: + DEBUG: '*' + GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-config.outputs.safe_outputs_port }} + GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-config.outputs.safe_outputs_api_key }} + GH_AW_SAFE_OUTPUTS_TOOLS_PATH: /opt/gh-aw/safeoutputs/tools.json + GH_AW_SAFE_OUTPUTS_CONFIG_PATH: /opt/gh-aw/safeoutputs/config.json + GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs + run: | + # Environment variables are set above to prevent template injection + export DEBUG + export GH_AW_SAFE_OUTPUTS_PORT + export GH_AW_SAFE_OUTPUTS_API_KEY + export GH_AW_SAFE_OUTPUTS_TOOLS_PATH + export GH_AW_SAFE_OUTPUTS_CONFIG_PATH + export GH_AW_MCP_LOG_DIR + + bash /opt/gh-aw/actions/start_safe_outputs_server.sh + + - name: Setup Safe Inputs Config + run: | + mkdir -p /opt/gh-aw/safe-inputs/logs + cat > /opt/gh-aw/safe-inputs/tools.json << 'GH_AW_SAFE_INPUTS_TOOLS_EOF' + { + "serverName": "safeinputs", + "version": "1.0.0", + "logDir": "/opt/gh-aw/safe-inputs/logs", + "tools": [ + { + "name": "ready-to-make-pr", + "description": "Run the PR readiness checklist before creating or updating a PR", + "inputSchema": { + "properties": {}, + "type": "object" + }, + "handler": "ready-to-make-pr.cjs", + "timeout": 60 + } + ] + } + GH_AW_SAFE_INPUTS_TOOLS_EOF + cat > /opt/gh-aw/safe-inputs/mcp-server.cjs << 'GH_AW_SAFE_INPUTS_SERVER_EOF' + const path = require("path"); + const { startHttpServer } = require("./safe_inputs_mcp_server_http.cjs"); + const configPath = path.join(__dirname, "tools.json"); + const port = parseInt(process.env.GH_AW_SAFE_INPUTS_PORT || "3000", 10); + const apiKey = process.env.GH_AW_SAFE_INPUTS_API_KEY || ""; + startHttpServer(configPath, { + port: port, + stateless: true, + logDir: "/opt/gh-aw/safe-inputs/logs" + }).catch(error => { + console.error("Failed to start safe-inputs HTTP server:", error); + process.exit(1); + }); + GH_AW_SAFE_INPUTS_SERVER_EOF + chmod +x /opt/gh-aw/safe-inputs/mcp-server.cjs + + - name: Setup Safe Inputs Tool Files + run: | + cat > /opt/gh-aw/safe-inputs/ready-to-make-pr.cjs << 'GH_AW_SAFE_INPUTS_JS_READY-TO-MAKE-PR_EOF' + async function execute(inputs) { + const fs = require('fs'); + const find = (...paths) => paths.find(p => fs.existsSync(p)) || null; + const contributing = find('CONTRIBUTING.md', 'CONTRIBUTING.rst', 'docs/CONTRIBUTING.md', 'docs/contributing.md'); + const prTemplate = find('.github/pull_request_template.md', '.github/PULL_REQUEST_TEMPLATE.md', '.github/PULL_REQUEST_TEMPLATE/pull_request_template.md'); + const checklist = []; + if (contributing) checklist.push(`Review the contributing guide (${contributing}) before opening or updating a PR.`); + if (prTemplate) checklist.push(`Follow the PR template (${prTemplate}) for title, description, and validation notes.`); + checklist.push('Confirm the requested task is fully completed and validated before creating or pushing PR changes.'); + return { status: 'ok', checklist, contributing_guide: contributing, pr_template: prTemplate }; + } + module.exports = { execute }; + GH_AW_SAFE_INPUTS_JS_READY-TO-MAKE-PR_EOF + + - name: Generate Safe Inputs MCP Server Config + id: safe-inputs-config + run: | + # Generate a secure random API key (360 bits of entropy, 40+ chars) + # Mask immediately to prevent timing vulnerabilities + API_KEY=$(openssl rand -base64 45 | tr -d '/+=') + echo "::add-mask::${API_KEY}" + + PORT=3000 + + # Set outputs for next steps + { + echo "safe_inputs_api_key=${API_KEY}" + echo "safe_inputs_port=${PORT}" + } >> "$GITHUB_OUTPUT" + + echo "Safe Inputs MCP server will run on port ${PORT}" + + - name: Start Safe Inputs MCP HTTP Server + id: safe-inputs-start + env: + DEBUG: '*' + GH_AW_SAFE_INPUTS_PORT: ${{ steps.safe-inputs-config.outputs.safe_inputs_port }} + GH_AW_SAFE_INPUTS_API_KEY: ${{ steps.safe-inputs-config.outputs.safe_inputs_api_key }} + run: | + # Environment variables are set above to prevent template injection + export DEBUG + export GH_AW_SAFE_INPUTS_PORT + export GH_AW_SAFE_INPUTS_API_KEY + + bash /opt/gh-aw/actions/start_safe_inputs_server.sh + + - name: Start MCP Gateway + id: start-mcp-gateway + env: + GH_AW_SAFE_INPUTS_API_KEY: ${{ steps.safe-inputs-start.outputs.api_key }} + GH_AW_SAFE_INPUTS_PORT: ${{ steps.safe-inputs-start.outputs.port }} + GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} + GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-start.outputs.api_key }} + GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-start.outputs.port }} + GITHUB_MCP_LOCKDOWN: ${{ steps.determine-automatic-lockdown.outputs.lockdown == 'true' && '1' || '0' }} + GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + run: | + set -eo pipefail + mkdir -p /tmp/gh-aw/mcp-config + + # Export gateway environment variables for MCP config and gateway script + export MCP_GATEWAY_PORT="80" + export MCP_GATEWAY_DOMAIN="host.docker.internal" + MCP_GATEWAY_API_KEY=$(openssl rand -base64 45 | tr -d '/+=') + echo "::add-mask::${MCP_GATEWAY_API_KEY}" + export MCP_GATEWAY_API_KEY + export MCP_GATEWAY_PAYLOAD_DIR="/tmp/gh-aw/mcp-payloads" + mkdir -p "${MCP_GATEWAY_PAYLOAD_DIR}" + export DEBUG="*" + + export GH_AW_ENGINE="copilot" + 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 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_LOCKDOWN -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_INPUTS_PORT -e GH_AW_SAFE_INPUTS_API_KEY -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.1.4' + + mkdir -p /home/runner/.copilot + cat << GH_AW_MCP_CONFIG_EOF | bash /opt/gh-aw/actions/start_mcp_gateway.sh + { + "mcpServers": { + "agents-md-generator": { + "type": "http", + "url": "https://agents-md-generator.fastmcp.app/mcp", + "tools": [ + "generate_agents_md" + ] + }, + "github": { + "type": "stdio", + "container": "ghcr.io/github/github-mcp-server:v0.31.0", + "env": { + "GITHUB_LOCKDOWN_MODE": "$GITHUB_MCP_LOCKDOWN", + "GITHUB_PERSONAL_ACCESS_TOKEN": "\${GITHUB_MCP_SERVER_TOKEN}", + "GITHUB_READ_ONLY": "1", + "GITHUB_TOOLSETS": "repos,issues,pull_requests,search" + } + }, + "public-code-search": { + "type": "http", + "url": "https://public-code-search.fastmcp.app/mcp", + "tools": [ + "search_code" + ] + }, + "safeinputs": { + "type": "http", + "url": "http://host.docker.internal:$GH_AW_SAFE_INPUTS_PORT", + "headers": { + "Authorization": "\${GH_AW_SAFE_INPUTS_API_KEY}" + } + }, + "safeoutputs": { + "type": "http", + "url": "http://host.docker.internal:$GH_AW_SAFE_OUTPUTS_PORT", + "headers": { + "Authorization": "\${GH_AW_SAFE_OUTPUTS_API_KEY}" + } + }, + "serena": { + "type": "stdio", + "container": "ghcr.io/github/serena-mcp-server:latest", + "args": ["--network", "host"], + "entrypoint": "serena", + "entrypointArgs": ["start-mcp-server", "--context", "codex", "--project", "\${GITHUB_WORKSPACE}"], + "mounts": ["\${GITHUB_WORKSPACE}:\${GITHUB_WORKSPACE}:rw"] + } + }, + "gateway": { + "port": $MCP_GATEWAY_PORT, + "domain": "${MCP_GATEWAY_DOMAIN}", + "apiKey": "${MCP_GATEWAY_API_KEY}", + "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" + } + } + GH_AW_MCP_CONFIG_EOF + - name: Generate workflow overview + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + with: + script: | + const { generateWorkflowOverview } = require('/opt/gh-aw/actions/generate_workflow_overview.cjs'); + await generateWorkflowOverview(core); + - name: Download prompt artifact + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 + with: + name: prompt + path: /tmp/gh-aw/aw-prompts + - name: Clean git credentials + run: bash /opt/gh-aw/actions/clean_git_credentials.sh + - name: Execute GitHub Copilot CLI + id: agentic_execution + # Copilot CLI tool arguments (sorted): + timeout-minutes: 90 + run: | + set -o pipefail + sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --allow-domains '*.githubusercontent.com,*.jsr.io,*.pythonhosted.org,*.rvm.io,agents-md-generator.fastmcp.app,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.rubygems.org,api.snapcraft.io,archive.ubuntu.com,artifacts.elastic.co,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,bun.sh,bundler.rubygems.org,cache.ruby-lang.org,cdn.jsdelivr.net,cloud.elastic.co,codeload.github.com,conda.anaconda.org,conda.binstar.org,crates.io,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,deb.nodesource.com,deno.land,ela.st,elastic.co,esm.sh,files.pythonhosted.org,gems.rubyforge.org,gems.rubyonrails.org,get.pnpm.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,host.docker.internal,index.crates.io,index.rubygems.org,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,lfs.github.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,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,pip.pypa.io,pkg.go.dev,ppa.launchpad.net,proxy.golang.org,public-code-search.fastmcp.app,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.bower.io,registry.npmjs.com,registry.npmjs.org,registry.yarnpkg.com,repo.anaconda.com,repo.continuum.io,repo.yarnpkg.com,rubygems.org,rubygems.pkg.github.com,s.symcb.com,s.symcd.com,security.ubuntu.com,skimdb.npmjs.com,static.crates.io,storage.googleapis.com,sum.golang.org,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.elastic.co,www.npmjs.com,www.npmjs.org,yarnpkg.com' --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.20.2 --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 --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log + env: + COPILOT_AGENT_RUNNER_TYPE: STANDALONE + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} + GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} + GITHUB_HEAD_REF: ${{ github.head_ref }} + GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + GITHUB_REF_NAME: ${{ github.ref_name }} + GITHUB_STEP_SUMMARY: ${{ env.GITHUB_STEP_SUMMARY }} + GITHUB_WORKSPACE: ${{ github.workspace }} + XDG_CONFIG_HOME: /home/runner + - name: Configure Git credentials + env: + REPO_NAME: ${{ github.repository }} + SERVER_URL: ${{ github.server_url }} + run: | + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git config --global user.name "github-actions[bot]" + # Re-authenticate git with GitHub token + SERVER_URL_STRIPPED="${SERVER_URL#https://}" + git remote set-url origin "https://x-access-token:${{ github.token }}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" + echo "Git configured with standard GitHub Actions identity" + - name: Copy Copilot session state files to logs + if: always() + continue-on-error: true + run: | + # Copy Copilot session state files to logs folder for artifact collection + # This ensures they are in /tmp/gh-aw/ where secret redaction can scan them + SESSION_STATE_DIR="$HOME/.copilot/session-state" + LOGS_DIR="/tmp/gh-aw/sandbox/agent/logs" + + if [ -d "$SESSION_STATE_DIR" ]; then + echo "Copying Copilot session state files from $SESSION_STATE_DIR to $LOGS_DIR" + mkdir -p "$LOGS_DIR" + cp -v "$SESSION_STATE_DIR"/*.jsonl "$LOGS_DIR/" 2>/dev/null || true + echo "Session state files copied successfully" + else + echo "No session-state directory found at $SESSION_STATE_DIR" + fi + - name: Stop MCP Gateway + if: always() + continue-on-error: true + env: + MCP_GATEWAY_PORT: ${{ steps.start-mcp-gateway.outputs.gateway-port }} + MCP_GATEWAY_API_KEY: ${{ steps.start-mcp-gateway.outputs.gateway-api-key }} + GATEWAY_PID: ${{ steps.start-mcp-gateway.outputs.gateway-pid }} + run: | + bash /opt/gh-aw/actions/stop_mcp_gateway.sh "$GATEWAY_PID" + - name: Redact secrets in logs + if: always() + 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/redact_secrets.cjs'); + await main(); + env: + GH_AW_SECRET_NAMES: 'COPILOT_GITHUB_TOKEN,GH_AW_GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,GITHUB_TOKEN' + SECRET_COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + SECRET_GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} + SECRET_GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} + SECRET_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Upload Safe Outputs + if: always() + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: safe-output + path: ${{ env.GH_AW_SAFE_OUTPUTS }} + if-no-files-found: warn + - name: Ingest agent output + id: collect_output + if: always() + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} + GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,*.jsr.io,*.pythonhosted.org,*.rvm.io,agents-md-generator.fastmcp.app,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.rubygems.org,api.snapcraft.io,archive.ubuntu.com,artifacts.elastic.co,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,bun.sh,bundler.rubygems.org,cache.ruby-lang.org,cdn.jsdelivr.net,cloud.elastic.co,codeload.github.com,conda.anaconda.org,conda.binstar.org,crates.io,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,deb.nodesource.com,deno.land,ela.st,elastic.co,esm.sh,files.pythonhosted.org,gems.rubyforge.org,gems.rubyonrails.org,get.pnpm.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,host.docker.internal,index.crates.io,index.rubygems.org,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,lfs.github.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,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,pip.pypa.io,pkg.go.dev,ppa.launchpad.net,proxy.golang.org,public-code-search.fastmcp.app,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.bower.io,registry.npmjs.com,registry.npmjs.org,registry.yarnpkg.com,repo.anaconda.com,repo.continuum.io,repo.yarnpkg.com,rubygems.org,rubygems.pkg.github.com,s.symcb.com,s.symcd.com,security.ubuntu.com,skimdb.npmjs.com,static.crates.io,storage.googleapis.com,sum.golang.org,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.elastic.co,www.npmjs.com,www.npmjs.org,yarnpkg.com" + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_API_URL: ${{ github.api_url }} + 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/collect_ndjson_output.cjs'); + await main(); + - name: Upload sanitized agent output + if: always() && env.GH_AW_AGENT_OUTPUT + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: agent-output + path: ${{ env.GH_AW_AGENT_OUTPUT }} + if-no-files-found: warn + - name: Upload engine output files + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: agent_outputs + path: | + /tmp/gh-aw/sandbox/agent/logs/ + /tmp/gh-aw/redacted-urls.log + if-no-files-found: ignore + - name: Parse agent logs for step summary + if: always() + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: /tmp/gh-aw/sandbox/agent/logs/ + 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/parse_copilot_log.cjs'); + await main(); + - name: Parse Safe Inputs logs for step summary + if: always() + 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/parse_safe_inputs_logs.cjs'); + await main(); + - name: Parse MCP Gateway logs for step summary + if: always() + 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/parse_mcp_gateway_log.cjs'); + await main(); + - name: Print firewall logs + if: always() + continue-on-error: true + env: + AWF_LOGS_DIR: /tmp/gh-aw/sandbox/firewall/logs + run: | + # Fix permissions on firewall logs so they can be uploaded as artifacts + # AWF runs with sudo, creating files owned by root + sudo chmod -R a+r /tmp/gh-aw/sandbox/firewall/logs 2>/dev/null || true + # Only run awf logs summary if awf command exists (it may not be installed if workflow failed before install step) + if command -v awf &> /dev/null; then + awf logs summary | tee -a "$GITHUB_STEP_SUMMARY" + else + echo 'AWF binary not installed, skipping firewall log summary' + fi + - name: Upload agent artifacts + if: always() + continue-on-error: true + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: agent-artifacts + path: | + /tmp/gh-aw/aw-prompts/prompt.txt + /tmp/gh-aw/aw_info.json + /tmp/gh-aw/mcp-logs/ + /tmp/gh-aw/safe-inputs/logs/ + /tmp/gh-aw/sandbox/firewall/logs/ + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/agent/ + /tmp/gh-aw/aw-*.patch + if-no-files-found: ignore + + conclusion: + needs: + - activation + - agent + - detection + - safe_outputs + if: (always()) && (needs.agent.result != 'skipped') + runs-on: ubuntu-slim + permissions: + contents: write + issues: write + pull-requests: write + outputs: + noop_message: ${{ steps.noop.outputs.noop_message }} + tools_reported: ${{ steps.missing_tool.outputs.tools_reported }} + total_count: ${{ steps.missing_tool.outputs.total_count }} + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 + with: + destination: /opt/gh-aw/actions + - name: Download agent output artifact + continue-on-error: true + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 + with: + name: agent-output + path: /tmp/gh-aw/safeoutputs/ + - name: Setup agent output environment variable + run: | + mkdir -p /tmp/gh-aw/safeoutputs/ + find "/tmp/gh-aw/safeoutputs/" -type f -print + echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/safeoutputs/agent_output.json" >> "$GITHUB_ENV" + - name: Process No-Op Messages + id: noop + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_NOOP_MAX: 1 + GH_AW_WORKFLOW_NAME: "Code Duplication Fixer" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/noop.cjs'); + await main(); + - name: Record Missing Tool + id: missing_tool + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_WORKFLOW_NAME: "Code Duplication Fixer" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/missing_tool.cjs'); + await main(); + - name: Handle Agent Failure + id: handle_agent_failure + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_WORKFLOW_NAME: "Code Duplication Fixer" + 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: "gh-aw-code-duplication-fixer" + GH_AW_SECRET_VERIFICATION_RESULT: ${{ needs.agent.outputs.secret_verification_result }} + GH_AW_CHECKOUT_PR_SUCCESS: ${{ needs.agent.outputs.checkout_pr_success }} + GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\"}" + GH_AW_GROUP_REPORTS: "false" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/handle_agent_failure.cjs'); + await main(); + - name: Handle No-Op Message + id: handle_noop_message + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_WORKFLOW_NAME: "Code Duplication Fixer" + 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 }} + GH_AW_NOOP_REPORT_AS_ISSUE: "true" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/handle_noop_message.cjs'); + await main(); + - name: Handle Create Pull Request Error + id: handle_create_pr_error + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_WORKFLOW_NAME: "Code Duplication Fixer" + GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/handle_create_pr_error.cjs'); + await main(); + + detection: + needs: agent + if: needs.agent.outputs.output_types != '' || needs.agent.outputs.has_patch == 'true' + runs-on: ubuntu-latest + permissions: {} + concurrency: + group: "gh-aw-copilot-${{ github.workflow }}" + timeout-minutes: 10 + outputs: + success: ${{ steps.parse_results.outputs.success }} + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 + with: + destination: /opt/gh-aw/actions + - name: Download agent artifacts + continue-on-error: true + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 + with: + name: agent-artifacts + path: /tmp/gh-aw/threat-detection/ + - name: Download agent output artifact + continue-on-error: true + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 + with: + name: agent-output + path: /tmp/gh-aw/threat-detection/ + - name: Print agent output types + env: + AGENT_OUTPUT_TYPES: ${{ needs.agent.outputs.output_types }} + run: | + echo "Agent output-types: $AGENT_OUTPUT_TYPES" + - name: Setup threat detection + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + WORKFLOW_NAME: "Code Duplication Fixer" + WORKFLOW_DESCRIPTION: "Fix code-duplication-detector issues by consolidating duplicates and opening a focused PR" + HAS_PATCH: ${{ needs.agent.outputs.has_patch }} + 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/setup_threat_detection.cjs'); + await main(); + - name: Ensure threat-detection directory and log + run: | + mkdir -p /tmp/gh-aw/threat-detection + touch /tmp/gh-aw/threat-detection/detection.log + - name: Validate COPILOT_GITHUB_TOKEN secret + id: validate-secret + run: /opt/gh-aw/actions/validate_multi_secret.sh COPILOT_GITHUB_TOKEN 'GitHub Copilot CLI' https://github.github.com/gh-aw/reference/engines/#github-copilot-default + env: + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + - name: Install GitHub Copilot CLI + run: /opt/gh-aw/actions/install_copilot_cli.sh 0.0.412 + - name: Execute GitHub Copilot CLI + id: agentic_execution + # Copilot CLI tool arguments (sorted): + # --allow-tool shell(cat) + # --allow-tool shell(grep) + # --allow-tool shell(head) + # --allow-tool shell(jq) + # --allow-tool shell(ls) + # --allow-tool shell(tail) + # --allow-tool shell(wc) + timeout-minutes: 20 + run: | + set -o pipefail + COPILOT_CLI_INSTRUCTION="$(cat /tmp/gh-aw/aw-prompts/prompt.txt)" + mkdir -p /tmp/ + mkdir -p /tmp/gh-aw/ + mkdir -p /tmp/gh-aw/agent/ + mkdir -p /tmp/gh-aw/sandbox/agent/logs/ + copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log + env: + COPILOT_AGENT_RUNNER_TYPE: STANDALONE + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GITHUB_HEAD_REF: ${{ github.head_ref }} + GITHUB_REF_NAME: ${{ github.ref_name }} + GITHUB_STEP_SUMMARY: ${{ env.GITHUB_STEP_SUMMARY }} + GITHUB_WORKSPACE: ${{ github.workspace }} + XDG_CONFIG_HOME: /home/runner + - name: Parse threat detection results + id: parse_results + 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/parse_threat_detection_results.cjs'); + await main(); + - name: Upload threat detection log + if: always() + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: threat-detection.log + path: /tmp/gh-aw/threat-detection/detection.log + if-no-files-found: ignore + + pre_activation: + runs-on: ubuntu-slim + outputs: + activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 + with: + destination: /opt/gh-aw/actions + - name: Check team membership for workflow + id: check_membership + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_REQUIRED_ROLES: admin,maintainer,write + GH_AW_ALLOWED_BOTS: ${{ inputs.allowed-bot-users }} + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + 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_membership.cjs'); + await main(); + + safe_outputs: + needs: + - activation + - agent + - detection + if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (needs.detection.outputs.success == 'true') + runs-on: ubuntu-slim + permissions: + contents: write + issues: write + pull-requests: write + timeout-minutes: 15 + env: + GH_AW_ENGINE_ID: "copilot" + GH_AW_ENGINE_MODEL: "${{ inputs.model }}" + GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\"}" + GH_AW_WORKFLOW_ID: "gh-aw-code-duplication-fixer" + GH_AW_WORKFLOW_NAME: "Code Duplication Fixer" + outputs: + create_discussion_error_count: ${{ steps.process_safe_outputs.outputs.create_discussion_error_count }} + create_discussion_errors: ${{ steps.process_safe_outputs.outputs.create_discussion_errors }} + process_safe_outputs_processed_count: ${{ steps.process_safe_outputs.outputs.processed_count }} + process_safe_outputs_temporary_id_map: ${{ steps.process_safe_outputs.outputs.temporary_id_map }} + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 + with: + destination: /opt/gh-aw/actions + - name: Download agent output artifact + continue-on-error: true + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 + with: + name: agent-output + path: /tmp/gh-aw/safeoutputs/ + - name: Setup agent output environment variable + run: | + mkdir -p /tmp/gh-aw/safeoutputs/ + find "/tmp/gh-aw/safeoutputs/" -type f -print + echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/safeoutputs/agent_output.json" >> "$GITHUB_ENV" + - name: Download patch artifact + continue-on-error: true + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 + with: + name: agent-artifacts + path: /tmp/gh-aw/ + - name: Checkout repository + if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + ref: ${{ github.base_ref || github.ref_name }} + token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + persist-credentials: false + fetch-depth: 1 + - name: Configure Git credentials + if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) + env: + REPO_NAME: ${{ github.repository }} + SERVER_URL: ${{ github.server_url }} + GIT_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + run: | + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git config --global user.name "github-actions[bot]" + # Re-authenticate git with GitHub token + SERVER_URL_STRIPPED="${SERVER_URL#https://}" + git remote set-url origin "https://x-access-token:${GIT_TOKEN}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" + echo "Git configured with standard GitHub Actions identity" + - name: Process Safe Outputs + id: process_safe_outputs + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_pull_request\":{\"base_branch\":\"${{ github.base_ref || github.ref_name }}\",\"max\":1,\"max_patch_size\":1024},\"missing_data\":{},\"missing_tool\":{}}" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/safe_output_handler_manager.cjs'); + await main(); + - name: Upload safe output items manifest + if: always() + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: safe-output-items + path: /tmp/safe-output-items.jsonl + if-no-files-found: warn + diff --git a/.github/workflows/gh-aw-code-duplication-fixer.md b/.github/workflows/gh-aw-code-duplication-fixer.md new file mode 100644 index 00000000..d7856aa4 --- /dev/null +++ b/.github/workflows/gh-aw-code-duplication-fixer.md @@ -0,0 +1,104 @@ +--- +inlined-imports: true +name: "Code Duplication Fixer" +description: "Fix code-duplication-detector issues by consolidating duplicates and opening a focused PR" +imports: + - gh-aw-fragments/elastic-tools.md + - gh-aw-fragments/runtime-setup.md + - gh-aw-fragments/formatting.md + - gh-aw-fragments/rigor.md + - gh-aw-fragments/mcp-pagination.md + - gh-aw-fragments/workflow-edit-guardrails.md + - gh-aw-fragments/messages-footer.md + - gh-aw-fragments/safe-output-create-pr.md + - gh-aw-fragments/scheduled-fix.md +engine: + id: copilot + model: ${{ inputs.model }} +on: + workflow_call: + inputs: + model: + description: "AI model to use" + type: string + required: false + default: "gpt-5.3-codex" + additional-instructions: + description: "Repo-specific instructions appended to the agent prompt" + type: string + required: false + default: "" + setup-commands: + description: "Shell commands to run before the agent starts (dependency install, build, etc.)" + type: string + required: false + default: "" + allowed-bot-users: + description: "Allowlisted bot actor usernames (comma-separated)" + type: string + required: false + default: "github-actions[bot]" + messages-footer: + description: "Footer appended to all agent comments and reviews" + type: string + required: false + default: "" + secrets: + COPILOT_GITHUB_TOKEN: + required: true + roles: [admin, maintainer, write] + bots: + - "${{ inputs.allowed-bot-users }}" +concurrency: + group: code-duplication-fixer + cancel-in-progress: true +permissions: + contents: read + issues: read + pull-requests: read +tools: + github: + toolsets: [repos, issues, pull_requests, search] + bash: true + web-fetch: + serena: ["go", "python", "typescript", "java", "csharp", "rust"] +network: + allowed: + - defaults + - github + - go + - node + - python + - ruby +strict: false +safe-outputs: + noop: +timeout-minutes: 90 +steps: + - name: Repo-specific setup + if: ${{ inputs.setup-commands != '' }} + env: + SETUP_COMMANDS: ${{ inputs.setup-commands }} + run: eval "$SETUP_COMMANDS" +--- + +### Candidate Search + +Search for open Code Duplication Detector issues: + +````text +github-search_issues: query="repo:{owner}/{repo} is:issue is:open (label:refactor OR in:title \"[refactor]\") sort:updated-asc" +```` + +### Implementation + +Each fix must be a safe, behavior-preserving refactor — no functional changes. + +1. Read the affected files and understand the duplication or misplacement. +2. Use Serena tools (`find_symbol`, `find_referencing_symbols`, `search_for_pattern`) to find all callers and references. +3. Consolidate duplicates into a single shared function, or move the misplaced function to its correct home. +4. Update all callers to use the consolidated/moved function. +5. Run the most relevant targeted tests. **Tests must pass.** +6. Commit the changes locally. + +${{ inputs.additional-instructions }} diff --git a/.github/workflows/gh-aw-code-simplifier.lock.yml b/.github/workflows/gh-aw-code-simplifier.lock.yml index aa34d97b..865480cc 100644 --- a/.github/workflows/gh-aw-code-simplifier.lock.yml +++ b/.github/workflows/gh-aw-code-simplifier.lock.yml @@ -34,7 +34,9 @@ # - gh-aw-fragments/safe-output-create-pr.md # - gh-aw-fragments/workflow-edit-guardrails.md # -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"67eef61fcea25c932fbf5385db5e43281d552cf874bab9692d22c82ac75fda64"} +# inlined-imports: true +# +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"b356afe8c7cfbac9e0142d64737f066f1e5d30554a3a17d37bb2fac72797cbb1"} name: "Code Simplifier" "on": @@ -61,6 +63,11 @@ name: "Code Simplifier" description: Footer appended to all agent comments and reviews required: false type: string + model: + default: gpt-5.3-codex + description: AI model to use + required: false + type: string setup-commands: default: "" description: Shell commands to run before the agent starts (dependency install, build, etc.) @@ -90,7 +97,7 @@ jobs: comment_repo: "" steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Validate context variables @@ -167,6 +174,30 @@ jobs: **Critical**: Tool calls write structured data that downstream jobs process. Without tool calls, follow-up actions will be skipped. **Note**: If you made no other safe output tool calls during this workflow execution, call the "noop" tool to provide a status message indicating completion or that no actions were needed. + + --- + + ## Creating a Pull Request, Reporting Missing Tools or Functionality, Reporting Missing Data + + **IMPORTANT**: To perform the actions listed above, use the **safeoutputs** tools. Do NOT use `gh`, do NOT call the GitHub API directly. You do not have write access to the GitHub repository. + + **Creating a Pull Request** + + To create a pull request: + 1. Make any file changes directly in the working directory. + 2. If you haven't done so already, create a local branch using an appropriate unique name. + 3. Add and commit your changes to the branch. Be careful to add exactly the files you intend, and check there are no extra files left un-added. Verify you haven't deleted or changed any files you didn't intend to. + 4. Do not push your changes. That will be done by the tool. + 5. Create the pull request with the create_pull_request tool from safeoutputs. + + **Reporting Missing Tools or Functionality** + + To report a missing tool or capability, use the missing_tool tool from safeoutputs. + + **Reporting Missing Data** + + To report missing data required to achieve a goal, use the missing_data tool from safeoutputs. + @@ -459,7 +490,7 @@ jobs: secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Checkout repository @@ -553,7 +584,7 @@ jobs: const awInfo = { engine_id: "copilot", engine_name: "GitHub Copilot CLI", - model: "gpt-5.3-codex", + model: "${{ inputs.model }}", version: "", agent_version: "0.0.412", workflow_name: "Code Simplifier", @@ -613,7 +644,7 @@ jobs: 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' - {"create_pull_request":{},"missing_data":{},"missing_tool":{},"noop":{"max":1}} + {"create_pull_request":{"max":1},"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' [ @@ -630,6 +661,10 @@ jobs: "description": "Source branch name containing the changes. If omitted, uses the current working branch.", "type": "string" }, + "draft": { + "description": "Whether to create the PR as a draft. Draft PRs cannot be merged until marked as ready for review. Use mark_pull_request_as_ready_for_review to convert a draft PR. Default: true.", + "type": "boolean" + }, "labels": { "description": "Labels to categorize the PR (e.g., 'enhancement', 'bugfix'). Labels must exist in the repository.", "items": { @@ -738,12 +773,19 @@ jobs: "sanitize": true, "maxLength": 256 }, + "draft": { + "type": "boolean" + }, "labels": { "type": "array", "itemType": "string", "itemSanitize": true, "itemMaxLength": 128 }, + "repo": { + "type": "string", + "maxLength": 256 + }, "title": { "required": true, "type": "string", @@ -752,6 +794,31 @@ jobs: } } }, + "missing_data": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "context": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "data_type": { + "type": "string", + "sanitize": true, + "maxLength": 128 + }, + "reason": { + "type": "string", + "sanitize": true, + "maxLength": 256 + } + } + }, "missing_tool": { "defaultMax": 20, "fields": { @@ -1010,10 +1077,11 @@ jobs: run: | set -o pipefail sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --allow-domains '*.githubusercontent.com,*.jsr.io,*.pythonhosted.org,*.rvm.io,agents-md-generator.fastmcp.app,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.rubygems.org,api.snapcraft.io,archive.ubuntu.com,artifacts.elastic.co,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,bun.sh,bundler.rubygems.org,cache.ruby-lang.org,cdn.jsdelivr.net,cloud.elastic.co,codeload.github.com,conda.anaconda.org,conda.binstar.org,crates.io,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,deb.nodesource.com,deno.land,ela.st,elastic.co,esm.sh,files.pythonhosted.org,gems.rubyforge.org,gems.rubyonrails.org,get.pnpm.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,host.docker.internal,index.crates.io,index.rubygems.org,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,lfs.github.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,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,pip.pypa.io,pkg.go.dev,ppa.launchpad.net,proxy.golang.org,public-code-search.fastmcp.app,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.bower.io,registry.npmjs.com,registry.npmjs.org,registry.yarnpkg.com,repo.anaconda.com,repo.continuum.io,repo.yarnpkg.com,rubygems.org,rubygems.pkg.github.com,s.symcb.com,s.symcd.com,security.ubuntu.com,skimdb.npmjs.com,static.crates.io,storage.googleapis.com,sum.golang.org,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.elastic.co,www.npmjs.com,www.npmjs.org,yarnpkg.com' --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.20.2 --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 --model gpt-5.3-codex --allow-all-tools --allow-all-paths --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log + -- /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 --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} @@ -1170,7 +1238,7 @@ jobs: /tmp/gh-aw/sandbox/firewall/logs/ /tmp/gh-aw/agent-stdio.log /tmp/gh-aw/agent/ - /tmp/gh-aw/aw.patch + /tmp/gh-aw/aw-*.patch if-no-files-found: ignore conclusion: @@ -1191,7 +1259,7 @@ jobs: total_count: ${{ steps.missing_tool.outputs.total_count }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent output artifact @@ -1296,7 +1364,7 @@ jobs: success: ${{ steps.parse_results.outputs.success }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent artifacts @@ -1357,10 +1425,11 @@ jobs: mkdir -p /tmp/gh-aw/ mkdir -p /tmp/gh-aw/agent/ mkdir -p /tmp/gh-aw/sandbox/agent/logs/ - copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --model gpt-5.3-codex --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log + copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_REF_NAME: ${{ github.ref_name }} @@ -1390,7 +1459,7 @@ jobs: activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Check team membership for workflow @@ -1421,7 +1490,7 @@ jobs: timeout-minutes: 15 env: GH_AW_ENGINE_ID: "copilot" - GH_AW_ENGINE_MODEL: "gpt-5.3-codex" + GH_AW_ENGINE_MODEL: "${{ inputs.model }}" GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\"}" GH_AW_WORKFLOW_ID: "gh-aw-code-simplifier" GH_AW_WORKFLOW_NAME: "Code Simplifier" @@ -1432,7 +1501,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@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent output artifact @@ -1456,7 +1525,7 @@ jobs: if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: - ref: ${{ github.ref_name }} + ref: ${{ github.base_ref || github.ref_name }} token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} persist-credentials: false fetch-depth: 1 @@ -1478,7 +1547,7 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_pull_request\":{\"base_branch\":\"${{ github.ref_name }}\",\"max\":1,\"max_patch_size\":1024},\"missing_data\":{},\"missing_tool\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_pull_request\":{\"base_branch\":\"${{ github.base_ref || github.ref_name }}\",\"max\":1,\"max_patch_size\":1024},\"missing_data\":{},\"missing_tool\":{}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/gh-aw-code-simplifier.md b/.github/workflows/gh-aw-code-simplifier.md index 84d8654e..54487bff 100644 --- a/.github/workflows/gh-aw-code-simplifier.md +++ b/.github/workflows/gh-aw-code-simplifier.md @@ -1,4 +1,5 @@ --- +inlined-imports: true description: "Simplify overcomplicated code with high-confidence refactors" imports: - gh-aw-fragments/elastic-tools.md @@ -11,10 +12,15 @@ imports: - gh-aw-fragments/safe-output-create-pr.md engine: id: copilot - model: gpt-5.3-codex + model: ${{ inputs.model }} on: workflow_call: inputs: + model: + description: "AI model to use" + type: string + required: false + default: "gpt-5.3-codex" additional-instructions: description: "Repo-specific instructions appended to the agent prompt" type: string diff --git a/.github/workflows/gh-aw-docs-drift.lock.yml b/.github/workflows/gh-aw-docs-drift.lock.yml deleted file mode 100644 index 5424b0a9..00000000 --- a/.github/workflows/gh-aw-docs-drift.lock.yml +++ /dev/null @@ -1,1436 +0,0 @@ -# -# ___ _ _ -# / _ \ | | (_) -# | |_| | __ _ ___ _ __ | |_ _ ___ -# | _ |/ _` |/ _ \ '_ \| __| |/ __| -# | | | | (_| | __/ | | | |_| | (__ -# \_| |_/\__, |\___|_| |_|\__|_|\___| -# __/ | -# _ _ |___/ -# | | | | / _| | -# | | | | ___ _ __ _ __| |_| | _____ ____ -# | |/\| |/ _ \ '__| |/ /| _| |/ _ \ \ /\ / / ___| -# \ /\ / (_) | | | | ( | | | | (_) \ V V /\__ \ -# \/ \/ \___/|_| |_|\_\|_| |_|\___/ \_/\_/ |___/ -# -# This file was automatically generated by gh-aw. DO NOT EDIT. -# -# To update this file, edit the corresponding .md file and run: -# gh aw compile -# Not all edits will cause changes to this file. -# -# For more information: https://github.github.com/gh-aw/introduction/overview/ -# -# Detect code changes that require documentation updates and file issues -# -# Resolved workflow manifest: -# Imports: -# - gh-aw-fragments/elastic-tools.md -# - gh-aw-fragments/ensure-full-history.md -# - gh-aw-fragments/formatting.md -# - gh-aw-fragments/mcp-pagination.md -# - gh-aw-fragments/messages-footer.md -# - gh-aw-fragments/rigor.md -# - gh-aw-fragments/runtime-setup.md -# - gh-aw-fragments/safe-output-create-issue.md -# - gh-aw-fragments/scheduled-report.md -# -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"ec91de2a401bd261317a7e46a1da0840d9af34df49c1df9b47caad45cecafe0d"} - -name: "Docs Drift" -"on": - # bots: # Bots processed as bot check in pre-activation job - # - ${{ inputs.allowed-bot-users }} # Bots processed as bot check in pre-activation job - # roles: # Roles processed as role check in pre-activation job - # - admin # Roles processed as role check in pre-activation job - # - maintainer # Roles processed as role check in pre-activation job - # - write # Roles processed as role check in pre-activation job - workflow_call: - inputs: - additional-instructions: - default: "" - description: Repo-specific instructions appended to the agent prompt - required: false - type: string - allowed-bot-users: - default: github-actions[bot] - description: Allowlisted bot actor usernames (comma-separated) - required: false - type: string - lookback-window: - default: 7 days ago - description: Git lookback window for detecting recent commits (e.g. '7 days ago', '14 days ago') - required: false - type: string - messages-footer: - default: "" - description: Footer appended to all agent comments and reviews - required: false - type: string - setup-commands: - default: "" - description: Shell commands to run before the agent starts (dependency install, build, etc.) - required: false - type: string - secrets: - COPILOT_GITHUB_TOKEN: - required: true - -permissions: {} - -concurrency: - cancel-in-progress: true - group: docs-drift - -run-name: "Docs Drift" - -jobs: - activation: - needs: pre_activation - if: needs.pre_activation.outputs.activated == 'true' - runs-on: ubuntu-slim - permissions: - contents: read - outputs: - comment_id: "" - comment_repo: "" - steps: - - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 - with: - destination: /opt/gh-aw/actions - - name: Validate context variables - 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/validate_context_variables.cjs'); - await main(); - - name: Checkout .github and .agents folders - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - sparse-checkout: | - .github - .agents - fetch-depth: 1 - persist-credentials: false - - name: Check workflow file timestamps - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_WORKFLOW_FILE: "gh-aw-docs-drift.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: Create prompt with built-in context - env: - GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} - GH_AW_EXPR_C9922AB3: ${{ inputs.lookback-window }} - GH_AW_GITHUB_ACTOR: ${{ github.actor }} - GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} - GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} - GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} - GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} - GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} - GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} - GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} - run: | - bash /opt/gh-aw/actions/create_prompt_first.sh - cat << 'GH_AW_PROMPT_EOF' > "$GH_AW_PROMPT" - - GH_AW_PROMPT_EOF - cat "/opt/gh-aw/prompts/xpia.md" >> "$GH_AW_PROMPT" - cat "/opt/gh-aw/prompts/temp_folder_prompt.md" >> "$GH_AW_PROMPT" - cat "/opt/gh-aw/prompts/markdown.md" >> "$GH_AW_PROMPT" - cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - - GitHub API Access Instructions - - The gh CLI is NOT authenticated. Do NOT use gh commands for GitHub operations. - - - To create or modify GitHub resources (issues, discussions, pull requests, etc.), you MUST call the appropriate safe output tool. Simply writing content will NOT work - the workflow requires actual tool calls. - - Temporary IDs: Some safe output tools support a temporary ID field (usually named temporary_id) so you can reference newly-created items elsewhere in the SAME agent output (for example, using #aw_abc1 in a later body). - - **IMPORTANT - temporary_id format rules:** - - If you DON'T need to reference the item later, OMIT the temporary_id field entirely (it will be auto-generated if needed) - - If you DO need cross-references/chaining, you MUST match this EXACT validation regex: /^aw_[A-Za-z0-9]{3,8}$/i - - Format: aw_ prefix followed by 3 to 8 alphanumeric characters (A-Z, a-z, 0-9, case-insensitive) - - Valid alphanumeric characters: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 - - INVALID examples: aw_ab (too short), aw_123456789 (too long), aw_test-id (contains hyphen), aw_id_123 (contains underscore) - - VALID examples: aw_abc, aw_abc1, aw_Test123, aw_A1B2C3D4, aw_12345678 - - To generate valid IDs: use 3-8 random alphanumeric characters or omit the field to let the system auto-generate - - Do NOT invent other aw_* formats — downstream steps will reject them with validation errors matching against /^aw_[A-Za-z0-9]{3,8}$/i. - - Discover available tools from the safeoutputs MCP server. - - **Critical**: Tool calls write structured data that downstream jobs process. Without tool calls, follow-up actions will be skipped. - - **Note**: If you made no other safe output tool calls during this workflow execution, call the "noop" tool to provide a status message indicating completion or that no actions were needed. - - - - The following GitHub context information is available for this workflow: - {{#if __GH_AW_GITHUB_ACTOR__ }} - - **actor**: __GH_AW_GITHUB_ACTOR__ - {{/if}} - {{#if __GH_AW_GITHUB_REPOSITORY__ }} - - **repository**: __GH_AW_GITHUB_REPOSITORY__ - {{/if}} - {{#if __GH_AW_GITHUB_WORKSPACE__ }} - - **workspace**: __GH_AW_GITHUB_WORKSPACE__ - {{/if}} - {{#if __GH_AW_GITHUB_EVENT_ISSUE_NUMBER__ }} - - **issue-number**: #__GH_AW_GITHUB_EVENT_ISSUE_NUMBER__ - {{/if}} - {{#if __GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__ }} - - **discussion-number**: #__GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__ - {{/if}} - {{#if __GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__ }} - - **pull-request-number**: #__GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__ - {{/if}} - {{#if __GH_AW_GITHUB_EVENT_COMMENT_ID__ }} - - **comment-id**: __GH_AW_GITHUB_EVENT_COMMENT_ID__ - {{/if}} - {{#if __GH_AW_GITHUB_RUN_ID__ }} - - **workflow-run-id**: __GH_AW_GITHUB_RUN_ID__ - {{/if}} - - - GH_AW_PROMPT_EOF - cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - - GH_AW_PROMPT_EOF - cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - ## MCP Servers - - - **`generate_agents_md`** — generates a summary of the repository's structure, conventions, and coding guidelines from AGENTS.md and related files. Call at the start of every workflow to get repo context. - - **`search_code`** — grep-style search across public GitHub repositories. Use for finding usage patterns in upstream libraries, reference implementations, or examples in open-source projects. This searches *public GitHub repos*, not the local codebase — if available you can use `grep` and file reading for local code. - GH_AW_PROMPT_EOF - cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - - GH_AW_PROMPT_EOF - cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - - GH_AW_PROMPT_EOF - cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - ## Formatting Guidelines - - - Lead with the most important information — your first sentence should be the key takeaway - - Be concise and actionable — no filler or praise - - Use `
` and `` tags for long sections to keep responses scannable - - Wrap branch names and @-references in backticks to avoid pinging users - - Include code snippets with file paths and line numbers when referencing the codebase - - GH_AW_PROMPT_EOF - cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - ## Rigor - - **Silence is better than noise. A false positive wastes a human's time and erodes trust in every future report.** - - - If you claim something is missing or broken, show the exact evidence in the code — file path, line number, and what you observed. - - If a conclusion depends on assumptions you haven't confirmed, do not assert it. Verify first; if you cannot verify, do not report. - - "I don't know" is better than a wrong answer. `noop` is better than a speculative finding. - - It's worth the time to verify now versus guessing and forcing someone else to verify later. - - Before filing any issue or opening any PR, re-read your own output as a skeptical reviewer. Ask: "Would a senior engineer on this team find this useful, or would they close it immediately?" If the answer is "close," call `noop` instead. - - Only report findings you would confidently defend in a code review. If you feel the need to hedge with "might," "could," or "possibly," the finding is not ready to file. - - GH_AW_PROMPT_EOF - cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - ## MCP Pagination - - MCP tool responses have a **25,000 token limit**. When responses exceed this limit, the call fails and you must retry with pagination — wasting turns and tokens. Use proactive pagination to stay under the limit. - - ### Recommended `perPage` Values - - - **5-10**: For detailed items (PR diffs, files with patches, issues with comments) - - **20-30**: For medium-detail lists (commits, review comments, issue lists) - - **50-100**: For simple list operations (branches, labels, tags) - - ### Pagination Pattern - - When you need all results from a paginated API: - - 1. Fetch the first page with a conservative `perPage` value - 2. Process the results before fetching the next page - 3. Continue fetching pages until you receive fewer results than `perPage` (indicating the last page) - - ### Error Recovery - - If you see an error like: - - `MCP tool response exceeds maximum allowed tokens (25000)` - - `Response too large for tool [tool_name]` - - Retry the same call with a smaller `perPage` value (halve it). - - ### Tips - - - **Start small**: It's better to make multiple small requests than one that fails - - **Fetch incrementally**: Get an overview first, then details for specific items - - **Use filters**: Combine `perPage` with state, label, or date filters to reduce result size - - **Process as you go**: Don't accumulate all pages before acting — process each batch immediately - - GH_AW_PROMPT_EOF - cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - ## Message Footer - - A footer is automatically appended to all comments and reviews. Do not add your own footer or sign-off — the runtime handles this. - GH_AW_PROMPT_EOF - cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - ## create-issue Limitations - - - **Title**: Max 128 characters. Sanitized (special characters escaped). - - **Labels**: Max 10 labels per issue. Each label max 64 characters. Labels containing only `-` are rejected. - - **Assignees**: Max 5 assignees per issue. - - **Body**: No strict character limit beyond GitHub's API limit (~65,536 characters), but fields over 16,000 tokens are written to a file reference instead of inlined. - - **Bot triggers**: References like `fixes #123` or `closes #456` in the body are neutralized to prevent unintended issue closures. - - **Mentions**: `@mentions` in the body are neutralized (backticked) by default. - GH_AW_PROMPT_EOF - cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - # Scheduled Report Agent - - You are a report agent for __GH_AW_GITHUB_REPOSITORY__. You run on a schedule to investigate the repository and file an issue when something needs attention. Your specific assignment is described in the **Report Assignment** section below. - - ## Context - - - **Repository**: __GH_AW_GITHUB_REPOSITORY__ - - ## Constraints - - This workflow is for detection and reporting only. You can read files, search code, run commands, and read PR/issue details — but your only output is either a single issue or a noop. - - ## Process - - Follow these steps in order. - - ### Step 1: Gather Context - - 1. Call `generate_agents_md` to get the repository's coding guidelines and conventions. If this fails, continue without it. - 2. Follow the data gathering instructions in the **Report Assignment** section. - - ### Step 2: Analyze - - Follow the analysis instructions in the **Report Assignment** section to determine whether an issue should be filed. The Report Assignment defines: - - What data to gather and how - - What to look for - - What constitutes a finding worth reporting - - What to skip or ignore - - ### Step 3: Self-Review (Quality Gate) - - Before filing anything, critically evaluate every finding against these criteria: - - 1. **Evidence is concrete** — you can point to exact file paths, line numbers, commit SHAs, or command outputs. No "I believe" or "it seems." - 2. **Finding is actionable** — a maintainer reading the issue can act on it without re-investigating from scratch. - 3. **Finding is not already tracked** — you checked open issues and recent PRs for duplicates. - 4. **Finding is worth a human's time** — the issue is material enough that a maintainer would thank you for filing it, not close it as noise. - - If zero findings pass all four criteria, call `noop` with a brief reason and stop. **Noop is the expected outcome most days.** Filing nothing is a success when there is nothing worth filing. - - ### Step 4: Report - - If there are findings that pass the quality gate, call `create_issue` with a structured report. Use the issue format specified in the Report Assignment if one is provided, otherwise use this default format: - - **Issue title:** Brief summary of findings - - **Issue body:** - - > ## Findings - > - > ### 1. [Brief description] - > - > **Evidence:** [Links, references, or data supporting the finding] - > **Action needed:** [What should be done] - > - > ## Suggested Actions - > - > - [ ] [Actionable checkbox for each finding] - - **Guidelines:** - - Group related findings together - - Be specific about what needs to happen - - Include links and references where possible - - Make suggested actions concrete enough to act on without re-investigating - - If a finding is ambiguous, it does not pass the quality gate — drop it - - ## Report Assignment - - GH_AW_PROMPT_EOF - cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - Detect documentation drift — code changes that require corresponding documentation updates. - - ### Data Gathering - - Use a lookback window of `--since="__GH_AW_EXPR_C9922AB3__"` for all runs (scheduled and manual). - - 1. Run `git log --since="__GH_AW_EXPR_C9922AB3__" --oneline --stat` to get a summary of recent commits. If there are no commits in the lookback window, report no findings and stop. - 2. Discover documentation files dynamically — scan the repository for common doc locations: `README.md`, `CONTRIBUTING.md`, `DEVELOPING.md`, `docs/`, `documentation/`, and any `.md` files in the repository root. Do not assume a fixed directory structure. - - ### What to Look For - - For each commit (or group of related commits), determine whether the changes could require documentation updates. Focus on: - - 1. **Public API changes** — new, renamed, or removed functions, endpoints, CLI flags, configuration options, or workflow inputs/outputs - 2. **Behavioral changes** — altered defaults, changed error messages, modified control flow that affects user-facing behavior - 3. **New features or workflows** — anything a user or contributor would need to know about - 4. **Dependency or tooling changes** — version bumps, new dependencies, changed build/test commands - 5. **Structural changes** — moved, renamed, or deleted files that are referenced in documentation - 6. **Configuration changes** — new environment variables, changed file formats, altered directory structures - - ### How to Analyze - - For each potentially impactful change: - - Read the full diff to understand what changed - - Read the current documentation files to understand what's documented - - Check whether the relevant documentation was already updated in the same commit or a subsequent commit within the lookback window - - Check whether an open issue or PR already tracks the documentation update - - ### What to Skip - - - Purely internal refactors with no user-facing impact - - Changes where documentation was already updated in the same or a later commit - - Changes where an open issue or PR already tracks the documentation update - - Test-only changes - - Minor changes where the existing docs are still substantially correct (e.g., a new optional parameter with a sensible default) - - Changes that only affect internal implementation details not referenced in any documentation - - ### Quality Gate — When to Noop - - **Noop is the expected outcome most days.** Only file an issue when: - - The documentation is **concretely wrong** — a user following the docs would get incorrect results or errors - - A **new public feature** has zero documentation - - A **removed or renamed** public interface is still referenced in docs - - Do not file for: vague "could be improved" suggestions, minor wording drift, or documentation that is slightly imprecise but still functionally correct. - - ### Issue Format - - **Issue title:** Brief summary of what's out of date (e.g., "Update README for new docs-drift workflow") - - **Issue body:** - - > Recent code changes in the repository have introduced documentation drift. The following changes need corresponding documentation updates. - > - > ## Changes Requiring Documentation Updates - > - > ### 1. [Brief description of the change] - > - > **Commit(s):** [SHA(s) with links] - > **What changed:** [Concise description of the code change] - > **Documentation impact:** [Which doc file(s) need updating and what specifically needs to change] - > - > ### 2. [Next change...] - > - > ## Suggested Actions - > - > - [ ] [Specific, actionable checkbox for each documentation update needed] - - __GH_AW_EXPR_49B959F1__ - - GH_AW_PROMPT_EOF - - name: Interpolate variables and render templates - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} - GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} - GH_AW_EXPR_C9922AB3: ${{ inputs.lookback-window }} - 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/interpolate_prompt.cjs'); - await main(); - - name: Substitute placeholders - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} - GH_AW_EXPR_C9922AB3: ${{ inputs.lookback-window }} - GH_AW_GITHUB_ACTOR: ${{ github.actor }} - GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} - GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} - GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} - GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} - 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'); - setupGlobals(core, github, context, exec, io); - - const substitutePlaceholders = require('/opt/gh-aw/actions/substitute_placeholders.cjs'); - - // Call the substitution function - return await substitutePlaceholders({ - file: process.env.GH_AW_PROMPT, - substitutions: { - GH_AW_EXPR_49B959F1: process.env.GH_AW_EXPR_49B959F1, - GH_AW_EXPR_C9922AB3: process.env.GH_AW_EXPR_C9922AB3, - GH_AW_GITHUB_ACTOR: process.env.GH_AW_GITHUB_ACTOR, - GH_AW_GITHUB_EVENT_COMMENT_ID: process.env.GH_AW_GITHUB_EVENT_COMMENT_ID, - GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: process.env.GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER, - GH_AW_GITHUB_EVENT_ISSUE_NUMBER: process.env.GH_AW_GITHUB_EVENT_ISSUE_NUMBER, - 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_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 - env: - GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - run: bash /opt/gh-aw/actions/validate_prompt_placeholders.sh - - name: Print prompt - env: - GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - run: bash /opt/gh-aw/actions/print_prompt_summary.sh - - name: Upload prompt artifact - if: success() - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 - with: - name: prompt - path: /tmp/gh-aw/aw-prompts/prompt.txt - retention-days: 1 - - agent: - needs: activation - runs-on: ubuntu-latest - permissions: - contents: read - issues: read - pull-requests: read - concurrency: - group: "gh-aw-copilot-${{ github.workflow }}" - env: - DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} - GH_AW_ASSETS_ALLOWED_EXTS: "" - GH_AW_ASSETS_BRANCH: "" - GH_AW_ASSETS_MAX_SIZE_KB: 0 - GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs - 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: ghawdocsdrift - outputs: - checkout_pr_success: ${{ steps.checkout-pr.outputs.checkout_pr_success || 'true' }} - has_patch: ${{ steps.collect_output.outputs.has_patch }} - model: ${{ steps.generate_aw_info.outputs.model }} - output: ${{ steps.collect_output.outputs.output }} - output_types: ${{ steps.collect_output.outputs.output_types }} - secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} - steps: - - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 - with: - destination: /opt/gh-aw/actions - - name: Checkout repository - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - persist-credentials: false - - name: Create gh-aw temp directory - run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh - - if: hashFiles('go.mod') != '' - name: Setup Go - uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5 - with: - cache: true - go-version-file: go.mod - - if: hashFiles('.python-version') != '' - name: Setup Python - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 - with: - python-version-file: .python-version - - if: hashFiles('.node-version') != '' - name: Setup Node.js (.node-version) - uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6 - with: - node-version-file: .node-version - - if: hashFiles('.node-version') == '' && hashFiles('.nvmrc') != '' - name: Setup Node.js (.nvmrc) - uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6 - with: - node-version-file: .nvmrc - - if: hashFiles('.ruby-version') != '' - name: Setup Ruby - uses: ruby/setup-ruby@09a7688d3b55cf0e976497ff046b70949eeaccfd # v1 - with: - bundler-cache: true - ruby-version: .ruby-version - - id: setup-uv - if: hashFiles('pyproject.toml', 'uv.lock') != '' - name: Setup uv - uses: astral-sh/setup-uv@e58605a9b6da7c637471fab8847a5e5a6b8df081 # v5 - - env: - UV_PATH: ${{ steps.setup-uv.outputs.uv-path }} - WORKSPACE: ${{ github.workspace }} - if: hashFiles('pyproject.toml', 'uv.lock') != '' - name: Expose uv in workspace - run: |- - set -euo pipefail - install_dir="$WORKSPACE/.gh-aw-tools/bin" - mkdir -p "$install_dir" - cp "$UV_PATH" "$install_dir/uv" - chmod +x "$install_dir/uv" - echo "$install_dir" >> "$GITHUB_PATH" - shell: bash - - env: - GITHUB_TOKEN: ${{ github.token }} - REPO_NAME: ${{ github.repository }} - SERVER_URL: ${{ github.server_url }} - name: Ensure full history - run: "if git rev-parse --is-shallow-repository | grep -q true; then\n SERVER_URL_STRIPPED=\"${SERVER_URL#https://}\"\n git remote set-url origin \"https://x-access-token:${GITHUB_TOKEN}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git\"\n git fetch --unshallow --quiet\nfi" - - env: - SETUP_COMMANDS: ${{ inputs.setup-commands }} - if: ${{ inputs.setup-commands != '' }} - name: Repo-specific setup - run: eval "$SETUP_COMMANDS" - - - name: Configure Git credentials - env: - REPO_NAME: ${{ github.repository }} - SERVER_URL: ${{ github.server_url }} - run: | - git config --global user.email "github-actions[bot]@users.noreply.github.com" - git config --global user.name "github-actions[bot]" - # Re-authenticate git with GitHub token - SERVER_URL_STRIPPED="${SERVER_URL#https://}" - git remote set-url origin "https://x-access-token:${{ github.token }}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" - echo "Git configured with standard GitHub Actions identity" - - name: Checkout PR branch - id: checkout-pr - if: | - github.event.pull_request - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - with: - github-token: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - script: | - const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io); - const { main } = require('/opt/gh-aw/actions/checkout_pr_branch.cjs'); - await main(); - - name: Generate agentic run info - id: generate_aw_info - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - with: - script: | - const fs = require('fs'); - - const awInfo = { - engine_id: "copilot", - engine_name: "GitHub Copilot CLI", - model: "gpt-5.3-codex", - version: "", - agent_version: "0.0.412", - workflow_name: "Docs Drift", - experimental: false, - supports_tools_allowlist: true, - run_id: context.runId, - run_number: context.runNumber, - run_attempt: process.env.GITHUB_RUN_ATTEMPT, - repository: context.repo.owner + '/' + context.repo.repo, - ref: context.ref, - sha: context.sha, - actor: context.actor, - event_name: context.eventName, - staged: false, - allowed_domains: ["agents-md-generator.fastmcp.app","artifacts.elastic.co","cloud.elastic.co","defaults","ela.st","elastic.co","github","go","node","public-code-search.fastmcp.app","python","ruby","www.elastic.co"], - firewall_enabled: true, - awf_version: "v0.20.2", - awmg_version: "v0.1.4", - steps: { - firewall: "squid" - }, - created_at: new Date().toISOString() - }; - - // Write to /tmp/gh-aw directory to avoid inclusion in PR - const tmpPath = '/tmp/gh-aw/aw_info.json'; - fs.writeFileSync(tmpPath, JSON.stringify(awInfo, null, 2)); - console.log('Generated aw_info.json at:', tmpPath); - console.log(JSON.stringify(awInfo, null, 2)); - - // Set model as output for reuse in other steps/jobs - core.setOutput('model', awInfo.model); - - name: Validate COPILOT_GITHUB_TOKEN secret - id: validate-secret - run: /opt/gh-aw/actions/validate_multi_secret.sh COPILOT_GITHUB_TOKEN 'GitHub Copilot CLI' https://github.github.com/gh-aw/reference/engines/#github-copilot-default - env: - COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} - - name: Install GitHub Copilot CLI - run: /opt/gh-aw/actions/install_copilot_cli.sh 0.0.412 - - name: Install awf binary - run: bash /opt/gh-aw/actions/install_awf_binary.sh v0.20.2 - - name: Determine automatic lockdown mode for GitHub MCP Server - id: determine-automatic-lockdown - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} - GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} - with: - script: | - 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.20.2 ghcr.io/github/gh-aw-firewall/api-proxy:0.20.2 ghcr.io/github/gh-aw-firewall/squid:0.20.2 ghcr.io/github/gh-aw-mcpg:v0.1.4 ghcr.io/github/github-mcp-server:v0.31.0 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' - {"create_issue":{"expires":168,"max":1},"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 \"[docs-drift] \".", - "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": "Report that a tool or capability needed to complete the task is not available, or share any information you deem important about missing functionality or limitations. Use this when you cannot accomplish what was requested because the required functionality is missing or access is restricted.", - "inputSchema": { - "additionalProperties": false, - "properties": { - "alternatives": { - "description": "Any workarounds, manual steps, or alternative approaches the user could take (max 256 characters).", - "type": "string" - }, - "reason": { - "description": "Explanation of why this tool is needed or what information you want to share about the limitation (max 256 characters).", - "type": "string" - }, - "tool": { - "description": "Optional: Name or description of the missing tool or capability (max 128 characters). Be specific about what functionality is needed.", - "type": "string" - } - }, - "required": [ - "reason" - ], - "type": "object" - }, - "name": "missing_tool" - }, - { - "description": "Log a transparency message when no significant actions are needed. Use this to confirm workflow completion and provide visibility when analysis is complete but no changes or outputs are required (e.g., 'No issues found', 'All checks passed'). This ensures the workflow produces human-visible output even when no other actions are taken.", - "inputSchema": { - "additionalProperties": false, - "properties": { - "message": { - "description": "Status or completion message to log. Should explain what was analyzed and the outcome (e.g., 'Code review complete - no issues found', 'Analysis complete - all tests passing').", - "type": "string" - } - }, - "required": [ - "message" - ], - "type": "object" - }, - "name": "noop" - }, - { - "description": "Report that data or information needed to complete the task is not available. Use this when you cannot accomplish what was requested because required data, context, or information is missing.", - "inputSchema": { - "additionalProperties": false, - "properties": { - "alternatives": { - "description": "Any workarounds, manual steps, or alternative approaches the user could take (max 256 characters).", - "type": "string" - }, - "context": { - "description": "Additional context about the missing data or where it should come from (max 256 characters).", - "type": "string" - }, - "data_type": { - "description": "Type or description of the missing data or information (max 128 characters). Be specific about what data is needed.", - "type": "string" - }, - "reason": { - "description": "Explanation of why this data is needed to complete the task (max 256 characters).", - "type": "string" - } - }, - "required": [], - "type": "object" - }, - "name": "missing_data" - } - ] - GH_AW_SAFE_OUTPUTS_TOOLS_EOF - cat > /opt/gh-aw/safeoutputs/validation.json << 'GH_AW_SAFE_OUTPUTS_VALIDATION_EOF' - { - "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": { - "alternatives": { - "type": "string", - "sanitize": true, - "maxLength": 512 - }, - "reason": { - "required": true, - "type": "string", - "sanitize": true, - "maxLength": 256 - }, - "tool": { - "type": "string", - "sanitize": true, - "maxLength": 128 - } - } - }, - "noop": { - "defaultMax": 1, - "fields": { - "message": { - "required": true, - "type": "string", - "sanitize": true, - "maxLength": 65000 - } - } - } - } - GH_AW_SAFE_OUTPUTS_VALIDATION_EOF - - name: Generate Safe Outputs MCP Server Config - id: safe-outputs-config - run: | - # Generate a secure random API key (360 bits of entropy, 40+ chars) - # Mask immediately to prevent timing vulnerabilities - API_KEY=$(openssl rand -base64 45 | tr -d '/+=') - echo "::add-mask::${API_KEY}" - - PORT=3001 - - # Set outputs for next steps - { - echo "safe_outputs_api_key=${API_KEY}" - echo "safe_outputs_port=${PORT}" - } >> "$GITHUB_OUTPUT" - - echo "Safe Outputs MCP server will run on port ${PORT}" - - - name: Start Safe Outputs MCP HTTP Server - id: safe-outputs-start - env: - DEBUG: '*' - GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-config.outputs.safe_outputs_port }} - GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-config.outputs.safe_outputs_api_key }} - GH_AW_SAFE_OUTPUTS_TOOLS_PATH: /opt/gh-aw/safeoutputs/tools.json - GH_AW_SAFE_OUTPUTS_CONFIG_PATH: /opt/gh-aw/safeoutputs/config.json - GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs - run: | - # Environment variables are set above to prevent template injection - export DEBUG - export GH_AW_SAFE_OUTPUTS_PORT - export GH_AW_SAFE_OUTPUTS_API_KEY - export GH_AW_SAFE_OUTPUTS_TOOLS_PATH - export GH_AW_SAFE_OUTPUTS_CONFIG_PATH - export GH_AW_MCP_LOG_DIR - - bash /opt/gh-aw/actions/start_safe_outputs_server.sh - - - name: Start MCP Gateway - id: start-mcp-gateway - env: - GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-start.outputs.api_key }} - GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-start.outputs.port }} - GITHUB_MCP_LOCKDOWN: ${{ steps.determine-automatic-lockdown.outputs.lockdown == 'true' && '1' || '0' }} - GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - run: | - set -eo pipefail - mkdir -p /tmp/gh-aw/mcp-config - - # Export gateway environment variables for MCP config and gateway script - export MCP_GATEWAY_PORT="80" - export MCP_GATEWAY_DOMAIN="host.docker.internal" - MCP_GATEWAY_API_KEY=$(openssl rand -base64 45 | tr -d '/+=') - echo "::add-mask::${MCP_GATEWAY_API_KEY}" - export MCP_GATEWAY_API_KEY - export MCP_GATEWAY_PAYLOAD_DIR="/tmp/gh-aw/mcp-payloads" - mkdir -p "${MCP_GATEWAY_PAYLOAD_DIR}" - export DEBUG="*" - - export GH_AW_ENGINE="copilot" - 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 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_LOCKDOWN -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.1.4' - - mkdir -p /home/runner/.copilot - cat << GH_AW_MCP_CONFIG_EOF | bash /opt/gh-aw/actions/start_mcp_gateway.sh - { - "mcpServers": { - "agents-md-generator": { - "type": "http", - "url": "https://agents-md-generator.fastmcp.app/mcp", - "tools": [ - "generate_agents_md" - ] - }, - "github": { - "type": "stdio", - "container": "ghcr.io/github/github-mcp-server:v0.31.0", - "env": { - "GITHUB_LOCKDOWN_MODE": "$GITHUB_MCP_LOCKDOWN", - "GITHUB_PERSONAL_ACCESS_TOKEN": "\${GITHUB_MCP_SERVER_TOKEN}", - "GITHUB_READ_ONLY": "1", - "GITHUB_TOOLSETS": "repos,issues,pull_requests,search" - } - }, - "public-code-search": { - "type": "http", - "url": "https://public-code-search.fastmcp.app/mcp", - "tools": [ - "search_code" - ] - }, - "safeoutputs": { - "type": "http", - "url": "http://host.docker.internal:$GH_AW_SAFE_OUTPUTS_PORT", - "headers": { - "Authorization": "\${GH_AW_SAFE_OUTPUTS_API_KEY}" - } - } - }, - "gateway": { - "port": $MCP_GATEWAY_PORT, - "domain": "${MCP_GATEWAY_DOMAIN}", - "apiKey": "${MCP_GATEWAY_API_KEY}", - "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" - } - } - GH_AW_MCP_CONFIG_EOF - - name: Generate workflow overview - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - with: - script: | - const { generateWorkflowOverview } = require('/opt/gh-aw/actions/generate_workflow_overview.cjs'); - await generateWorkflowOverview(core); - - name: Download prompt artifact - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 - with: - name: prompt - path: /tmp/gh-aw/aw-prompts - - name: Clean git credentials - run: bash /opt/gh-aw/actions/clean_git_credentials.sh - - name: Execute GitHub Copilot CLI - id: agentic_execution - # Copilot CLI tool arguments (sorted): - timeout-minutes: 90 - run: | - set -o pipefail - sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --allow-domains '*.githubusercontent.com,*.jsr.io,*.pythonhosted.org,*.rvm.io,agents-md-generator.fastmcp.app,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.rubygems.org,api.snapcraft.io,archive.ubuntu.com,artifacts.elastic.co,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,bun.sh,bundler.rubygems.org,cache.ruby-lang.org,cdn.jsdelivr.net,cloud.elastic.co,codeload.github.com,conda.anaconda.org,conda.binstar.org,crates.io,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,deb.nodesource.com,deno.land,ela.st,elastic.co,esm.sh,files.pythonhosted.org,gems.rubyforge.org,gems.rubyonrails.org,get.pnpm.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,host.docker.internal,index.crates.io,index.rubygems.org,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,lfs.github.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,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,pip.pypa.io,pkg.go.dev,ppa.launchpad.net,proxy.golang.org,public-code-search.fastmcp.app,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.bower.io,registry.npmjs.com,registry.npmjs.org,registry.yarnpkg.com,repo.anaconda.com,repo.continuum.io,repo.yarnpkg.com,rubygems.org,rubygems.pkg.github.com,s.symcb.com,s.symcd.com,security.ubuntu.com,skimdb.npmjs.com,static.crates.io,storage.googleapis.com,sum.golang.org,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.elastic.co,www.npmjs.com,www.npmjs.org,yarnpkg.com' --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.20.2 --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 --model gpt-5.3-codex --allow-all-tools --allow-all-paths --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log - env: - COPILOT_AGENT_RUNNER_TYPE: STANDALONE - COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} - GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json - GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GITHUB_HEAD_REF: ${{ github.head_ref }} - GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - GITHUB_REF_NAME: ${{ github.ref_name }} - GITHUB_STEP_SUMMARY: ${{ env.GITHUB_STEP_SUMMARY }} - GITHUB_WORKSPACE: ${{ github.workspace }} - XDG_CONFIG_HOME: /home/runner - - name: Configure Git credentials - env: - REPO_NAME: ${{ github.repository }} - SERVER_URL: ${{ github.server_url }} - run: | - git config --global user.email "github-actions[bot]@users.noreply.github.com" - git config --global user.name "github-actions[bot]" - # Re-authenticate git with GitHub token - SERVER_URL_STRIPPED="${SERVER_URL#https://}" - git remote set-url origin "https://x-access-token:${{ github.token }}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" - echo "Git configured with standard GitHub Actions identity" - - name: Copy Copilot session state files to logs - if: always() - continue-on-error: true - run: | - # Copy Copilot session state files to logs folder for artifact collection - # This ensures they are in /tmp/gh-aw/ where secret redaction can scan them - SESSION_STATE_DIR="$HOME/.copilot/session-state" - LOGS_DIR="/tmp/gh-aw/sandbox/agent/logs" - - if [ -d "$SESSION_STATE_DIR" ]; then - echo "Copying Copilot session state files from $SESSION_STATE_DIR to $LOGS_DIR" - mkdir -p "$LOGS_DIR" - cp -v "$SESSION_STATE_DIR"/*.jsonl "$LOGS_DIR/" 2>/dev/null || true - echo "Session state files copied successfully" - else - echo "No session-state directory found at $SESSION_STATE_DIR" - fi - - name: Stop MCP Gateway - if: always() - continue-on-error: true - env: - MCP_GATEWAY_PORT: ${{ steps.start-mcp-gateway.outputs.gateway-port }} - MCP_GATEWAY_API_KEY: ${{ steps.start-mcp-gateway.outputs.gateway-api-key }} - GATEWAY_PID: ${{ steps.start-mcp-gateway.outputs.gateway-pid }} - run: | - bash /opt/gh-aw/actions/stop_mcp_gateway.sh "$GATEWAY_PID" - - name: Redact secrets in logs - if: always() - 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/redact_secrets.cjs'); - await main(); - env: - GH_AW_SECRET_NAMES: 'COPILOT_GITHUB_TOKEN,GH_AW_GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,GITHUB_TOKEN' - SECRET_COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} - SECRET_GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} - SECRET_GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} - SECRET_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Upload Safe Outputs - if: always() - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 - with: - name: safe-output - path: ${{ env.GH_AW_SAFE_OUTPUTS }} - if-no-files-found: warn - - name: Ingest agent output - id: collect_output - if: always() - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,*.jsr.io,*.pythonhosted.org,*.rvm.io,agents-md-generator.fastmcp.app,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.rubygems.org,api.snapcraft.io,archive.ubuntu.com,artifacts.elastic.co,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,bun.sh,bundler.rubygems.org,cache.ruby-lang.org,cdn.jsdelivr.net,cloud.elastic.co,codeload.github.com,conda.anaconda.org,conda.binstar.org,crates.io,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,deb.nodesource.com,deno.land,ela.st,elastic.co,esm.sh,files.pythonhosted.org,gems.rubyforge.org,gems.rubyonrails.org,get.pnpm.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,host.docker.internal,index.crates.io,index.rubygems.org,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,lfs.github.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,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,pip.pypa.io,pkg.go.dev,ppa.launchpad.net,proxy.golang.org,public-code-search.fastmcp.app,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.bower.io,registry.npmjs.com,registry.npmjs.org,registry.yarnpkg.com,repo.anaconda.com,repo.continuum.io,repo.yarnpkg.com,rubygems.org,rubygems.pkg.github.com,s.symcb.com,s.symcd.com,security.ubuntu.com,skimdb.npmjs.com,static.crates.io,storage.googleapis.com,sum.golang.org,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.elastic.co,www.npmjs.com,www.npmjs.org,yarnpkg.com" - GITHUB_SERVER_URL: ${{ github.server_url }} - GITHUB_API_URL: ${{ github.api_url }} - 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/collect_ndjson_output.cjs'); - await main(); - - name: Upload sanitized agent output - if: always() && env.GH_AW_AGENT_OUTPUT - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 - with: - name: agent-output - path: ${{ env.GH_AW_AGENT_OUTPUT }} - if-no-files-found: warn - - name: Upload engine output files - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 - with: - name: agent_outputs - path: | - /tmp/gh-aw/sandbox/agent/logs/ - /tmp/gh-aw/redacted-urls.log - if-no-files-found: ignore - - name: Parse agent logs for step summary - if: always() - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_AGENT_OUTPUT: /tmp/gh-aw/sandbox/agent/logs/ - 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/parse_copilot_log.cjs'); - await main(); - - name: Parse MCP Gateway logs for step summary - if: always() - 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/parse_mcp_gateway_log.cjs'); - await main(); - - name: Print firewall logs - if: always() - continue-on-error: true - env: - AWF_LOGS_DIR: /tmp/gh-aw/sandbox/firewall/logs - run: | - # Fix permissions on firewall logs so they can be uploaded as artifacts - # AWF runs with sudo, creating files owned by root - sudo chmod -R a+r /tmp/gh-aw/sandbox/firewall/logs 2>/dev/null || true - # Only run awf logs summary if awf command exists (it may not be installed if workflow failed before install step) - if command -v awf &> /dev/null; then - awf logs summary | tee -a "$GITHUB_STEP_SUMMARY" - else - echo 'AWF binary not installed, skipping firewall log summary' - fi - - name: Upload agent artifacts - if: always() - continue-on-error: true - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 - with: - name: agent-artifacts - path: | - /tmp/gh-aw/aw-prompts/prompt.txt - /tmp/gh-aw/aw_info.json - /tmp/gh-aw/mcp-logs/ - /tmp/gh-aw/sandbox/firewall/logs/ - /tmp/gh-aw/agent-stdio.log - /tmp/gh-aw/agent/ - if-no-files-found: ignore - - conclusion: - needs: - - activation - - agent - - detection - - safe_outputs - if: (always()) && (needs.agent.result != 'skipped') - runs-on: ubuntu-slim - permissions: - contents: read - issues: write - outputs: - noop_message: ${{ steps.noop.outputs.noop_message }} - tools_reported: ${{ steps.missing_tool.outputs.tools_reported }} - total_count: ${{ steps.missing_tool.outputs.total_count }} - steps: - - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 - with: - destination: /opt/gh-aw/actions - - name: Download agent output artifact - continue-on-error: true - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 - with: - name: agent-output - path: /tmp/gh-aw/safeoutputs/ - - name: Setup agent output environment variable - run: | - mkdir -p /tmp/gh-aw/safeoutputs/ - find "/tmp/gh-aw/safeoutputs/" -type f -print - echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/safeoutputs/agent_output.json" >> "$GITHUB_ENV" - - name: Process No-Op Messages - id: noop - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_NOOP_MAX: 1 - GH_AW_WORKFLOW_NAME: "Docs Drift" - with: - github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - script: | - const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io); - const { main } = require('/opt/gh-aw/actions/noop.cjs'); - await main(); - - name: Record Missing Tool - id: missing_tool - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_WORKFLOW_NAME: "Docs Drift" - with: - github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - script: | - const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io); - const { main } = require('/opt/gh-aw/actions/missing_tool.cjs'); - await main(); - - name: Handle Agent Failure - id: handle_agent_failure - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_WORKFLOW_NAME: "Docs Drift" - 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: "gh-aw-docs-drift" - GH_AW_SECRET_VERIFICATION_RESULT: ${{ needs.agent.outputs.secret_verification_result }} - GH_AW_CHECKOUT_PR_SUCCESS: ${{ needs.agent.outputs.checkout_pr_success }} - GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\"}" - GH_AW_GROUP_REPORTS: "false" - with: - github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - script: | - const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io); - const { main } = require('/opt/gh-aw/actions/handle_agent_failure.cjs'); - await main(); - - name: Handle No-Op Message - id: handle_noop_message - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_WORKFLOW_NAME: "Docs Drift" - 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 }} - GH_AW_NOOP_REPORT_AS_ISSUE: "true" - with: - github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - script: | - const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io); - const { main } = require('/opt/gh-aw/actions/handle_noop_message.cjs'); - await main(); - - detection: - needs: agent - if: needs.agent.outputs.output_types != '' || needs.agent.outputs.has_patch == 'true' - runs-on: ubuntu-latest - permissions: {} - concurrency: - group: "gh-aw-copilot-${{ github.workflow }}" - timeout-minutes: 10 - outputs: - success: ${{ steps.parse_results.outputs.success }} - steps: - - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 - with: - destination: /opt/gh-aw/actions - - name: Download agent artifacts - continue-on-error: true - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 - with: - name: agent-artifacts - path: /tmp/gh-aw/threat-detection/ - - name: Download agent output artifact - continue-on-error: true - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 - with: - name: agent-output - path: /tmp/gh-aw/threat-detection/ - - name: Print agent output types - env: - AGENT_OUTPUT_TYPES: ${{ needs.agent.outputs.output_types }} - run: | - echo "Agent output-types: $AGENT_OUTPUT_TYPES" - - name: Setup threat detection - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - WORKFLOW_NAME: "Docs Drift" - WORKFLOW_DESCRIPTION: "Detect code changes that require documentation updates and file issues" - HAS_PATCH: ${{ needs.agent.outputs.has_patch }} - 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/setup_threat_detection.cjs'); - await main(); - - name: Ensure threat-detection directory and log - run: | - mkdir -p /tmp/gh-aw/threat-detection - touch /tmp/gh-aw/threat-detection/detection.log - - name: Validate COPILOT_GITHUB_TOKEN secret - id: validate-secret - run: /opt/gh-aw/actions/validate_multi_secret.sh COPILOT_GITHUB_TOKEN 'GitHub Copilot CLI' https://github.github.com/gh-aw/reference/engines/#github-copilot-default - env: - COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} - - name: Install GitHub Copilot CLI - run: /opt/gh-aw/actions/install_copilot_cli.sh 0.0.412 - - name: Execute GitHub Copilot CLI - id: agentic_execution - # Copilot CLI tool arguments (sorted): - # --allow-tool shell(cat) - # --allow-tool shell(grep) - # --allow-tool shell(head) - # --allow-tool shell(jq) - # --allow-tool shell(ls) - # --allow-tool shell(tail) - # --allow-tool shell(wc) - timeout-minutes: 20 - run: | - set -o pipefail - COPILOT_CLI_INSTRUCTION="$(cat /tmp/gh-aw/aw-prompts/prompt.txt)" - mkdir -p /tmp/ - mkdir -p /tmp/gh-aw/ - mkdir -p /tmp/gh-aw/agent/ - mkdir -p /tmp/gh-aw/sandbox/agent/logs/ - copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --model gpt-5.3-codex --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log - env: - COPILOT_AGENT_RUNNER_TYPE: STANDALONE - COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} - GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - GITHUB_HEAD_REF: ${{ github.head_ref }} - GITHUB_REF_NAME: ${{ github.ref_name }} - GITHUB_STEP_SUMMARY: ${{ env.GITHUB_STEP_SUMMARY }} - GITHUB_WORKSPACE: ${{ github.workspace }} - XDG_CONFIG_HOME: /home/runner - - name: Parse threat detection results - id: parse_results - 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/parse_threat_detection_results.cjs'); - await main(); - - name: Upload threat detection log - if: always() - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 - with: - name: threat-detection.log - path: /tmp/gh-aw/threat-detection/detection.log - if-no-files-found: ignore - - pre_activation: - runs-on: ubuntu-slim - outputs: - activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} - steps: - - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 - with: - destination: /opt/gh-aw/actions - - name: Check team membership for workflow - id: check_membership - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_REQUIRED_ROLES: admin,maintainer,write - GH_AW_ALLOWED_BOTS: ${{ inputs.allowed-bot-users }} - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - 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_membership.cjs'); - await main(); - - safe_outputs: - needs: - - agent - - detection - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (needs.detection.outputs.success == 'true') - runs-on: ubuntu-slim - permissions: - contents: read - issues: write - timeout-minutes: 15 - env: - GH_AW_ENGINE_ID: "copilot" - GH_AW_ENGINE_MODEL: "gpt-5.3-codex" - GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\"}" - GH_AW_WORKFLOW_ID: "gh-aw-docs-drift" - GH_AW_WORKFLOW_NAME: "Docs Drift" - outputs: - create_discussion_error_count: ${{ steps.process_safe_outputs.outputs.create_discussion_error_count }} - create_discussion_errors: ${{ steps.process_safe_outputs.outputs.create_discussion_errors }} - process_safe_outputs_processed_count: ${{ steps.process_safe_outputs.outputs.processed_count }} - process_safe_outputs_temporary_id_map: ${{ steps.process_safe_outputs.outputs.temporary_id_map }} - steps: - - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 - with: - destination: /opt/gh-aw/actions - - name: Download agent output artifact - continue-on-error: true - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 - with: - name: agent-output - path: /tmp/gh-aw/safeoutputs/ - - name: Setup agent output environment variable - run: | - mkdir -p /tmp/gh-aw/safeoutputs/ - find "/tmp/gh-aw/safeoutputs/" -type f -print - echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/safeoutputs/agent_output.json" >> "$GITHUB_ENV" - - name: Process Safe Outputs - id: process_safe_outputs - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_issue\":{\"close_older_issues\":true,\"expires\":168,\"max\":1,\"title_prefix\":\"[docs-drift] \"},\"missing_data\":{},\"missing_tool\":{}}" - with: - github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - script: | - const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io); - const { main } = require('/opt/gh-aw/actions/safe_output_handler_manager.cjs'); - await main(); - - name: Upload safe output items manifest - if: always() - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 - with: - name: safe-output-items - path: /tmp/safe-output-items.jsonl - if-no-files-found: warn - diff --git a/.github/workflows/gh-aw-docs-drift.lock.yml b/.github/workflows/gh-aw-docs-drift.lock.yml new file mode 120000 index 00000000..23c76300 --- /dev/null +++ b/.github/workflows/gh-aw-docs-drift.lock.yml @@ -0,0 +1 @@ +gh-aw-docs-patrol.lock.yml \ No newline at end of file diff --git a/.github/workflows/gh-aw-docs-drift-external.lock.yml b/.github/workflows/gh-aw-docs-patrol-external.lock.yml similarity index 94% rename from .github/workflows/gh-aw-docs-drift-external.lock.yml rename to .github/workflows/gh-aw-docs-patrol-external.lock.yml index 54c6bb43..03fe9e21 100644 --- a/.github/workflows/gh-aw-docs-drift-external.lock.yml +++ b/.github/workflows/gh-aw-docs-patrol-external.lock.yml @@ -33,11 +33,13 @@ # - gh-aw-fragments/rigor.md # - gh-aw-fragments/runtime-setup.md # - gh-aw-fragments/safe-output-create-issue.md -# - gh-aw-fragments/scheduled-report.md +# - gh-aw-fragments/scheduled-audit.md # -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"20a2133a748d0addc832cccd3a36e88841e16b8ace85c470dfacc009283f5279"} +# inlined-imports: true +# +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"524d010a9afdffa2c7634092afdd9b76b933b1ee3b52d83a4ac6db581758b009"} -name: "Docs Drift External" +name: "Docs Patrol External" "on": # bots: # Bots processed as bot check in pre-activation job # - ${{ inputs.allowed-bot-users }} # Bots processed as bot check in pre-activation job @@ -67,6 +69,11 @@ name: "Docs Drift External" description: Footer appended to all agent comments and reviews required: false type: string + model: + default: gpt-5.3-codex + description: AI model to use + required: false + type: string setup-commands: default: "" description: Shell commands to run before the agent starts (dependency install, build, etc.) @@ -80,9 +87,9 @@ permissions: {} concurrency: cancel-in-progress: true - group: docs-drift-external + group: docs-patrol-external -run-name: "Docs Drift External" +run-name: "Docs Patrol External" jobs: activation: @@ -96,7 +103,7 @@ jobs: comment_repo: "" steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Validate context variables @@ -118,7 +125,7 @@ jobs: - name: Check workflow file timestamps uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: - GH_AW_WORKFLOW_FILE: "gh-aw-docs-drift-external.lock.yml" + GH_AW_WORKFLOW_FILE: "gh-aw-docs-patrol-external.lock.yml" with: script: | const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); @@ -174,6 +181,25 @@ jobs: **Critical**: Tool calls write structured data that downstream jobs process. Without tool calls, follow-up actions will be skipped. **Note**: If you made no other safe output tool calls during this workflow execution, call the "noop" tool to provide a status message indicating completion or that no actions were needed. + + --- + + ## Creating an Issue, Reporting Missing Tools or Functionality, Reporting Missing Data + + **IMPORTANT**: To perform the actions listed above, use the **safeoutputs** tools. Do NOT use `gh`, do NOT call the GitHub API directly. You do not have write access to the GitHub repository. + + **Creating an Issue** + + To create an issue, use the create_issue tool from safeoutputs. + + **Reporting Missing Tools or Functionality** + + To report a missing tool or capability, use the missing_tool tool from safeoutputs. + + **Reporting Missing Data** + + To report missing data required to achieve a goal, use the missing_data tool from safeoutputs. + @@ -294,9 +320,7 @@ jobs: - **Mentions**: `@mentions` in the body are neutralized (backticked) by default. GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - # Scheduled Report Agent - - You are a report agent for __GH_AW_GITHUB_REPOSITORY__. You run on a schedule to investigate the repository and file an issue when something needs attention. Your specific assignment is described in the **Report Assignment** section below. + You are an agent for __GH_AW_GITHUB_REPOSITORY__. You run on a schedule to investigate the repository and file an issue when something needs attention. Your specific assignment is described in the **Report Assignment** section below. ## Context @@ -360,7 +384,7 @@ jobs: - Make suggested actions concrete enough to act on without re-investigating - If a finding is ambiguous, it does not pass the quality gate — drop it - ## Report Assignment + **Report Assignment:** GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" @@ -548,7 +572,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: ghawdocsdriftexternal + GH_AW_WORKFLOW_ID_SANITIZED: ghawdocspatrolexternal outputs: checkout_pr_success: ${{ steps.checkout-pr.outputs.checkout_pr_success || 'true' }} has_patch: ${{ steps.collect_output.outputs.has_patch }} @@ -558,7 +582,7 @@ jobs: secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Checkout repository @@ -658,10 +682,10 @@ jobs: const awInfo = { engine_id: "copilot", engine_name: "GitHub Copilot CLI", - model: "gpt-5.3-codex", + model: "${{ inputs.model }}", version: "", agent_version: "0.0.412", - workflow_name: "Docs Drift External", + workflow_name: "Docs Patrol External", experimental: false, supports_tools_allowlist: true, run_id: context.runId, @@ -723,7 +747,7 @@ jobs: 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 \"[docs-drift-external] \".", + "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 \"[docs-patrol-external] \".", "inputSchema": { "additionalProperties": false, "properties": { @@ -869,6 +893,31 @@ jobs: } } }, + "missing_data": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "context": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "data_type": { + "type": "string", + "sanitize": true, + "maxLength": 128 + }, + "reason": { + "type": "string", + "sanitize": true, + "maxLength": 256 + } + } + }, "missing_tool": { "defaultMax": 20, "fields": { @@ -1040,10 +1089,11 @@ jobs: run: | set -o pipefail sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --allow-domains '*.githubusercontent.com,*.jsr.io,*.pythonhosted.org,*.rvm.io,agents-md-generator.fastmcp.app,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.rubygems.org,api.snapcraft.io,archive.ubuntu.com,artifacts.elastic.co,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,bun.sh,bundler.rubygems.org,cache.ruby-lang.org,cdn.jsdelivr.net,cloud.elastic.co,codeload.github.com,conda.anaconda.org,conda.binstar.org,crates.io,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,deb.nodesource.com,deno.land,ela.st,elastic.co,esm.sh,files.pythonhosted.org,gems.rubyforge.org,gems.rubyonrails.org,get.pnpm.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,host.docker.internal,index.crates.io,index.rubygems.org,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,lfs.github.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,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,pip.pypa.io,pkg.go.dev,ppa.launchpad.net,proxy.golang.org,public-code-search.fastmcp.app,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.bower.io,registry.npmjs.com,registry.npmjs.org,registry.yarnpkg.com,repo.anaconda.com,repo.continuum.io,repo.yarnpkg.com,rubygems.org,rubygems.pkg.github.com,s.symcb.com,s.symcd.com,security.ubuntu.com,skimdb.npmjs.com,static.crates.io,storage.googleapis.com,sum.golang.org,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.elastic.co,www.npmjs.com,www.npmjs.org,yarnpkg.com' --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.20.2 --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 --model gpt-5.3-codex --allow-all-tools --allow-all-paths --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log + -- /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 --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} @@ -1209,7 +1259,7 @@ jobs: total_count: ${{ steps.missing_tool.outputs.total_count }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent output artifact @@ -1229,7 +1279,7 @@ jobs: env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} GH_AW_NOOP_MAX: 1 - GH_AW_WORKFLOW_NAME: "Docs Drift External" + GH_AW_WORKFLOW_NAME: "Docs Patrol External" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | @@ -1242,7 +1292,7 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_WORKFLOW_NAME: "Docs Drift External" + GH_AW_WORKFLOW_NAME: "Docs Patrol External" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | @@ -1255,10 +1305,10 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_WORKFLOW_NAME: "Docs Drift External" + GH_AW_WORKFLOW_NAME: "Docs Patrol External" 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: "gh-aw-docs-drift-external" + GH_AW_WORKFLOW_ID: "gh-aw-docs-patrol-external" GH_AW_SECRET_VERIFICATION_RESULT: ${{ needs.agent.outputs.secret_verification_result }} GH_AW_CHECKOUT_PR_SUCCESS: ${{ needs.agent.outputs.checkout_pr_success }} GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\"}" @@ -1275,7 +1325,7 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_WORKFLOW_NAME: "Docs Drift External" + GH_AW_WORKFLOW_NAME: "Docs Patrol External" 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 }} @@ -1300,7 +1350,7 @@ jobs: success: ${{ steps.parse_results.outputs.success }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent artifacts @@ -1323,7 +1373,7 @@ jobs: - name: Setup threat detection uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: - WORKFLOW_NAME: "Docs Drift External" + WORKFLOW_NAME: "Docs Patrol External" WORKFLOW_DESCRIPTION: "Detect code changes that require updates to published Elastic documentation" HAS_PATCH: ${{ needs.agent.outputs.has_patch }} with: @@ -1361,10 +1411,11 @@ jobs: mkdir -p /tmp/gh-aw/ mkdir -p /tmp/gh-aw/agent/ mkdir -p /tmp/gh-aw/sandbox/agent/logs/ - copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --model gpt-5.3-codex --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log + copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_REF_NAME: ${{ github.ref_name }} @@ -1394,7 +1445,7 @@ jobs: activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Check team membership for workflow @@ -1423,10 +1474,10 @@ jobs: timeout-minutes: 15 env: GH_AW_ENGINE_ID: "copilot" - GH_AW_ENGINE_MODEL: "gpt-5.3-codex" + GH_AW_ENGINE_MODEL: "${{ inputs.model }}" GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\"}" - GH_AW_WORKFLOW_ID: "gh-aw-docs-drift-external" - GH_AW_WORKFLOW_NAME: "Docs Drift External" + GH_AW_WORKFLOW_ID: "gh-aw-docs-patrol-external" + GH_AW_WORKFLOW_NAME: "Docs Patrol External" outputs: create_discussion_error_count: ${{ steps.process_safe_outputs.outputs.create_discussion_error_count }} create_discussion_errors: ${{ steps.process_safe_outputs.outputs.create_discussion_errors }} @@ -1434,7 +1485,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@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent output artifact @@ -1453,7 +1504,7 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_issue\":{\"close_older_issues\":true,\"expires\":168,\"max\":1,\"title_prefix\":\"[docs-drift-external] \"},\"missing_data\":{},\"missing_tool\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_issue\":{\"close_older_issues\":true,\"expires\":168,\"max\":1,\"title_prefix\":\"[docs-patrol-external] \"},\"missing_data\":{},\"missing_tool\":{}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/gh-aw-docs-drift-external.md b/.github/workflows/gh-aw-docs-patrol-external.md similarity index 95% rename from .github/workflows/gh-aw-docs-drift-external.md rename to .github/workflows/gh-aw-docs-patrol-external.md index 812ec117..6c0132d9 100644 --- a/.github/workflows/gh-aw-docs-drift-external.md +++ b/.github/workflows/gh-aw-docs-patrol-external.md @@ -1,5 +1,6 @@ --- -name: "Docs Drift External" +inlined-imports: true +name: "Docs Patrol External" description: "Detect code changes that require updates to published Elastic documentation" imports: - gh-aw-fragments/elastic-tools.md @@ -10,13 +11,18 @@ imports: - gh-aw-fragments/mcp-pagination.md - gh-aw-fragments/messages-footer.md - gh-aw-fragments/safe-output-create-issue.md - - gh-aw-fragments/scheduled-report.md + - gh-aw-fragments/scheduled-audit.md engine: id: copilot - model: gpt-5.3-codex + model: ${{ inputs.model }} on: workflow_call: inputs: + model: + description: "AI model to use" + type: string + required: false + default: "gpt-5.3-codex" additional-instructions: description: "Repo-specific instructions appended to the agent prompt" type: string @@ -49,7 +55,7 @@ on: bots: - "${{ inputs.allowed-bot-users }}" concurrency: - group: docs-drift-external + group: docs-patrol-external cancel-in-progress: true permissions: contents: read @@ -82,7 +88,7 @@ safe-outputs: noop: create-issue: max: 1 - title-prefix: "[docs-drift-external] " + title-prefix: "[docs-patrol-external] " close-older-issues: true expires: 7d timeout-minutes: 90 diff --git a/.github/workflows/gh-aw-docs-patrol.lock.yml b/.github/workflows/gh-aw-docs-patrol.lock.yml new file mode 100644 index 00000000..c084bcd3 --- /dev/null +++ b/.github/workflows/gh-aw-docs-patrol.lock.yml @@ -0,0 +1,1487 @@ +# +# ___ _ _ +# / _ \ | | (_) +# | |_| | __ _ ___ _ __ | |_ _ ___ +# | _ |/ _` |/ _ \ '_ \| __| |/ __| +# | | | | (_| | __/ | | | |_| | (__ +# \_| |_/\__, |\___|_| |_|\__|_|\___| +# __/ | +# _ _ |___/ +# | | | | / _| | +# | | | | ___ _ __ _ __| |_| | _____ ____ +# | |/\| |/ _ \ '__| |/ /| _| |/ _ \ \ /\ / / ___| +# \ /\ / (_) | | | | ( | | | | (_) \ V V /\__ \ +# \/ \/ \___/|_| |_|\_\|_| |_|\___/ \_/\_/ |___/ +# +# This file was automatically generated by gh-aw. DO NOT EDIT. +# +# To update this file, edit the corresponding .md file and run: +# gh aw compile +# Not all edits will cause changes to this file. +# +# For more information: https://github.github.com/gh-aw/introduction/overview/ +# +# Detect code changes that require documentation updates and file issues +# +# Resolved workflow manifest: +# Imports: +# - gh-aw-fragments/elastic-tools.md +# - gh-aw-fragments/ensure-full-history.md +# - gh-aw-fragments/formatting.md +# - gh-aw-fragments/mcp-pagination.md +# - gh-aw-fragments/messages-footer.md +# - gh-aw-fragments/rigor.md +# - gh-aw-fragments/runtime-setup.md +# - gh-aw-fragments/safe-output-create-issue.md +# - gh-aw-fragments/scheduled-audit.md +# +# inlined-imports: true +# +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"534d44254a3ea17148b2a627e57c179de00dbfe286876c0175888f81f9dcecd7"} + +name: "Docs Patrol" +"on": + # bots: # Bots processed as bot check in pre-activation job + # - ${{ inputs.allowed-bot-users }} # Bots processed as bot check in pre-activation job + # roles: # Roles processed as role check in pre-activation job + # - admin # Roles processed as role check in pre-activation job + # - maintainer # Roles processed as role check in pre-activation job + # - write # Roles processed as role check in pre-activation job + workflow_call: + inputs: + additional-instructions: + default: "" + description: Repo-specific instructions appended to the agent prompt + required: false + type: string + allowed-bot-users: + default: github-actions[bot] + description: Allowlisted bot actor usernames (comma-separated) + required: false + type: string + lookback-window: + default: 7 days ago + description: Git lookback window for detecting recent commits (e.g. '7 days ago', '14 days ago') + required: false + type: string + messages-footer: + default: "" + description: Footer appended to all agent comments and reviews + required: false + type: string + model: + default: gpt-5.3-codex + description: AI model to use + required: false + type: string + setup-commands: + default: "" + description: Shell commands to run before the agent starts (dependency install, build, etc.) + required: false + type: string + secrets: + COPILOT_GITHUB_TOKEN: + required: true + +permissions: {} + +concurrency: + cancel-in-progress: true + group: docs-patrol + +run-name: "Docs Patrol" + +jobs: + activation: + needs: pre_activation + if: needs.pre_activation.outputs.activated == 'true' + runs-on: ubuntu-slim + permissions: + contents: read + outputs: + comment_id: "" + comment_repo: "" + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 + with: + destination: /opt/gh-aw/actions + - name: Validate context variables + 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/validate_context_variables.cjs'); + await main(); + - name: Checkout .github and .agents folders + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + sparse-checkout: | + .github + .agents + fetch-depth: 1 + persist-credentials: false + - name: Check workflow file timestamps + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_WORKFLOW_FILE: "gh-aw-docs-patrol.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: Create prompt with built-in context + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} + GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} + GH_AW_EXPR_C9922AB3: ${{ inputs.lookback-window }} + GH_AW_GITHUB_ACTOR: ${{ github.actor }} + GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} + GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} + GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} + GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} + GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} + GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} + run: | + bash /opt/gh-aw/actions/create_prompt_first.sh + cat << 'GH_AW_PROMPT_EOF' > "$GH_AW_PROMPT" + + GH_AW_PROMPT_EOF + cat "/opt/gh-aw/prompts/xpia.md" >> "$GH_AW_PROMPT" + cat "/opt/gh-aw/prompts/temp_folder_prompt.md" >> "$GH_AW_PROMPT" + cat "/opt/gh-aw/prompts/markdown.md" >> "$GH_AW_PROMPT" + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + + GitHub API Access Instructions + + The gh CLI is NOT authenticated. Do NOT use gh commands for GitHub operations. + + + To create or modify GitHub resources (issues, discussions, pull requests, etc.), you MUST call the appropriate safe output tool. Simply writing content will NOT work - the workflow requires actual tool calls. + + Temporary IDs: Some safe output tools support a temporary ID field (usually named temporary_id) so you can reference newly-created items elsewhere in the SAME agent output (for example, using #aw_abc1 in a later body). + + **IMPORTANT - temporary_id format rules:** + - If you DON'T need to reference the item later, OMIT the temporary_id field entirely (it will be auto-generated if needed) + - If you DO need cross-references/chaining, you MUST match this EXACT validation regex: /^aw_[A-Za-z0-9]{3,8}$/i + - Format: aw_ prefix followed by 3 to 8 alphanumeric characters (A-Z, a-z, 0-9, case-insensitive) + - Valid alphanumeric characters: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 + - INVALID examples: aw_ab (too short), aw_123456789 (too long), aw_test-id (contains hyphen), aw_id_123 (contains underscore) + - VALID examples: aw_abc, aw_abc1, aw_Test123, aw_A1B2C3D4, aw_12345678 + - To generate valid IDs: use 3-8 random alphanumeric characters or omit the field to let the system auto-generate + + Do NOT invent other aw_* formats — downstream steps will reject them with validation errors matching against /^aw_[A-Za-z0-9]{3,8}$/i. + + Discover available tools from the safeoutputs MCP server. + + **Critical**: Tool calls write structured data that downstream jobs process. Without tool calls, follow-up actions will be skipped. + + **Note**: If you made no other safe output tool calls during this workflow execution, call the "noop" tool to provide a status message indicating completion or that no actions were needed. + + --- + + ## Creating an Issue, Reporting Missing Tools or Functionality, Reporting Missing Data + + **IMPORTANT**: To perform the actions listed above, use the **safeoutputs** tools. Do NOT use `gh`, do NOT call the GitHub API directly. You do not have write access to the GitHub repository. + + **Creating an Issue** + + To create an issue, use the create_issue tool from safeoutputs. + + **Reporting Missing Tools or Functionality** + + To report a missing tool or capability, use the missing_tool tool from safeoutputs. + + **Reporting Missing Data** + + To report missing data required to achieve a goal, use the missing_data tool from safeoutputs. + + + + + The following GitHub context information is available for this workflow: + {{#if __GH_AW_GITHUB_ACTOR__ }} + - **actor**: __GH_AW_GITHUB_ACTOR__ + {{/if}} + {{#if __GH_AW_GITHUB_REPOSITORY__ }} + - **repository**: __GH_AW_GITHUB_REPOSITORY__ + {{/if}} + {{#if __GH_AW_GITHUB_WORKSPACE__ }} + - **workspace**: __GH_AW_GITHUB_WORKSPACE__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_ISSUE_NUMBER__ }} + - **issue-number**: #__GH_AW_GITHUB_EVENT_ISSUE_NUMBER__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__ }} + - **discussion-number**: #__GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__ }} + - **pull-request-number**: #__GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_COMMENT_ID__ }} + - **comment-id**: __GH_AW_GITHUB_EVENT_COMMENT_ID__ + {{/if}} + {{#if __GH_AW_GITHUB_RUN_ID__ }} + - **workflow-run-id**: __GH_AW_GITHUB_RUN_ID__ + {{/if}} + + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + ## MCP Servers + + - **`generate_agents_md`** — generates a summary of the repository's structure, conventions, and coding guidelines from AGENTS.md and related files. Call at the start of every workflow to get repo context. + - **`search_code`** — grep-style search across public GitHub repositories. Use for finding usage patterns in upstream libraries, reference implementations, or examples in open-source projects. This searches *public GitHub repos*, not the local codebase — if available you can use `grep` and file reading for local code. + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + ## Formatting Guidelines + + - Lead with the most important information — your first sentence should be the key takeaway + - Be concise and actionable — no filler or praise + - Use `
` and `` tags for long sections to keep responses scannable + - Wrap branch names and @-references in backticks to avoid pinging users + - Include code snippets with file paths and line numbers when referencing the codebase + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + ## Rigor + + **Silence is better than noise. A false positive wastes a human's time and erodes trust in every future report.** + + - If you claim something is missing or broken, show the exact evidence in the code — file path, line number, and what you observed. + - If a conclusion depends on assumptions you haven't confirmed, do not assert it. Verify first; if you cannot verify, do not report. + - "I don't know" is better than a wrong answer. `noop` is better than a speculative finding. + - It's worth the time to verify now versus guessing and forcing someone else to verify later. + - Before filing any issue or opening any PR, re-read your own output as a skeptical reviewer. Ask: "Would a senior engineer on this team find this useful, or would they close it immediately?" If the answer is "close," call `noop` instead. + - Only report findings you would confidently defend in a code review. If you feel the need to hedge with "might," "could," or "possibly," the finding is not ready to file. + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + ## MCP Pagination + + MCP tool responses have a **25,000 token limit**. When responses exceed this limit, the call fails and you must retry with pagination — wasting turns and tokens. Use proactive pagination to stay under the limit. + + ### Recommended `perPage` Values + + - **5-10**: For detailed items (PR diffs, files with patches, issues with comments) + - **20-30**: For medium-detail lists (commits, review comments, issue lists) + - **50-100**: For simple list operations (branches, labels, tags) + + ### Pagination Pattern + + When you need all results from a paginated API: + + 1. Fetch the first page with a conservative `perPage` value + 2. Process the results before fetching the next page + 3. Continue fetching pages until you receive fewer results than `perPage` (indicating the last page) + + ### Error Recovery + + If you see an error like: + - `MCP tool response exceeds maximum allowed tokens (25000)` + - `Response too large for tool [tool_name]` + + Retry the same call with a smaller `perPage` value (halve it). + + ### Tips + + - **Start small**: It's better to make multiple small requests than one that fails + - **Fetch incrementally**: Get an overview first, then details for specific items + - **Use filters**: Combine `perPage` with state, label, or date filters to reduce result size + - **Process as you go**: Don't accumulate all pages before acting — process each batch immediately + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + ## Message Footer + + A footer is automatically appended to all comments and reviews. Do not add your own footer or sign-off — the runtime handles this. + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + ## create-issue Limitations + + - **Title**: Max 128 characters. Sanitized (special characters escaped). + - **Labels**: Max 10 labels per issue. Each label max 64 characters. Labels containing only `-` are rejected. + - **Assignees**: Max 5 assignees per issue. + - **Body**: No strict character limit beyond GitHub's API limit (~65,536 characters), but fields over 16,000 tokens are written to a file reference instead of inlined. + - **Bot triggers**: References like `fixes #123` or `closes #456` in the body are neutralized to prevent unintended issue closures. + - **Mentions**: `@mentions` in the body are neutralized (backticked) by default. + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + You are an agent for __GH_AW_GITHUB_REPOSITORY__. You run on a schedule to investigate the repository and file an issue when something needs attention. Your specific assignment is described in the **Report Assignment** section below. + + ## Context + + - **Repository**: __GH_AW_GITHUB_REPOSITORY__ + + ## Constraints + + This workflow is for detection and reporting only. You can read files, search code, run commands, and read PR/issue details — but your only output is either a single issue or a noop. + + ## Process + + Follow these steps in order. + + ### Step 1: Gather Context + + 1. Call `generate_agents_md` to get the repository's coding guidelines and conventions. If this fails, continue without it. + 2. Follow the data gathering instructions in the **Report Assignment** section. + + ### Step 2: Analyze + + Follow the analysis instructions in the **Report Assignment** section to determine whether an issue should be filed. The Report Assignment defines: + - What data to gather and how + - What to look for + - What constitutes a finding worth reporting + - What to skip or ignore + + ### Step 3: Self-Review (Quality Gate) + + Before filing anything, critically evaluate every finding against these criteria: + + 1. **Evidence is concrete** — you can point to exact file paths, line numbers, commit SHAs, or command outputs. No "I believe" or "it seems." + 2. **Finding is actionable** — a maintainer reading the issue can act on it without re-investigating from scratch. + 3. **Finding is not already tracked** — you checked open issues and recent PRs for duplicates. + 4. **Finding is worth a human's time** — the issue is material enough that a maintainer would thank you for filing it, not close it as noise. + + If zero findings pass all four criteria, call `noop` with a brief reason and stop. **Noop is the expected outcome most days.** Filing nothing is a success when there is nothing worth filing. + + ### Step 4: Report + + If there are findings that pass the quality gate, call `create_issue` with a structured report. Use the issue format specified in the Report Assignment if one is provided, otherwise use this default format: + + **Issue title:** Brief summary of findings + + **Issue body:** + + > ## Findings + > + > ### 1. [Brief description] + > + > **Evidence:** [Links, references, or data supporting the finding] + > **Action needed:** [What should be done] + > + > ## Suggested Actions + > + > - [ ] [Actionable checkbox for each finding] + + **Guidelines:** + - Group related findings together + - Be specific about what needs to happen + - Include links and references where possible + - Make suggested actions concrete enough to act on without re-investigating + - If a finding is ambiguous, it does not pass the quality gate — drop it + + **Report Assignment:** + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + Detect documentation drift — code changes that require corresponding documentation updates. + + ### Data Gathering + + Use a lookback window of `--since="__GH_AW_EXPR_C9922AB3__"` for all runs (scheduled and manual). + + 1. Run `git log --since="__GH_AW_EXPR_C9922AB3__" --oneline --stat` to get a summary of recent commits. If there are no commits in the lookback window, report no findings and stop. + 2. Discover documentation files dynamically — scan the repository for common doc locations: `README.md`, `CONTRIBUTING.md`, `DEVELOPING.md`, `docs/`, `documentation/`, and any `.md` files in the repository root. Do not assume a fixed directory structure. + + ### What to Look For + + For each commit (or group of related commits), determine whether the changes could require documentation updates. Focus on: + + 1. **Public API changes** — new, renamed, or removed functions, endpoints, CLI flags, configuration options, or workflow inputs/outputs + 2. **Behavioral changes** — altered defaults, changed error messages, modified control flow that affects user-facing behavior + 3. **New features or workflows** — anything a user or contributor would need to know about + 4. **Dependency or tooling changes** — version bumps, new dependencies, changed build/test commands + 5. **Structural changes** — moved, renamed, or deleted files that are referenced in documentation + 6. **Configuration changes** — new environment variables, changed file formats, altered directory structures + + ### How to Analyze + + For each potentially impactful change: + - Read the full diff to understand what changed + - Read the current documentation files to understand what's documented + - Check whether the relevant documentation was already updated in the same commit or a subsequent commit within the lookback window + - Check whether an open issue or PR already tracks the documentation update + + ### What to Skip + + - Purely internal refactors with no user-facing impact + - Changes where documentation was already updated in the same or a later commit + - Changes where an open issue or PR already tracks the documentation update + - Test-only changes + - Minor changes where the existing docs are still substantially correct (e.g., a new optional parameter with a sensible default) + - Changes that only affect internal implementation details not referenced in any documentation + + ### Quality Gate — When to Noop + + **Noop is the expected outcome most days.** Only file an issue when: + - The documentation is **concretely wrong** — a user following the docs would get incorrect results or errors + - A **new public feature** has zero documentation + - A **removed or renamed** public interface is still referenced in docs + + Do not file for: vague "could be improved" suggestions, minor wording drift, or documentation that is slightly imprecise but still functionally correct. + + ### Issue Format + + **Issue title:** Brief summary of what's out of date (e.g., "Update README for new CLI flag") + + **Issue body:** + + > Recent code changes in the repository have introduced documentation drift. The following changes need corresponding documentation updates. + > + > ## Changes Requiring Documentation Updates + > + > ### 1. [Brief description of the change] + > + > **Commit(s):** [SHA(s) with links] + > **What changed:** [Concise description of the code change] + > **Documentation impact:** [Which doc file(s) need updating and what specifically needs to change] + > + > ### 2. [Next change...] + > + > ## Suggested Actions + > + > - [ ] [Specific, actionable checkbox for each documentation update needed] + + __GH_AW_EXPR_49B959F1__ + + GH_AW_PROMPT_EOF + - name: Interpolate variables and render templates + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} + GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} + GH_AW_EXPR_C9922AB3: ${{ inputs.lookback-window }} + 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/interpolate_prompt.cjs'); + await main(); + - name: Substitute placeholders + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} + GH_AW_EXPR_C9922AB3: ${{ inputs.lookback-window }} + GH_AW_GITHUB_ACTOR: ${{ github.actor }} + GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} + GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} + GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} + 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'); + setupGlobals(core, github, context, exec, io); + + const substitutePlaceholders = require('/opt/gh-aw/actions/substitute_placeholders.cjs'); + + // Call the substitution function + return await substitutePlaceholders({ + file: process.env.GH_AW_PROMPT, + substitutions: { + GH_AW_EXPR_49B959F1: process.env.GH_AW_EXPR_49B959F1, + GH_AW_EXPR_C9922AB3: process.env.GH_AW_EXPR_C9922AB3, + GH_AW_GITHUB_ACTOR: process.env.GH_AW_GITHUB_ACTOR, + GH_AW_GITHUB_EVENT_COMMENT_ID: process.env.GH_AW_GITHUB_EVENT_COMMENT_ID, + GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: process.env.GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER, + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: process.env.GH_AW_GITHUB_EVENT_ISSUE_NUMBER, + 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_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 + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + run: bash /opt/gh-aw/actions/validate_prompt_placeholders.sh + - name: Print prompt + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + run: bash /opt/gh-aw/actions/print_prompt_summary.sh + - name: Upload prompt artifact + if: success() + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: prompt + path: /tmp/gh-aw/aw-prompts/prompt.txt + retention-days: 1 + + agent: + needs: activation + runs-on: ubuntu-latest + permissions: + contents: read + issues: read + pull-requests: read + concurrency: + group: "gh-aw-copilot-${{ github.workflow }}" + env: + DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} + GH_AW_ASSETS_ALLOWED_EXTS: "" + GH_AW_ASSETS_BRANCH: "" + GH_AW_ASSETS_MAX_SIZE_KB: 0 + GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs + 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: ghawdocspatrol + outputs: + checkout_pr_success: ${{ steps.checkout-pr.outputs.checkout_pr_success || 'true' }} + has_patch: ${{ steps.collect_output.outputs.has_patch }} + model: ${{ steps.generate_aw_info.outputs.model }} + output: ${{ steps.collect_output.outputs.output }} + output_types: ${{ steps.collect_output.outputs.output_types }} + secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 + with: + destination: /opt/gh-aw/actions + - name: Checkout repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + - name: Create gh-aw temp directory + run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh + - if: hashFiles('go.mod') != '' + name: Setup Go + uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5 + with: + cache: true + go-version-file: go.mod + - if: hashFiles('.python-version') != '' + name: Setup Python + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 + with: + python-version-file: .python-version + - if: hashFiles('.node-version') != '' + name: Setup Node.js (.node-version) + uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6 + with: + node-version-file: .node-version + - if: hashFiles('.node-version') == '' && hashFiles('.nvmrc') != '' + name: Setup Node.js (.nvmrc) + uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6 + with: + node-version-file: .nvmrc + - if: hashFiles('.ruby-version') != '' + name: Setup Ruby + uses: ruby/setup-ruby@09a7688d3b55cf0e976497ff046b70949eeaccfd # v1 + with: + bundler-cache: true + ruby-version: .ruby-version + - id: setup-uv + if: hashFiles('pyproject.toml', 'uv.lock') != '' + name: Setup uv + uses: astral-sh/setup-uv@e58605a9b6da7c637471fab8847a5e5a6b8df081 # v5 + - env: + UV_PATH: ${{ steps.setup-uv.outputs.uv-path }} + WORKSPACE: ${{ github.workspace }} + if: hashFiles('pyproject.toml', 'uv.lock') != '' + name: Expose uv in workspace + run: |- + set -euo pipefail + install_dir="$WORKSPACE/.gh-aw-tools/bin" + mkdir -p "$install_dir" + cp "$UV_PATH" "$install_dir/uv" + chmod +x "$install_dir/uv" + echo "$install_dir" >> "$GITHUB_PATH" + shell: bash + - env: + GITHUB_TOKEN: ${{ github.token }} + REPO_NAME: ${{ github.repository }} + SERVER_URL: ${{ github.server_url }} + name: Ensure full history + run: "if git rev-parse --is-shallow-repository | grep -q true; then\n SERVER_URL_STRIPPED=\"${SERVER_URL#https://}\"\n git remote set-url origin \"https://x-access-token:${GITHUB_TOKEN}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git\"\n git fetch --unshallow --quiet\nfi" + - env: + SETUP_COMMANDS: ${{ inputs.setup-commands }} + if: ${{ inputs.setup-commands != '' }} + name: Repo-specific setup + run: eval "$SETUP_COMMANDS" + + - name: Configure Git credentials + env: + REPO_NAME: ${{ github.repository }} + SERVER_URL: ${{ github.server_url }} + run: | + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git config --global user.name "github-actions[bot]" + # Re-authenticate git with GitHub token + SERVER_URL_STRIPPED="${SERVER_URL#https://}" + git remote set-url origin "https://x-access-token:${{ github.token }}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" + echo "Git configured with standard GitHub Actions identity" + - name: Checkout PR branch + id: checkout-pr + if: | + github.event.pull_request + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + with: + github-token: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/checkout_pr_branch.cjs'); + await main(); + - name: Generate agentic run info + id: generate_aw_info + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + with: + script: | + const fs = require('fs'); + + const awInfo = { + engine_id: "copilot", + engine_name: "GitHub Copilot CLI", + model: "${{ inputs.model }}", + version: "", + agent_version: "0.0.412", + workflow_name: "Docs Patrol", + experimental: false, + supports_tools_allowlist: true, + run_id: context.runId, + run_number: context.runNumber, + run_attempt: process.env.GITHUB_RUN_ATTEMPT, + repository: context.repo.owner + '/' + context.repo.repo, + ref: context.ref, + sha: context.sha, + actor: context.actor, + event_name: context.eventName, + staged: false, + allowed_domains: ["agents-md-generator.fastmcp.app","artifacts.elastic.co","cloud.elastic.co","defaults","ela.st","elastic.co","github","go","node","public-code-search.fastmcp.app","python","ruby","www.elastic.co"], + firewall_enabled: true, + awf_version: "v0.20.2", + awmg_version: "v0.1.4", + steps: { + firewall: "squid" + }, + created_at: new Date().toISOString() + }; + + // Write to /tmp/gh-aw directory to avoid inclusion in PR + const tmpPath = '/tmp/gh-aw/aw_info.json'; + fs.writeFileSync(tmpPath, JSON.stringify(awInfo, null, 2)); + console.log('Generated aw_info.json at:', tmpPath); + console.log(JSON.stringify(awInfo, null, 2)); + + // Set model as output for reuse in other steps/jobs + core.setOutput('model', awInfo.model); + - name: Validate COPILOT_GITHUB_TOKEN secret + id: validate-secret + run: /opt/gh-aw/actions/validate_multi_secret.sh COPILOT_GITHUB_TOKEN 'GitHub Copilot CLI' https://github.github.com/gh-aw/reference/engines/#github-copilot-default + env: + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + - name: Install GitHub Copilot CLI + run: /opt/gh-aw/actions/install_copilot_cli.sh 0.0.412 + - name: Install awf binary + run: bash /opt/gh-aw/actions/install_awf_binary.sh v0.20.2 + - name: Determine automatic lockdown mode for GitHub MCP Server + id: determine-automatic-lockdown + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} + GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} + with: + script: | + 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.20.2 ghcr.io/github/gh-aw-firewall/api-proxy:0.20.2 ghcr.io/github/gh-aw-firewall/squid:0.20.2 ghcr.io/github/gh-aw-mcpg:v0.1.4 ghcr.io/github/github-mcp-server:v0.31.0 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' + {"create_issue":{"expires":168,"max":1},"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 \"[docs-patrol] \".", + "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": "Report that a tool or capability needed to complete the task is not available, or share any information you deem important about missing functionality or limitations. Use this when you cannot accomplish what was requested because the required functionality is missing or access is restricted.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "alternatives": { + "description": "Any workarounds, manual steps, or alternative approaches the user could take (max 256 characters).", + "type": "string" + }, + "reason": { + "description": "Explanation of why this tool is needed or what information you want to share about the limitation (max 256 characters).", + "type": "string" + }, + "tool": { + "description": "Optional: Name or description of the missing tool or capability (max 128 characters). Be specific about what functionality is needed.", + "type": "string" + } + }, + "required": [ + "reason" + ], + "type": "object" + }, + "name": "missing_tool" + }, + { + "description": "Log a transparency message when no significant actions are needed. Use this to confirm workflow completion and provide visibility when analysis is complete but no changes or outputs are required (e.g., 'No issues found', 'All checks passed'). This ensures the workflow produces human-visible output even when no other actions are taken.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "message": { + "description": "Status or completion message to log. Should explain what was analyzed and the outcome (e.g., 'Code review complete - no issues found', 'Analysis complete - all tests passing').", + "type": "string" + } + }, + "required": [ + "message" + ], + "type": "object" + }, + "name": "noop" + }, + { + "description": "Report that data or information needed to complete the task is not available. Use this when you cannot accomplish what was requested because required data, context, or information is missing.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "alternatives": { + "description": "Any workarounds, manual steps, or alternative approaches the user could take (max 256 characters).", + "type": "string" + }, + "context": { + "description": "Additional context about the missing data or where it should come from (max 256 characters).", + "type": "string" + }, + "data_type": { + "description": "Type or description of the missing data or information (max 128 characters). Be specific about what data is needed.", + "type": "string" + }, + "reason": { + "description": "Explanation of why this data is needed to complete the task (max 256 characters).", + "type": "string" + } + }, + "required": [], + "type": "object" + }, + "name": "missing_data" + } + ] + GH_AW_SAFE_OUTPUTS_TOOLS_EOF + cat > /opt/gh-aw/safeoutputs/validation.json << 'GH_AW_SAFE_OUTPUTS_VALIDATION_EOF' + { + "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_data": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "context": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "data_type": { + "type": "string", + "sanitize": true, + "maxLength": 128 + }, + "reason": { + "type": "string", + "sanitize": true, + "maxLength": 256 + } + } + }, + "missing_tool": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 512 + }, + "reason": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "tool": { + "type": "string", + "sanitize": true, + "maxLength": 128 + } + } + }, + "noop": { + "defaultMax": 1, + "fields": { + "message": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + } + } + } + } + GH_AW_SAFE_OUTPUTS_VALIDATION_EOF + - name: Generate Safe Outputs MCP Server Config + id: safe-outputs-config + run: | + # Generate a secure random API key (360 bits of entropy, 40+ chars) + # Mask immediately to prevent timing vulnerabilities + API_KEY=$(openssl rand -base64 45 | tr -d '/+=') + echo "::add-mask::${API_KEY}" + + PORT=3001 + + # Set outputs for next steps + { + echo "safe_outputs_api_key=${API_KEY}" + echo "safe_outputs_port=${PORT}" + } >> "$GITHUB_OUTPUT" + + echo "Safe Outputs MCP server will run on port ${PORT}" + + - name: Start Safe Outputs MCP HTTP Server + id: safe-outputs-start + env: + DEBUG: '*' + GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-config.outputs.safe_outputs_port }} + GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-config.outputs.safe_outputs_api_key }} + GH_AW_SAFE_OUTPUTS_TOOLS_PATH: /opt/gh-aw/safeoutputs/tools.json + GH_AW_SAFE_OUTPUTS_CONFIG_PATH: /opt/gh-aw/safeoutputs/config.json + GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs + run: | + # Environment variables are set above to prevent template injection + export DEBUG + export GH_AW_SAFE_OUTPUTS_PORT + export GH_AW_SAFE_OUTPUTS_API_KEY + export GH_AW_SAFE_OUTPUTS_TOOLS_PATH + export GH_AW_SAFE_OUTPUTS_CONFIG_PATH + export GH_AW_MCP_LOG_DIR + + bash /opt/gh-aw/actions/start_safe_outputs_server.sh + + - name: Start MCP Gateway + id: start-mcp-gateway + env: + GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} + GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-start.outputs.api_key }} + GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-start.outputs.port }} + GITHUB_MCP_LOCKDOWN: ${{ steps.determine-automatic-lockdown.outputs.lockdown == 'true' && '1' || '0' }} + GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + run: | + set -eo pipefail + mkdir -p /tmp/gh-aw/mcp-config + + # Export gateway environment variables for MCP config and gateway script + export MCP_GATEWAY_PORT="80" + export MCP_GATEWAY_DOMAIN="host.docker.internal" + MCP_GATEWAY_API_KEY=$(openssl rand -base64 45 | tr -d '/+=') + echo "::add-mask::${MCP_GATEWAY_API_KEY}" + export MCP_GATEWAY_API_KEY + export MCP_GATEWAY_PAYLOAD_DIR="/tmp/gh-aw/mcp-payloads" + mkdir -p "${MCP_GATEWAY_PAYLOAD_DIR}" + export DEBUG="*" + + export GH_AW_ENGINE="copilot" + 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 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_LOCKDOWN -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.1.4' + + mkdir -p /home/runner/.copilot + cat << GH_AW_MCP_CONFIG_EOF | bash /opt/gh-aw/actions/start_mcp_gateway.sh + { + "mcpServers": { + "agents-md-generator": { + "type": "http", + "url": "https://agents-md-generator.fastmcp.app/mcp", + "tools": [ + "generate_agents_md" + ] + }, + "github": { + "type": "stdio", + "container": "ghcr.io/github/github-mcp-server:v0.31.0", + "env": { + "GITHUB_LOCKDOWN_MODE": "$GITHUB_MCP_LOCKDOWN", + "GITHUB_PERSONAL_ACCESS_TOKEN": "\${GITHUB_MCP_SERVER_TOKEN}", + "GITHUB_READ_ONLY": "1", + "GITHUB_TOOLSETS": "repos,issues,pull_requests,search" + } + }, + "public-code-search": { + "type": "http", + "url": "https://public-code-search.fastmcp.app/mcp", + "tools": [ + "search_code" + ] + }, + "safeoutputs": { + "type": "http", + "url": "http://host.docker.internal:$GH_AW_SAFE_OUTPUTS_PORT", + "headers": { + "Authorization": "\${GH_AW_SAFE_OUTPUTS_API_KEY}" + } + } + }, + "gateway": { + "port": $MCP_GATEWAY_PORT, + "domain": "${MCP_GATEWAY_DOMAIN}", + "apiKey": "${MCP_GATEWAY_API_KEY}", + "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" + } + } + GH_AW_MCP_CONFIG_EOF + - name: Generate workflow overview + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + with: + script: | + const { generateWorkflowOverview } = require('/opt/gh-aw/actions/generate_workflow_overview.cjs'); + await generateWorkflowOverview(core); + - name: Download prompt artifact + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 + with: + name: prompt + path: /tmp/gh-aw/aw-prompts + - name: Clean git credentials + run: bash /opt/gh-aw/actions/clean_git_credentials.sh + - name: Execute GitHub Copilot CLI + id: agentic_execution + # Copilot CLI tool arguments (sorted): + timeout-minutes: 90 + run: | + set -o pipefail + sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --allow-domains '*.githubusercontent.com,*.jsr.io,*.pythonhosted.org,*.rvm.io,agents-md-generator.fastmcp.app,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.rubygems.org,api.snapcraft.io,archive.ubuntu.com,artifacts.elastic.co,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,bun.sh,bundler.rubygems.org,cache.ruby-lang.org,cdn.jsdelivr.net,cloud.elastic.co,codeload.github.com,conda.anaconda.org,conda.binstar.org,crates.io,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,deb.nodesource.com,deno.land,ela.st,elastic.co,esm.sh,files.pythonhosted.org,gems.rubyforge.org,gems.rubyonrails.org,get.pnpm.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,host.docker.internal,index.crates.io,index.rubygems.org,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,lfs.github.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,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,pip.pypa.io,pkg.go.dev,ppa.launchpad.net,proxy.golang.org,public-code-search.fastmcp.app,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.bower.io,registry.npmjs.com,registry.npmjs.org,registry.yarnpkg.com,repo.anaconda.com,repo.continuum.io,repo.yarnpkg.com,rubygems.org,rubygems.pkg.github.com,s.symcb.com,s.symcd.com,security.ubuntu.com,skimdb.npmjs.com,static.crates.io,storage.googleapis.com,sum.golang.org,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.elastic.co,www.npmjs.com,www.npmjs.org,yarnpkg.com' --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.20.2 --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 --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log + env: + COPILOT_AGENT_RUNNER_TYPE: STANDALONE + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} + GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} + GITHUB_HEAD_REF: ${{ github.head_ref }} + GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + GITHUB_REF_NAME: ${{ github.ref_name }} + GITHUB_STEP_SUMMARY: ${{ env.GITHUB_STEP_SUMMARY }} + GITHUB_WORKSPACE: ${{ github.workspace }} + XDG_CONFIG_HOME: /home/runner + - name: Configure Git credentials + env: + REPO_NAME: ${{ github.repository }} + SERVER_URL: ${{ github.server_url }} + run: | + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git config --global user.name "github-actions[bot]" + # Re-authenticate git with GitHub token + SERVER_URL_STRIPPED="${SERVER_URL#https://}" + git remote set-url origin "https://x-access-token:${{ github.token }}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" + echo "Git configured with standard GitHub Actions identity" + - name: Copy Copilot session state files to logs + if: always() + continue-on-error: true + run: | + # Copy Copilot session state files to logs folder for artifact collection + # This ensures they are in /tmp/gh-aw/ where secret redaction can scan them + SESSION_STATE_DIR="$HOME/.copilot/session-state" + LOGS_DIR="/tmp/gh-aw/sandbox/agent/logs" + + if [ -d "$SESSION_STATE_DIR" ]; then + echo "Copying Copilot session state files from $SESSION_STATE_DIR to $LOGS_DIR" + mkdir -p "$LOGS_DIR" + cp -v "$SESSION_STATE_DIR"/*.jsonl "$LOGS_DIR/" 2>/dev/null || true + echo "Session state files copied successfully" + else + echo "No session-state directory found at $SESSION_STATE_DIR" + fi + - name: Stop MCP Gateway + if: always() + continue-on-error: true + env: + MCP_GATEWAY_PORT: ${{ steps.start-mcp-gateway.outputs.gateway-port }} + MCP_GATEWAY_API_KEY: ${{ steps.start-mcp-gateway.outputs.gateway-api-key }} + GATEWAY_PID: ${{ steps.start-mcp-gateway.outputs.gateway-pid }} + run: | + bash /opt/gh-aw/actions/stop_mcp_gateway.sh "$GATEWAY_PID" + - name: Redact secrets in logs + if: always() + 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/redact_secrets.cjs'); + await main(); + env: + GH_AW_SECRET_NAMES: 'COPILOT_GITHUB_TOKEN,GH_AW_GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,GITHUB_TOKEN' + SECRET_COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + SECRET_GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} + SECRET_GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} + SECRET_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Upload Safe Outputs + if: always() + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: safe-output + path: ${{ env.GH_AW_SAFE_OUTPUTS }} + if-no-files-found: warn + - name: Ingest agent output + id: collect_output + if: always() + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} + GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,*.jsr.io,*.pythonhosted.org,*.rvm.io,agents-md-generator.fastmcp.app,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.rubygems.org,api.snapcraft.io,archive.ubuntu.com,artifacts.elastic.co,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,bun.sh,bundler.rubygems.org,cache.ruby-lang.org,cdn.jsdelivr.net,cloud.elastic.co,codeload.github.com,conda.anaconda.org,conda.binstar.org,crates.io,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,deb.nodesource.com,deno.land,ela.st,elastic.co,esm.sh,files.pythonhosted.org,gems.rubyforge.org,gems.rubyonrails.org,get.pnpm.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,host.docker.internal,index.crates.io,index.rubygems.org,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,lfs.github.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,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,pip.pypa.io,pkg.go.dev,ppa.launchpad.net,proxy.golang.org,public-code-search.fastmcp.app,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.bower.io,registry.npmjs.com,registry.npmjs.org,registry.yarnpkg.com,repo.anaconda.com,repo.continuum.io,repo.yarnpkg.com,rubygems.org,rubygems.pkg.github.com,s.symcb.com,s.symcd.com,security.ubuntu.com,skimdb.npmjs.com,static.crates.io,storage.googleapis.com,sum.golang.org,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.elastic.co,www.npmjs.com,www.npmjs.org,yarnpkg.com" + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_API_URL: ${{ github.api_url }} + 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/collect_ndjson_output.cjs'); + await main(); + - name: Upload sanitized agent output + if: always() && env.GH_AW_AGENT_OUTPUT + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: agent-output + path: ${{ env.GH_AW_AGENT_OUTPUT }} + if-no-files-found: warn + - name: Upload engine output files + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: agent_outputs + path: | + /tmp/gh-aw/sandbox/agent/logs/ + /tmp/gh-aw/redacted-urls.log + if-no-files-found: ignore + - name: Parse agent logs for step summary + if: always() + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: /tmp/gh-aw/sandbox/agent/logs/ + 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/parse_copilot_log.cjs'); + await main(); + - name: Parse MCP Gateway logs for step summary + if: always() + 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/parse_mcp_gateway_log.cjs'); + await main(); + - name: Print firewall logs + if: always() + continue-on-error: true + env: + AWF_LOGS_DIR: /tmp/gh-aw/sandbox/firewall/logs + run: | + # Fix permissions on firewall logs so they can be uploaded as artifacts + # AWF runs with sudo, creating files owned by root + sudo chmod -R a+r /tmp/gh-aw/sandbox/firewall/logs 2>/dev/null || true + # Only run awf logs summary if awf command exists (it may not be installed if workflow failed before install step) + if command -v awf &> /dev/null; then + awf logs summary | tee -a "$GITHUB_STEP_SUMMARY" + else + echo 'AWF binary not installed, skipping firewall log summary' + fi + - name: Upload agent artifacts + if: always() + continue-on-error: true + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: agent-artifacts + path: | + /tmp/gh-aw/aw-prompts/prompt.txt + /tmp/gh-aw/aw_info.json + /tmp/gh-aw/mcp-logs/ + /tmp/gh-aw/sandbox/firewall/logs/ + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/agent/ + if-no-files-found: ignore + + conclusion: + needs: + - activation + - agent + - detection + - safe_outputs + if: (always()) && (needs.agent.result != 'skipped') + runs-on: ubuntu-slim + permissions: + contents: read + issues: write + outputs: + noop_message: ${{ steps.noop.outputs.noop_message }} + tools_reported: ${{ steps.missing_tool.outputs.tools_reported }} + total_count: ${{ steps.missing_tool.outputs.total_count }} + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 + with: + destination: /opt/gh-aw/actions + - name: Download agent output artifact + continue-on-error: true + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 + with: + name: agent-output + path: /tmp/gh-aw/safeoutputs/ + - name: Setup agent output environment variable + run: | + mkdir -p /tmp/gh-aw/safeoutputs/ + find "/tmp/gh-aw/safeoutputs/" -type f -print + echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/safeoutputs/agent_output.json" >> "$GITHUB_ENV" + - name: Process No-Op Messages + id: noop + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_NOOP_MAX: 1 + GH_AW_WORKFLOW_NAME: "Docs Patrol" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/noop.cjs'); + await main(); + - name: Record Missing Tool + id: missing_tool + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_WORKFLOW_NAME: "Docs Patrol" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/missing_tool.cjs'); + await main(); + - name: Handle Agent Failure + id: handle_agent_failure + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_WORKFLOW_NAME: "Docs Patrol" + 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: "gh-aw-docs-patrol" + GH_AW_SECRET_VERIFICATION_RESULT: ${{ needs.agent.outputs.secret_verification_result }} + GH_AW_CHECKOUT_PR_SUCCESS: ${{ needs.agent.outputs.checkout_pr_success }} + GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\"}" + GH_AW_GROUP_REPORTS: "false" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/handle_agent_failure.cjs'); + await main(); + - name: Handle No-Op Message + id: handle_noop_message + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_WORKFLOW_NAME: "Docs Patrol" + 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 }} + GH_AW_NOOP_REPORT_AS_ISSUE: "true" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/handle_noop_message.cjs'); + await main(); + + detection: + needs: agent + if: needs.agent.outputs.output_types != '' || needs.agent.outputs.has_patch == 'true' + runs-on: ubuntu-latest + permissions: {} + concurrency: + group: "gh-aw-copilot-${{ github.workflow }}" + timeout-minutes: 10 + outputs: + success: ${{ steps.parse_results.outputs.success }} + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 + with: + destination: /opt/gh-aw/actions + - name: Download agent artifacts + continue-on-error: true + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 + with: + name: agent-artifacts + path: /tmp/gh-aw/threat-detection/ + - name: Download agent output artifact + continue-on-error: true + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 + with: + name: agent-output + path: /tmp/gh-aw/threat-detection/ + - name: Print agent output types + env: + AGENT_OUTPUT_TYPES: ${{ needs.agent.outputs.output_types }} + run: | + echo "Agent output-types: $AGENT_OUTPUT_TYPES" + - name: Setup threat detection + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + WORKFLOW_NAME: "Docs Patrol" + WORKFLOW_DESCRIPTION: "Detect code changes that require documentation updates and file issues" + HAS_PATCH: ${{ needs.agent.outputs.has_patch }} + 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/setup_threat_detection.cjs'); + await main(); + - name: Ensure threat-detection directory and log + run: | + mkdir -p /tmp/gh-aw/threat-detection + touch /tmp/gh-aw/threat-detection/detection.log + - name: Validate COPILOT_GITHUB_TOKEN secret + id: validate-secret + run: /opt/gh-aw/actions/validate_multi_secret.sh COPILOT_GITHUB_TOKEN 'GitHub Copilot CLI' https://github.github.com/gh-aw/reference/engines/#github-copilot-default + env: + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + - name: Install GitHub Copilot CLI + run: /opt/gh-aw/actions/install_copilot_cli.sh 0.0.412 + - name: Execute GitHub Copilot CLI + id: agentic_execution + # Copilot CLI tool arguments (sorted): + # --allow-tool shell(cat) + # --allow-tool shell(grep) + # --allow-tool shell(head) + # --allow-tool shell(jq) + # --allow-tool shell(ls) + # --allow-tool shell(tail) + # --allow-tool shell(wc) + timeout-minutes: 20 + run: | + set -o pipefail + COPILOT_CLI_INSTRUCTION="$(cat /tmp/gh-aw/aw-prompts/prompt.txt)" + mkdir -p /tmp/ + mkdir -p /tmp/gh-aw/ + mkdir -p /tmp/gh-aw/agent/ + mkdir -p /tmp/gh-aw/sandbox/agent/logs/ + copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log + env: + COPILOT_AGENT_RUNNER_TYPE: STANDALONE + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GITHUB_HEAD_REF: ${{ github.head_ref }} + GITHUB_REF_NAME: ${{ github.ref_name }} + GITHUB_STEP_SUMMARY: ${{ env.GITHUB_STEP_SUMMARY }} + GITHUB_WORKSPACE: ${{ github.workspace }} + XDG_CONFIG_HOME: /home/runner + - name: Parse threat detection results + id: parse_results + 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/parse_threat_detection_results.cjs'); + await main(); + - name: Upload threat detection log + if: always() + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: threat-detection.log + path: /tmp/gh-aw/threat-detection/detection.log + if-no-files-found: ignore + + pre_activation: + runs-on: ubuntu-slim + outputs: + activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 + with: + destination: /opt/gh-aw/actions + - name: Check team membership for workflow + id: check_membership + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_REQUIRED_ROLES: admin,maintainer,write + GH_AW_ALLOWED_BOTS: ${{ inputs.allowed-bot-users }} + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + 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_membership.cjs'); + await main(); + + safe_outputs: + needs: + - agent + - detection + if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (needs.detection.outputs.success == 'true') + runs-on: ubuntu-slim + permissions: + contents: read + issues: write + timeout-minutes: 15 + env: + GH_AW_ENGINE_ID: "copilot" + GH_AW_ENGINE_MODEL: "${{ inputs.model }}" + GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\"}" + GH_AW_WORKFLOW_ID: "gh-aw-docs-patrol" + GH_AW_WORKFLOW_NAME: "Docs Patrol" + outputs: + create_discussion_error_count: ${{ steps.process_safe_outputs.outputs.create_discussion_error_count }} + create_discussion_errors: ${{ steps.process_safe_outputs.outputs.create_discussion_errors }} + process_safe_outputs_processed_count: ${{ steps.process_safe_outputs.outputs.processed_count }} + process_safe_outputs_temporary_id_map: ${{ steps.process_safe_outputs.outputs.temporary_id_map }} + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 + with: + destination: /opt/gh-aw/actions + - name: Download agent output artifact + continue-on-error: true + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 + with: + name: agent-output + path: /tmp/gh-aw/safeoutputs/ + - name: Setup agent output environment variable + run: | + mkdir -p /tmp/gh-aw/safeoutputs/ + find "/tmp/gh-aw/safeoutputs/" -type f -print + echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/safeoutputs/agent_output.json" >> "$GITHUB_ENV" + - name: Process Safe Outputs + id: process_safe_outputs + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_issue\":{\"close_older_issues\":true,\"expires\":168,\"max\":1,\"title_prefix\":\"[docs-patrol] \"},\"missing_data\":{},\"missing_tool\":{}}" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/safe_output_handler_manager.cjs'); + await main(); + - name: Upload safe output items manifest + if: always() + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: safe-output-items + path: /tmp/safe-output-items.jsonl + if-no-files-found: warn + diff --git a/.github/workflows/gh-aw-docs-drift.md b/.github/workflows/gh-aw-docs-patrol.md similarity index 94% rename from .github/workflows/gh-aw-docs-drift.md rename to .github/workflows/gh-aw-docs-patrol.md index eba9977f..3e88f87e 100644 --- a/.github/workflows/gh-aw-docs-drift.md +++ b/.github/workflows/gh-aw-docs-patrol.md @@ -1,5 +1,6 @@ --- -name: "Docs Drift" +inlined-imports: true +name: "Docs Patrol" description: "Detect code changes that require documentation updates and file issues" imports: - gh-aw-fragments/elastic-tools.md @@ -10,13 +11,18 @@ imports: - gh-aw-fragments/mcp-pagination.md - gh-aw-fragments/messages-footer.md - gh-aw-fragments/safe-output-create-issue.md - - gh-aw-fragments/scheduled-report.md + - gh-aw-fragments/scheduled-audit.md engine: id: copilot - model: gpt-5.3-codex + model: ${{ inputs.model }} on: workflow_call: inputs: + model: + description: "AI model to use" + type: string + required: false + default: "gpt-5.3-codex" additional-instructions: description: "Repo-specific instructions appended to the agent prompt" type: string @@ -49,7 +55,7 @@ on: bots: - "${{ inputs.allowed-bot-users }}" concurrency: - group: docs-drift + group: docs-patrol cancel-in-progress: true permissions: contents: read @@ -73,7 +79,7 @@ safe-outputs: noop: create-issue: max: 1 - title-prefix: "[docs-drift] " + title-prefix: "[docs-patrol] " close-older-issues: true expires: 7d timeout-minutes: 90 @@ -133,7 +139,7 @@ Do not file for: vague "could be improved" suggestions, minor wording drift, or ### Issue Format -**Issue title:** Brief summary of what's out of date (e.g., "Update README for new docs-drift workflow") +**Issue title:** Brief summary of what's out of date (e.g., "Update README for new CLI flag") **Issue body:** diff --git a/.github/workflows/gh-aw-docs-pr-review.lock.yml b/.github/workflows/gh-aw-docs-pr-review.lock.yml index 7c40b729..fbc91f19 100644 --- a/.github/workflows/gh-aw-docs-pr-review.lock.yml +++ b/.github/workflows/gh-aw-docs-pr-review.lock.yml @@ -34,7 +34,9 @@ # - gh-aw-fragments/safe-output-review-comment.md # - gh-aw-fragments/safe-output-submit-review.md # -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"f628edb14807296f4004e5d0d9e2befa60a9d7462759441eaee5c17f809d515d"} +# inlined-imports: true +# +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"b6bcd79c08619e7218ad4369f84c40e2185c566fe965fbe02be5cce63fd52f22"} name: "Docs PR Review" "on": @@ -71,6 +73,11 @@ name: "Docs PR Review" description: "Minimum severity for inline comments: critical, high, medium, low, or nitpick. Issues below this threshold go in a collapsible section of the review body instead." required: false type: string + model: + default: gpt-5.3-codex + description: AI model to use + required: false + type: string setup-commands: default: "" description: Shell commands to run before the agent starts (dependency install, build, etc.) @@ -100,7 +107,7 @@ jobs: comment_repo: "" steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Validate context variables @@ -181,6 +188,29 @@ jobs: **Critical**: Tool calls write structured data that downstream jobs process. Without tool calls, follow-up actions will be skipped. **Note**: If you made no other safe output tool calls during this workflow execution, call the "noop" tool to provide a status message indicating completion or that no actions were needed. + + --- + + ## Creating a Pull Request Review Comment, Submitting a Pull Request Review, Reporting Missing Tools or Functionality, Reporting Missing Data + + **IMPORTANT**: To perform the actions listed above, use the **safeoutputs** tools. Do NOT use `gh`, do NOT call the GitHub API directly. You do not have write access to the GitHub repository. + + **Creating a Pull Request Review Comment** + + To create a pull request review comment, use the create_pull_request_review_comment tool from safeoutputs. + + **Submitting a Pull Request Review** + + To submit a pull request review (APPROVE, REQUEST_CHANGES, or COMMENT), use the submit_pull_request_review tool from safeoutputs. + + **Reporting Missing Tools or Functionality** + + To report a missing tool or capability, use the missing_tool tool from safeoutputs. + + **Reporting Missing Data** + + To report missing data required to achieve a goal, use the missing_data tool from safeoutputs. + @@ -595,7 +625,7 @@ jobs: secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Checkout repository @@ -689,7 +719,7 @@ jobs: const awInfo = { engine_id: "copilot", engine_name: "GitHub Copilot CLI", - model: "gpt-5.3-codex", + model: "${{ inputs.model }}", version: "", agent_version: "0.0.412", workflow_name: "Docs PR Review", @@ -911,6 +941,10 @@ jobs: "required": true, "type": "string" }, + "repo": { + "type": "string", + "maxLength": 256 + }, "side": { "type": "string", "enum": [ @@ -924,6 +958,31 @@ jobs: }, "customValidation": "startLineLessOrEqualLine" }, + "missing_data": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "context": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "data_type": { + "type": "string", + "sanitize": true, + "maxLength": 128 + }, + "reason": { + "type": "string", + "sanitize": true, + "maxLength": 256 + } + } + }, "missing_tool": { "defaultMax": 20, "fields": { @@ -1116,10 +1175,11 @@ jobs: run: | set -o pipefail sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --allow-domains '*.githubusercontent.com,*.jsr.io,*.pythonhosted.org,*.rvm.io,agents-md-generator.fastmcp.app,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.rubygems.org,api.snapcraft.io,archive.ubuntu.com,artifacts.elastic.co,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,bun.sh,bundler.rubygems.org,cache.ruby-lang.org,cdn.jsdelivr.net,cloud.elastic.co,codeload.github.com,conda.anaconda.org,conda.binstar.org,crates.io,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,deb.nodesource.com,deno.land,docs-v3-preview.elastic.dev,ela.st,elastic.co,esm.sh,files.pythonhosted.org,gems.rubyforge.org,gems.rubyonrails.org,get.pnpm.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,host.docker.internal,index.crates.io,index.rubygems.org,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,lfs.github.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,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,pip.pypa.io,pkg.go.dev,ppa.launchpad.net,proxy.golang.org,public-code-search.fastmcp.app,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.bower.io,registry.npmjs.com,registry.npmjs.org,registry.yarnpkg.com,repo.anaconda.com,repo.continuum.io,repo.yarnpkg.com,rubygems.org,rubygems.pkg.github.com,s.symcb.com,s.symcd.com,security.ubuntu.com,skimdb.npmjs.com,static.crates.io,storage.googleapis.com,sum.golang.org,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.elastic.co,www.npmjs.com,www.npmjs.org,yarnpkg.com' --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.20.2 --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 --model gpt-5.3-codex --allow-all-tools --allow-all-paths --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log + -- /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 --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} @@ -1285,7 +1345,7 @@ jobs: total_count: ${{ steps.missing_tool.outputs.total_count }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent output artifact @@ -1376,7 +1436,7 @@ jobs: success: ${{ steps.parse_results.outputs.success }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent artifacts @@ -1437,10 +1497,11 @@ jobs: mkdir -p /tmp/gh-aw/ mkdir -p /tmp/gh-aw/agent/ mkdir -p /tmp/gh-aw/sandbox/agent/logs/ - copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --model gpt-5.3-codex --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log + copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_REF_NAME: ${{ github.ref_name }} @@ -1470,7 +1531,7 @@ jobs: activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Check team membership for workflow @@ -1499,7 +1560,7 @@ jobs: timeout-minutes: 15 env: GH_AW_ENGINE_ID: "copilot" - GH_AW_ENGINE_MODEL: "gpt-5.3-codex" + GH_AW_ENGINE_MODEL: "${{ inputs.model }}" GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\"}" GH_AW_WORKFLOW_ID: "gh-aw-docs-pr-review" GH_AW_WORKFLOW_NAME: "Docs PR Review" @@ -1510,7 +1571,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@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent output artifact diff --git a/.github/workflows/gh-aw-docs-pr-review.md b/.github/workflows/gh-aw-docs-pr-review.md index a1175496..1eabaa23 100644 --- a/.github/workflows/gh-aw-docs-pr-review.md +++ b/.github/workflows/gh-aw-docs-pr-review.md @@ -1,4 +1,5 @@ --- +inlined-imports: true name: "Docs PR Review" description: "Docs PR review from an Elastic technical writer perspective" imports: @@ -12,12 +13,17 @@ imports: - gh-aw-fragments/safe-output-submit-review.md engine: id: copilot - model: gpt-5.3-codex + model: ${{ inputs.model }} concurrency: group: "gh-aw-copilot-docs-pr-review-${{ github.event.pull_request.number }}" on: workflow_call: inputs: + model: + description: "AI model to use" + type: string + required: false + default: "gpt-5.3-codex" additional-instructions: description: "Repo-specific instructions appended to the agent prompt" type: string diff --git a/.github/workflows/gh-aw-downstream-health.lock.yml b/.github/workflows/gh-aw-downstream-health.lock.yml index a533bdd8..b48473e8 100644 --- a/.github/workflows/gh-aw-downstream-health.lock.yml +++ b/.github/workflows/gh-aw-downstream-health.lock.yml @@ -32,9 +32,11 @@ # - gh-aw-fragments/rigor.md # - gh-aw-fragments/runtime-setup.md # - gh-aw-fragments/safe-output-create-issue.md -# - gh-aw-fragments/scheduled-report.md +# - gh-aw-fragments/scheduled-audit.md # -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"aab6ee673263c7a7c0a34ee2666bbb3520614b781cbce51078f724070e19996f"} +# inlined-imports: true +# +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"690adae32c44740e440da80b9ba4ea9260c21892661324cc6478f3bb1545ab79"} name: "Downstream Health" "on": @@ -61,6 +63,11 @@ name: "Downstream Health" description: Footer appended to all agent comments and reviews required: false type: string + model: + default: gpt-5.3-codex + description: AI model to use + required: false + type: string setup-commands: default: "" description: Shell commands to run before the agent starts (dependency install, build, etc.) @@ -90,7 +97,7 @@ jobs: comment_repo: "" steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Validate context variables @@ -167,6 +174,25 @@ jobs: **Critical**: Tool calls write structured data that downstream jobs process. Without tool calls, follow-up actions will be skipped. **Note**: If you made no other safe output tool calls during this workflow execution, call the "noop" tool to provide a status message indicating completion or that no actions were needed. + + --- + + ## Creating an Issue, Reporting Missing Tools or Functionality, Reporting Missing Data + + **IMPORTANT**: To perform the actions listed above, use the **safeoutputs** tools. Do NOT use `gh`, do NOT call the GitHub API directly. You do not have write access to the GitHub repository. + + **Creating an Issue** + + To create an issue, use the create_issue tool from safeoutputs. + + **Reporting Missing Tools or Functionality** + + To report a missing tool or capability, use the missing_tool tool from safeoutputs. + + **Reporting Missing Data** + + To report missing data required to achieve a goal, use the missing_data tool from safeoutputs. + @@ -284,9 +310,7 @@ jobs: - **Mentions**: `@mentions` in the body are neutralized (backticked) by default. GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - # Scheduled Report Agent - - You are a report agent for __GH_AW_GITHUB_REPOSITORY__. You run on a schedule to investigate the repository and file an issue when something needs attention. Your specific assignment is described in the **Report Assignment** section below. + You are an agent for __GH_AW_GITHUB_REPOSITORY__. You run on a schedule to investigate the repository and file an issue when something needs attention. Your specific assignment is described in the **Report Assignment** section below. ## Context @@ -350,7 +374,7 @@ jobs: - Make suggested actions concrete enough to act on without re-investigating - If a finding is ambiguous, it does not pass the quality gate — drop it - ## Report Assignment + **Report Assignment:** GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" @@ -566,7 +590,7 @@ jobs: secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Checkout repository @@ -660,7 +684,7 @@ jobs: const awInfo = { engine_id: "copilot", engine_name: "GitHub Copilot CLI", - model: "gpt-5.3-codex", + model: "${{ inputs.model }}", version: "", agent_version: "0.0.412", workflow_name: "Downstream Health", @@ -871,6 +895,31 @@ jobs: } } }, + "missing_data": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "context": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "data_type": { + "type": "string", + "sanitize": true, + "maxLength": 128 + }, + "reason": { + "type": "string", + "sanitize": true, + "maxLength": 256 + } + } + }, "missing_tool": { "defaultMax": 20, "fields": { @@ -1032,10 +1081,11 @@ jobs: run: | set -o pipefail sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --allow-domains '*.githubusercontent.com,*.jsr.io,*.pythonhosted.org,*.rvm.io,agents-md-generator.fastmcp.app,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.rubygems.org,api.snapcraft.io,archive.ubuntu.com,artifacts.elastic.co,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,bun.sh,bundler.rubygems.org,cache.ruby-lang.org,cdn.jsdelivr.net,cloud.elastic.co,codeload.github.com,conda.anaconda.org,conda.binstar.org,crates.io,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,deb.nodesource.com,deno.land,ela.st,elastic.co,esm.sh,files.pythonhosted.org,gems.rubyforge.org,gems.rubyonrails.org,get.pnpm.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,host.docker.internal,index.crates.io,index.rubygems.org,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,lfs.github.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,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,pip.pypa.io,pkg.go.dev,ppa.launchpad.net,proxy.golang.org,public-code-search.fastmcp.app,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.bower.io,registry.npmjs.com,registry.npmjs.org,registry.yarnpkg.com,repo.anaconda.com,repo.continuum.io,repo.yarnpkg.com,rubygems.org,rubygems.pkg.github.com,s.symcb.com,s.symcd.com,security.ubuntu.com,skimdb.npmjs.com,static.crates.io,storage.googleapis.com,sum.golang.org,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.elastic.co,www.npmjs.com,www.npmjs.org,yarnpkg.com' --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.20.2 --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 --model gpt-5.3-codex --allow-all-tools --allow-all-paths --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log + -- /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 --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} @@ -1201,7 +1251,7 @@ jobs: total_count: ${{ steps.missing_tool.outputs.total_count }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent output artifact @@ -1292,7 +1342,7 @@ jobs: success: ${{ steps.parse_results.outputs.success }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent artifacts @@ -1353,10 +1403,11 @@ jobs: mkdir -p /tmp/gh-aw/ mkdir -p /tmp/gh-aw/agent/ mkdir -p /tmp/gh-aw/sandbox/agent/logs/ - copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --model gpt-5.3-codex --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log + copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_REF_NAME: ${{ github.ref_name }} @@ -1386,7 +1437,7 @@ jobs: activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Check team membership for workflow @@ -1415,7 +1466,7 @@ jobs: timeout-minutes: 15 env: GH_AW_ENGINE_ID: "copilot" - GH_AW_ENGINE_MODEL: "gpt-5.3-codex" + GH_AW_ENGINE_MODEL: "${{ inputs.model }}" GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\"}" GH_AW_WORKFLOW_ID: "gh-aw-downstream-health" GH_AW_WORKFLOW_NAME: "Downstream Health" @@ -1426,7 +1477,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@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent output artifact diff --git a/.github/workflows/gh-aw-downstream-health.md b/.github/workflows/gh-aw-downstream-health.md index 87161527..7069c029 100644 --- a/.github/workflows/gh-aw-downstream-health.md +++ b/.github/workflows/gh-aw-downstream-health.md @@ -1,4 +1,5 @@ --- +inlined-imports: true name: "Downstream Health" description: "Monitor downstream repositories using AI workflows and report quality issues" imports: @@ -9,13 +10,18 @@ imports: - gh-aw-fragments/mcp-pagination.md - gh-aw-fragments/messages-footer.md - gh-aw-fragments/safe-output-create-issue.md - - gh-aw-fragments/scheduled-report.md + - gh-aw-fragments/scheduled-audit.md engine: id: copilot - model: gpt-5.3-codex + model: ${{ inputs.model }} on: workflow_call: inputs: + model: + description: "AI model to use" + type: string + required: false + default: "gpt-5.3-codex" additional-instructions: description: "Repo-specific instructions appended to the agent prompt" type: string diff --git a/.github/workflows/gh-aw-duplicate-issue-detector.lock.yml b/.github/workflows/gh-aw-duplicate-issue-detector.lock.yml index 5beee7fe..c94f5ec7 100644 --- a/.github/workflows/gh-aw-duplicate-issue-detector.lock.yml +++ b/.github/workflows/gh-aw-duplicate-issue-detector.lock.yml @@ -32,7 +32,9 @@ # - gh-aw-fragments/rigor.md # - gh-aw-fragments/safe-output-add-comment.md # -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"f5abc3ea0dd624459275726bbbdad68705d7273e78bd85f59bc77568174b5762"} +# inlined-imports: true +# +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"a42e6db2bc4a150c439e71c44d24fe9ca2e3ff4bed1b9ec5e4c9ecdd2ee278d0"} name: "Duplicate Issue Detector" "on": @@ -64,6 +66,11 @@ name: "Duplicate Issue Detector" description: Footer appended to all agent comments and reviews required: false type: string + model: + default: gpt-5.3-codex + description: AI model to use + required: false + type: string secrets: COPILOT_GITHUB_TOKEN: required: true @@ -91,7 +98,7 @@ jobs: title: ${{ steps.sanitized.outputs.title }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Validate context variables @@ -179,6 +186,25 @@ jobs: **Critical**: Tool calls write structured data that downstream jobs process. Without tool calls, follow-up actions will be skipped. **Note**: If you made no other safe output tool calls during this workflow execution, call the "noop" tool to provide a status message indicating completion or that no actions were needed. + + --- + + ## Adding a Comment to an Issue or Pull Request, Reporting Missing Tools or Functionality, Reporting Missing Data + + **IMPORTANT**: To perform the actions listed above, use the **safeoutputs** tools. Do NOT use `gh`, do NOT call the GitHub API directly. You do not have write access to the GitHub repository. + + **Adding a Comment to an Issue or Pull Request** + + To add a comment to an issue or pull request, use the add_comment tool from safeoutputs. + + **Reporting Missing Tools or Functionality** + + To report a missing tool or capability, use the missing_tool tool from safeoutputs. + + **Reporting Missing Data** + + To report missing data required to achieve a goal, use the missing_data tool from safeoutputs. + @@ -487,7 +513,7 @@ jobs: secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Checkout repository @@ -531,7 +557,7 @@ jobs: const awInfo = { engine_id: "copilot", engine_name: "GitHub Copilot CLI", - model: "gpt-5.3-codex", + model: "${{ inputs.model }}", version: "", agent_version: "0.0.412", workflow_name: "Duplicate Issue Detector", @@ -605,7 +631,7 @@ jobs: "type": "string" }, "item_number": { - "description": "The issue, pull request, or discussion number to comment on. This is the numeric ID from the GitHub URL (e.g., 123 in github.com/owner/repo/issues/123). If omitted, the tool will attempt to resolve the target from the current workflow context (triggering issue, PR, or discussion).", + "description": "The issue, pull request, or discussion number to comment on. This is the numeric ID from the GitHub URL (e.g., 123 in github.com/owner/repo/issues/123). If omitted, the tool auto-targets the issue, PR, or discussion that triggered this workflow. Auto-targeting only works for issue, pull_request, discussion, and comment event triggers — it does NOT work for schedule, workflow_dispatch, push, or workflow_run triggers. For those trigger types, always provide item_number explicitly, or the comment will be silently discarded.", "type": "number" } }, @@ -700,6 +726,35 @@ jobs: }, "item_number": { "issueOrPRNumber": true + }, + "repo": { + "type": "string", + "maxLength": 256 + } + } + }, + "missing_data": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "context": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "data_type": { + "type": "string", + "sanitize": true, + "maxLength": 128 + }, + "reason": { + "type": "string", + "sanitize": true, + "maxLength": 256 } } }, @@ -864,10 +919,11 @@ jobs: run: | set -o pipefail sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --allow-domains agents-md-generator.fastmcp.app,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,artifacts.elastic.co,azure.archive.ubuntu.com,cloud.elastic.co,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,ela.st,elastic.co,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,public-code-search.fastmcp.app,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.elastic.co --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.20.2 --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 --model gpt-5.3-codex --allow-all-tools --allow-all-paths --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log + -- /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 --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} @@ -1034,7 +1090,7 @@ jobs: total_count: ${{ steps.missing_tool.outputs.total_count }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent output artifact @@ -1125,7 +1181,7 @@ jobs: success: ${{ steps.parse_results.outputs.success }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent artifacts @@ -1186,10 +1242,11 @@ jobs: mkdir -p /tmp/gh-aw/ mkdir -p /tmp/gh-aw/agent/ mkdir -p /tmp/gh-aw/sandbox/agent/logs/ - copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --model gpt-5.3-codex --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log + copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_REF_NAME: ${{ github.ref_name }} @@ -1219,7 +1276,7 @@ jobs: activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Check team membership for workflow @@ -1249,7 +1306,7 @@ jobs: timeout-minutes: 15 env: GH_AW_ENGINE_ID: "copilot" - GH_AW_ENGINE_MODEL: "gpt-5.3-codex" + GH_AW_ENGINE_MODEL: "${{ inputs.model }}" GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\"}" GH_AW_WORKFLOW_ID: "gh-aw-duplicate-issue-detector" GH_AW_WORKFLOW_NAME: "Duplicate Issue Detector" @@ -1260,7 +1317,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@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent output artifact diff --git a/.github/workflows/gh-aw-duplicate-issue-detector.md b/.github/workflows/gh-aw-duplicate-issue-detector.md index 49c29e7e..42eeab27 100644 --- a/.github/workflows/gh-aw-duplicate-issue-detector.md +++ b/.github/workflows/gh-aw-duplicate-issue-detector.md @@ -1,4 +1,5 @@ --- +inlined-imports: true description: "Detect duplicate issues and notify reporters when a matching open or closed issue exists" imports: - gh-aw-fragments/elastic-tools.md @@ -9,12 +10,17 @@ imports: - gh-aw-fragments/safe-output-add-comment.md engine: id: copilot - model: gpt-5.3-codex + model: ${{ inputs.model }} concurrency: group: "gh-aw-copilot-duplicate-issue-detector-${{ github.event.issue.number }}" on: workflow_call: inputs: + model: + description: "AI model to use" + type: string + required: false + default: "gpt-5.3-codex" additional-instructions: description: "Repo-specific instructions appended to the agent prompt" type: string diff --git a/.github/workflows/gh-aw-flaky-test-triage.lock.yml b/.github/workflows/gh-aw-flaky-test-investigator.lock.yml similarity index 94% rename from .github/workflows/gh-aw-flaky-test-triage.lock.yml rename to .github/workflows/gh-aw-flaky-test-investigator.lock.yml index 304540e1..d1979f6a 100644 --- a/.github/workflows/gh-aw-flaky-test-triage.lock.yml +++ b/.github/workflows/gh-aw-flaky-test-investigator.lock.yml @@ -32,12 +32,14 @@ # - gh-aw-fragments/rigor.md # - gh-aw-fragments/runtime-setup.md # - gh-aw-fragments/safe-output-create-issue.md -# - gh-aw-fragments/scheduled-report.md +# - gh-aw-fragments/scheduled-audit.md # - gh-aw-fragments/workflow-edit-guardrails.md # -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"9822175a557aec475463ebeb16f3b0473ce046563452b1e26e6a10c75b4afd46"} +# inlined-imports: true +# +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"c57800689f45c5797e4b8d101c9679d53ff1ac7492df7d02953e959811459a7f"} -name: "Flaky Test Triage" +name: "Flaky Test Investigator" "on": # bots: # Bots processed as bot check in pre-activation job # - ${{ inputs.allowed-bot-users }} # Bots processed as bot check in pre-activation job @@ -62,6 +64,11 @@ name: "Flaky Test Triage" description: Footer appended to all agent comments and reviews required: false type: string + model: + default: gpt-5.3-codex + description: AI model to use + required: false + type: string setup-commands: default: "" description: Shell commands to run before the agent starts (dependency install, build, etc.) @@ -75,9 +82,9 @@ permissions: {} concurrency: cancel-in-progress: true - group: flaky-test-triage + group: flaky-test-investigator -run-name: "Flaky Test Triage" +run-name: "Flaky Test Investigator" jobs: activation: @@ -91,7 +98,7 @@ jobs: comment_repo: "" steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Validate context variables @@ -113,7 +120,7 @@ jobs: - name: Check workflow file timestamps uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: - GH_AW_WORKFLOW_FILE: "gh-aw-flaky-test-triage.lock.yml" + GH_AW_WORKFLOW_FILE: "gh-aw-flaky-test-investigator.lock.yml" with: script: | const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); @@ -168,6 +175,25 @@ jobs: **Critical**: Tool calls write structured data that downstream jobs process. Without tool calls, follow-up actions will be skipped. **Note**: If you made no other safe output tool calls during this workflow execution, call the "noop" tool to provide a status message indicating completion or that no actions were needed. + + --- + + ## Creating an Issue, Reporting Missing Tools or Functionality, Reporting Missing Data + + **IMPORTANT**: To perform the actions listed above, use the **safeoutputs** tools. Do NOT use `gh`, do NOT call the GitHub API directly. You do not have write access to the GitHub repository. + + **Creating an Issue** + + To create an issue, use the create_issue tool from safeoutputs. + + **Reporting Missing Tools or Functionality** + + To report a missing tool or capability, use the missing_tool tool from safeoutputs. + + **Reporting Missing Data** + + To report missing data required to achieve a goal, use the missing_data tool from safeoutputs. + @@ -292,9 +318,7 @@ jobs: - **Mentions**: `@mentions` in the body are neutralized (backticked) by default. GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - # Scheduled Report Agent - - You are a report agent for __GH_AW_GITHUB_REPOSITORY__. You run on a schedule to investigate the repository and file an issue when something needs attention. Your specific assignment is described in the **Report Assignment** section below. + You are an agent for __GH_AW_GITHUB_REPOSITORY__. You run on a schedule to investigate the repository and file an issue when something needs attention. Your specific assignment is described in the **Report Assignment** section below. ## Context @@ -358,7 +382,7 @@ jobs: - Make suggested actions concrete enough to act on without re-investigating - If a finding is ambiguous, it does not pass the quality gate — drop it - ## Report Assignment + **Report Assignment:** GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" @@ -405,11 +429,11 @@ jobs: ### Issue Format - **Issue title:** Brief flaky-test triage summary for the window + **Issue title:** Brief flaky-test investigation summary for the window **Issue body:** - > ## Flaky Test Triage Report + > ## Flaky Test Investigation Report > > **Window:** [date range analyzed] > @@ -516,7 +540,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: ghawflakytesttriage + GH_AW_WORKFLOW_ID_SANITIZED: ghawflakytestinvestigator outputs: checkout_pr_success: ${{ steps.checkout-pr.outputs.checkout_pr_success || 'true' }} has_patch: ${{ steps.collect_output.outputs.has_patch }} @@ -526,7 +550,7 @@ jobs: secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Checkout repository @@ -620,10 +644,10 @@ jobs: const awInfo = { engine_id: "copilot", engine_name: "GitHub Copilot CLI", - model: "gpt-5.3-codex", + model: "${{ inputs.model }}", version: "", agent_version: "0.0.412", - workflow_name: "Flaky Test Triage", + workflow_name: "Flaky Test Investigator", experimental: false, supports_tools_allowlist: true, run_id: context.runId, @@ -685,7 +709,7 @@ jobs: 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 \"[flaky-test-triage] \".", + "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 \"[flaky-test-investigator] \".", "inputSchema": { "additionalProperties": false, "properties": { @@ -831,6 +855,31 @@ jobs: } } }, + "missing_data": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "context": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "data_type": { + "type": "string", + "sanitize": true, + "maxLength": 128 + }, + "reason": { + "type": "string", + "sanitize": true, + "maxLength": 256 + } + } + }, "missing_tool": { "defaultMax": 20, "fields": { @@ -992,10 +1041,11 @@ jobs: run: | set -o pipefail sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --allow-domains '*.githubusercontent.com,agents-md-generator.fastmcp.app,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,artifacts.elastic.co,azure.archive.ubuntu.com,cloud.elastic.co,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,ela.st,elastic.co,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,public-code-search.fastmcp.app,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.elastic.co' --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.20.2 --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 --model gpt-5.3-codex --allow-all-tools --allow-all-paths --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log + -- /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 --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} @@ -1161,7 +1211,7 @@ jobs: total_count: ${{ steps.missing_tool.outputs.total_count }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent output artifact @@ -1181,7 +1231,7 @@ jobs: env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} GH_AW_NOOP_MAX: 1 - GH_AW_WORKFLOW_NAME: "Flaky Test Triage" + GH_AW_WORKFLOW_NAME: "Flaky Test Investigator" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | @@ -1194,7 +1244,7 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_WORKFLOW_NAME: "Flaky Test Triage" + GH_AW_WORKFLOW_NAME: "Flaky Test Investigator" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | @@ -1207,10 +1257,10 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_WORKFLOW_NAME: "Flaky Test Triage" + GH_AW_WORKFLOW_NAME: "Flaky Test Investigator" 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: "gh-aw-flaky-test-triage" + GH_AW_WORKFLOW_ID: "gh-aw-flaky-test-investigator" GH_AW_SECRET_VERIFICATION_RESULT: ${{ needs.agent.outputs.secret_verification_result }} GH_AW_CHECKOUT_PR_SUCCESS: ${{ needs.agent.outputs.checkout_pr_success }} GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\"}" @@ -1227,7 +1277,7 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_WORKFLOW_NAME: "Flaky Test Triage" + GH_AW_WORKFLOW_NAME: "Flaky Test Investigator" 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 }} @@ -1252,7 +1302,7 @@ jobs: success: ${{ steps.parse_results.outputs.success }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent artifacts @@ -1275,7 +1325,7 @@ jobs: - name: Setup threat detection uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: - WORKFLOW_NAME: "Flaky Test Triage" + WORKFLOW_NAME: "Flaky Test Investigator" WORKFLOW_DESCRIPTION: "Investigate flaky tests from issues and failed CI runs; file triage reports" HAS_PATCH: ${{ needs.agent.outputs.has_patch }} with: @@ -1313,10 +1363,11 @@ jobs: mkdir -p /tmp/gh-aw/ mkdir -p /tmp/gh-aw/agent/ mkdir -p /tmp/gh-aw/sandbox/agent/logs/ - copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --model gpt-5.3-codex --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log + copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_REF_NAME: ${{ github.ref_name }} @@ -1346,7 +1397,7 @@ jobs: activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Check team membership for workflow @@ -1375,10 +1426,10 @@ jobs: timeout-minutes: 15 env: GH_AW_ENGINE_ID: "copilot" - GH_AW_ENGINE_MODEL: "gpt-5.3-codex" + GH_AW_ENGINE_MODEL: "${{ inputs.model }}" GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\"}" - GH_AW_WORKFLOW_ID: "gh-aw-flaky-test-triage" - GH_AW_WORKFLOW_NAME: "Flaky Test Triage" + GH_AW_WORKFLOW_ID: "gh-aw-flaky-test-investigator" + GH_AW_WORKFLOW_NAME: "Flaky Test Investigator" outputs: create_discussion_error_count: ${{ steps.process_safe_outputs.outputs.create_discussion_error_count }} create_discussion_errors: ${{ steps.process_safe_outputs.outputs.create_discussion_errors }} @@ -1386,7 +1437,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@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent output artifact @@ -1405,7 +1456,7 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_issue\":{\"close_older_issues\":true,\"expires\":168,\"max\":1,\"title_prefix\":\"[flaky-test-triage] \"},\"missing_data\":{},\"missing_tool\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_issue\":{\"close_older_issues\":true,\"expires\":168,\"max\":1,\"title_prefix\":\"[flaky-test-investigator] \"},\"missing_data\":{},\"missing_tool\":{}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/gh-aw-flaky-test-triage.md b/.github/workflows/gh-aw-flaky-test-investigator.md similarity index 91% rename from .github/workflows/gh-aw-flaky-test-triage.md rename to .github/workflows/gh-aw-flaky-test-investigator.md index f309118b..b45000e5 100644 --- a/.github/workflows/gh-aw-flaky-test-triage.md +++ b/.github/workflows/gh-aw-flaky-test-investigator.md @@ -1,5 +1,6 @@ --- -name: "Flaky Test Triage" +inlined-imports: true +name: "Flaky Test Investigator" description: "Investigate flaky tests from issues and failed CI runs; file triage reports" imports: - gh-aw-fragments/elastic-tools.md @@ -10,13 +11,18 @@ imports: - gh-aw-fragments/workflow-edit-guardrails.md - gh-aw-fragments/messages-footer.md - gh-aw-fragments/safe-output-create-issue.md - - gh-aw-fragments/scheduled-report.md + - gh-aw-fragments/scheduled-audit.md engine: id: copilot - model: gpt-5.3-codex + model: ${{ inputs.model }} on: workflow_call: inputs: + model: + description: "AI model to use" + type: string + required: false + default: "gpt-5.3-codex" additional-instructions: description: "Repo-specific instructions appended to the agent prompt" type: string @@ -44,7 +50,7 @@ on: bots: - "${{ inputs.allowed-bot-users }}" concurrency: - group: flaky-test-triage + group: flaky-test-investigator cancel-in-progress: true permissions: actions: read @@ -65,7 +71,7 @@ safe-outputs: noop: create-issue: max: 1 - title-prefix: "[flaky-test-triage] " + title-prefix: "[flaky-test-investigator] " close-older-issues: true expires: 7d timeout-minutes: 90 @@ -120,11 +126,11 @@ Call `noop` when: ### Issue Format -**Issue title:** Brief flaky-test triage summary for the window +**Issue title:** Brief flaky-test investigation summary for the window **Issue body:** -> ## Flaky Test Triage Report +> ## Flaky Test Investigation Report > > **Window:** [date range analyzed] > diff --git a/.github/workflows/gh-aw-fragments/scheduled-report.md b/.github/workflows/gh-aw-fragments/scheduled-audit.md similarity index 89% rename from .github/workflows/gh-aw-fragments/scheduled-report.md rename to .github/workflows/gh-aw-fragments/scheduled-audit.md index b61c57a7..0b64d129 100644 --- a/.github/workflows/gh-aw-fragments/scheduled-report.md +++ b/.github/workflows/gh-aw-fragments/scheduled-audit.md @@ -1,6 +1,4 @@ -# Scheduled Report Agent - -You are a report agent for ${{ github.repository }}. You run on a schedule to investigate the repository and file an issue when something needs attention. Your specific assignment is described in the **Report Assignment** section below. +You are an agent for ${{ github.repository }}. You run on a schedule to investigate the repository and file an issue when something needs attention. Your specific assignment is described in the **Report Assignment** section below. ## Context @@ -64,4 +62,4 @@ If there are findings that pass the quality gate, call `create_issue` with a str - Make suggested actions concrete enough to act on without re-investigating - If a finding is ambiguous, it does not pass the quality gate — drop it -## Report Assignment +**Report Assignment:** diff --git a/.github/workflows/gh-aw-fragments/scheduled-fix.md b/.github/workflows/gh-aw-fragments/scheduled-fix.md new file mode 100644 index 00000000..18440ce7 --- /dev/null +++ b/.github/workflows/gh-aw-fragments/scheduled-fix.md @@ -0,0 +1,61 @@ +You are an agent for ${{ github.repository }}. You run on a schedule to pick up an open issue and create a focused pull request that addresses it. Your specific assignment is described in the **Fix Assignment** section below. + +## Context + +- **Repository**: ${{ github.repository }} + +## Constraints + +- **CAN**: Read files, search code, modify files locally, run tests and commands, create a pull request. +- **CANNOT**: Directly push to the repository — use `create_pull_request`. +- **Only one PR per run.** +- If no suitable issue is found, call `noop` with a brief reason. +- **Most runs should end with `noop`.** Only open a PR when the fix is clearly correct, tested, and small enough for quick review. + +## Process + +Follow these steps in order. + +### Step 1: Gather Candidates + +1. Call `generate_agents_md` to get the repository's coding guidelines and conventions. If this fails, continue without it. +2. Follow the candidate gathering instructions in the **Fix Assignment** section. +3. For each candidate, read the full issue and comments using `issue_read` (methods `get` and `get_comments`). + +### Step 2: Select a Target + +Choose one issue with: + +- Concrete, actionable instructions (file paths, function names, suggested changes) +- A well-scoped fix that doesn't require design decisions +- No active discussion suggesting the fix should go a different direction + +Skip any issue where the suggested fix is ambiguous, controversial, or too large for a single PR. + +### Step 3: Implement + +Follow the implementation instructions in the **Fix Assignment** section. The Fix Assignment defines: +- What kind of changes to make +- What tools to use +- Any domain-specific constraints + +### Step 4: Quality Gate — Self-Review + +Before creating the PR, verify: + +1. **Fix is correct** — the change directly addresses the issue. +2. **Tests pass** — you ran the most relevant tests and they pass. +3. **Scope is minimal** — only changes needed for the fix, no scope creep. +4. **No regressions** — linters pass, no formatting broken, no new warnings. + +If any check fails, call `noop` with a brief reason. + +### Step 5: Create the PR + +Call `create_pull_request` with: +- A concise summary of the changes +- A link to the source issue (e.g., "Fixes #123") +- The specific tests that were run and passed +- A note on any items from the issue that were skipped (if any) + +**Fix Assignment:** diff --git a/.github/workflows/gh-aw-issue-triage-pr.lock.yml b/.github/workflows/gh-aw-issue-fixer.lock.yml similarity index 92% rename from .github/workflows/gh-aw-issue-triage-pr.lock.yml rename to .github/workflows/gh-aw-issue-fixer.lock.yml index 2b8841c5..41f49f2e 100644 --- a/.github/workflows/gh-aw-issue-triage-pr.lock.yml +++ b/.github/workflows/gh-aw-issue-fixer.lock.yml @@ -21,7 +21,7 @@ # # For more information: https://github.github.com/gh-aw/introduction/overview/ # -# Investigate new issues and provide actionable triage analysis with optional PR creation +# Investigate new issues and provide actionable triage analysis with automatic PR creation # # Resolved workflow manifest: # Imports: @@ -35,9 +35,11 @@ # - gh-aw-fragments/safe-output-create-pr.md # - gh-aw-fragments/workflow-edit-guardrails.md # -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"a3928174a4a6b2312b977e3f47a9d731dcd99dec9b8ad9b311a7c8928159c70c"} +# inlined-imports: true +# +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"7cb47f202abb49164bc3816b120f1cf4f37344a351b5ee2a42b5217ae1f4b407"} -name: "Issue Triage (with PR)" +name: "Issue Fixer" "on": # bots: # Bots processed as bot check in pre-activation job # - ${{ inputs.allowed-bot-users }} # Bots processed as bot check in pre-activation job @@ -62,6 +64,11 @@ name: "Issue Triage (with PR)" description: Footer appended to all agent comments and reviews required: false type: string + model: + default: gpt-5.3-codex + description: AI model to use + required: false + type: string setup-commands: default: "" description: Shell commands to run before the agent starts (dependency install, build, etc.) @@ -75,9 +82,9 @@ permissions: {} concurrency: cancel-in-progress: true - group: issue-triage-pr-${{ github.event.issue.number }} + group: issue-fixer-${{ github.event.issue.number }} -run-name: "Issue Triage (with PR)" +run-name: "Issue Fixer" jobs: activation: @@ -94,7 +101,7 @@ jobs: comment_repo: "" steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Validate context variables @@ -116,7 +123,7 @@ jobs: - name: Check workflow file timestamps uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: - GH_AW_WORKFLOW_FILE: "gh-aw-issue-triage-pr.lock.yml" + GH_AW_WORKFLOW_FILE: "gh-aw-issue-fixer.lock.yml" with: script: | const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); @@ -172,6 +179,34 @@ jobs: **Critical**: Tool calls write structured data that downstream jobs process. Without tool calls, follow-up actions will be skipped. **Note**: If you made no other safe output tool calls during this workflow execution, call the "noop" tool to provide a status message indicating completion or that no actions were needed. + + --- + + ## Adding a Comment to an Issue or Pull Request, Creating a Pull Request, Reporting Missing Tools or Functionality, Reporting Missing Data + + **IMPORTANT**: To perform the actions listed above, use the **safeoutputs** tools. Do NOT use `gh`, do NOT call the GitHub API directly. You do not have write access to the GitHub repository. + + **Adding a Comment to an Issue or Pull Request** + + To add a comment to an issue or pull request, use the add_comment tool from safeoutputs. + + **Creating a Pull Request** + + To create a pull request: + 1. Make any file changes directly in the working directory. + 2. If you haven't done so already, create a local branch using an appropriate unique name. + 3. Add and commit your changes to the branch. Be careful to add exactly the files you intend, and check there are no extra files left un-added. Verify you haven't deleted or changed any files you didn't intend to. + 4. Do not push your changes. That will be done by the tool. + 5. Create the pull request with the create_pull_request tool from safeoutputs. + + **Reporting Missing Tools or Functionality** + + To report a missing tool or capability, use the missing_tool tool from safeoutputs. + + **Reporting Missing Data** + + To report missing data required to achieve a goal, use the missing_data tool from safeoutputs. + @@ -312,9 +347,9 @@ jobs: - You may not submit code that modifies files in `.github/workflows/`. Doing so will cause the submission to be rejected. If asked to modify workflow files, propose the change in a copy placed in a `github/` folder (without the leading period) and note in the PR that the file needs to be relocated by someone with workflow write access. GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - # Issue Triage Agent (with PR) + # Issue Fixer - Triage new issues in __GH_AW_GITHUB_REPOSITORY__ and provide actionable analysis with implementation plans. For straightforward fixes, implement and open a draft PR. + Investigate and fix issues in __GH_AW_GITHUB_REPOSITORY__. Provide actionable analysis with implementation plans. For straightforward fixes, implement and open a draft PR. ## Context @@ -455,7 +490,7 @@ jobs: issues: read pull-requests: read concurrency: - group: "gh-aw-copilot-issue-triage-pr-${{ github.event.issue.number }}" + group: "gh-aw-copilot-issue-fixer-${{ github.event.issue.number }}" env: DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} GH_AW_ASSETS_ALLOWED_EXTS: "" @@ -465,7 +500,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: ghawissuetriagepr + GH_AW_WORKFLOW_ID_SANITIZED: ghawissuefixer outputs: checkout_pr_success: ${{ steps.checkout-pr.outputs.checkout_pr_success || 'true' }} has_patch: ${{ steps.collect_output.outputs.has_patch }} @@ -475,7 +510,7 @@ jobs: secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Checkout repository @@ -569,10 +604,10 @@ jobs: const awInfo = { engine_id: "copilot", engine_name: "GitHub Copilot CLI", - model: "gpt-5.3-codex", + model: "${{ inputs.model }}", version: "", agent_version: "0.0.412", - workflow_name: "Issue Triage (with PR)", + workflow_name: "Issue Fixer", experimental: false, supports_tools_allowlist: true, run_id: context.runId, @@ -629,7 +664,7 @@ jobs: 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},"create_pull_request":{},"missing_data":{},"missing_tool":{},"noop":{"max":1}} + {"add_comment":{"max":1},"create_pull_request":{"max":1},"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' [ @@ -643,7 +678,7 @@ jobs: "type": "string" }, "item_number": { - "description": "The issue, pull request, or discussion number to comment on. This is the numeric ID from the GitHub URL (e.g., 123 in github.com/owner/repo/issues/123). If omitted, the tool will attempt to resolve the target from the current workflow context (triggering issue, PR, or discussion).", + "description": "The issue, pull request, or discussion number to comment on. This is the numeric ID from the GitHub URL (e.g., 123 in github.com/owner/repo/issues/123). If omitted, the tool auto-targets the issue, PR, or discussion that triggered this workflow. Auto-targeting only works for issue, pull_request, discussion, and comment event triggers — it does NOT work for schedule, workflow_dispatch, push, or workflow_run triggers. For those trigger types, always provide item_number explicitly, or the comment will be silently discarded.", "type": "number" } }, @@ -667,6 +702,10 @@ jobs: "description": "Source branch name containing the changes. If omitted, uses the current working branch.", "type": "string" }, + "draft": { + "description": "Whether to create the PR as a draft. Draft PRs cannot be merged until marked as ready for review. Use mark_pull_request_as_ready_for_review to convert a draft PR. Default: true.", + "type": "boolean" + }, "labels": { "description": "Labels to categorize the PR (e.g., 'enhancement', 'bugfix'). Labels must exist in the repository.", "items": { @@ -771,6 +810,10 @@ jobs: }, "item_number": { "issueOrPRNumber": true + }, + "repo": { + "type": "string", + "maxLength": 256 } } }, @@ -789,12 +832,19 @@ jobs: "sanitize": true, "maxLength": 256 }, + "draft": { + "type": "boolean" + }, "labels": { "type": "array", "itemType": "string", "itemSanitize": true, "itemMaxLength": 128 }, + "repo": { + "type": "string", + "maxLength": 256 + }, "title": { "required": true, "type": "string", @@ -803,6 +853,31 @@ jobs: } } }, + "missing_data": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "context": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "data_type": { + "type": "string", + "sanitize": true, + "maxLength": 128 + }, + "reason": { + "type": "string", + "sanitize": true, + "maxLength": 256 + } + } + }, "missing_tool": { "defaultMax": 20, "fields": { @@ -1061,10 +1136,11 @@ jobs: run: | set -o pipefail sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --allow-domains '*.githubusercontent.com,*.jsr.io,*.pythonhosted.org,*.rvm.io,agents-md-generator.fastmcp.app,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.rubygems.org,api.snapcraft.io,archive.ubuntu.com,artifacts.elastic.co,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,bun.sh,bundler.rubygems.org,cache.ruby-lang.org,cdn.jsdelivr.net,cloud.elastic.co,codeload.github.com,conda.anaconda.org,conda.binstar.org,crates.io,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,deb.nodesource.com,deno.land,ela.st,elastic.co,esm.sh,files.pythonhosted.org,gems.rubyforge.org,gems.rubyonrails.org,get.pnpm.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,host.docker.internal,index.crates.io,index.rubygems.org,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,lfs.github.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,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,pip.pypa.io,pkg.go.dev,ppa.launchpad.net,proxy.golang.org,public-code-search.fastmcp.app,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.bower.io,registry.npmjs.com,registry.npmjs.org,registry.yarnpkg.com,repo.anaconda.com,repo.continuum.io,repo.yarnpkg.com,rubygems.org,rubygems.pkg.github.com,s.symcb.com,s.symcd.com,security.ubuntu.com,skimdb.npmjs.com,static.crates.io,storage.googleapis.com,sum.golang.org,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.elastic.co,www.npmjs.com,www.npmjs.org,yarnpkg.com' --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.20.2 --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 --model gpt-5.3-codex --allow-all-tools --allow-all-paths --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log + -- /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 --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} @@ -1221,7 +1297,7 @@ jobs: /tmp/gh-aw/sandbox/firewall/logs/ /tmp/gh-aw/agent-stdio.log /tmp/gh-aw/agent/ - /tmp/gh-aw/aw.patch + /tmp/gh-aw/aw-*.patch if-no-files-found: ignore conclusion: @@ -1242,7 +1318,7 @@ jobs: total_count: ${{ steps.missing_tool.outputs.total_count }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent output artifact @@ -1262,7 +1338,7 @@ jobs: env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} GH_AW_NOOP_MAX: 1 - GH_AW_WORKFLOW_NAME: "Issue Triage (with PR)" + GH_AW_WORKFLOW_NAME: "Issue Fixer" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | @@ -1275,7 +1351,7 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_WORKFLOW_NAME: "Issue Triage (with PR)" + GH_AW_WORKFLOW_NAME: "Issue Fixer" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | @@ -1288,10 +1364,10 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_WORKFLOW_NAME: "Issue Triage (with PR)" + GH_AW_WORKFLOW_NAME: "Issue Fixer" 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: "gh-aw-issue-triage-pr" + GH_AW_WORKFLOW_ID: "gh-aw-issue-fixer" GH_AW_SECRET_VERIFICATION_RESULT: ${{ needs.agent.outputs.secret_verification_result }} GH_AW_CHECKOUT_PR_SUCCESS: ${{ needs.agent.outputs.checkout_pr_success }} GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\"}" @@ -1308,7 +1384,7 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_WORKFLOW_NAME: "Issue Triage (with PR)" + GH_AW_WORKFLOW_NAME: "Issue Fixer" 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 }} @@ -1325,7 +1401,7 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_WORKFLOW_NAME: "Issue Triage (with PR)" + GH_AW_WORKFLOW_NAME: "Issue Fixer" GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} @@ -1341,13 +1417,13 @@ jobs: runs-on: ubuntu-latest permissions: {} concurrency: - group: "gh-aw-copilot-issue-triage-pr-${{ github.event.issue.number }}" + group: "gh-aw-copilot-issue-fixer-${{ github.event.issue.number }}" timeout-minutes: 10 outputs: success: ${{ steps.parse_results.outputs.success }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent artifacts @@ -1370,8 +1446,8 @@ jobs: - name: Setup threat detection uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: - WORKFLOW_NAME: "Issue Triage (with PR)" - WORKFLOW_DESCRIPTION: "Investigate new issues and provide actionable triage analysis with optional PR creation" + WORKFLOW_NAME: "Issue Fixer" + WORKFLOW_DESCRIPTION: "Investigate new issues and provide actionable triage analysis with automatic PR creation" HAS_PATCH: ${{ needs.agent.outputs.has_patch }} with: script: | @@ -1408,10 +1484,11 @@ jobs: mkdir -p /tmp/gh-aw/ mkdir -p /tmp/gh-aw/agent/ mkdir -p /tmp/gh-aw/sandbox/agent/logs/ - copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --model gpt-5.3-codex --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log + copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_REF_NAME: ${{ github.ref_name }} @@ -1445,7 +1522,7 @@ jobs: activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Add eyes reaction for immediate feedback @@ -1489,10 +1566,10 @@ jobs: timeout-minutes: 15 env: GH_AW_ENGINE_ID: "copilot" - GH_AW_ENGINE_MODEL: "gpt-5.3-codex" + GH_AW_ENGINE_MODEL: "${{ inputs.model }}" GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\"}" - GH_AW_WORKFLOW_ID: "gh-aw-issue-triage-pr" - GH_AW_WORKFLOW_NAME: "Issue Triage (with PR)" + GH_AW_WORKFLOW_ID: "gh-aw-issue-fixer" + GH_AW_WORKFLOW_NAME: "Issue Fixer" outputs: create_discussion_error_count: ${{ steps.process_safe_outputs.outputs.create_discussion_error_count }} create_discussion_errors: ${{ steps.process_safe_outputs.outputs.create_discussion_errors }} @@ -1500,7 +1577,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@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent output artifact @@ -1524,7 +1601,7 @@ jobs: if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: - ref: ${{ github.ref_name }} + ref: ${{ github.base_ref || github.ref_name }} token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} persist-credentials: false fetch-depth: 1 @@ -1546,7 +1623,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},\"create_pull_request\":{\"base_branch\":\"${{ github.ref_name }}\",\"max\":1,\"max_patch_size\":1024},\"missing_data\":{},\"missing_tool\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_comment\":{\"max\":1},\"create_pull_request\":{\"base_branch\":\"${{ github.base_ref || github.ref_name }}\",\"max\":1,\"max_patch_size\":1024},\"missing_data\":{},\"missing_tool\":{}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/gh-aw-issue-triage-pr.md b/.github/workflows/gh-aw-issue-fixer.md similarity index 90% rename from .github/workflows/gh-aw-issue-triage-pr.md rename to .github/workflows/gh-aw-issue-fixer.md index 179c5436..b4dc651c 100644 --- a/.github/workflows/gh-aw-issue-triage-pr.md +++ b/.github/workflows/gh-aw-issue-fixer.md @@ -1,6 +1,7 @@ --- -name: "Issue Triage (with PR)" -description: "Investigate new issues and provide actionable triage analysis with optional PR creation" +inlined-imports: true +name: "Issue Fixer" +description: "Investigate new issues and provide actionable triage analysis with automatic PR creation" imports: - gh-aw-fragments/elastic-tools.md - gh-aw-fragments/runtime-setup.md @@ -13,12 +14,17 @@ imports: - gh-aw-fragments/safe-output-create-pr.md engine: id: copilot - model: gpt-5.3-codex + model: ${{ inputs.model }} concurrency: - group: "gh-aw-copilot-issue-triage-pr-${{ github.event.issue.number }}" + group: "gh-aw-copilot-issue-fixer-${{ github.event.issue.number }}" on: workflow_call: inputs: + model: + description: "AI model to use" + type: string + required: false + default: "gpt-5.3-codex" additional-instructions: description: "Repo-specific instructions appended to the agent prompt" type: string @@ -47,7 +53,7 @@ on: bots: - "${{ inputs.allowed-bot-users }}" concurrency: - group: issue-triage-pr-${{ github.event.issue.number }} + group: issue-fixer-${{ github.event.issue.number }} cancel-in-progress: true permissions: contents: read @@ -76,9 +82,9 @@ steps: run: eval "$SETUP_COMMANDS" --- -# Issue Triage Agent (with PR) +# Issue Fixer -Triage new issues in ${{ github.repository }} and provide actionable analysis with implementation plans. For straightforward fixes, implement and open a draft PR. +Investigate and fix issues in ${{ github.repository }}. Provide actionable analysis with implementation plans. For straightforward fixes, implement and open a draft PR. ## Context diff --git a/.github/workflows/gh-aw-issue-triage.lock.yml b/.github/workflows/gh-aw-issue-triage.lock.yml index 9d80fc40..1489b303 100644 --- a/.github/workflows/gh-aw-issue-triage.lock.yml +++ b/.github/workflows/gh-aw-issue-triage.lock.yml @@ -33,7 +33,9 @@ # - gh-aw-fragments/runtime-setup.md # - gh-aw-fragments/safe-output-add-comment.md # -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"e94459147270a05efe43bf03a24d4045e6ef4ff49e86e34a686ba5d9fbc0d043"} +# inlined-imports: true +# +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"5f0fe44d6886cbb7f04f9648fbbc84a760575c2014e691bd7ff384417372bc00"} name: "Issue Triage" "on": @@ -60,6 +62,11 @@ name: "Issue Triage" description: Footer appended to all agent comments and reviews required: false type: string + model: + default: gpt-5.3-codex + description: AI model to use + required: false + type: string setup-commands: default: "" description: Shell commands to run before the agent starts (dependency install, build, etc.) @@ -92,7 +99,7 @@ jobs: comment_repo: "" steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Validate context variables @@ -170,6 +177,25 @@ jobs: **Critical**: Tool calls write structured data that downstream jobs process. Without tool calls, follow-up actions will be skipped. **Note**: If you made no other safe output tool calls during this workflow execution, call the "noop" tool to provide a status message indicating completion or that no actions were needed. + + --- + + ## Adding a Comment to an Issue or Pull Request, Reporting Missing Tools or Functionality, Reporting Missing Data + + **IMPORTANT**: To perform the actions listed above, use the **safeoutputs** tools. Do NOT use `gh`, do NOT call the GitHub API directly. You do not have write access to the GitHub repository. + + **Adding a Comment to an Issue or Pull Request** + + To add a comment to an issue or pull request, use the add_comment tool from safeoutputs. + + **Reporting Missing Tools or Functionality** + + To report a missing tool or capability, use the missing_tool tool from safeoutputs. + + **Reporting Missing Data** + + To report missing data required to achieve a goal, use the missing_data tool from safeoutputs. + @@ -482,7 +508,7 @@ jobs: secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Checkout repository @@ -576,7 +602,7 @@ jobs: const awInfo = { engine_id: "copilot", engine_name: "GitHub Copilot CLI", - model: "gpt-5.3-codex", + model: "${{ inputs.model }}", version: "", agent_version: "0.0.412", workflow_name: "Issue Triage", @@ -650,7 +676,7 @@ jobs: "type": "string" }, "item_number": { - "description": "The issue, pull request, or discussion number to comment on. This is the numeric ID from the GitHub URL (e.g., 123 in github.com/owner/repo/issues/123). If omitted, the tool will attempt to resolve the target from the current workflow context (triggering issue, PR, or discussion).", + "description": "The issue, pull request, or discussion number to comment on. This is the numeric ID from the GitHub URL (e.g., 123 in github.com/owner/repo/issues/123). If omitted, the tool auto-targets the issue, PR, or discussion that triggered this workflow. Auto-targeting only works for issue, pull_request, discussion, and comment event triggers — it does NOT work for schedule, workflow_dispatch, push, or workflow_run triggers. For those trigger types, always provide item_number explicitly, or the comment will be silently discarded.", "type": "number" } }, @@ -745,6 +771,35 @@ jobs: }, "item_number": { "issueOrPRNumber": true + }, + "repo": { + "type": "string", + "maxLength": 256 + } + } + }, + "missing_data": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "context": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "data_type": { + "type": "string", + "sanitize": true, + "maxLength": 128 + }, + "reason": { + "type": "string", + "sanitize": true, + "maxLength": 256 } } }, @@ -909,10 +964,11 @@ jobs: run: | set -o pipefail sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --allow-domains '*.githubusercontent.com,*.jsr.io,*.pythonhosted.org,*.rvm.io,agents-md-generator.fastmcp.app,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.rubygems.org,api.snapcraft.io,archive.ubuntu.com,artifacts.elastic.co,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,bun.sh,bundler.rubygems.org,cache.ruby-lang.org,cdn.jsdelivr.net,cloud.elastic.co,codeload.github.com,conda.anaconda.org,conda.binstar.org,crates.io,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,deb.nodesource.com,deno.land,ela.st,elastic.co,esm.sh,files.pythonhosted.org,gems.rubyforge.org,gems.rubyonrails.org,get.pnpm.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,host.docker.internal,index.crates.io,index.rubygems.org,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,lfs.github.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,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,pip.pypa.io,pkg.go.dev,ppa.launchpad.net,proxy.golang.org,public-code-search.fastmcp.app,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.bower.io,registry.npmjs.com,registry.npmjs.org,registry.yarnpkg.com,repo.anaconda.com,repo.continuum.io,repo.yarnpkg.com,rubygems.org,rubygems.pkg.github.com,s.symcb.com,s.symcd.com,security.ubuntu.com,skimdb.npmjs.com,static.crates.io,storage.googleapis.com,sum.golang.org,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.elastic.co,www.npmjs.com,www.npmjs.org,yarnpkg.com' --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.20.2 --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 --model gpt-5.3-codex --allow-all-tools --allow-all-paths --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log + -- /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 --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} @@ -1078,7 +1134,7 @@ jobs: total_count: ${{ steps.missing_tool.outputs.total_count }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent output artifact @@ -1169,7 +1225,7 @@ jobs: success: ${{ steps.parse_results.outputs.success }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent artifacts @@ -1230,10 +1286,11 @@ jobs: mkdir -p /tmp/gh-aw/ mkdir -p /tmp/gh-aw/agent/ mkdir -p /tmp/gh-aw/sandbox/agent/logs/ - copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --model gpt-5.3-codex --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log + copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_REF_NAME: ${{ github.ref_name }} @@ -1267,7 +1324,7 @@ jobs: activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Add eyes reaction for immediate feedback @@ -1309,7 +1366,7 @@ jobs: timeout-minutes: 15 env: GH_AW_ENGINE_ID: "copilot" - GH_AW_ENGINE_MODEL: "gpt-5.3-codex" + GH_AW_ENGINE_MODEL: "${{ inputs.model }}" GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\"}" GH_AW_WORKFLOW_ID: "gh-aw-issue-triage" GH_AW_WORKFLOW_NAME: "Issue Triage" @@ -1320,7 +1377,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@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent output artifact diff --git a/.github/workflows/gh-aw-issue-triage.md b/.github/workflows/gh-aw-issue-triage.md index ca056695..5e047b26 100644 --- a/.github/workflows/gh-aw-issue-triage.md +++ b/.github/workflows/gh-aw-issue-triage.md @@ -1,4 +1,5 @@ --- +inlined-imports: true name: "Issue Triage" description: "Investigate new issues and provide actionable triage analysis" imports: @@ -11,12 +12,17 @@ imports: - gh-aw-fragments/safe-output-add-comment.md engine: id: copilot - model: gpt-5.3-codex + model: ${{ inputs.model }} concurrency: group: "gh-aw-copilot-issue-triage-${{ github.event.issue.number }}" on: workflow_call: inputs: + model: + description: "AI model to use" + type: string + required: false + default: "gpt-5.3-codex" additional-instructions: description: "Repo-specific instructions appended to the agent prompt" type: string diff --git a/.github/workflows/gh-aw-mention-in-issue.lock.yml b/.github/workflows/gh-aw-mention-in-issue.lock.yml index 80acfba9..40995d07 100644 --- a/.github/workflows/gh-aw-mention-in-issue.lock.yml +++ b/.github/workflows/gh-aw-mention-in-issue.lock.yml @@ -36,7 +36,9 @@ # - gh-aw-fragments/safe-output-create-pr.md # - gh-aw-fragments/workflow-edit-guardrails.md # -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"4d5dbf51f8e12caa1ab17cef6e4b13c9c130c531b9324032c38e1e743264b462"} +# inlined-imports: true +# +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"9880ac6dba9d404fde60f78403fcb4f977132063f0375d67fc5d1842cf99a3e8"} name: "Mention in Issue" "on": @@ -68,6 +70,11 @@ name: "Mention in Issue" description: Footer appended to all agent comments and reviews required: false type: string + model: + default: gpt-5.3-codex + description: AI model to use + required: false + type: string setup-commands: default: "" description: Shell commands to run before the agent starts (dependency install, build, etc.) @@ -100,7 +107,7 @@ jobs: comment_repo: "" steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Validate context variables @@ -179,6 +186,38 @@ jobs: **Critical**: Tool calls write structured data that downstream jobs process. Without tool calls, follow-up actions will be skipped. **Note**: If you made no other safe output tool calls during this workflow execution, call the "noop" tool to provide a status message indicating completion or that no actions were needed. + + --- + + ## Adding a Comment to an Issue or Pull Request, Creating an Issue, Creating a Pull Request, Reporting Missing Tools or Functionality, Reporting Missing Data + + **IMPORTANT**: To perform the actions listed above, use the **safeoutputs** tools. Do NOT use `gh`, do NOT call the GitHub API directly. You do not have write access to the GitHub repository. + + **Adding a Comment to an Issue or Pull Request** + + To add a comment to an issue or pull request, use the add_comment tool from safeoutputs. + + **Creating an Issue** + + To create an issue, use the create_issue tool from safeoutputs. + + **Creating a Pull Request** + + To create a pull request: + 1. Make any file changes directly in the working directory. + 2. If you haven't done so already, create a local branch using an appropriate unique name. + 3. Add and commit your changes to the branch. Be careful to add exactly the files you intend, and check there are no extra files left un-added. Verify you haven't deleted or changed any files you didn't intend to. + 4. Do not push your changes. That will be done by the tool. + 5. Create the pull request with the create_pull_request tool from safeoutputs. + + **Reporting Missing Tools or Functionality** + + To report a missing tool or capability, use the missing_tool tool from safeoutputs. + + **Reporting Missing Data** + + To report missing data required to achieve a goal, use the missing_data tool from safeoutputs. + @@ -482,7 +521,7 @@ jobs: secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Checkout repository @@ -576,7 +615,7 @@ jobs: const awInfo = { engine_id: "copilot", engine_name: "GitHub Copilot CLI", - model: "gpt-5.3-codex", + model: "${{ inputs.model }}", version: "", agent_version: "0.0.412", workflow_name: "Mention in Issue", @@ -636,7 +675,7 @@ jobs: 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},"create_issue":{"max":1},"create_pull_request":{},"missing_data":{},"missing_tool":{},"noop":{"max":1}} + {"add_comment":{"max":1},"create_issue":{"max":1},"create_pull_request":{"max":1},"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' [ @@ -691,7 +730,7 @@ jobs: "type": "string" }, "item_number": { - "description": "The issue, pull request, or discussion number to comment on. This is the numeric ID from the GitHub URL (e.g., 123 in github.com/owner/repo/issues/123). If omitted, the tool will attempt to resolve the target from the current workflow context (triggering issue, PR, or discussion).", + "description": "The issue, pull request, or discussion number to comment on. This is the numeric ID from the GitHub URL (e.g., 123 in github.com/owner/repo/issues/123). If omitted, the tool auto-targets the issue, PR, or discussion that triggered this workflow. Auto-targeting only works for issue, pull_request, discussion, and comment event triggers — it does NOT work for schedule, workflow_dispatch, push, or workflow_run triggers. For those trigger types, always provide item_number explicitly, or the comment will be silently discarded.", "type": "number" } }, @@ -715,6 +754,10 @@ jobs: "description": "Source branch name containing the changes. If omitted, uses the current working branch.", "type": "string" }, + "draft": { + "description": "Whether to create the PR as a draft. Draft PRs cannot be merged until marked as ready for review. Use mark_pull_request_as_ready_for_review to convert a draft PR. Default: true.", + "type": "boolean" + }, "labels": { "description": "Labels to categorize the PR (e.g., 'enhancement', 'bugfix'). Labels must exist in the repository.", "items": { @@ -819,6 +862,10 @@ jobs: }, "item_number": { "issueOrPRNumber": true + }, + "repo": { + "type": "string", + "maxLength": 256 } } }, @@ -870,12 +917,19 @@ jobs: "sanitize": true, "maxLength": 256 }, + "draft": { + "type": "boolean" + }, "labels": { "type": "array", "itemType": "string", "itemSanitize": true, "itemMaxLength": 128 }, + "repo": { + "type": "string", + "maxLength": 256 + }, "title": { "required": true, "type": "string", @@ -884,6 +938,31 @@ jobs: } } }, + "missing_data": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "context": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "data_type": { + "type": "string", + "sanitize": true, + "maxLength": 128 + }, + "reason": { + "type": "string", + "sanitize": true, + "maxLength": 256 + } + } + }, "missing_tool": { "defaultMax": 20, "fields": { @@ -1142,10 +1221,11 @@ jobs: run: | set -o pipefail sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --allow-domains '*.githubusercontent.com,*.jsr.io,*.pythonhosted.org,*.rvm.io,agents-md-generator.fastmcp.app,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.rubygems.org,api.snapcraft.io,archive.ubuntu.com,artifacts.elastic.co,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,bun.sh,bundler.rubygems.org,cache.ruby-lang.org,cdn.jsdelivr.net,cloud.elastic.co,codeload.github.com,conda.anaconda.org,conda.binstar.org,crates.io,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,deb.nodesource.com,deno.land,ela.st,elastic.co,esm.sh,files.pythonhosted.org,gems.rubyforge.org,gems.rubyonrails.org,get.pnpm.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,host.docker.internal,index.crates.io,index.rubygems.org,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,lfs.github.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,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,pip.pypa.io,pkg.go.dev,ppa.launchpad.net,proxy.golang.org,public-code-search.fastmcp.app,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.bower.io,registry.npmjs.com,registry.npmjs.org,registry.yarnpkg.com,repo.anaconda.com,repo.continuum.io,repo.yarnpkg.com,rubygems.org,rubygems.pkg.github.com,s.symcb.com,s.symcd.com,security.ubuntu.com,skimdb.npmjs.com,static.crates.io,storage.googleapis.com,sum.golang.org,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.elastic.co,www.npmjs.com,www.npmjs.org,yarnpkg.com' --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.20.2 --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 --model gpt-5.3-codex --allow-all-tools --allow-all-paths --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log + -- /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 --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} @@ -1302,7 +1382,7 @@ jobs: /tmp/gh-aw/sandbox/firewall/logs/ /tmp/gh-aw/agent-stdio.log /tmp/gh-aw/agent/ - /tmp/gh-aw/aw.patch + /tmp/gh-aw/aw-*.patch if-no-files-found: ignore conclusion: @@ -1323,7 +1403,7 @@ jobs: total_count: ${{ steps.missing_tool.outputs.total_count }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent output artifact @@ -1428,7 +1508,7 @@ jobs: success: ${{ steps.parse_results.outputs.success }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent artifacts @@ -1489,10 +1569,11 @@ jobs: mkdir -p /tmp/gh-aw/ mkdir -p /tmp/gh-aw/agent/ mkdir -p /tmp/gh-aw/sandbox/agent/logs/ - copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --model gpt-5.3-codex --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log + copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_REF_NAME: ${{ github.ref_name }} @@ -1526,7 +1607,7 @@ jobs: activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Add eyes reaction for immediate feedback @@ -1570,7 +1651,7 @@ jobs: timeout-minutes: 15 env: GH_AW_ENGINE_ID: "copilot" - GH_AW_ENGINE_MODEL: "gpt-5.3-codex" + GH_AW_ENGINE_MODEL: "${{ inputs.model }}" GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\"}" GH_AW_WORKFLOW_ID: "gh-aw-mention-in-issue" GH_AW_WORKFLOW_NAME: "Mention in Issue" @@ -1581,7 +1662,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@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent output artifact @@ -1605,7 +1686,7 @@ jobs: if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: - ref: ${{ github.ref_name }} + ref: ${{ github.base_ref || github.ref_name }} token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} persist-credentials: false fetch-depth: 1 @@ -1627,7 +1708,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},\"create_issue\":{\"max\":1},\"create_pull_request\":{\"base_branch\":\"${{ github.ref_name }}\",\"max\":1,\"max_patch_size\":1024},\"missing_data\":{},\"missing_tool\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_comment\":{\"max\":1},\"create_issue\":{\"max\":1},\"create_pull_request\":{\"base_branch\":\"${{ github.base_ref || github.ref_name }}\",\"max\":1,\"max_patch_size\":1024},\"missing_data\":{},\"missing_tool\":{}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/gh-aw-mention-in-issue.md b/.github/workflows/gh-aw-mention-in-issue.md index a4227e88..c9f39349 100644 --- a/.github/workflows/gh-aw-mention-in-issue.md +++ b/.github/workflows/gh-aw-mention-in-issue.md @@ -1,4 +1,5 @@ --- +inlined-imports: true name: "Mention in Issue" description: "AI assistant for issues — answer questions, debug, and create PRs on demand" imports: @@ -14,12 +15,17 @@ imports: - gh-aw-fragments/safe-output-create-issue.md engine: id: copilot - model: gpt-5.3-codex + model: ${{ inputs.model }} concurrency: group: "gh-aw-copilot-mention-issue-${{ github.event.issue.number }}" on: workflow_call: inputs: + model: + description: "AI model to use" + type: string + required: false + default: "gpt-5.3-codex" additional-instructions: description: "Repo-specific instructions appended to the agent prompt" type: string diff --git a/.github/workflows/gh-aw-mention-in-pr.lock.yml b/.github/workflows/gh-aw-mention-in-pr.lock.yml index 85227b06..267cff0e 100644 --- a/.github/workflows/gh-aw-mention-in-pr.lock.yml +++ b/.github/workflows/gh-aw-mention-in-pr.lock.yml @@ -39,7 +39,9 @@ # - gh-aw-fragments/safe-output-submit-review.md # - gh-aw-fragments/workflow-edit-guardrails.md # -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"5b3e245e5facdc6dffd46b9743163cac46825dfd6b17c0ec9732dc56efae216c"} +# inlined-imports: true +# +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"ef1c36fca7a4230cf4e9e156dfe9aa602041a93c1455b49bed657bf12f99fc72"} name: "Mention in PR" "on": @@ -66,6 +68,11 @@ name: "Mention in PR" description: Footer appended to all agent comments and reviews required: false type: string + model: + default: gpt-5.3-codex + description: AI model to use + required: false + type: string setup-commands: default: "" description: Shell commands to run before the agent starts (dependency install, build, etc.) @@ -98,7 +105,7 @@ jobs: comment_repo: "" steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Validate context variables @@ -177,6 +184,44 @@ jobs: **Critical**: Tool calls write structured data that downstream jobs process. Without tool calls, follow-up actions will be skipped. **Note**: If you made no other safe output tool calls during this workflow execution, call the "noop" tool to provide a status message indicating completion or that no actions were needed. + + --- + + ## Adding a Comment to an Issue or Pull Request, Creating a Pull Request Review Comment, Submitting a Pull Request Review, Resolving a Pull Request Review Thread, Pushing Changes to Branch, Reporting Missing Tools or Functionality, Reporting Missing Data + + **IMPORTANT**: To perform the actions listed above, use the **safeoutputs** tools. Do NOT use `gh`, do NOT call the GitHub API directly. You do not have write access to the GitHub repository. + + **Adding a Comment to an Issue or Pull Request** + + To add a comment to an issue or pull request, use the add_comment tool from safeoutputs. + + **Creating a Pull Request Review Comment** + + To create a pull request review comment, use the create_pull_request_review_comment tool from safeoutputs. + + **Submitting a Pull Request Review** + + To submit a pull request review (APPROVE, REQUEST_CHANGES, or COMMENT), use the submit_pull_request_review tool from safeoutputs. + + **Resolving a Pull Request Review Thread** + + To resolve a review thread on a pull request, use the resolve_pull_request_review_thread tool from safeoutputs. + + **Pushing Changes to a Pull Request Branch** + + To push changes to the branch of a pull request: + 1. Make any file changes directly in the working directory. + 2. Add and commit your changes to the local copy of the pull request branch. Be careful to add exactly the files you intend, and verify you haven't deleted or changed any files you didn't intend to. + 3. Push the branch to the repo by using the push_to_pull_request_branch tool from safeoutputs. + + **Reporting Missing Tools or Functionality** + + To report a missing tool or capability, use the missing_tool tool from safeoutputs. + + **Reporting Missing Data** + + To report missing data required to achieve a goal, use the missing_data tool from safeoutputs. + @@ -625,7 +670,7 @@ jobs: secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Checkout repository @@ -725,7 +770,7 @@ jobs: const awInfo = { engine_id: "copilot", engine_name: "GitHub Copilot CLI", - model: "gpt-5.3-codex", + model: "${{ inputs.model }}", version: "", agent_version: "0.0.412", workflow_name: "Mention in PR", @@ -799,7 +844,7 @@ jobs: "type": "string" }, "item_number": { - "description": "The issue, pull request, or discussion number to comment on. This is the numeric ID from the GitHub URL (e.g., 123 in github.com/owner/repo/issues/123). If omitted, the tool will attempt to resolve the target from the current workflow context (triggering issue, PR, or discussion).", + "description": "The issue, pull request, or discussion number to comment on. This is the numeric ID from the GitHub URL (e.g., 123 in github.com/owner/repo/issues/123). If omitted, the tool auto-targets the issue, PR, or discussion that triggered this workflow. Auto-targeting only works for issue, pull_request, discussion, and comment event triggers — it does NOT work for schedule, workflow_dispatch, push, or workflow_run triggers. For those trigger types, always provide item_number explicitly, or the comment will be silently discarded.", "type": "number" } }, @@ -1007,6 +1052,10 @@ jobs: }, "item_number": { "issueOrPRNumber": true + }, + "repo": { + "type": "string", + "maxLength": 256 } } }, @@ -1027,6 +1076,10 @@ jobs: "required": true, "type": "string" }, + "repo": { + "type": "string", + "maxLength": 256 + }, "side": { "type": "string", "enum": [ @@ -1040,6 +1093,31 @@ jobs: }, "customValidation": "startLineLessOrEqualLine" }, + "missing_data": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "context": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "data_type": { + "type": "string", + "sanitize": true, + "maxLength": 128 + }, + "reason": { + "type": "string", + "sanitize": true, + "maxLength": 256 + } + } + }, "missing_tool": { "defaultMax": 20, "fields": { @@ -1345,10 +1423,11 @@ jobs: run: | set -o pipefail sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --allow-domains '*.githubusercontent.com,*.jsr.io,*.pythonhosted.org,*.rvm.io,agents-md-generator.fastmcp.app,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.rubygems.org,api.snapcraft.io,archive.ubuntu.com,artifacts.elastic.co,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,bun.sh,bundler.rubygems.org,cache.ruby-lang.org,cdn.jsdelivr.net,cloud.elastic.co,codeload.github.com,conda.anaconda.org,conda.binstar.org,crates.io,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,deb.nodesource.com,deno.land,ela.st,elastic.co,esm.sh,files.pythonhosted.org,gems.rubyforge.org,gems.rubyonrails.org,get.pnpm.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,host.docker.internal,index.crates.io,index.rubygems.org,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,lfs.github.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,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,pip.pypa.io,pkg.go.dev,ppa.launchpad.net,proxy.golang.org,public-code-search.fastmcp.app,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.bower.io,registry.npmjs.com,registry.npmjs.org,registry.yarnpkg.com,repo.anaconda.com,repo.continuum.io,repo.yarnpkg.com,rubygems.org,rubygems.pkg.github.com,s.symcb.com,s.symcd.com,security.ubuntu.com,skimdb.npmjs.com,static.crates.io,storage.googleapis.com,sum.golang.org,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.elastic.co,www.npmjs.com,www.npmjs.org,yarnpkg.com' --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.20.2 --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 --model gpt-5.3-codex --allow-all-tools --allow-all-paths --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log + -- /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 --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} @@ -1505,7 +1584,7 @@ jobs: /tmp/gh-aw/sandbox/firewall/logs/ /tmp/gh-aw/agent-stdio.log /tmp/gh-aw/agent/ - /tmp/gh-aw/aw.patch + /tmp/gh-aw/aw-*.patch if-no-files-found: ignore conclusion: @@ -1526,7 +1605,7 @@ jobs: total_count: ${{ steps.missing_tool.outputs.total_count }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent output artifact @@ -1617,7 +1696,7 @@ jobs: success: ${{ steps.parse_results.outputs.success }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent artifacts @@ -1678,10 +1757,11 @@ jobs: mkdir -p /tmp/gh-aw/ mkdir -p /tmp/gh-aw/agent/ mkdir -p /tmp/gh-aw/sandbox/agent/logs/ - copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --model gpt-5.3-codex --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log + copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_REF_NAME: ${{ github.ref_name }} @@ -1715,7 +1795,7 @@ jobs: activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Add eyes reaction for immediate feedback @@ -1759,7 +1839,7 @@ jobs: timeout-minutes: 15 env: GH_AW_ENGINE_ID: "copilot" - GH_AW_ENGINE_MODEL: "gpt-5.3-codex" + GH_AW_ENGINE_MODEL: "${{ inputs.model }}" GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\"}" GH_AW_WORKFLOW_ID: "gh-aw-mention-in-pr" GH_AW_WORKFLOW_NAME: "Mention in PR" @@ -1770,7 +1850,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@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent output artifact @@ -1794,7 +1874,7 @@ jobs: if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'push_to_pull_request_branch')) uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: - ref: ${{ github.ref_name }} + ref: ${{ github.base_ref || github.ref_name }} token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} persist-credentials: false fetch-depth: 1 @@ -1816,7 +1896,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},\"create_pull_request_review_comment\":{\"max\":30,\"side\":\"RIGHT\"},\"missing_data\":{},\"missing_tool\":{},\"push_to_pull_request_branch\":{\"base_branch\":\"${{ github.ref_name }}\",\"if_no_changes\":\"warn\",\"max_patch_size\":1024},\"resolve_pull_request_review_thread\":{\"max\":10},\"submit_pull_request_review\":{\"footer\":\"if-body\",\"max\":1}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_comment\":{\"max\":1},\"create_pull_request_review_comment\":{\"max\":30,\"side\":\"RIGHT\"},\"missing_data\":{},\"missing_tool\":{},\"push_to_pull_request_branch\":{\"base_branch\":\"${{ github.base_ref || github.ref_name }}\",\"if_no_changes\":\"warn\",\"max_patch_size\":1024},\"resolve_pull_request_review_thread\":{\"max\":10},\"submit_pull_request_review\":{\"footer\":\"if-body\",\"max\":1}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/gh-aw-mention-in-pr.md b/.github/workflows/gh-aw-mention-in-pr.md index ccbaaab9..7204ad83 100644 --- a/.github/workflows/gh-aw-mention-in-pr.md +++ b/.github/workflows/gh-aw-mention-in-pr.md @@ -1,4 +1,5 @@ --- +inlined-imports: true name: "Mention in PR" description: "AI assistant for PRs — review, fix code, and push changes on demand" imports: @@ -17,12 +18,17 @@ imports: - gh-aw-fragments/safe-output-resolve-thread.md engine: id: copilot - model: gpt-5.3-codex + model: ${{ inputs.model }} concurrency: group: "gh-aw-copilot-mention-pr-${{ github.event.issue.number }}" on: workflow_call: inputs: + model: + description: "AI model to use" + type: string + required: false + default: "gpt-5.3-codex" additional-instructions: description: "Repo-specific instructions appended to the agent prompt" type: string diff --git a/.github/workflows/gh-aw-newbie-contributor-fixer.lock.yml b/.github/workflows/gh-aw-newbie-contributor-fixer.lock.yml new file mode 100644 index 00000000..af306222 --- /dev/null +++ b/.github/workflows/gh-aw-newbie-contributor-fixer.lock.yml @@ -0,0 +1,1584 @@ +# +# ___ _ _ +# / _ \ | | (_) +# | |_| | __ _ ___ _ __ | |_ _ ___ +# | _ |/ _` |/ _ \ '_ \| __| |/ __| +# | | | | (_| | __/ | | | |_| | (__ +# \_| |_/\__, |\___|_| |_|\__|_|\___| +# __/ | +# _ _ |___/ +# | | | | / _| | +# | | | | ___ _ __ _ __| |_| | _____ ____ +# | |/\| |/ _ \ '__| |/ /| _| |/ _ \ \ /\ / / ___| +# \ /\ / (_) | | | | ( | | | | (_) \ V V /\__ \ +# \/ \/ \___/|_| |_|\_\|_| |_|\___/ \_/\_/ |___/ +# +# This file was automatically generated by gh-aw. DO NOT EDIT. +# +# To update this file, edit the corresponding .md file and run: +# gh aw compile +# Not all edits will cause changes to this file. +# +# For more information: https://github.github.com/gh-aw/introduction/overview/ +# +# Fix newbie-contributor-patrol issues by improving documentation and opening a focused PR +# +# Resolved workflow manifest: +# Imports: +# - gh-aw-fragments/elastic-tools.md +# - gh-aw-fragments/formatting.md +# - gh-aw-fragments/mcp-pagination.md +# - gh-aw-fragments/messages-footer.md +# - gh-aw-fragments/rigor.md +# - gh-aw-fragments/runtime-setup.md +# - gh-aw-fragments/safe-output-create-pr.md +# - gh-aw-fragments/scheduled-fix.md +# - gh-aw-fragments/workflow-edit-guardrails.md +# +# inlined-imports: true +# +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"71fdb51b1f06d1af55282c62b52ca0113e227491f74cbbc78ae29ce6c46becde"} + +name: "Newbie Contributor Fixer" +"on": + # bots: # Bots processed as bot check in pre-activation job + # - ${{ inputs.allowed-bot-users }} # Bots processed as bot check in pre-activation job + # roles: # Roles processed as role check in pre-activation job + # - admin # Roles processed as role check in pre-activation job + # - maintainer # Roles processed as role check in pre-activation job + # - write # Roles processed as role check in pre-activation job + workflow_call: + inputs: + additional-instructions: + default: "" + description: Repo-specific instructions appended to the agent prompt + required: false + type: string + allowed-bot-users: + default: github-actions[bot] + description: Allowlisted bot actor usernames (comma-separated) + required: false + type: string + messages-footer: + default: "" + description: Footer appended to all agent comments and reviews + required: false + type: string + model: + default: gpt-5.3-codex + description: AI model to use + required: false + type: string + setup-commands: + default: "" + description: Shell commands to run before the agent starts (dependency install, build, etc.) + required: false + type: string + secrets: + COPILOT_GITHUB_TOKEN: + required: true + +permissions: {} + +concurrency: + cancel-in-progress: true + group: newbie-contributor-fixer + +run-name: "Newbie Contributor Fixer" + +jobs: + activation: + needs: pre_activation + if: needs.pre_activation.outputs.activated == 'true' + runs-on: ubuntu-slim + permissions: + contents: read + outputs: + comment_id: "" + comment_repo: "" + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 + with: + destination: /opt/gh-aw/actions + - name: Validate context variables + 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/validate_context_variables.cjs'); + await main(); + - name: Checkout .github and .agents folders + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + sparse-checkout: | + .github + .agents + fetch-depth: 1 + persist-credentials: false + - name: Check workflow file timestamps + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_WORKFLOW_FILE: "gh-aw-newbie-contributor-fixer.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: Create prompt with built-in context + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} + GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} + GH_AW_GITHUB_ACTOR: ${{ github.actor }} + GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} + GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} + GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} + GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} + GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} + GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} + run: | + bash /opt/gh-aw/actions/create_prompt_first.sh + cat << 'GH_AW_PROMPT_EOF' > "$GH_AW_PROMPT" + + GH_AW_PROMPT_EOF + cat "/opt/gh-aw/prompts/xpia.md" >> "$GH_AW_PROMPT" + cat "/opt/gh-aw/prompts/temp_folder_prompt.md" >> "$GH_AW_PROMPT" + cat "/opt/gh-aw/prompts/markdown.md" >> "$GH_AW_PROMPT" + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + + GitHub API Access Instructions + + The gh CLI is NOT authenticated. Do NOT use gh commands for GitHub operations. + + + To create or modify GitHub resources (issues, discussions, pull requests, etc.), you MUST call the appropriate safe output tool. Simply writing content will NOT work - the workflow requires actual tool calls. + + Temporary IDs: Some safe output tools support a temporary ID field (usually named temporary_id) so you can reference newly-created items elsewhere in the SAME agent output (for example, using #aw_abc1 in a later body). + + **IMPORTANT - temporary_id format rules:** + - If you DON'T need to reference the item later, OMIT the temporary_id field entirely (it will be auto-generated if needed) + - If you DO need cross-references/chaining, you MUST match this EXACT validation regex: /^aw_[A-Za-z0-9]{3,8}$/i + - Format: aw_ prefix followed by 3 to 8 alphanumeric characters (A-Z, a-z, 0-9, case-insensitive) + - Valid alphanumeric characters: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 + - INVALID examples: aw_ab (too short), aw_123456789 (too long), aw_test-id (contains hyphen), aw_id_123 (contains underscore) + - VALID examples: aw_abc, aw_abc1, aw_Test123, aw_A1B2C3D4, aw_12345678 + - To generate valid IDs: use 3-8 random alphanumeric characters or omit the field to let the system auto-generate + + Do NOT invent other aw_* formats — downstream steps will reject them with validation errors matching against /^aw_[A-Za-z0-9]{3,8}$/i. + + Discover available tools from the safeoutputs MCP server. + + **Critical**: Tool calls write structured data that downstream jobs process. Without tool calls, follow-up actions will be skipped. + + **Note**: If you made no other safe output tool calls during this workflow execution, call the "noop" tool to provide a status message indicating completion or that no actions were needed. + + --- + + ## Creating a Pull Request, Reporting Missing Tools or Functionality, Reporting Missing Data + + **IMPORTANT**: To perform the actions listed above, use the **safeoutputs** tools. Do NOT use `gh`, do NOT call the GitHub API directly. You do not have write access to the GitHub repository. + + **Creating a Pull Request** + + To create a pull request: + 1. Make any file changes directly in the working directory. + 2. If you haven't done so already, create a local branch using an appropriate unique name. + 3. Add and commit your changes to the branch. Be careful to add exactly the files you intend, and check there are no extra files left un-added. Verify you haven't deleted or changed any files you didn't intend to. + 4. Do not push your changes. That will be done by the tool. + 5. Create the pull request with the create_pull_request tool from safeoutputs. + + **Reporting Missing Tools or Functionality** + + To report a missing tool or capability, use the missing_tool tool from safeoutputs. + + **Reporting Missing Data** + + To report missing data required to achieve a goal, use the missing_data tool from safeoutputs. + + + + + The following GitHub context information is available for this workflow: + {{#if __GH_AW_GITHUB_ACTOR__ }} + - **actor**: __GH_AW_GITHUB_ACTOR__ + {{/if}} + {{#if __GH_AW_GITHUB_REPOSITORY__ }} + - **repository**: __GH_AW_GITHUB_REPOSITORY__ + {{/if}} + {{#if __GH_AW_GITHUB_WORKSPACE__ }} + - **workspace**: __GH_AW_GITHUB_WORKSPACE__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_ISSUE_NUMBER__ }} + - **issue-number**: #__GH_AW_GITHUB_EVENT_ISSUE_NUMBER__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__ }} + - **discussion-number**: #__GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__ }} + - **pull-request-number**: #__GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_COMMENT_ID__ }} + - **comment-id**: __GH_AW_GITHUB_EVENT_COMMENT_ID__ + {{/if}} + {{#if __GH_AW_GITHUB_RUN_ID__ }} + - **workflow-run-id**: __GH_AW_GITHUB_RUN_ID__ + {{/if}} + + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + ## MCP Servers + + - **`generate_agents_md`** — generates a summary of the repository's structure, conventions, and coding guidelines from AGENTS.md and related files. Call at the start of every workflow to get repo context. + - **`search_code`** — grep-style search across public GitHub repositories. Use for finding usage patterns in upstream libraries, reference implementations, or examples in open-source projects. This searches *public GitHub repos*, not the local codebase — if available you can use `grep` and file reading for local code. + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + ## Formatting Guidelines + + - Lead with the most important information — your first sentence should be the key takeaway + - Be concise and actionable — no filler or praise + - Use `
` and `` tags for long sections to keep responses scannable + - Wrap branch names and @-references in backticks to avoid pinging users + - Include code snippets with file paths and line numbers when referencing the codebase + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + ## Rigor + + **Silence is better than noise. A false positive wastes a human's time and erodes trust in every future report.** + + - If you claim something is missing or broken, show the exact evidence in the code — file path, line number, and what you observed. + - If a conclusion depends on assumptions you haven't confirmed, do not assert it. Verify first; if you cannot verify, do not report. + - "I don't know" is better than a wrong answer. `noop` is better than a speculative finding. + - It's worth the time to verify now versus guessing and forcing someone else to verify later. + - Before filing any issue or opening any PR, re-read your own output as a skeptical reviewer. Ask: "Would a senior engineer on this team find this useful, or would they close it immediately?" If the answer is "close," call `noop` instead. + - Only report findings you would confidently defend in a code review. If you feel the need to hedge with "might," "could," or "possibly," the finding is not ready to file. + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + ## MCP Pagination + + MCP tool responses have a **25,000 token limit**. When responses exceed this limit, the call fails and you must retry with pagination — wasting turns and tokens. Use proactive pagination to stay under the limit. + + ### Recommended `perPage` Values + + - **5-10**: For detailed items (PR diffs, files with patches, issues with comments) + - **20-30**: For medium-detail lists (commits, review comments, issue lists) + - **50-100**: For simple list operations (branches, labels, tags) + + ### Pagination Pattern + + When you need all results from a paginated API: + + 1. Fetch the first page with a conservative `perPage` value + 2. Process the results before fetching the next page + 3. Continue fetching pages until you receive fewer results than `perPage` (indicating the last page) + + ### Error Recovery + + If you see an error like: + - `MCP tool response exceeds maximum allowed tokens (25000)` + - `Response too large for tool [tool_name]` + + Retry the same call with a smaller `perPage` value (halve it). + + ### Tips + + - **Start small**: It's better to make multiple small requests than one that fails + - **Fetch incrementally**: Get an overview first, then details for specific items + - **Use filters**: Combine `perPage` with state, label, or date filters to reduce result size + - **Process as you go**: Don't accumulate all pages before acting — process each batch immediately + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + ## Workflow Editing Guardrails + + - Do not modify files under `.github/workflows/`. + - If asked to change workflow files, place a copy under `github/` (no leading dot) and note that a maintainer must relocate it into `.github/workflows/`. + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + ## Message Footer + + A footer is automatically appended to all comments and reviews. Do not add your own footer or sign-off — the runtime handles this. + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + Before calling `create_pull_request`, call `ready_to_make_pr` and apply its checklist. + + ## create-pull-request Limitations + + - **Patch files**: Max 100 files per PR. If changes span more files, split into multiple focused PRs. + - **Patch size**: Max 1,024 KB by default. Keep changes focused. + - **Title**: Max 128 characters. Sanitized. + - **Body**: No explicit mention/link limits, but bot triggers (`fixes #123`, `closes #456`) are neutralized. + - **Committed changes required**: You must have locally committed changes before creating a PR (unless `allow_empty` is configured). + - **Base branch**: Must be configured in the safe-output config. The PR targets this branch. + - **Max per run**: Typically 1 PR creation per workflow run. + - You may not submit code that modifies files in `.github/workflows/`. Doing so will cause the submission to be rejected. If asked to modify workflow files, propose the change in a copy placed in a `github/` folder (without the leading period) and note in the PR that the file needs to be relocated by someone with workflow write access. + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + You are an agent for __GH_AW_GITHUB_REPOSITORY__. You run on a schedule to pick up an open issue and create a focused pull request that addresses it. Your specific assignment is described in the **Fix Assignment** section below. + + ## Context + + - **Repository**: __GH_AW_GITHUB_REPOSITORY__ + + ## Constraints + + - **CAN**: Read files, search code, modify files locally, run tests and commands, create a pull request. + - **CANNOT**: Directly push to the repository — use `create_pull_request`. + - **Only one PR per run.** + - If no suitable issue is found, call `noop` with a brief reason. + - **Most runs should end with `noop`.** Only open a PR when the fix is clearly correct, tested, and small enough for quick review. + + ## Process + + Follow these steps in order. + + ### Step 1: Gather Candidates + + 1. Call `generate_agents_md` to get the repository's coding guidelines and conventions. If this fails, continue without it. + 2. Follow the candidate gathering instructions in the **Fix Assignment** section. + 3. For each candidate, read the full issue and comments using `issue_read` (methods `get` and `get_comments`). + + ### Step 2: Select a Target + + Choose one issue with: + + - Concrete, actionable instructions (file paths, function names, suggested changes) + - A well-scoped fix that doesn't require design decisions + - No active discussion suggesting the fix should go a different direction + + Skip any issue where the suggested fix is ambiguous, controversial, or too large for a single PR. + + ### Step 3: Implement + + Follow the implementation instructions in the **Fix Assignment** section. The Fix Assignment defines: + - What kind of changes to make + - What tools to use + - Any domain-specific constraints + + ### Step 4: Quality Gate — Self-Review + + Before creating the PR, verify: + + 1. **Fix is correct** — the change directly addresses the issue. + 2. **Tests pass** — you ran the most relevant tests and they pass. + 3. **Scope is minimal** — only changes needed for the fix, no scope creep. + 4. **No regressions** — linters pass, no formatting broken, no new warnings. + + If any check fails, call `noop` with a brief reason. + + ### Step 5: Create the PR + + Call `create_pull_request` with: + - A concise summary of the changes + - A link to the source issue (e.g., "Fixes #123") + - The specific tests that were run and passed + - A note on any items from the issue that were skipped (if any) + + **Fix Assignment:** + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + ### Candidate Search + + Search for open Newbie Contributor Patrol issues: + + ````text + github-search_issues: query="repo:{owner}/{repo} is:issue is:open (label:newbie-contributor OR in:title \"[newbie-contributor]\") sort:updated-asc" + ```` + + ### Implementation + + 1. Read each documentation file mentioned in the issue. + 2. For each finding: + - Add missing prerequisites, setup steps, or explanations where the issue identifies a gap. + - Fix inconsistencies between documentation files. + - Update commands or file paths that don't match the current repository state. + - Document required secrets, permissions, or roles where the step appears. + 3. Keep edits focused on the contributor onboarding path — no rewrites beyond what the issue asks for. + 4. Run any available linters or formatters to verify the changes don't break anything. + 5. Commit the changes locally. + + __GH_AW_EXPR_49B959F1__ + + GH_AW_PROMPT_EOF + - name: Interpolate variables and render templates + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} + GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} + 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/interpolate_prompt.cjs'); + await main(); + - name: Substitute placeholders + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} + GH_AW_GITHUB_ACTOR: ${{ github.actor }} + GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} + GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} + GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} + 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'); + setupGlobals(core, github, context, exec, io); + + const substitutePlaceholders = require('/opt/gh-aw/actions/substitute_placeholders.cjs'); + + // Call the substitution function + return await substitutePlaceholders({ + file: process.env.GH_AW_PROMPT, + substitutions: { + GH_AW_EXPR_49B959F1: process.env.GH_AW_EXPR_49B959F1, + GH_AW_GITHUB_ACTOR: process.env.GH_AW_GITHUB_ACTOR, + GH_AW_GITHUB_EVENT_COMMENT_ID: process.env.GH_AW_GITHUB_EVENT_COMMENT_ID, + GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: process.env.GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER, + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: process.env.GH_AW_GITHUB_EVENT_ISSUE_NUMBER, + 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_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 + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + run: bash /opt/gh-aw/actions/validate_prompt_placeholders.sh + - name: Print prompt + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + run: bash /opt/gh-aw/actions/print_prompt_summary.sh + - name: Upload prompt artifact + if: success() + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: prompt + path: /tmp/gh-aw/aw-prompts/prompt.txt + retention-days: 1 + + agent: + needs: activation + runs-on: ubuntu-latest + permissions: + contents: read + issues: read + pull-requests: read + concurrency: + group: "gh-aw-copilot-${{ github.workflow }}" + env: + DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} + GH_AW_ASSETS_ALLOWED_EXTS: "" + GH_AW_ASSETS_BRANCH: "" + GH_AW_ASSETS_MAX_SIZE_KB: 0 + GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs + 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: ghawnewbiecontributorfixer + outputs: + checkout_pr_success: ${{ steps.checkout-pr.outputs.checkout_pr_success || 'true' }} + has_patch: ${{ steps.collect_output.outputs.has_patch }} + model: ${{ steps.generate_aw_info.outputs.model }} + output: ${{ steps.collect_output.outputs.output }} + output_types: ${{ steps.collect_output.outputs.output_types }} + secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 + with: + destination: /opt/gh-aw/actions + - name: Checkout repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + - name: Create gh-aw temp directory + run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh + - if: hashFiles('go.mod') != '' + name: Setup Go + uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5 + with: + cache: true + go-version-file: go.mod + - if: hashFiles('.python-version') != '' + name: Setup Python + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 + with: + python-version-file: .python-version + - if: hashFiles('.node-version') != '' + name: Setup Node.js (.node-version) + uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6 + with: + node-version-file: .node-version + - if: hashFiles('.node-version') == '' && hashFiles('.nvmrc') != '' + name: Setup Node.js (.nvmrc) + uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6 + with: + node-version-file: .nvmrc + - if: hashFiles('.ruby-version') != '' + name: Setup Ruby + uses: ruby/setup-ruby@09a7688d3b55cf0e976497ff046b70949eeaccfd # v1 + with: + bundler-cache: true + ruby-version: .ruby-version + - id: setup-uv + if: hashFiles('pyproject.toml', 'uv.lock') != '' + name: Setup uv + uses: astral-sh/setup-uv@e58605a9b6da7c637471fab8847a5e5a6b8df081 # v5 + - env: + UV_PATH: ${{ steps.setup-uv.outputs.uv-path }} + WORKSPACE: ${{ github.workspace }} + if: hashFiles('pyproject.toml', 'uv.lock') != '' + name: Expose uv in workspace + run: |- + set -euo pipefail + install_dir="$WORKSPACE/.gh-aw-tools/bin" + mkdir -p "$install_dir" + cp "$UV_PATH" "$install_dir/uv" + chmod +x "$install_dir/uv" + echo "$install_dir" >> "$GITHUB_PATH" + shell: bash + - env: + SETUP_COMMANDS: ${{ inputs.setup-commands }} + if: ${{ inputs.setup-commands != '' }} + name: Repo-specific setup + run: eval "$SETUP_COMMANDS" + + - name: Configure Git credentials + env: + REPO_NAME: ${{ github.repository }} + SERVER_URL: ${{ github.server_url }} + run: | + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git config --global user.name "github-actions[bot]" + # Re-authenticate git with GitHub token + SERVER_URL_STRIPPED="${SERVER_URL#https://}" + git remote set-url origin "https://x-access-token:${{ github.token }}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" + echo "Git configured with standard GitHub Actions identity" + - name: Checkout PR branch + id: checkout-pr + if: | + github.event.pull_request + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + with: + github-token: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/checkout_pr_branch.cjs'); + await main(); + - name: Generate agentic run info + id: generate_aw_info + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + with: + script: | + const fs = require('fs'); + + const awInfo = { + engine_id: "copilot", + engine_name: "GitHub Copilot CLI", + model: "${{ inputs.model }}", + version: "", + agent_version: "0.0.412", + workflow_name: "Newbie Contributor Fixer", + experimental: false, + supports_tools_allowlist: true, + run_id: context.runId, + run_number: context.runNumber, + run_attempt: process.env.GITHUB_RUN_ATTEMPT, + repository: context.repo.owner + '/' + context.repo.repo, + ref: context.ref, + sha: context.sha, + actor: context.actor, + event_name: context.eventName, + staged: false, + allowed_domains: ["agents-md-generator.fastmcp.app","artifacts.elastic.co","cloud.elastic.co","defaults","ela.st","elastic.co","github","go","node","public-code-search.fastmcp.app","python","ruby","www.elastic.co"], + firewall_enabled: true, + awf_version: "v0.20.2", + awmg_version: "v0.1.4", + steps: { + firewall: "squid" + }, + created_at: new Date().toISOString() + }; + + // Write to /tmp/gh-aw directory to avoid inclusion in PR + const tmpPath = '/tmp/gh-aw/aw_info.json'; + fs.writeFileSync(tmpPath, JSON.stringify(awInfo, null, 2)); + console.log('Generated aw_info.json at:', tmpPath); + console.log(JSON.stringify(awInfo, null, 2)); + + // Set model as output for reuse in other steps/jobs + core.setOutput('model', awInfo.model); + - name: Validate COPILOT_GITHUB_TOKEN secret + id: validate-secret + run: /opt/gh-aw/actions/validate_multi_secret.sh COPILOT_GITHUB_TOKEN 'GitHub Copilot CLI' https://github.github.com/gh-aw/reference/engines/#github-copilot-default + env: + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + - name: Install GitHub Copilot CLI + run: /opt/gh-aw/actions/install_copilot_cli.sh 0.0.412 + - name: Install awf binary + run: bash /opt/gh-aw/actions/install_awf_binary.sh v0.20.2 + - name: Determine automatic lockdown mode for GitHub MCP Server + id: determine-automatic-lockdown + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} + GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} + with: + script: | + 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.20.2 ghcr.io/github/gh-aw-firewall/api-proxy:0.20.2 ghcr.io/github/gh-aw-firewall/squid:0.20.2 ghcr.io/github/gh-aw-mcpg:v0.1.4 ghcr.io/github/github-mcp-server:v0.31.0 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' + {"create_pull_request":{"max":1},"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 pull request to propose code changes. Use this after making file edits to submit them for review and merging. The PR will be created from the current branch with your committed changes. For code review comments on an existing PR, use create_pull_request_review_comment instead. CONSTRAINTS: Maximum 1 pull request(s) can be created.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "body": { + "description": "Detailed PR description in Markdown. Include what changes were made, why, testing notes, and any breaking changes. Do NOT repeat the title as a heading.", + "type": "string" + }, + "branch": { + "description": "Source branch name containing the changes. If omitted, uses the current working branch.", + "type": "string" + }, + "draft": { + "description": "Whether to create the PR as a draft. Draft PRs cannot be merged until marked as ready for review. Use mark_pull_request_as_ready_for_review to convert a draft PR. Default: true.", + "type": "boolean" + }, + "labels": { + "description": "Labels to categorize the PR (e.g., 'enhancement', 'bugfix'). Labels must exist in the repository.", + "items": { + "type": "string" + }, + "type": "array" + }, + "title": { + "description": "Concise PR title describing the changes. Follow repository conventions (e.g., conventional commits). The title appears as the main heading.", + "type": "string" + } + }, + "required": [ + "title", + "body" + ], + "type": "object" + }, + "name": "create_pull_request" + }, + { + "description": "Report that a tool or capability needed to complete the task is not available, or share any information you deem important about missing functionality or limitations. Use this when you cannot accomplish what was requested because the required functionality is missing or access is restricted.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "alternatives": { + "description": "Any workarounds, manual steps, or alternative approaches the user could take (max 256 characters).", + "type": "string" + }, + "reason": { + "description": "Explanation of why this tool is needed or what information you want to share about the limitation (max 256 characters).", + "type": "string" + }, + "tool": { + "description": "Optional: Name or description of the missing tool or capability (max 128 characters). Be specific about what functionality is needed.", + "type": "string" + } + }, + "required": [ + "reason" + ], + "type": "object" + }, + "name": "missing_tool" + }, + { + "description": "Log a transparency message when no significant actions are needed. Use this to confirm workflow completion and provide visibility when analysis is complete but no changes or outputs are required (e.g., 'No issues found', 'All checks passed'). This ensures the workflow produces human-visible output even when no other actions are taken.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "message": { + "description": "Status or completion message to log. Should explain what was analyzed and the outcome (e.g., 'Code review complete - no issues found', 'Analysis complete - all tests passing').", + "type": "string" + } + }, + "required": [ + "message" + ], + "type": "object" + }, + "name": "noop" + }, + { + "description": "Report that data or information needed to complete the task is not available. Use this when you cannot accomplish what was requested because required data, context, or information is missing.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "alternatives": { + "description": "Any workarounds, manual steps, or alternative approaches the user could take (max 256 characters).", + "type": "string" + }, + "context": { + "description": "Additional context about the missing data or where it should come from (max 256 characters).", + "type": "string" + }, + "data_type": { + "description": "Type or description of the missing data or information (max 128 characters). Be specific about what data is needed.", + "type": "string" + }, + "reason": { + "description": "Explanation of why this data is needed to complete the task (max 256 characters).", + "type": "string" + } + }, + "required": [], + "type": "object" + }, + "name": "missing_data" + } + ] + GH_AW_SAFE_OUTPUTS_TOOLS_EOF + cat > /opt/gh-aw/safeoutputs/validation.json << 'GH_AW_SAFE_OUTPUTS_VALIDATION_EOF' + { + "create_pull_request": { + "defaultMax": 1, + "fields": { + "body": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "branch": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "draft": { + "type": "boolean" + }, + "labels": { + "type": "array", + "itemType": "string", + "itemSanitize": true, + "itemMaxLength": 128 + }, + "repo": { + "type": "string", + "maxLength": 256 + }, + "title": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 128 + } + } + }, + "missing_data": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "context": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "data_type": { + "type": "string", + "sanitize": true, + "maxLength": 128 + }, + "reason": { + "type": "string", + "sanitize": true, + "maxLength": 256 + } + } + }, + "missing_tool": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 512 + }, + "reason": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "tool": { + "type": "string", + "sanitize": true, + "maxLength": 128 + } + } + }, + "noop": { + "defaultMax": 1, + "fields": { + "message": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + } + } + } + } + GH_AW_SAFE_OUTPUTS_VALIDATION_EOF + - name: Generate Safe Outputs MCP Server Config + id: safe-outputs-config + run: | + # Generate a secure random API key (360 bits of entropy, 40+ chars) + # Mask immediately to prevent timing vulnerabilities + API_KEY=$(openssl rand -base64 45 | tr -d '/+=') + echo "::add-mask::${API_KEY}" + + PORT=3001 + + # Set outputs for next steps + { + echo "safe_outputs_api_key=${API_KEY}" + echo "safe_outputs_port=${PORT}" + } >> "$GITHUB_OUTPUT" + + echo "Safe Outputs MCP server will run on port ${PORT}" + + - name: Start Safe Outputs MCP HTTP Server + id: safe-outputs-start + env: + DEBUG: '*' + GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-config.outputs.safe_outputs_port }} + GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-config.outputs.safe_outputs_api_key }} + GH_AW_SAFE_OUTPUTS_TOOLS_PATH: /opt/gh-aw/safeoutputs/tools.json + GH_AW_SAFE_OUTPUTS_CONFIG_PATH: /opt/gh-aw/safeoutputs/config.json + GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs + run: | + # Environment variables are set above to prevent template injection + export DEBUG + export GH_AW_SAFE_OUTPUTS_PORT + export GH_AW_SAFE_OUTPUTS_API_KEY + export GH_AW_SAFE_OUTPUTS_TOOLS_PATH + export GH_AW_SAFE_OUTPUTS_CONFIG_PATH + export GH_AW_MCP_LOG_DIR + + bash /opt/gh-aw/actions/start_safe_outputs_server.sh + + - name: Setup Safe Inputs Config + run: | + mkdir -p /opt/gh-aw/safe-inputs/logs + cat > /opt/gh-aw/safe-inputs/tools.json << 'GH_AW_SAFE_INPUTS_TOOLS_EOF' + { + "serverName": "safeinputs", + "version": "1.0.0", + "logDir": "/opt/gh-aw/safe-inputs/logs", + "tools": [ + { + "name": "ready-to-make-pr", + "description": "Run the PR readiness checklist before creating or updating a PR", + "inputSchema": { + "properties": {}, + "type": "object" + }, + "handler": "ready-to-make-pr.cjs", + "timeout": 60 + } + ] + } + GH_AW_SAFE_INPUTS_TOOLS_EOF + cat > /opt/gh-aw/safe-inputs/mcp-server.cjs << 'GH_AW_SAFE_INPUTS_SERVER_EOF' + const path = require("path"); + const { startHttpServer } = require("./safe_inputs_mcp_server_http.cjs"); + const configPath = path.join(__dirname, "tools.json"); + const port = parseInt(process.env.GH_AW_SAFE_INPUTS_PORT || "3000", 10); + const apiKey = process.env.GH_AW_SAFE_INPUTS_API_KEY || ""; + startHttpServer(configPath, { + port: port, + stateless: true, + logDir: "/opt/gh-aw/safe-inputs/logs" + }).catch(error => { + console.error("Failed to start safe-inputs HTTP server:", error); + process.exit(1); + }); + GH_AW_SAFE_INPUTS_SERVER_EOF + chmod +x /opt/gh-aw/safe-inputs/mcp-server.cjs + + - name: Setup Safe Inputs Tool Files + run: | + cat > /opt/gh-aw/safe-inputs/ready-to-make-pr.cjs << 'GH_AW_SAFE_INPUTS_JS_READY-TO-MAKE-PR_EOF' + async function execute(inputs) { + const fs = require('fs'); + const find = (...paths) => paths.find(p => fs.existsSync(p)) || null; + const contributing = find('CONTRIBUTING.md', 'CONTRIBUTING.rst', 'docs/CONTRIBUTING.md', 'docs/contributing.md'); + const prTemplate = find('.github/pull_request_template.md', '.github/PULL_REQUEST_TEMPLATE.md', '.github/PULL_REQUEST_TEMPLATE/pull_request_template.md'); + const checklist = []; + if (contributing) checklist.push(`Review the contributing guide (${contributing}) before opening or updating a PR.`); + if (prTemplate) checklist.push(`Follow the PR template (${prTemplate}) for title, description, and validation notes.`); + checklist.push('Confirm the requested task is fully completed and validated before creating or pushing PR changes.'); + return { status: 'ok', checklist, contributing_guide: contributing, pr_template: prTemplate }; + } + module.exports = { execute }; + GH_AW_SAFE_INPUTS_JS_READY-TO-MAKE-PR_EOF + + - name: Generate Safe Inputs MCP Server Config + id: safe-inputs-config + run: | + # Generate a secure random API key (360 bits of entropy, 40+ chars) + # Mask immediately to prevent timing vulnerabilities + API_KEY=$(openssl rand -base64 45 | tr -d '/+=') + echo "::add-mask::${API_KEY}" + + PORT=3000 + + # Set outputs for next steps + { + echo "safe_inputs_api_key=${API_KEY}" + echo "safe_inputs_port=${PORT}" + } >> "$GITHUB_OUTPUT" + + echo "Safe Inputs MCP server will run on port ${PORT}" + + - name: Start Safe Inputs MCP HTTP Server + id: safe-inputs-start + env: + DEBUG: '*' + GH_AW_SAFE_INPUTS_PORT: ${{ steps.safe-inputs-config.outputs.safe_inputs_port }} + GH_AW_SAFE_INPUTS_API_KEY: ${{ steps.safe-inputs-config.outputs.safe_inputs_api_key }} + run: | + # Environment variables are set above to prevent template injection + export DEBUG + export GH_AW_SAFE_INPUTS_PORT + export GH_AW_SAFE_INPUTS_API_KEY + + bash /opt/gh-aw/actions/start_safe_inputs_server.sh + + - name: Start MCP Gateway + id: start-mcp-gateway + env: + GH_AW_SAFE_INPUTS_API_KEY: ${{ steps.safe-inputs-start.outputs.api_key }} + GH_AW_SAFE_INPUTS_PORT: ${{ steps.safe-inputs-start.outputs.port }} + GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} + GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-start.outputs.api_key }} + GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-start.outputs.port }} + GITHUB_MCP_LOCKDOWN: ${{ steps.determine-automatic-lockdown.outputs.lockdown == 'true' && '1' || '0' }} + GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + run: | + set -eo pipefail + mkdir -p /tmp/gh-aw/mcp-config + + # Export gateway environment variables for MCP config and gateway script + export MCP_GATEWAY_PORT="80" + export MCP_GATEWAY_DOMAIN="host.docker.internal" + MCP_GATEWAY_API_KEY=$(openssl rand -base64 45 | tr -d '/+=') + echo "::add-mask::${MCP_GATEWAY_API_KEY}" + export MCP_GATEWAY_API_KEY + export MCP_GATEWAY_PAYLOAD_DIR="/tmp/gh-aw/mcp-payloads" + mkdir -p "${MCP_GATEWAY_PAYLOAD_DIR}" + export DEBUG="*" + + export GH_AW_ENGINE="copilot" + 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 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_LOCKDOWN -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_INPUTS_PORT -e GH_AW_SAFE_INPUTS_API_KEY -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.1.4' + + mkdir -p /home/runner/.copilot + cat << GH_AW_MCP_CONFIG_EOF | bash /opt/gh-aw/actions/start_mcp_gateway.sh + { + "mcpServers": { + "agents-md-generator": { + "type": "http", + "url": "https://agents-md-generator.fastmcp.app/mcp", + "tools": [ + "generate_agents_md" + ] + }, + "github": { + "type": "stdio", + "container": "ghcr.io/github/github-mcp-server:v0.31.0", + "env": { + "GITHUB_LOCKDOWN_MODE": "$GITHUB_MCP_LOCKDOWN", + "GITHUB_PERSONAL_ACCESS_TOKEN": "\${GITHUB_MCP_SERVER_TOKEN}", + "GITHUB_READ_ONLY": "1", + "GITHUB_TOOLSETS": "repos,issues,pull_requests,search" + } + }, + "public-code-search": { + "type": "http", + "url": "https://public-code-search.fastmcp.app/mcp", + "tools": [ + "search_code" + ] + }, + "safeinputs": { + "type": "http", + "url": "http://host.docker.internal:$GH_AW_SAFE_INPUTS_PORT", + "headers": { + "Authorization": "\${GH_AW_SAFE_INPUTS_API_KEY}" + } + }, + "safeoutputs": { + "type": "http", + "url": "http://host.docker.internal:$GH_AW_SAFE_OUTPUTS_PORT", + "headers": { + "Authorization": "\${GH_AW_SAFE_OUTPUTS_API_KEY}" + } + } + }, + "gateway": { + "port": $MCP_GATEWAY_PORT, + "domain": "${MCP_GATEWAY_DOMAIN}", + "apiKey": "${MCP_GATEWAY_API_KEY}", + "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" + } + } + GH_AW_MCP_CONFIG_EOF + - name: Generate workflow overview + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + with: + script: | + const { generateWorkflowOverview } = require('/opt/gh-aw/actions/generate_workflow_overview.cjs'); + await generateWorkflowOverview(core); + - name: Download prompt artifact + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 + with: + name: prompt + path: /tmp/gh-aw/aw-prompts + - name: Clean git credentials + run: bash /opt/gh-aw/actions/clean_git_credentials.sh + - name: Execute GitHub Copilot CLI + id: agentic_execution + # Copilot CLI tool arguments (sorted): + timeout-minutes: 90 + run: | + set -o pipefail + sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --allow-domains '*.githubusercontent.com,*.jsr.io,*.pythonhosted.org,*.rvm.io,agents-md-generator.fastmcp.app,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.rubygems.org,api.snapcraft.io,archive.ubuntu.com,artifacts.elastic.co,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,bun.sh,bundler.rubygems.org,cache.ruby-lang.org,cdn.jsdelivr.net,cloud.elastic.co,codeload.github.com,conda.anaconda.org,conda.binstar.org,crates.io,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,deb.nodesource.com,deno.land,ela.st,elastic.co,esm.sh,files.pythonhosted.org,gems.rubyforge.org,gems.rubyonrails.org,get.pnpm.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,host.docker.internal,index.crates.io,index.rubygems.org,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,lfs.github.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,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,pip.pypa.io,pkg.go.dev,ppa.launchpad.net,proxy.golang.org,public-code-search.fastmcp.app,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.bower.io,registry.npmjs.com,registry.npmjs.org,registry.yarnpkg.com,repo.anaconda.com,repo.continuum.io,repo.yarnpkg.com,rubygems.org,rubygems.pkg.github.com,s.symcb.com,s.symcd.com,security.ubuntu.com,skimdb.npmjs.com,static.crates.io,storage.googleapis.com,sum.golang.org,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.elastic.co,www.npmjs.com,www.npmjs.org,yarnpkg.com' --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.20.2 --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 --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log + env: + COPILOT_AGENT_RUNNER_TYPE: STANDALONE + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} + GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} + GITHUB_HEAD_REF: ${{ github.head_ref }} + GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + GITHUB_REF_NAME: ${{ github.ref_name }} + GITHUB_STEP_SUMMARY: ${{ env.GITHUB_STEP_SUMMARY }} + GITHUB_WORKSPACE: ${{ github.workspace }} + XDG_CONFIG_HOME: /home/runner + - name: Configure Git credentials + env: + REPO_NAME: ${{ github.repository }} + SERVER_URL: ${{ github.server_url }} + run: | + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git config --global user.name "github-actions[bot]" + # Re-authenticate git with GitHub token + SERVER_URL_STRIPPED="${SERVER_URL#https://}" + git remote set-url origin "https://x-access-token:${{ github.token }}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" + echo "Git configured with standard GitHub Actions identity" + - name: Copy Copilot session state files to logs + if: always() + continue-on-error: true + run: | + # Copy Copilot session state files to logs folder for artifact collection + # This ensures they are in /tmp/gh-aw/ where secret redaction can scan them + SESSION_STATE_DIR="$HOME/.copilot/session-state" + LOGS_DIR="/tmp/gh-aw/sandbox/agent/logs" + + if [ -d "$SESSION_STATE_DIR" ]; then + echo "Copying Copilot session state files from $SESSION_STATE_DIR to $LOGS_DIR" + mkdir -p "$LOGS_DIR" + cp -v "$SESSION_STATE_DIR"/*.jsonl "$LOGS_DIR/" 2>/dev/null || true + echo "Session state files copied successfully" + else + echo "No session-state directory found at $SESSION_STATE_DIR" + fi + - name: Stop MCP Gateway + if: always() + continue-on-error: true + env: + MCP_GATEWAY_PORT: ${{ steps.start-mcp-gateway.outputs.gateway-port }} + MCP_GATEWAY_API_KEY: ${{ steps.start-mcp-gateway.outputs.gateway-api-key }} + GATEWAY_PID: ${{ steps.start-mcp-gateway.outputs.gateway-pid }} + run: | + bash /opt/gh-aw/actions/stop_mcp_gateway.sh "$GATEWAY_PID" + - name: Redact secrets in logs + if: always() + 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/redact_secrets.cjs'); + await main(); + env: + GH_AW_SECRET_NAMES: 'COPILOT_GITHUB_TOKEN,GH_AW_GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,GITHUB_TOKEN' + SECRET_COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + SECRET_GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} + SECRET_GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} + SECRET_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Upload Safe Outputs + if: always() + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: safe-output + path: ${{ env.GH_AW_SAFE_OUTPUTS }} + if-no-files-found: warn + - name: Ingest agent output + id: collect_output + if: always() + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} + GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,*.jsr.io,*.pythonhosted.org,*.rvm.io,agents-md-generator.fastmcp.app,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.rubygems.org,api.snapcraft.io,archive.ubuntu.com,artifacts.elastic.co,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,bun.sh,bundler.rubygems.org,cache.ruby-lang.org,cdn.jsdelivr.net,cloud.elastic.co,codeload.github.com,conda.anaconda.org,conda.binstar.org,crates.io,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,deb.nodesource.com,deno.land,ela.st,elastic.co,esm.sh,files.pythonhosted.org,gems.rubyforge.org,gems.rubyonrails.org,get.pnpm.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,host.docker.internal,index.crates.io,index.rubygems.org,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,lfs.github.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,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,pip.pypa.io,pkg.go.dev,ppa.launchpad.net,proxy.golang.org,public-code-search.fastmcp.app,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.bower.io,registry.npmjs.com,registry.npmjs.org,registry.yarnpkg.com,repo.anaconda.com,repo.continuum.io,repo.yarnpkg.com,rubygems.org,rubygems.pkg.github.com,s.symcb.com,s.symcd.com,security.ubuntu.com,skimdb.npmjs.com,static.crates.io,storage.googleapis.com,sum.golang.org,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.elastic.co,www.npmjs.com,www.npmjs.org,yarnpkg.com" + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_API_URL: ${{ github.api_url }} + 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/collect_ndjson_output.cjs'); + await main(); + - name: Upload sanitized agent output + if: always() && env.GH_AW_AGENT_OUTPUT + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: agent-output + path: ${{ env.GH_AW_AGENT_OUTPUT }} + if-no-files-found: warn + - name: Upload engine output files + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: agent_outputs + path: | + /tmp/gh-aw/sandbox/agent/logs/ + /tmp/gh-aw/redacted-urls.log + if-no-files-found: ignore + - name: Parse agent logs for step summary + if: always() + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: /tmp/gh-aw/sandbox/agent/logs/ + 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/parse_copilot_log.cjs'); + await main(); + - name: Parse Safe Inputs logs for step summary + if: always() + 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/parse_safe_inputs_logs.cjs'); + await main(); + - name: Parse MCP Gateway logs for step summary + if: always() + 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/parse_mcp_gateway_log.cjs'); + await main(); + - name: Print firewall logs + if: always() + continue-on-error: true + env: + AWF_LOGS_DIR: /tmp/gh-aw/sandbox/firewall/logs + run: | + # Fix permissions on firewall logs so they can be uploaded as artifacts + # AWF runs with sudo, creating files owned by root + sudo chmod -R a+r /tmp/gh-aw/sandbox/firewall/logs 2>/dev/null || true + # Only run awf logs summary if awf command exists (it may not be installed if workflow failed before install step) + if command -v awf &> /dev/null; then + awf logs summary | tee -a "$GITHUB_STEP_SUMMARY" + else + echo 'AWF binary not installed, skipping firewall log summary' + fi + - name: Upload agent artifacts + if: always() + continue-on-error: true + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: agent-artifacts + path: | + /tmp/gh-aw/aw-prompts/prompt.txt + /tmp/gh-aw/aw_info.json + /tmp/gh-aw/mcp-logs/ + /tmp/gh-aw/safe-inputs/logs/ + /tmp/gh-aw/sandbox/firewall/logs/ + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/agent/ + /tmp/gh-aw/aw-*.patch + if-no-files-found: ignore + + conclusion: + needs: + - activation + - agent + - detection + - safe_outputs + if: (always()) && (needs.agent.result != 'skipped') + runs-on: ubuntu-slim + permissions: + contents: write + issues: write + pull-requests: write + outputs: + noop_message: ${{ steps.noop.outputs.noop_message }} + tools_reported: ${{ steps.missing_tool.outputs.tools_reported }} + total_count: ${{ steps.missing_tool.outputs.total_count }} + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 + with: + destination: /opt/gh-aw/actions + - name: Download agent output artifact + continue-on-error: true + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 + with: + name: agent-output + path: /tmp/gh-aw/safeoutputs/ + - name: Setup agent output environment variable + run: | + mkdir -p /tmp/gh-aw/safeoutputs/ + find "/tmp/gh-aw/safeoutputs/" -type f -print + echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/safeoutputs/agent_output.json" >> "$GITHUB_ENV" + - name: Process No-Op Messages + id: noop + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_NOOP_MAX: 1 + GH_AW_WORKFLOW_NAME: "Newbie Contributor Fixer" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/noop.cjs'); + await main(); + - name: Record Missing Tool + id: missing_tool + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_WORKFLOW_NAME: "Newbie Contributor Fixer" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/missing_tool.cjs'); + await main(); + - name: Handle Agent Failure + id: handle_agent_failure + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_WORKFLOW_NAME: "Newbie Contributor Fixer" + 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: "gh-aw-newbie-contributor-fixer" + GH_AW_SECRET_VERIFICATION_RESULT: ${{ needs.agent.outputs.secret_verification_result }} + GH_AW_CHECKOUT_PR_SUCCESS: ${{ needs.agent.outputs.checkout_pr_success }} + GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\"}" + GH_AW_GROUP_REPORTS: "false" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/handle_agent_failure.cjs'); + await main(); + - name: Handle No-Op Message + id: handle_noop_message + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_WORKFLOW_NAME: "Newbie Contributor Fixer" + 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 }} + GH_AW_NOOP_REPORT_AS_ISSUE: "true" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/handle_noop_message.cjs'); + await main(); + - name: Handle Create Pull Request Error + id: handle_create_pr_error + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_WORKFLOW_NAME: "Newbie Contributor Fixer" + GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/handle_create_pr_error.cjs'); + await main(); + + detection: + needs: agent + if: needs.agent.outputs.output_types != '' || needs.agent.outputs.has_patch == 'true' + runs-on: ubuntu-latest + permissions: {} + concurrency: + group: "gh-aw-copilot-${{ github.workflow }}" + timeout-minutes: 10 + outputs: + success: ${{ steps.parse_results.outputs.success }} + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 + with: + destination: /opt/gh-aw/actions + - name: Download agent artifacts + continue-on-error: true + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 + with: + name: agent-artifacts + path: /tmp/gh-aw/threat-detection/ + - name: Download agent output artifact + continue-on-error: true + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 + with: + name: agent-output + path: /tmp/gh-aw/threat-detection/ + - name: Print agent output types + env: + AGENT_OUTPUT_TYPES: ${{ needs.agent.outputs.output_types }} + run: | + echo "Agent output-types: $AGENT_OUTPUT_TYPES" + - name: Setup threat detection + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + WORKFLOW_NAME: "Newbie Contributor Fixer" + WORKFLOW_DESCRIPTION: "Fix newbie-contributor-patrol issues by improving documentation and opening a focused PR" + HAS_PATCH: ${{ needs.agent.outputs.has_patch }} + 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/setup_threat_detection.cjs'); + await main(); + - name: Ensure threat-detection directory and log + run: | + mkdir -p /tmp/gh-aw/threat-detection + touch /tmp/gh-aw/threat-detection/detection.log + - name: Validate COPILOT_GITHUB_TOKEN secret + id: validate-secret + run: /opt/gh-aw/actions/validate_multi_secret.sh COPILOT_GITHUB_TOKEN 'GitHub Copilot CLI' https://github.github.com/gh-aw/reference/engines/#github-copilot-default + env: + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + - name: Install GitHub Copilot CLI + run: /opt/gh-aw/actions/install_copilot_cli.sh 0.0.412 + - name: Execute GitHub Copilot CLI + id: agentic_execution + # Copilot CLI tool arguments (sorted): + # --allow-tool shell(cat) + # --allow-tool shell(grep) + # --allow-tool shell(head) + # --allow-tool shell(jq) + # --allow-tool shell(ls) + # --allow-tool shell(tail) + # --allow-tool shell(wc) + timeout-minutes: 20 + run: | + set -o pipefail + COPILOT_CLI_INSTRUCTION="$(cat /tmp/gh-aw/aw-prompts/prompt.txt)" + mkdir -p /tmp/ + mkdir -p /tmp/gh-aw/ + mkdir -p /tmp/gh-aw/agent/ + mkdir -p /tmp/gh-aw/sandbox/agent/logs/ + copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log + env: + COPILOT_AGENT_RUNNER_TYPE: STANDALONE + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GITHUB_HEAD_REF: ${{ github.head_ref }} + GITHUB_REF_NAME: ${{ github.ref_name }} + GITHUB_STEP_SUMMARY: ${{ env.GITHUB_STEP_SUMMARY }} + GITHUB_WORKSPACE: ${{ github.workspace }} + XDG_CONFIG_HOME: /home/runner + - name: Parse threat detection results + id: parse_results + 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/parse_threat_detection_results.cjs'); + await main(); + - name: Upload threat detection log + if: always() + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: threat-detection.log + path: /tmp/gh-aw/threat-detection/detection.log + if-no-files-found: ignore + + pre_activation: + runs-on: ubuntu-slim + outputs: + activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 + with: + destination: /opt/gh-aw/actions + - name: Check team membership for workflow + id: check_membership + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_REQUIRED_ROLES: admin,maintainer,write + GH_AW_ALLOWED_BOTS: ${{ inputs.allowed-bot-users }} + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + 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_membership.cjs'); + await main(); + + safe_outputs: + needs: + - activation + - agent + - detection + if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (needs.detection.outputs.success == 'true') + runs-on: ubuntu-slim + permissions: + contents: write + issues: write + pull-requests: write + timeout-minutes: 15 + env: + GH_AW_ENGINE_ID: "copilot" + GH_AW_ENGINE_MODEL: "${{ inputs.model }}" + GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\"}" + GH_AW_WORKFLOW_ID: "gh-aw-newbie-contributor-fixer" + GH_AW_WORKFLOW_NAME: "Newbie Contributor Fixer" + outputs: + create_discussion_error_count: ${{ steps.process_safe_outputs.outputs.create_discussion_error_count }} + create_discussion_errors: ${{ steps.process_safe_outputs.outputs.create_discussion_errors }} + process_safe_outputs_processed_count: ${{ steps.process_safe_outputs.outputs.processed_count }} + process_safe_outputs_temporary_id_map: ${{ steps.process_safe_outputs.outputs.temporary_id_map }} + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 + with: + destination: /opt/gh-aw/actions + - name: Download agent output artifact + continue-on-error: true + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 + with: + name: agent-output + path: /tmp/gh-aw/safeoutputs/ + - name: Setup agent output environment variable + run: | + mkdir -p /tmp/gh-aw/safeoutputs/ + find "/tmp/gh-aw/safeoutputs/" -type f -print + echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/safeoutputs/agent_output.json" >> "$GITHUB_ENV" + - name: Download patch artifact + continue-on-error: true + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 + with: + name: agent-artifacts + path: /tmp/gh-aw/ + - name: Checkout repository + if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + ref: ${{ github.base_ref || github.ref_name }} + token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + persist-credentials: false + fetch-depth: 1 + - name: Configure Git credentials + if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) + env: + REPO_NAME: ${{ github.repository }} + SERVER_URL: ${{ github.server_url }} + GIT_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + run: | + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git config --global user.name "github-actions[bot]" + # Re-authenticate git with GitHub token + SERVER_URL_STRIPPED="${SERVER_URL#https://}" + git remote set-url origin "https://x-access-token:${GIT_TOKEN}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" + echo "Git configured with standard GitHub Actions identity" + - name: Process Safe Outputs + id: process_safe_outputs + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_pull_request\":{\"base_branch\":\"${{ github.base_ref || github.ref_name }}\",\"max\":1,\"max_patch_size\":1024},\"missing_data\":{},\"missing_tool\":{}}" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/safe_output_handler_manager.cjs'); + await main(); + - name: Upload safe output items manifest + if: always() + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: safe-output-items + path: /tmp/safe-output-items.jsonl + if-no-files-found: warn + diff --git a/.github/workflows/gh-aw-newbie-contributor-fixer.md b/.github/workflows/gh-aw-newbie-contributor-fixer.md new file mode 100644 index 00000000..2b7d210b --- /dev/null +++ b/.github/workflows/gh-aw-newbie-contributor-fixer.md @@ -0,0 +1,104 @@ +--- +inlined-imports: true +name: "Newbie Contributor Fixer" +description: "Fix newbie-contributor-patrol issues by improving documentation and opening a focused PR" +imports: + - gh-aw-fragments/elastic-tools.md + - gh-aw-fragments/runtime-setup.md + - gh-aw-fragments/formatting.md + - gh-aw-fragments/rigor.md + - gh-aw-fragments/mcp-pagination.md + - gh-aw-fragments/workflow-edit-guardrails.md + - gh-aw-fragments/messages-footer.md + - gh-aw-fragments/safe-output-create-pr.md + - gh-aw-fragments/scheduled-fix.md +engine: + id: copilot + model: ${{ inputs.model }} +on: + workflow_call: + inputs: + model: + description: "AI model to use" + type: string + required: false + default: "gpt-5.3-codex" + additional-instructions: + description: "Repo-specific instructions appended to the agent prompt" + type: string + required: false + default: "" + setup-commands: + description: "Shell commands to run before the agent starts (dependency install, build, etc.)" + type: string + required: false + default: "" + allowed-bot-users: + description: "Allowlisted bot actor usernames (comma-separated)" + type: string + required: false + default: "github-actions[bot]" + messages-footer: + description: "Footer appended to all agent comments and reviews" + type: string + required: false + default: "" + secrets: + COPILOT_GITHUB_TOKEN: + required: true + roles: [admin, maintainer, write] + bots: + - "${{ inputs.allowed-bot-users }}" +concurrency: + group: newbie-contributor-fixer + cancel-in-progress: true +permissions: + contents: read + issues: read + pull-requests: read +tools: + github: + toolsets: [repos, issues, pull_requests, search] + bash: true + web-fetch: +network: + allowed: + - defaults + - github + - go + - node + - python + - ruby +strict: false +safe-outputs: + noop: +timeout-minutes: 90 +steps: + - name: Repo-specific setup + if: ${{ inputs.setup-commands != '' }} + env: + SETUP_COMMANDS: ${{ inputs.setup-commands }} + run: eval "$SETUP_COMMANDS" +--- + +### Candidate Search + +Search for open Newbie Contributor Patrol issues: + +````text +github-search_issues: query="repo:{owner}/{repo} is:issue is:open (label:newbie-contributor OR in:title \"[newbie-contributor]\") sort:updated-asc" +```` + +### Implementation + +1. Read each documentation file mentioned in the issue. +2. For each finding: + - Add missing prerequisites, setup steps, or explanations where the issue identifies a gap. + - Fix inconsistencies between documentation files. + - Update commands or file paths that don't match the current repository state. + - Document required secrets, permissions, or roles where the step appears. +3. Keep edits focused on the contributor onboarding path — no rewrites beyond what the issue asks for. +4. Run any available linters or formatters to verify the changes don't break anything. +5. Commit the changes locally. + +${{ inputs.additional-instructions }} diff --git a/.github/workflows/gh-aw-docs-new-contributor-review-external.lock.yml b/.github/workflows/gh-aw-newbie-contributor-patrol-external.lock.yml similarity index 94% rename from .github/workflows/gh-aw-docs-new-contributor-review-external.lock.yml rename to .github/workflows/gh-aw-newbie-contributor-patrol-external.lock.yml index 7edf9be3..75108553 100644 --- a/.github/workflows/gh-aw-docs-new-contributor-review-external.lock.yml +++ b/.github/workflows/gh-aw-newbie-contributor-patrol-external.lock.yml @@ -32,11 +32,13 @@ # - gh-aw-fragments/rigor.md # - gh-aw-fragments/runtime-setup.md # - gh-aw-fragments/safe-output-create-issue.md -# - gh-aw-fragments/scheduled-report.md +# - gh-aw-fragments/scheduled-audit.md # -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"6fc129b697dfc73906743f61523bbdd62c9e5fb17290422f0ce461272078c160"} +# inlined-imports: true +# +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"fc58e605bfa7ecfb4131d8ac36c2476337519dab3c704d204dc3c54d3f106d49"} -name: "Docs New Contributor Review External" +name: "Newbie Contributor Patrol External" "on": # bots: # Bots processed as bot check in pre-activation job # - ${{ inputs.allowed-bot-users }} # Bots processed as bot check in pre-activation job @@ -61,6 +63,11 @@ name: "Docs New Contributor Review External" description: Footer appended to all agent comments and reviews required: false type: string + model: + default: gpt-5.3-codex + description: AI model to use + required: false + type: string setup-commands: default: "" description: Shell commands to run before the agent starts (dependency install, build, etc.) @@ -74,9 +81,9 @@ permissions: {} concurrency: cancel-in-progress: true - group: docs-new-contributor-review-external + group: newbie-contributor-patrol-external -run-name: "Docs New Contributor Review External" +run-name: "Newbie Contributor Patrol External" jobs: activation: @@ -90,7 +97,7 @@ jobs: comment_repo: "" steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Validate context variables @@ -112,7 +119,7 @@ jobs: - name: Check workflow file timestamps uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: - GH_AW_WORKFLOW_FILE: "gh-aw-docs-new-contributor-review-external.lock.yml" + GH_AW_WORKFLOW_FILE: "gh-aw-newbie-contributor-patrol-external.lock.yml" with: script: | const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); @@ -167,6 +174,25 @@ jobs: **Critical**: Tool calls write structured data that downstream jobs process. Without tool calls, follow-up actions will be skipped. **Note**: If you made no other safe output tool calls during this workflow execution, call the "noop" tool to provide a status message indicating completion or that no actions were needed. + + --- + + ## Creating an Issue, Reporting Missing Tools or Functionality, Reporting Missing Data + + **IMPORTANT**: To perform the actions listed above, use the **safeoutputs** tools. Do NOT use `gh`, do NOT call the GitHub API directly. You do not have write access to the GitHub repository. + + **Creating an Issue** + + To create an issue, use the create_issue tool from safeoutputs. + + **Reporting Missing Tools or Functionality** + + To report a missing tool or capability, use the missing_tool tool from safeoutputs. + + **Reporting Missing Data** + + To report missing data required to achieve a goal, use the missing_data tool from safeoutputs. + @@ -284,9 +310,7 @@ jobs: - **Mentions**: `@mentions` in the body are neutralized (backticked) by default. GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - # Scheduled Report Agent - - You are a report agent for __GH_AW_GITHUB_REPOSITORY__. You run on a schedule to investigate the repository and file an issue when something needs attention. Your specific assignment is described in the **Report Assignment** section below. + You are an agent for __GH_AW_GITHUB_REPOSITORY__. You run on a schedule to investigate the repository and file an issue when something needs attention. Your specific assignment is described in the **Report Assignment** section below. ## Context @@ -350,7 +374,7 @@ jobs: - Make suggested actions concrete enough to act on without re-investigating - If a finding is ambiguous, it does not pass the quality gate — drop it - ## Report Assignment + **Report Assignment:** GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" @@ -497,7 +521,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: ghawdocsnewcontributorreviewexternal + GH_AW_WORKFLOW_ID_SANITIZED: ghawnewbiecontributorpatrolexternal outputs: checkout_pr_success: ${{ steps.checkout-pr.outputs.checkout_pr_success || 'true' }} has_patch: ${{ steps.collect_output.outputs.has_patch }} @@ -507,7 +531,7 @@ jobs: secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Checkout repository @@ -601,10 +625,10 @@ jobs: const awInfo = { engine_id: "copilot", engine_name: "GitHub Copilot CLI", - model: "gpt-5.3-codex", + model: "${{ inputs.model }}", version: "", agent_version: "0.0.412", - workflow_name: "Docs New Contributor Review External", + workflow_name: "Newbie Contributor Patrol External", experimental: false, supports_tools_allowlist: true, run_id: context.runId, @@ -666,7 +690,7 @@ jobs: 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 \"[docs-new-contributor-external] \".", + "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 \"[newbie-contributor-external] \".", "inputSchema": { "additionalProperties": false, "properties": { @@ -812,6 +836,31 @@ jobs: } } }, + "missing_data": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "context": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "data_type": { + "type": "string", + "sanitize": true, + "maxLength": 128 + }, + "reason": { + "type": "string", + "sanitize": true, + "maxLength": 256 + } + } + }, "missing_tool": { "defaultMax": 20, "fields": { @@ -982,10 +1031,11 @@ jobs: run: | set -o pipefail sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --allow-domains '*.githubusercontent.com,*.jsr.io,*.pythonhosted.org,*.rvm.io,agents-md-generator.fastmcp.app,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.rubygems.org,api.snapcraft.io,archive.ubuntu.com,artifacts.elastic.co,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,bun.sh,bundler.rubygems.org,cache.ruby-lang.org,cdn.jsdelivr.net,cloud.elastic.co,codeload.github.com,conda.anaconda.org,conda.binstar.org,crates.io,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,deb.nodesource.com,deno.land,ela.st,elastic.co,esm.sh,files.pythonhosted.org,gems.rubyforge.org,gems.rubyonrails.org,get.pnpm.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,host.docker.internal,index.crates.io,index.rubygems.org,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,lfs.github.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,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,pip.pypa.io,pkg.go.dev,ppa.launchpad.net,proxy.golang.org,public-code-search.fastmcp.app,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.bower.io,registry.npmjs.com,registry.npmjs.org,registry.yarnpkg.com,repo.anaconda.com,repo.continuum.io,repo.yarnpkg.com,rubygems.org,rubygems.pkg.github.com,s.symcb.com,s.symcd.com,security.ubuntu.com,skimdb.npmjs.com,static.crates.io,storage.googleapis.com,sum.golang.org,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.elastic.co,www.npmjs.com,www.npmjs.org,yarnpkg.com' --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.20.2 --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 --model gpt-5.3-codex --allow-all-tools --allow-all-paths --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log + -- /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 --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} @@ -1151,7 +1201,7 @@ jobs: total_count: ${{ steps.missing_tool.outputs.total_count }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent output artifact @@ -1171,7 +1221,7 @@ jobs: env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} GH_AW_NOOP_MAX: 1 - GH_AW_WORKFLOW_NAME: "Docs New Contributor Review External" + GH_AW_WORKFLOW_NAME: "Newbie Contributor Patrol External" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | @@ -1184,7 +1234,7 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_WORKFLOW_NAME: "Docs New Contributor Review External" + GH_AW_WORKFLOW_NAME: "Newbie Contributor Patrol External" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | @@ -1197,10 +1247,10 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_WORKFLOW_NAME: "Docs New Contributor Review External" + GH_AW_WORKFLOW_NAME: "Newbie Contributor Patrol External" 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: "gh-aw-docs-new-contributor-review-external" + GH_AW_WORKFLOW_ID: "gh-aw-newbie-contributor-patrol-external" GH_AW_SECRET_VERIFICATION_RESULT: ${{ needs.agent.outputs.secret_verification_result }} GH_AW_CHECKOUT_PR_SUCCESS: ${{ needs.agent.outputs.checkout_pr_success }} GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\"}" @@ -1217,7 +1267,7 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_WORKFLOW_NAME: "Docs New Contributor Review External" + GH_AW_WORKFLOW_NAME: "Newbie Contributor Patrol External" 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 }} @@ -1242,7 +1292,7 @@ jobs: success: ${{ steps.parse_results.outputs.success }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent artifacts @@ -1265,7 +1315,7 @@ jobs: - name: Setup threat detection uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: - WORKFLOW_NAME: "Docs New Contributor Review External" + WORKFLOW_NAME: "Newbie Contributor Patrol External" WORKFLOW_DESCRIPTION: "Review docs from a new contributor perspective, cross-referencing published Elastic documentation" HAS_PATCH: ${{ needs.agent.outputs.has_patch }} with: @@ -1303,10 +1353,11 @@ jobs: mkdir -p /tmp/gh-aw/ mkdir -p /tmp/gh-aw/agent/ mkdir -p /tmp/gh-aw/sandbox/agent/logs/ - copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --model gpt-5.3-codex --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log + copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_REF_NAME: ${{ github.ref_name }} @@ -1336,7 +1387,7 @@ jobs: activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Check team membership for workflow @@ -1365,10 +1416,10 @@ jobs: timeout-minutes: 15 env: GH_AW_ENGINE_ID: "copilot" - GH_AW_ENGINE_MODEL: "gpt-5.3-codex" + GH_AW_ENGINE_MODEL: "${{ inputs.model }}" GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\"}" - GH_AW_WORKFLOW_ID: "gh-aw-docs-new-contributor-review-external" - GH_AW_WORKFLOW_NAME: "Docs New Contributor Review External" + GH_AW_WORKFLOW_ID: "gh-aw-newbie-contributor-patrol-external" + GH_AW_WORKFLOW_NAME: "Newbie Contributor Patrol External" outputs: create_discussion_error_count: ${{ steps.process_safe_outputs.outputs.create_discussion_error_count }} create_discussion_errors: ${{ steps.process_safe_outputs.outputs.create_discussion_errors }} @@ -1376,7 +1427,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@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent output artifact @@ -1395,7 +1446,7 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_issue\":{\"close_older_issues\":true,\"expires\":168,\"max\":1,\"title_prefix\":\"[docs-new-contributor-external] \"},\"missing_data\":{},\"missing_tool\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_issue\":{\"close_older_issues\":true,\"expires\":168,\"max\":1,\"title_prefix\":\"[newbie-contributor-external] \"},\"missing_data\":{},\"missing_tool\":{}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/gh-aw-docs-new-contributor-review-external.md b/.github/workflows/gh-aw-newbie-contributor-patrol-external.md similarity index 93% rename from .github/workflows/gh-aw-docs-new-contributor-review-external.md rename to .github/workflows/gh-aw-newbie-contributor-patrol-external.md index 676d0847..9a44e53e 100644 --- a/.github/workflows/gh-aw-docs-new-contributor-review-external.md +++ b/.github/workflows/gh-aw-newbie-contributor-patrol-external.md @@ -1,5 +1,6 @@ --- -name: "Docs New Contributor Review External" +inlined-imports: true +name: "Newbie Contributor Patrol External" description: "Review docs from a new contributor perspective, cross-referencing published Elastic documentation" imports: - gh-aw-fragments/elastic-tools.md @@ -9,13 +10,18 @@ imports: - gh-aw-fragments/mcp-pagination.md - gh-aw-fragments/messages-footer.md - gh-aw-fragments/safe-output-create-issue.md - - gh-aw-fragments/scheduled-report.md + - gh-aw-fragments/scheduled-audit.md engine: id: copilot - model: gpt-5.3-codex + model: ${{ inputs.model }} on: workflow_call: inputs: + model: + description: "AI model to use" + type: string + required: false + default: "gpt-5.3-codex" additional-instructions: description: "Repo-specific instructions appended to the agent prompt" type: string @@ -43,7 +49,7 @@ on: bots: - "${{ inputs.allowed-bot-users }}" concurrency: - group: docs-new-contributor-review-external + group: newbie-contributor-patrol-external cancel-in-progress: true permissions: contents: read @@ -75,7 +81,7 @@ safe-outputs: noop: create-issue: max: 1 - title-prefix: "[docs-new-contributor-external] " + title-prefix: "[newbie-contributor-external] " close-older-issues: true expires: 7d timeout-minutes: 90 diff --git a/.github/workflows/gh-aw-docs-new-contributor-review.lock.yml b/.github/workflows/gh-aw-newbie-contributor-patrol.lock.yml similarity index 94% rename from .github/workflows/gh-aw-docs-new-contributor-review.lock.yml rename to .github/workflows/gh-aw-newbie-contributor-patrol.lock.yml index e0f3d840..5b3bb870 100644 --- a/.github/workflows/gh-aw-docs-new-contributor-review.lock.yml +++ b/.github/workflows/gh-aw-newbie-contributor-patrol.lock.yml @@ -32,11 +32,13 @@ # - gh-aw-fragments/rigor.md # - gh-aw-fragments/runtime-setup.md # - gh-aw-fragments/safe-output-create-issue.md -# - gh-aw-fragments/scheduled-report.md +# - gh-aw-fragments/scheduled-audit.md # -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"394152b69af9519f9bf07459fa9342694d5f267f7bc6029329373f6ad1322059"} +# inlined-imports: true +# +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"b5789f7e38c9157dccdb578449c69b70c958977e5124dd5e5c50592d5145d912"} -name: "Docs New Contributor Review" +name: "Newbie Contributor Patrol" "on": # bots: # Bots processed as bot check in pre-activation job # - ${{ inputs.allowed-bot-users }} # Bots processed as bot check in pre-activation job @@ -61,6 +63,11 @@ name: "Docs New Contributor Review" description: Footer appended to all agent comments and reviews required: false type: string + model: + default: gpt-5.3-codex + description: AI model to use + required: false + type: string setup-commands: default: "" description: Shell commands to run before the agent starts (dependency install, build, etc.) @@ -74,9 +81,9 @@ permissions: {} concurrency: cancel-in-progress: true - group: docs-new-contributor-review + group: newbie-contributor-patrol -run-name: "Docs New Contributor Review" +run-name: "Newbie Contributor Patrol" jobs: activation: @@ -90,7 +97,7 @@ jobs: comment_repo: "" steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Validate context variables @@ -112,7 +119,7 @@ jobs: - name: Check workflow file timestamps uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: - GH_AW_WORKFLOW_FILE: "gh-aw-docs-new-contributor-review.lock.yml" + GH_AW_WORKFLOW_FILE: "gh-aw-newbie-contributor-patrol.lock.yml" with: script: | const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); @@ -167,6 +174,25 @@ jobs: **Critical**: Tool calls write structured data that downstream jobs process. Without tool calls, follow-up actions will be skipped. **Note**: If you made no other safe output tool calls during this workflow execution, call the "noop" tool to provide a status message indicating completion or that no actions were needed. + + --- + + ## Creating an Issue, Reporting Missing Tools or Functionality, Reporting Missing Data + + **IMPORTANT**: To perform the actions listed above, use the **safeoutputs** tools. Do NOT use `gh`, do NOT call the GitHub API directly. You do not have write access to the GitHub repository. + + **Creating an Issue** + + To create an issue, use the create_issue tool from safeoutputs. + + **Reporting Missing Tools or Functionality** + + To report a missing tool or capability, use the missing_tool tool from safeoutputs. + + **Reporting Missing Data** + + To report missing data required to achieve a goal, use the missing_data tool from safeoutputs. + @@ -284,9 +310,7 @@ jobs: - **Mentions**: `@mentions` in the body are neutralized (backticked) by default. GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - # Scheduled Report Agent - - You are a report agent for __GH_AW_GITHUB_REPOSITORY__. You run on a schedule to investigate the repository and file an issue when something needs attention. Your specific assignment is described in the **Report Assignment** section below. + You are an agent for __GH_AW_GITHUB_REPOSITORY__. You run on a schedule to investigate the repository and file an issue when something needs attention. Your specific assignment is described in the **Report Assignment** section below. ## Context @@ -350,7 +374,7 @@ jobs: - Make suggested actions concrete enough to act on without re-investigating - If a finding is ambiguous, it does not pass the quality gate — drop it - ## Report Assignment + **Report Assignment:** GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" @@ -489,7 +513,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: ghawdocsnewcontributorreview + GH_AW_WORKFLOW_ID_SANITIZED: ghawnewbiecontributorpatrol outputs: checkout_pr_success: ${{ steps.checkout-pr.outputs.checkout_pr_success || 'true' }} has_patch: ${{ steps.collect_output.outputs.has_patch }} @@ -499,7 +523,7 @@ jobs: secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Checkout repository @@ -593,10 +617,10 @@ jobs: const awInfo = { engine_id: "copilot", engine_name: "GitHub Copilot CLI", - model: "gpt-5.3-codex", + model: "${{ inputs.model }}", version: "", agent_version: "0.0.412", - workflow_name: "Docs New Contributor Review", + workflow_name: "Newbie Contributor Patrol", experimental: false, supports_tools_allowlist: true, run_id: context.runId, @@ -658,7 +682,7 @@ jobs: 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 \"[docs-new-contributor] \".", + "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 \"[newbie-contributor] \".", "inputSchema": { "additionalProperties": false, "properties": { @@ -804,6 +828,31 @@ jobs: } } }, + "missing_data": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "context": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "data_type": { + "type": "string", + "sanitize": true, + "maxLength": 128 + }, + "reason": { + "type": "string", + "sanitize": true, + "maxLength": 256 + } + } + }, "missing_tool": { "defaultMax": 20, "fields": { @@ -965,10 +1014,11 @@ jobs: run: | set -o pipefail sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --allow-domains '*.githubusercontent.com,*.jsr.io,*.pythonhosted.org,*.rvm.io,agents-md-generator.fastmcp.app,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.rubygems.org,api.snapcraft.io,archive.ubuntu.com,artifacts.elastic.co,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,bun.sh,bundler.rubygems.org,cache.ruby-lang.org,cdn.jsdelivr.net,cloud.elastic.co,codeload.github.com,conda.anaconda.org,conda.binstar.org,crates.io,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,deb.nodesource.com,deno.land,ela.st,elastic.co,esm.sh,files.pythonhosted.org,gems.rubyforge.org,gems.rubyonrails.org,get.pnpm.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,host.docker.internal,index.crates.io,index.rubygems.org,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,lfs.github.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,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,pip.pypa.io,pkg.go.dev,ppa.launchpad.net,proxy.golang.org,public-code-search.fastmcp.app,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.bower.io,registry.npmjs.com,registry.npmjs.org,registry.yarnpkg.com,repo.anaconda.com,repo.continuum.io,repo.yarnpkg.com,rubygems.org,rubygems.pkg.github.com,s.symcb.com,s.symcd.com,security.ubuntu.com,skimdb.npmjs.com,static.crates.io,storage.googleapis.com,sum.golang.org,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.elastic.co,www.npmjs.com,www.npmjs.org,yarnpkg.com' --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.20.2 --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 --model gpt-5.3-codex --allow-all-tools --allow-all-paths --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log + -- /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 --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} @@ -1134,7 +1184,7 @@ jobs: total_count: ${{ steps.missing_tool.outputs.total_count }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent output artifact @@ -1154,7 +1204,7 @@ jobs: env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} GH_AW_NOOP_MAX: 1 - GH_AW_WORKFLOW_NAME: "Docs New Contributor Review" + GH_AW_WORKFLOW_NAME: "Newbie Contributor Patrol" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | @@ -1167,7 +1217,7 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_WORKFLOW_NAME: "Docs New Contributor Review" + GH_AW_WORKFLOW_NAME: "Newbie Contributor Patrol" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | @@ -1180,10 +1230,10 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_WORKFLOW_NAME: "Docs New Contributor Review" + GH_AW_WORKFLOW_NAME: "Newbie Contributor Patrol" 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: "gh-aw-docs-new-contributor-review" + GH_AW_WORKFLOW_ID: "gh-aw-newbie-contributor-patrol" GH_AW_SECRET_VERIFICATION_RESULT: ${{ needs.agent.outputs.secret_verification_result }} GH_AW_CHECKOUT_PR_SUCCESS: ${{ needs.agent.outputs.checkout_pr_success }} GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\"}" @@ -1200,7 +1250,7 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_WORKFLOW_NAME: "Docs New Contributor Review" + GH_AW_WORKFLOW_NAME: "Newbie Contributor Patrol" 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 }} @@ -1225,7 +1275,7 @@ jobs: success: ${{ steps.parse_results.outputs.success }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent artifacts @@ -1248,7 +1298,7 @@ jobs: - name: Setup threat detection uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: - WORKFLOW_NAME: "Docs New Contributor Review" + WORKFLOW_NAME: "Newbie Contributor Patrol" WORKFLOW_DESCRIPTION: "Review docs from a new contributor perspective and file high-impact issues" HAS_PATCH: ${{ needs.agent.outputs.has_patch }} with: @@ -1286,10 +1336,11 @@ jobs: mkdir -p /tmp/gh-aw/ mkdir -p /tmp/gh-aw/agent/ mkdir -p /tmp/gh-aw/sandbox/agent/logs/ - copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --model gpt-5.3-codex --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log + copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_REF_NAME: ${{ github.ref_name }} @@ -1319,7 +1370,7 @@ jobs: activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Check team membership for workflow @@ -1348,10 +1399,10 @@ jobs: timeout-minutes: 15 env: GH_AW_ENGINE_ID: "copilot" - GH_AW_ENGINE_MODEL: "gpt-5.3-codex" + GH_AW_ENGINE_MODEL: "${{ inputs.model }}" GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\"}" - GH_AW_WORKFLOW_ID: "gh-aw-docs-new-contributor-review" - GH_AW_WORKFLOW_NAME: "Docs New Contributor Review" + GH_AW_WORKFLOW_ID: "gh-aw-newbie-contributor-patrol" + GH_AW_WORKFLOW_NAME: "Newbie Contributor Patrol" outputs: create_discussion_error_count: ${{ steps.process_safe_outputs.outputs.create_discussion_error_count }} create_discussion_errors: ${{ steps.process_safe_outputs.outputs.create_discussion_errors }} @@ -1359,7 +1410,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@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent output artifact @@ -1378,7 +1429,7 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_issue\":{\"close_older_issues\":true,\"expires\":168,\"max\":1,\"title_prefix\":\"[docs-new-contributor] \"},\"missing_data\":{},\"missing_tool\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_issue\":{\"close_older_issues\":true,\"expires\":168,\"max\":1,\"title_prefix\":\"[newbie-contributor] \"},\"missing_data\":{},\"missing_tool\":{}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/gh-aw-docs-new-contributor-review.md b/.github/workflows/gh-aw-newbie-contributor-patrol.md similarity index 92% rename from .github/workflows/gh-aw-docs-new-contributor-review.md rename to .github/workflows/gh-aw-newbie-contributor-patrol.md index 7c3cef52..0f025106 100644 --- a/.github/workflows/gh-aw-docs-new-contributor-review.md +++ b/.github/workflows/gh-aw-newbie-contributor-patrol.md @@ -1,5 +1,6 @@ --- -name: "Docs New Contributor Review" +inlined-imports: true +name: "Newbie Contributor Patrol" description: "Review docs from a new contributor perspective and file high-impact issues" imports: - gh-aw-fragments/elastic-tools.md @@ -9,13 +10,18 @@ imports: - gh-aw-fragments/mcp-pagination.md - gh-aw-fragments/messages-footer.md - gh-aw-fragments/safe-output-create-issue.md - - gh-aw-fragments/scheduled-report.md + - gh-aw-fragments/scheduled-audit.md engine: id: copilot - model: gpt-5.3-codex + model: ${{ inputs.model }} on: workflow_call: inputs: + model: + description: "AI model to use" + type: string + required: false + default: "gpt-5.3-codex" additional-instructions: description: "Repo-specific instructions appended to the agent prompt" type: string @@ -43,7 +49,7 @@ on: bots: - "${{ inputs.allowed-bot-users }}" concurrency: - group: docs-new-contributor-review + group: newbie-contributor-patrol cancel-in-progress: true permissions: contents: read @@ -67,7 +73,7 @@ safe-outputs: noop: create-issue: max: 1 - title-prefix: "[docs-new-contributor] " + title-prefix: "[newbie-contributor] " close-older-issues: true expires: 7d timeout-minutes: 90 diff --git a/.github/workflows/gh-aw-performance-profiler.lock.yml b/.github/workflows/gh-aw-performance-profiler.lock.yml index 411f49af..047194dc 100644 --- a/.github/workflows/gh-aw-performance-profiler.lock.yml +++ b/.github/workflows/gh-aw-performance-profiler.lock.yml @@ -33,10 +33,12 @@ # - gh-aw-fragments/rigor.md # - gh-aw-fragments/runtime-setup.md # - gh-aw-fragments/safe-output-create-issue.md -# - gh-aw-fragments/scheduled-report.md +# - gh-aw-fragments/scheduled-audit.md # - gh-aw-fragments/workflow-edit-guardrails.md # -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"10d210d6a35a6c8a1eda5f2020752e020b7eb7dc903a8630e91e899473c41875"} +# inlined-imports: true +# +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"c33667a31d297bd575adf8ea5180d7837df6e48e24d4ac5999bf97048ae8f6d5"} name: "Performance Profiler" "on": @@ -63,6 +65,11 @@ name: "Performance Profiler" description: Footer appended to all agent comments and reviews required: false type: string + model: + default: gpt-5.3-codex + description: AI model to use + required: false + type: string setup-commands: default: "" description: Shell commands to run before the agent starts (dependency install, build, etc.) @@ -92,7 +99,7 @@ jobs: comment_repo: "" steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Validate context variables @@ -169,6 +176,25 @@ jobs: **Critical**: Tool calls write structured data that downstream jobs process. Without tool calls, follow-up actions will be skipped. **Note**: If you made no other safe output tool calls during this workflow execution, call the "noop" tool to provide a status message indicating completion or that no actions were needed. + + --- + + ## Creating an Issue, Reporting Missing Tools or Functionality, Reporting Missing Data + + **IMPORTANT**: To perform the actions listed above, use the **safeoutputs** tools. Do NOT use `gh`, do NOT call the GitHub API directly. You do not have write access to the GitHub repository. + + **Creating an Issue** + + To create an issue, use the create_issue tool from safeoutputs. + + **Reporting Missing Tools or Functionality** + + To report a missing tool or capability, use the missing_tool tool from safeoutputs. + + **Reporting Missing Data** + + To report missing data required to achieve a goal, use the missing_data tool from safeoutputs. + @@ -296,9 +322,7 @@ jobs: - **Mentions**: `@mentions` in the body are neutralized (backticked) by default. GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - # Scheduled Report Agent - - You are a report agent for __GH_AW_GITHUB_REPOSITORY__. You run on a schedule to investigate the repository and file an issue when something needs attention. Your specific assignment is described in the **Report Assignment** section below. + You are an agent for __GH_AW_GITHUB_REPOSITORY__. You run on a schedule to investigate the repository and file an issue when something needs attention. Your specific assignment is described in the **Report Assignment** section below. ## Context @@ -362,7 +386,7 @@ jobs: - Make suggested actions concrete enough to act on without re-investigating - If a finding is ambiguous, it does not pass the quality gate — drop it - ## Report Assignment + **Report Assignment:** GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" @@ -577,7 +601,7 @@ jobs: secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Checkout repository @@ -677,7 +701,7 @@ jobs: const awInfo = { engine_id: "copilot", engine_name: "GitHub Copilot CLI", - model: "gpt-5.3-codex", + model: "${{ inputs.model }}", version: "", agent_version: "0.0.412", workflow_name: "Performance Profiler", @@ -888,6 +912,31 @@ jobs: } } }, + "missing_data": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "context": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "data_type": { + "type": "string", + "sanitize": true, + "maxLength": 128 + }, + "reason": { + "type": "string", + "sanitize": true, + "maxLength": 256 + } + } + }, "missing_tool": { "defaultMax": 20, "fields": { @@ -1049,10 +1098,11 @@ jobs: run: | set -o pipefail sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --allow-domains '*.githubusercontent.com,*.jsr.io,*.pythonhosted.org,*.rvm.io,agents-md-generator.fastmcp.app,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.rubygems.org,api.snapcraft.io,archive.ubuntu.com,artifacts.elastic.co,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,bun.sh,bundler.rubygems.org,cache.ruby-lang.org,cdn.jsdelivr.net,cloud.elastic.co,codeload.github.com,conda.anaconda.org,conda.binstar.org,crates.io,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,deb.nodesource.com,deno.land,ela.st,elastic.co,esm.sh,files.pythonhosted.org,gems.rubyforge.org,gems.rubyonrails.org,get.pnpm.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,host.docker.internal,index.crates.io,index.rubygems.org,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,lfs.github.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,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,pip.pypa.io,pkg.go.dev,ppa.launchpad.net,proxy.golang.org,public-code-search.fastmcp.app,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.bower.io,registry.npmjs.com,registry.npmjs.org,registry.yarnpkg.com,repo.anaconda.com,repo.continuum.io,repo.yarnpkg.com,rubygems.org,rubygems.pkg.github.com,s.symcb.com,s.symcd.com,security.ubuntu.com,skimdb.npmjs.com,static.crates.io,storage.googleapis.com,sum.golang.org,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.elastic.co,www.npmjs.com,www.npmjs.org,yarnpkg.com' --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.20.2 --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 --model gpt-5.3-codex --allow-all-tools --allow-all-paths --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log + -- /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 --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} @@ -1218,7 +1268,7 @@ jobs: total_count: ${{ steps.missing_tool.outputs.total_count }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent output artifact @@ -1309,7 +1359,7 @@ jobs: success: ${{ steps.parse_results.outputs.success }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent artifacts @@ -1370,10 +1420,11 @@ jobs: mkdir -p /tmp/gh-aw/ mkdir -p /tmp/gh-aw/agent/ mkdir -p /tmp/gh-aw/sandbox/agent/logs/ - copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --model gpt-5.3-codex --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log + copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_REF_NAME: ${{ github.ref_name }} @@ -1403,7 +1454,7 @@ jobs: activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Check team membership for workflow @@ -1432,7 +1483,7 @@ jobs: timeout-minutes: 15 env: GH_AW_ENGINE_ID: "copilot" - GH_AW_ENGINE_MODEL: "gpt-5.3-codex" + GH_AW_ENGINE_MODEL: "${{ inputs.model }}" GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\"}" GH_AW_WORKFLOW_ID: "gh-aw-performance-profiler" GH_AW_WORKFLOW_NAME: "Performance Profiler" @@ -1443,7 +1494,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@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent output artifact diff --git a/.github/workflows/gh-aw-performance-profiler.md b/.github/workflows/gh-aw-performance-profiler.md index 6358e5fb..0c03e481 100644 --- a/.github/workflows/gh-aw-performance-profiler.md +++ b/.github/workflows/gh-aw-performance-profiler.md @@ -1,4 +1,5 @@ --- +inlined-imports: true name: "Performance Profiler" description: "Identify hot paths, profile code, and propose meaningful performance improvements" imports: @@ -11,13 +12,18 @@ imports: - gh-aw-fragments/workflow-edit-guardrails.md - gh-aw-fragments/messages-footer.md - gh-aw-fragments/safe-output-create-issue.md - - gh-aw-fragments/scheduled-report.md + - gh-aw-fragments/scheduled-audit.md engine: id: copilot - model: gpt-5.3-codex + model: ${{ inputs.model }} on: workflow_call: inputs: + model: + description: "AI model to use" + type: string + required: false + default: "gpt-5.3-codex" additional-instructions: description: "Repo-specific instructions appended to the agent prompt" type: string diff --git a/.github/workflows/gh-aw-pr-actions-detective.lock.yml b/.github/workflows/gh-aw-pr-actions-detective.lock.yml new file mode 100644 index 00000000..efe82922 --- /dev/null +++ b/.github/workflows/gh-aw-pr-actions-detective.lock.yml @@ -0,0 +1,1365 @@ +# +# ___ _ _ +# / _ \ | | (_) +# | |_| | __ _ ___ _ __ | |_ _ ___ +# | _ |/ _` |/ _ \ '_ \| __| |/ __| +# | | | | (_| | __/ | | | |_| | (__ +# \_| |_/\__, |\___|_| |_|\__|_|\___| +# __/ | +# _ _ |___/ +# | | | | / _| | +# | | | | ___ _ __ _ __| |_| | _____ ____ +# | |/\| |/ _ \ '__| |/ /| _| |/ _ \ \ /\ / / ___| +# \ /\ / (_) | | | | ( | | | | (_) \ V V /\__ \ +# \/ \/ \___/|_| |_|\_\|_| |_|\___/ \_/\_/ |___/ +# +# This file was automatically generated by gh-aw. DO NOT EDIT. +# +# To update this file, edit the corresponding .md file and run: +# gh aw compile +# Not all edits will cause changes to this file. +# +# For more information: https://github.github.com/gh-aw/introduction/overview/ +# +# Analyze failed PR checks and report findings +# +# Resolved workflow manifest: +# Imports: +# - gh-aw-fragments/elastic-tools.md +# - gh-aw-fragments/formatting.md +# - gh-aw-fragments/mcp-pagination.md +# - gh-aw-fragments/messages-footer.md +# - gh-aw-fragments/rigor.md +# - gh-aw-fragments/runtime-setup.md +# - gh-aw-fragments/safe-output-add-comment.md +# - gh-aw-fragments/workflow-edit-guardrails.md +# +# inlined-imports: true +# +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"c0e061afa63fe1d7938d61e9ab60cd5204d64453e9661adbf151ff81df2230db"} + +name: "PR Actions Detective" +"on": + # bots: # Bots processed as bot check in pre-activation job + # - ${{ inputs.allowed-bot-users }} # Bots processed as bot check in pre-activation job + # roles: # Roles processed as role check in pre-activation job + # - admin # Roles processed as role check in pre-activation job + # - maintainer # Roles processed as role check in pre-activation job + # - write # Roles processed as role check in pre-activation job + workflow_call: + inputs: + additional-instructions: + default: "" + description: Repo-specific instructions appended to the agent prompt + required: false + type: string + allowed-bot-users: + default: github-actions[bot] + description: Allowlisted bot actor usernames (comma-separated) + required: false + type: string + messages-footer: + default: "" + description: Footer appended to all agent comments and reviews + required: false + type: string + model: + default: gpt-5.3-codex + description: AI model to use + required: false + type: string + setup-commands: + default: "" + description: Shell commands to run before the agent starts (dependency install, build, etc.) + required: false + type: string + secrets: + COPILOT_GITHUB_TOKEN: + required: true + +permissions: {} + +concurrency: + cancel-in-progress: false + group: pr-actions-detective-${{ github.event.workflow_run.id }} + +run-name: "PR Actions Detective" + +jobs: + activation: + needs: pre_activation + if: needs.pre_activation.outputs.activated == 'true' + runs-on: ubuntu-slim + permissions: + contents: read + outputs: + comment_id: "" + comment_repo: "" + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 + with: + destination: /opt/gh-aw/actions + - name: Validate context variables + 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/validate_context_variables.cjs'); + await main(); + - name: Checkout .github and .agents folders + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + sparse-checkout: | + .github + .agents + fetch-depth: 1 + persist-credentials: false + - name: Check workflow file timestamps + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_WORKFLOW_FILE: "gh-aw-pr-actions-detective.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: Create prompt with built-in context + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} + GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} + GH_AW_GITHUB_ACTOR: ${{ github.actor }} + GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} + GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} + GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} + GH_AW_GITHUB_EVENT_WORKFLOW_RUN_CONCLUSION: ${{ github.event.workflow_run.conclusion }} + GH_AW_GITHUB_EVENT_WORKFLOW_RUN_ID: ${{ github.event.workflow_run.id }} + GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} + GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} + GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} + run: | + bash /opt/gh-aw/actions/create_prompt_first.sh + cat << 'GH_AW_PROMPT_EOF' > "$GH_AW_PROMPT" + + GH_AW_PROMPT_EOF + cat "/opt/gh-aw/prompts/xpia.md" >> "$GH_AW_PROMPT" + cat "/opt/gh-aw/prompts/temp_folder_prompt.md" >> "$GH_AW_PROMPT" + cat "/opt/gh-aw/prompts/markdown.md" >> "$GH_AW_PROMPT" + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + + GitHub API Access Instructions + + The gh CLI is NOT authenticated. Do NOT use gh commands for GitHub operations. + + + To create or modify GitHub resources (issues, discussions, pull requests, etc.), you MUST call the appropriate safe output tool. Simply writing content will NOT work - the workflow requires actual tool calls. + + Temporary IDs: Some safe output tools support a temporary ID field (usually named temporary_id) so you can reference newly-created items elsewhere in the SAME agent output (for example, using #aw_abc1 in a later body). + + **IMPORTANT - temporary_id format rules:** + - If you DON'T need to reference the item later, OMIT the temporary_id field entirely (it will be auto-generated if needed) + - If you DO need cross-references/chaining, you MUST match this EXACT validation regex: /^aw_[A-Za-z0-9]{3,8}$/i + - Format: aw_ prefix followed by 3 to 8 alphanumeric characters (A-Z, a-z, 0-9, case-insensitive) + - Valid alphanumeric characters: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 + - INVALID examples: aw_ab (too short), aw_123456789 (too long), aw_test-id (contains hyphen), aw_id_123 (contains underscore) + - VALID examples: aw_abc, aw_abc1, aw_Test123, aw_A1B2C3D4, aw_12345678 + - To generate valid IDs: use 3-8 random alphanumeric characters or omit the field to let the system auto-generate + + Do NOT invent other aw_* formats — downstream steps will reject them with validation errors matching against /^aw_[A-Za-z0-9]{3,8}$/i. + + Discover available tools from the safeoutputs MCP server. + + **Critical**: Tool calls write structured data that downstream jobs process. Without tool calls, follow-up actions will be skipped. + + **Note**: If you made no other safe output tool calls during this workflow execution, call the "noop" tool to provide a status message indicating completion or that no actions were needed. + + --- + + ## Adding a Comment to an Issue or Pull Request, Reporting Missing Tools or Functionality, Reporting Missing Data + + **IMPORTANT**: To perform the actions listed above, use the **safeoutputs** tools. Do NOT use `gh`, do NOT call the GitHub API directly. You do not have write access to the GitHub repository. + + **Adding a Comment to an Issue or Pull Request** + + To add a comment to an issue or pull request, use the add_comment tool from safeoutputs. + + **Reporting Missing Tools or Functionality** + + To report a missing tool or capability, use the missing_tool tool from safeoutputs. + + **Reporting Missing Data** + + To report missing data required to achieve a goal, use the missing_data tool from safeoutputs. + + + + + The following GitHub context information is available for this workflow: + {{#if __GH_AW_GITHUB_ACTOR__ }} + - **actor**: __GH_AW_GITHUB_ACTOR__ + {{/if}} + {{#if __GH_AW_GITHUB_REPOSITORY__ }} + - **repository**: __GH_AW_GITHUB_REPOSITORY__ + {{/if}} + {{#if __GH_AW_GITHUB_WORKSPACE__ }} + - **workspace**: __GH_AW_GITHUB_WORKSPACE__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_ISSUE_NUMBER__ }} + - **issue-number**: #__GH_AW_GITHUB_EVENT_ISSUE_NUMBER__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__ }} + - **discussion-number**: #__GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__ }} + - **pull-request-number**: #__GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_COMMENT_ID__ }} + - **comment-id**: __GH_AW_GITHUB_EVENT_COMMENT_ID__ + {{/if}} + {{#if __GH_AW_GITHUB_RUN_ID__ }} + - **workflow-run-id**: __GH_AW_GITHUB_RUN_ID__ + {{/if}} + + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + ## MCP Servers + + - **`generate_agents_md`** — generates a summary of the repository's structure, conventions, and coding guidelines from AGENTS.md and related files. Call at the start of every workflow to get repo context. + - **`search_code`** — grep-style search across public GitHub repositories. Use for finding usage patterns in upstream libraries, reference implementations, or examples in open-source projects. This searches *public GitHub repos*, not the local codebase — if available you can use `grep` and file reading for local code. + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + ## Formatting Guidelines + + - Lead with the most important information — your first sentence should be the key takeaway + - Be concise and actionable — no filler or praise + - Use `
` and `` tags for long sections to keep responses scannable + - Wrap branch names and @-references in backticks to avoid pinging users + - Include code snippets with file paths and line numbers when referencing the codebase + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + ## Rigor + + **Silence is better than noise. A false positive wastes a human's time and erodes trust in every future report.** + + - If you claim something is missing or broken, show the exact evidence in the code — file path, line number, and what you observed. + - If a conclusion depends on assumptions you haven't confirmed, do not assert it. Verify first; if you cannot verify, do not report. + - "I don't know" is better than a wrong answer. `noop` is better than a speculative finding. + - It's worth the time to verify now versus guessing and forcing someone else to verify later. + - Before filing any issue or opening any PR, re-read your own output as a skeptical reviewer. Ask: "Would a senior engineer on this team find this useful, or would they close it immediately?" If the answer is "close," call `noop` instead. + - Only report findings you would confidently defend in a code review. If you feel the need to hedge with "might," "could," or "possibly," the finding is not ready to file. + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + ## MCP Pagination + + MCP tool responses have a **25,000 token limit**. When responses exceed this limit, the call fails and you must retry with pagination — wasting turns and tokens. Use proactive pagination to stay under the limit. + + ### Recommended `perPage` Values + + - **5-10**: For detailed items (PR diffs, files with patches, issues with comments) + - **20-30**: For medium-detail lists (commits, review comments, issue lists) + - **50-100**: For simple list operations (branches, labels, tags) + + ### Pagination Pattern + + When you need all results from a paginated API: + + 1. Fetch the first page with a conservative `perPage` value + 2. Process the results before fetching the next page + 3. Continue fetching pages until you receive fewer results than `perPage` (indicating the last page) + + ### Error Recovery + + If you see an error like: + - `MCP tool response exceeds maximum allowed tokens (25000)` + - `Response too large for tool [tool_name]` + + Retry the same call with a smaller `perPage` value (halve it). + + ### Tips + + - **Start small**: It's better to make multiple small requests than one that fails + - **Fetch incrementally**: Get an overview first, then details for specific items + - **Use filters**: Combine `perPage` with state, label, or date filters to reduce result size + - **Process as you go**: Don't accumulate all pages before acting — process each batch immediately + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + ## Workflow Editing Guardrails + + - Do not modify files under `.github/workflows/`. + - If asked to change workflow files, place a copy under `github/` (no leading dot) and note that a maintainer must relocate it into `.github/workflows/`. + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + ## Message Footer + + A footer is automatically appended to all comments and reviews. Do not add your own footer or sign-off — the runtime handles this. + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + ## add-comment Limitations + + - **Body**: Max 65,536 characters (including any footer added by gh-aw). Keep well under this limit. + - **Mentions**: Max 10 `@` mentions per comment. + - **Links**: Max 50 URLs per comment. + - **HTML**: Only safe tags allowed (`details`, `summary`, `code`, `pre`, `blockquote`, `table`, `b`, `em`, `strong`, `h1`–`h6`, `hr`, `br`, `li`, `ol`, `ul`, `p`, `sub`, `sup`). Other tags are converted to parentheses. + - **URLs**: Only HTTPS URLs to allowed domains. Non-HTTPS and non-allowed domains are redacted. + - **Bot triggers**: References like `fixes #123` or `closes #456` are neutralized to prevent unintended issue closures. + + If you exceed 10 mentions or 50 links, the comment will be rejected. + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + # PR Actions Detective + + Assist with failed GitHub Actions checks for pull requests in __GH_AW_GITHUB_REPOSITORY__. Analyze workflow run logs, explain failures, and recommend fixes. This workflow is read-only. + + ## Context + + - **Repository**: __GH_AW_GITHUB_REPOSITORY__ + - **Workflow Run ID**: __GH_AW_GITHUB_EVENT_WORKFLOW_RUN_ID__ + - **Conclusion**: __GH_AW_GITHUB_EVENT_WORKFLOW_RUN_CONCLUSION__ + + ## Constraints + + - **CAN**: Read files, search code, run tests and commands, comment on PRs + - **CANNOT**: Push changes, merge PRs, or modify `.github/workflows/` + + ## Instructions + + ### Step 1: Gather Context + + 1. Call `generate_agents_md` to get the repository's coding guidelines and conventions. If this fails, continue without it. + 2. Identify the PRs associated with the workflow run using `github.event.workflow_run.pull_requests`. If there are none, call `noop` with message "No pull request associated with workflow run; nothing to do" and stop. + 3. For each PR, call `pull_request_read` with method `get` to capture the author, branches, and fork status. + 4. Fetch workflow run details and logs with `bash` + `gh api`: + - List jobs and their conclusions: + ````bash + gh api repos/{owner}/{repo}/actions/runs/{run_id}/jobs \ + --jq '.jobs[] | {id: .id, name: .name, conclusion: .conclusion, html_url: .html_url}' + ```` + - Download logs to `/tmp/gh-aw/agent/` and inspect the failing step output: + ````bash + gh api repos/{owner}/{repo}/actions/runs/{run_id}/logs \ + -H "Accept: application/vnd.github+json" \ + > /tmp/gh-aw/agent/workflow-logs-{run_id}.zip + unzip -o /tmp/gh-aw/agent/workflow-logs-{run_id}.zip -d /tmp/gh-aw/agent/workflow-logs-{run_id}/ + ```` + + ### Step 2: Analyze + + - Identify the failing job/step and summarize the root cause. + - Propose a concrete, minimal fix or remediation plan. + - If the logs are inconclusive, state what additional data is needed. + + ### Step 3: Respond + + Call `add_comment` on the PR with: + - A concise summary of the failure and root cause + - The recommended fix or remediation plan + - Tests run and their results (if any) + - Any follow-up steps required + + __GH_AW_EXPR_49B959F1__ + + GH_AW_PROMPT_EOF + - name: Interpolate variables and render templates + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_GITHUB_EVENT_WORKFLOW_RUN_CONCLUSION: ${{ github.event.workflow_run.conclusion }} + GH_AW_GITHUB_EVENT_WORKFLOW_RUN_ID: ${{ github.event.workflow_run.id }} + GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} + GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} + 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/interpolate_prompt.cjs'); + await main(); + - name: Substitute placeholders + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} + GH_AW_GITHUB_ACTOR: ${{ github.actor }} + GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} + GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} + GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} + GH_AW_GITHUB_EVENT_WORKFLOW_RUN_CONCLUSION: ${{ github.event.workflow_run.conclusion }} + GH_AW_GITHUB_EVENT_WORKFLOW_RUN_ID: ${{ github.event.workflow_run.id }} + 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'); + setupGlobals(core, github, context, exec, io); + + const substitutePlaceholders = require('/opt/gh-aw/actions/substitute_placeholders.cjs'); + + // Call the substitution function + return await substitutePlaceholders({ + file: process.env.GH_AW_PROMPT, + substitutions: { + GH_AW_EXPR_49B959F1: process.env.GH_AW_EXPR_49B959F1, + GH_AW_GITHUB_ACTOR: process.env.GH_AW_GITHUB_ACTOR, + GH_AW_GITHUB_EVENT_COMMENT_ID: process.env.GH_AW_GITHUB_EVENT_COMMENT_ID, + GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: process.env.GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER, + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: process.env.GH_AW_GITHUB_EVENT_ISSUE_NUMBER, + GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: process.env.GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER, + GH_AW_GITHUB_EVENT_WORKFLOW_RUN_CONCLUSION: process.env.GH_AW_GITHUB_EVENT_WORKFLOW_RUN_CONCLUSION, + GH_AW_GITHUB_EVENT_WORKFLOW_RUN_ID: process.env.GH_AW_GITHUB_EVENT_WORKFLOW_RUN_ID, + 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_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 + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + run: bash /opt/gh-aw/actions/validate_prompt_placeholders.sh + - name: Print prompt + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + run: bash /opt/gh-aw/actions/print_prompt_summary.sh + - name: Upload prompt artifact + if: success() + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: prompt + path: /tmp/gh-aw/aw-prompts/prompt.txt + retention-days: 1 + + agent: + needs: activation + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + issues: read + pull-requests: read + concurrency: + group: "gh-aw-copilot-${{ github.workflow }}" + env: + DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} + GH_AW_ASSETS_ALLOWED_EXTS: "" + GH_AW_ASSETS_BRANCH: "" + GH_AW_ASSETS_MAX_SIZE_KB: 0 + GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs + 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: ghawpractionsdetective + outputs: + checkout_pr_success: ${{ steps.checkout-pr.outputs.checkout_pr_success || 'true' }} + has_patch: ${{ steps.collect_output.outputs.has_patch }} + model: ${{ steps.generate_aw_info.outputs.model }} + output: ${{ steps.collect_output.outputs.output }} + output_types: ${{ steps.collect_output.outputs.output_types }} + secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 + with: + destination: /opt/gh-aw/actions + - name: Checkout repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + - name: Create gh-aw temp directory + run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh + - if: hashFiles('go.mod') != '' + name: Setup Go + uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5 + with: + cache: true + go-version-file: go.mod + - if: hashFiles('.python-version') != '' + name: Setup Python + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 + with: + python-version-file: .python-version + - if: hashFiles('.node-version') != '' + name: Setup Node.js (.node-version) + uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6 + with: + node-version-file: .node-version + - if: hashFiles('.node-version') == '' && hashFiles('.nvmrc') != '' + name: Setup Node.js (.nvmrc) + uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6 + with: + node-version-file: .nvmrc + - if: hashFiles('.ruby-version') != '' + name: Setup Ruby + uses: ruby/setup-ruby@09a7688d3b55cf0e976497ff046b70949eeaccfd # v1 + with: + bundler-cache: true + ruby-version: .ruby-version + - id: setup-uv + if: hashFiles('pyproject.toml', 'uv.lock') != '' + name: Setup uv + uses: astral-sh/setup-uv@e58605a9b6da7c637471fab8847a5e5a6b8df081 # v5 + - env: + UV_PATH: ${{ steps.setup-uv.outputs.uv-path }} + WORKSPACE: ${{ github.workspace }} + if: hashFiles('pyproject.toml', 'uv.lock') != '' + name: Expose uv in workspace + run: |- + set -euo pipefail + install_dir="$WORKSPACE/.gh-aw-tools/bin" + mkdir -p "$install_dir" + cp "$UV_PATH" "$install_dir/uv" + chmod +x "$install_dir/uv" + echo "$install_dir" >> "$GITHUB_PATH" + shell: bash + - env: + SETUP_COMMANDS: ${{ inputs.setup-commands }} + if: ${{ inputs.setup-commands != '' }} + name: Repo-specific setup + run: eval "$SETUP_COMMANDS" + + - name: Configure Git credentials + env: + REPO_NAME: ${{ github.repository }} + SERVER_URL: ${{ github.server_url }} + run: | + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git config --global user.name "github-actions[bot]" + # Re-authenticate git with GitHub token + SERVER_URL_STRIPPED="${SERVER_URL#https://}" + git remote set-url origin "https://x-access-token:${{ github.token }}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" + echo "Git configured with standard GitHub Actions identity" + - name: Checkout PR branch + id: checkout-pr + if: | + github.event.pull_request + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + with: + github-token: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/checkout_pr_branch.cjs'); + await main(); + - name: Generate agentic run info + id: generate_aw_info + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + with: + script: | + const fs = require('fs'); + + const awInfo = { + engine_id: "copilot", + engine_name: "GitHub Copilot CLI", + model: "${{ inputs.model }}", + version: "", + agent_version: "0.0.412", + workflow_name: "PR Actions Detective", + experimental: false, + supports_tools_allowlist: true, + run_id: context.runId, + run_number: context.runNumber, + run_attempt: process.env.GITHUB_RUN_ATTEMPT, + repository: context.repo.owner + '/' + context.repo.repo, + ref: context.ref, + sha: context.sha, + actor: context.actor, + event_name: context.eventName, + staged: false, + allowed_domains: ["agents-md-generator.fastmcp.app","artifacts.elastic.co","cloud.elastic.co","defaults","ela.st","elastic.co","github","public-code-search.fastmcp.app","www.elastic.co"], + firewall_enabled: true, + awf_version: "v0.20.2", + awmg_version: "v0.1.4", + steps: { + firewall: "squid" + }, + created_at: new Date().toISOString() + }; + + // Write to /tmp/gh-aw directory to avoid inclusion in PR + const tmpPath = '/tmp/gh-aw/aw_info.json'; + fs.writeFileSync(tmpPath, JSON.stringify(awInfo, null, 2)); + console.log('Generated aw_info.json at:', tmpPath); + console.log(JSON.stringify(awInfo, null, 2)); + + // Set model as output for reuse in other steps/jobs + core.setOutput('model', awInfo.model); + - name: Validate COPILOT_GITHUB_TOKEN secret + id: validate-secret + run: /opt/gh-aw/actions/validate_multi_secret.sh COPILOT_GITHUB_TOKEN 'GitHub Copilot CLI' https://github.github.com/gh-aw/reference/engines/#github-copilot-default + env: + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + - name: Install GitHub Copilot CLI + run: /opt/gh-aw/actions/install_copilot_cli.sh 0.0.412 + - name: Install awf binary + run: bash /opt/gh-aw/actions/install_awf_binary.sh v0.20.2 + - name: Determine automatic lockdown mode for GitHub MCP Server + id: determine-automatic-lockdown + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} + GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} + with: + script: | + 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.20.2 ghcr.io/github/gh-aw-firewall/api-proxy:0.20.2 ghcr.io/github/gh-aw-firewall/squid:0.20.2 ghcr.io/github/gh-aw-mcpg:v0.1.4 ghcr.io/github/github-mcp-server:v0.31.0 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},"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": "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. NOTE: By default, this tool requires discussions:write permission. If your GitHub App lacks Discussions permission, set 'discussions: false' in the workflow's safe-outputs.add-comment configuration to exclude this permission. CONSTRAINTS: Maximum 1 comment(s) can be added.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "body": { + "description": "The comment text in Markdown format. This is the 'body' field - do not use 'comment_body' or other variations. Provide helpful, relevant information that adds value to the conversation. CONSTRAINTS: The complete comment (your body text + automatically added footer) must not exceed 65536 characters total. Maximum 10 mentions (@username), maximum 50 links (http/https URLs). A footer (~200-500 characters) is automatically appended with workflow attribution, so leave adequate space. If these limits are exceeded, the tool call will fail with a detailed error message indicating which constraint was violated.", + "type": "string" + }, + "item_number": { + "description": "The issue, pull request, or discussion number to comment on. This is the numeric ID from the GitHub URL (e.g., 123 in github.com/owner/repo/issues/123). If omitted, the tool auto-targets the issue, PR, or discussion that triggered this workflow. Auto-targeting only works for issue, pull_request, discussion, and comment event triggers — it does NOT work for schedule, workflow_dispatch, push, or workflow_run triggers. For those trigger types, always provide item_number explicitly, or the comment will be silently discarded.", + "type": "number" + } + }, + "required": [ + "body" + ], + "type": "object" + }, + "name": "add_comment" + }, + { + "description": "Report that a tool or capability needed to complete the task is not available, or share any information you deem important about missing functionality or limitations. Use this when you cannot accomplish what was requested because the required functionality is missing or access is restricted.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "alternatives": { + "description": "Any workarounds, manual steps, or alternative approaches the user could take (max 256 characters).", + "type": "string" + }, + "reason": { + "description": "Explanation of why this tool is needed or what information you want to share about the limitation (max 256 characters).", + "type": "string" + }, + "tool": { + "description": "Optional: Name or description of the missing tool or capability (max 128 characters). Be specific about what functionality is needed.", + "type": "string" + } + }, + "required": [ + "reason" + ], + "type": "object" + }, + "name": "missing_tool" + }, + { + "description": "Log a transparency message when no significant actions are needed. Use this to confirm workflow completion and provide visibility when analysis is complete but no changes or outputs are required (e.g., 'No issues found', 'All checks passed'). This ensures the workflow produces human-visible output even when no other actions are taken.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "message": { + "description": "Status or completion message to log. Should explain what was analyzed and the outcome (e.g., 'Code review complete - no issues found', 'Analysis complete - all tests passing').", + "type": "string" + } + }, + "required": [ + "message" + ], + "type": "object" + }, + "name": "noop" + }, + { + "description": "Report that data or information needed to complete the task is not available. Use this when you cannot accomplish what was requested because required data, context, or information is missing.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "alternatives": { + "description": "Any workarounds, manual steps, or alternative approaches the user could take (max 256 characters).", + "type": "string" + }, + "context": { + "description": "Additional context about the missing data or where it should come from (max 256 characters).", + "type": "string" + }, + "data_type": { + "description": "Type or description of the missing data or information (max 128 characters). Be specific about what data is needed.", + "type": "string" + }, + "reason": { + "description": "Explanation of why this data is needed to complete the task (max 256 characters).", + "type": "string" + } + }, + "required": [], + "type": "object" + }, + "name": "missing_data" + } + ] + GH_AW_SAFE_OUTPUTS_TOOLS_EOF + cat > /opt/gh-aw/safeoutputs/validation.json << 'GH_AW_SAFE_OUTPUTS_VALIDATION_EOF' + { + "add_comment": { + "defaultMax": 1, + "fields": { + "body": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "item_number": { + "issueOrPRNumber": true + }, + "repo": { + "type": "string", + "maxLength": 256 + } + } + }, + "missing_data": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "context": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "data_type": { + "type": "string", + "sanitize": true, + "maxLength": 128 + }, + "reason": { + "type": "string", + "sanitize": true, + "maxLength": 256 + } + } + }, + "missing_tool": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 512 + }, + "reason": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "tool": { + "type": "string", + "sanitize": true, + "maxLength": 128 + } + } + }, + "noop": { + "defaultMax": 1, + "fields": { + "message": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + } + } + } + } + GH_AW_SAFE_OUTPUTS_VALIDATION_EOF + - name: Generate Safe Outputs MCP Server Config + id: safe-outputs-config + run: | + # Generate a secure random API key (360 bits of entropy, 40+ chars) + # Mask immediately to prevent timing vulnerabilities + API_KEY=$(openssl rand -base64 45 | tr -d '/+=') + echo "::add-mask::${API_KEY}" + + PORT=3001 + + # Set outputs for next steps + { + echo "safe_outputs_api_key=${API_KEY}" + echo "safe_outputs_port=${PORT}" + } >> "$GITHUB_OUTPUT" + + echo "Safe Outputs MCP server will run on port ${PORT}" + + - name: Start Safe Outputs MCP HTTP Server + id: safe-outputs-start + env: + DEBUG: '*' + GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-config.outputs.safe_outputs_port }} + GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-config.outputs.safe_outputs_api_key }} + GH_AW_SAFE_OUTPUTS_TOOLS_PATH: /opt/gh-aw/safeoutputs/tools.json + GH_AW_SAFE_OUTPUTS_CONFIG_PATH: /opt/gh-aw/safeoutputs/config.json + GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs + run: | + # Environment variables are set above to prevent template injection + export DEBUG + export GH_AW_SAFE_OUTPUTS_PORT + export GH_AW_SAFE_OUTPUTS_API_KEY + export GH_AW_SAFE_OUTPUTS_TOOLS_PATH + export GH_AW_SAFE_OUTPUTS_CONFIG_PATH + export GH_AW_MCP_LOG_DIR + + bash /opt/gh-aw/actions/start_safe_outputs_server.sh + + - name: Start MCP Gateway + id: start-mcp-gateway + env: + GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} + GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-start.outputs.api_key }} + GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-start.outputs.port }} + GITHUB_MCP_LOCKDOWN: ${{ steps.determine-automatic-lockdown.outputs.lockdown == 'true' && '1' || '0' }} + GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + run: | + set -eo pipefail + mkdir -p /tmp/gh-aw/mcp-config + + # Export gateway environment variables for MCP config and gateway script + export MCP_GATEWAY_PORT="80" + export MCP_GATEWAY_DOMAIN="host.docker.internal" + MCP_GATEWAY_API_KEY=$(openssl rand -base64 45 | tr -d '/+=') + echo "::add-mask::${MCP_GATEWAY_API_KEY}" + export MCP_GATEWAY_API_KEY + export MCP_GATEWAY_PAYLOAD_DIR="/tmp/gh-aw/mcp-payloads" + mkdir -p "${MCP_GATEWAY_PAYLOAD_DIR}" + export DEBUG="*" + + export GH_AW_ENGINE="copilot" + 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 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_LOCKDOWN -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.1.4' + + mkdir -p /home/runner/.copilot + cat << GH_AW_MCP_CONFIG_EOF | bash /opt/gh-aw/actions/start_mcp_gateway.sh + { + "mcpServers": { + "agents-md-generator": { + "type": "http", + "url": "https://agents-md-generator.fastmcp.app/mcp", + "tools": [ + "generate_agents_md" + ] + }, + "github": { + "type": "stdio", + "container": "ghcr.io/github/github-mcp-server:v0.31.0", + "env": { + "GITHUB_LOCKDOWN_MODE": "$GITHUB_MCP_LOCKDOWN", + "GITHUB_PERSONAL_ACCESS_TOKEN": "\${GITHUB_MCP_SERVER_TOKEN}", + "GITHUB_READ_ONLY": "1", + "GITHUB_TOOLSETS": "repos,issues,pull_requests,search,actions" + } + }, + "public-code-search": { + "type": "http", + "url": "https://public-code-search.fastmcp.app/mcp", + "tools": [ + "search_code" + ] + }, + "safeoutputs": { + "type": "http", + "url": "http://host.docker.internal:$GH_AW_SAFE_OUTPUTS_PORT", + "headers": { + "Authorization": "\${GH_AW_SAFE_OUTPUTS_API_KEY}" + } + } + }, + "gateway": { + "port": $MCP_GATEWAY_PORT, + "domain": "${MCP_GATEWAY_DOMAIN}", + "apiKey": "${MCP_GATEWAY_API_KEY}", + "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" + } + } + GH_AW_MCP_CONFIG_EOF + - name: Generate workflow overview + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + with: + script: | + const { generateWorkflowOverview } = require('/opt/gh-aw/actions/generate_workflow_overview.cjs'); + await generateWorkflowOverview(core); + - name: Download prompt artifact + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 + with: + name: prompt + path: /tmp/gh-aw/aw-prompts + - name: Clean git credentials + run: bash /opt/gh-aw/actions/clean_git_credentials.sh + - name: Execute GitHub Copilot CLI + id: agentic_execution + # Copilot CLI tool arguments (sorted): + timeout-minutes: 60 + run: | + set -o pipefail + sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --allow-domains '*.githubusercontent.com,agents-md-generator.fastmcp.app,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,artifacts.elastic.co,azure.archive.ubuntu.com,cloud.elastic.co,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,ela.st,elastic.co,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,public-code-search.fastmcp.app,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.elastic.co' --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.20.2 --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 --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log + env: + COPILOT_AGENT_RUNNER_TYPE: STANDALONE + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} + GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} + GITHUB_HEAD_REF: ${{ github.head_ref }} + GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + GITHUB_REF_NAME: ${{ github.ref_name }} + GITHUB_STEP_SUMMARY: ${{ env.GITHUB_STEP_SUMMARY }} + GITHUB_WORKSPACE: ${{ github.workspace }} + XDG_CONFIG_HOME: /home/runner + - name: Configure Git credentials + env: + REPO_NAME: ${{ github.repository }} + SERVER_URL: ${{ github.server_url }} + run: | + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git config --global user.name "github-actions[bot]" + # Re-authenticate git with GitHub token + SERVER_URL_STRIPPED="${SERVER_URL#https://}" + git remote set-url origin "https://x-access-token:${{ github.token }}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" + echo "Git configured with standard GitHub Actions identity" + - name: Copy Copilot session state files to logs + if: always() + continue-on-error: true + run: | + # Copy Copilot session state files to logs folder for artifact collection + # This ensures they are in /tmp/gh-aw/ where secret redaction can scan them + SESSION_STATE_DIR="$HOME/.copilot/session-state" + LOGS_DIR="/tmp/gh-aw/sandbox/agent/logs" + + if [ -d "$SESSION_STATE_DIR" ]; then + echo "Copying Copilot session state files from $SESSION_STATE_DIR to $LOGS_DIR" + mkdir -p "$LOGS_DIR" + cp -v "$SESSION_STATE_DIR"/*.jsonl "$LOGS_DIR/" 2>/dev/null || true + echo "Session state files copied successfully" + else + echo "No session-state directory found at $SESSION_STATE_DIR" + fi + - name: Stop MCP Gateway + if: always() + continue-on-error: true + env: + MCP_GATEWAY_PORT: ${{ steps.start-mcp-gateway.outputs.gateway-port }} + MCP_GATEWAY_API_KEY: ${{ steps.start-mcp-gateway.outputs.gateway-api-key }} + GATEWAY_PID: ${{ steps.start-mcp-gateway.outputs.gateway-pid }} + run: | + bash /opt/gh-aw/actions/stop_mcp_gateway.sh "$GATEWAY_PID" + - name: Redact secrets in logs + if: always() + 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/redact_secrets.cjs'); + await main(); + env: + GH_AW_SECRET_NAMES: 'COPILOT_GITHUB_TOKEN,GH_AW_GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,GITHUB_TOKEN' + SECRET_COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + SECRET_GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} + SECRET_GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} + SECRET_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Upload Safe Outputs + if: always() + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: safe-output + path: ${{ env.GH_AW_SAFE_OUTPUTS }} + if-no-files-found: warn + - name: Ingest agent output + id: collect_output + if: always() + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} + GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,agents-md-generator.fastmcp.app,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,artifacts.elastic.co,azure.archive.ubuntu.com,cloud.elastic.co,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,ela.st,elastic.co,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,public-code-search.fastmcp.app,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.elastic.co" + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_API_URL: ${{ github.api_url }} + 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/collect_ndjson_output.cjs'); + await main(); + - name: Upload sanitized agent output + if: always() && env.GH_AW_AGENT_OUTPUT + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: agent-output + path: ${{ env.GH_AW_AGENT_OUTPUT }} + if-no-files-found: warn + - name: Upload engine output files + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: agent_outputs + path: | + /tmp/gh-aw/sandbox/agent/logs/ + /tmp/gh-aw/redacted-urls.log + if-no-files-found: ignore + - name: Parse agent logs for step summary + if: always() + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: /tmp/gh-aw/sandbox/agent/logs/ + 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/parse_copilot_log.cjs'); + await main(); + - name: Parse MCP Gateway logs for step summary + if: always() + 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/parse_mcp_gateway_log.cjs'); + await main(); + - name: Print firewall logs + if: always() + continue-on-error: true + env: + AWF_LOGS_DIR: /tmp/gh-aw/sandbox/firewall/logs + run: | + # Fix permissions on firewall logs so they can be uploaded as artifacts + # AWF runs with sudo, creating files owned by root + sudo chmod -R a+r /tmp/gh-aw/sandbox/firewall/logs 2>/dev/null || true + # Only run awf logs summary if awf command exists (it may not be installed if workflow failed before install step) + if command -v awf &> /dev/null; then + awf logs summary | tee -a "$GITHUB_STEP_SUMMARY" + else + echo 'AWF binary not installed, skipping firewall log summary' + fi + - name: Upload agent artifacts + if: always() + continue-on-error: true + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: agent-artifacts + path: | + /tmp/gh-aw/aw-prompts/prompt.txt + /tmp/gh-aw/aw_info.json + /tmp/gh-aw/mcp-logs/ + /tmp/gh-aw/sandbox/firewall/logs/ + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/agent/ + if-no-files-found: ignore + + conclusion: + needs: + - activation + - agent + - detection + - safe_outputs + if: (always()) && (needs.agent.result != 'skipped') + runs-on: ubuntu-slim + permissions: + contents: read + issues: write + outputs: + noop_message: ${{ steps.noop.outputs.noop_message }} + tools_reported: ${{ steps.missing_tool.outputs.tools_reported }} + total_count: ${{ steps.missing_tool.outputs.total_count }} + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 + with: + destination: /opt/gh-aw/actions + - name: Download agent output artifact + continue-on-error: true + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 + with: + name: agent-output + path: /tmp/gh-aw/safeoutputs/ + - name: Setup agent output environment variable + run: | + mkdir -p /tmp/gh-aw/safeoutputs/ + find "/tmp/gh-aw/safeoutputs/" -type f -print + echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/safeoutputs/agent_output.json" >> "$GITHUB_ENV" + - name: Process No-Op Messages + id: noop + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_NOOP_MAX: 1 + GH_AW_WORKFLOW_NAME: "PR Actions Detective" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/noop.cjs'); + await main(); + - name: Record Missing Tool + id: missing_tool + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_WORKFLOW_NAME: "PR Actions Detective" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/missing_tool.cjs'); + await main(); + - name: Handle Agent Failure + id: handle_agent_failure + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_WORKFLOW_NAME: "PR Actions Detective" + 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: "gh-aw-pr-actions-detective" + GH_AW_SECRET_VERIFICATION_RESULT: ${{ needs.agent.outputs.secret_verification_result }} + GH_AW_CHECKOUT_PR_SUCCESS: ${{ needs.agent.outputs.checkout_pr_success }} + GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\"}" + GH_AW_GROUP_REPORTS: "false" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/handle_agent_failure.cjs'); + await main(); + - name: Handle No-Op Message + id: handle_noop_message + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_WORKFLOW_NAME: "PR Actions Detective" + 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 }} + GH_AW_NOOP_REPORT_AS_ISSUE: "true" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/handle_noop_message.cjs'); + await main(); + + detection: + needs: agent + if: needs.agent.outputs.output_types != '' || needs.agent.outputs.has_patch == 'true' + runs-on: ubuntu-latest + permissions: {} + concurrency: + group: "gh-aw-copilot-${{ github.workflow }}" + timeout-minutes: 10 + outputs: + success: ${{ steps.parse_results.outputs.success }} + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 + with: + destination: /opt/gh-aw/actions + - name: Download agent artifacts + continue-on-error: true + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 + with: + name: agent-artifacts + path: /tmp/gh-aw/threat-detection/ + - name: Download agent output artifact + continue-on-error: true + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 + with: + name: agent-output + path: /tmp/gh-aw/threat-detection/ + - name: Print agent output types + env: + AGENT_OUTPUT_TYPES: ${{ needs.agent.outputs.output_types }} + run: | + echo "Agent output-types: $AGENT_OUTPUT_TYPES" + - name: Setup threat detection + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + WORKFLOW_NAME: "PR Actions Detective" + WORKFLOW_DESCRIPTION: "Analyze failed PR checks and report findings" + HAS_PATCH: ${{ needs.agent.outputs.has_patch }} + 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/setup_threat_detection.cjs'); + await main(); + - name: Ensure threat-detection directory and log + run: | + mkdir -p /tmp/gh-aw/threat-detection + touch /tmp/gh-aw/threat-detection/detection.log + - name: Validate COPILOT_GITHUB_TOKEN secret + id: validate-secret + run: /opt/gh-aw/actions/validate_multi_secret.sh COPILOT_GITHUB_TOKEN 'GitHub Copilot CLI' https://github.github.com/gh-aw/reference/engines/#github-copilot-default + env: + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + - name: Install GitHub Copilot CLI + run: /opt/gh-aw/actions/install_copilot_cli.sh 0.0.412 + - name: Execute GitHub Copilot CLI + id: agentic_execution + # Copilot CLI tool arguments (sorted): + # --allow-tool shell(cat) + # --allow-tool shell(grep) + # --allow-tool shell(head) + # --allow-tool shell(jq) + # --allow-tool shell(ls) + # --allow-tool shell(tail) + # --allow-tool shell(wc) + timeout-minutes: 20 + run: | + set -o pipefail + COPILOT_CLI_INSTRUCTION="$(cat /tmp/gh-aw/aw-prompts/prompt.txt)" + mkdir -p /tmp/ + mkdir -p /tmp/gh-aw/ + mkdir -p /tmp/gh-aw/agent/ + mkdir -p /tmp/gh-aw/sandbox/agent/logs/ + copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log + env: + COPILOT_AGENT_RUNNER_TYPE: STANDALONE + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GITHUB_HEAD_REF: ${{ github.head_ref }} + GITHUB_REF_NAME: ${{ github.ref_name }} + GITHUB_STEP_SUMMARY: ${{ env.GITHUB_STEP_SUMMARY }} + GITHUB_WORKSPACE: ${{ github.workspace }} + XDG_CONFIG_HOME: /home/runner + - name: Parse threat detection results + id: parse_results + 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/parse_threat_detection_results.cjs'); + await main(); + - name: Upload threat detection log + if: always() + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: threat-detection.log + path: /tmp/gh-aw/threat-detection/detection.log + if-no-files-found: ignore + + pre_activation: + runs-on: ubuntu-slim + outputs: + activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 + with: + destination: /opt/gh-aw/actions + - name: Check team membership for workflow + id: check_membership + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_REQUIRED_ROLES: admin,maintainer,write + GH_AW_ALLOWED_BOTS: ${{ inputs.allowed-bot-users }} + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + 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_membership.cjs'); + await main(); + + safe_outputs: + needs: + - agent + - detection + if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (needs.detection.outputs.success == 'true') + runs-on: ubuntu-slim + permissions: + contents: read + issues: write + timeout-minutes: 15 + env: + GH_AW_ENGINE_ID: "copilot" + GH_AW_ENGINE_MODEL: "${{ inputs.model }}" + GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\"}" + GH_AW_WORKFLOW_ID: "gh-aw-pr-actions-detective" + GH_AW_WORKFLOW_NAME: "PR Actions Detective" + outputs: + create_discussion_error_count: ${{ steps.process_safe_outputs.outputs.create_discussion_error_count }} + create_discussion_errors: ${{ steps.process_safe_outputs.outputs.create_discussion_errors }} + process_safe_outputs_processed_count: ${{ steps.process_safe_outputs.outputs.processed_count }} + process_safe_outputs_temporary_id_map: ${{ steps.process_safe_outputs.outputs.temporary_id_map }} + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 + with: + destination: /opt/gh-aw/actions + - name: Download agent output artifact + continue-on-error: true + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 + with: + name: agent-output + path: /tmp/gh-aw/safeoutputs/ + - name: Setup agent output environment variable + run: | + mkdir -p /tmp/gh-aw/safeoutputs/ + find "/tmp/gh-aw/safeoutputs/" -type f -print + echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/safeoutputs/agent_output.json" >> "$GITHUB_ENV" + - name: Process Safe Outputs + id: process_safe_outputs + 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},\"missing_data\":{},\"missing_tool\":{}}" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/safe_output_handler_manager.cjs'); + await main(); + - name: Upload safe output items manifest + if: always() + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: safe-output-items + path: /tmp/safe-output-items.jsonl + if-no-files-found: warn + diff --git a/.github/workflows/gh-aw-pr-ci-detective.md b/.github/workflows/gh-aw-pr-actions-detective.md similarity index 93% rename from .github/workflows/gh-aw-pr-ci-detective.md rename to .github/workflows/gh-aw-pr-actions-detective.md index 748cee2c..f955f964 100644 --- a/.github/workflows/gh-aw-pr-ci-detective.md +++ b/.github/workflows/gh-aw-pr-actions-detective.md @@ -1,4 +1,5 @@ --- +inlined-imports: true description: "Analyze failed PR checks and report findings" imports: - gh-aw-fragments/elastic-tools.md @@ -11,10 +12,15 @@ imports: - gh-aw-fragments/safe-output-add-comment.md engine: id: copilot - model: gpt-5.3-codex + model: ${{ inputs.model }} on: workflow_call: inputs: + model: + description: "AI model to use" + type: string + required: false + default: "gpt-5.3-codex" additional-instructions: description: "Repo-specific instructions appended to the agent prompt" type: string @@ -42,7 +48,7 @@ on: bots: - "${{ inputs.allowed-bot-users }}" concurrency: - group: pr-ci-detective-${{ github.event.workflow_run.id }} + group: pr-actions-detective-${{ github.event.workflow_run.id }} cancel-in-progress: false permissions: actions: read @@ -68,7 +74,7 @@ steps: run: eval "$SETUP_COMMANDS" --- -# PR CI Detective +# PR Actions Detective Assist with failed GitHub Actions checks for pull requests in ${{ github.repository }}. Analyze workflow run logs, explain failures, and recommend fixes. This workflow is read-only. diff --git a/.github/workflows/gh-aw-pr-ci-fixer.lock.yml b/.github/workflows/gh-aw-pr-actions-fixer.lock.yml similarity index 93% rename from .github/workflows/gh-aw-pr-ci-fixer.lock.yml rename to .github/workflows/gh-aw-pr-actions-fixer.lock.yml index 7e4fa6af..48897b06 100644 --- a/.github/workflows/gh-aw-pr-ci-fixer.lock.yml +++ b/.github/workflows/gh-aw-pr-actions-fixer.lock.yml @@ -35,9 +35,11 @@ # - gh-aw-fragments/safe-output-push-to-pr.md # - gh-aw-fragments/workflow-edit-guardrails.md # -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"ebe7a43073688cbe96c7448df7124638457ab018060da9906b79720a2f569701"} +# inlined-imports: true +# +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"e1596fb0ff104ce90843c131835190adbd09adf41291c87b51c11fd34ba00b13"} -name: "PR CI Fixer" +name: "PR Actions Fixer" "on": # bots: # Bots processed as bot check in pre-activation job # - ${{ inputs.allowed-bot-users }} # Bots processed as bot check in pre-activation job @@ -62,6 +64,11 @@ name: "PR CI Fixer" description: Footer appended to all agent comments and reviews required: false type: string + model: + default: gpt-5.3-codex + description: AI model to use + required: false + type: string setup-commands: default: "" description: Shell commands to run before the agent starts (dependency install, build, etc.) @@ -79,9 +86,9 @@ permissions: {} concurrency: cancel-in-progress: false - group: pr-ci-fixer-${{ inputs.workflow-run-id }} + group: pr-actions-fixer-${{ inputs.workflow-run-id }} -run-name: "PR CI Fixer" +run-name: "PR Actions Fixer" jobs: activation: @@ -95,7 +102,7 @@ jobs: comment_repo: "" steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Validate context variables @@ -117,7 +124,7 @@ jobs: - name: Check workflow file timestamps uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: - GH_AW_WORKFLOW_FILE: "gh-aw-pr-ci-fixer.lock.yml" + GH_AW_WORKFLOW_FILE: "gh-aw-pr-actions-fixer.lock.yml" with: script: | const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); @@ -173,6 +180,32 @@ jobs: **Critical**: Tool calls write structured data that downstream jobs process. Without tool calls, follow-up actions will be skipped. **Note**: If you made no other safe output tool calls during this workflow execution, call the "noop" tool to provide a status message indicating completion or that no actions were needed. + + --- + + ## Adding a Comment to an Issue or Pull Request, Pushing Changes to Branch, Reporting Missing Tools or Functionality, Reporting Missing Data + + **IMPORTANT**: To perform the actions listed above, use the **safeoutputs** tools. Do NOT use `gh`, do NOT call the GitHub API directly. You do not have write access to the GitHub repository. + + **Adding a Comment to an Issue or Pull Request** + + To add a comment to an issue or pull request, use the add_comment tool from safeoutputs. + + **Pushing Changes to a Pull Request Branch** + + To push changes to the branch of a pull request: + 1. Make any file changes directly in the working directory. + 2. Add and commit your changes to the local copy of the pull request branch. Be careful to add exactly the files you intend, and verify you haven't deleted or changed any files you didn't intend to. + 3. Push the branch to the repo by using the push_to_pull_request_branch tool from safeoutputs. + + **Reporting Missing Tools or Functionality** + + To report a missing tool or capability, use the missing_tool tool from safeoutputs. + + **Reporting Missing Data** + + To report missing data required to achieve a goal, use the missing_data tool from safeoutputs. + @@ -316,7 +349,7 @@ jobs: 4. Use push_to_pull_request_branch to push GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - # PR CI Fixer + # PR Actions Fixer Assist with failed GitHub Actions checks for pull requests in __GH_AW_GITHUB_REPOSITORY__. This workflow is opt-in and uses a provided workflow run ID. @@ -468,7 +501,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: ghawprcifixer + GH_AW_WORKFLOW_ID_SANITIZED: ghawpractionsfixer outputs: checkout_pr_success: ${{ steps.checkout-pr.outputs.checkout_pr_success || 'true' }} has_patch: ${{ steps.collect_output.outputs.has_patch }} @@ -478,7 +511,7 @@ jobs: secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Checkout repository @@ -572,10 +605,10 @@ jobs: const awInfo = { engine_id: "copilot", engine_name: "GitHub Copilot CLI", - model: "gpt-5.3-codex", + model: "${{ inputs.model }}", version: "", agent_version: "0.0.412", - workflow_name: "PR CI Fixer", + workflow_name: "PR Actions Fixer", experimental: false, supports_tools_allowlist: true, run_id: context.runId, @@ -646,7 +679,7 @@ jobs: "type": "string" }, "item_number": { - "description": "The issue, pull request, or discussion number to comment on. This is the numeric ID from the GitHub URL (e.g., 123 in github.com/owner/repo/issues/123). If omitted, the tool will attempt to resolve the target from the current workflow context (triggering issue, PR, or discussion).", + "description": "The issue, pull request, or discussion number to comment on. This is the numeric ID from the GitHub URL (e.g., 123 in github.com/owner/repo/issues/123). If omitted, the tool auto-targets the issue, PR, or discussion that triggered this workflow. Auto-targeting only works for issue, pull_request, discussion, and comment event triggers — it does NOT work for schedule, workflow_dispatch, push, or workflow_run triggers. For those trigger types, always provide item_number explicitly, or the comment will be silently discarded.", "type": "number" } }, @@ -769,6 +802,35 @@ jobs: }, "item_number": { "issueOrPRNumber": true + }, + "repo": { + "type": "string", + "maxLength": 256 + } + } + }, + "missing_data": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "context": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "data_type": { + "type": "string", + "sanitize": true, + "maxLength": 128 + }, + "reason": { + "type": "string", + "sanitize": true, + "maxLength": 256 } } }, @@ -1050,10 +1112,11 @@ jobs: run: | set -o pipefail sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --allow-domains '*.githubusercontent.com,agents-md-generator.fastmcp.app,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,artifacts.elastic.co,azure.archive.ubuntu.com,cloud.elastic.co,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,ela.st,elastic.co,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,public-code-search.fastmcp.app,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.elastic.co' --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.20.2 --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 --model gpt-5.3-codex --allow-all-tools --allow-all-paths --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log + -- /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 --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} @@ -1210,7 +1273,7 @@ jobs: /tmp/gh-aw/sandbox/firewall/logs/ /tmp/gh-aw/agent-stdio.log /tmp/gh-aw/agent/ - /tmp/gh-aw/aw.patch + /tmp/gh-aw/aw-*.patch if-no-files-found: ignore conclusion: @@ -1231,7 +1294,7 @@ jobs: total_count: ${{ steps.missing_tool.outputs.total_count }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent output artifact @@ -1251,7 +1314,7 @@ jobs: env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} GH_AW_NOOP_MAX: 1 - GH_AW_WORKFLOW_NAME: "PR CI Fixer" + GH_AW_WORKFLOW_NAME: "PR Actions Fixer" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | @@ -1264,7 +1327,7 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_WORKFLOW_NAME: "PR CI Fixer" + GH_AW_WORKFLOW_NAME: "PR Actions Fixer" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | @@ -1277,10 +1340,10 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_WORKFLOW_NAME: "PR CI Fixer" + GH_AW_WORKFLOW_NAME: "PR Actions Fixer" 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: "gh-aw-pr-ci-fixer" + GH_AW_WORKFLOW_ID: "gh-aw-pr-actions-fixer" GH_AW_SECRET_VERIFICATION_RESULT: ${{ needs.agent.outputs.secret_verification_result }} GH_AW_CHECKOUT_PR_SUCCESS: ${{ needs.agent.outputs.checkout_pr_success }} GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\"}" @@ -1297,7 +1360,7 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_WORKFLOW_NAME: "PR CI Fixer" + GH_AW_WORKFLOW_NAME: "PR Actions Fixer" 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 }} @@ -1322,7 +1385,7 @@ jobs: success: ${{ steps.parse_results.outputs.success }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent artifacts @@ -1345,7 +1408,7 @@ jobs: - name: Setup threat detection uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: - WORKFLOW_NAME: "PR CI Fixer" + WORKFLOW_NAME: "PR Actions Fixer" WORKFLOW_DESCRIPTION: "Opt-in fixer for failed PR checks that can push safe, targeted changes" HAS_PATCH: ${{ needs.agent.outputs.has_patch }} with: @@ -1383,10 +1446,11 @@ jobs: mkdir -p /tmp/gh-aw/ mkdir -p /tmp/gh-aw/agent/ mkdir -p /tmp/gh-aw/sandbox/agent/logs/ - copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --model gpt-5.3-codex --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log + copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_REF_NAME: ${{ github.ref_name }} @@ -1416,7 +1480,7 @@ jobs: activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Check team membership for workflow @@ -1447,10 +1511,10 @@ jobs: timeout-minutes: 15 env: GH_AW_ENGINE_ID: "copilot" - GH_AW_ENGINE_MODEL: "gpt-5.3-codex" + GH_AW_ENGINE_MODEL: "${{ inputs.model }}" GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\"}" - GH_AW_WORKFLOW_ID: "gh-aw-pr-ci-fixer" - GH_AW_WORKFLOW_NAME: "PR CI Fixer" + GH_AW_WORKFLOW_ID: "gh-aw-pr-actions-fixer" + GH_AW_WORKFLOW_NAME: "PR Actions Fixer" outputs: create_discussion_error_count: ${{ steps.process_safe_outputs.outputs.create_discussion_error_count }} create_discussion_errors: ${{ steps.process_safe_outputs.outputs.create_discussion_errors }} @@ -1458,7 +1522,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@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent output artifact @@ -1482,7 +1546,7 @@ jobs: if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'push_to_pull_request_branch')) uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: - ref: ${{ github.ref_name }} + ref: ${{ github.base_ref || github.ref_name }} token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} persist-credentials: false fetch-depth: 1 @@ -1504,7 +1568,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},\"missing_data\":{},\"missing_tool\":{},\"push_to_pull_request_branch\":{\"base_branch\":\"${{ github.ref_name }}\",\"if_no_changes\":\"warn\",\"max_patch_size\":1024}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_comment\":{\"max\":1},\"missing_data\":{},\"missing_tool\":{},\"push_to_pull_request_branch\":{\"base_branch\":\"${{ github.base_ref || github.ref_name }}\",\"if_no_changes\":\"warn\",\"max_patch_size\":1024}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/gh-aw-pr-ci-fixer.md b/.github/workflows/gh-aw-pr-actions-fixer.md similarity index 94% rename from .github/workflows/gh-aw-pr-ci-fixer.md rename to .github/workflows/gh-aw-pr-actions-fixer.md index d5efb96f..37d74ca1 100644 --- a/.github/workflows/gh-aw-pr-ci-fixer.md +++ b/.github/workflows/gh-aw-pr-actions-fixer.md @@ -1,4 +1,5 @@ --- +inlined-imports: true description: "Opt-in fixer for failed PR checks that can push safe, targeted changes" imports: - gh-aw-fragments/elastic-tools.md @@ -12,10 +13,15 @@ imports: - gh-aw-fragments/safe-output-push-to-pr.md engine: id: copilot - model: gpt-5.3-codex + model: ${{ inputs.model }} on: workflow_call: inputs: + model: + description: "AI model to use" + type: string + required: false + default: "gpt-5.3-codex" additional-instructions: description: "Repo-specific instructions appended to the agent prompt" type: string @@ -47,7 +53,7 @@ on: bots: - "${{ inputs.allowed-bot-users }}" concurrency: - group: pr-ci-fixer-${{ inputs.workflow-run-id }} + group: pr-actions-fixer-${{ inputs.workflow-run-id }} cancel-in-progress: false permissions: actions: read @@ -73,7 +79,7 @@ steps: run: eval "$SETUP_COMMANDS" --- -# PR CI Fixer +# PR Actions Fixer Assist with failed GitHub Actions checks for pull requests in ${{ github.repository }}. This workflow is opt-in and uses a provided workflow run ID. diff --git a/.github/workflows/gh-aw-pr-buildkite-detective.lock.yml b/.github/workflows/gh-aw-pr-buildkite-detective.lock.yml index 4e3b6056..904fa4c5 100644 --- a/.github/workflows/gh-aw-pr-buildkite-detective.lock.yml +++ b/.github/workflows/gh-aw-pr-buildkite-detective.lock.yml @@ -33,7 +33,9 @@ # - gh-aw-fragments/runtime-setup.md # - gh-aw-fragments/safe-output-add-comment.md # -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"49c223e171fc8509c66bde986cd214564d91e0944b4a17ddd78ec1c4e60ed8de"} +# inlined-imports: true +# +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"cc7c14a7433b79cbd13c3d506db174c7b72c0bb7d8684847e702cd9608ec71c4"} name: "PR Buildkite Detective" "on": @@ -70,6 +72,11 @@ name: "PR Buildkite Detective" description: Footer appended to all agent comments and reviews required: false type: string + model: + default: gpt-5.3-codex + description: AI model to use + required: false + type: string setup-commands: default: "" description: Shell commands to run before the agent starts (dependency install, build, etc.) @@ -101,7 +108,7 @@ jobs: comment_repo: "" steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Validate context variables @@ -183,6 +190,25 @@ jobs: **Critical**: Tool calls write structured data that downstream jobs process. Without tool calls, follow-up actions will be skipped. **Note**: If you made no other safe output tool calls during this workflow execution, call the "noop" tool to provide a status message indicating completion or that no actions were needed. + + --- + + ## Adding a Comment to an Issue or Pull Request, Reporting Missing Tools or Functionality, Reporting Missing Data + + **IMPORTANT**: To perform the actions listed above, use the **safeoutputs** tools. Do NOT use `gh`, do NOT call the GitHub API directly. You do not have write access to the GitHub repository. + + **Adding a Comment to an Issue or Pull Request** + + To add a comment to an issue or pull request, use the add_comment tool from safeoutputs. + + **Reporting Missing Tools or Functionality** + + To report a missing tool or capability, use the missing_tool tool from safeoutputs. + + **Reporting Missing Data** + + To report missing data required to achieve a goal, use the missing_data tool from safeoutputs. + @@ -498,7 +524,7 @@ jobs: secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Checkout repository @@ -592,7 +618,7 @@ jobs: const awInfo = { engine_id: "copilot", engine_name: "GitHub Copilot CLI", - model: "gpt-5.3-codex", + model: "${{ inputs.model }}", version: "", agent_version: "0.0.412", workflow_name: "PR Buildkite Detective", @@ -666,7 +692,7 @@ jobs: "type": "string" }, "item_number": { - "description": "The issue, pull request, or discussion number to comment on. This is the numeric ID from the GitHub URL (e.g., 123 in github.com/owner/repo/issues/123). If omitted, the tool will attempt to resolve the target from the current workflow context (triggering issue, PR, or discussion).", + "description": "The issue, pull request, or discussion number to comment on. This is the numeric ID from the GitHub URL (e.g., 123 in github.com/owner/repo/issues/123). If omitted, the tool auto-targets the issue, PR, or discussion that triggered this workflow. Auto-targeting only works for issue, pull_request, discussion, and comment event triggers — it does NOT work for schedule, workflow_dispatch, push, or workflow_run triggers. For those trigger types, always provide item_number explicitly, or the comment will be silently discarded.", "type": "number" } }, @@ -761,6 +787,35 @@ jobs: }, "item_number": { "issueOrPRNumber": true + }, + "repo": { + "type": "string", + "maxLength": 256 + } + } + }, + "missing_data": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "context": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "data_type": { + "type": "string", + "sanitize": true, + "maxLength": 128 + }, + "reason": { + "type": "string", + "sanitize": true, + "maxLength": 256 } } }, @@ -939,11 +994,12 @@ jobs: run: | set -o pipefail sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --allow-domains '*.githubusercontent.com,agents-md-generator.fastmcp.app,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,artifacts.elastic.co,azure.archive.ubuntu.com,cloud.elastic.co,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,ela.st,elastic.co,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,mcp.buildkite.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,public-code-search.fastmcp.app,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.elastic.co' --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.20.2 --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 --model gpt-5.3-codex --allow-all-tools --allow-all-paths --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log + -- /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 --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log env: BUILDKITE_API_TOKEN: ${{ secrets.BUILDKITE_API_TOKEN }} COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} @@ -1110,7 +1166,7 @@ jobs: total_count: ${{ steps.missing_tool.outputs.total_count }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent output artifact @@ -1201,7 +1257,7 @@ jobs: success: ${{ steps.parse_results.outputs.success }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent artifacts @@ -1262,10 +1318,11 @@ jobs: mkdir -p /tmp/gh-aw/ mkdir -p /tmp/gh-aw/agent/ mkdir -p /tmp/gh-aw/sandbox/agent/logs/ - copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --model gpt-5.3-codex --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log + copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_REF_NAME: ${{ github.ref_name }} @@ -1295,7 +1352,7 @@ jobs: activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Check team membership for workflow @@ -1324,7 +1381,7 @@ jobs: timeout-minutes: 15 env: GH_AW_ENGINE_ID: "copilot" - GH_AW_ENGINE_MODEL: "gpt-5.3-codex" + GH_AW_ENGINE_MODEL: "${{ inputs.model }}" GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\"}" GH_AW_WORKFLOW_ID: "gh-aw-pr-buildkite-detective" GH_AW_WORKFLOW_NAME: "PR Buildkite Detective" @@ -1335,7 +1392,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@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent output artifact diff --git a/.github/workflows/gh-aw-pr-buildkite-detective.md b/.github/workflows/gh-aw-pr-buildkite-detective.md index 82d50a30..32a9647b 100644 --- a/.github/workflows/gh-aw-pr-buildkite-detective.md +++ b/.github/workflows/gh-aw-pr-buildkite-detective.md @@ -1,4 +1,5 @@ --- +inlined-imports: true description: "Analyze failed Buildkite PR checks and report findings" imports: - gh-aw-fragments/elastic-tools.md @@ -10,10 +11,15 @@ imports: - gh-aw-fragments/safe-output-add-comment.md engine: id: copilot - model: gpt-5.3-codex + model: ${{ inputs.model }} on: workflow_call: inputs: + model: + description: "AI model to use" + type: string + required: false + default: "gpt-5.3-codex" additional-instructions: description: "Repo-specific instructions appended to the agent prompt" type: string diff --git a/.github/workflows/gh-aw-pr-ci-detective.lock.yml b/.github/workflows/gh-aw-pr-ci-detective.lock.yml deleted file mode 100644 index 59d5a9ba..00000000 --- a/.github/workflows/gh-aw-pr-ci-detective.lock.yml +++ /dev/null @@ -1,1308 +0,0 @@ -# -# ___ _ _ -# / _ \ | | (_) -# | |_| | __ _ ___ _ __ | |_ _ ___ -# | _ |/ _` |/ _ \ '_ \| __| |/ __| -# | | | | (_| | __/ | | | |_| | (__ -# \_| |_/\__, |\___|_| |_|\__|_|\___| -# __/ | -# _ _ |___/ -# | | | | / _| | -# | | | | ___ _ __ _ __| |_| | _____ ____ -# | |/\| |/ _ \ '__| |/ /| _| |/ _ \ \ /\ / / ___| -# \ /\ / (_) | | | | ( | | | | (_) \ V V /\__ \ -# \/ \/ \___/|_| |_|\_\|_| |_|\___/ \_/\_/ |___/ -# -# This file was automatically generated by gh-aw. DO NOT EDIT. -# -# To update this file, edit the corresponding .md file and run: -# gh aw compile -# Not all edits will cause changes to this file. -# -# For more information: https://github.github.com/gh-aw/introduction/overview/ -# -# Analyze failed PR checks and report findings -# -# Resolved workflow manifest: -# Imports: -# - gh-aw-fragments/elastic-tools.md -# - gh-aw-fragments/formatting.md -# - gh-aw-fragments/mcp-pagination.md -# - gh-aw-fragments/messages-footer.md -# - gh-aw-fragments/rigor.md -# - gh-aw-fragments/runtime-setup.md -# - gh-aw-fragments/safe-output-add-comment.md -# - gh-aw-fragments/workflow-edit-guardrails.md -# -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"7df8aaa0e9f73130ba31526e12cdb467fcceeb54b3a7682a6de4627fb941dffe"} - -name: "PR CI Detective" -"on": - # bots: # Bots processed as bot check in pre-activation job - # - ${{ inputs.allowed-bot-users }} # Bots processed as bot check in pre-activation job - # roles: # Roles processed as role check in pre-activation job - # - admin # Roles processed as role check in pre-activation job - # - maintainer # Roles processed as role check in pre-activation job - # - write # Roles processed as role check in pre-activation job - workflow_call: - inputs: - additional-instructions: - default: "" - description: Repo-specific instructions appended to the agent prompt - required: false - type: string - allowed-bot-users: - default: github-actions[bot] - description: Allowlisted bot actor usernames (comma-separated) - required: false - type: string - messages-footer: - default: "" - description: Footer appended to all agent comments and reviews - required: false - type: string - setup-commands: - default: "" - description: Shell commands to run before the agent starts (dependency install, build, etc.) - required: false - type: string - secrets: - COPILOT_GITHUB_TOKEN: - required: true - -permissions: {} - -concurrency: - cancel-in-progress: false - group: pr-ci-detective-${{ github.event.workflow_run.id }} - -run-name: "PR CI Detective" - -jobs: - activation: - needs: pre_activation - if: needs.pre_activation.outputs.activated == 'true' - runs-on: ubuntu-slim - permissions: - contents: read - outputs: - comment_id: "" - comment_repo: "" - steps: - - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 - with: - destination: /opt/gh-aw/actions - - name: Validate context variables - 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/validate_context_variables.cjs'); - await main(); - - name: Checkout .github and .agents folders - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - sparse-checkout: | - .github - .agents - fetch-depth: 1 - persist-credentials: false - - name: Check workflow file timestamps - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_WORKFLOW_FILE: "gh-aw-pr-ci-detective.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: Create prompt with built-in context - env: - GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} - GH_AW_GITHUB_ACTOR: ${{ github.actor }} - GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} - GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} - GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} - GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} - GH_AW_GITHUB_EVENT_WORKFLOW_RUN_CONCLUSION: ${{ github.event.workflow_run.conclusion }} - GH_AW_GITHUB_EVENT_WORKFLOW_RUN_ID: ${{ github.event.workflow_run.id }} - GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} - GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} - GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} - run: | - bash /opt/gh-aw/actions/create_prompt_first.sh - cat << 'GH_AW_PROMPT_EOF' > "$GH_AW_PROMPT" - - GH_AW_PROMPT_EOF - cat "/opt/gh-aw/prompts/xpia.md" >> "$GH_AW_PROMPT" - cat "/opt/gh-aw/prompts/temp_folder_prompt.md" >> "$GH_AW_PROMPT" - cat "/opt/gh-aw/prompts/markdown.md" >> "$GH_AW_PROMPT" - cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - - GitHub API Access Instructions - - The gh CLI is NOT authenticated. Do NOT use gh commands for GitHub operations. - - - To create or modify GitHub resources (issues, discussions, pull requests, etc.), you MUST call the appropriate safe output tool. Simply writing content will NOT work - the workflow requires actual tool calls. - - Temporary IDs: Some safe output tools support a temporary ID field (usually named temporary_id) so you can reference newly-created items elsewhere in the SAME agent output (for example, using #aw_abc1 in a later body). - - **IMPORTANT - temporary_id format rules:** - - If you DON'T need to reference the item later, OMIT the temporary_id field entirely (it will be auto-generated if needed) - - If you DO need cross-references/chaining, you MUST match this EXACT validation regex: /^aw_[A-Za-z0-9]{3,8}$/i - - Format: aw_ prefix followed by 3 to 8 alphanumeric characters (A-Z, a-z, 0-9, case-insensitive) - - Valid alphanumeric characters: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 - - INVALID examples: aw_ab (too short), aw_123456789 (too long), aw_test-id (contains hyphen), aw_id_123 (contains underscore) - - VALID examples: aw_abc, aw_abc1, aw_Test123, aw_A1B2C3D4, aw_12345678 - - To generate valid IDs: use 3-8 random alphanumeric characters or omit the field to let the system auto-generate - - Do NOT invent other aw_* formats — downstream steps will reject them with validation errors matching against /^aw_[A-Za-z0-9]{3,8}$/i. - - Discover available tools from the safeoutputs MCP server. - - **Critical**: Tool calls write structured data that downstream jobs process. Without tool calls, follow-up actions will be skipped. - - **Note**: If you made no other safe output tool calls during this workflow execution, call the "noop" tool to provide a status message indicating completion or that no actions were needed. - - - - The following GitHub context information is available for this workflow: - {{#if __GH_AW_GITHUB_ACTOR__ }} - - **actor**: __GH_AW_GITHUB_ACTOR__ - {{/if}} - {{#if __GH_AW_GITHUB_REPOSITORY__ }} - - **repository**: __GH_AW_GITHUB_REPOSITORY__ - {{/if}} - {{#if __GH_AW_GITHUB_WORKSPACE__ }} - - **workspace**: __GH_AW_GITHUB_WORKSPACE__ - {{/if}} - {{#if __GH_AW_GITHUB_EVENT_ISSUE_NUMBER__ }} - - **issue-number**: #__GH_AW_GITHUB_EVENT_ISSUE_NUMBER__ - {{/if}} - {{#if __GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__ }} - - **discussion-number**: #__GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__ - {{/if}} - {{#if __GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__ }} - - **pull-request-number**: #__GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__ - {{/if}} - {{#if __GH_AW_GITHUB_EVENT_COMMENT_ID__ }} - - **comment-id**: __GH_AW_GITHUB_EVENT_COMMENT_ID__ - {{/if}} - {{#if __GH_AW_GITHUB_RUN_ID__ }} - - **workflow-run-id**: __GH_AW_GITHUB_RUN_ID__ - {{/if}} - - - GH_AW_PROMPT_EOF - cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - - GH_AW_PROMPT_EOF - cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - ## MCP Servers - - - **`generate_agents_md`** — generates a summary of the repository's structure, conventions, and coding guidelines from AGENTS.md and related files. Call at the start of every workflow to get repo context. - - **`search_code`** — grep-style search across public GitHub repositories. Use for finding usage patterns in upstream libraries, reference implementations, or examples in open-source projects. This searches *public GitHub repos*, not the local codebase — if available you can use `grep` and file reading for local code. - GH_AW_PROMPT_EOF - cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - - GH_AW_PROMPT_EOF - cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - ## Formatting Guidelines - - - Lead with the most important information — your first sentence should be the key takeaway - - Be concise and actionable — no filler or praise - - Use `
` and `` tags for long sections to keep responses scannable - - Wrap branch names and @-references in backticks to avoid pinging users - - Include code snippets with file paths and line numbers when referencing the codebase - - GH_AW_PROMPT_EOF - cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - ## Rigor - - **Silence is better than noise. A false positive wastes a human's time and erodes trust in every future report.** - - - If you claim something is missing or broken, show the exact evidence in the code — file path, line number, and what you observed. - - If a conclusion depends on assumptions you haven't confirmed, do not assert it. Verify first; if you cannot verify, do not report. - - "I don't know" is better than a wrong answer. `noop` is better than a speculative finding. - - It's worth the time to verify now versus guessing and forcing someone else to verify later. - - Before filing any issue or opening any PR, re-read your own output as a skeptical reviewer. Ask: "Would a senior engineer on this team find this useful, or would they close it immediately?" If the answer is "close," call `noop` instead. - - Only report findings you would confidently defend in a code review. If you feel the need to hedge with "might," "could," or "possibly," the finding is not ready to file. - - GH_AW_PROMPT_EOF - cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - ## MCP Pagination - - MCP tool responses have a **25,000 token limit**. When responses exceed this limit, the call fails and you must retry with pagination — wasting turns and tokens. Use proactive pagination to stay under the limit. - - ### Recommended `perPage` Values - - - **5-10**: For detailed items (PR diffs, files with patches, issues with comments) - - **20-30**: For medium-detail lists (commits, review comments, issue lists) - - **50-100**: For simple list operations (branches, labels, tags) - - ### Pagination Pattern - - When you need all results from a paginated API: - - 1. Fetch the first page with a conservative `perPage` value - 2. Process the results before fetching the next page - 3. Continue fetching pages until you receive fewer results than `perPage` (indicating the last page) - - ### Error Recovery - - If you see an error like: - - `MCP tool response exceeds maximum allowed tokens (25000)` - - `Response too large for tool [tool_name]` - - Retry the same call with a smaller `perPage` value (halve it). - - ### Tips - - - **Start small**: It's better to make multiple small requests than one that fails - - **Fetch incrementally**: Get an overview first, then details for specific items - - **Use filters**: Combine `perPage` with state, label, or date filters to reduce result size - - **Process as you go**: Don't accumulate all pages before acting — process each batch immediately - - GH_AW_PROMPT_EOF - cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - ## Workflow Editing Guardrails - - - Do not modify files under `.github/workflows/`. - - If asked to change workflow files, place a copy under `github/` (no leading dot) and note that a maintainer must relocate it into `.github/workflows/`. - - GH_AW_PROMPT_EOF - cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - ## Message Footer - - A footer is automatically appended to all comments and reviews. Do not add your own footer or sign-off — the runtime handles this. - GH_AW_PROMPT_EOF - cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - ## add-comment Limitations - - - **Body**: Max 65,536 characters (including any footer added by gh-aw). Keep well under this limit. - - **Mentions**: Max 10 `@` mentions per comment. - - **Links**: Max 50 URLs per comment. - - **HTML**: Only safe tags allowed (`details`, `summary`, `code`, `pre`, `blockquote`, `table`, `b`, `em`, `strong`, `h1`–`h6`, `hr`, `br`, `li`, `ol`, `ul`, `p`, `sub`, `sup`). Other tags are converted to parentheses. - - **URLs**: Only HTTPS URLs to allowed domains. Non-HTTPS and non-allowed domains are redacted. - - **Bot triggers**: References like `fixes #123` or `closes #456` are neutralized to prevent unintended issue closures. - - If you exceed 10 mentions or 50 links, the comment will be rejected. - GH_AW_PROMPT_EOF - cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - # PR CI Detective - - Assist with failed GitHub Actions checks for pull requests in __GH_AW_GITHUB_REPOSITORY__. Analyze workflow run logs, explain failures, and recommend fixes. This workflow is read-only. - - ## Context - - - **Repository**: __GH_AW_GITHUB_REPOSITORY__ - - **Workflow Run ID**: __GH_AW_GITHUB_EVENT_WORKFLOW_RUN_ID__ - - **Conclusion**: __GH_AW_GITHUB_EVENT_WORKFLOW_RUN_CONCLUSION__ - - ## Constraints - - - **CAN**: Read files, search code, run tests and commands, comment on PRs - - **CANNOT**: Push changes, merge PRs, or modify `.github/workflows/` - - ## Instructions - - ### Step 1: Gather Context - - 1. Call `generate_agents_md` to get the repository's coding guidelines and conventions. If this fails, continue without it. - 2. Identify the PRs associated with the workflow run using `github.event.workflow_run.pull_requests`. If there are none, call `noop` with message "No pull request associated with workflow run; nothing to do" and stop. - 3. For each PR, call `pull_request_read` with method `get` to capture the author, branches, and fork status. - 4. Fetch workflow run details and logs with `bash` + `gh api`: - - List jobs and their conclusions: - ````bash - gh api repos/{owner}/{repo}/actions/runs/{run_id}/jobs \ - --jq '.jobs[] | {id: .id, name: .name, conclusion: .conclusion, html_url: .html_url}' - ```` - - Download logs to `/tmp/gh-aw/agent/` and inspect the failing step output: - ````bash - gh api repos/{owner}/{repo}/actions/runs/{run_id}/logs \ - -H "Accept: application/vnd.github+json" \ - > /tmp/gh-aw/agent/workflow-logs-{run_id}.zip - unzip -o /tmp/gh-aw/agent/workflow-logs-{run_id}.zip -d /tmp/gh-aw/agent/workflow-logs-{run_id}/ - ```` - - ### Step 2: Analyze - - - Identify the failing job/step and summarize the root cause. - - Propose a concrete, minimal fix or remediation plan. - - If the logs are inconclusive, state what additional data is needed. - - ### Step 3: Respond - - Call `add_comment` on the PR with: - - A concise summary of the failure and root cause - - The recommended fix or remediation plan - - Tests run and their results (if any) - - Any follow-up steps required - - __GH_AW_EXPR_49B959F1__ - - GH_AW_PROMPT_EOF - - name: Interpolate variables and render templates - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - GH_AW_GITHUB_EVENT_WORKFLOW_RUN_CONCLUSION: ${{ github.event.workflow_run.conclusion }} - GH_AW_GITHUB_EVENT_WORKFLOW_RUN_ID: ${{ github.event.workflow_run.id }} - GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} - GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} - 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/interpolate_prompt.cjs'); - await main(); - - name: Substitute placeholders - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} - GH_AW_GITHUB_ACTOR: ${{ github.actor }} - GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} - GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} - GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} - GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} - GH_AW_GITHUB_EVENT_WORKFLOW_RUN_CONCLUSION: ${{ github.event.workflow_run.conclusion }} - GH_AW_GITHUB_EVENT_WORKFLOW_RUN_ID: ${{ github.event.workflow_run.id }} - 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'); - setupGlobals(core, github, context, exec, io); - - const substitutePlaceholders = require('/opt/gh-aw/actions/substitute_placeholders.cjs'); - - // Call the substitution function - return await substitutePlaceholders({ - file: process.env.GH_AW_PROMPT, - substitutions: { - GH_AW_EXPR_49B959F1: process.env.GH_AW_EXPR_49B959F1, - GH_AW_GITHUB_ACTOR: process.env.GH_AW_GITHUB_ACTOR, - GH_AW_GITHUB_EVENT_COMMENT_ID: process.env.GH_AW_GITHUB_EVENT_COMMENT_ID, - GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: process.env.GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER, - GH_AW_GITHUB_EVENT_ISSUE_NUMBER: process.env.GH_AW_GITHUB_EVENT_ISSUE_NUMBER, - GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: process.env.GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER, - GH_AW_GITHUB_EVENT_WORKFLOW_RUN_CONCLUSION: process.env.GH_AW_GITHUB_EVENT_WORKFLOW_RUN_CONCLUSION, - GH_AW_GITHUB_EVENT_WORKFLOW_RUN_ID: process.env.GH_AW_GITHUB_EVENT_WORKFLOW_RUN_ID, - 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_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 - env: - GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - run: bash /opt/gh-aw/actions/validate_prompt_placeholders.sh - - name: Print prompt - env: - GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - run: bash /opt/gh-aw/actions/print_prompt_summary.sh - - name: Upload prompt artifact - if: success() - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 - with: - name: prompt - path: /tmp/gh-aw/aw-prompts/prompt.txt - retention-days: 1 - - agent: - needs: activation - runs-on: ubuntu-latest - permissions: - actions: read - contents: read - issues: read - pull-requests: read - concurrency: - group: "gh-aw-copilot-${{ github.workflow }}" - env: - DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} - GH_AW_ASSETS_ALLOWED_EXTS: "" - GH_AW_ASSETS_BRANCH: "" - GH_AW_ASSETS_MAX_SIZE_KB: 0 - GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs - 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: ghawprcidetective - outputs: - checkout_pr_success: ${{ steps.checkout-pr.outputs.checkout_pr_success || 'true' }} - has_patch: ${{ steps.collect_output.outputs.has_patch }} - model: ${{ steps.generate_aw_info.outputs.model }} - output: ${{ steps.collect_output.outputs.output }} - output_types: ${{ steps.collect_output.outputs.output_types }} - secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} - steps: - - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 - with: - destination: /opt/gh-aw/actions - - name: Checkout repository - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - persist-credentials: false - - name: Create gh-aw temp directory - run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh - - if: hashFiles('go.mod') != '' - name: Setup Go - uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5 - with: - cache: true - go-version-file: go.mod - - if: hashFiles('.python-version') != '' - name: Setup Python - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 - with: - python-version-file: .python-version - - if: hashFiles('.node-version') != '' - name: Setup Node.js (.node-version) - uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6 - with: - node-version-file: .node-version - - if: hashFiles('.node-version') == '' && hashFiles('.nvmrc') != '' - name: Setup Node.js (.nvmrc) - uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6 - with: - node-version-file: .nvmrc - - if: hashFiles('.ruby-version') != '' - name: Setup Ruby - uses: ruby/setup-ruby@09a7688d3b55cf0e976497ff046b70949eeaccfd # v1 - with: - bundler-cache: true - ruby-version: .ruby-version - - id: setup-uv - if: hashFiles('pyproject.toml', 'uv.lock') != '' - name: Setup uv - uses: astral-sh/setup-uv@e58605a9b6da7c637471fab8847a5e5a6b8df081 # v5 - - env: - UV_PATH: ${{ steps.setup-uv.outputs.uv-path }} - WORKSPACE: ${{ github.workspace }} - if: hashFiles('pyproject.toml', 'uv.lock') != '' - name: Expose uv in workspace - run: |- - set -euo pipefail - install_dir="$WORKSPACE/.gh-aw-tools/bin" - mkdir -p "$install_dir" - cp "$UV_PATH" "$install_dir/uv" - chmod +x "$install_dir/uv" - echo "$install_dir" >> "$GITHUB_PATH" - shell: bash - - env: - SETUP_COMMANDS: ${{ inputs.setup-commands }} - if: ${{ inputs.setup-commands != '' }} - name: Repo-specific setup - run: eval "$SETUP_COMMANDS" - - - name: Configure Git credentials - env: - REPO_NAME: ${{ github.repository }} - SERVER_URL: ${{ github.server_url }} - run: | - git config --global user.email "github-actions[bot]@users.noreply.github.com" - git config --global user.name "github-actions[bot]" - # Re-authenticate git with GitHub token - SERVER_URL_STRIPPED="${SERVER_URL#https://}" - git remote set-url origin "https://x-access-token:${{ github.token }}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" - echo "Git configured with standard GitHub Actions identity" - - name: Checkout PR branch - id: checkout-pr - if: | - github.event.pull_request - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - with: - github-token: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - script: | - const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io); - const { main } = require('/opt/gh-aw/actions/checkout_pr_branch.cjs'); - await main(); - - name: Generate agentic run info - id: generate_aw_info - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - with: - script: | - const fs = require('fs'); - - const awInfo = { - engine_id: "copilot", - engine_name: "GitHub Copilot CLI", - model: "gpt-5.3-codex", - version: "", - agent_version: "0.0.412", - workflow_name: "PR CI Detective", - experimental: false, - supports_tools_allowlist: true, - run_id: context.runId, - run_number: context.runNumber, - run_attempt: process.env.GITHUB_RUN_ATTEMPT, - repository: context.repo.owner + '/' + context.repo.repo, - ref: context.ref, - sha: context.sha, - actor: context.actor, - event_name: context.eventName, - staged: false, - allowed_domains: ["agents-md-generator.fastmcp.app","artifacts.elastic.co","cloud.elastic.co","defaults","ela.st","elastic.co","github","public-code-search.fastmcp.app","www.elastic.co"], - firewall_enabled: true, - awf_version: "v0.20.2", - awmg_version: "v0.1.4", - steps: { - firewall: "squid" - }, - created_at: new Date().toISOString() - }; - - // Write to /tmp/gh-aw directory to avoid inclusion in PR - const tmpPath = '/tmp/gh-aw/aw_info.json'; - fs.writeFileSync(tmpPath, JSON.stringify(awInfo, null, 2)); - console.log('Generated aw_info.json at:', tmpPath); - console.log(JSON.stringify(awInfo, null, 2)); - - // Set model as output for reuse in other steps/jobs - core.setOutput('model', awInfo.model); - - name: Validate COPILOT_GITHUB_TOKEN secret - id: validate-secret - run: /opt/gh-aw/actions/validate_multi_secret.sh COPILOT_GITHUB_TOKEN 'GitHub Copilot CLI' https://github.github.com/gh-aw/reference/engines/#github-copilot-default - env: - COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} - - name: Install GitHub Copilot CLI - run: /opt/gh-aw/actions/install_copilot_cli.sh 0.0.412 - - name: Install awf binary - run: bash /opt/gh-aw/actions/install_awf_binary.sh v0.20.2 - - name: Determine automatic lockdown mode for GitHub MCP Server - id: determine-automatic-lockdown - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} - GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} - with: - script: | - 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.20.2 ghcr.io/github/gh-aw-firewall/api-proxy:0.20.2 ghcr.io/github/gh-aw-firewall/squid:0.20.2 ghcr.io/github/gh-aw-mcpg:v0.1.4 ghcr.io/github/github-mcp-server:v0.31.0 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},"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": "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. NOTE: By default, this tool requires discussions:write permission. If your GitHub App lacks Discussions permission, set 'discussions: false' in the workflow's safe-outputs.add-comment configuration to exclude this permission. CONSTRAINTS: Maximum 1 comment(s) can be added.", - "inputSchema": { - "additionalProperties": false, - "properties": { - "body": { - "description": "The comment text in Markdown format. This is the 'body' field - do not use 'comment_body' or other variations. Provide helpful, relevant information that adds value to the conversation. CONSTRAINTS: The complete comment (your body text + automatically added footer) must not exceed 65536 characters total. Maximum 10 mentions (@username), maximum 50 links (http/https URLs). A footer (~200-500 characters) is automatically appended with workflow attribution, so leave adequate space. If these limits are exceeded, the tool call will fail with a detailed error message indicating which constraint was violated.", - "type": "string" - }, - "item_number": { - "description": "The issue, pull request, or discussion number to comment on. This is the numeric ID from the GitHub URL (e.g., 123 in github.com/owner/repo/issues/123). If omitted, the tool will attempt to resolve the target from the current workflow context (triggering issue, PR, or discussion).", - "type": "number" - } - }, - "required": [ - "body" - ], - "type": "object" - }, - "name": "add_comment" - }, - { - "description": "Report that a tool or capability needed to complete the task is not available, or share any information you deem important about missing functionality or limitations. Use this when you cannot accomplish what was requested because the required functionality is missing or access is restricted.", - "inputSchema": { - "additionalProperties": false, - "properties": { - "alternatives": { - "description": "Any workarounds, manual steps, or alternative approaches the user could take (max 256 characters).", - "type": "string" - }, - "reason": { - "description": "Explanation of why this tool is needed or what information you want to share about the limitation (max 256 characters).", - "type": "string" - }, - "tool": { - "description": "Optional: Name or description of the missing tool or capability (max 128 characters). Be specific about what functionality is needed.", - "type": "string" - } - }, - "required": [ - "reason" - ], - "type": "object" - }, - "name": "missing_tool" - }, - { - "description": "Log a transparency message when no significant actions are needed. Use this to confirm workflow completion and provide visibility when analysis is complete but no changes or outputs are required (e.g., 'No issues found', 'All checks passed'). This ensures the workflow produces human-visible output even when no other actions are taken.", - "inputSchema": { - "additionalProperties": false, - "properties": { - "message": { - "description": "Status or completion message to log. Should explain what was analyzed and the outcome (e.g., 'Code review complete - no issues found', 'Analysis complete - all tests passing').", - "type": "string" - } - }, - "required": [ - "message" - ], - "type": "object" - }, - "name": "noop" - }, - { - "description": "Report that data or information needed to complete the task is not available. Use this when you cannot accomplish what was requested because required data, context, or information is missing.", - "inputSchema": { - "additionalProperties": false, - "properties": { - "alternatives": { - "description": "Any workarounds, manual steps, or alternative approaches the user could take (max 256 characters).", - "type": "string" - }, - "context": { - "description": "Additional context about the missing data or where it should come from (max 256 characters).", - "type": "string" - }, - "data_type": { - "description": "Type or description of the missing data or information (max 128 characters). Be specific about what data is needed.", - "type": "string" - }, - "reason": { - "description": "Explanation of why this data is needed to complete the task (max 256 characters).", - "type": "string" - } - }, - "required": [], - "type": "object" - }, - "name": "missing_data" - } - ] - GH_AW_SAFE_OUTPUTS_TOOLS_EOF - cat > /opt/gh-aw/safeoutputs/validation.json << 'GH_AW_SAFE_OUTPUTS_VALIDATION_EOF' - { - "add_comment": { - "defaultMax": 1, - "fields": { - "body": { - "required": true, - "type": "string", - "sanitize": true, - "maxLength": 65000 - }, - "item_number": { - "issueOrPRNumber": true - } - } - }, - "missing_tool": { - "defaultMax": 20, - "fields": { - "alternatives": { - "type": "string", - "sanitize": true, - "maxLength": 512 - }, - "reason": { - "required": true, - "type": "string", - "sanitize": true, - "maxLength": 256 - }, - "tool": { - "type": "string", - "sanitize": true, - "maxLength": 128 - } - } - }, - "noop": { - "defaultMax": 1, - "fields": { - "message": { - "required": true, - "type": "string", - "sanitize": true, - "maxLength": 65000 - } - } - } - } - GH_AW_SAFE_OUTPUTS_VALIDATION_EOF - - name: Generate Safe Outputs MCP Server Config - id: safe-outputs-config - run: | - # Generate a secure random API key (360 bits of entropy, 40+ chars) - # Mask immediately to prevent timing vulnerabilities - API_KEY=$(openssl rand -base64 45 | tr -d '/+=') - echo "::add-mask::${API_KEY}" - - PORT=3001 - - # Set outputs for next steps - { - echo "safe_outputs_api_key=${API_KEY}" - echo "safe_outputs_port=${PORT}" - } >> "$GITHUB_OUTPUT" - - echo "Safe Outputs MCP server will run on port ${PORT}" - - - name: Start Safe Outputs MCP HTTP Server - id: safe-outputs-start - env: - DEBUG: '*' - GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-config.outputs.safe_outputs_port }} - GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-config.outputs.safe_outputs_api_key }} - GH_AW_SAFE_OUTPUTS_TOOLS_PATH: /opt/gh-aw/safeoutputs/tools.json - GH_AW_SAFE_OUTPUTS_CONFIG_PATH: /opt/gh-aw/safeoutputs/config.json - GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs - run: | - # Environment variables are set above to prevent template injection - export DEBUG - export GH_AW_SAFE_OUTPUTS_PORT - export GH_AW_SAFE_OUTPUTS_API_KEY - export GH_AW_SAFE_OUTPUTS_TOOLS_PATH - export GH_AW_SAFE_OUTPUTS_CONFIG_PATH - export GH_AW_MCP_LOG_DIR - - bash /opt/gh-aw/actions/start_safe_outputs_server.sh - - - name: Start MCP Gateway - id: start-mcp-gateway - env: - GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-start.outputs.api_key }} - GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-start.outputs.port }} - GITHUB_MCP_LOCKDOWN: ${{ steps.determine-automatic-lockdown.outputs.lockdown == 'true' && '1' || '0' }} - GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - run: | - set -eo pipefail - mkdir -p /tmp/gh-aw/mcp-config - - # Export gateway environment variables for MCP config and gateway script - export MCP_GATEWAY_PORT="80" - export MCP_GATEWAY_DOMAIN="host.docker.internal" - MCP_GATEWAY_API_KEY=$(openssl rand -base64 45 | tr -d '/+=') - echo "::add-mask::${MCP_GATEWAY_API_KEY}" - export MCP_GATEWAY_API_KEY - export MCP_GATEWAY_PAYLOAD_DIR="/tmp/gh-aw/mcp-payloads" - mkdir -p "${MCP_GATEWAY_PAYLOAD_DIR}" - export DEBUG="*" - - export GH_AW_ENGINE="copilot" - 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 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_LOCKDOWN -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.1.4' - - mkdir -p /home/runner/.copilot - cat << GH_AW_MCP_CONFIG_EOF | bash /opt/gh-aw/actions/start_mcp_gateway.sh - { - "mcpServers": { - "agents-md-generator": { - "type": "http", - "url": "https://agents-md-generator.fastmcp.app/mcp", - "tools": [ - "generate_agents_md" - ] - }, - "github": { - "type": "stdio", - "container": "ghcr.io/github/github-mcp-server:v0.31.0", - "env": { - "GITHUB_LOCKDOWN_MODE": "$GITHUB_MCP_LOCKDOWN", - "GITHUB_PERSONAL_ACCESS_TOKEN": "\${GITHUB_MCP_SERVER_TOKEN}", - "GITHUB_READ_ONLY": "1", - "GITHUB_TOOLSETS": "repos,issues,pull_requests,search,actions" - } - }, - "public-code-search": { - "type": "http", - "url": "https://public-code-search.fastmcp.app/mcp", - "tools": [ - "search_code" - ] - }, - "safeoutputs": { - "type": "http", - "url": "http://host.docker.internal:$GH_AW_SAFE_OUTPUTS_PORT", - "headers": { - "Authorization": "\${GH_AW_SAFE_OUTPUTS_API_KEY}" - } - } - }, - "gateway": { - "port": $MCP_GATEWAY_PORT, - "domain": "${MCP_GATEWAY_DOMAIN}", - "apiKey": "${MCP_GATEWAY_API_KEY}", - "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" - } - } - GH_AW_MCP_CONFIG_EOF - - name: Generate workflow overview - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - with: - script: | - const { generateWorkflowOverview } = require('/opt/gh-aw/actions/generate_workflow_overview.cjs'); - await generateWorkflowOverview(core); - - name: Download prompt artifact - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 - with: - name: prompt - path: /tmp/gh-aw/aw-prompts - - name: Clean git credentials - run: bash /opt/gh-aw/actions/clean_git_credentials.sh - - name: Execute GitHub Copilot CLI - id: agentic_execution - # Copilot CLI tool arguments (sorted): - timeout-minutes: 60 - run: | - set -o pipefail - sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --allow-domains '*.githubusercontent.com,agents-md-generator.fastmcp.app,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,artifacts.elastic.co,azure.archive.ubuntu.com,cloud.elastic.co,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,ela.st,elastic.co,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,public-code-search.fastmcp.app,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.elastic.co' --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.20.2 --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 --model gpt-5.3-codex --allow-all-tools --allow-all-paths --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log - env: - COPILOT_AGENT_RUNNER_TYPE: STANDALONE - COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} - GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json - GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GITHUB_HEAD_REF: ${{ github.head_ref }} - GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - GITHUB_REF_NAME: ${{ github.ref_name }} - GITHUB_STEP_SUMMARY: ${{ env.GITHUB_STEP_SUMMARY }} - GITHUB_WORKSPACE: ${{ github.workspace }} - XDG_CONFIG_HOME: /home/runner - - name: Configure Git credentials - env: - REPO_NAME: ${{ github.repository }} - SERVER_URL: ${{ github.server_url }} - run: | - git config --global user.email "github-actions[bot]@users.noreply.github.com" - git config --global user.name "github-actions[bot]" - # Re-authenticate git with GitHub token - SERVER_URL_STRIPPED="${SERVER_URL#https://}" - git remote set-url origin "https://x-access-token:${{ github.token }}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" - echo "Git configured with standard GitHub Actions identity" - - name: Copy Copilot session state files to logs - if: always() - continue-on-error: true - run: | - # Copy Copilot session state files to logs folder for artifact collection - # This ensures they are in /tmp/gh-aw/ where secret redaction can scan them - SESSION_STATE_DIR="$HOME/.copilot/session-state" - LOGS_DIR="/tmp/gh-aw/sandbox/agent/logs" - - if [ -d "$SESSION_STATE_DIR" ]; then - echo "Copying Copilot session state files from $SESSION_STATE_DIR to $LOGS_DIR" - mkdir -p "$LOGS_DIR" - cp -v "$SESSION_STATE_DIR"/*.jsonl "$LOGS_DIR/" 2>/dev/null || true - echo "Session state files copied successfully" - else - echo "No session-state directory found at $SESSION_STATE_DIR" - fi - - name: Stop MCP Gateway - if: always() - continue-on-error: true - env: - MCP_GATEWAY_PORT: ${{ steps.start-mcp-gateway.outputs.gateway-port }} - MCP_GATEWAY_API_KEY: ${{ steps.start-mcp-gateway.outputs.gateway-api-key }} - GATEWAY_PID: ${{ steps.start-mcp-gateway.outputs.gateway-pid }} - run: | - bash /opt/gh-aw/actions/stop_mcp_gateway.sh "$GATEWAY_PID" - - name: Redact secrets in logs - if: always() - 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/redact_secrets.cjs'); - await main(); - env: - GH_AW_SECRET_NAMES: 'COPILOT_GITHUB_TOKEN,GH_AW_GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,GITHUB_TOKEN' - SECRET_COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} - SECRET_GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} - SECRET_GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} - SECRET_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Upload Safe Outputs - if: always() - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 - with: - name: safe-output - path: ${{ env.GH_AW_SAFE_OUTPUTS }} - if-no-files-found: warn - - name: Ingest agent output - id: collect_output - if: always() - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,agents-md-generator.fastmcp.app,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,artifacts.elastic.co,azure.archive.ubuntu.com,cloud.elastic.co,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,ela.st,elastic.co,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,public-code-search.fastmcp.app,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.elastic.co" - GITHUB_SERVER_URL: ${{ github.server_url }} - GITHUB_API_URL: ${{ github.api_url }} - 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/collect_ndjson_output.cjs'); - await main(); - - name: Upload sanitized agent output - if: always() && env.GH_AW_AGENT_OUTPUT - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 - with: - name: agent-output - path: ${{ env.GH_AW_AGENT_OUTPUT }} - if-no-files-found: warn - - name: Upload engine output files - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 - with: - name: agent_outputs - path: | - /tmp/gh-aw/sandbox/agent/logs/ - /tmp/gh-aw/redacted-urls.log - if-no-files-found: ignore - - name: Parse agent logs for step summary - if: always() - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_AGENT_OUTPUT: /tmp/gh-aw/sandbox/agent/logs/ - 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/parse_copilot_log.cjs'); - await main(); - - name: Parse MCP Gateway logs for step summary - if: always() - 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/parse_mcp_gateway_log.cjs'); - await main(); - - name: Print firewall logs - if: always() - continue-on-error: true - env: - AWF_LOGS_DIR: /tmp/gh-aw/sandbox/firewall/logs - run: | - # Fix permissions on firewall logs so they can be uploaded as artifacts - # AWF runs with sudo, creating files owned by root - sudo chmod -R a+r /tmp/gh-aw/sandbox/firewall/logs 2>/dev/null || true - # Only run awf logs summary if awf command exists (it may not be installed if workflow failed before install step) - if command -v awf &> /dev/null; then - awf logs summary | tee -a "$GITHUB_STEP_SUMMARY" - else - echo 'AWF binary not installed, skipping firewall log summary' - fi - - name: Upload agent artifacts - if: always() - continue-on-error: true - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 - with: - name: agent-artifacts - path: | - /tmp/gh-aw/aw-prompts/prompt.txt - /tmp/gh-aw/aw_info.json - /tmp/gh-aw/mcp-logs/ - /tmp/gh-aw/sandbox/firewall/logs/ - /tmp/gh-aw/agent-stdio.log - /tmp/gh-aw/agent/ - if-no-files-found: ignore - - conclusion: - needs: - - activation - - agent - - detection - - safe_outputs - if: (always()) && (needs.agent.result != 'skipped') - runs-on: ubuntu-slim - permissions: - contents: read - issues: write - outputs: - noop_message: ${{ steps.noop.outputs.noop_message }} - tools_reported: ${{ steps.missing_tool.outputs.tools_reported }} - total_count: ${{ steps.missing_tool.outputs.total_count }} - steps: - - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 - with: - destination: /opt/gh-aw/actions - - name: Download agent output artifact - continue-on-error: true - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 - with: - name: agent-output - path: /tmp/gh-aw/safeoutputs/ - - name: Setup agent output environment variable - run: | - mkdir -p /tmp/gh-aw/safeoutputs/ - find "/tmp/gh-aw/safeoutputs/" -type f -print - echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/safeoutputs/agent_output.json" >> "$GITHUB_ENV" - - name: Process No-Op Messages - id: noop - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_NOOP_MAX: 1 - GH_AW_WORKFLOW_NAME: "PR CI Detective" - with: - github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - script: | - const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io); - const { main } = require('/opt/gh-aw/actions/noop.cjs'); - await main(); - - name: Record Missing Tool - id: missing_tool - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_WORKFLOW_NAME: "PR CI Detective" - with: - github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - script: | - const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io); - const { main } = require('/opt/gh-aw/actions/missing_tool.cjs'); - await main(); - - name: Handle Agent Failure - id: handle_agent_failure - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_WORKFLOW_NAME: "PR CI Detective" - 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: "gh-aw-pr-ci-detective" - GH_AW_SECRET_VERIFICATION_RESULT: ${{ needs.agent.outputs.secret_verification_result }} - GH_AW_CHECKOUT_PR_SUCCESS: ${{ needs.agent.outputs.checkout_pr_success }} - GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\"}" - GH_AW_GROUP_REPORTS: "false" - with: - github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - script: | - const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io); - const { main } = require('/opt/gh-aw/actions/handle_agent_failure.cjs'); - await main(); - - name: Handle No-Op Message - id: handle_noop_message - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_WORKFLOW_NAME: "PR CI Detective" - 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 }} - GH_AW_NOOP_REPORT_AS_ISSUE: "true" - with: - github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - script: | - const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io); - const { main } = require('/opt/gh-aw/actions/handle_noop_message.cjs'); - await main(); - - detection: - needs: agent - if: needs.agent.outputs.output_types != '' || needs.agent.outputs.has_patch == 'true' - runs-on: ubuntu-latest - permissions: {} - concurrency: - group: "gh-aw-copilot-${{ github.workflow }}" - timeout-minutes: 10 - outputs: - success: ${{ steps.parse_results.outputs.success }} - steps: - - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 - with: - destination: /opt/gh-aw/actions - - name: Download agent artifacts - continue-on-error: true - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 - with: - name: agent-artifacts - path: /tmp/gh-aw/threat-detection/ - - name: Download agent output artifact - continue-on-error: true - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 - with: - name: agent-output - path: /tmp/gh-aw/threat-detection/ - - name: Print agent output types - env: - AGENT_OUTPUT_TYPES: ${{ needs.agent.outputs.output_types }} - run: | - echo "Agent output-types: $AGENT_OUTPUT_TYPES" - - name: Setup threat detection - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - WORKFLOW_NAME: "PR CI Detective" - WORKFLOW_DESCRIPTION: "Analyze failed PR checks and report findings" - HAS_PATCH: ${{ needs.agent.outputs.has_patch }} - 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/setup_threat_detection.cjs'); - await main(); - - name: Ensure threat-detection directory and log - run: | - mkdir -p /tmp/gh-aw/threat-detection - touch /tmp/gh-aw/threat-detection/detection.log - - name: Validate COPILOT_GITHUB_TOKEN secret - id: validate-secret - run: /opt/gh-aw/actions/validate_multi_secret.sh COPILOT_GITHUB_TOKEN 'GitHub Copilot CLI' https://github.github.com/gh-aw/reference/engines/#github-copilot-default - env: - COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} - - name: Install GitHub Copilot CLI - run: /opt/gh-aw/actions/install_copilot_cli.sh 0.0.412 - - name: Execute GitHub Copilot CLI - id: agentic_execution - # Copilot CLI tool arguments (sorted): - # --allow-tool shell(cat) - # --allow-tool shell(grep) - # --allow-tool shell(head) - # --allow-tool shell(jq) - # --allow-tool shell(ls) - # --allow-tool shell(tail) - # --allow-tool shell(wc) - timeout-minutes: 20 - run: | - set -o pipefail - COPILOT_CLI_INSTRUCTION="$(cat /tmp/gh-aw/aw-prompts/prompt.txt)" - mkdir -p /tmp/ - mkdir -p /tmp/gh-aw/ - mkdir -p /tmp/gh-aw/agent/ - mkdir -p /tmp/gh-aw/sandbox/agent/logs/ - copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --model gpt-5.3-codex --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log - env: - COPILOT_AGENT_RUNNER_TYPE: STANDALONE - COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} - GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - GITHUB_HEAD_REF: ${{ github.head_ref }} - GITHUB_REF_NAME: ${{ github.ref_name }} - GITHUB_STEP_SUMMARY: ${{ env.GITHUB_STEP_SUMMARY }} - GITHUB_WORKSPACE: ${{ github.workspace }} - XDG_CONFIG_HOME: /home/runner - - name: Parse threat detection results - id: parse_results - 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/parse_threat_detection_results.cjs'); - await main(); - - name: Upload threat detection log - if: always() - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 - with: - name: threat-detection.log - path: /tmp/gh-aw/threat-detection/detection.log - if-no-files-found: ignore - - pre_activation: - runs-on: ubuntu-slim - outputs: - activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} - steps: - - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 - with: - destination: /opt/gh-aw/actions - - name: Check team membership for workflow - id: check_membership - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_REQUIRED_ROLES: admin,maintainer,write - GH_AW_ALLOWED_BOTS: ${{ inputs.allowed-bot-users }} - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - 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_membership.cjs'); - await main(); - - safe_outputs: - needs: - - agent - - detection - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (needs.detection.outputs.success == 'true') - runs-on: ubuntu-slim - permissions: - contents: read - issues: write - timeout-minutes: 15 - env: - GH_AW_ENGINE_ID: "copilot" - GH_AW_ENGINE_MODEL: "gpt-5.3-codex" - GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\"}" - GH_AW_WORKFLOW_ID: "gh-aw-pr-ci-detective" - GH_AW_WORKFLOW_NAME: "PR CI Detective" - outputs: - create_discussion_error_count: ${{ steps.process_safe_outputs.outputs.create_discussion_error_count }} - create_discussion_errors: ${{ steps.process_safe_outputs.outputs.create_discussion_errors }} - process_safe_outputs_processed_count: ${{ steps.process_safe_outputs.outputs.processed_count }} - process_safe_outputs_temporary_id_map: ${{ steps.process_safe_outputs.outputs.temporary_id_map }} - steps: - - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 - with: - destination: /opt/gh-aw/actions - - name: Download agent output artifact - continue-on-error: true - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 - with: - name: agent-output - path: /tmp/gh-aw/safeoutputs/ - - name: Setup agent output environment variable - run: | - mkdir -p /tmp/gh-aw/safeoutputs/ - find "/tmp/gh-aw/safeoutputs/" -type f -print - echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/safeoutputs/agent_output.json" >> "$GITHUB_ENV" - - name: Process Safe Outputs - id: process_safe_outputs - 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},\"missing_data\":{},\"missing_tool\":{}}" - with: - github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - script: | - const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io); - const { main } = require('/opt/gh-aw/actions/safe_output_handler_manager.cjs'); - await main(); - - name: Upload safe output items manifest - if: always() - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 - with: - name: safe-output-items - path: /tmp/safe-output-items.jsonl - if-no-files-found: warn - diff --git a/.github/workflows/gh-aw-pr-ci-detective.lock.yml b/.github/workflows/gh-aw-pr-ci-detective.lock.yml new file mode 120000 index 00000000..606e42b8 --- /dev/null +++ b/.github/workflows/gh-aw-pr-ci-detective.lock.yml @@ -0,0 +1 @@ +gh-aw-pr-actions-detective.lock.yml \ No newline at end of file diff --git a/.github/workflows/gh-aw-pr-review.lock.yml b/.github/workflows/gh-aw-pr-review.lock.yml index 0722cc37..71fe1936 100644 --- a/.github/workflows/gh-aw-pr-review.lock.yml +++ b/.github/workflows/gh-aw-pr-review.lock.yml @@ -36,7 +36,9 @@ # - gh-aw-fragments/safe-output-review-comment.md # - gh-aw-fragments/safe-output-submit-review.md # -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"acd461b0089ef5c9beb4e8a04c8b222617f91b91bb662d57c578d723a15a3ec2"} +# inlined-imports: true +# +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"460f3a2c367e1e10e8572c37fe53c27f9386073e3df4cd327b20a50affc7259f"} name: "PR Review" "on": @@ -73,6 +75,11 @@ name: "PR Review" description: "Minimum severity for inline comments: critical, high, medium, low, or nitpick. Issues below this threshold go in a collapsible section of the review body instead." required: false type: string + model: + default: gpt-5.3-codex + description: AI model to use + required: false + type: string setup-commands: default: "" description: Shell commands to run before the agent starts (dependency install, build, etc.) @@ -102,7 +109,7 @@ jobs: comment_repo: "" steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Validate context variables @@ -182,6 +189,29 @@ jobs: **Critical**: Tool calls write structured data that downstream jobs process. Without tool calls, follow-up actions will be skipped. **Note**: If you made no other safe output tool calls during this workflow execution, call the "noop" tool to provide a status message indicating completion or that no actions were needed. + + --- + + ## Creating a Pull Request Review Comment, Submitting a Pull Request Review, Reporting Missing Tools or Functionality, Reporting Missing Data + + **IMPORTANT**: To perform the actions listed above, use the **safeoutputs** tools. Do NOT use `gh`, do NOT call the GitHub API directly. You do not have write access to the GitHub repository. + + **Creating a Pull Request Review Comment** + + To create a pull request review comment, use the create_pull_request_review_comment tool from safeoutputs. + + **Submitting a Pull Request Review** + + To submit a pull request review (APPROVE, REQUEST_CHANGES, or COMMENT), use the submit_pull_request_review tool from safeoutputs. + + **Reporting Missing Tools or Functionality** + + To report a missing tool or capability, use the missing_tool tool from safeoutputs. + + **Reporting Missing Data** + + To report missing data required to achieve a goal, use the missing_data tool from safeoutputs. + @@ -643,7 +673,7 @@ jobs: secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Checkout repository @@ -737,7 +767,7 @@ jobs: const awInfo = { engine_id: "copilot", engine_name: "GitHub Copilot CLI", - model: "gpt-5.3-codex", + model: "${{ inputs.model }}", version: "", agent_version: "0.0.412", workflow_name: "PR Review", @@ -959,6 +989,10 @@ jobs: "required": true, "type": "string" }, + "repo": { + "type": "string", + "maxLength": 256 + }, "side": { "type": "string", "enum": [ @@ -972,6 +1006,31 @@ jobs: }, "customValidation": "startLineLessOrEqualLine" }, + "missing_data": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "context": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "data_type": { + "type": "string", + "sanitize": true, + "maxLength": 128 + }, + "reason": { + "type": "string", + "sanitize": true, + "maxLength": 256 + } + } + }, "missing_tool": { "defaultMax": 20, "fields": { @@ -1151,10 +1210,11 @@ jobs: run: | set -o pipefail sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --allow-domains '*.githubusercontent.com,*.jsr.io,*.pythonhosted.org,*.rvm.io,agents-md-generator.fastmcp.app,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.rubygems.org,api.snapcraft.io,archive.ubuntu.com,artifacts.elastic.co,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,bun.sh,bundler.rubygems.org,cache.ruby-lang.org,cdn.jsdelivr.net,cloud.elastic.co,codeload.github.com,conda.anaconda.org,conda.binstar.org,crates.io,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,deb.nodesource.com,deno.land,ela.st,elastic.co,esm.sh,files.pythonhosted.org,gems.rubyforge.org,gems.rubyonrails.org,get.pnpm.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,host.docker.internal,index.crates.io,index.rubygems.org,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,lfs.github.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,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,pip.pypa.io,pkg.go.dev,ppa.launchpad.net,proxy.golang.org,public-code-search.fastmcp.app,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.bower.io,registry.npmjs.com,registry.npmjs.org,registry.yarnpkg.com,repo.anaconda.com,repo.continuum.io,repo.yarnpkg.com,rubygems.org,rubygems.pkg.github.com,s.symcb.com,s.symcd.com,security.ubuntu.com,skimdb.npmjs.com,static.crates.io,storage.googleapis.com,sum.golang.org,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.elastic.co,www.npmjs.com,www.npmjs.org,yarnpkg.com' --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.20.2 --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 --model gpt-5.3-codex --allow-all-tools --allow-all-paths --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log + -- /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 --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} @@ -1320,7 +1380,7 @@ jobs: total_count: ${{ steps.missing_tool.outputs.total_count }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent output artifact @@ -1411,7 +1471,7 @@ jobs: success: ${{ steps.parse_results.outputs.success }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent artifacts @@ -1472,10 +1532,11 @@ jobs: mkdir -p /tmp/gh-aw/ mkdir -p /tmp/gh-aw/agent/ mkdir -p /tmp/gh-aw/sandbox/agent/logs/ - copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --model gpt-5.3-codex --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log + copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_REF_NAME: ${{ github.ref_name }} @@ -1505,7 +1566,7 @@ jobs: activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Check team membership for workflow @@ -1534,7 +1595,7 @@ jobs: timeout-minutes: 15 env: GH_AW_ENGINE_ID: "copilot" - GH_AW_ENGINE_MODEL: "gpt-5.3-codex" + GH_AW_ENGINE_MODEL: "${{ inputs.model }}" GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\"}" GH_AW_WORKFLOW_ID: "gh-aw-pr-review" GH_AW_WORKFLOW_NAME: "PR Review" @@ -1545,7 +1606,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@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent output artifact diff --git a/.github/workflows/gh-aw-pr-review.md b/.github/workflows/gh-aw-pr-review.md index e755b8ee..b3e88595 100644 --- a/.github/workflows/gh-aw-pr-review.md +++ b/.github/workflows/gh-aw-pr-review.md @@ -1,4 +1,5 @@ --- +inlined-imports: true name: "PR Review" description: "AI code review with inline comments on pull requests" imports: @@ -14,12 +15,17 @@ imports: - gh-aw-fragments/safe-output-submit-review.md engine: id: copilot - model: gpt-5.3-codex + model: ${{ inputs.model }} concurrency: group: "gh-aw-copilot-pr-review-${{ github.event.pull_request.number }}" on: workflow_call: inputs: + model: + description: "AI model to use" + type: string + required: false + default: "gpt-5.3-codex" additional-instructions: description: "Repo-specific instructions appended to the agent prompt" type: string diff --git a/.github/workflows/gh-aw-project-summary.lock.yml b/.github/workflows/gh-aw-project-summary.lock.yml index 6ed13f62..3291954f 100644 --- a/.github/workflows/gh-aw-project-summary.lock.yml +++ b/.github/workflows/gh-aw-project-summary.lock.yml @@ -33,9 +33,11 @@ # - gh-aw-fragments/rigor.md # - gh-aw-fragments/runtime-setup.md # - gh-aw-fragments/safe-output-create-issue.md -# - gh-aw-fragments/scheduled-report.md +# - gh-aw-fragments/scheduled-audit.md # -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"40abe98423339c8528d909aaec65d6dea2f1b3203bdb4ca675386d3a6d9b5ca0"} +# inlined-imports: true +# +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"1887b29fb6b85d26f97ce732baabc822303689e15fd3242b5989d8db3720040b"} name: "Project Summary" "on": @@ -62,6 +64,11 @@ name: "Project Summary" description: Footer appended to all agent comments and reviews required: false type: string + model: + default: gpt-5.3-codex + description: AI model to use + required: false + type: string setup-commands: default: "" description: Shell commands to run before the agent starts (dependency install, build, etc.) @@ -91,7 +98,7 @@ jobs: comment_repo: "" steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Validate context variables @@ -168,6 +175,25 @@ jobs: **Critical**: Tool calls write structured data that downstream jobs process. Without tool calls, follow-up actions will be skipped. **Note**: If you made no other safe output tool calls during this workflow execution, call the "noop" tool to provide a status message indicating completion or that no actions were needed. + + --- + + ## Creating an Issue, Reporting Missing Tools or Functionality, Reporting Missing Data + + **IMPORTANT**: To perform the actions listed above, use the **safeoutputs** tools. Do NOT use `gh`, do NOT call the GitHub API directly. You do not have write access to the GitHub repository. + + **Creating an Issue** + + To create an issue, use the create_issue tool from safeoutputs. + + **Reporting Missing Tools or Functionality** + + To report a missing tool or capability, use the missing_tool tool from safeoutputs. + + **Reporting Missing Data** + + To report missing data required to achieve a goal, use the missing_data tool from safeoutputs. + @@ -288,9 +314,7 @@ jobs: - **Mentions**: `@mentions` in the body are neutralized (backticked) by default. GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - # Scheduled Report Agent - - You are a report agent for __GH_AW_GITHUB_REPOSITORY__. You run on a schedule to investigate the repository and file an issue when something needs attention. Your specific assignment is described in the **Report Assignment** section below. + You are an agent for __GH_AW_GITHUB_REPOSITORY__. You run on a schedule to investigate the repository and file an issue when something needs attention. Your specific assignment is described in the **Report Assignment** section below. ## Context @@ -354,7 +378,7 @@ jobs: - Make suggested actions concrete enough to act on without re-investigating - If a finding is ambiguous, it does not pass the quality gate — drop it - ## Report Assignment + **Report Assignment:** GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" @@ -515,7 +539,7 @@ jobs: secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Checkout repository @@ -615,7 +639,7 @@ jobs: const awInfo = { engine_id: "copilot", engine_name: "GitHub Copilot CLI", - model: "gpt-5.3-codex", + model: "${{ inputs.model }}", version: "", agent_version: "0.0.412", workflow_name: "Project Summary", @@ -826,6 +850,31 @@ jobs: } } }, + "missing_data": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "context": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "data_type": { + "type": "string", + "sanitize": true, + "maxLength": 128 + }, + "reason": { + "type": "string", + "sanitize": true, + "maxLength": 256 + } + } + }, "missing_tool": { "defaultMax": 20, "fields": { @@ -987,10 +1036,11 @@ jobs: run: | set -o pipefail sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --allow-domains '*.githubusercontent.com,*.jsr.io,*.pythonhosted.org,*.rvm.io,agents-md-generator.fastmcp.app,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.rubygems.org,api.snapcraft.io,archive.ubuntu.com,artifacts.elastic.co,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,bun.sh,bundler.rubygems.org,cache.ruby-lang.org,cdn.jsdelivr.net,cloud.elastic.co,codeload.github.com,conda.anaconda.org,conda.binstar.org,crates.io,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,deb.nodesource.com,deno.land,ela.st,elastic.co,esm.sh,files.pythonhosted.org,gems.rubyforge.org,gems.rubyonrails.org,get.pnpm.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,host.docker.internal,index.crates.io,index.rubygems.org,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,lfs.github.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,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,pip.pypa.io,pkg.go.dev,ppa.launchpad.net,proxy.golang.org,public-code-search.fastmcp.app,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.bower.io,registry.npmjs.com,registry.npmjs.org,registry.yarnpkg.com,repo.anaconda.com,repo.continuum.io,repo.yarnpkg.com,rubygems.org,rubygems.pkg.github.com,s.symcb.com,s.symcd.com,security.ubuntu.com,skimdb.npmjs.com,static.crates.io,storage.googleapis.com,sum.golang.org,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.elastic.co,www.npmjs.com,www.npmjs.org,yarnpkg.com' --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.20.2 --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 --model gpt-5.3-codex --allow-all-tools --allow-all-paths --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log + -- /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 --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} @@ -1156,7 +1206,7 @@ jobs: total_count: ${{ steps.missing_tool.outputs.total_count }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent output artifact @@ -1247,7 +1297,7 @@ jobs: success: ${{ steps.parse_results.outputs.success }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent artifacts @@ -1308,10 +1358,11 @@ jobs: mkdir -p /tmp/gh-aw/ mkdir -p /tmp/gh-aw/agent/ mkdir -p /tmp/gh-aw/sandbox/agent/logs/ - copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --model gpt-5.3-codex --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log + copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_REF_NAME: ${{ github.ref_name }} @@ -1341,7 +1392,7 @@ jobs: activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Check team membership for workflow @@ -1370,7 +1421,7 @@ jobs: timeout-minutes: 15 env: GH_AW_ENGINE_ID: "copilot" - GH_AW_ENGINE_MODEL: "gpt-5.3-codex" + GH_AW_ENGINE_MODEL: "${{ inputs.model }}" GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\"}" GH_AW_WORKFLOW_ID: "gh-aw-project-summary" GH_AW_WORKFLOW_NAME: "Project Summary" @@ -1381,7 +1432,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@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent output artifact diff --git a/.github/workflows/gh-aw-project-summary.md b/.github/workflows/gh-aw-project-summary.md index 9d307040..689f99d7 100644 --- a/.github/workflows/gh-aw-project-summary.md +++ b/.github/workflows/gh-aw-project-summary.md @@ -1,4 +1,5 @@ --- +inlined-imports: true name: "Project Summary" description: "Create periodic project summary issues covering recent activity and priorities" imports: @@ -10,13 +11,18 @@ imports: - gh-aw-fragments/mcp-pagination.md - gh-aw-fragments/messages-footer.md - gh-aw-fragments/safe-output-create-issue.md - - gh-aw-fragments/scheduled-report.md + - gh-aw-fragments/scheduled-audit.md engine: id: copilot - model: gpt-5.3-codex + model: ${{ inputs.model }} on: workflow_call: inputs: + model: + description: "AI model to use" + type: string + required: false + default: "gpt-5.3-codex" additional-instructions: description: "Repo-specific instructions appended to the agent prompt" type: string diff --git a/.github/workflows/gh-aw-release-update.lock.yml b/.github/workflows/gh-aw-release-update.lock.yml index 77fe52d7..6c298fe7 100644 --- a/.github/workflows/gh-aw-release-update.lock.yml +++ b/.github/workflows/gh-aw-release-update.lock.yml @@ -33,7 +33,9 @@ # - gh-aw-fragments/runtime-setup.md # - gh-aw-fragments/safe-output-create-pr.md # -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"c6b977b399ce114f6cc7a6d07f42349057d5be5055f591a1bf0cc58e583fe87a"} +# inlined-imports: true +# +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"997287a3ecffdf06b7320ba081d4a5d6eca7a2490106dd11cee7284b2960ff5b"} name: "Release Update Check" "on": @@ -60,6 +62,11 @@ name: "Release Update Check" description: Footer appended to all agent comments and reviews required: false type: string + model: + default: gpt-5.3-codex + description: AI model to use + required: false + type: string setup-commands: default: "" description: Shell commands to run before the agent starts (dependency install, build, etc.) @@ -89,7 +96,7 @@ jobs: comment_repo: "" steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Validate context variables @@ -166,6 +173,30 @@ jobs: **Critical**: Tool calls write structured data that downstream jobs process. Without tool calls, follow-up actions will be skipped. **Note**: If you made no other safe output tool calls during this workflow execution, call the "noop" tool to provide a status message indicating completion or that no actions were needed. + + --- + + ## Creating a Pull Request, Reporting Missing Tools or Functionality, Reporting Missing Data + + **IMPORTANT**: To perform the actions listed above, use the **safeoutputs** tools. Do NOT use `gh`, do NOT call the GitHub API directly. You do not have write access to the GitHub repository. + + **Creating a Pull Request** + + To create a pull request: + 1. Make any file changes directly in the working directory. + 2. If you haven't done so already, create a local branch using an appropriate unique name. + 3. Add and commit your changes to the branch. Be careful to add exactly the files you intend, and check there are no extra files left un-added. Verify you haven't deleted or changed any files you didn't intend to. + 4. Do not push your changes. That will be done by the tool. + 5. Create the pull request with the create_pull_request tool from safeoutputs. + + **Reporting Missing Tools or Functionality** + + To report a missing tool or capability, use the missing_tool tool from safeoutputs. + + **Reporting Missing Data** + + To report missing data required to achieve a goal, use the missing_data tool from safeoutputs. + @@ -433,7 +464,7 @@ jobs: secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Checkout repository @@ -527,7 +558,7 @@ jobs: const awInfo = { engine_id: "copilot", engine_name: "GitHub Copilot CLI", - model: "gpt-5.2-codex", + model: "${{ inputs.model }}", version: "", agent_version: "0.0.412", workflow_name: "Release Update Check", @@ -587,7 +618,7 @@ jobs: 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' - {"create_pull_request":{},"missing_data":{},"missing_tool":{},"noop":{"max":1}} + {"create_pull_request":{"max":1},"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' [ @@ -604,6 +635,10 @@ jobs: "description": "Source branch name containing the changes. If omitted, uses the current working branch.", "type": "string" }, + "draft": { + "description": "Whether to create the PR as a draft. Draft PRs cannot be merged until marked as ready for review. Use mark_pull_request_as_ready_for_review to convert a draft PR. Default: true.", + "type": "boolean" + }, "labels": { "description": "Labels to categorize the PR (e.g., 'enhancement', 'bugfix'). Labels must exist in the repository.", "items": { @@ -712,12 +747,19 @@ jobs: "sanitize": true, "maxLength": 256 }, + "draft": { + "type": "boolean" + }, "labels": { "type": "array", "itemType": "string", "itemSanitize": true, "itemMaxLength": 128 }, + "repo": { + "type": "string", + "maxLength": 256 + }, "title": { "required": true, "type": "string", @@ -726,6 +768,31 @@ jobs: } } }, + "missing_data": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "context": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "data_type": { + "type": "string", + "sanitize": true, + "maxLength": 128 + }, + "reason": { + "type": "string", + "sanitize": true, + "maxLength": 256 + } + } + }, "missing_tool": { "defaultMax": 20, "fields": { @@ -984,10 +1051,11 @@ jobs: run: | set -o pipefail sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --allow-domains '*.githubusercontent.com,agents-md-generator.fastmcp.app,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,artifacts.elastic.co,azure.archive.ubuntu.com,cloud.elastic.co,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,ela.st,elastic.co,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,public-code-search.fastmcp.app,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.elastic.co' --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.20.2 --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 --model gpt-5.2-codex --allow-all-tools --allow-all-paths --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log + -- /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 --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} @@ -1144,7 +1212,7 @@ jobs: /tmp/gh-aw/sandbox/firewall/logs/ /tmp/gh-aw/agent-stdio.log /tmp/gh-aw/agent/ - /tmp/gh-aw/aw.patch + /tmp/gh-aw/aw-*.patch if-no-files-found: ignore conclusion: @@ -1165,7 +1233,7 @@ jobs: total_count: ${{ steps.missing_tool.outputs.total_count }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent output artifact @@ -1270,7 +1338,7 @@ jobs: success: ${{ steps.parse_results.outputs.success }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent artifacts @@ -1331,10 +1399,11 @@ jobs: mkdir -p /tmp/gh-aw/ mkdir -p /tmp/gh-aw/agent/ mkdir -p /tmp/gh-aw/sandbox/agent/logs/ - copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --model gpt-5.2-codex --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log + copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_REF_NAME: ${{ github.ref_name }} @@ -1364,7 +1433,7 @@ jobs: activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Check team membership for workflow @@ -1395,7 +1464,7 @@ jobs: timeout-minutes: 15 env: GH_AW_ENGINE_ID: "copilot" - GH_AW_ENGINE_MODEL: "gpt-5.2-codex" + GH_AW_ENGINE_MODEL: "${{ inputs.model }}" GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\"}" GH_AW_WORKFLOW_ID: "gh-aw-release-update" GH_AW_WORKFLOW_NAME: "Release Update Check" @@ -1406,7 +1475,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@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent output artifact @@ -1430,7 +1499,7 @@ jobs: if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: - ref: ${{ github.ref_name }} + ref: ${{ github.base_ref || github.ref_name }} token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} persist-credentials: false fetch-depth: 1 @@ -1452,7 +1521,7 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_pull_request\":{\"base_branch\":\"${{ github.ref_name }}\",\"max\":1,\"max_patch_size\":1024},\"missing_data\":{},\"missing_tool\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_pull_request\":{\"base_branch\":\"${{ github.base_ref || github.ref_name }}\",\"max\":1,\"max_patch_size\":1024},\"missing_data\":{},\"missing_tool\":{}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/gh-aw-release-update.md b/.github/workflows/gh-aw-release-update.md index 0090049e..1fbc66ed 100644 --- a/.github/workflows/gh-aw-release-update.md +++ b/.github/workflows/gh-aw-release-update.md @@ -1,4 +1,5 @@ --- +inlined-imports: true description: "Check for new ai-github-actions releases and open PRs to update pinned workflow SHAs" imports: - gh-aw-fragments/elastic-tools.md @@ -10,10 +11,15 @@ imports: - gh-aw-fragments/safe-output-create-pr.md engine: id: copilot - model: gpt-5.2-codex + model: ${{ inputs.model }} on: workflow_call: inputs: + model: + description: "AI model to use" + type: string + required: false + default: "gpt-5.3-codex" additional-instructions: description: "Repo-specific instructions appended to the agent prompt" type: string diff --git a/.github/workflows/gh-aw-scheduled-audit.lock.yml b/.github/workflows/gh-aw-scheduled-audit.lock.yml new file mode 100644 index 00000000..a71a2a3a --- /dev/null +++ b/.github/workflows/gh-aw-scheduled-audit.lock.yml @@ -0,0 +1,1412 @@ +# +# ___ _ _ +# / _ \ | | (_) +# | |_| | __ _ ___ _ __ | |_ _ ___ +# | _ |/ _` |/ _ \ '_ \| __| |/ __| +# | | | | (_| | __/ | | | |_| | (__ +# \_| |_/\__, |\___|_| |_|\__|_|\___| +# __/ | +# _ _ |___/ +# | | | | / _| | +# | | | | ___ _ __ _ __| |_| | _____ ____ +# | |/\| |/ _ \ '__| |/ /| _| |/ _ \ \ /\ / / ___| +# \ /\ / (_) | | | | ( | | | | (_) \ V V /\__ \ +# \/ \/ \___/|_| |_|\_\|_| |_|\___/ \_/\_/ |___/ +# +# This file was automatically generated by gh-aw. DO NOT EDIT. +# +# To update this file, edit the corresponding .md file and run: +# gh aw compile +# Not all edits will cause changes to this file. +# +# For more information: https://github.github.com/gh-aw/introduction/overview/ +# +# Generic scheduled audit — investigate the repository and file an issue when something needs attention +# +# Resolved workflow manifest: +# Imports: +# - gh-aw-fragments/elastic-tools.md +# - gh-aw-fragments/formatting.md +# - gh-aw-fragments/mcp-pagination.md +# - gh-aw-fragments/messages-footer.md +# - gh-aw-fragments/rigor.md +# - gh-aw-fragments/runtime-setup.md +# - gh-aw-fragments/safe-output-create-issue.md +# - gh-aw-fragments/scheduled-audit.md +# +# inlined-imports: true +# +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"5407be51afed9319bcbdd8da718762d79b3ddb6c28bc2ed7edf261cd01714d58"} + +name: "Scheduled Audit" +"on": + # bots: # Bots processed as bot check in pre-activation job + # - ${{ inputs.allowed-bot-users }} # Bots processed as bot check in pre-activation job + # roles: # Roles processed as role check in pre-activation job + # - admin # Roles processed as role check in pre-activation job + # - maintainer # Roles processed as role check in pre-activation job + # - write # Roles processed as role check in pre-activation job + workflow_call: + inputs: + additional-instructions: + description: What the audit agent should investigate — appended as the Report Assignment + required: true + type: string + allowed-bot-users: + default: github-actions[bot] + description: Allowlisted bot actor usernames (comma-separated) + required: false + type: string + issue-label: + default: "" + description: Label to apply to created issues (must already exist in the target repo) + required: false + type: string + issue-title-prefix: + description: Title prefix for created issues, e.g. '[my-audit]' + required: true + type: string + messages-footer: + default: "" + description: Footer appended to all agent comments and reviews + required: false + type: string + model: + default: gpt-5.3-codex + description: AI model to use + required: false + type: string + setup-commands: + default: "" + description: Shell commands to run before the agent starts (dependency install, build, etc.) + required: false + type: string + secrets: + COPILOT_GITHUB_TOKEN: + required: true + +permissions: {} + +concurrency: + cancel-in-progress: true + group: scheduled-audit-${{ inputs.issue-title-prefix }} + +run-name: "Scheduled Audit" + +jobs: + activation: + needs: pre_activation + if: needs.pre_activation.outputs.activated == 'true' + runs-on: ubuntu-slim + permissions: + contents: read + outputs: + comment_id: "" + comment_repo: "" + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 + with: + destination: /opt/gh-aw/actions + - name: Validate context variables + 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/validate_context_variables.cjs'); + await main(); + - name: Checkout .github and .agents folders + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + sparse-checkout: | + .github + .agents + fetch-depth: 1 + persist-credentials: false + - name: Check workflow file timestamps + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_WORKFLOW_FILE: "gh-aw-scheduled-audit.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: Create prompt with built-in context + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} + GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} + GH_AW_EXPR_955E52F5: ${{ inputs.issue-label }} + GH_AW_GITHUB_ACTOR: ${{ github.actor }} + GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} + GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} + GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} + GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} + GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} + GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} + run: | + bash /opt/gh-aw/actions/create_prompt_first.sh + cat << 'GH_AW_PROMPT_EOF' > "$GH_AW_PROMPT" + + GH_AW_PROMPT_EOF + cat "/opt/gh-aw/prompts/xpia.md" >> "$GH_AW_PROMPT" + cat "/opt/gh-aw/prompts/temp_folder_prompt.md" >> "$GH_AW_PROMPT" + cat "/opt/gh-aw/prompts/markdown.md" >> "$GH_AW_PROMPT" + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + + GitHub API Access Instructions + + The gh CLI is NOT authenticated. Do NOT use gh commands for GitHub operations. + + + To create or modify GitHub resources (issues, discussions, pull requests, etc.), you MUST call the appropriate safe output tool. Simply writing content will NOT work - the workflow requires actual tool calls. + + Temporary IDs: Some safe output tools support a temporary ID field (usually named temporary_id) so you can reference newly-created items elsewhere in the SAME agent output (for example, using #aw_abc1 in a later body). + + **IMPORTANT - temporary_id format rules:** + - If you DON'T need to reference the item later, OMIT the temporary_id field entirely (it will be auto-generated if needed) + - If you DO need cross-references/chaining, you MUST match this EXACT validation regex: /^aw_[A-Za-z0-9]{3,8}$/i + - Format: aw_ prefix followed by 3 to 8 alphanumeric characters (A-Z, a-z, 0-9, case-insensitive) + - Valid alphanumeric characters: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 + - INVALID examples: aw_ab (too short), aw_123456789 (too long), aw_test-id (contains hyphen), aw_id_123 (contains underscore) + - VALID examples: aw_abc, aw_abc1, aw_Test123, aw_A1B2C3D4, aw_12345678 + - To generate valid IDs: use 3-8 random alphanumeric characters or omit the field to let the system auto-generate + + Do NOT invent other aw_* formats — downstream steps will reject them with validation errors matching against /^aw_[A-Za-z0-9]{3,8}$/i. + + Discover available tools from the safeoutputs MCP server. + + **Critical**: Tool calls write structured data that downstream jobs process. Without tool calls, follow-up actions will be skipped. + + **Note**: If you made no other safe output tool calls during this workflow execution, call the "noop" tool to provide a status message indicating completion or that no actions were needed. + + --- + + ## Creating an Issue, Reporting Missing Tools or Functionality, Reporting Missing Data + + **IMPORTANT**: To perform the actions listed above, use the **safeoutputs** tools. Do NOT use `gh`, do NOT call the GitHub API directly. You do not have write access to the GitHub repository. + + **Creating an Issue** + + To create an issue, use the create_issue tool from safeoutputs. + + **Reporting Missing Tools or Functionality** + + To report a missing tool or capability, use the missing_tool tool from safeoutputs. + + **Reporting Missing Data** + + To report missing data required to achieve a goal, use the missing_data tool from safeoutputs. + + + + + The following GitHub context information is available for this workflow: + {{#if __GH_AW_GITHUB_ACTOR__ }} + - **actor**: __GH_AW_GITHUB_ACTOR__ + {{/if}} + {{#if __GH_AW_GITHUB_REPOSITORY__ }} + - **repository**: __GH_AW_GITHUB_REPOSITORY__ + {{/if}} + {{#if __GH_AW_GITHUB_WORKSPACE__ }} + - **workspace**: __GH_AW_GITHUB_WORKSPACE__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_ISSUE_NUMBER__ }} + - **issue-number**: #__GH_AW_GITHUB_EVENT_ISSUE_NUMBER__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__ }} + - **discussion-number**: #__GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__ }} + - **pull-request-number**: #__GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_COMMENT_ID__ }} + - **comment-id**: __GH_AW_GITHUB_EVENT_COMMENT_ID__ + {{/if}} + {{#if __GH_AW_GITHUB_RUN_ID__ }} + - **workflow-run-id**: __GH_AW_GITHUB_RUN_ID__ + {{/if}} + + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + ## MCP Servers + + - **`generate_agents_md`** — generates a summary of the repository's structure, conventions, and coding guidelines from AGENTS.md and related files. Call at the start of every workflow to get repo context. + - **`search_code`** — grep-style search across public GitHub repositories. Use for finding usage patterns in upstream libraries, reference implementations, or examples in open-source projects. This searches *public GitHub repos*, not the local codebase — if available you can use `grep` and file reading for local code. + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + ## Formatting Guidelines + + - Lead with the most important information — your first sentence should be the key takeaway + - Be concise and actionable — no filler or praise + - Use `
` and `` tags for long sections to keep responses scannable + - Wrap branch names and @-references in backticks to avoid pinging users + - Include code snippets with file paths and line numbers when referencing the codebase + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + ## Rigor + + **Silence is better than noise. A false positive wastes a human's time and erodes trust in every future report.** + + - If you claim something is missing or broken, show the exact evidence in the code — file path, line number, and what you observed. + - If a conclusion depends on assumptions you haven't confirmed, do not assert it. Verify first; if you cannot verify, do not report. + - "I don't know" is better than a wrong answer. `noop` is better than a speculative finding. + - It's worth the time to verify now versus guessing and forcing someone else to verify later. + - Before filing any issue or opening any PR, re-read your own output as a skeptical reviewer. Ask: "Would a senior engineer on this team find this useful, or would they close it immediately?" If the answer is "close," call `noop` instead. + - Only report findings you would confidently defend in a code review. If you feel the need to hedge with "might," "could," or "possibly," the finding is not ready to file. + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + ## MCP Pagination + + MCP tool responses have a **25,000 token limit**. When responses exceed this limit, the call fails and you must retry with pagination — wasting turns and tokens. Use proactive pagination to stay under the limit. + + ### Recommended `perPage` Values + + - **5-10**: For detailed items (PR diffs, files with patches, issues with comments) + - **20-30**: For medium-detail lists (commits, review comments, issue lists) + - **50-100**: For simple list operations (branches, labels, tags) + + ### Pagination Pattern + + When you need all results from a paginated API: + + 1. Fetch the first page with a conservative `perPage` value + 2. Process the results before fetching the next page + 3. Continue fetching pages until you receive fewer results than `perPage` (indicating the last page) + + ### Error Recovery + + If you see an error like: + - `MCP tool response exceeds maximum allowed tokens (25000)` + - `Response too large for tool [tool_name]` + + Retry the same call with a smaller `perPage` value (halve it). + + ### Tips + + - **Start small**: It's better to make multiple small requests than one that fails + - **Fetch incrementally**: Get an overview first, then details for specific items + - **Use filters**: Combine `perPage` with state, label, or date filters to reduce result size + - **Process as you go**: Don't accumulate all pages before acting — process each batch immediately + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + ## Message Footer + + A footer is automatically appended to all comments and reviews. Do not add your own footer or sign-off — the runtime handles this. + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + ## create-issue Limitations + + - **Title**: Max 128 characters. Sanitized (special characters escaped). + - **Labels**: Max 10 labels per issue. Each label max 64 characters. Labels containing only `-` are rejected. + - **Assignees**: Max 5 assignees per issue. + - **Body**: No strict character limit beyond GitHub's API limit (~65,536 characters), but fields over 16,000 tokens are written to a file reference instead of inlined. + - **Bot triggers**: References like `fixes #123` or `closes #456` in the body are neutralized to prevent unintended issue closures. + - **Mentions**: `@mentions` in the body are neutralized (backticked) by default. + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + You are an agent for __GH_AW_GITHUB_REPOSITORY__. You run on a schedule to investigate the repository and file an issue when something needs attention. Your specific assignment is described in the **Report Assignment** section below. + + ## Context + + - **Repository**: __GH_AW_GITHUB_REPOSITORY__ + + ## Constraints + + This workflow is for detection and reporting only. You can read files, search code, run commands, and read PR/issue details — but your only output is either a single issue or a noop. + + ## Process + + Follow these steps in order. + + ### Step 1: Gather Context + + 1. Call `generate_agents_md` to get the repository's coding guidelines and conventions. If this fails, continue without it. + 2. Follow the data gathering instructions in the **Report Assignment** section. + + ### Step 2: Analyze + + Follow the analysis instructions in the **Report Assignment** section to determine whether an issue should be filed. The Report Assignment defines: + - What data to gather and how + - What to look for + - What constitutes a finding worth reporting + - What to skip or ignore + + ### Step 3: Self-Review (Quality Gate) + + Before filing anything, critically evaluate every finding against these criteria: + + 1. **Evidence is concrete** — you can point to exact file paths, line numbers, commit SHAs, or command outputs. No "I believe" or "it seems." + 2. **Finding is actionable** — a maintainer reading the issue can act on it without re-investigating from scratch. + 3. **Finding is not already tracked** — you checked open issues and recent PRs for duplicates. + 4. **Finding is worth a human's time** — the issue is material enough that a maintainer would thank you for filing it, not close it as noise. + + If zero findings pass all four criteria, call `noop` with a brief reason and stop. **Noop is the expected outcome most days.** Filing nothing is a success when there is nothing worth filing. + + ### Step 4: Report + + If there are findings that pass the quality gate, call `create_issue` with a structured report. Use the issue format specified in the Report Assignment if one is provided, otherwise use this default format: + + **Issue title:** Brief summary of findings + + **Issue body:** + + > ## Findings + > + > ### 1. [Brief description] + > + > **Evidence:** [Links, references, or data supporting the finding] + > **Action needed:** [What should be done] + > + > ## Suggested Actions + > + > - [ ] [Actionable checkbox for each finding] + + **Guidelines:** + - Group related findings together + - Be specific about what needs to happen + - Include links and references where possible + - Make suggested actions concrete enough to act on without re-investigating + - If a finding is ambiguous, it does not pass the quality gate — drop it + + **Report Assignment:** + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + ### Labeling + + If `__GH_AW_EXPR_955E52F5__` is set and the label exists in the repository (check with `github-get_label`), include it in the `create_issue` call. Otherwise rely on the title prefix only. + + __GH_AW_EXPR_49B959F1__ + + GH_AW_PROMPT_EOF + - name: Interpolate variables and render templates + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} + GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} + GH_AW_EXPR_955E52F5: ${{ inputs.issue-label }} + 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/interpolate_prompt.cjs'); + await main(); + - name: Substitute placeholders + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} + GH_AW_EXPR_955E52F5: ${{ inputs.issue-label }} + GH_AW_GITHUB_ACTOR: ${{ github.actor }} + GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} + GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} + GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} + 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'); + setupGlobals(core, github, context, exec, io); + + const substitutePlaceholders = require('/opt/gh-aw/actions/substitute_placeholders.cjs'); + + // Call the substitution function + return await substitutePlaceholders({ + file: process.env.GH_AW_PROMPT, + substitutions: { + GH_AW_EXPR_49B959F1: process.env.GH_AW_EXPR_49B959F1, + GH_AW_EXPR_955E52F5: process.env.GH_AW_EXPR_955E52F5, + GH_AW_GITHUB_ACTOR: process.env.GH_AW_GITHUB_ACTOR, + GH_AW_GITHUB_EVENT_COMMENT_ID: process.env.GH_AW_GITHUB_EVENT_COMMENT_ID, + GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: process.env.GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER, + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: process.env.GH_AW_GITHUB_EVENT_ISSUE_NUMBER, + 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_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 + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + run: bash /opt/gh-aw/actions/validate_prompt_placeholders.sh + - name: Print prompt + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + run: bash /opt/gh-aw/actions/print_prompt_summary.sh + - name: Upload prompt artifact + if: success() + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: prompt + path: /tmp/gh-aw/aw-prompts/prompt.txt + retention-days: 1 + + agent: + needs: activation + runs-on: ubuntu-latest + permissions: + contents: read + issues: read + pull-requests: read + env: + DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} + GH_AW_ASSETS_ALLOWED_EXTS: "" + GH_AW_ASSETS_BRANCH: "" + GH_AW_ASSETS_MAX_SIZE_KB: 0 + GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs + 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: ghawscheduledaudit + outputs: + checkout_pr_success: ${{ steps.checkout-pr.outputs.checkout_pr_success || 'true' }} + has_patch: ${{ steps.collect_output.outputs.has_patch }} + model: ${{ steps.generate_aw_info.outputs.model }} + output: ${{ steps.collect_output.outputs.output }} + output_types: ${{ steps.collect_output.outputs.output_types }} + secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 + with: + destination: /opt/gh-aw/actions + - name: Checkout repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + - name: Create gh-aw temp directory + run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh + - if: hashFiles('go.mod') != '' + name: Setup Go + uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5 + with: + cache: true + go-version-file: go.mod + - if: hashFiles('.python-version') != '' + name: Setup Python + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 + with: + python-version-file: .python-version + - if: hashFiles('.node-version') != '' + name: Setup Node.js (.node-version) + uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6 + with: + node-version-file: .node-version + - if: hashFiles('.node-version') == '' && hashFiles('.nvmrc') != '' + name: Setup Node.js (.nvmrc) + uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6 + with: + node-version-file: .nvmrc + - if: hashFiles('.ruby-version') != '' + name: Setup Ruby + uses: ruby/setup-ruby@09a7688d3b55cf0e976497ff046b70949eeaccfd # v1 + with: + bundler-cache: true + ruby-version: .ruby-version + - id: setup-uv + if: hashFiles('pyproject.toml', 'uv.lock') != '' + name: Setup uv + uses: astral-sh/setup-uv@e58605a9b6da7c637471fab8847a5e5a6b8df081 # v5 + - env: + UV_PATH: ${{ steps.setup-uv.outputs.uv-path }} + WORKSPACE: ${{ github.workspace }} + if: hashFiles('pyproject.toml', 'uv.lock') != '' + name: Expose uv in workspace + run: |- + set -euo pipefail + install_dir="$WORKSPACE/.gh-aw-tools/bin" + mkdir -p "$install_dir" + cp "$UV_PATH" "$install_dir/uv" + chmod +x "$install_dir/uv" + echo "$install_dir" >> "$GITHUB_PATH" + shell: bash + - env: + SETUP_COMMANDS: ${{ inputs.setup-commands }} + if: ${{ inputs.setup-commands != '' }} + name: Repo-specific setup + run: eval "$SETUP_COMMANDS" + + - name: Configure Git credentials + env: + REPO_NAME: ${{ github.repository }} + SERVER_URL: ${{ github.server_url }} + run: | + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git config --global user.name "github-actions[bot]" + # Re-authenticate git with GitHub token + SERVER_URL_STRIPPED="${SERVER_URL#https://}" + git remote set-url origin "https://x-access-token:${{ github.token }}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" + echo "Git configured with standard GitHub Actions identity" + - name: Checkout PR branch + id: checkout-pr + if: | + github.event.pull_request + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + with: + github-token: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/checkout_pr_branch.cjs'); + await main(); + - name: Generate agentic run info + id: generate_aw_info + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + with: + script: | + const fs = require('fs'); + + const awInfo = { + engine_id: "copilot", + engine_name: "GitHub Copilot CLI", + model: "${{ inputs.model }}", + version: "", + agent_version: "0.0.412", + workflow_name: "Scheduled Audit", + experimental: false, + supports_tools_allowlist: true, + run_id: context.runId, + run_number: context.runNumber, + run_attempt: process.env.GITHUB_RUN_ATTEMPT, + repository: context.repo.owner + '/' + context.repo.repo, + ref: context.ref, + sha: context.sha, + actor: context.actor, + event_name: context.eventName, + staged: false, + allowed_domains: ["agents-md-generator.fastmcp.app","artifacts.elastic.co","cloud.elastic.co","defaults","ela.st","elastic.co","github","go","node","public-code-search.fastmcp.app","python","ruby","www.elastic.co"], + firewall_enabled: true, + awf_version: "v0.20.2", + awmg_version: "v0.1.4", + steps: { + firewall: "squid" + }, + created_at: new Date().toISOString() + }; + + // Write to /tmp/gh-aw directory to avoid inclusion in PR + const tmpPath = '/tmp/gh-aw/aw_info.json'; + fs.writeFileSync(tmpPath, JSON.stringify(awInfo, null, 2)); + console.log('Generated aw_info.json at:', tmpPath); + console.log(JSON.stringify(awInfo, null, 2)); + + // Set model as output for reuse in other steps/jobs + core.setOutput('model', awInfo.model); + - name: Validate COPILOT_GITHUB_TOKEN secret + id: validate-secret + run: /opt/gh-aw/actions/validate_multi_secret.sh COPILOT_GITHUB_TOKEN 'GitHub Copilot CLI' https://github.github.com/gh-aw/reference/engines/#github-copilot-default + env: + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + - name: Install GitHub Copilot CLI + run: /opt/gh-aw/actions/install_copilot_cli.sh 0.0.412 + - name: Install awf binary + run: bash /opt/gh-aw/actions/install_awf_binary.sh v0.20.2 + - name: Determine automatic lockdown mode for GitHub MCP Server + id: determine-automatic-lockdown + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} + GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} + with: + script: | + 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.20.2 ghcr.io/github/gh-aw-firewall/api-proxy:0.20.2 ghcr.io/github/gh-aw-firewall/squid:0.20.2 ghcr.io/github/gh-aw-mcpg:v0.1.4 ghcr.io/github/github-mcp-server:v0.31.0 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' + {"create_issue":{"expires":168,"max":1},"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 \"${{ inputs.issue-title-prefix }} \".", + "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": "Report that a tool or capability needed to complete the task is not available, or share any information you deem important about missing functionality or limitations. Use this when you cannot accomplish what was requested because the required functionality is missing or access is restricted.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "alternatives": { + "description": "Any workarounds, manual steps, or alternative approaches the user could take (max 256 characters).", + "type": "string" + }, + "reason": { + "description": "Explanation of why this tool is needed or what information you want to share about the limitation (max 256 characters).", + "type": "string" + }, + "tool": { + "description": "Optional: Name or description of the missing tool or capability (max 128 characters). Be specific about what functionality is needed.", + "type": "string" + } + }, + "required": [ + "reason" + ], + "type": "object" + }, + "name": "missing_tool" + }, + { + "description": "Log a transparency message when no significant actions are needed. Use this to confirm workflow completion and provide visibility when analysis is complete but no changes or outputs are required (e.g., 'No issues found', 'All checks passed'). This ensures the workflow produces human-visible output even when no other actions are taken.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "message": { + "description": "Status or completion message to log. Should explain what was analyzed and the outcome (e.g., 'Code review complete - no issues found', 'Analysis complete - all tests passing').", + "type": "string" + } + }, + "required": [ + "message" + ], + "type": "object" + }, + "name": "noop" + }, + { + "description": "Report that data or information needed to complete the task is not available. Use this when you cannot accomplish what was requested because required data, context, or information is missing.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "alternatives": { + "description": "Any workarounds, manual steps, or alternative approaches the user could take (max 256 characters).", + "type": "string" + }, + "context": { + "description": "Additional context about the missing data or where it should come from (max 256 characters).", + "type": "string" + }, + "data_type": { + "description": "Type or description of the missing data or information (max 128 characters). Be specific about what data is needed.", + "type": "string" + }, + "reason": { + "description": "Explanation of why this data is needed to complete the task (max 256 characters).", + "type": "string" + } + }, + "required": [], + "type": "object" + }, + "name": "missing_data" + } + ] + GH_AW_SAFE_OUTPUTS_TOOLS_EOF + cat > /opt/gh-aw/safeoutputs/validation.json << 'GH_AW_SAFE_OUTPUTS_VALIDATION_EOF' + { + "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_data": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "context": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "data_type": { + "type": "string", + "sanitize": true, + "maxLength": 128 + }, + "reason": { + "type": "string", + "sanitize": true, + "maxLength": 256 + } + } + }, + "missing_tool": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 512 + }, + "reason": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "tool": { + "type": "string", + "sanitize": true, + "maxLength": 128 + } + } + }, + "noop": { + "defaultMax": 1, + "fields": { + "message": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + } + } + } + } + GH_AW_SAFE_OUTPUTS_VALIDATION_EOF + - name: Generate Safe Outputs MCP Server Config + id: safe-outputs-config + run: | + # Generate a secure random API key (360 bits of entropy, 40+ chars) + # Mask immediately to prevent timing vulnerabilities + API_KEY=$(openssl rand -base64 45 | tr -d '/+=') + echo "::add-mask::${API_KEY}" + + PORT=3001 + + # Set outputs for next steps + { + echo "safe_outputs_api_key=${API_KEY}" + echo "safe_outputs_port=${PORT}" + } >> "$GITHUB_OUTPUT" + + echo "Safe Outputs MCP server will run on port ${PORT}" + + - name: Start Safe Outputs MCP HTTP Server + id: safe-outputs-start + env: + DEBUG: '*' + GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-config.outputs.safe_outputs_port }} + GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-config.outputs.safe_outputs_api_key }} + GH_AW_SAFE_OUTPUTS_TOOLS_PATH: /opt/gh-aw/safeoutputs/tools.json + GH_AW_SAFE_OUTPUTS_CONFIG_PATH: /opt/gh-aw/safeoutputs/config.json + GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs + run: | + # Environment variables are set above to prevent template injection + export DEBUG + export GH_AW_SAFE_OUTPUTS_PORT + export GH_AW_SAFE_OUTPUTS_API_KEY + export GH_AW_SAFE_OUTPUTS_TOOLS_PATH + export GH_AW_SAFE_OUTPUTS_CONFIG_PATH + export GH_AW_MCP_LOG_DIR + + bash /opt/gh-aw/actions/start_safe_outputs_server.sh + + - name: Start MCP Gateway + id: start-mcp-gateway + env: + GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} + GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-start.outputs.api_key }} + GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-start.outputs.port }} + GITHUB_MCP_LOCKDOWN: ${{ steps.determine-automatic-lockdown.outputs.lockdown == 'true' && '1' || '0' }} + GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + run: | + set -eo pipefail + mkdir -p /tmp/gh-aw/mcp-config + + # Export gateway environment variables for MCP config and gateway script + export MCP_GATEWAY_PORT="80" + export MCP_GATEWAY_DOMAIN="host.docker.internal" + MCP_GATEWAY_API_KEY=$(openssl rand -base64 45 | tr -d '/+=') + echo "::add-mask::${MCP_GATEWAY_API_KEY}" + export MCP_GATEWAY_API_KEY + export MCP_GATEWAY_PAYLOAD_DIR="/tmp/gh-aw/mcp-payloads" + mkdir -p "${MCP_GATEWAY_PAYLOAD_DIR}" + export DEBUG="*" + + export GH_AW_ENGINE="copilot" + 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 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_LOCKDOWN -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.1.4' + + mkdir -p /home/runner/.copilot + cat << GH_AW_MCP_CONFIG_EOF | bash /opt/gh-aw/actions/start_mcp_gateway.sh + { + "mcpServers": { + "agents-md-generator": { + "type": "http", + "url": "https://agents-md-generator.fastmcp.app/mcp", + "tools": [ + "generate_agents_md" + ] + }, + "github": { + "type": "stdio", + "container": "ghcr.io/github/github-mcp-server:v0.31.0", + "env": { + "GITHUB_LOCKDOWN_MODE": "$GITHUB_MCP_LOCKDOWN", + "GITHUB_PERSONAL_ACCESS_TOKEN": "\${GITHUB_MCP_SERVER_TOKEN}", + "GITHUB_READ_ONLY": "1", + "GITHUB_TOOLSETS": "repos,issues,pull_requests,search,labels" + } + }, + "public-code-search": { + "type": "http", + "url": "https://public-code-search.fastmcp.app/mcp", + "tools": [ + "search_code" + ] + }, + "safeoutputs": { + "type": "http", + "url": "http://host.docker.internal:$GH_AW_SAFE_OUTPUTS_PORT", + "headers": { + "Authorization": "\${GH_AW_SAFE_OUTPUTS_API_KEY}" + } + } + }, + "gateway": { + "port": $MCP_GATEWAY_PORT, + "domain": "${MCP_GATEWAY_DOMAIN}", + "apiKey": "${MCP_GATEWAY_API_KEY}", + "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" + } + } + GH_AW_MCP_CONFIG_EOF + - name: Generate workflow overview + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + with: + script: | + const { generateWorkflowOverview } = require('/opt/gh-aw/actions/generate_workflow_overview.cjs'); + await generateWorkflowOverview(core); + - name: Download prompt artifact + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 + with: + name: prompt + path: /tmp/gh-aw/aw-prompts + - name: Clean git credentials + run: bash /opt/gh-aw/actions/clean_git_credentials.sh + - name: Execute GitHub Copilot CLI + id: agentic_execution + # Copilot CLI tool arguments (sorted): + timeout-minutes: 90 + run: | + set -o pipefail + sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --allow-domains '*.githubusercontent.com,*.jsr.io,*.pythonhosted.org,*.rvm.io,agents-md-generator.fastmcp.app,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.rubygems.org,api.snapcraft.io,archive.ubuntu.com,artifacts.elastic.co,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,bun.sh,bundler.rubygems.org,cache.ruby-lang.org,cdn.jsdelivr.net,cloud.elastic.co,codeload.github.com,conda.anaconda.org,conda.binstar.org,crates.io,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,deb.nodesource.com,deno.land,ela.st,elastic.co,esm.sh,files.pythonhosted.org,gems.rubyforge.org,gems.rubyonrails.org,get.pnpm.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,host.docker.internal,index.crates.io,index.rubygems.org,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,lfs.github.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,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,pip.pypa.io,pkg.go.dev,ppa.launchpad.net,proxy.golang.org,public-code-search.fastmcp.app,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.bower.io,registry.npmjs.com,registry.npmjs.org,registry.yarnpkg.com,repo.anaconda.com,repo.continuum.io,repo.yarnpkg.com,rubygems.org,rubygems.pkg.github.com,s.symcb.com,s.symcd.com,security.ubuntu.com,skimdb.npmjs.com,static.crates.io,storage.googleapis.com,sum.golang.org,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.elastic.co,www.npmjs.com,www.npmjs.org,yarnpkg.com' --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.20.2 --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 --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log + env: + COPILOT_AGENT_RUNNER_TYPE: STANDALONE + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} + GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} + GITHUB_HEAD_REF: ${{ github.head_ref }} + GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + GITHUB_REF_NAME: ${{ github.ref_name }} + GITHUB_STEP_SUMMARY: ${{ env.GITHUB_STEP_SUMMARY }} + GITHUB_WORKSPACE: ${{ github.workspace }} + XDG_CONFIG_HOME: /home/runner + - name: Configure Git credentials + env: + REPO_NAME: ${{ github.repository }} + SERVER_URL: ${{ github.server_url }} + run: | + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git config --global user.name "github-actions[bot]" + # Re-authenticate git with GitHub token + SERVER_URL_STRIPPED="${SERVER_URL#https://}" + git remote set-url origin "https://x-access-token:${{ github.token }}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" + echo "Git configured with standard GitHub Actions identity" + - name: Copy Copilot session state files to logs + if: always() + continue-on-error: true + run: | + # Copy Copilot session state files to logs folder for artifact collection + # This ensures they are in /tmp/gh-aw/ where secret redaction can scan them + SESSION_STATE_DIR="$HOME/.copilot/session-state" + LOGS_DIR="/tmp/gh-aw/sandbox/agent/logs" + + if [ -d "$SESSION_STATE_DIR" ]; then + echo "Copying Copilot session state files from $SESSION_STATE_DIR to $LOGS_DIR" + mkdir -p "$LOGS_DIR" + cp -v "$SESSION_STATE_DIR"/*.jsonl "$LOGS_DIR/" 2>/dev/null || true + echo "Session state files copied successfully" + else + echo "No session-state directory found at $SESSION_STATE_DIR" + fi + - name: Stop MCP Gateway + if: always() + continue-on-error: true + env: + MCP_GATEWAY_PORT: ${{ steps.start-mcp-gateway.outputs.gateway-port }} + MCP_GATEWAY_API_KEY: ${{ steps.start-mcp-gateway.outputs.gateway-api-key }} + GATEWAY_PID: ${{ steps.start-mcp-gateway.outputs.gateway-pid }} + run: | + bash /opt/gh-aw/actions/stop_mcp_gateway.sh "$GATEWAY_PID" + - name: Redact secrets in logs + if: always() + 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/redact_secrets.cjs'); + await main(); + env: + GH_AW_SECRET_NAMES: 'COPILOT_GITHUB_TOKEN,GH_AW_GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,GITHUB_TOKEN' + SECRET_COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + SECRET_GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} + SECRET_GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} + SECRET_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Upload Safe Outputs + if: always() + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: safe-output + path: ${{ env.GH_AW_SAFE_OUTPUTS }} + if-no-files-found: warn + - name: Ingest agent output + id: collect_output + if: always() + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} + GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,*.jsr.io,*.pythonhosted.org,*.rvm.io,agents-md-generator.fastmcp.app,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.rubygems.org,api.snapcraft.io,archive.ubuntu.com,artifacts.elastic.co,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,bun.sh,bundler.rubygems.org,cache.ruby-lang.org,cdn.jsdelivr.net,cloud.elastic.co,codeload.github.com,conda.anaconda.org,conda.binstar.org,crates.io,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,deb.nodesource.com,deno.land,ela.st,elastic.co,esm.sh,files.pythonhosted.org,gems.rubyforge.org,gems.rubyonrails.org,get.pnpm.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,host.docker.internal,index.crates.io,index.rubygems.org,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,lfs.github.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,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,pip.pypa.io,pkg.go.dev,ppa.launchpad.net,proxy.golang.org,public-code-search.fastmcp.app,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.bower.io,registry.npmjs.com,registry.npmjs.org,registry.yarnpkg.com,repo.anaconda.com,repo.continuum.io,repo.yarnpkg.com,rubygems.org,rubygems.pkg.github.com,s.symcb.com,s.symcd.com,security.ubuntu.com,skimdb.npmjs.com,static.crates.io,storage.googleapis.com,sum.golang.org,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.elastic.co,www.npmjs.com,www.npmjs.org,yarnpkg.com" + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_API_URL: ${{ github.api_url }} + 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/collect_ndjson_output.cjs'); + await main(); + - name: Upload sanitized agent output + if: always() && env.GH_AW_AGENT_OUTPUT + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: agent-output + path: ${{ env.GH_AW_AGENT_OUTPUT }} + if-no-files-found: warn + - name: Upload engine output files + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: agent_outputs + path: | + /tmp/gh-aw/sandbox/agent/logs/ + /tmp/gh-aw/redacted-urls.log + if-no-files-found: ignore + - name: Parse agent logs for step summary + if: always() + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: /tmp/gh-aw/sandbox/agent/logs/ + 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/parse_copilot_log.cjs'); + await main(); + - name: Parse MCP Gateway logs for step summary + if: always() + 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/parse_mcp_gateway_log.cjs'); + await main(); + - name: Print firewall logs + if: always() + continue-on-error: true + env: + AWF_LOGS_DIR: /tmp/gh-aw/sandbox/firewall/logs + run: | + # Fix permissions on firewall logs so they can be uploaded as artifacts + # AWF runs with sudo, creating files owned by root + sudo chmod -R a+r /tmp/gh-aw/sandbox/firewall/logs 2>/dev/null || true + # Only run awf logs summary if awf command exists (it may not be installed if workflow failed before install step) + if command -v awf &> /dev/null; then + awf logs summary | tee -a "$GITHUB_STEP_SUMMARY" + else + echo 'AWF binary not installed, skipping firewall log summary' + fi + - name: Upload agent artifacts + if: always() + continue-on-error: true + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: agent-artifacts + path: | + /tmp/gh-aw/aw-prompts/prompt.txt + /tmp/gh-aw/aw_info.json + /tmp/gh-aw/mcp-logs/ + /tmp/gh-aw/sandbox/firewall/logs/ + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/agent/ + if-no-files-found: ignore + + conclusion: + needs: + - activation + - agent + - detection + - safe_outputs + if: (always()) && (needs.agent.result != 'skipped') + runs-on: ubuntu-slim + permissions: + contents: read + issues: write + outputs: + noop_message: ${{ steps.noop.outputs.noop_message }} + tools_reported: ${{ steps.missing_tool.outputs.tools_reported }} + total_count: ${{ steps.missing_tool.outputs.total_count }} + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 + with: + destination: /opt/gh-aw/actions + - name: Download agent output artifact + continue-on-error: true + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 + with: + name: agent-output + path: /tmp/gh-aw/safeoutputs/ + - name: Setup agent output environment variable + run: | + mkdir -p /tmp/gh-aw/safeoutputs/ + find "/tmp/gh-aw/safeoutputs/" -type f -print + echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/safeoutputs/agent_output.json" >> "$GITHUB_ENV" + - name: Process No-Op Messages + id: noop + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_NOOP_MAX: 1 + GH_AW_WORKFLOW_NAME: "Scheduled Audit" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/noop.cjs'); + await main(); + - name: Record Missing Tool + id: missing_tool + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_WORKFLOW_NAME: "Scheduled Audit" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/missing_tool.cjs'); + await main(); + - name: Handle Agent Failure + id: handle_agent_failure + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_WORKFLOW_NAME: "Scheduled Audit" + 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: "gh-aw-scheduled-audit" + GH_AW_SECRET_VERIFICATION_RESULT: ${{ needs.agent.outputs.secret_verification_result }} + GH_AW_CHECKOUT_PR_SUCCESS: ${{ needs.agent.outputs.checkout_pr_success }} + GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\"}" + GH_AW_GROUP_REPORTS: "false" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/handle_agent_failure.cjs'); + await main(); + - name: Handle No-Op Message + id: handle_noop_message + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_WORKFLOW_NAME: "Scheduled Audit" + 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 }} + GH_AW_NOOP_REPORT_AS_ISSUE: "true" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/handle_noop_message.cjs'); + await main(); + + detection: + needs: agent + if: needs.agent.outputs.output_types != '' || needs.agent.outputs.has_patch == 'true' + runs-on: ubuntu-latest + permissions: {} + timeout-minutes: 10 + outputs: + success: ${{ steps.parse_results.outputs.success }} + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 + with: + destination: /opt/gh-aw/actions + - name: Download agent artifacts + continue-on-error: true + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 + with: + name: agent-artifacts + path: /tmp/gh-aw/threat-detection/ + - name: Download agent output artifact + continue-on-error: true + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 + with: + name: agent-output + path: /tmp/gh-aw/threat-detection/ + - name: Print agent output types + env: + AGENT_OUTPUT_TYPES: ${{ needs.agent.outputs.output_types }} + run: | + echo "Agent output-types: $AGENT_OUTPUT_TYPES" + - name: Setup threat detection + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + WORKFLOW_NAME: "Scheduled Audit" + WORKFLOW_DESCRIPTION: "Generic scheduled audit — investigate the repository and file an issue when something needs attention" + HAS_PATCH: ${{ needs.agent.outputs.has_patch }} + 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/setup_threat_detection.cjs'); + await main(); + - name: Ensure threat-detection directory and log + run: | + mkdir -p /tmp/gh-aw/threat-detection + touch /tmp/gh-aw/threat-detection/detection.log + - name: Validate COPILOT_GITHUB_TOKEN secret + id: validate-secret + run: /opt/gh-aw/actions/validate_multi_secret.sh COPILOT_GITHUB_TOKEN 'GitHub Copilot CLI' https://github.github.com/gh-aw/reference/engines/#github-copilot-default + env: + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + - name: Install GitHub Copilot CLI + run: /opt/gh-aw/actions/install_copilot_cli.sh 0.0.412 + - name: Execute GitHub Copilot CLI + id: agentic_execution + # Copilot CLI tool arguments (sorted): + # --allow-tool shell(cat) + # --allow-tool shell(grep) + # --allow-tool shell(head) + # --allow-tool shell(jq) + # --allow-tool shell(ls) + # --allow-tool shell(tail) + # --allow-tool shell(wc) + timeout-minutes: 20 + run: | + set -o pipefail + COPILOT_CLI_INSTRUCTION="$(cat /tmp/gh-aw/aw-prompts/prompt.txt)" + mkdir -p /tmp/ + mkdir -p /tmp/gh-aw/ + mkdir -p /tmp/gh-aw/agent/ + mkdir -p /tmp/gh-aw/sandbox/agent/logs/ + copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log + env: + COPILOT_AGENT_RUNNER_TYPE: STANDALONE + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GITHUB_HEAD_REF: ${{ github.head_ref }} + GITHUB_REF_NAME: ${{ github.ref_name }} + GITHUB_STEP_SUMMARY: ${{ env.GITHUB_STEP_SUMMARY }} + GITHUB_WORKSPACE: ${{ github.workspace }} + XDG_CONFIG_HOME: /home/runner + - name: Parse threat detection results + id: parse_results + 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/parse_threat_detection_results.cjs'); + await main(); + - name: Upload threat detection log + if: always() + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: threat-detection.log + path: /tmp/gh-aw/threat-detection/detection.log + if-no-files-found: ignore + + pre_activation: + runs-on: ubuntu-slim + outputs: + activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 + with: + destination: /opt/gh-aw/actions + - name: Check team membership for workflow + id: check_membership + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_REQUIRED_ROLES: admin,maintainer,write + GH_AW_ALLOWED_BOTS: ${{ inputs.allowed-bot-users }} + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + 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_membership.cjs'); + await main(); + + safe_outputs: + needs: + - agent + - detection + if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (needs.detection.outputs.success == 'true') + runs-on: ubuntu-slim + permissions: + contents: read + issues: write + timeout-minutes: 15 + env: + GH_AW_ENGINE_ID: "copilot" + GH_AW_ENGINE_MODEL: "${{ inputs.model }}" + GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\"}" + GH_AW_WORKFLOW_ID: "gh-aw-scheduled-audit" + GH_AW_WORKFLOW_NAME: "Scheduled Audit" + outputs: + create_discussion_error_count: ${{ steps.process_safe_outputs.outputs.create_discussion_error_count }} + create_discussion_errors: ${{ steps.process_safe_outputs.outputs.create_discussion_errors }} + process_safe_outputs_processed_count: ${{ steps.process_safe_outputs.outputs.processed_count }} + process_safe_outputs_temporary_id_map: ${{ steps.process_safe_outputs.outputs.temporary_id_map }} + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 + with: + destination: /opt/gh-aw/actions + - name: Download agent output artifact + continue-on-error: true + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 + with: + name: agent-output + path: /tmp/gh-aw/safeoutputs/ + - name: Setup agent output environment variable + run: | + mkdir -p /tmp/gh-aw/safeoutputs/ + find "/tmp/gh-aw/safeoutputs/" -type f -print + echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/safeoutputs/agent_output.json" >> "$GITHUB_ENV" + - name: Process Safe Outputs + id: process_safe_outputs + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_issue\":{\"close_older_issues\":true,\"expires\":168,\"max\":1,\"title_prefix\":\"${{ inputs.issue-title-prefix }} \"},\"missing_data\":{},\"missing_tool\":{}}" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/safe_output_handler_manager.cjs'); + await main(); + - name: Upload safe output items manifest + if: always() + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: safe-output-items + path: /tmp/safe-output-items.jsonl + if-no-files-found: warn + diff --git a/.github/workflows/gh-aw-scheduled-audit.md b/.github/workflows/gh-aw-scheduled-audit.md new file mode 100644 index 00000000..e17b2eb1 --- /dev/null +++ b/.github/workflows/gh-aw-scheduled-audit.md @@ -0,0 +1,100 @@ +--- +inlined-imports: true +name: "Scheduled Audit" +description: "Generic scheduled audit — investigate the repository and file an issue when something needs attention" +imports: + - gh-aw-fragments/elastic-tools.md + - gh-aw-fragments/runtime-setup.md + - gh-aw-fragments/formatting.md + - gh-aw-fragments/rigor.md + - gh-aw-fragments/mcp-pagination.md + - gh-aw-fragments/messages-footer.md + - gh-aw-fragments/safe-output-create-issue.md + - gh-aw-fragments/scheduled-audit.md +engine: + id: copilot + model: ${{ inputs.model }} +on: + workflow_call: + inputs: + model: + description: "AI model to use" + type: string + required: false + default: "gpt-5.3-codex" + additional-instructions: + description: "What the audit agent should investigate — appended as the Report Assignment" + type: string + required: true + issue-title-prefix: + description: "Title prefix for created issues, e.g. '[my-audit]'" + type: string + required: true + issue-label: + description: "Label to apply to created issues (must already exist in the target repo)" + type: string + required: false + default: "" + setup-commands: + description: "Shell commands to run before the agent starts (dependency install, build, etc.)" + type: string + required: false + default: "" + allowed-bot-users: + description: "Allowlisted bot actor usernames (comma-separated)" + type: string + required: false + default: "github-actions[bot]" + messages-footer: + description: "Footer appended to all agent comments and reviews" + type: string + required: false + default: "" + secrets: + COPILOT_GITHUB_TOKEN: + required: true + roles: [admin, maintainer, write] + bots: + - "${{ inputs.allowed-bot-users }}" +concurrency: + group: scheduled-audit-${{ inputs.issue-title-prefix }} + cancel-in-progress: true +permissions: + contents: read + issues: read + pull-requests: read +tools: + github: + toolsets: [repos, issues, pull_requests, search, labels] + bash: true + web-fetch: +network: + allowed: + - defaults + - github + - go + - node + - python + - ruby +strict: false +safe-outputs: + noop: + create-issue: + max: 1 + title-prefix: "${{ inputs.issue-title-prefix }} " + close-older-issues: true + expires: 7d +timeout-minutes: 90 +steps: + - name: Repo-specific setup + if: ${{ inputs.setup-commands != '' }} + env: + SETUP_COMMANDS: ${{ inputs.setup-commands }} + run: eval "$SETUP_COMMANDS" +--- + +### Labeling + +If `${{ inputs.issue-label }}` is set and the label exists in the repository (check with `github-get_label`), include it in the `create_issue` call. Otherwise rely on the title prefix only. + +${{ inputs.additional-instructions }} diff --git a/.github/workflows/gh-aw-scheduled-fix.lock.yml b/.github/workflows/gh-aw-scheduled-fix.lock.yml new file mode 100644 index 00000000..76dbb639 --- /dev/null +++ b/.github/workflows/gh-aw-scheduled-fix.lock.yml @@ -0,0 +1,1591 @@ +# +# ___ _ _ +# / _ \ | | (_) +# | |_| | __ _ ___ _ __ | |_ _ ___ +# | _ |/ _` |/ _ \ '_ \| __| |/ __| +# | | | | (_| | __/ | | | |_| | (__ +# \_| |_/\__, |\___|_| |_|\__|_|\___| +# __/ | +# _ _ |___/ +# | | | | / _| | +# | | | | ___ _ __ _ __| |_| | _____ ____ +# | |/\| |/ _ \ '__| |/ /| _| |/ _ \ \ /\ / / ___| +# \ /\ / (_) | | | | ( | | | | (_) \ V V /\__ \ +# \/ \/ \___/|_| |_|\_\|_| |_|\___/ \_/\_/ |___/ +# +# This file was automatically generated by gh-aw. DO NOT EDIT. +# +# To update this file, edit the corresponding .md file and run: +# gh aw compile +# Not all edits will cause changes to this file. +# +# For more information: https://github.github.com/gh-aw/introduction/overview/ +# +# Generic scheduled fixer — pick up an open issue and create a focused PR that addresses it +# +# Resolved workflow manifest: +# Imports: +# - gh-aw-fragments/elastic-tools.md +# - gh-aw-fragments/formatting.md +# - gh-aw-fragments/mcp-pagination.md +# - gh-aw-fragments/messages-footer.md +# - gh-aw-fragments/rigor.md +# - gh-aw-fragments/runtime-setup.md +# - gh-aw-fragments/safe-output-create-pr.md +# - gh-aw-fragments/scheduled-fix.md +# - gh-aw-fragments/workflow-edit-guardrails.md +# +# inlined-imports: true +# +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"c465c6dad1086f101ec331fa349f22b48f43a2c883e2fd6cfca8fafe013356f6"} + +name: "Scheduled Fix" +"on": + # bots: # Bots processed as bot check in pre-activation job + # - ${{ inputs.allowed-bot-users }} # Bots processed as bot check in pre-activation job + # roles: # Roles processed as role check in pre-activation job + # - admin # Roles processed as role check in pre-activation job + # - maintainer # Roles processed as role check in pre-activation job + # - write # Roles processed as role check in pre-activation job + workflow_call: + inputs: + additional-instructions: + description: Domain-specific fix instructions — appended as the Fix Assignment + required: true + type: string + allowed-bot-users: + default: github-actions[bot] + description: Allowlisted bot actor usernames (comma-separated) + required: false + type: string + draft-prs: + default: "true" + description: Create PRs as draft (true/false) + required: false + type: string + issue-label: + default: "" + description: Label to search for in open issues + required: false + type: string + issue-title-prefix: + description: Title prefix to search for in open issues, e.g. '[text-auditor]' + required: true + type: string + messages-footer: + default: "" + description: Footer appended to all agent comments and reviews + required: false + type: string + model: + default: gpt-5.3-codex + description: AI model to use + required: false + type: string + setup-commands: + default: "" + description: Shell commands to run before the agent starts (dependency install, build, etc.) + required: false + type: string + secrets: + COPILOT_GITHUB_TOKEN: + required: true + +permissions: {} + +concurrency: + cancel-in-progress: true + group: scheduled-fix-${{ inputs.issue-title-prefix }} + +run-name: "Scheduled Fix" + +jobs: + activation: + needs: pre_activation + if: needs.pre_activation.outputs.activated == 'true' + runs-on: ubuntu-slim + permissions: + contents: read + outputs: + comment_id: "" + comment_repo: "" + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 + with: + destination: /opt/gh-aw/actions + - name: Validate context variables + 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/validate_context_variables.cjs'); + await main(); + - name: Checkout .github and .agents folders + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + sparse-checkout: | + .github + .agents + fetch-depth: 1 + persist-credentials: false + - name: Check workflow file timestamps + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_WORKFLOW_FILE: "gh-aw-scheduled-fix.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: Create prompt with built-in context + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} + GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} + GH_AW_EXPR_955E52F5: ${{ inputs.issue-label }} + GH_AW_EXPR_CE96317F: ${{ inputs.issue-title-prefix }} + GH_AW_GITHUB_ACTOR: ${{ github.actor }} + GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} + GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} + GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} + GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} + GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} + GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} + run: | + bash /opt/gh-aw/actions/create_prompt_first.sh + cat << 'GH_AW_PROMPT_EOF' > "$GH_AW_PROMPT" + + GH_AW_PROMPT_EOF + cat "/opt/gh-aw/prompts/xpia.md" >> "$GH_AW_PROMPT" + cat "/opt/gh-aw/prompts/temp_folder_prompt.md" >> "$GH_AW_PROMPT" + cat "/opt/gh-aw/prompts/markdown.md" >> "$GH_AW_PROMPT" + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + + GitHub API Access Instructions + + The gh CLI is NOT authenticated. Do NOT use gh commands for GitHub operations. + + + To create or modify GitHub resources (issues, discussions, pull requests, etc.), you MUST call the appropriate safe output tool. Simply writing content will NOT work - the workflow requires actual tool calls. + + Temporary IDs: Some safe output tools support a temporary ID field (usually named temporary_id) so you can reference newly-created items elsewhere in the SAME agent output (for example, using #aw_abc1 in a later body). + + **IMPORTANT - temporary_id format rules:** + - If you DON'T need to reference the item later, OMIT the temporary_id field entirely (it will be auto-generated if needed) + - If you DO need cross-references/chaining, you MUST match this EXACT validation regex: /^aw_[A-Za-z0-9]{3,8}$/i + - Format: aw_ prefix followed by 3 to 8 alphanumeric characters (A-Z, a-z, 0-9, case-insensitive) + - Valid alphanumeric characters: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 + - INVALID examples: aw_ab (too short), aw_123456789 (too long), aw_test-id (contains hyphen), aw_id_123 (contains underscore) + - VALID examples: aw_abc, aw_abc1, aw_Test123, aw_A1B2C3D4, aw_12345678 + - To generate valid IDs: use 3-8 random alphanumeric characters or omit the field to let the system auto-generate + + Do NOT invent other aw_* formats — downstream steps will reject them with validation errors matching against /^aw_[A-Za-z0-9]{3,8}$/i. + + Discover available tools from the safeoutputs MCP server. + + **Critical**: Tool calls write structured data that downstream jobs process. Without tool calls, follow-up actions will be skipped. + + **Note**: If you made no other safe output tool calls during this workflow execution, call the "noop" tool to provide a status message indicating completion or that no actions were needed. + + --- + + ## Creating a Pull Request, Reporting Missing Tools or Functionality, Reporting Missing Data + + **IMPORTANT**: To perform the actions listed above, use the **safeoutputs** tools. Do NOT use `gh`, do NOT call the GitHub API directly. You do not have write access to the GitHub repository. + + **Creating a Pull Request** + + To create a pull request: + 1. Make any file changes directly in the working directory. + 2. If you haven't done so already, create a local branch using an appropriate unique name. + 3. Add and commit your changes to the branch. Be careful to add exactly the files you intend, and check there are no extra files left un-added. Verify you haven't deleted or changed any files you didn't intend to. + 4. Do not push your changes. That will be done by the tool. + 5. Create the pull request with the create_pull_request tool from safeoutputs. + + **Reporting Missing Tools or Functionality** + + To report a missing tool or capability, use the missing_tool tool from safeoutputs. + + **Reporting Missing Data** + + To report missing data required to achieve a goal, use the missing_data tool from safeoutputs. + + + + + The following GitHub context information is available for this workflow: + {{#if __GH_AW_GITHUB_ACTOR__ }} + - **actor**: __GH_AW_GITHUB_ACTOR__ + {{/if}} + {{#if __GH_AW_GITHUB_REPOSITORY__ }} + - **repository**: __GH_AW_GITHUB_REPOSITORY__ + {{/if}} + {{#if __GH_AW_GITHUB_WORKSPACE__ }} + - **workspace**: __GH_AW_GITHUB_WORKSPACE__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_ISSUE_NUMBER__ }} + - **issue-number**: #__GH_AW_GITHUB_EVENT_ISSUE_NUMBER__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__ }} + - **discussion-number**: #__GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__ }} + - **pull-request-number**: #__GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_COMMENT_ID__ }} + - **comment-id**: __GH_AW_GITHUB_EVENT_COMMENT_ID__ + {{/if}} + {{#if __GH_AW_GITHUB_RUN_ID__ }} + - **workflow-run-id**: __GH_AW_GITHUB_RUN_ID__ + {{/if}} + + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + ## MCP Servers + + - **`generate_agents_md`** — generates a summary of the repository's structure, conventions, and coding guidelines from AGENTS.md and related files. Call at the start of every workflow to get repo context. + - **`search_code`** — grep-style search across public GitHub repositories. Use for finding usage patterns in upstream libraries, reference implementations, or examples in open-source projects. This searches *public GitHub repos*, not the local codebase — if available you can use `grep` and file reading for local code. + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + ## Formatting Guidelines + + - Lead with the most important information — your first sentence should be the key takeaway + - Be concise and actionable — no filler or praise + - Use `
` and `` tags for long sections to keep responses scannable + - Wrap branch names and @-references in backticks to avoid pinging users + - Include code snippets with file paths and line numbers when referencing the codebase + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + ## Rigor + + **Silence is better than noise. A false positive wastes a human's time and erodes trust in every future report.** + + - If you claim something is missing or broken, show the exact evidence in the code — file path, line number, and what you observed. + - If a conclusion depends on assumptions you haven't confirmed, do not assert it. Verify first; if you cannot verify, do not report. + - "I don't know" is better than a wrong answer. `noop` is better than a speculative finding. + - It's worth the time to verify now versus guessing and forcing someone else to verify later. + - Before filing any issue or opening any PR, re-read your own output as a skeptical reviewer. Ask: "Would a senior engineer on this team find this useful, or would they close it immediately?" If the answer is "close," call `noop` instead. + - Only report findings you would confidently defend in a code review. If you feel the need to hedge with "might," "could," or "possibly," the finding is not ready to file. + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + ## MCP Pagination + + MCP tool responses have a **25,000 token limit**. When responses exceed this limit, the call fails and you must retry with pagination — wasting turns and tokens. Use proactive pagination to stay under the limit. + + ### Recommended `perPage` Values + + - **5-10**: For detailed items (PR diffs, files with patches, issues with comments) + - **20-30**: For medium-detail lists (commits, review comments, issue lists) + - **50-100**: For simple list operations (branches, labels, tags) + + ### Pagination Pattern + + When you need all results from a paginated API: + + 1. Fetch the first page with a conservative `perPage` value + 2. Process the results before fetching the next page + 3. Continue fetching pages until you receive fewer results than `perPage` (indicating the last page) + + ### Error Recovery + + If you see an error like: + - `MCP tool response exceeds maximum allowed tokens (25000)` + - `Response too large for tool [tool_name]` + + Retry the same call with a smaller `perPage` value (halve it). + + ### Tips + + - **Start small**: It's better to make multiple small requests than one that fails + - **Fetch incrementally**: Get an overview first, then details for specific items + - **Use filters**: Combine `perPage` with state, label, or date filters to reduce result size + - **Process as you go**: Don't accumulate all pages before acting — process each batch immediately + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + ## Workflow Editing Guardrails + + - Do not modify files under `.github/workflows/`. + - If asked to change workflow files, place a copy under `github/` (no leading dot) and note that a maintainer must relocate it into `.github/workflows/`. + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + ## Message Footer + + A footer is automatically appended to all comments and reviews. Do not add your own footer or sign-off — the runtime handles this. + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + Before calling `create_pull_request`, call `ready_to_make_pr` and apply its checklist. + + ## create-pull-request Limitations + + - **Patch files**: Max 100 files per PR. If changes span more files, split into multiple focused PRs. + - **Patch size**: Max 1,024 KB by default. Keep changes focused. + - **Title**: Max 128 characters. Sanitized. + - **Body**: No explicit mention/link limits, but bot triggers (`fixes #123`, `closes #456`) are neutralized. + - **Committed changes required**: You must have locally committed changes before creating a PR (unless `allow_empty` is configured). + - **Base branch**: Must be configured in the safe-output config. The PR targets this branch. + - **Max per run**: Typically 1 PR creation per workflow run. + - You may not submit code that modifies files in `.github/workflows/`. Doing so will cause the submission to be rejected. If asked to modify workflow files, propose the change in a copy placed in a `github/` folder (without the leading period) and note in the PR that the file needs to be relocated by someone with workflow write access. + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + You are an agent for __GH_AW_GITHUB_REPOSITORY__. You run on a schedule to pick up an open issue and create a focused pull request that addresses it. Your specific assignment is described in the **Fix Assignment** section below. + + ## Context + + - **Repository**: __GH_AW_GITHUB_REPOSITORY__ + + ## Constraints + + - **CAN**: Read files, search code, modify files locally, run tests and commands, create a pull request. + - **CANNOT**: Directly push to the repository — use `create_pull_request`. + - **Only one PR per run.** + - If no suitable issue is found, call `noop` with a brief reason. + - **Most runs should end with `noop`.** Only open a PR when the fix is clearly correct, tested, and small enough for quick review. + + ## Process + + Follow these steps in order. + + ### Step 1: Gather Candidates + + 1. Call `generate_agents_md` to get the repository's coding guidelines and conventions. If this fails, continue without it. + 2. Follow the candidate gathering instructions in the **Fix Assignment** section. + 3. For each candidate, read the full issue and comments using `issue_read` (methods `get` and `get_comments`). + + ### Step 2: Select a Target + + Choose one issue with: + + - Concrete, actionable instructions (file paths, function names, suggested changes) + - A well-scoped fix that doesn't require design decisions + - No active discussion suggesting the fix should go a different direction + + Skip any issue where the suggested fix is ambiguous, controversial, or too large for a single PR. + + ### Step 3: Implement + + Follow the implementation instructions in the **Fix Assignment** section. The Fix Assignment defines: + - What kind of changes to make + - What tools to use + - Any domain-specific constraints + + ### Step 4: Quality Gate — Self-Review + + Before creating the PR, verify: + + 1. **Fix is correct** — the change directly addresses the issue. + 2. **Tests pass** — you ran the most relevant tests and they pass. + 3. **Scope is minimal** — only changes needed for the fix, no scope creep. + 4. **No regressions** — linters pass, no formatting broken, no new warnings. + + If any check fails, call `noop` with a brief reason. + + ### Step 5: Create the PR + + Call `create_pull_request` with: + - A concise summary of the changes + - A link to the source issue (e.g., "Fixes #123") + - The specific tests that were run and passed + - A note on any items from the issue that were skipped (if any) + + **Fix Assignment:** + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + ### Candidate Search + + Search for open issues matching the configured label or title prefix: + + ````text + github-search_issues: query="repo:{owner}/{repo} is:issue is:open (label:__GH_AW_EXPR_955E52F5__ OR in:title \"__GH_AW_EXPR_CE96317F__\") sort:updated-asc" + ```` + + ### Implementation + + __GH_AW_EXPR_49B959F1__ + + GH_AW_PROMPT_EOF + - name: Interpolate variables and render templates + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} + GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} + GH_AW_EXPR_955E52F5: ${{ inputs.issue-label }} + GH_AW_EXPR_CE96317F: ${{ inputs.issue-title-prefix }} + 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/interpolate_prompt.cjs'); + await main(); + - name: Substitute placeholders + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} + GH_AW_EXPR_955E52F5: ${{ inputs.issue-label }} + GH_AW_EXPR_CE96317F: ${{ inputs.issue-title-prefix }} + GH_AW_GITHUB_ACTOR: ${{ github.actor }} + GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} + GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} + GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} + 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'); + setupGlobals(core, github, context, exec, io); + + const substitutePlaceholders = require('/opt/gh-aw/actions/substitute_placeholders.cjs'); + + // Call the substitution function + return await substitutePlaceholders({ + file: process.env.GH_AW_PROMPT, + substitutions: { + GH_AW_EXPR_49B959F1: process.env.GH_AW_EXPR_49B959F1, + GH_AW_EXPR_955E52F5: process.env.GH_AW_EXPR_955E52F5, + GH_AW_EXPR_CE96317F: process.env.GH_AW_EXPR_CE96317F, + GH_AW_GITHUB_ACTOR: process.env.GH_AW_GITHUB_ACTOR, + GH_AW_GITHUB_EVENT_COMMENT_ID: process.env.GH_AW_GITHUB_EVENT_COMMENT_ID, + GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: process.env.GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER, + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: process.env.GH_AW_GITHUB_EVENT_ISSUE_NUMBER, + 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_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 + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + run: bash /opt/gh-aw/actions/validate_prompt_placeholders.sh + - name: Print prompt + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + run: bash /opt/gh-aw/actions/print_prompt_summary.sh + - name: Upload prompt artifact + if: success() + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: prompt + path: /tmp/gh-aw/aw-prompts/prompt.txt + retention-days: 1 + + agent: + needs: activation + runs-on: ubuntu-latest + permissions: + contents: read + issues: read + pull-requests: read + env: + DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} + GH_AW_ASSETS_ALLOWED_EXTS: "" + GH_AW_ASSETS_BRANCH: "" + GH_AW_ASSETS_MAX_SIZE_KB: 0 + GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs + 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: ghawscheduledfix + outputs: + checkout_pr_success: ${{ steps.checkout-pr.outputs.checkout_pr_success || 'true' }} + has_patch: ${{ steps.collect_output.outputs.has_patch }} + model: ${{ steps.generate_aw_info.outputs.model }} + output: ${{ steps.collect_output.outputs.output }} + output_types: ${{ steps.collect_output.outputs.output_types }} + secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 + with: + destination: /opt/gh-aw/actions + - name: Checkout repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + - name: Create gh-aw temp directory + run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh + - if: hashFiles('go.mod') != '' + name: Setup Go + uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5 + with: + cache: true + go-version-file: go.mod + - if: hashFiles('.python-version') != '' + name: Setup Python + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 + with: + python-version-file: .python-version + - if: hashFiles('.node-version') != '' + name: Setup Node.js (.node-version) + uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6 + with: + node-version-file: .node-version + - if: hashFiles('.node-version') == '' && hashFiles('.nvmrc') != '' + name: Setup Node.js (.nvmrc) + uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6 + with: + node-version-file: .nvmrc + - if: hashFiles('.ruby-version') != '' + name: Setup Ruby + uses: ruby/setup-ruby@09a7688d3b55cf0e976497ff046b70949eeaccfd # v1 + with: + bundler-cache: true + ruby-version: .ruby-version + - id: setup-uv + if: hashFiles('pyproject.toml', 'uv.lock') != '' + name: Setup uv + uses: astral-sh/setup-uv@e58605a9b6da7c637471fab8847a5e5a6b8df081 # v5 + - env: + UV_PATH: ${{ steps.setup-uv.outputs.uv-path }} + WORKSPACE: ${{ github.workspace }} + if: hashFiles('pyproject.toml', 'uv.lock') != '' + name: Expose uv in workspace + run: |- + set -euo pipefail + install_dir="$WORKSPACE/.gh-aw-tools/bin" + mkdir -p "$install_dir" + cp "$UV_PATH" "$install_dir/uv" + chmod +x "$install_dir/uv" + echo "$install_dir" >> "$GITHUB_PATH" + shell: bash + - env: + SETUP_COMMANDS: ${{ inputs.setup-commands }} + if: ${{ inputs.setup-commands != '' }} + name: Repo-specific setup + run: eval "$SETUP_COMMANDS" + + - name: Configure Git credentials + env: + REPO_NAME: ${{ github.repository }} + SERVER_URL: ${{ github.server_url }} + run: | + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git config --global user.name "github-actions[bot]" + # Re-authenticate git with GitHub token + SERVER_URL_STRIPPED="${SERVER_URL#https://}" + git remote set-url origin "https://x-access-token:${{ github.token }}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" + echo "Git configured with standard GitHub Actions identity" + - name: Checkout PR branch + id: checkout-pr + if: | + github.event.pull_request + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + with: + github-token: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/checkout_pr_branch.cjs'); + await main(); + - name: Generate agentic run info + id: generate_aw_info + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + with: + script: | + const fs = require('fs'); + + const awInfo = { + engine_id: "copilot", + engine_name: "GitHub Copilot CLI", + model: "${{ inputs.model }}", + version: "", + agent_version: "0.0.412", + workflow_name: "Scheduled Fix", + experimental: false, + supports_tools_allowlist: true, + run_id: context.runId, + run_number: context.runNumber, + run_attempt: process.env.GITHUB_RUN_ATTEMPT, + repository: context.repo.owner + '/' + context.repo.repo, + ref: context.ref, + sha: context.sha, + actor: context.actor, + event_name: context.eventName, + staged: false, + allowed_domains: ["agents-md-generator.fastmcp.app","artifacts.elastic.co","cloud.elastic.co","defaults","ela.st","elastic.co","github","go","node","public-code-search.fastmcp.app","python","ruby","www.elastic.co"], + firewall_enabled: true, + awf_version: "v0.20.2", + awmg_version: "v0.1.4", + steps: { + firewall: "squid" + }, + created_at: new Date().toISOString() + }; + + // Write to /tmp/gh-aw directory to avoid inclusion in PR + const tmpPath = '/tmp/gh-aw/aw_info.json'; + fs.writeFileSync(tmpPath, JSON.stringify(awInfo, null, 2)); + console.log('Generated aw_info.json at:', tmpPath); + console.log(JSON.stringify(awInfo, null, 2)); + + // Set model as output for reuse in other steps/jobs + core.setOutput('model', awInfo.model); + - name: Validate COPILOT_GITHUB_TOKEN secret + id: validate-secret + run: /opt/gh-aw/actions/validate_multi_secret.sh COPILOT_GITHUB_TOKEN 'GitHub Copilot CLI' https://github.github.com/gh-aw/reference/engines/#github-copilot-default + env: + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + - name: Install GitHub Copilot CLI + run: /opt/gh-aw/actions/install_copilot_cli.sh 0.0.412 + - name: Install awf binary + run: bash /opt/gh-aw/actions/install_awf_binary.sh v0.20.2 + - name: Determine automatic lockdown mode for GitHub MCP Server + id: determine-automatic-lockdown + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} + GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} + with: + script: | + 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.20.2 ghcr.io/github/gh-aw-firewall/api-proxy:0.20.2 ghcr.io/github/gh-aw-firewall/squid:0.20.2 ghcr.io/github/gh-aw-mcpg:v0.1.4 ghcr.io/github/github-mcp-server:v0.31.0 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' + {"create_pull_request":{"max":1},"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 pull request to propose code changes. Use this after making file edits to submit them for review and merging. The PR will be created from the current branch with your committed changes. For code review comments on an existing PR, use create_pull_request_review_comment instead. CONSTRAINTS: Maximum 1 pull request(s) can be created.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "body": { + "description": "Detailed PR description in Markdown. Include what changes were made, why, testing notes, and any breaking changes. Do NOT repeat the title as a heading.", + "type": "string" + }, + "branch": { + "description": "Source branch name containing the changes. If omitted, uses the current working branch.", + "type": "string" + }, + "draft": { + "description": "Whether to create the PR as a draft. Draft PRs cannot be merged until marked as ready for review. Use mark_pull_request_as_ready_for_review to convert a draft PR. Default: true.", + "type": "boolean" + }, + "labels": { + "description": "Labels to categorize the PR (e.g., 'enhancement', 'bugfix'). Labels must exist in the repository.", + "items": { + "type": "string" + }, + "type": "array" + }, + "title": { + "description": "Concise PR title describing the changes. Follow repository conventions (e.g., conventional commits). The title appears as the main heading.", + "type": "string" + } + }, + "required": [ + "title", + "body" + ], + "type": "object" + }, + "name": "create_pull_request" + }, + { + "description": "Report that a tool or capability needed to complete the task is not available, or share any information you deem important about missing functionality or limitations. Use this when you cannot accomplish what was requested because the required functionality is missing or access is restricted.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "alternatives": { + "description": "Any workarounds, manual steps, or alternative approaches the user could take (max 256 characters).", + "type": "string" + }, + "reason": { + "description": "Explanation of why this tool is needed or what information you want to share about the limitation (max 256 characters).", + "type": "string" + }, + "tool": { + "description": "Optional: Name or description of the missing tool or capability (max 128 characters). Be specific about what functionality is needed.", + "type": "string" + } + }, + "required": [ + "reason" + ], + "type": "object" + }, + "name": "missing_tool" + }, + { + "description": "Log a transparency message when no significant actions are needed. Use this to confirm workflow completion and provide visibility when analysis is complete but no changes or outputs are required (e.g., 'No issues found', 'All checks passed'). This ensures the workflow produces human-visible output even when no other actions are taken.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "message": { + "description": "Status or completion message to log. Should explain what was analyzed and the outcome (e.g., 'Code review complete - no issues found', 'Analysis complete - all tests passing').", + "type": "string" + } + }, + "required": [ + "message" + ], + "type": "object" + }, + "name": "noop" + }, + { + "description": "Report that data or information needed to complete the task is not available. Use this when you cannot accomplish what was requested because required data, context, or information is missing.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "alternatives": { + "description": "Any workarounds, manual steps, or alternative approaches the user could take (max 256 characters).", + "type": "string" + }, + "context": { + "description": "Additional context about the missing data or where it should come from (max 256 characters).", + "type": "string" + }, + "data_type": { + "description": "Type or description of the missing data or information (max 128 characters). Be specific about what data is needed.", + "type": "string" + }, + "reason": { + "description": "Explanation of why this data is needed to complete the task (max 256 characters).", + "type": "string" + } + }, + "required": [], + "type": "object" + }, + "name": "missing_data" + } + ] + GH_AW_SAFE_OUTPUTS_TOOLS_EOF + cat > /opt/gh-aw/safeoutputs/validation.json << 'GH_AW_SAFE_OUTPUTS_VALIDATION_EOF' + { + "create_pull_request": { + "defaultMax": 1, + "fields": { + "body": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "branch": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "draft": { + "type": "boolean" + }, + "labels": { + "type": "array", + "itemType": "string", + "itemSanitize": true, + "itemMaxLength": 128 + }, + "repo": { + "type": "string", + "maxLength": 256 + }, + "title": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 128 + } + } + }, + "missing_data": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "context": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "data_type": { + "type": "string", + "sanitize": true, + "maxLength": 128 + }, + "reason": { + "type": "string", + "sanitize": true, + "maxLength": 256 + } + } + }, + "missing_tool": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 512 + }, + "reason": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "tool": { + "type": "string", + "sanitize": true, + "maxLength": 128 + } + } + }, + "noop": { + "defaultMax": 1, + "fields": { + "message": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + } + } + } + } + GH_AW_SAFE_OUTPUTS_VALIDATION_EOF + - name: Generate Safe Outputs MCP Server Config + id: safe-outputs-config + run: | + # Generate a secure random API key (360 bits of entropy, 40+ chars) + # Mask immediately to prevent timing vulnerabilities + API_KEY=$(openssl rand -base64 45 | tr -d '/+=') + echo "::add-mask::${API_KEY}" + + PORT=3001 + + # Set outputs for next steps + { + echo "safe_outputs_api_key=${API_KEY}" + echo "safe_outputs_port=${PORT}" + } >> "$GITHUB_OUTPUT" + + echo "Safe Outputs MCP server will run on port ${PORT}" + + - name: Start Safe Outputs MCP HTTP Server + id: safe-outputs-start + env: + DEBUG: '*' + GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-config.outputs.safe_outputs_port }} + GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-config.outputs.safe_outputs_api_key }} + GH_AW_SAFE_OUTPUTS_TOOLS_PATH: /opt/gh-aw/safeoutputs/tools.json + GH_AW_SAFE_OUTPUTS_CONFIG_PATH: /opt/gh-aw/safeoutputs/config.json + GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs + run: | + # Environment variables are set above to prevent template injection + export DEBUG + export GH_AW_SAFE_OUTPUTS_PORT + export GH_AW_SAFE_OUTPUTS_API_KEY + export GH_AW_SAFE_OUTPUTS_TOOLS_PATH + export GH_AW_SAFE_OUTPUTS_CONFIG_PATH + export GH_AW_MCP_LOG_DIR + + bash /opt/gh-aw/actions/start_safe_outputs_server.sh + + - name: Setup Safe Inputs Config + run: | + mkdir -p /opt/gh-aw/safe-inputs/logs + cat > /opt/gh-aw/safe-inputs/tools.json << 'GH_AW_SAFE_INPUTS_TOOLS_EOF' + { + "serverName": "safeinputs", + "version": "1.0.0", + "logDir": "/opt/gh-aw/safe-inputs/logs", + "tools": [ + { + "name": "ready-to-make-pr", + "description": "Run the PR readiness checklist before creating or updating a PR", + "inputSchema": { + "properties": {}, + "type": "object" + }, + "handler": "ready-to-make-pr.cjs", + "timeout": 60 + } + ] + } + GH_AW_SAFE_INPUTS_TOOLS_EOF + cat > /opt/gh-aw/safe-inputs/mcp-server.cjs << 'GH_AW_SAFE_INPUTS_SERVER_EOF' + const path = require("path"); + const { startHttpServer } = require("./safe_inputs_mcp_server_http.cjs"); + const configPath = path.join(__dirname, "tools.json"); + const port = parseInt(process.env.GH_AW_SAFE_INPUTS_PORT || "3000", 10); + const apiKey = process.env.GH_AW_SAFE_INPUTS_API_KEY || ""; + startHttpServer(configPath, { + port: port, + stateless: true, + logDir: "/opt/gh-aw/safe-inputs/logs" + }).catch(error => { + console.error("Failed to start safe-inputs HTTP server:", error); + process.exit(1); + }); + GH_AW_SAFE_INPUTS_SERVER_EOF + chmod +x /opt/gh-aw/safe-inputs/mcp-server.cjs + + - name: Setup Safe Inputs Tool Files + run: | + cat > /opt/gh-aw/safe-inputs/ready-to-make-pr.cjs << 'GH_AW_SAFE_INPUTS_JS_READY-TO-MAKE-PR_EOF' + async function execute(inputs) { + const fs = require('fs'); + const find = (...paths) => paths.find(p => fs.existsSync(p)) || null; + const contributing = find('CONTRIBUTING.md', 'CONTRIBUTING.rst', 'docs/CONTRIBUTING.md', 'docs/contributing.md'); + const prTemplate = find('.github/pull_request_template.md', '.github/PULL_REQUEST_TEMPLATE.md', '.github/PULL_REQUEST_TEMPLATE/pull_request_template.md'); + const checklist = []; + if (contributing) checklist.push(`Review the contributing guide (${contributing}) before opening or updating a PR.`); + if (prTemplate) checklist.push(`Follow the PR template (${prTemplate}) for title, description, and validation notes.`); + checklist.push('Confirm the requested task is fully completed and validated before creating or pushing PR changes.'); + return { status: 'ok', checklist, contributing_guide: contributing, pr_template: prTemplate }; + } + module.exports = { execute }; + GH_AW_SAFE_INPUTS_JS_READY-TO-MAKE-PR_EOF + + - name: Generate Safe Inputs MCP Server Config + id: safe-inputs-config + run: | + # Generate a secure random API key (360 bits of entropy, 40+ chars) + # Mask immediately to prevent timing vulnerabilities + API_KEY=$(openssl rand -base64 45 | tr -d '/+=') + echo "::add-mask::${API_KEY}" + + PORT=3000 + + # Set outputs for next steps + { + echo "safe_inputs_api_key=${API_KEY}" + echo "safe_inputs_port=${PORT}" + } >> "$GITHUB_OUTPUT" + + echo "Safe Inputs MCP server will run on port ${PORT}" + + - name: Start Safe Inputs MCP HTTP Server + id: safe-inputs-start + env: + DEBUG: '*' + GH_AW_SAFE_INPUTS_PORT: ${{ steps.safe-inputs-config.outputs.safe_inputs_port }} + GH_AW_SAFE_INPUTS_API_KEY: ${{ steps.safe-inputs-config.outputs.safe_inputs_api_key }} + run: | + # Environment variables are set above to prevent template injection + export DEBUG + export GH_AW_SAFE_INPUTS_PORT + export GH_AW_SAFE_INPUTS_API_KEY + + bash /opt/gh-aw/actions/start_safe_inputs_server.sh + + - name: Start MCP Gateway + id: start-mcp-gateway + env: + GH_AW_SAFE_INPUTS_API_KEY: ${{ steps.safe-inputs-start.outputs.api_key }} + GH_AW_SAFE_INPUTS_PORT: ${{ steps.safe-inputs-start.outputs.port }} + GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} + GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-start.outputs.api_key }} + GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-start.outputs.port }} + GITHUB_MCP_LOCKDOWN: ${{ steps.determine-automatic-lockdown.outputs.lockdown == 'true' && '1' || '0' }} + GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + run: | + set -eo pipefail + mkdir -p /tmp/gh-aw/mcp-config + + # Export gateway environment variables for MCP config and gateway script + export MCP_GATEWAY_PORT="80" + export MCP_GATEWAY_DOMAIN="host.docker.internal" + MCP_GATEWAY_API_KEY=$(openssl rand -base64 45 | tr -d '/+=') + echo "::add-mask::${MCP_GATEWAY_API_KEY}" + export MCP_GATEWAY_API_KEY + export MCP_GATEWAY_PAYLOAD_DIR="/tmp/gh-aw/mcp-payloads" + mkdir -p "${MCP_GATEWAY_PAYLOAD_DIR}" + export DEBUG="*" + + export GH_AW_ENGINE="copilot" + 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 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_LOCKDOWN -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_INPUTS_PORT -e GH_AW_SAFE_INPUTS_API_KEY -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.1.4' + + mkdir -p /home/runner/.copilot + cat << GH_AW_MCP_CONFIG_EOF | bash /opt/gh-aw/actions/start_mcp_gateway.sh + { + "mcpServers": { + "agents-md-generator": { + "type": "http", + "url": "https://agents-md-generator.fastmcp.app/mcp", + "tools": [ + "generate_agents_md" + ] + }, + "github": { + "type": "stdio", + "container": "ghcr.io/github/github-mcp-server:v0.31.0", + "env": { + "GITHUB_LOCKDOWN_MODE": "$GITHUB_MCP_LOCKDOWN", + "GITHUB_PERSONAL_ACCESS_TOKEN": "\${GITHUB_MCP_SERVER_TOKEN}", + "GITHUB_READ_ONLY": "1", + "GITHUB_TOOLSETS": "repos,issues,pull_requests,search" + } + }, + "public-code-search": { + "type": "http", + "url": "https://public-code-search.fastmcp.app/mcp", + "tools": [ + "search_code" + ] + }, + "safeinputs": { + "type": "http", + "url": "http://host.docker.internal:$GH_AW_SAFE_INPUTS_PORT", + "headers": { + "Authorization": "\${GH_AW_SAFE_INPUTS_API_KEY}" + } + }, + "safeoutputs": { + "type": "http", + "url": "http://host.docker.internal:$GH_AW_SAFE_OUTPUTS_PORT", + "headers": { + "Authorization": "\${GH_AW_SAFE_OUTPUTS_API_KEY}" + } + } + }, + "gateway": { + "port": $MCP_GATEWAY_PORT, + "domain": "${MCP_GATEWAY_DOMAIN}", + "apiKey": "${MCP_GATEWAY_API_KEY}", + "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" + } + } + GH_AW_MCP_CONFIG_EOF + - name: Generate workflow overview + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + with: + script: | + const { generateWorkflowOverview } = require('/opt/gh-aw/actions/generate_workflow_overview.cjs'); + await generateWorkflowOverview(core); + - name: Download prompt artifact + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 + with: + name: prompt + path: /tmp/gh-aw/aw-prompts + - name: Clean git credentials + run: bash /opt/gh-aw/actions/clean_git_credentials.sh + - name: Execute GitHub Copilot CLI + id: agentic_execution + # Copilot CLI tool arguments (sorted): + timeout-minutes: 90 + run: | + set -o pipefail + sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --allow-domains '*.githubusercontent.com,*.jsr.io,*.pythonhosted.org,*.rvm.io,agents-md-generator.fastmcp.app,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.rubygems.org,api.snapcraft.io,archive.ubuntu.com,artifacts.elastic.co,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,bun.sh,bundler.rubygems.org,cache.ruby-lang.org,cdn.jsdelivr.net,cloud.elastic.co,codeload.github.com,conda.anaconda.org,conda.binstar.org,crates.io,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,deb.nodesource.com,deno.land,ela.st,elastic.co,esm.sh,files.pythonhosted.org,gems.rubyforge.org,gems.rubyonrails.org,get.pnpm.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,host.docker.internal,index.crates.io,index.rubygems.org,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,lfs.github.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,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,pip.pypa.io,pkg.go.dev,ppa.launchpad.net,proxy.golang.org,public-code-search.fastmcp.app,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.bower.io,registry.npmjs.com,registry.npmjs.org,registry.yarnpkg.com,repo.anaconda.com,repo.continuum.io,repo.yarnpkg.com,rubygems.org,rubygems.pkg.github.com,s.symcb.com,s.symcd.com,security.ubuntu.com,skimdb.npmjs.com,static.crates.io,storage.googleapis.com,sum.golang.org,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.elastic.co,www.npmjs.com,www.npmjs.org,yarnpkg.com' --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.20.2 --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 --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log + env: + COPILOT_AGENT_RUNNER_TYPE: STANDALONE + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} + GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} + GITHUB_HEAD_REF: ${{ github.head_ref }} + GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + GITHUB_REF_NAME: ${{ github.ref_name }} + GITHUB_STEP_SUMMARY: ${{ env.GITHUB_STEP_SUMMARY }} + GITHUB_WORKSPACE: ${{ github.workspace }} + XDG_CONFIG_HOME: /home/runner + - name: Configure Git credentials + env: + REPO_NAME: ${{ github.repository }} + SERVER_URL: ${{ github.server_url }} + run: | + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git config --global user.name "github-actions[bot]" + # Re-authenticate git with GitHub token + SERVER_URL_STRIPPED="${SERVER_URL#https://}" + git remote set-url origin "https://x-access-token:${{ github.token }}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" + echo "Git configured with standard GitHub Actions identity" + - name: Copy Copilot session state files to logs + if: always() + continue-on-error: true + run: | + # Copy Copilot session state files to logs folder for artifact collection + # This ensures they are in /tmp/gh-aw/ where secret redaction can scan them + SESSION_STATE_DIR="$HOME/.copilot/session-state" + LOGS_DIR="/tmp/gh-aw/sandbox/agent/logs" + + if [ -d "$SESSION_STATE_DIR" ]; then + echo "Copying Copilot session state files from $SESSION_STATE_DIR to $LOGS_DIR" + mkdir -p "$LOGS_DIR" + cp -v "$SESSION_STATE_DIR"/*.jsonl "$LOGS_DIR/" 2>/dev/null || true + echo "Session state files copied successfully" + else + echo "No session-state directory found at $SESSION_STATE_DIR" + fi + - name: Stop MCP Gateway + if: always() + continue-on-error: true + env: + MCP_GATEWAY_PORT: ${{ steps.start-mcp-gateway.outputs.gateway-port }} + MCP_GATEWAY_API_KEY: ${{ steps.start-mcp-gateway.outputs.gateway-api-key }} + GATEWAY_PID: ${{ steps.start-mcp-gateway.outputs.gateway-pid }} + run: | + bash /opt/gh-aw/actions/stop_mcp_gateway.sh "$GATEWAY_PID" + - name: Redact secrets in logs + if: always() + 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/redact_secrets.cjs'); + await main(); + env: + GH_AW_SECRET_NAMES: 'COPILOT_GITHUB_TOKEN,GH_AW_GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,GITHUB_TOKEN' + SECRET_COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + SECRET_GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} + SECRET_GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} + SECRET_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Upload Safe Outputs + if: always() + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: safe-output + path: ${{ env.GH_AW_SAFE_OUTPUTS }} + if-no-files-found: warn + - name: Ingest agent output + id: collect_output + if: always() + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} + GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,*.jsr.io,*.pythonhosted.org,*.rvm.io,agents-md-generator.fastmcp.app,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.rubygems.org,api.snapcraft.io,archive.ubuntu.com,artifacts.elastic.co,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,bun.sh,bundler.rubygems.org,cache.ruby-lang.org,cdn.jsdelivr.net,cloud.elastic.co,codeload.github.com,conda.anaconda.org,conda.binstar.org,crates.io,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,deb.nodesource.com,deno.land,ela.st,elastic.co,esm.sh,files.pythonhosted.org,gems.rubyforge.org,gems.rubyonrails.org,get.pnpm.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,host.docker.internal,index.crates.io,index.rubygems.org,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,lfs.github.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,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,pip.pypa.io,pkg.go.dev,ppa.launchpad.net,proxy.golang.org,public-code-search.fastmcp.app,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.bower.io,registry.npmjs.com,registry.npmjs.org,registry.yarnpkg.com,repo.anaconda.com,repo.continuum.io,repo.yarnpkg.com,rubygems.org,rubygems.pkg.github.com,s.symcb.com,s.symcd.com,security.ubuntu.com,skimdb.npmjs.com,static.crates.io,storage.googleapis.com,sum.golang.org,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.elastic.co,www.npmjs.com,www.npmjs.org,yarnpkg.com" + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_API_URL: ${{ github.api_url }} + 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/collect_ndjson_output.cjs'); + await main(); + - name: Upload sanitized agent output + if: always() && env.GH_AW_AGENT_OUTPUT + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: agent-output + path: ${{ env.GH_AW_AGENT_OUTPUT }} + if-no-files-found: warn + - name: Upload engine output files + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: agent_outputs + path: | + /tmp/gh-aw/sandbox/agent/logs/ + /tmp/gh-aw/redacted-urls.log + if-no-files-found: ignore + - name: Parse agent logs for step summary + if: always() + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: /tmp/gh-aw/sandbox/agent/logs/ + 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/parse_copilot_log.cjs'); + await main(); + - name: Parse Safe Inputs logs for step summary + if: always() + 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/parse_safe_inputs_logs.cjs'); + await main(); + - name: Parse MCP Gateway logs for step summary + if: always() + 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/parse_mcp_gateway_log.cjs'); + await main(); + - name: Print firewall logs + if: always() + continue-on-error: true + env: + AWF_LOGS_DIR: /tmp/gh-aw/sandbox/firewall/logs + run: | + # Fix permissions on firewall logs so they can be uploaded as artifacts + # AWF runs with sudo, creating files owned by root + sudo chmod -R a+r /tmp/gh-aw/sandbox/firewall/logs 2>/dev/null || true + # Only run awf logs summary if awf command exists (it may not be installed if workflow failed before install step) + if command -v awf &> /dev/null; then + awf logs summary | tee -a "$GITHUB_STEP_SUMMARY" + else + echo 'AWF binary not installed, skipping firewall log summary' + fi + - name: Upload agent artifacts + if: always() + continue-on-error: true + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: agent-artifacts + path: | + /tmp/gh-aw/aw-prompts/prompt.txt + /tmp/gh-aw/aw_info.json + /tmp/gh-aw/mcp-logs/ + /tmp/gh-aw/safe-inputs/logs/ + /tmp/gh-aw/sandbox/firewall/logs/ + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/agent/ + /tmp/gh-aw/aw-*.patch + if-no-files-found: ignore + + conclusion: + needs: + - activation + - agent + - detection + - safe_outputs + if: (always()) && (needs.agent.result != 'skipped') + runs-on: ubuntu-slim + permissions: + contents: write + issues: write + pull-requests: write + outputs: + noop_message: ${{ steps.noop.outputs.noop_message }} + tools_reported: ${{ steps.missing_tool.outputs.tools_reported }} + total_count: ${{ steps.missing_tool.outputs.total_count }} + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 + with: + destination: /opt/gh-aw/actions + - name: Download agent output artifact + continue-on-error: true + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 + with: + name: agent-output + path: /tmp/gh-aw/safeoutputs/ + - name: Setup agent output environment variable + run: | + mkdir -p /tmp/gh-aw/safeoutputs/ + find "/tmp/gh-aw/safeoutputs/" -type f -print + echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/safeoutputs/agent_output.json" >> "$GITHUB_ENV" + - name: Process No-Op Messages + id: noop + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_NOOP_MAX: 1 + GH_AW_WORKFLOW_NAME: "Scheduled Fix" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/noop.cjs'); + await main(); + - name: Record Missing Tool + id: missing_tool + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_WORKFLOW_NAME: "Scheduled Fix" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/missing_tool.cjs'); + await main(); + - name: Handle Agent Failure + id: handle_agent_failure + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_WORKFLOW_NAME: "Scheduled Fix" + 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: "gh-aw-scheduled-fix" + GH_AW_SECRET_VERIFICATION_RESULT: ${{ needs.agent.outputs.secret_verification_result }} + GH_AW_CHECKOUT_PR_SUCCESS: ${{ needs.agent.outputs.checkout_pr_success }} + GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\"}" + GH_AW_GROUP_REPORTS: "false" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/handle_agent_failure.cjs'); + await main(); + - name: Handle No-Op Message + id: handle_noop_message + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_WORKFLOW_NAME: "Scheduled Fix" + 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 }} + GH_AW_NOOP_REPORT_AS_ISSUE: "true" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/handle_noop_message.cjs'); + await main(); + - name: Handle Create Pull Request Error + id: handle_create_pr_error + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_WORKFLOW_NAME: "Scheduled Fix" + GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/handle_create_pr_error.cjs'); + await main(); + + detection: + needs: agent + if: needs.agent.outputs.output_types != '' || needs.agent.outputs.has_patch == 'true' + runs-on: ubuntu-latest + permissions: {} + timeout-minutes: 10 + outputs: + success: ${{ steps.parse_results.outputs.success }} + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 + with: + destination: /opt/gh-aw/actions + - name: Download agent artifacts + continue-on-error: true + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 + with: + name: agent-artifacts + path: /tmp/gh-aw/threat-detection/ + - name: Download agent output artifact + continue-on-error: true + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 + with: + name: agent-output + path: /tmp/gh-aw/threat-detection/ + - name: Print agent output types + env: + AGENT_OUTPUT_TYPES: ${{ needs.agent.outputs.output_types }} + run: | + echo "Agent output-types: $AGENT_OUTPUT_TYPES" + - name: Setup threat detection + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + WORKFLOW_NAME: "Scheduled Fix" + WORKFLOW_DESCRIPTION: "Generic scheduled fixer — pick up an open issue and create a focused PR that addresses it" + HAS_PATCH: ${{ needs.agent.outputs.has_patch }} + 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/setup_threat_detection.cjs'); + await main(); + - name: Ensure threat-detection directory and log + run: | + mkdir -p /tmp/gh-aw/threat-detection + touch /tmp/gh-aw/threat-detection/detection.log + - name: Validate COPILOT_GITHUB_TOKEN secret + id: validate-secret + run: /opt/gh-aw/actions/validate_multi_secret.sh COPILOT_GITHUB_TOKEN 'GitHub Copilot CLI' https://github.github.com/gh-aw/reference/engines/#github-copilot-default + env: + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + - name: Install GitHub Copilot CLI + run: /opt/gh-aw/actions/install_copilot_cli.sh 0.0.412 + - name: Execute GitHub Copilot CLI + id: agentic_execution + # Copilot CLI tool arguments (sorted): + # --allow-tool shell(cat) + # --allow-tool shell(grep) + # --allow-tool shell(head) + # --allow-tool shell(jq) + # --allow-tool shell(ls) + # --allow-tool shell(tail) + # --allow-tool shell(wc) + timeout-minutes: 20 + run: | + set -o pipefail + COPILOT_CLI_INSTRUCTION="$(cat /tmp/gh-aw/aw-prompts/prompt.txt)" + mkdir -p /tmp/ + mkdir -p /tmp/gh-aw/ + mkdir -p /tmp/gh-aw/agent/ + mkdir -p /tmp/gh-aw/sandbox/agent/logs/ + copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log + env: + COPILOT_AGENT_RUNNER_TYPE: STANDALONE + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GITHUB_HEAD_REF: ${{ github.head_ref }} + GITHUB_REF_NAME: ${{ github.ref_name }} + GITHUB_STEP_SUMMARY: ${{ env.GITHUB_STEP_SUMMARY }} + GITHUB_WORKSPACE: ${{ github.workspace }} + XDG_CONFIG_HOME: /home/runner + - name: Parse threat detection results + id: parse_results + 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/parse_threat_detection_results.cjs'); + await main(); + - name: Upload threat detection log + if: always() + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: threat-detection.log + path: /tmp/gh-aw/threat-detection/detection.log + if-no-files-found: ignore + + pre_activation: + runs-on: ubuntu-slim + outputs: + activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 + with: + destination: /opt/gh-aw/actions + - name: Check team membership for workflow + id: check_membership + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_REQUIRED_ROLES: admin,maintainer,write + GH_AW_ALLOWED_BOTS: ${{ inputs.allowed-bot-users }} + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + 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_membership.cjs'); + await main(); + + safe_outputs: + needs: + - activation + - agent + - detection + if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (needs.detection.outputs.success == 'true') + runs-on: ubuntu-slim + permissions: + contents: write + issues: write + pull-requests: write + timeout-minutes: 15 + env: + GH_AW_ENGINE_ID: "copilot" + GH_AW_ENGINE_MODEL: "${{ inputs.model }}" + GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\"}" + GH_AW_WORKFLOW_ID: "gh-aw-scheduled-fix" + GH_AW_WORKFLOW_NAME: "Scheduled Fix" + outputs: + create_discussion_error_count: ${{ steps.process_safe_outputs.outputs.create_discussion_error_count }} + create_discussion_errors: ${{ steps.process_safe_outputs.outputs.create_discussion_errors }} + process_safe_outputs_processed_count: ${{ steps.process_safe_outputs.outputs.processed_count }} + process_safe_outputs_temporary_id_map: ${{ steps.process_safe_outputs.outputs.temporary_id_map }} + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 + with: + destination: /opt/gh-aw/actions + - name: Download agent output artifact + continue-on-error: true + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 + with: + name: agent-output + path: /tmp/gh-aw/safeoutputs/ + - name: Setup agent output environment variable + run: | + mkdir -p /tmp/gh-aw/safeoutputs/ + find "/tmp/gh-aw/safeoutputs/" -type f -print + echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/safeoutputs/agent_output.json" >> "$GITHUB_ENV" + - name: Download patch artifact + continue-on-error: true + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 + with: + name: agent-artifacts + path: /tmp/gh-aw/ + - name: Checkout repository + if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + ref: ${{ github.base_ref || github.ref_name }} + token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + persist-credentials: false + fetch-depth: 1 + - name: Configure Git credentials + if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) + env: + REPO_NAME: ${{ github.repository }} + SERVER_URL: ${{ github.server_url }} + GIT_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + run: | + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git config --global user.name "github-actions[bot]" + # Re-authenticate git with GitHub token + SERVER_URL_STRIPPED="${SERVER_URL#https://}" + git remote set-url origin "https://x-access-token:${GIT_TOKEN}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" + echo "Git configured with standard GitHub Actions identity" + - name: Process Safe Outputs + id: process_safe_outputs + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_pull_request\":{\"base_branch\":\"${{ github.base_ref || github.ref_name }}\",\"max\":1,\"max_patch_size\":1024},\"missing_data\":{},\"missing_tool\":{}}" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/safe_output_handler_manager.cjs'); + await main(); + - name: Upload safe output items manifest + if: always() + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: safe-output-items + path: /tmp/safe-output-items.jsonl + if-no-files-found: warn + diff --git a/.github/workflows/gh-aw-scheduled-fix.md b/.github/workflows/gh-aw-scheduled-fix.md new file mode 100644 index 00000000..2292728d --- /dev/null +++ b/.github/workflows/gh-aw-scheduled-fix.md @@ -0,0 +1,107 @@ +--- +inlined-imports: true +name: "Scheduled Fix" +description: "Generic scheduled fixer — pick up an open issue and create a focused PR that addresses it" +imports: + - gh-aw-fragments/elastic-tools.md + - gh-aw-fragments/runtime-setup.md + - gh-aw-fragments/formatting.md + - gh-aw-fragments/rigor.md + - gh-aw-fragments/mcp-pagination.md + - gh-aw-fragments/workflow-edit-guardrails.md + - gh-aw-fragments/messages-footer.md + - gh-aw-fragments/safe-output-create-pr.md + - gh-aw-fragments/scheduled-fix.md +engine: + id: copilot + model: ${{ inputs.model }} +on: + workflow_call: + inputs: + model: + description: "AI model to use" + type: string + required: false + default: "gpt-5.3-codex" + additional-instructions: + description: "Domain-specific fix instructions — appended as the Fix Assignment" + type: string + required: true + issue-title-prefix: + description: "Title prefix to search for in open issues, e.g. '[text-auditor]'" + type: string + required: true + issue-label: + description: "Label to search for in open issues" + type: string + required: false + default: "" + setup-commands: + description: "Shell commands to run before the agent starts (dependency install, build, etc.)" + type: string + required: false + default: "" + allowed-bot-users: + description: "Allowlisted bot actor usernames (comma-separated)" + type: string + required: false + default: "github-actions[bot]" + messages-footer: + description: "Footer appended to all agent comments and reviews" + type: string + required: false + default: "" + draft-prs: + description: "Create PRs as draft (true/false)" + type: string + required: false + default: "true" + secrets: + COPILOT_GITHUB_TOKEN: + required: true + roles: [admin, maintainer, write] + bots: + - "${{ inputs.allowed-bot-users }}" +concurrency: + group: scheduled-fix-${{ inputs.issue-title-prefix }} + cancel-in-progress: true +permissions: + contents: read + issues: read + pull-requests: read +tools: + github: + toolsets: [repos, issues, pull_requests, search] + bash: true + web-fetch: +network: + allowed: + - defaults + - github + - go + - node + - python + - ruby +strict: false +safe-outputs: + noop: +timeout-minutes: 90 +steps: + - name: Repo-specific setup + if: ${{ inputs.setup-commands != '' }} + env: + SETUP_COMMANDS: ${{ inputs.setup-commands }} + run: eval "$SETUP_COMMANDS" +--- + +### Candidate Search + +Search for open issues matching the configured label or title prefix: + +````text +github-search_issues: query="repo:{owner}/{repo} is:issue is:open (label:${{ inputs.issue-label }} OR in:title \"${{ inputs.issue-title-prefix }}\") sort:updated-asc" +```` + +### Implementation + +${{ inputs.additional-instructions }} diff --git a/.github/workflows/gh-aw-small-problem-fixer.lock.yml b/.github/workflows/gh-aw-small-problem-fixer.lock.yml index 11b9d50e..0e32ace0 100644 --- a/.github/workflows/gh-aw-small-problem-fixer.lock.yml +++ b/.github/workflows/gh-aw-small-problem-fixer.lock.yml @@ -34,7 +34,9 @@ # - gh-aw-fragments/safe-output-create-pr.md # - gh-aw-fragments/workflow-edit-guardrails.md # -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"3605fb74690b61bcb927f31df70d9965e422118e085eaf5a577e1fc04272dd2b"} +# inlined-imports: true +# +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"c334fb0e60093333f671503d27e5637a6aca797b4056d8292aa1201fdc385cff"} name: "Small Problem Fixer" "on": @@ -61,6 +63,11 @@ name: "Small Problem Fixer" description: Footer appended to all agent comments and reviews required: false type: string + model: + default: gpt-5.3-codex + description: AI model to use + required: false + type: string setup-commands: default: "" description: Shell commands to run before the agent starts (dependency install, build, etc.) @@ -90,7 +97,7 @@ jobs: comment_repo: "" steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Validate context variables @@ -167,6 +174,30 @@ jobs: **Critical**: Tool calls write structured data that downstream jobs process. Without tool calls, follow-up actions will be skipped. **Note**: If you made no other safe output tool calls during this workflow execution, call the "noop" tool to provide a status message indicating completion or that no actions were needed. + + --- + + ## Creating a Pull Request, Reporting Missing Tools or Functionality, Reporting Missing Data + + **IMPORTANT**: To perform the actions listed above, use the **safeoutputs** tools. Do NOT use `gh`, do NOT call the GitHub API directly. You do not have write access to the GitHub repository. + + **Creating a Pull Request** + + To create a pull request: + 1. Make any file changes directly in the working directory. + 2. If you haven't done so already, create a local branch using an appropriate unique name. + 3. Add and commit your changes to the branch. Be careful to add exactly the files you intend, and check there are no extra files left un-added. Verify you haven't deleted or changed any files you didn't intend to. + 4. Do not push your changes. That will be done by the tool. + 5. Create the pull request with the create_pull_request tool from safeoutputs. + + **Reporting Missing Tools or Functionality** + + To report a missing tool or capability, use the missing_tool tool from safeoutputs. + + **Reporting Missing Data** + + To report missing data required to achieve a goal, use the missing_data tool from safeoutputs. + @@ -472,7 +503,7 @@ jobs: secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Checkout repository @@ -566,7 +597,7 @@ jobs: const awInfo = { engine_id: "copilot", engine_name: "GitHub Copilot CLI", - model: "gpt-5.3-codex", + model: "${{ inputs.model }}", version: "", agent_version: "0.0.412", workflow_name: "Small Problem Fixer", @@ -626,7 +657,7 @@ jobs: 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' - {"create_pull_request":{},"missing_data":{},"missing_tool":{},"noop":{"max":1}} + {"create_pull_request":{"max":1},"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' [ @@ -643,6 +674,10 @@ jobs: "description": "Source branch name containing the changes. If omitted, uses the current working branch.", "type": "string" }, + "draft": { + "description": "Whether to create the PR as a draft. Draft PRs cannot be merged until marked as ready for review. Use mark_pull_request_as_ready_for_review to convert a draft PR. Default: true.", + "type": "boolean" + }, "labels": { "description": "Labels to categorize the PR (e.g., 'enhancement', 'bugfix'). Labels must exist in the repository.", "items": { @@ -751,12 +786,19 @@ jobs: "sanitize": true, "maxLength": 256 }, + "draft": { + "type": "boolean" + }, "labels": { "type": "array", "itemType": "string", "itemSanitize": true, "itemMaxLength": 128 }, + "repo": { + "type": "string", + "maxLength": 256 + }, "title": { "required": true, "type": "string", @@ -765,6 +807,31 @@ jobs: } } }, + "missing_data": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "context": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "data_type": { + "type": "string", + "sanitize": true, + "maxLength": 128 + }, + "reason": { + "type": "string", + "sanitize": true, + "maxLength": 256 + } + } + }, "missing_tool": { "defaultMax": 20, "fields": { @@ -1023,10 +1090,11 @@ jobs: run: | set -o pipefail sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --allow-domains '*.githubusercontent.com,*.jsr.io,*.pythonhosted.org,*.rvm.io,agents-md-generator.fastmcp.app,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.rubygems.org,api.snapcraft.io,archive.ubuntu.com,artifacts.elastic.co,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,bun.sh,bundler.rubygems.org,cache.ruby-lang.org,cdn.jsdelivr.net,cloud.elastic.co,codeload.github.com,conda.anaconda.org,conda.binstar.org,crates.io,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,deb.nodesource.com,deno.land,ela.st,elastic.co,esm.sh,files.pythonhosted.org,gems.rubyforge.org,gems.rubyonrails.org,get.pnpm.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,host.docker.internal,index.crates.io,index.rubygems.org,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,lfs.github.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,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,pip.pypa.io,pkg.go.dev,ppa.launchpad.net,proxy.golang.org,public-code-search.fastmcp.app,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.bower.io,registry.npmjs.com,registry.npmjs.org,registry.yarnpkg.com,repo.anaconda.com,repo.continuum.io,repo.yarnpkg.com,rubygems.org,rubygems.pkg.github.com,s.symcb.com,s.symcd.com,security.ubuntu.com,skimdb.npmjs.com,static.crates.io,storage.googleapis.com,sum.golang.org,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.elastic.co,www.npmjs.com,www.npmjs.org,yarnpkg.com' --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.20.2 --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 --model gpt-5.3-codex --allow-all-tools --allow-all-paths --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log + -- /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 --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} @@ -1183,7 +1251,7 @@ jobs: /tmp/gh-aw/sandbox/firewall/logs/ /tmp/gh-aw/agent-stdio.log /tmp/gh-aw/agent/ - /tmp/gh-aw/aw.patch + /tmp/gh-aw/aw-*.patch if-no-files-found: ignore conclusion: @@ -1204,7 +1272,7 @@ jobs: total_count: ${{ steps.missing_tool.outputs.total_count }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent output artifact @@ -1309,7 +1377,7 @@ jobs: success: ${{ steps.parse_results.outputs.success }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent artifacts @@ -1370,10 +1438,11 @@ jobs: mkdir -p /tmp/gh-aw/ mkdir -p /tmp/gh-aw/agent/ mkdir -p /tmp/gh-aw/sandbox/agent/logs/ - copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --model gpt-5.3-codex --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log + copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_REF_NAME: ${{ github.ref_name }} @@ -1403,7 +1472,7 @@ jobs: activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Check team membership for workflow @@ -1434,7 +1503,7 @@ jobs: timeout-minutes: 15 env: GH_AW_ENGINE_ID: "copilot" - GH_AW_ENGINE_MODEL: "gpt-5.3-codex" + GH_AW_ENGINE_MODEL: "${{ inputs.model }}" GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\"}" GH_AW_WORKFLOW_ID: "gh-aw-small-problem-fixer" GH_AW_WORKFLOW_NAME: "Small Problem Fixer" @@ -1445,7 +1514,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@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent output artifact @@ -1469,7 +1538,7 @@ jobs: if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: - ref: ${{ github.ref_name }} + ref: ${{ github.base_ref || github.ref_name }} token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} persist-credentials: false fetch-depth: 1 @@ -1491,7 +1560,7 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_pull_request\":{\"base_branch\":\"${{ github.ref_name }}\",\"max\":1,\"max_patch_size\":1024},\"missing_data\":{},\"missing_tool\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_pull_request\":{\"base_branch\":\"${{ github.base_ref || github.ref_name }}\",\"max\":1,\"max_patch_size\":1024},\"missing_data\":{},\"missing_tool\":{}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/gh-aw-small-problem-fixer.md b/.github/workflows/gh-aw-small-problem-fixer.md index ac97748b..d1f19979 100644 --- a/.github/workflows/gh-aw-small-problem-fixer.md +++ b/.github/workflows/gh-aw-small-problem-fixer.md @@ -1,4 +1,5 @@ --- +inlined-imports: true description: "Find small, related issues and open a focused PR" imports: - gh-aw-fragments/elastic-tools.md @@ -11,10 +12,15 @@ imports: - gh-aw-fragments/safe-output-create-pr.md engine: id: copilot - model: gpt-5.3-codex + model: ${{ inputs.model }} on: workflow_call: inputs: + model: + description: "AI model to use" + type: string + required: false + default: "gpt-5.3-codex" additional-instructions: description: "Repo-specific instructions appended to the agent prompt" type: string diff --git a/.github/workflows/gh-aw-stale-issues.lock.yml b/.github/workflows/gh-aw-stale-issues.lock.yml index ef812311..854eafbf 100644 --- a/.github/workflows/gh-aw-stale-issues.lock.yml +++ b/.github/workflows/gh-aw-stale-issues.lock.yml @@ -32,9 +32,11 @@ # - gh-aw-fragments/rigor.md # - gh-aw-fragments/runtime-setup.md # - gh-aw-fragments/safe-output-create-issue.md -# - gh-aw-fragments/scheduled-report.md +# - gh-aw-fragments/scheduled-audit.md # -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"1ce8d8e548b56188f9ee61deab959528492e8f8bca69b39134668d0403613afe"} +# inlined-imports: true +# +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"cb0ac749cfef989a2813f1b15b3a6104ecb4a68760a9f56c33c811bc0c48f61a"} name: "Stale Issues" "on": @@ -61,6 +63,11 @@ name: "Stale Issues" description: Footer appended to all agent comments and reviews required: false type: string + model: + default: gpt-5.3-codex + description: AI model to use + required: false + type: string setup-commands: default: "" description: Shell commands to run before the agent starts (dependency install, build, etc.) @@ -90,7 +97,7 @@ jobs: comment_repo: "" steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Validate context variables @@ -167,6 +174,25 @@ jobs: **Critical**: Tool calls write structured data that downstream jobs process. Without tool calls, follow-up actions will be skipped. **Note**: If you made no other safe output tool calls during this workflow execution, call the "noop" tool to provide a status message indicating completion or that no actions were needed. + + --- + + ## Creating an Issue, Reporting Missing Tools or Functionality, Reporting Missing Data + + **IMPORTANT**: To perform the actions listed above, use the **safeoutputs** tools. Do NOT use `gh`, do NOT call the GitHub API directly. You do not have write access to the GitHub repository. + + **Creating an Issue** + + To create an issue, use the create_issue tool from safeoutputs. + + **Reporting Missing Tools or Functionality** + + To report a missing tool or capability, use the missing_tool tool from safeoutputs. + + **Reporting Missing Data** + + To report missing data required to achieve a goal, use the missing_data tool from safeoutputs. + @@ -284,9 +310,7 @@ jobs: - **Mentions**: `@mentions` in the body are neutralized (backticked) by default. GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - # Scheduled Report Agent - - You are a report agent for __GH_AW_GITHUB_REPOSITORY__. You run on a schedule to investigate the repository and file an issue when something needs attention. Your specific assignment is described in the **Report Assignment** section below. + You are an agent for __GH_AW_GITHUB_REPOSITORY__. You run on a schedule to investigate the repository and file an issue when something needs attention. Your specific assignment is described in the **Report Assignment** section below. ## Context @@ -350,7 +374,7 @@ jobs: - Make suggested actions concrete enough to act on without re-investigating - If a finding is ambiguous, it does not pass the quality gate — drop it - ## Report Assignment + **Report Assignment:** GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" @@ -550,7 +574,7 @@ jobs: secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Checkout repository @@ -644,7 +668,7 @@ jobs: const awInfo = { engine_id: "copilot", engine_name: "GitHub Copilot CLI", - model: "gpt-5.3-codex", + model: "${{ inputs.model }}", version: "", agent_version: "0.0.412", workflow_name: "Stale Issues", @@ -855,6 +879,31 @@ jobs: } } }, + "missing_data": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "context": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "data_type": { + "type": "string", + "sanitize": true, + "maxLength": 128 + }, + "reason": { + "type": "string", + "sanitize": true, + "maxLength": 256 + } + } + }, "missing_tool": { "defaultMax": 20, "fields": { @@ -1016,10 +1065,11 @@ jobs: run: | set -o pipefail sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --allow-domains '*.githubusercontent.com,*.jsr.io,*.pythonhosted.org,*.rvm.io,agents-md-generator.fastmcp.app,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.rubygems.org,api.snapcraft.io,archive.ubuntu.com,artifacts.elastic.co,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,bun.sh,bundler.rubygems.org,cache.ruby-lang.org,cdn.jsdelivr.net,cloud.elastic.co,codeload.github.com,conda.anaconda.org,conda.binstar.org,crates.io,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,deb.nodesource.com,deno.land,ela.st,elastic.co,esm.sh,files.pythonhosted.org,gems.rubyforge.org,gems.rubyonrails.org,get.pnpm.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,host.docker.internal,index.crates.io,index.rubygems.org,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,lfs.github.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,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,pip.pypa.io,pkg.go.dev,ppa.launchpad.net,proxy.golang.org,public-code-search.fastmcp.app,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.bower.io,registry.npmjs.com,registry.npmjs.org,registry.yarnpkg.com,repo.anaconda.com,repo.continuum.io,repo.yarnpkg.com,rubygems.org,rubygems.pkg.github.com,s.symcb.com,s.symcd.com,security.ubuntu.com,skimdb.npmjs.com,static.crates.io,storage.googleapis.com,sum.golang.org,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.elastic.co,www.npmjs.com,www.npmjs.org,yarnpkg.com' --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.20.2 --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 --model gpt-5.3-codex --allow-all-tools --allow-all-paths --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log + -- /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 --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} @@ -1185,7 +1235,7 @@ jobs: total_count: ${{ steps.missing_tool.outputs.total_count }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent output artifact @@ -1276,7 +1326,7 @@ jobs: success: ${{ steps.parse_results.outputs.success }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent artifacts @@ -1337,10 +1387,11 @@ jobs: mkdir -p /tmp/gh-aw/ mkdir -p /tmp/gh-aw/agent/ mkdir -p /tmp/gh-aw/sandbox/agent/logs/ - copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --model gpt-5.3-codex --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log + copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_REF_NAME: ${{ github.ref_name }} @@ -1370,7 +1421,7 @@ jobs: activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Check team membership for workflow @@ -1399,7 +1450,7 @@ jobs: timeout-minutes: 15 env: GH_AW_ENGINE_ID: "copilot" - GH_AW_ENGINE_MODEL: "gpt-5.3-codex" + GH_AW_ENGINE_MODEL: "${{ inputs.model }}" GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\"}" GH_AW_WORKFLOW_ID: "gh-aw-stale-issues" GH_AW_WORKFLOW_NAME: "Stale Issues" @@ -1410,7 +1461,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@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent output artifact diff --git a/.github/workflows/gh-aw-stale-issues.md b/.github/workflows/gh-aw-stale-issues.md index f11f416e..8e1dc1d7 100644 --- a/.github/workflows/gh-aw-stale-issues.md +++ b/.github/workflows/gh-aw-stale-issues.md @@ -1,4 +1,5 @@ --- +inlined-imports: true name: "Stale Issues" description: "Find open issues that appear to already be resolved and recommend closing them" imports: @@ -9,13 +10,18 @@ imports: - gh-aw-fragments/mcp-pagination.md - gh-aw-fragments/messages-footer.md - gh-aw-fragments/safe-output-create-issue.md - - gh-aw-fragments/scheduled-report.md + - gh-aw-fragments/scheduled-audit.md engine: id: copilot - model: gpt-5.3-codex + model: ${{ inputs.model }} on: workflow_call: inputs: + model: + description: "AI model to use" + type: string + required: false + default: "gpt-5.3-codex" additional-instructions: description: "Repo-specific instructions appended to the agent prompt" type: string diff --git a/.github/workflows/gh-aw-test-improvement.lock.yml b/.github/workflows/gh-aw-test-improvement.lock.yml deleted file mode 100644 index dd8c10e3..00000000 --- a/.github/workflows/gh-aw-test-improvement.lock.yml +++ /dev/null @@ -1,1502 +0,0 @@ -# -# ___ _ _ -# / _ \ | | (_) -# | |_| | __ _ ___ _ __ | |_ _ ___ -# | _ |/ _` |/ _ \ '_ \| __| |/ __| -# | | | | (_| | __/ | | | |_| | (__ -# \_| |_/\__, |\___|_| |_|\__|_|\___| -# __/ | -# _ _ |___/ -# | | | | / _| | -# | | | | ___ _ __ _ __| |_| | _____ ____ -# | |/\| |/ _ \ '__| |/ /| _| |/ _ \ \ /\ / / ___| -# \ /\ / (_) | | | | ( | | | | (_) \ V V /\__ \ -# \/ \/ \___/|_| |_|\_\|_| |_|\___/ \_/\_/ |___/ -# -# This file was automatically generated by gh-aw. DO NOT EDIT. -# -# To update this file, edit the corresponding .md file and run: -# gh aw compile -# Not all edits will cause changes to this file. -# -# For more information: https://github.github.com/gh-aw/introduction/overview/ -# -# Add focused tests for under-tested code and clean up redundant tests -# -# Resolved workflow manifest: -# Imports: -# - gh-aw-fragments/elastic-tools.md -# - gh-aw-fragments/formatting.md -# - gh-aw-fragments/mcp-pagination.md -# - gh-aw-fragments/messages-footer.md -# - gh-aw-fragments/rigor.md -# - gh-aw-fragments/runtime-setup.md -# - gh-aw-fragments/safe-output-create-pr.md -# - gh-aw-fragments/workflow-edit-guardrails.md -# -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"c771f91238f21abf0f1589dcbe5a460c4af08df2f1f8792b4f7ae47ee8b2439a"} - -name: "Test Improvement" -"on": - # bots: # Bots processed as bot check in pre-activation job - # - ${{ inputs.allowed-bot-users }} # Bots processed as bot check in pre-activation job - # roles: # Roles processed as role check in pre-activation job - # - admin # Roles processed as role check in pre-activation job - # - maintainer # Roles processed as role check in pre-activation job - # - write # Roles processed as role check in pre-activation job - workflow_call: - inputs: - additional-instructions: - default: "" - description: Repo-specific instructions appended to the agent prompt - required: false - type: string - allowed-bot-users: - default: github-actions[bot] - description: Allowlisted bot actor usernames (comma-separated) - required: false - type: string - messages-footer: - default: "" - description: Footer appended to all agent comments and reviews - required: false - type: string - setup-commands: - default: "" - description: Shell commands to run before the agent starts (dependency install, build, etc.) - required: false - type: string - secrets: - COPILOT_GITHUB_TOKEN: - required: true - -permissions: {} - -concurrency: - cancel-in-progress: true - group: test-improvement - -run-name: "Test Improvement" - -jobs: - activation: - needs: pre_activation - if: needs.pre_activation.outputs.activated == 'true' - runs-on: ubuntu-slim - permissions: - contents: read - outputs: - comment_id: "" - comment_repo: "" - steps: - - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 - with: - destination: /opt/gh-aw/actions - - name: Validate context variables - 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/validate_context_variables.cjs'); - await main(); - - name: Checkout .github and .agents folders - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - sparse-checkout: | - .github - .agents - fetch-depth: 1 - persist-credentials: false - - name: Check workflow file timestamps - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_WORKFLOW_FILE: "gh-aw-test-improvement.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: Create prompt with built-in context - env: - GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} - GH_AW_GITHUB_ACTOR: ${{ github.actor }} - GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} - GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} - GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} - GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} - GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} - GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} - GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} - run: | - bash /opt/gh-aw/actions/create_prompt_first.sh - cat << 'GH_AW_PROMPT_EOF' > "$GH_AW_PROMPT" - - GH_AW_PROMPT_EOF - cat "/opt/gh-aw/prompts/xpia.md" >> "$GH_AW_PROMPT" - cat "/opt/gh-aw/prompts/temp_folder_prompt.md" >> "$GH_AW_PROMPT" - cat "/opt/gh-aw/prompts/markdown.md" >> "$GH_AW_PROMPT" - cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - - GitHub API Access Instructions - - The gh CLI is NOT authenticated. Do NOT use gh commands for GitHub operations. - - - To create or modify GitHub resources (issues, discussions, pull requests, etc.), you MUST call the appropriate safe output tool. Simply writing content will NOT work - the workflow requires actual tool calls. - - Temporary IDs: Some safe output tools support a temporary ID field (usually named temporary_id) so you can reference newly-created items elsewhere in the SAME agent output (for example, using #aw_abc1 in a later body). - - **IMPORTANT - temporary_id format rules:** - - If you DON'T need to reference the item later, OMIT the temporary_id field entirely (it will be auto-generated if needed) - - If you DO need cross-references/chaining, you MUST match this EXACT validation regex: /^aw_[A-Za-z0-9]{3,8}$/i - - Format: aw_ prefix followed by 3 to 8 alphanumeric characters (A-Z, a-z, 0-9, case-insensitive) - - Valid alphanumeric characters: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 - - INVALID examples: aw_ab (too short), aw_123456789 (too long), aw_test-id (contains hyphen), aw_id_123 (contains underscore) - - VALID examples: aw_abc, aw_abc1, aw_Test123, aw_A1B2C3D4, aw_12345678 - - To generate valid IDs: use 3-8 random alphanumeric characters or omit the field to let the system auto-generate - - Do NOT invent other aw_* formats — downstream steps will reject them with validation errors matching against /^aw_[A-Za-z0-9]{3,8}$/i. - - Discover available tools from the safeoutputs MCP server. - - **Critical**: Tool calls write structured data that downstream jobs process. Without tool calls, follow-up actions will be skipped. - - **Note**: If you made no other safe output tool calls during this workflow execution, call the "noop" tool to provide a status message indicating completion or that no actions were needed. - - - - The following GitHub context information is available for this workflow: - {{#if __GH_AW_GITHUB_ACTOR__ }} - - **actor**: __GH_AW_GITHUB_ACTOR__ - {{/if}} - {{#if __GH_AW_GITHUB_REPOSITORY__ }} - - **repository**: __GH_AW_GITHUB_REPOSITORY__ - {{/if}} - {{#if __GH_AW_GITHUB_WORKSPACE__ }} - - **workspace**: __GH_AW_GITHUB_WORKSPACE__ - {{/if}} - {{#if __GH_AW_GITHUB_EVENT_ISSUE_NUMBER__ }} - - **issue-number**: #__GH_AW_GITHUB_EVENT_ISSUE_NUMBER__ - {{/if}} - {{#if __GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__ }} - - **discussion-number**: #__GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__ - {{/if}} - {{#if __GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__ }} - - **pull-request-number**: #__GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__ - {{/if}} - {{#if __GH_AW_GITHUB_EVENT_COMMENT_ID__ }} - - **comment-id**: __GH_AW_GITHUB_EVENT_COMMENT_ID__ - {{/if}} - {{#if __GH_AW_GITHUB_RUN_ID__ }} - - **workflow-run-id**: __GH_AW_GITHUB_RUN_ID__ - {{/if}} - - - GH_AW_PROMPT_EOF - cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - - GH_AW_PROMPT_EOF - cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - ## MCP Servers - - - **`generate_agents_md`** — generates a summary of the repository's structure, conventions, and coding guidelines from AGENTS.md and related files. Call at the start of every workflow to get repo context. - - **`search_code`** — grep-style search across public GitHub repositories. Use for finding usage patterns in upstream libraries, reference implementations, or examples in open-source projects. This searches *public GitHub repos*, not the local codebase — if available you can use `grep` and file reading for local code. - GH_AW_PROMPT_EOF - cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - - GH_AW_PROMPT_EOF - cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - ## Formatting Guidelines - - - Lead with the most important information — your first sentence should be the key takeaway - - Be concise and actionable — no filler or praise - - Use `
` and `` tags for long sections to keep responses scannable - - Wrap branch names and @-references in backticks to avoid pinging users - - Include code snippets with file paths and line numbers when referencing the codebase - - GH_AW_PROMPT_EOF - cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - ## Rigor - - **Silence is better than noise. A false positive wastes a human's time and erodes trust in every future report.** - - - If you claim something is missing or broken, show the exact evidence in the code — file path, line number, and what you observed. - - If a conclusion depends on assumptions you haven't confirmed, do not assert it. Verify first; if you cannot verify, do not report. - - "I don't know" is better than a wrong answer. `noop` is better than a speculative finding. - - It's worth the time to verify now versus guessing and forcing someone else to verify later. - - Before filing any issue or opening any PR, re-read your own output as a skeptical reviewer. Ask: "Would a senior engineer on this team find this useful, or would they close it immediately?" If the answer is "close," call `noop` instead. - - Only report findings you would confidently defend in a code review. If you feel the need to hedge with "might," "could," or "possibly," the finding is not ready to file. - - GH_AW_PROMPT_EOF - cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - ## MCP Pagination - - MCP tool responses have a **25,000 token limit**. When responses exceed this limit, the call fails and you must retry with pagination — wasting turns and tokens. Use proactive pagination to stay under the limit. - - ### Recommended `perPage` Values - - - **5-10**: For detailed items (PR diffs, files with patches, issues with comments) - - **20-30**: For medium-detail lists (commits, review comments, issue lists) - - **50-100**: For simple list operations (branches, labels, tags) - - ### Pagination Pattern - - When you need all results from a paginated API: - - 1. Fetch the first page with a conservative `perPage` value - 2. Process the results before fetching the next page - 3. Continue fetching pages until you receive fewer results than `perPage` (indicating the last page) - - ### Error Recovery - - If you see an error like: - - `MCP tool response exceeds maximum allowed tokens (25000)` - - `Response too large for tool [tool_name]` - - Retry the same call with a smaller `perPage` value (halve it). - - ### Tips - - - **Start small**: It's better to make multiple small requests than one that fails - - **Fetch incrementally**: Get an overview first, then details for specific items - - **Use filters**: Combine `perPage` with state, label, or date filters to reduce result size - - **Process as you go**: Don't accumulate all pages before acting — process each batch immediately - - GH_AW_PROMPT_EOF - cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - ## Workflow Editing Guardrails - - - Do not modify files under `.github/workflows/`. - - If asked to change workflow files, place a copy under `github/` (no leading dot) and note that a maintainer must relocate it into `.github/workflows/`. - - GH_AW_PROMPT_EOF - cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - ## Message Footer - - A footer is automatically appended to all comments and reviews. Do not add your own footer or sign-off — the runtime handles this. - GH_AW_PROMPT_EOF - cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - Before calling `create_pull_request`, call `ready_to_make_pr` and apply its checklist. - - ## create-pull-request Limitations - - - **Patch files**: Max 100 files per PR. If changes span more files, split into multiple focused PRs. - - **Patch size**: Max 1,024 KB by default. Keep changes focused. - - **Title**: Max 128 characters. Sanitized. - - **Body**: No explicit mention/link limits, but bot triggers (`fixes #123`, `closes #456`) are neutralized. - - **Committed changes required**: You must have locally committed changes before creating a PR (unless `allow_empty` is configured). - - **Base branch**: Must be configured in the safe-output config. The PR targets this branch. - - **Max per run**: Typically 1 PR creation per workflow run. - - You may not submit code that modifies files in `.github/workflows/`. Doing so will cause the submission to be rejected. If asked to modify workflow files, propose the change in a copy placed in a `github/` folder (without the leading period) and note in the PR that the file needs to be relocated by someone with workflow write access. - GH_AW_PROMPT_EOF - cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - # Test Improvement Agent - - Identify under-tested code paths, add focused tests, and remove or consolidate duplicate or useless tests when safe. Open a single PR with the improvements. - - ## Context - - - **Repository**: __GH_AW_GITHUB_REPOSITORY__ - - ## Constraints - - - **CAN**: Read files, search code, modify files locally, run tests and commands, create a pull request. - - **CANNOT**: Push directly to the repository — use `create_pull_request`. - - **Only one PR per run.** - - No large refactors; prioritize targeted test additions or small cleanup of redundant tests. - - If the change set is large or unsafe, call `noop` with a brief reason. - - **Most runs should end with `noop`.** Only open a PR when the added tests are clearly valuable — they test real behavior, not trivial getters, and they would catch actual regressions. - - ## Step 1: Gather context - - 1. Call `generate_agents_md` to get repository conventions (if it fails, continue). - 2. Determine required repo commands (lint/build/test) and how to run tests: - - Check README, CONTRIBUTING, DEVELOPING, Makefile, CI config, package.json, pyproject.toml, and similar files. - 3. Identify coverage tooling (nyc, jest --coverage, pytest --cov, go test -cover, etc.). - - If coverage is available and reasonably fast, run it to find low-coverage files. - - ## Step 2: Identify targets - - - Prefer low-coverage or untested public APIs, error paths, or recent changes without tests. - - **Trace to user-facing behavior.** For every candidate, answer: "What end-to-end user action would exercise this code path?" If you cannot describe a concrete user scenario (e.g., "a user configures X and then Y happens"), the target is too internal to justify a PR. - - Prefer code paths reachable from public entry points (CLI commands, API endpoints, config parsing, UI interactions) over deeply internal helpers. - - Look for redundant tests: - - identical assertions or test bodies, - - tests that only duplicate coverage from more comprehensive tests. - - Only remove or merge tests when a clearer, equivalent test remains. - - ## Step 3: Implement improvements - - 1. Add minimal, focused tests in existing test suites. - 2. Keep production code changes minimal and only when needed to enable testing. - 3. Consolidate or remove redundant tests if safe, keeping behavior coverage intact. - - ## Step 4: Verify - - - Run required repo commands (lint/build/test) relevant to the change and capture results. - - Run the most relevant test command(s). **All tests — new and existing — must pass.** If the full suite is too heavy, run targeted tests. - - If required commands, tests, or coverage cannot be run, call `noop`. Do not open a PR with untested test code. - - ## Step 5: Quality Gate — Test Value Check - - Before creating the PR, evaluate each new test: - - - **Does it test real behavior?** Tests for trivial getters, simple constructors, or obvious pass-through functions are not worth filing a PR for. - - **Would it catch a real regression?** If the tested code changed in a buggy way, would this test actually fail? - - **Can you describe the user scenario?** For each test, you must be able to state: "A user doing [action] would hit this code path when [condition]." If you cannot connect the test to a describable end-to-end user experience, drop it. - - **Is it maintainable?** Fragile tests that break on cosmetic changes (string formatting, log messages) add burden, not value. - - **Does it follow project conventions?** Match the existing test style, naming, and organization. - - If the tests don't pass this bar, call `noop`. Low-value tests are worse than no tests — they create maintenance burden and false confidence. - - ## Step 6: Create the PR - - 1. Commit the changes locally. - 2. Call `create_pull_request` with: - - **Title**: concise summary of the test improvements - - **Body** must include: - - Summary of what changed - - **User scenario**: for each test, describe the real-world user action or workflow that exercises the tested code path (e.g., "When a user runs `beat setup` with an invalid config, this error path is triggered") - - Why the tests matter — what regressions they would catch - - Tests run and their results - - Any removed or merged tests - 3. If no safe improvements are found, call `noop` with a brief reason. - - __GH_AW_EXPR_49B959F1__ - - GH_AW_PROMPT_EOF - - name: Interpolate variables and render templates - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} - GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} - 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/interpolate_prompt.cjs'); - await main(); - - name: Substitute placeholders - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} - GH_AW_GITHUB_ACTOR: ${{ github.actor }} - GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} - GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} - GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} - GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} - 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'); - setupGlobals(core, github, context, exec, io); - - const substitutePlaceholders = require('/opt/gh-aw/actions/substitute_placeholders.cjs'); - - // Call the substitution function - return await substitutePlaceholders({ - file: process.env.GH_AW_PROMPT, - substitutions: { - GH_AW_EXPR_49B959F1: process.env.GH_AW_EXPR_49B959F1, - GH_AW_GITHUB_ACTOR: process.env.GH_AW_GITHUB_ACTOR, - GH_AW_GITHUB_EVENT_COMMENT_ID: process.env.GH_AW_GITHUB_EVENT_COMMENT_ID, - GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: process.env.GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER, - GH_AW_GITHUB_EVENT_ISSUE_NUMBER: process.env.GH_AW_GITHUB_EVENT_ISSUE_NUMBER, - 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_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 - env: - GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - run: bash /opt/gh-aw/actions/validate_prompt_placeholders.sh - - name: Print prompt - env: - GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - run: bash /opt/gh-aw/actions/print_prompt_summary.sh - - name: Upload prompt artifact - if: success() - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 - with: - name: prompt - path: /tmp/gh-aw/aw-prompts/prompt.txt - retention-days: 1 - - agent: - needs: activation - runs-on: ubuntu-latest - permissions: - contents: read - issues: read - pull-requests: read - concurrency: - group: "gh-aw-copilot-${{ github.workflow }}" - env: - DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} - GH_AW_ASSETS_ALLOWED_EXTS: "" - GH_AW_ASSETS_BRANCH: "" - GH_AW_ASSETS_MAX_SIZE_KB: 0 - GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs - 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: ghawtestimprovement - outputs: - checkout_pr_success: ${{ steps.checkout-pr.outputs.checkout_pr_success || 'true' }} - has_patch: ${{ steps.collect_output.outputs.has_patch }} - model: ${{ steps.generate_aw_info.outputs.model }} - output: ${{ steps.collect_output.outputs.output }} - output_types: ${{ steps.collect_output.outputs.output_types }} - secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} - steps: - - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 - with: - destination: /opt/gh-aw/actions - - name: Checkout repository - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - persist-credentials: false - - name: Create gh-aw temp directory - run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh - - if: hashFiles('go.mod') != '' - name: Setup Go - uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5 - with: - cache: true - go-version-file: go.mod - - if: hashFiles('.python-version') != '' - name: Setup Python - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 - with: - python-version-file: .python-version - - if: hashFiles('.node-version') != '' - name: Setup Node.js (.node-version) - uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6 - with: - node-version-file: .node-version - - if: hashFiles('.node-version') == '' && hashFiles('.nvmrc') != '' - name: Setup Node.js (.nvmrc) - uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6 - with: - node-version-file: .nvmrc - - if: hashFiles('.ruby-version') != '' - name: Setup Ruby - uses: ruby/setup-ruby@09a7688d3b55cf0e976497ff046b70949eeaccfd # v1 - with: - bundler-cache: true - ruby-version: .ruby-version - - id: setup-uv - if: hashFiles('pyproject.toml', 'uv.lock') != '' - name: Setup uv - uses: astral-sh/setup-uv@e58605a9b6da7c637471fab8847a5e5a6b8df081 # v5 - - env: - UV_PATH: ${{ steps.setup-uv.outputs.uv-path }} - WORKSPACE: ${{ github.workspace }} - if: hashFiles('pyproject.toml', 'uv.lock') != '' - name: Expose uv in workspace - run: |- - set -euo pipefail - install_dir="$WORKSPACE/.gh-aw-tools/bin" - mkdir -p "$install_dir" - cp "$UV_PATH" "$install_dir/uv" - chmod +x "$install_dir/uv" - echo "$install_dir" >> "$GITHUB_PATH" - shell: bash - - env: - SETUP_COMMANDS: ${{ inputs.setup-commands }} - if: ${{ inputs.setup-commands != '' }} - name: Repo-specific setup - run: eval "$SETUP_COMMANDS" - - - name: Configure Git credentials - env: - REPO_NAME: ${{ github.repository }} - SERVER_URL: ${{ github.server_url }} - run: | - git config --global user.email "github-actions[bot]@users.noreply.github.com" - git config --global user.name "github-actions[bot]" - # Re-authenticate git with GitHub token - SERVER_URL_STRIPPED="${SERVER_URL#https://}" - git remote set-url origin "https://x-access-token:${{ github.token }}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" - echo "Git configured with standard GitHub Actions identity" - - name: Checkout PR branch - id: checkout-pr - if: | - github.event.pull_request - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - with: - github-token: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - script: | - const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io); - const { main } = require('/opt/gh-aw/actions/checkout_pr_branch.cjs'); - await main(); - - name: Generate agentic run info - id: generate_aw_info - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - with: - script: | - const fs = require('fs'); - - const awInfo = { - engine_id: "copilot", - engine_name: "GitHub Copilot CLI", - model: "gpt-5.3-codex", - version: "", - agent_version: "0.0.412", - workflow_name: "Test Improvement", - experimental: false, - supports_tools_allowlist: true, - run_id: context.runId, - run_number: context.runNumber, - run_attempt: process.env.GITHUB_RUN_ATTEMPT, - repository: context.repo.owner + '/' + context.repo.repo, - ref: context.ref, - sha: context.sha, - actor: context.actor, - event_name: context.eventName, - staged: false, - allowed_domains: ["agents-md-generator.fastmcp.app","artifacts.elastic.co","cloud.elastic.co","defaults","ela.st","elastic.co","github","go","node","public-code-search.fastmcp.app","python","ruby","www.elastic.co"], - firewall_enabled: true, - awf_version: "v0.20.2", - awmg_version: "v0.1.4", - steps: { - firewall: "squid" - }, - created_at: new Date().toISOString() - }; - - // Write to /tmp/gh-aw directory to avoid inclusion in PR - const tmpPath = '/tmp/gh-aw/aw_info.json'; - fs.writeFileSync(tmpPath, JSON.stringify(awInfo, null, 2)); - console.log('Generated aw_info.json at:', tmpPath); - console.log(JSON.stringify(awInfo, null, 2)); - - // Set model as output for reuse in other steps/jobs - core.setOutput('model', awInfo.model); - - name: Validate COPILOT_GITHUB_TOKEN secret - id: validate-secret - run: /opt/gh-aw/actions/validate_multi_secret.sh COPILOT_GITHUB_TOKEN 'GitHub Copilot CLI' https://github.github.com/gh-aw/reference/engines/#github-copilot-default - env: - COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} - - name: Install GitHub Copilot CLI - run: /opt/gh-aw/actions/install_copilot_cli.sh 0.0.412 - - name: Install awf binary - run: bash /opt/gh-aw/actions/install_awf_binary.sh v0.20.2 - - name: Determine automatic lockdown mode for GitHub MCP Server - id: determine-automatic-lockdown - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} - GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} - with: - script: | - 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.20.2 ghcr.io/github/gh-aw-firewall/api-proxy:0.20.2 ghcr.io/github/gh-aw-firewall/squid:0.20.2 ghcr.io/github/gh-aw-mcpg:v0.1.4 ghcr.io/github/github-mcp-server:v0.31.0 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' - {"create_pull_request":{},"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 pull request to propose code changes. Use this after making file edits to submit them for review and merging. The PR will be created from the current branch with your committed changes. For code review comments on an existing PR, use create_pull_request_review_comment instead. CONSTRAINTS: Maximum 1 pull request(s) can be created.", - "inputSchema": { - "additionalProperties": false, - "properties": { - "body": { - "description": "Detailed PR description in Markdown. Include what changes were made, why, testing notes, and any breaking changes. Do NOT repeat the title as a heading.", - "type": "string" - }, - "branch": { - "description": "Source branch name containing the changes. If omitted, uses the current working branch.", - "type": "string" - }, - "labels": { - "description": "Labels to categorize the PR (e.g., 'enhancement', 'bugfix'). Labels must exist in the repository.", - "items": { - "type": "string" - }, - "type": "array" - }, - "title": { - "description": "Concise PR title describing the changes. Follow repository conventions (e.g., conventional commits). The title appears as the main heading.", - "type": "string" - } - }, - "required": [ - "title", - "body" - ], - "type": "object" - }, - "name": "create_pull_request" - }, - { - "description": "Report that a tool or capability needed to complete the task is not available, or share any information you deem important about missing functionality or limitations. Use this when you cannot accomplish what was requested because the required functionality is missing or access is restricted.", - "inputSchema": { - "additionalProperties": false, - "properties": { - "alternatives": { - "description": "Any workarounds, manual steps, or alternative approaches the user could take (max 256 characters).", - "type": "string" - }, - "reason": { - "description": "Explanation of why this tool is needed or what information you want to share about the limitation (max 256 characters).", - "type": "string" - }, - "tool": { - "description": "Optional: Name or description of the missing tool or capability (max 128 characters). Be specific about what functionality is needed.", - "type": "string" - } - }, - "required": [ - "reason" - ], - "type": "object" - }, - "name": "missing_tool" - }, - { - "description": "Log a transparency message when no significant actions are needed. Use this to confirm workflow completion and provide visibility when analysis is complete but no changes or outputs are required (e.g., 'No issues found', 'All checks passed'). This ensures the workflow produces human-visible output even when no other actions are taken.", - "inputSchema": { - "additionalProperties": false, - "properties": { - "message": { - "description": "Status or completion message to log. Should explain what was analyzed and the outcome (e.g., 'Code review complete - no issues found', 'Analysis complete - all tests passing').", - "type": "string" - } - }, - "required": [ - "message" - ], - "type": "object" - }, - "name": "noop" - }, - { - "description": "Report that data or information needed to complete the task is not available. Use this when you cannot accomplish what was requested because required data, context, or information is missing.", - "inputSchema": { - "additionalProperties": false, - "properties": { - "alternatives": { - "description": "Any workarounds, manual steps, or alternative approaches the user could take (max 256 characters).", - "type": "string" - }, - "context": { - "description": "Additional context about the missing data or where it should come from (max 256 characters).", - "type": "string" - }, - "data_type": { - "description": "Type or description of the missing data or information (max 128 characters). Be specific about what data is needed.", - "type": "string" - }, - "reason": { - "description": "Explanation of why this data is needed to complete the task (max 256 characters).", - "type": "string" - } - }, - "required": [], - "type": "object" - }, - "name": "missing_data" - } - ] - GH_AW_SAFE_OUTPUTS_TOOLS_EOF - cat > /opt/gh-aw/safeoutputs/validation.json << 'GH_AW_SAFE_OUTPUTS_VALIDATION_EOF' - { - "create_pull_request": { - "defaultMax": 1, - "fields": { - "body": { - "required": true, - "type": "string", - "sanitize": true, - "maxLength": 65000 - }, - "branch": { - "required": true, - "type": "string", - "sanitize": true, - "maxLength": 256 - }, - "labels": { - "type": "array", - "itemType": "string", - "itemSanitize": true, - "itemMaxLength": 128 - }, - "title": { - "required": true, - "type": "string", - "sanitize": true, - "maxLength": 128 - } - } - }, - "missing_tool": { - "defaultMax": 20, - "fields": { - "alternatives": { - "type": "string", - "sanitize": true, - "maxLength": 512 - }, - "reason": { - "required": true, - "type": "string", - "sanitize": true, - "maxLength": 256 - }, - "tool": { - "type": "string", - "sanitize": true, - "maxLength": 128 - } - } - }, - "noop": { - "defaultMax": 1, - "fields": { - "message": { - "required": true, - "type": "string", - "sanitize": true, - "maxLength": 65000 - } - } - } - } - GH_AW_SAFE_OUTPUTS_VALIDATION_EOF - - name: Generate Safe Outputs MCP Server Config - id: safe-outputs-config - run: | - # Generate a secure random API key (360 bits of entropy, 40+ chars) - # Mask immediately to prevent timing vulnerabilities - API_KEY=$(openssl rand -base64 45 | tr -d '/+=') - echo "::add-mask::${API_KEY}" - - PORT=3001 - - # Set outputs for next steps - { - echo "safe_outputs_api_key=${API_KEY}" - echo "safe_outputs_port=${PORT}" - } >> "$GITHUB_OUTPUT" - - echo "Safe Outputs MCP server will run on port ${PORT}" - - - name: Start Safe Outputs MCP HTTP Server - id: safe-outputs-start - env: - DEBUG: '*' - GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-config.outputs.safe_outputs_port }} - GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-config.outputs.safe_outputs_api_key }} - GH_AW_SAFE_OUTPUTS_TOOLS_PATH: /opt/gh-aw/safeoutputs/tools.json - GH_AW_SAFE_OUTPUTS_CONFIG_PATH: /opt/gh-aw/safeoutputs/config.json - GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs - run: | - # Environment variables are set above to prevent template injection - export DEBUG - export GH_AW_SAFE_OUTPUTS_PORT - export GH_AW_SAFE_OUTPUTS_API_KEY - export GH_AW_SAFE_OUTPUTS_TOOLS_PATH - export GH_AW_SAFE_OUTPUTS_CONFIG_PATH - export GH_AW_MCP_LOG_DIR - - bash /opt/gh-aw/actions/start_safe_outputs_server.sh - - - name: Setup Safe Inputs Config - run: | - mkdir -p /opt/gh-aw/safe-inputs/logs - cat > /opt/gh-aw/safe-inputs/tools.json << 'GH_AW_SAFE_INPUTS_TOOLS_EOF' - { - "serverName": "safeinputs", - "version": "1.0.0", - "logDir": "/opt/gh-aw/safe-inputs/logs", - "tools": [ - { - "name": "ready-to-make-pr", - "description": "Run the PR readiness checklist before creating or updating a PR", - "inputSchema": { - "properties": {}, - "type": "object" - }, - "handler": "ready-to-make-pr.cjs", - "timeout": 60 - } - ] - } - GH_AW_SAFE_INPUTS_TOOLS_EOF - cat > /opt/gh-aw/safe-inputs/mcp-server.cjs << 'GH_AW_SAFE_INPUTS_SERVER_EOF' - const path = require("path"); - const { startHttpServer } = require("./safe_inputs_mcp_server_http.cjs"); - const configPath = path.join(__dirname, "tools.json"); - const port = parseInt(process.env.GH_AW_SAFE_INPUTS_PORT || "3000", 10); - const apiKey = process.env.GH_AW_SAFE_INPUTS_API_KEY || ""; - startHttpServer(configPath, { - port: port, - stateless: true, - logDir: "/opt/gh-aw/safe-inputs/logs" - }).catch(error => { - console.error("Failed to start safe-inputs HTTP server:", error); - process.exit(1); - }); - GH_AW_SAFE_INPUTS_SERVER_EOF - chmod +x /opt/gh-aw/safe-inputs/mcp-server.cjs - - - name: Setup Safe Inputs Tool Files - run: | - cat > /opt/gh-aw/safe-inputs/ready-to-make-pr.cjs << 'GH_AW_SAFE_INPUTS_JS_READY-TO-MAKE-PR_EOF' - async function execute(inputs) { - const fs = require('fs'); - const find = (...paths) => paths.find(p => fs.existsSync(p)) || null; - const contributing = find('CONTRIBUTING.md', 'CONTRIBUTING.rst', 'docs/CONTRIBUTING.md', 'docs/contributing.md'); - const prTemplate = find('.github/pull_request_template.md', '.github/PULL_REQUEST_TEMPLATE.md', '.github/PULL_REQUEST_TEMPLATE/pull_request_template.md'); - const checklist = []; - if (contributing) checklist.push(`Review the contributing guide (${contributing}) before opening or updating a PR.`); - if (prTemplate) checklist.push(`Follow the PR template (${prTemplate}) for title, description, and validation notes.`); - checklist.push('Confirm the requested task is fully completed and validated before creating or pushing PR changes.'); - return { status: 'ok', checklist, contributing_guide: contributing, pr_template: prTemplate }; - } - module.exports = { execute }; - GH_AW_SAFE_INPUTS_JS_READY-TO-MAKE-PR_EOF - - - name: Generate Safe Inputs MCP Server Config - id: safe-inputs-config - run: | - # Generate a secure random API key (360 bits of entropy, 40+ chars) - # Mask immediately to prevent timing vulnerabilities - API_KEY=$(openssl rand -base64 45 | tr -d '/+=') - echo "::add-mask::${API_KEY}" - - PORT=3000 - - # Set outputs for next steps - { - echo "safe_inputs_api_key=${API_KEY}" - echo "safe_inputs_port=${PORT}" - } >> "$GITHUB_OUTPUT" - - echo "Safe Inputs MCP server will run on port ${PORT}" - - - name: Start Safe Inputs MCP HTTP Server - id: safe-inputs-start - env: - DEBUG: '*' - GH_AW_SAFE_INPUTS_PORT: ${{ steps.safe-inputs-config.outputs.safe_inputs_port }} - GH_AW_SAFE_INPUTS_API_KEY: ${{ steps.safe-inputs-config.outputs.safe_inputs_api_key }} - run: | - # Environment variables are set above to prevent template injection - export DEBUG - export GH_AW_SAFE_INPUTS_PORT - export GH_AW_SAFE_INPUTS_API_KEY - - bash /opt/gh-aw/actions/start_safe_inputs_server.sh - - - name: Start MCP Gateway - id: start-mcp-gateway - env: - GH_AW_SAFE_INPUTS_API_KEY: ${{ steps.safe-inputs-start.outputs.api_key }} - GH_AW_SAFE_INPUTS_PORT: ${{ steps.safe-inputs-start.outputs.port }} - GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-start.outputs.api_key }} - GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-start.outputs.port }} - GITHUB_MCP_LOCKDOWN: ${{ steps.determine-automatic-lockdown.outputs.lockdown == 'true' && '1' || '0' }} - GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - run: | - set -eo pipefail - mkdir -p /tmp/gh-aw/mcp-config - - # Export gateway environment variables for MCP config and gateway script - export MCP_GATEWAY_PORT="80" - export MCP_GATEWAY_DOMAIN="host.docker.internal" - MCP_GATEWAY_API_KEY=$(openssl rand -base64 45 | tr -d '/+=') - echo "::add-mask::${MCP_GATEWAY_API_KEY}" - export MCP_GATEWAY_API_KEY - export MCP_GATEWAY_PAYLOAD_DIR="/tmp/gh-aw/mcp-payloads" - mkdir -p "${MCP_GATEWAY_PAYLOAD_DIR}" - export DEBUG="*" - - export GH_AW_ENGINE="copilot" - 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 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_LOCKDOWN -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_INPUTS_PORT -e GH_AW_SAFE_INPUTS_API_KEY -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.1.4' - - mkdir -p /home/runner/.copilot - cat << GH_AW_MCP_CONFIG_EOF | bash /opt/gh-aw/actions/start_mcp_gateway.sh - { - "mcpServers": { - "agents-md-generator": { - "type": "http", - "url": "https://agents-md-generator.fastmcp.app/mcp", - "tools": [ - "generate_agents_md" - ] - }, - "github": { - "type": "stdio", - "container": "ghcr.io/github/github-mcp-server:v0.31.0", - "env": { - "GITHUB_LOCKDOWN_MODE": "$GITHUB_MCP_LOCKDOWN", - "GITHUB_PERSONAL_ACCESS_TOKEN": "\${GITHUB_MCP_SERVER_TOKEN}", - "GITHUB_READ_ONLY": "1", - "GITHUB_TOOLSETS": "repos,issues,pull_requests,search" - } - }, - "public-code-search": { - "type": "http", - "url": "https://public-code-search.fastmcp.app/mcp", - "tools": [ - "search_code" - ] - }, - "safeinputs": { - "type": "http", - "url": "http://host.docker.internal:$GH_AW_SAFE_INPUTS_PORT", - "headers": { - "Authorization": "\${GH_AW_SAFE_INPUTS_API_KEY}" - } - }, - "safeoutputs": { - "type": "http", - "url": "http://host.docker.internal:$GH_AW_SAFE_OUTPUTS_PORT", - "headers": { - "Authorization": "\${GH_AW_SAFE_OUTPUTS_API_KEY}" - } - } - }, - "gateway": { - "port": $MCP_GATEWAY_PORT, - "domain": "${MCP_GATEWAY_DOMAIN}", - "apiKey": "${MCP_GATEWAY_API_KEY}", - "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" - } - } - GH_AW_MCP_CONFIG_EOF - - name: Generate workflow overview - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - with: - script: | - const { generateWorkflowOverview } = require('/opt/gh-aw/actions/generate_workflow_overview.cjs'); - await generateWorkflowOverview(core); - - name: Download prompt artifact - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 - with: - name: prompt - path: /tmp/gh-aw/aw-prompts - - name: Clean git credentials - run: bash /opt/gh-aw/actions/clean_git_credentials.sh - - name: Execute GitHub Copilot CLI - id: agentic_execution - # Copilot CLI tool arguments (sorted): - timeout-minutes: 90 - run: | - set -o pipefail - sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --allow-domains '*.githubusercontent.com,*.jsr.io,*.pythonhosted.org,*.rvm.io,agents-md-generator.fastmcp.app,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.rubygems.org,api.snapcraft.io,archive.ubuntu.com,artifacts.elastic.co,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,bun.sh,bundler.rubygems.org,cache.ruby-lang.org,cdn.jsdelivr.net,cloud.elastic.co,codeload.github.com,conda.anaconda.org,conda.binstar.org,crates.io,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,deb.nodesource.com,deno.land,ela.st,elastic.co,esm.sh,files.pythonhosted.org,gems.rubyforge.org,gems.rubyonrails.org,get.pnpm.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,host.docker.internal,index.crates.io,index.rubygems.org,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,lfs.github.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,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,pip.pypa.io,pkg.go.dev,ppa.launchpad.net,proxy.golang.org,public-code-search.fastmcp.app,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.bower.io,registry.npmjs.com,registry.npmjs.org,registry.yarnpkg.com,repo.anaconda.com,repo.continuum.io,repo.yarnpkg.com,rubygems.org,rubygems.pkg.github.com,s.symcb.com,s.symcd.com,security.ubuntu.com,skimdb.npmjs.com,static.crates.io,storage.googleapis.com,sum.golang.org,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.elastic.co,www.npmjs.com,www.npmjs.org,yarnpkg.com' --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.20.2 --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 --model gpt-5.3-codex --allow-all-tools --allow-all-paths --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log - env: - COPILOT_AGENT_RUNNER_TYPE: STANDALONE - COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} - GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json - GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GITHUB_HEAD_REF: ${{ github.head_ref }} - GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - GITHUB_REF_NAME: ${{ github.ref_name }} - GITHUB_STEP_SUMMARY: ${{ env.GITHUB_STEP_SUMMARY }} - GITHUB_WORKSPACE: ${{ github.workspace }} - XDG_CONFIG_HOME: /home/runner - - name: Configure Git credentials - env: - REPO_NAME: ${{ github.repository }} - SERVER_URL: ${{ github.server_url }} - run: | - git config --global user.email "github-actions[bot]@users.noreply.github.com" - git config --global user.name "github-actions[bot]" - # Re-authenticate git with GitHub token - SERVER_URL_STRIPPED="${SERVER_URL#https://}" - git remote set-url origin "https://x-access-token:${{ github.token }}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" - echo "Git configured with standard GitHub Actions identity" - - name: Copy Copilot session state files to logs - if: always() - continue-on-error: true - run: | - # Copy Copilot session state files to logs folder for artifact collection - # This ensures they are in /tmp/gh-aw/ where secret redaction can scan them - SESSION_STATE_DIR="$HOME/.copilot/session-state" - LOGS_DIR="/tmp/gh-aw/sandbox/agent/logs" - - if [ -d "$SESSION_STATE_DIR" ]; then - echo "Copying Copilot session state files from $SESSION_STATE_DIR to $LOGS_DIR" - mkdir -p "$LOGS_DIR" - cp -v "$SESSION_STATE_DIR"/*.jsonl "$LOGS_DIR/" 2>/dev/null || true - echo "Session state files copied successfully" - else - echo "No session-state directory found at $SESSION_STATE_DIR" - fi - - name: Stop MCP Gateway - if: always() - continue-on-error: true - env: - MCP_GATEWAY_PORT: ${{ steps.start-mcp-gateway.outputs.gateway-port }} - MCP_GATEWAY_API_KEY: ${{ steps.start-mcp-gateway.outputs.gateway-api-key }} - GATEWAY_PID: ${{ steps.start-mcp-gateway.outputs.gateway-pid }} - run: | - bash /opt/gh-aw/actions/stop_mcp_gateway.sh "$GATEWAY_PID" - - name: Redact secrets in logs - if: always() - 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/redact_secrets.cjs'); - await main(); - env: - GH_AW_SECRET_NAMES: 'COPILOT_GITHUB_TOKEN,GH_AW_GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,GITHUB_TOKEN' - SECRET_COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} - SECRET_GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} - SECRET_GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} - SECRET_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Upload Safe Outputs - if: always() - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 - with: - name: safe-output - path: ${{ env.GH_AW_SAFE_OUTPUTS }} - if-no-files-found: warn - - name: Ingest agent output - id: collect_output - if: always() - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,*.jsr.io,*.pythonhosted.org,*.rvm.io,agents-md-generator.fastmcp.app,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.rubygems.org,api.snapcraft.io,archive.ubuntu.com,artifacts.elastic.co,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,bun.sh,bundler.rubygems.org,cache.ruby-lang.org,cdn.jsdelivr.net,cloud.elastic.co,codeload.github.com,conda.anaconda.org,conda.binstar.org,crates.io,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,deb.nodesource.com,deno.land,ela.st,elastic.co,esm.sh,files.pythonhosted.org,gems.rubyforge.org,gems.rubyonrails.org,get.pnpm.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,host.docker.internal,index.crates.io,index.rubygems.org,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,lfs.github.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,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,pip.pypa.io,pkg.go.dev,ppa.launchpad.net,proxy.golang.org,public-code-search.fastmcp.app,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.bower.io,registry.npmjs.com,registry.npmjs.org,registry.yarnpkg.com,repo.anaconda.com,repo.continuum.io,repo.yarnpkg.com,rubygems.org,rubygems.pkg.github.com,s.symcb.com,s.symcd.com,security.ubuntu.com,skimdb.npmjs.com,static.crates.io,storage.googleapis.com,sum.golang.org,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.elastic.co,www.npmjs.com,www.npmjs.org,yarnpkg.com" - GITHUB_SERVER_URL: ${{ github.server_url }} - GITHUB_API_URL: ${{ github.api_url }} - 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/collect_ndjson_output.cjs'); - await main(); - - name: Upload sanitized agent output - if: always() && env.GH_AW_AGENT_OUTPUT - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 - with: - name: agent-output - path: ${{ env.GH_AW_AGENT_OUTPUT }} - if-no-files-found: warn - - name: Upload engine output files - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 - with: - name: agent_outputs - path: | - /tmp/gh-aw/sandbox/agent/logs/ - /tmp/gh-aw/redacted-urls.log - if-no-files-found: ignore - - name: Parse agent logs for step summary - if: always() - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_AGENT_OUTPUT: /tmp/gh-aw/sandbox/agent/logs/ - 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/parse_copilot_log.cjs'); - await main(); - - name: Parse Safe Inputs logs for step summary - if: always() - 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/parse_safe_inputs_logs.cjs'); - await main(); - - name: Parse MCP Gateway logs for step summary - if: always() - 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/parse_mcp_gateway_log.cjs'); - await main(); - - name: Print firewall logs - if: always() - continue-on-error: true - env: - AWF_LOGS_DIR: /tmp/gh-aw/sandbox/firewall/logs - run: | - # Fix permissions on firewall logs so they can be uploaded as artifacts - # AWF runs with sudo, creating files owned by root - sudo chmod -R a+r /tmp/gh-aw/sandbox/firewall/logs 2>/dev/null || true - # Only run awf logs summary if awf command exists (it may not be installed if workflow failed before install step) - if command -v awf &> /dev/null; then - awf logs summary | tee -a "$GITHUB_STEP_SUMMARY" - else - echo 'AWF binary not installed, skipping firewall log summary' - fi - - name: Upload agent artifacts - if: always() - continue-on-error: true - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 - with: - name: agent-artifacts - path: | - /tmp/gh-aw/aw-prompts/prompt.txt - /tmp/gh-aw/aw_info.json - /tmp/gh-aw/mcp-logs/ - /tmp/gh-aw/safe-inputs/logs/ - /tmp/gh-aw/sandbox/firewall/logs/ - /tmp/gh-aw/agent-stdio.log - /tmp/gh-aw/agent/ - /tmp/gh-aw/aw.patch - if-no-files-found: ignore - - conclusion: - needs: - - activation - - agent - - detection - - safe_outputs - if: (always()) && (needs.agent.result != 'skipped') - runs-on: ubuntu-slim - permissions: - contents: write - issues: write - pull-requests: write - outputs: - noop_message: ${{ steps.noop.outputs.noop_message }} - tools_reported: ${{ steps.missing_tool.outputs.tools_reported }} - total_count: ${{ steps.missing_tool.outputs.total_count }} - steps: - - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 - with: - destination: /opt/gh-aw/actions - - name: Download agent output artifact - continue-on-error: true - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 - with: - name: agent-output - path: /tmp/gh-aw/safeoutputs/ - - name: Setup agent output environment variable - run: | - mkdir -p /tmp/gh-aw/safeoutputs/ - find "/tmp/gh-aw/safeoutputs/" -type f -print - echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/safeoutputs/agent_output.json" >> "$GITHUB_ENV" - - name: Process No-Op Messages - id: noop - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_NOOP_MAX: 1 - GH_AW_WORKFLOW_NAME: "Test Improvement" - with: - github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - script: | - const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io); - const { main } = require('/opt/gh-aw/actions/noop.cjs'); - await main(); - - name: Record Missing Tool - id: missing_tool - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_WORKFLOW_NAME: "Test Improvement" - with: - github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - script: | - const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io); - const { main } = require('/opt/gh-aw/actions/missing_tool.cjs'); - await main(); - - name: Handle Agent Failure - id: handle_agent_failure - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_WORKFLOW_NAME: "Test Improvement" - 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: "gh-aw-test-improvement" - GH_AW_SECRET_VERIFICATION_RESULT: ${{ needs.agent.outputs.secret_verification_result }} - GH_AW_CHECKOUT_PR_SUCCESS: ${{ needs.agent.outputs.checkout_pr_success }} - GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\"}" - GH_AW_GROUP_REPORTS: "false" - with: - github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - script: | - const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io); - const { main } = require('/opt/gh-aw/actions/handle_agent_failure.cjs'); - await main(); - - name: Handle No-Op Message - id: handle_noop_message - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_WORKFLOW_NAME: "Test Improvement" - 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 }} - GH_AW_NOOP_REPORT_AS_ISSUE: "true" - with: - github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - script: | - const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io); - const { main } = require('/opt/gh-aw/actions/handle_noop_message.cjs'); - await main(); - - name: Handle Create Pull Request Error - id: handle_create_pr_error - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_WORKFLOW_NAME: "Test Improvement" - GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} - with: - github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - script: | - const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io); - const { main } = require('/opt/gh-aw/actions/handle_create_pr_error.cjs'); - await main(); - - detection: - needs: agent - if: needs.agent.outputs.output_types != '' || needs.agent.outputs.has_patch == 'true' - runs-on: ubuntu-latest - permissions: {} - concurrency: - group: "gh-aw-copilot-${{ github.workflow }}" - timeout-minutes: 10 - outputs: - success: ${{ steps.parse_results.outputs.success }} - steps: - - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 - with: - destination: /opt/gh-aw/actions - - name: Download agent artifacts - continue-on-error: true - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 - with: - name: agent-artifacts - path: /tmp/gh-aw/threat-detection/ - - name: Download agent output artifact - continue-on-error: true - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 - with: - name: agent-output - path: /tmp/gh-aw/threat-detection/ - - name: Print agent output types - env: - AGENT_OUTPUT_TYPES: ${{ needs.agent.outputs.output_types }} - run: | - echo "Agent output-types: $AGENT_OUTPUT_TYPES" - - name: Setup threat detection - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - WORKFLOW_NAME: "Test Improvement" - WORKFLOW_DESCRIPTION: "Add focused tests for under-tested code and clean up redundant tests" - HAS_PATCH: ${{ needs.agent.outputs.has_patch }} - 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/setup_threat_detection.cjs'); - await main(); - - name: Ensure threat-detection directory and log - run: | - mkdir -p /tmp/gh-aw/threat-detection - touch /tmp/gh-aw/threat-detection/detection.log - - name: Validate COPILOT_GITHUB_TOKEN secret - id: validate-secret - run: /opt/gh-aw/actions/validate_multi_secret.sh COPILOT_GITHUB_TOKEN 'GitHub Copilot CLI' https://github.github.com/gh-aw/reference/engines/#github-copilot-default - env: - COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} - - name: Install GitHub Copilot CLI - run: /opt/gh-aw/actions/install_copilot_cli.sh 0.0.412 - - name: Execute GitHub Copilot CLI - id: agentic_execution - # Copilot CLI tool arguments (sorted): - # --allow-tool shell(cat) - # --allow-tool shell(grep) - # --allow-tool shell(head) - # --allow-tool shell(jq) - # --allow-tool shell(ls) - # --allow-tool shell(tail) - # --allow-tool shell(wc) - timeout-minutes: 20 - run: | - set -o pipefail - COPILOT_CLI_INSTRUCTION="$(cat /tmp/gh-aw/aw-prompts/prompt.txt)" - mkdir -p /tmp/ - mkdir -p /tmp/gh-aw/ - mkdir -p /tmp/gh-aw/agent/ - mkdir -p /tmp/gh-aw/sandbox/agent/logs/ - copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --model gpt-5.3-codex --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log - env: - COPILOT_AGENT_RUNNER_TYPE: STANDALONE - COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} - GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - GITHUB_HEAD_REF: ${{ github.head_ref }} - GITHUB_REF_NAME: ${{ github.ref_name }} - GITHUB_STEP_SUMMARY: ${{ env.GITHUB_STEP_SUMMARY }} - GITHUB_WORKSPACE: ${{ github.workspace }} - XDG_CONFIG_HOME: /home/runner - - name: Parse threat detection results - id: parse_results - 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/parse_threat_detection_results.cjs'); - await main(); - - name: Upload threat detection log - if: always() - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 - with: - name: threat-detection.log - path: /tmp/gh-aw/threat-detection/detection.log - if-no-files-found: ignore - - pre_activation: - runs-on: ubuntu-slim - outputs: - activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} - steps: - - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 - with: - destination: /opt/gh-aw/actions - - name: Check team membership for workflow - id: check_membership - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_REQUIRED_ROLES: admin,maintainer,write - GH_AW_ALLOWED_BOTS: ${{ inputs.allowed-bot-users }} - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - 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_membership.cjs'); - await main(); - - safe_outputs: - needs: - - activation - - agent - - detection - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (needs.detection.outputs.success == 'true') - runs-on: ubuntu-slim - permissions: - contents: write - issues: write - pull-requests: write - timeout-minutes: 15 - env: - GH_AW_ENGINE_ID: "copilot" - GH_AW_ENGINE_MODEL: "gpt-5.3-codex" - GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\"}" - GH_AW_WORKFLOW_ID: "gh-aw-test-improvement" - GH_AW_WORKFLOW_NAME: "Test Improvement" - outputs: - create_discussion_error_count: ${{ steps.process_safe_outputs.outputs.create_discussion_error_count }} - create_discussion_errors: ${{ steps.process_safe_outputs.outputs.create_discussion_errors }} - process_safe_outputs_processed_count: ${{ steps.process_safe_outputs.outputs.processed_count }} - process_safe_outputs_temporary_id_map: ${{ steps.process_safe_outputs.outputs.temporary_id_map }} - steps: - - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 - with: - destination: /opt/gh-aw/actions - - name: Download agent output artifact - continue-on-error: true - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 - with: - name: agent-output - path: /tmp/gh-aw/safeoutputs/ - - name: Setup agent output environment variable - run: | - mkdir -p /tmp/gh-aw/safeoutputs/ - find "/tmp/gh-aw/safeoutputs/" -type f -print - echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/safeoutputs/agent_output.json" >> "$GITHUB_ENV" - - name: Download patch artifact - continue-on-error: true - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 - with: - name: agent-artifacts - path: /tmp/gh-aw/ - - name: Checkout repository - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - ref: ${{ github.ref_name }} - token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - persist-credentials: false - fetch-depth: 1 - - name: Configure Git credentials - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) - env: - REPO_NAME: ${{ github.repository }} - SERVER_URL: ${{ github.server_url }} - GIT_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - run: | - git config --global user.email "github-actions[bot]@users.noreply.github.com" - git config --global user.name "github-actions[bot]" - # Re-authenticate git with GitHub token - SERVER_URL_STRIPPED="${SERVER_URL#https://}" - git remote set-url origin "https://x-access-token:${GIT_TOKEN}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" - echo "Git configured with standard GitHub Actions identity" - - name: Process Safe Outputs - id: process_safe_outputs - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_pull_request\":{\"base_branch\":\"${{ github.ref_name }}\",\"max\":1,\"max_patch_size\":1024},\"missing_data\":{},\"missing_tool\":{}}" - with: - github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - script: | - const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io); - const { main } = require('/opt/gh-aw/actions/safe_output_handler_manager.cjs'); - await main(); - - name: Upload safe output items manifest - if: always() - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 - with: - name: safe-output-items - path: /tmp/safe-output-items.jsonl - if-no-files-found: warn - diff --git a/.github/workflows/gh-aw-test-improvement.lock.yml b/.github/workflows/gh-aw-test-improvement.lock.yml new file mode 120000 index 00000000..409f2a29 --- /dev/null +++ b/.github/workflows/gh-aw-test-improvement.lock.yml @@ -0,0 +1 @@ +gh-aw-test-improver.lock.yml \ No newline at end of file diff --git a/.github/workflows/gh-aw-test-improver.lock.yml b/.github/workflows/gh-aw-test-improver.lock.yml new file mode 100644 index 00000000..c24e28ff --- /dev/null +++ b/.github/workflows/gh-aw-test-improver.lock.yml @@ -0,0 +1,1571 @@ +# +# ___ _ _ +# / _ \ | | (_) +# | |_| | __ _ ___ _ __ | |_ _ ___ +# | _ |/ _` |/ _ \ '_ \| __| |/ __| +# | | | | (_| | __/ | | | |_| | (__ +# \_| |_/\__, |\___|_| |_|\__|_|\___| +# __/ | +# _ _ |___/ +# | | | | / _| | +# | | | | ___ _ __ _ __| |_| | _____ ____ +# | |/\| |/ _ \ '__| |/ /| _| |/ _ \ \ /\ / / ___| +# \ /\ / (_) | | | | ( | | | | (_) \ V V /\__ \ +# \/ \/ \___/|_| |_|\_\|_| |_|\___/ \_/\_/ |___/ +# +# This file was automatically generated by gh-aw. DO NOT EDIT. +# +# To update this file, edit the corresponding .md file and run: +# gh aw compile +# Not all edits will cause changes to this file. +# +# For more information: https://github.github.com/gh-aw/introduction/overview/ +# +# Add focused tests for under-tested code and clean up redundant tests +# +# Resolved workflow manifest: +# Imports: +# - gh-aw-fragments/elastic-tools.md +# - gh-aw-fragments/formatting.md +# - gh-aw-fragments/mcp-pagination.md +# - gh-aw-fragments/messages-footer.md +# - gh-aw-fragments/rigor.md +# - gh-aw-fragments/runtime-setup.md +# - gh-aw-fragments/safe-output-create-pr.md +# - gh-aw-fragments/workflow-edit-guardrails.md +# +# inlined-imports: true +# +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"c1429c3c1b7b155be7afa26dd65308b3a995c2ef7a32a88f999213c273cc962e"} + +name: "Test Improver" +"on": + # bots: # Bots processed as bot check in pre-activation job + # - ${{ inputs.allowed-bot-users }} # Bots processed as bot check in pre-activation job + # roles: # Roles processed as role check in pre-activation job + # - admin # Roles processed as role check in pre-activation job + # - maintainer # Roles processed as role check in pre-activation job + # - write # Roles processed as role check in pre-activation job + workflow_call: + inputs: + additional-instructions: + default: "" + description: Repo-specific instructions appended to the agent prompt + required: false + type: string + allowed-bot-users: + default: github-actions[bot] + description: Allowlisted bot actor usernames (comma-separated) + required: false + type: string + messages-footer: + default: "" + description: Footer appended to all agent comments and reviews + required: false + type: string + model: + default: gpt-5.3-codex + description: AI model to use + required: false + type: string + setup-commands: + default: "" + description: Shell commands to run before the agent starts (dependency install, build, etc.) + required: false + type: string + secrets: + COPILOT_GITHUB_TOKEN: + required: true + +permissions: {} + +concurrency: + cancel-in-progress: true + group: test-improver + +run-name: "Test Improver" + +jobs: + activation: + needs: pre_activation + if: needs.pre_activation.outputs.activated == 'true' + runs-on: ubuntu-slim + permissions: + contents: read + outputs: + comment_id: "" + comment_repo: "" + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 + with: + destination: /opt/gh-aw/actions + - name: Validate context variables + 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/validate_context_variables.cjs'); + await main(); + - name: Checkout .github and .agents folders + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + sparse-checkout: | + .github + .agents + fetch-depth: 1 + persist-credentials: false + - name: Check workflow file timestamps + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_WORKFLOW_FILE: "gh-aw-test-improver.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: Create prompt with built-in context + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} + GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} + GH_AW_GITHUB_ACTOR: ${{ github.actor }} + GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} + GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} + GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} + GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} + GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} + GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} + run: | + bash /opt/gh-aw/actions/create_prompt_first.sh + cat << 'GH_AW_PROMPT_EOF' > "$GH_AW_PROMPT" + + GH_AW_PROMPT_EOF + cat "/opt/gh-aw/prompts/xpia.md" >> "$GH_AW_PROMPT" + cat "/opt/gh-aw/prompts/temp_folder_prompt.md" >> "$GH_AW_PROMPT" + cat "/opt/gh-aw/prompts/markdown.md" >> "$GH_AW_PROMPT" + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + + GitHub API Access Instructions + + The gh CLI is NOT authenticated. Do NOT use gh commands for GitHub operations. + + + To create or modify GitHub resources (issues, discussions, pull requests, etc.), you MUST call the appropriate safe output tool. Simply writing content will NOT work - the workflow requires actual tool calls. + + Temporary IDs: Some safe output tools support a temporary ID field (usually named temporary_id) so you can reference newly-created items elsewhere in the SAME agent output (for example, using #aw_abc1 in a later body). + + **IMPORTANT - temporary_id format rules:** + - If you DON'T need to reference the item later, OMIT the temporary_id field entirely (it will be auto-generated if needed) + - If you DO need cross-references/chaining, you MUST match this EXACT validation regex: /^aw_[A-Za-z0-9]{3,8}$/i + - Format: aw_ prefix followed by 3 to 8 alphanumeric characters (A-Z, a-z, 0-9, case-insensitive) + - Valid alphanumeric characters: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 + - INVALID examples: aw_ab (too short), aw_123456789 (too long), aw_test-id (contains hyphen), aw_id_123 (contains underscore) + - VALID examples: aw_abc, aw_abc1, aw_Test123, aw_A1B2C3D4, aw_12345678 + - To generate valid IDs: use 3-8 random alphanumeric characters or omit the field to let the system auto-generate + + Do NOT invent other aw_* formats — downstream steps will reject them with validation errors matching against /^aw_[A-Za-z0-9]{3,8}$/i. + + Discover available tools from the safeoutputs MCP server. + + **Critical**: Tool calls write structured data that downstream jobs process. Without tool calls, follow-up actions will be skipped. + + **Note**: If you made no other safe output tool calls during this workflow execution, call the "noop" tool to provide a status message indicating completion or that no actions were needed. + + --- + + ## Creating a Pull Request, Reporting Missing Tools or Functionality, Reporting Missing Data + + **IMPORTANT**: To perform the actions listed above, use the **safeoutputs** tools. Do NOT use `gh`, do NOT call the GitHub API directly. You do not have write access to the GitHub repository. + + **Creating a Pull Request** + + To create a pull request: + 1. Make any file changes directly in the working directory. + 2. If you haven't done so already, create a local branch using an appropriate unique name. + 3. Add and commit your changes to the branch. Be careful to add exactly the files you intend, and check there are no extra files left un-added. Verify you haven't deleted or changed any files you didn't intend to. + 4. Do not push your changes. That will be done by the tool. + 5. Create the pull request with the create_pull_request tool from safeoutputs. + + **Reporting Missing Tools or Functionality** + + To report a missing tool or capability, use the missing_tool tool from safeoutputs. + + **Reporting Missing Data** + + To report missing data required to achieve a goal, use the missing_data tool from safeoutputs. + + + + + The following GitHub context information is available for this workflow: + {{#if __GH_AW_GITHUB_ACTOR__ }} + - **actor**: __GH_AW_GITHUB_ACTOR__ + {{/if}} + {{#if __GH_AW_GITHUB_REPOSITORY__ }} + - **repository**: __GH_AW_GITHUB_REPOSITORY__ + {{/if}} + {{#if __GH_AW_GITHUB_WORKSPACE__ }} + - **workspace**: __GH_AW_GITHUB_WORKSPACE__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_ISSUE_NUMBER__ }} + - **issue-number**: #__GH_AW_GITHUB_EVENT_ISSUE_NUMBER__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__ }} + - **discussion-number**: #__GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__ }} + - **pull-request-number**: #__GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_COMMENT_ID__ }} + - **comment-id**: __GH_AW_GITHUB_EVENT_COMMENT_ID__ + {{/if}} + {{#if __GH_AW_GITHUB_RUN_ID__ }} + - **workflow-run-id**: __GH_AW_GITHUB_RUN_ID__ + {{/if}} + + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + ## MCP Servers + + - **`generate_agents_md`** — generates a summary of the repository's structure, conventions, and coding guidelines from AGENTS.md and related files. Call at the start of every workflow to get repo context. + - **`search_code`** — grep-style search across public GitHub repositories. Use for finding usage patterns in upstream libraries, reference implementations, or examples in open-source projects. This searches *public GitHub repos*, not the local codebase — if available you can use `grep` and file reading for local code. + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + ## Formatting Guidelines + + - Lead with the most important information — your first sentence should be the key takeaway + - Be concise and actionable — no filler or praise + - Use `
` and `` tags for long sections to keep responses scannable + - Wrap branch names and @-references in backticks to avoid pinging users + - Include code snippets with file paths and line numbers when referencing the codebase + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + ## Rigor + + **Silence is better than noise. A false positive wastes a human's time and erodes trust in every future report.** + + - If you claim something is missing or broken, show the exact evidence in the code — file path, line number, and what you observed. + - If a conclusion depends on assumptions you haven't confirmed, do not assert it. Verify first; if you cannot verify, do not report. + - "I don't know" is better than a wrong answer. `noop` is better than a speculative finding. + - It's worth the time to verify now versus guessing and forcing someone else to verify later. + - Before filing any issue or opening any PR, re-read your own output as a skeptical reviewer. Ask: "Would a senior engineer on this team find this useful, or would they close it immediately?" If the answer is "close," call `noop` instead. + - Only report findings you would confidently defend in a code review. If you feel the need to hedge with "might," "could," or "possibly," the finding is not ready to file. + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + ## MCP Pagination + + MCP tool responses have a **25,000 token limit**. When responses exceed this limit, the call fails and you must retry with pagination — wasting turns and tokens. Use proactive pagination to stay under the limit. + + ### Recommended `perPage` Values + + - **5-10**: For detailed items (PR diffs, files with patches, issues with comments) + - **20-30**: For medium-detail lists (commits, review comments, issue lists) + - **50-100**: For simple list operations (branches, labels, tags) + + ### Pagination Pattern + + When you need all results from a paginated API: + + 1. Fetch the first page with a conservative `perPage` value + 2. Process the results before fetching the next page + 3. Continue fetching pages until you receive fewer results than `perPage` (indicating the last page) + + ### Error Recovery + + If you see an error like: + - `MCP tool response exceeds maximum allowed tokens (25000)` + - `Response too large for tool [tool_name]` + + Retry the same call with a smaller `perPage` value (halve it). + + ### Tips + + - **Start small**: It's better to make multiple small requests than one that fails + - **Fetch incrementally**: Get an overview first, then details for specific items + - **Use filters**: Combine `perPage` with state, label, or date filters to reduce result size + - **Process as you go**: Don't accumulate all pages before acting — process each batch immediately + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + ## Workflow Editing Guardrails + + - Do not modify files under `.github/workflows/`. + - If asked to change workflow files, place a copy under `github/` (no leading dot) and note that a maintainer must relocate it into `.github/workflows/`. + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + ## Message Footer + + A footer is automatically appended to all comments and reviews. Do not add your own footer or sign-off — the runtime handles this. + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + Before calling `create_pull_request`, call `ready_to_make_pr` and apply its checklist. + + ## create-pull-request Limitations + + - **Patch files**: Max 100 files per PR. If changes span more files, split into multiple focused PRs. + - **Patch size**: Max 1,024 KB by default. Keep changes focused. + - **Title**: Max 128 characters. Sanitized. + - **Body**: No explicit mention/link limits, but bot triggers (`fixes #123`, `closes #456`) are neutralized. + - **Committed changes required**: You must have locally committed changes before creating a PR (unless `allow_empty` is configured). + - **Base branch**: Must be configured in the safe-output config. The PR targets this branch. + - **Max per run**: Typically 1 PR creation per workflow run. + - You may not submit code that modifies files in `.github/workflows/`. Doing so will cause the submission to be rejected. If asked to modify workflow files, propose the change in a copy placed in a `github/` folder (without the leading period) and note in the PR that the file needs to be relocated by someone with workflow write access. + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + # Test Improver Agent + + Identify under-tested code paths, add focused tests, and remove or consolidate duplicate or useless tests when safe. Open a single PR with the improvements. + + ## Context + + - **Repository**: __GH_AW_GITHUB_REPOSITORY__ + + ## Constraints + + - **CAN**: Read files, search code, modify files locally, run tests and commands, create a pull request. + - **CANNOT**: Push directly to the repository — use `create_pull_request`. + - **Only one PR per run.** + - No large refactors; prioritize targeted test additions or small cleanup of redundant tests. + - If the change set is large or unsafe, call `noop` with a brief reason. + - **Most runs should end with `noop`.** Only open a PR when the added tests are clearly valuable — they test real behavior, not trivial getters, and they would catch actual regressions. + + ## Step 1: Gather context + + 1. Call `generate_agents_md` to get repository conventions (if it fails, continue). + 2. Determine required repo commands (lint/build/test) and how to run tests: + - Check README, CONTRIBUTING, DEVELOPING, Makefile, CI config, package.json, pyproject.toml, and similar files. + 3. Identify coverage tooling (nyc, jest --coverage, pytest --cov, go test -cover, etc.). + - If coverage is available and reasonably fast, run it to find low-coverage files. + + ## Step 2: Identify targets + + - Prefer low-coverage or untested public APIs, error paths, or recent changes without tests. + - **Trace to user-facing behavior.** For every candidate, answer: "What end-to-end user action would exercise this code path?" If you cannot describe a concrete user scenario (e.g., "a user configures X and then Y happens"), the target is too internal to justify a PR. + - Prefer code paths reachable from public entry points (CLI commands, API endpoints, config parsing, UI interactions) over deeply internal helpers. + - Look for redundant tests: + - identical assertions or test bodies, + - tests that only duplicate coverage from more comprehensive tests. + - Only remove or merge tests when a clearer, equivalent test remains. + + ## Step 3: Implement improvements + + 1. Add minimal, focused tests in existing test suites. + 2. Keep production code changes minimal and only when needed to enable testing. + 3. Consolidate or remove redundant tests if safe, keeping behavior coverage intact. + + ## Step 4: Verify + + - Run required repo commands (lint/build/test) relevant to the change and capture results. + - Run the most relevant test command(s). **All tests — new and existing — must pass.** If the full suite is too heavy, run targeted tests. + - If required commands, tests, or coverage cannot be run, call `noop`. Do not open a PR with untested test code. + + ## Step 5: Quality Gate — Test Value Check + + Before creating the PR, evaluate each new test: + + - **Does it test real behavior?** Tests for trivial getters, simple constructors, or obvious pass-through functions are not worth filing a PR for. + - **Would it catch a real regression?** If the tested code changed in a buggy way, would this test actually fail? + - **Can you describe the user scenario?** For each test, you must be able to state: "A user doing [action] would hit this code path when [condition]." If you cannot connect the test to a describable end-to-end user experience, drop it. + - **Is it maintainable?** Fragile tests that break on cosmetic changes (string formatting, log messages) add burden, not value. + - **Does it follow project conventions?** Match the existing test style, naming, and organization. + + If the tests don't pass this bar, call `noop`. Low-value tests are worse than no tests — they create maintenance burden and false confidence. + + ## Step 6: Create the PR + + 1. Commit the changes locally. + 2. Call `create_pull_request` with: + - **Title**: concise summary of the test improvements + - **Body** must include: + - Summary of what changed + - **User scenario**: for each test, describe the real-world user action or workflow that exercises the tested code path (e.g., "When a user runs `beat setup` with an invalid config, this error path is triggered") + - Why the tests matter — what regressions they would catch + - Tests run and their results + - Any removed or merged tests + 3. If no safe improvements are found, call `noop` with a brief reason. + + __GH_AW_EXPR_49B959F1__ + + GH_AW_PROMPT_EOF + - name: Interpolate variables and render templates + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} + GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} + 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/interpolate_prompt.cjs'); + await main(); + - name: Substitute placeholders + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} + GH_AW_GITHUB_ACTOR: ${{ github.actor }} + GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} + GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} + GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} + 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'); + setupGlobals(core, github, context, exec, io); + + const substitutePlaceholders = require('/opt/gh-aw/actions/substitute_placeholders.cjs'); + + // Call the substitution function + return await substitutePlaceholders({ + file: process.env.GH_AW_PROMPT, + substitutions: { + GH_AW_EXPR_49B959F1: process.env.GH_AW_EXPR_49B959F1, + GH_AW_GITHUB_ACTOR: process.env.GH_AW_GITHUB_ACTOR, + GH_AW_GITHUB_EVENT_COMMENT_ID: process.env.GH_AW_GITHUB_EVENT_COMMENT_ID, + GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: process.env.GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER, + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: process.env.GH_AW_GITHUB_EVENT_ISSUE_NUMBER, + 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_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 + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + run: bash /opt/gh-aw/actions/validate_prompt_placeholders.sh + - name: Print prompt + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + run: bash /opt/gh-aw/actions/print_prompt_summary.sh + - name: Upload prompt artifact + if: success() + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: prompt + path: /tmp/gh-aw/aw-prompts/prompt.txt + retention-days: 1 + + agent: + needs: activation + runs-on: ubuntu-latest + permissions: + contents: read + issues: read + pull-requests: read + concurrency: + group: "gh-aw-copilot-${{ github.workflow }}" + env: + DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} + GH_AW_ASSETS_ALLOWED_EXTS: "" + GH_AW_ASSETS_BRANCH: "" + GH_AW_ASSETS_MAX_SIZE_KB: 0 + GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs + 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: ghawtestimprover + outputs: + checkout_pr_success: ${{ steps.checkout-pr.outputs.checkout_pr_success || 'true' }} + has_patch: ${{ steps.collect_output.outputs.has_patch }} + model: ${{ steps.generate_aw_info.outputs.model }} + output: ${{ steps.collect_output.outputs.output }} + output_types: ${{ steps.collect_output.outputs.output_types }} + secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 + with: + destination: /opt/gh-aw/actions + - name: Checkout repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + - name: Create gh-aw temp directory + run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh + - if: hashFiles('go.mod') != '' + name: Setup Go + uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5 + with: + cache: true + go-version-file: go.mod + - if: hashFiles('.python-version') != '' + name: Setup Python + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 + with: + python-version-file: .python-version + - if: hashFiles('.node-version') != '' + name: Setup Node.js (.node-version) + uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6 + with: + node-version-file: .node-version + - if: hashFiles('.node-version') == '' && hashFiles('.nvmrc') != '' + name: Setup Node.js (.nvmrc) + uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6 + with: + node-version-file: .nvmrc + - if: hashFiles('.ruby-version') != '' + name: Setup Ruby + uses: ruby/setup-ruby@09a7688d3b55cf0e976497ff046b70949eeaccfd # v1 + with: + bundler-cache: true + ruby-version: .ruby-version + - id: setup-uv + if: hashFiles('pyproject.toml', 'uv.lock') != '' + name: Setup uv + uses: astral-sh/setup-uv@e58605a9b6da7c637471fab8847a5e5a6b8df081 # v5 + - env: + UV_PATH: ${{ steps.setup-uv.outputs.uv-path }} + WORKSPACE: ${{ github.workspace }} + if: hashFiles('pyproject.toml', 'uv.lock') != '' + name: Expose uv in workspace + run: |- + set -euo pipefail + install_dir="$WORKSPACE/.gh-aw-tools/bin" + mkdir -p "$install_dir" + cp "$UV_PATH" "$install_dir/uv" + chmod +x "$install_dir/uv" + echo "$install_dir" >> "$GITHUB_PATH" + shell: bash + - env: + SETUP_COMMANDS: ${{ inputs.setup-commands }} + if: ${{ inputs.setup-commands != '' }} + name: Repo-specific setup + run: eval "$SETUP_COMMANDS" + + - name: Configure Git credentials + env: + REPO_NAME: ${{ github.repository }} + SERVER_URL: ${{ github.server_url }} + run: | + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git config --global user.name "github-actions[bot]" + # Re-authenticate git with GitHub token + SERVER_URL_STRIPPED="${SERVER_URL#https://}" + git remote set-url origin "https://x-access-token:${{ github.token }}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" + echo "Git configured with standard GitHub Actions identity" + - name: Checkout PR branch + id: checkout-pr + if: | + github.event.pull_request + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + with: + github-token: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/checkout_pr_branch.cjs'); + await main(); + - name: Generate agentic run info + id: generate_aw_info + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + with: + script: | + const fs = require('fs'); + + const awInfo = { + engine_id: "copilot", + engine_name: "GitHub Copilot CLI", + model: "${{ inputs.model }}", + version: "", + agent_version: "0.0.412", + workflow_name: "Test Improver", + experimental: false, + supports_tools_allowlist: true, + run_id: context.runId, + run_number: context.runNumber, + run_attempt: process.env.GITHUB_RUN_ATTEMPT, + repository: context.repo.owner + '/' + context.repo.repo, + ref: context.ref, + sha: context.sha, + actor: context.actor, + event_name: context.eventName, + staged: false, + allowed_domains: ["agents-md-generator.fastmcp.app","artifacts.elastic.co","cloud.elastic.co","defaults","ela.st","elastic.co","github","go","node","public-code-search.fastmcp.app","python","ruby","www.elastic.co"], + firewall_enabled: true, + awf_version: "v0.20.2", + awmg_version: "v0.1.4", + steps: { + firewall: "squid" + }, + created_at: new Date().toISOString() + }; + + // Write to /tmp/gh-aw directory to avoid inclusion in PR + const tmpPath = '/tmp/gh-aw/aw_info.json'; + fs.writeFileSync(tmpPath, JSON.stringify(awInfo, null, 2)); + console.log('Generated aw_info.json at:', tmpPath); + console.log(JSON.stringify(awInfo, null, 2)); + + // Set model as output for reuse in other steps/jobs + core.setOutput('model', awInfo.model); + - name: Validate COPILOT_GITHUB_TOKEN secret + id: validate-secret + run: /opt/gh-aw/actions/validate_multi_secret.sh COPILOT_GITHUB_TOKEN 'GitHub Copilot CLI' https://github.github.com/gh-aw/reference/engines/#github-copilot-default + env: + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + - name: Install GitHub Copilot CLI + run: /opt/gh-aw/actions/install_copilot_cli.sh 0.0.412 + - name: Install awf binary + run: bash /opt/gh-aw/actions/install_awf_binary.sh v0.20.2 + - name: Determine automatic lockdown mode for GitHub MCP Server + id: determine-automatic-lockdown + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} + GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} + with: + script: | + 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.20.2 ghcr.io/github/gh-aw-firewall/api-proxy:0.20.2 ghcr.io/github/gh-aw-firewall/squid:0.20.2 ghcr.io/github/gh-aw-mcpg:v0.1.4 ghcr.io/github/github-mcp-server:v0.31.0 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' + {"create_pull_request":{"max":1},"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 pull request to propose code changes. Use this after making file edits to submit them for review and merging. The PR will be created from the current branch with your committed changes. For code review comments on an existing PR, use create_pull_request_review_comment instead. CONSTRAINTS: Maximum 1 pull request(s) can be created.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "body": { + "description": "Detailed PR description in Markdown. Include what changes were made, why, testing notes, and any breaking changes. Do NOT repeat the title as a heading.", + "type": "string" + }, + "branch": { + "description": "Source branch name containing the changes. If omitted, uses the current working branch.", + "type": "string" + }, + "draft": { + "description": "Whether to create the PR as a draft. Draft PRs cannot be merged until marked as ready for review. Use mark_pull_request_as_ready_for_review to convert a draft PR. Default: true.", + "type": "boolean" + }, + "labels": { + "description": "Labels to categorize the PR (e.g., 'enhancement', 'bugfix'). Labels must exist in the repository.", + "items": { + "type": "string" + }, + "type": "array" + }, + "title": { + "description": "Concise PR title describing the changes. Follow repository conventions (e.g., conventional commits). The title appears as the main heading.", + "type": "string" + } + }, + "required": [ + "title", + "body" + ], + "type": "object" + }, + "name": "create_pull_request" + }, + { + "description": "Report that a tool or capability needed to complete the task is not available, or share any information you deem important about missing functionality or limitations. Use this when you cannot accomplish what was requested because the required functionality is missing or access is restricted.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "alternatives": { + "description": "Any workarounds, manual steps, or alternative approaches the user could take (max 256 characters).", + "type": "string" + }, + "reason": { + "description": "Explanation of why this tool is needed or what information you want to share about the limitation (max 256 characters).", + "type": "string" + }, + "tool": { + "description": "Optional: Name or description of the missing tool or capability (max 128 characters). Be specific about what functionality is needed.", + "type": "string" + } + }, + "required": [ + "reason" + ], + "type": "object" + }, + "name": "missing_tool" + }, + { + "description": "Log a transparency message when no significant actions are needed. Use this to confirm workflow completion and provide visibility when analysis is complete but no changes or outputs are required (e.g., 'No issues found', 'All checks passed'). This ensures the workflow produces human-visible output even when no other actions are taken.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "message": { + "description": "Status or completion message to log. Should explain what was analyzed and the outcome (e.g., 'Code review complete - no issues found', 'Analysis complete - all tests passing').", + "type": "string" + } + }, + "required": [ + "message" + ], + "type": "object" + }, + "name": "noop" + }, + { + "description": "Report that data or information needed to complete the task is not available. Use this when you cannot accomplish what was requested because required data, context, or information is missing.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "alternatives": { + "description": "Any workarounds, manual steps, or alternative approaches the user could take (max 256 characters).", + "type": "string" + }, + "context": { + "description": "Additional context about the missing data or where it should come from (max 256 characters).", + "type": "string" + }, + "data_type": { + "description": "Type or description of the missing data or information (max 128 characters). Be specific about what data is needed.", + "type": "string" + }, + "reason": { + "description": "Explanation of why this data is needed to complete the task (max 256 characters).", + "type": "string" + } + }, + "required": [], + "type": "object" + }, + "name": "missing_data" + } + ] + GH_AW_SAFE_OUTPUTS_TOOLS_EOF + cat > /opt/gh-aw/safeoutputs/validation.json << 'GH_AW_SAFE_OUTPUTS_VALIDATION_EOF' + { + "create_pull_request": { + "defaultMax": 1, + "fields": { + "body": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "branch": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "draft": { + "type": "boolean" + }, + "labels": { + "type": "array", + "itemType": "string", + "itemSanitize": true, + "itemMaxLength": 128 + }, + "repo": { + "type": "string", + "maxLength": 256 + }, + "title": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 128 + } + } + }, + "missing_data": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "context": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "data_type": { + "type": "string", + "sanitize": true, + "maxLength": 128 + }, + "reason": { + "type": "string", + "sanitize": true, + "maxLength": 256 + } + } + }, + "missing_tool": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 512 + }, + "reason": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "tool": { + "type": "string", + "sanitize": true, + "maxLength": 128 + } + } + }, + "noop": { + "defaultMax": 1, + "fields": { + "message": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + } + } + } + } + GH_AW_SAFE_OUTPUTS_VALIDATION_EOF + - name: Generate Safe Outputs MCP Server Config + id: safe-outputs-config + run: | + # Generate a secure random API key (360 bits of entropy, 40+ chars) + # Mask immediately to prevent timing vulnerabilities + API_KEY=$(openssl rand -base64 45 | tr -d '/+=') + echo "::add-mask::${API_KEY}" + + PORT=3001 + + # Set outputs for next steps + { + echo "safe_outputs_api_key=${API_KEY}" + echo "safe_outputs_port=${PORT}" + } >> "$GITHUB_OUTPUT" + + echo "Safe Outputs MCP server will run on port ${PORT}" + + - name: Start Safe Outputs MCP HTTP Server + id: safe-outputs-start + env: + DEBUG: '*' + GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-config.outputs.safe_outputs_port }} + GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-config.outputs.safe_outputs_api_key }} + GH_AW_SAFE_OUTPUTS_TOOLS_PATH: /opt/gh-aw/safeoutputs/tools.json + GH_AW_SAFE_OUTPUTS_CONFIG_PATH: /opt/gh-aw/safeoutputs/config.json + GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs + run: | + # Environment variables are set above to prevent template injection + export DEBUG + export GH_AW_SAFE_OUTPUTS_PORT + export GH_AW_SAFE_OUTPUTS_API_KEY + export GH_AW_SAFE_OUTPUTS_TOOLS_PATH + export GH_AW_SAFE_OUTPUTS_CONFIG_PATH + export GH_AW_MCP_LOG_DIR + + bash /opt/gh-aw/actions/start_safe_outputs_server.sh + + - name: Setup Safe Inputs Config + run: | + mkdir -p /opt/gh-aw/safe-inputs/logs + cat > /opt/gh-aw/safe-inputs/tools.json << 'GH_AW_SAFE_INPUTS_TOOLS_EOF' + { + "serverName": "safeinputs", + "version": "1.0.0", + "logDir": "/opt/gh-aw/safe-inputs/logs", + "tools": [ + { + "name": "ready-to-make-pr", + "description": "Run the PR readiness checklist before creating or updating a PR", + "inputSchema": { + "properties": {}, + "type": "object" + }, + "handler": "ready-to-make-pr.cjs", + "timeout": 60 + } + ] + } + GH_AW_SAFE_INPUTS_TOOLS_EOF + cat > /opt/gh-aw/safe-inputs/mcp-server.cjs << 'GH_AW_SAFE_INPUTS_SERVER_EOF' + const path = require("path"); + const { startHttpServer } = require("./safe_inputs_mcp_server_http.cjs"); + const configPath = path.join(__dirname, "tools.json"); + const port = parseInt(process.env.GH_AW_SAFE_INPUTS_PORT || "3000", 10); + const apiKey = process.env.GH_AW_SAFE_INPUTS_API_KEY || ""; + startHttpServer(configPath, { + port: port, + stateless: true, + logDir: "/opt/gh-aw/safe-inputs/logs" + }).catch(error => { + console.error("Failed to start safe-inputs HTTP server:", error); + process.exit(1); + }); + GH_AW_SAFE_INPUTS_SERVER_EOF + chmod +x /opt/gh-aw/safe-inputs/mcp-server.cjs + + - name: Setup Safe Inputs Tool Files + run: | + cat > /opt/gh-aw/safe-inputs/ready-to-make-pr.cjs << 'GH_AW_SAFE_INPUTS_JS_READY-TO-MAKE-PR_EOF' + async function execute(inputs) { + const fs = require('fs'); + const find = (...paths) => paths.find(p => fs.existsSync(p)) || null; + const contributing = find('CONTRIBUTING.md', 'CONTRIBUTING.rst', 'docs/CONTRIBUTING.md', 'docs/contributing.md'); + const prTemplate = find('.github/pull_request_template.md', '.github/PULL_REQUEST_TEMPLATE.md', '.github/PULL_REQUEST_TEMPLATE/pull_request_template.md'); + const checklist = []; + if (contributing) checklist.push(`Review the contributing guide (${contributing}) before opening or updating a PR.`); + if (prTemplate) checklist.push(`Follow the PR template (${prTemplate}) for title, description, and validation notes.`); + checklist.push('Confirm the requested task is fully completed and validated before creating or pushing PR changes.'); + return { status: 'ok', checklist, contributing_guide: contributing, pr_template: prTemplate }; + } + module.exports = { execute }; + GH_AW_SAFE_INPUTS_JS_READY-TO-MAKE-PR_EOF + + - name: Generate Safe Inputs MCP Server Config + id: safe-inputs-config + run: | + # Generate a secure random API key (360 bits of entropy, 40+ chars) + # Mask immediately to prevent timing vulnerabilities + API_KEY=$(openssl rand -base64 45 | tr -d '/+=') + echo "::add-mask::${API_KEY}" + + PORT=3000 + + # Set outputs for next steps + { + echo "safe_inputs_api_key=${API_KEY}" + echo "safe_inputs_port=${PORT}" + } >> "$GITHUB_OUTPUT" + + echo "Safe Inputs MCP server will run on port ${PORT}" + + - name: Start Safe Inputs MCP HTTP Server + id: safe-inputs-start + env: + DEBUG: '*' + GH_AW_SAFE_INPUTS_PORT: ${{ steps.safe-inputs-config.outputs.safe_inputs_port }} + GH_AW_SAFE_INPUTS_API_KEY: ${{ steps.safe-inputs-config.outputs.safe_inputs_api_key }} + run: | + # Environment variables are set above to prevent template injection + export DEBUG + export GH_AW_SAFE_INPUTS_PORT + export GH_AW_SAFE_INPUTS_API_KEY + + bash /opt/gh-aw/actions/start_safe_inputs_server.sh + + - name: Start MCP Gateway + id: start-mcp-gateway + env: + GH_AW_SAFE_INPUTS_API_KEY: ${{ steps.safe-inputs-start.outputs.api_key }} + GH_AW_SAFE_INPUTS_PORT: ${{ steps.safe-inputs-start.outputs.port }} + GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} + GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-start.outputs.api_key }} + GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-start.outputs.port }} + GITHUB_MCP_LOCKDOWN: ${{ steps.determine-automatic-lockdown.outputs.lockdown == 'true' && '1' || '0' }} + GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + run: | + set -eo pipefail + mkdir -p /tmp/gh-aw/mcp-config + + # Export gateway environment variables for MCP config and gateway script + export MCP_GATEWAY_PORT="80" + export MCP_GATEWAY_DOMAIN="host.docker.internal" + MCP_GATEWAY_API_KEY=$(openssl rand -base64 45 | tr -d '/+=') + echo "::add-mask::${MCP_GATEWAY_API_KEY}" + export MCP_GATEWAY_API_KEY + export MCP_GATEWAY_PAYLOAD_DIR="/tmp/gh-aw/mcp-payloads" + mkdir -p "${MCP_GATEWAY_PAYLOAD_DIR}" + export DEBUG="*" + + export GH_AW_ENGINE="copilot" + 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 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_LOCKDOWN -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_INPUTS_PORT -e GH_AW_SAFE_INPUTS_API_KEY -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.1.4' + + mkdir -p /home/runner/.copilot + cat << GH_AW_MCP_CONFIG_EOF | bash /opt/gh-aw/actions/start_mcp_gateway.sh + { + "mcpServers": { + "agents-md-generator": { + "type": "http", + "url": "https://agents-md-generator.fastmcp.app/mcp", + "tools": [ + "generate_agents_md" + ] + }, + "github": { + "type": "stdio", + "container": "ghcr.io/github/github-mcp-server:v0.31.0", + "env": { + "GITHUB_LOCKDOWN_MODE": "$GITHUB_MCP_LOCKDOWN", + "GITHUB_PERSONAL_ACCESS_TOKEN": "\${GITHUB_MCP_SERVER_TOKEN}", + "GITHUB_READ_ONLY": "1", + "GITHUB_TOOLSETS": "repos,issues,pull_requests,search" + } + }, + "public-code-search": { + "type": "http", + "url": "https://public-code-search.fastmcp.app/mcp", + "tools": [ + "search_code" + ] + }, + "safeinputs": { + "type": "http", + "url": "http://host.docker.internal:$GH_AW_SAFE_INPUTS_PORT", + "headers": { + "Authorization": "\${GH_AW_SAFE_INPUTS_API_KEY}" + } + }, + "safeoutputs": { + "type": "http", + "url": "http://host.docker.internal:$GH_AW_SAFE_OUTPUTS_PORT", + "headers": { + "Authorization": "\${GH_AW_SAFE_OUTPUTS_API_KEY}" + } + } + }, + "gateway": { + "port": $MCP_GATEWAY_PORT, + "domain": "${MCP_GATEWAY_DOMAIN}", + "apiKey": "${MCP_GATEWAY_API_KEY}", + "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" + } + } + GH_AW_MCP_CONFIG_EOF + - name: Generate workflow overview + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + with: + script: | + const { generateWorkflowOverview } = require('/opt/gh-aw/actions/generate_workflow_overview.cjs'); + await generateWorkflowOverview(core); + - name: Download prompt artifact + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 + with: + name: prompt + path: /tmp/gh-aw/aw-prompts + - name: Clean git credentials + run: bash /opt/gh-aw/actions/clean_git_credentials.sh + - name: Execute GitHub Copilot CLI + id: agentic_execution + # Copilot CLI tool arguments (sorted): + timeout-minutes: 90 + run: | + set -o pipefail + sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --allow-domains '*.githubusercontent.com,*.jsr.io,*.pythonhosted.org,*.rvm.io,agents-md-generator.fastmcp.app,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.rubygems.org,api.snapcraft.io,archive.ubuntu.com,artifacts.elastic.co,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,bun.sh,bundler.rubygems.org,cache.ruby-lang.org,cdn.jsdelivr.net,cloud.elastic.co,codeload.github.com,conda.anaconda.org,conda.binstar.org,crates.io,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,deb.nodesource.com,deno.land,ela.st,elastic.co,esm.sh,files.pythonhosted.org,gems.rubyforge.org,gems.rubyonrails.org,get.pnpm.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,host.docker.internal,index.crates.io,index.rubygems.org,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,lfs.github.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,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,pip.pypa.io,pkg.go.dev,ppa.launchpad.net,proxy.golang.org,public-code-search.fastmcp.app,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.bower.io,registry.npmjs.com,registry.npmjs.org,registry.yarnpkg.com,repo.anaconda.com,repo.continuum.io,repo.yarnpkg.com,rubygems.org,rubygems.pkg.github.com,s.symcb.com,s.symcd.com,security.ubuntu.com,skimdb.npmjs.com,static.crates.io,storage.googleapis.com,sum.golang.org,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.elastic.co,www.npmjs.com,www.npmjs.org,yarnpkg.com' --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.20.2 --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 --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log + env: + COPILOT_AGENT_RUNNER_TYPE: STANDALONE + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} + GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} + GITHUB_HEAD_REF: ${{ github.head_ref }} + GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + GITHUB_REF_NAME: ${{ github.ref_name }} + GITHUB_STEP_SUMMARY: ${{ env.GITHUB_STEP_SUMMARY }} + GITHUB_WORKSPACE: ${{ github.workspace }} + XDG_CONFIG_HOME: /home/runner + - name: Configure Git credentials + env: + REPO_NAME: ${{ github.repository }} + SERVER_URL: ${{ github.server_url }} + run: | + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git config --global user.name "github-actions[bot]" + # Re-authenticate git with GitHub token + SERVER_URL_STRIPPED="${SERVER_URL#https://}" + git remote set-url origin "https://x-access-token:${{ github.token }}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" + echo "Git configured with standard GitHub Actions identity" + - name: Copy Copilot session state files to logs + if: always() + continue-on-error: true + run: | + # Copy Copilot session state files to logs folder for artifact collection + # This ensures they are in /tmp/gh-aw/ where secret redaction can scan them + SESSION_STATE_DIR="$HOME/.copilot/session-state" + LOGS_DIR="/tmp/gh-aw/sandbox/agent/logs" + + if [ -d "$SESSION_STATE_DIR" ]; then + echo "Copying Copilot session state files from $SESSION_STATE_DIR to $LOGS_DIR" + mkdir -p "$LOGS_DIR" + cp -v "$SESSION_STATE_DIR"/*.jsonl "$LOGS_DIR/" 2>/dev/null || true + echo "Session state files copied successfully" + else + echo "No session-state directory found at $SESSION_STATE_DIR" + fi + - name: Stop MCP Gateway + if: always() + continue-on-error: true + env: + MCP_GATEWAY_PORT: ${{ steps.start-mcp-gateway.outputs.gateway-port }} + MCP_GATEWAY_API_KEY: ${{ steps.start-mcp-gateway.outputs.gateway-api-key }} + GATEWAY_PID: ${{ steps.start-mcp-gateway.outputs.gateway-pid }} + run: | + bash /opt/gh-aw/actions/stop_mcp_gateway.sh "$GATEWAY_PID" + - name: Redact secrets in logs + if: always() + 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/redact_secrets.cjs'); + await main(); + env: + GH_AW_SECRET_NAMES: 'COPILOT_GITHUB_TOKEN,GH_AW_GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,GITHUB_TOKEN' + SECRET_COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + SECRET_GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} + SECRET_GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} + SECRET_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Upload Safe Outputs + if: always() + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: safe-output + path: ${{ env.GH_AW_SAFE_OUTPUTS }} + if-no-files-found: warn + - name: Ingest agent output + id: collect_output + if: always() + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} + GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,*.jsr.io,*.pythonhosted.org,*.rvm.io,agents-md-generator.fastmcp.app,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.rubygems.org,api.snapcraft.io,archive.ubuntu.com,artifacts.elastic.co,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,bun.sh,bundler.rubygems.org,cache.ruby-lang.org,cdn.jsdelivr.net,cloud.elastic.co,codeload.github.com,conda.anaconda.org,conda.binstar.org,crates.io,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,deb.nodesource.com,deno.land,ela.st,elastic.co,esm.sh,files.pythonhosted.org,gems.rubyforge.org,gems.rubyonrails.org,get.pnpm.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,host.docker.internal,index.crates.io,index.rubygems.org,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,lfs.github.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,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,pip.pypa.io,pkg.go.dev,ppa.launchpad.net,proxy.golang.org,public-code-search.fastmcp.app,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.bower.io,registry.npmjs.com,registry.npmjs.org,registry.yarnpkg.com,repo.anaconda.com,repo.continuum.io,repo.yarnpkg.com,rubygems.org,rubygems.pkg.github.com,s.symcb.com,s.symcd.com,security.ubuntu.com,skimdb.npmjs.com,static.crates.io,storage.googleapis.com,sum.golang.org,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.elastic.co,www.npmjs.com,www.npmjs.org,yarnpkg.com" + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_API_URL: ${{ github.api_url }} + 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/collect_ndjson_output.cjs'); + await main(); + - name: Upload sanitized agent output + if: always() && env.GH_AW_AGENT_OUTPUT + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: agent-output + path: ${{ env.GH_AW_AGENT_OUTPUT }} + if-no-files-found: warn + - name: Upload engine output files + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: agent_outputs + path: | + /tmp/gh-aw/sandbox/agent/logs/ + /tmp/gh-aw/redacted-urls.log + if-no-files-found: ignore + - name: Parse agent logs for step summary + if: always() + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: /tmp/gh-aw/sandbox/agent/logs/ + 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/parse_copilot_log.cjs'); + await main(); + - name: Parse Safe Inputs logs for step summary + if: always() + 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/parse_safe_inputs_logs.cjs'); + await main(); + - name: Parse MCP Gateway logs for step summary + if: always() + 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/parse_mcp_gateway_log.cjs'); + await main(); + - name: Print firewall logs + if: always() + continue-on-error: true + env: + AWF_LOGS_DIR: /tmp/gh-aw/sandbox/firewall/logs + run: | + # Fix permissions on firewall logs so they can be uploaded as artifacts + # AWF runs with sudo, creating files owned by root + sudo chmod -R a+r /tmp/gh-aw/sandbox/firewall/logs 2>/dev/null || true + # Only run awf logs summary if awf command exists (it may not be installed if workflow failed before install step) + if command -v awf &> /dev/null; then + awf logs summary | tee -a "$GITHUB_STEP_SUMMARY" + else + echo 'AWF binary not installed, skipping firewall log summary' + fi + - name: Upload agent artifacts + if: always() + continue-on-error: true + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: agent-artifacts + path: | + /tmp/gh-aw/aw-prompts/prompt.txt + /tmp/gh-aw/aw_info.json + /tmp/gh-aw/mcp-logs/ + /tmp/gh-aw/safe-inputs/logs/ + /tmp/gh-aw/sandbox/firewall/logs/ + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/agent/ + /tmp/gh-aw/aw-*.patch + if-no-files-found: ignore + + conclusion: + needs: + - activation + - agent + - detection + - safe_outputs + if: (always()) && (needs.agent.result != 'skipped') + runs-on: ubuntu-slim + permissions: + contents: write + issues: write + pull-requests: write + outputs: + noop_message: ${{ steps.noop.outputs.noop_message }} + tools_reported: ${{ steps.missing_tool.outputs.tools_reported }} + total_count: ${{ steps.missing_tool.outputs.total_count }} + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 + with: + destination: /opt/gh-aw/actions + - name: Download agent output artifact + continue-on-error: true + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 + with: + name: agent-output + path: /tmp/gh-aw/safeoutputs/ + - name: Setup agent output environment variable + run: | + mkdir -p /tmp/gh-aw/safeoutputs/ + find "/tmp/gh-aw/safeoutputs/" -type f -print + echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/safeoutputs/agent_output.json" >> "$GITHUB_ENV" + - name: Process No-Op Messages + id: noop + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_NOOP_MAX: 1 + GH_AW_WORKFLOW_NAME: "Test Improver" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/noop.cjs'); + await main(); + - name: Record Missing Tool + id: missing_tool + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_WORKFLOW_NAME: "Test Improver" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/missing_tool.cjs'); + await main(); + - name: Handle Agent Failure + id: handle_agent_failure + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_WORKFLOW_NAME: "Test Improver" + 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: "gh-aw-test-improver" + GH_AW_SECRET_VERIFICATION_RESULT: ${{ needs.agent.outputs.secret_verification_result }} + GH_AW_CHECKOUT_PR_SUCCESS: ${{ needs.agent.outputs.checkout_pr_success }} + GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\"}" + GH_AW_GROUP_REPORTS: "false" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/handle_agent_failure.cjs'); + await main(); + - name: Handle No-Op Message + id: handle_noop_message + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_WORKFLOW_NAME: "Test Improver" + 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 }} + GH_AW_NOOP_REPORT_AS_ISSUE: "true" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/handle_noop_message.cjs'); + await main(); + - name: Handle Create Pull Request Error + id: handle_create_pr_error + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_WORKFLOW_NAME: "Test Improver" + GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/handle_create_pr_error.cjs'); + await main(); + + detection: + needs: agent + if: needs.agent.outputs.output_types != '' || needs.agent.outputs.has_patch == 'true' + runs-on: ubuntu-latest + permissions: {} + concurrency: + group: "gh-aw-copilot-${{ github.workflow }}" + timeout-minutes: 10 + outputs: + success: ${{ steps.parse_results.outputs.success }} + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 + with: + destination: /opt/gh-aw/actions + - name: Download agent artifacts + continue-on-error: true + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 + with: + name: agent-artifacts + path: /tmp/gh-aw/threat-detection/ + - name: Download agent output artifact + continue-on-error: true + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 + with: + name: agent-output + path: /tmp/gh-aw/threat-detection/ + - name: Print agent output types + env: + AGENT_OUTPUT_TYPES: ${{ needs.agent.outputs.output_types }} + run: | + echo "Agent output-types: $AGENT_OUTPUT_TYPES" + - name: Setup threat detection + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + WORKFLOW_NAME: "Test Improver" + WORKFLOW_DESCRIPTION: "Add focused tests for under-tested code and clean up redundant tests" + HAS_PATCH: ${{ needs.agent.outputs.has_patch }} + 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/setup_threat_detection.cjs'); + await main(); + - name: Ensure threat-detection directory and log + run: | + mkdir -p /tmp/gh-aw/threat-detection + touch /tmp/gh-aw/threat-detection/detection.log + - name: Validate COPILOT_GITHUB_TOKEN secret + id: validate-secret + run: /opt/gh-aw/actions/validate_multi_secret.sh COPILOT_GITHUB_TOKEN 'GitHub Copilot CLI' https://github.github.com/gh-aw/reference/engines/#github-copilot-default + env: + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + - name: Install GitHub Copilot CLI + run: /opt/gh-aw/actions/install_copilot_cli.sh 0.0.412 + - name: Execute GitHub Copilot CLI + id: agentic_execution + # Copilot CLI tool arguments (sorted): + # --allow-tool shell(cat) + # --allow-tool shell(grep) + # --allow-tool shell(head) + # --allow-tool shell(jq) + # --allow-tool shell(ls) + # --allow-tool shell(tail) + # --allow-tool shell(wc) + timeout-minutes: 20 + run: | + set -o pipefail + COPILOT_CLI_INSTRUCTION="$(cat /tmp/gh-aw/aw-prompts/prompt.txt)" + mkdir -p /tmp/ + mkdir -p /tmp/gh-aw/ + mkdir -p /tmp/gh-aw/agent/ + mkdir -p /tmp/gh-aw/sandbox/agent/logs/ + copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log + env: + COPILOT_AGENT_RUNNER_TYPE: STANDALONE + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GITHUB_HEAD_REF: ${{ github.head_ref }} + GITHUB_REF_NAME: ${{ github.ref_name }} + GITHUB_STEP_SUMMARY: ${{ env.GITHUB_STEP_SUMMARY }} + GITHUB_WORKSPACE: ${{ github.workspace }} + XDG_CONFIG_HOME: /home/runner + - name: Parse threat detection results + id: parse_results + 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/parse_threat_detection_results.cjs'); + await main(); + - name: Upload threat detection log + if: always() + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: threat-detection.log + path: /tmp/gh-aw/threat-detection/detection.log + if-no-files-found: ignore + + pre_activation: + runs-on: ubuntu-slim + outputs: + activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 + with: + destination: /opt/gh-aw/actions + - name: Check team membership for workflow + id: check_membership + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_REQUIRED_ROLES: admin,maintainer,write + GH_AW_ALLOWED_BOTS: ${{ inputs.allowed-bot-users }} + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + 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_membership.cjs'); + await main(); + + safe_outputs: + needs: + - activation + - agent + - detection + if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (needs.detection.outputs.success == 'true') + runs-on: ubuntu-slim + permissions: + contents: write + issues: write + pull-requests: write + timeout-minutes: 15 + env: + GH_AW_ENGINE_ID: "copilot" + GH_AW_ENGINE_MODEL: "${{ inputs.model }}" + GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\"}" + GH_AW_WORKFLOW_ID: "gh-aw-test-improver" + GH_AW_WORKFLOW_NAME: "Test Improver" + outputs: + create_discussion_error_count: ${{ steps.process_safe_outputs.outputs.create_discussion_error_count }} + create_discussion_errors: ${{ steps.process_safe_outputs.outputs.create_discussion_errors }} + process_safe_outputs_processed_count: ${{ steps.process_safe_outputs.outputs.processed_count }} + process_safe_outputs_temporary_id_map: ${{ steps.process_safe_outputs.outputs.temporary_id_map }} + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 + with: + destination: /opt/gh-aw/actions + - name: Download agent output artifact + continue-on-error: true + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 + with: + name: agent-output + path: /tmp/gh-aw/safeoutputs/ + - name: Setup agent output environment variable + run: | + mkdir -p /tmp/gh-aw/safeoutputs/ + find "/tmp/gh-aw/safeoutputs/" -type f -print + echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/safeoutputs/agent_output.json" >> "$GITHUB_ENV" + - name: Download patch artifact + continue-on-error: true + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 + with: + name: agent-artifacts + path: /tmp/gh-aw/ + - name: Checkout repository + if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + ref: ${{ github.base_ref || github.ref_name }} + token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + persist-credentials: false + fetch-depth: 1 + - name: Configure Git credentials + if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) + env: + REPO_NAME: ${{ github.repository }} + SERVER_URL: ${{ github.server_url }} + GIT_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + run: | + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git config --global user.name "github-actions[bot]" + # Re-authenticate git with GitHub token + SERVER_URL_STRIPPED="${SERVER_URL#https://}" + git remote set-url origin "https://x-access-token:${GIT_TOKEN}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" + echo "Git configured with standard GitHub Actions identity" + - name: Process Safe Outputs + id: process_safe_outputs + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_pull_request\":{\"base_branch\":\"${{ github.base_ref || github.ref_name }}\",\"max\":1,\"max_patch_size\":1024},\"missing_data\":{},\"missing_tool\":{}}" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/safe_output_handler_manager.cjs'); + await main(); + - name: Upload safe output items manifest + if: always() + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: safe-output-items + path: /tmp/safe-output-items.jsonl + if-no-files-found: warn + diff --git a/.github/workflows/gh-aw-test-improvement.md b/.github/workflows/gh-aw-test-improver.md similarity index 96% rename from .github/workflows/gh-aw-test-improvement.md rename to .github/workflows/gh-aw-test-improver.md index dab6da32..c79d26bf 100644 --- a/.github/workflows/gh-aw-test-improvement.md +++ b/.github/workflows/gh-aw-test-improver.md @@ -1,5 +1,6 @@ --- -name: "Test Improvement" +inlined-imports: true +name: "Test Improver" description: "Add focused tests for under-tested code and clean up redundant tests" imports: - gh-aw-fragments/elastic-tools.md @@ -12,10 +13,15 @@ imports: - gh-aw-fragments/safe-output-create-pr.md engine: id: copilot - model: gpt-5.3-codex + model: ${{ inputs.model }} on: workflow_call: inputs: + model: + description: "AI model to use" + type: string + required: false + default: "gpt-5.3-codex" additional-instructions: description: "Repo-specific instructions appended to the agent prompt" type: string @@ -43,7 +49,7 @@ on: bots: - "${{ inputs.allowed-bot-users }}" concurrency: - group: test-improvement + group: test-improver cancel-in-progress: true permissions: contents: read @@ -74,7 +80,7 @@ steps: run: eval "$SETUP_COMMANDS" --- -# Test Improvement Agent +# Test Improver Agent Identify under-tested code paths, add focused tests, and remove or consolidate duplicate or useless tests when safe. Open a single PR with the improvements. diff --git a/.github/workflows/gh-aw-text-auditor.lock.yml b/.github/workflows/gh-aw-text-auditor.lock.yml new file mode 100644 index 00000000..d93620c5 --- /dev/null +++ b/.github/workflows/gh-aw-text-auditor.lock.yml @@ -0,0 +1,1556 @@ +# +# ___ _ _ +# / _ \ | | (_) +# | |_| | __ _ ___ _ __ | |_ _ ___ +# | _ |/ _` |/ _ \ '_ \| __| |/ __| +# | | | | (_| | __/ | | | |_| | (__ +# \_| |_/\__, |\___|_| |_|\__|_|\___| +# __/ | +# _ _ |___/ +# | | | | / _| | +# | | | | ___ _ __ _ __| |_| | _____ ____ +# | |/\| |/ _ \ '__| |/ /| _| |/ _ \ \ /\ / / ___| +# \ /\ / (_) | | | | ( | | | | (_) \ V V /\__ \ +# \/ \/ \___/|_| |_|\_\|_| |_|\___/ \_/\_/ |___/ +# +# This file was automatically generated by gh-aw. DO NOT EDIT. +# +# To update this file, edit the corresponding .md file and run: +# gh aw compile +# Not all edits will cause changes to this file. +# +# For more information: https://github.github.com/gh-aw/introduction/overview/ +# +# Find typos, unclear error messages, and awkward user-facing text, then file an improvement issue +# +# Resolved workflow manifest: +# Imports: +# - gh-aw-fragments/elastic-tools.md +# - gh-aw-fragments/formatting.md +# - gh-aw-fragments/mcp-pagination.md +# - gh-aw-fragments/messages-footer.md +# - gh-aw-fragments/rigor.md +# - gh-aw-fragments/runtime-setup.md +# - gh-aw-fragments/safe-output-create-issue.md +# - gh-aw-fragments/scheduled-audit.md +# +# inlined-imports: true +# +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"6d6a022a2976cda11259a6b1e39386d5aa9c7fb5cf5a74b1189ffbd6925d297b"} + +name: "Text Auditor" +"on": + # bots: # Bots processed as bot check in pre-activation job + # - ${{ inputs.allowed-bot-users }} # Bots processed as bot check in pre-activation job + # roles: # Roles processed as role check in pre-activation job + # - admin # Roles processed as role check in pre-activation job + # - maintainer # Roles processed as role check in pre-activation job + # - write # Roles processed as role check in pre-activation job + workflow_call: + inputs: + additional-instructions: + default: "" + description: Repo-specific instructions appended to the agent prompt + required: false + type: string + allowed-bot-users: + default: github-actions[bot] + description: Allowlisted bot actor usernames (comma-separated) + required: false + type: string + edit-clarity: + default: low + description: How aggressively to flag unclear user-facing text, especially error/help messages. 'high' = proactively suggest clearer phrasing, 'low' = flag only clearly ambiguous text, 'none' = skip clarity checks + required: false + type: string + edit-grammar: + default: low + description: How aggressively to flag grammar and sentence construction problems. 'high' = improve awkward sentence structure, 'low' = flag only clear grammatical errors, 'none' = skip grammar checks + required: false + type: string + edit-misleading-text: + default: low + description: How aggressively to flag text that conflicts with current behavior. 'high' = proactively flag likely drift, 'low' = flag only direct contradictions, 'none' = skip behavior-alignment checks + required: false + type: string + edit-terminology: + default: low + description: How aggressively to flag inconsistent terminology for the same concept. 'high' = proactively normalize wording, 'low' = flag only unambiguous inconsistencies, 'none' = skip terminology checks + required: false + type: string + edit-typos: + default: low + description: How aggressively to flag typos and misspellings. 'high' = suggest broad consistency fixes, 'low' = flag only clear spelling errors, 'none' = skip typo checks + required: false + type: string + messages-footer: + default: "" + description: Footer appended to all agent comments and reviews + required: false + type: string + model: + default: gpt-5.3-codex + description: AI model to use + required: false + type: string + setup-commands: + default: "" + description: Shell commands to run before the agent starts (dependency install, build, etc.) + required: false + type: string + secrets: + COPILOT_GITHUB_TOKEN: + required: true + +permissions: {} + +concurrency: + cancel-in-progress: true + group: text-auditor + +run-name: "Text Auditor" + +jobs: + activation: + needs: pre_activation + if: needs.pre_activation.outputs.activated == 'true' + runs-on: ubuntu-slim + permissions: + contents: read + outputs: + comment_id: "" + comment_repo: "" + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 + with: + destination: /opt/gh-aw/actions + - name: Validate context variables + 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/validate_context_variables.cjs'); + await main(); + - name: Checkout .github and .agents folders + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + sparse-checkout: | + .github + .agents + fetch-depth: 1 + persist-credentials: false + - name: Check workflow file timestamps + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_WORKFLOW_FILE: "gh-aw-text-auditor.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: Create prompt with built-in context + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} + GH_AW_EXPR_118A0B98: ${{ inputs.edit-terminology }} + GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} + GH_AW_EXPR_7193CB58: ${{ inputs.edit-typos }} + GH_AW_EXPR_A0224D4D: ${{ inputs.edit-misleading-text }} + GH_AW_EXPR_CFC1B138: ${{ inputs.edit-grammar }} + GH_AW_EXPR_FEB6148B: ${{ inputs.edit-clarity }} + GH_AW_GITHUB_ACTOR: ${{ github.actor }} + GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} + GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} + GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} + GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} + GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} + GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} + run: | + bash /opt/gh-aw/actions/create_prompt_first.sh + cat << 'GH_AW_PROMPT_EOF' > "$GH_AW_PROMPT" + + GH_AW_PROMPT_EOF + cat "/opt/gh-aw/prompts/xpia.md" >> "$GH_AW_PROMPT" + cat "/opt/gh-aw/prompts/temp_folder_prompt.md" >> "$GH_AW_PROMPT" + cat "/opt/gh-aw/prompts/markdown.md" >> "$GH_AW_PROMPT" + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + + GitHub API Access Instructions + + The gh CLI is NOT authenticated. Do NOT use gh commands for GitHub operations. + + + To create or modify GitHub resources (issues, discussions, pull requests, etc.), you MUST call the appropriate safe output tool. Simply writing content will NOT work - the workflow requires actual tool calls. + + Temporary IDs: Some safe output tools support a temporary ID field (usually named temporary_id) so you can reference newly-created items elsewhere in the SAME agent output (for example, using #aw_abc1 in a later body). + + **IMPORTANT - temporary_id format rules:** + - If you DON'T need to reference the item later, OMIT the temporary_id field entirely (it will be auto-generated if needed) + - If you DO need cross-references/chaining, you MUST match this EXACT validation regex: /^aw_[A-Za-z0-9]{3,8}$/i + - Format: aw_ prefix followed by 3 to 8 alphanumeric characters (A-Z, a-z, 0-9, case-insensitive) + - Valid alphanumeric characters: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 + - INVALID examples: aw_ab (too short), aw_123456789 (too long), aw_test-id (contains hyphen), aw_id_123 (contains underscore) + - VALID examples: aw_abc, aw_abc1, aw_Test123, aw_A1B2C3D4, aw_12345678 + - To generate valid IDs: use 3-8 random alphanumeric characters or omit the field to let the system auto-generate + + Do NOT invent other aw_* formats — downstream steps will reject them with validation errors matching against /^aw_[A-Za-z0-9]{3,8}$/i. + + Discover available tools from the safeoutputs MCP server. + + **Critical**: Tool calls write structured data that downstream jobs process. Without tool calls, follow-up actions will be skipped. + + **Note**: If you made no other safe output tool calls during this workflow execution, call the "noop" tool to provide a status message indicating completion or that no actions were needed. + + --- + + ## Creating an Issue, Reporting Missing Tools or Functionality, Reporting Missing Data + + **IMPORTANT**: To perform the actions listed above, use the **safeoutputs** tools. Do NOT use `gh`, do NOT call the GitHub API directly. You do not have write access to the GitHub repository. + + **Creating an Issue** + + To create an issue, use the create_issue tool from safeoutputs. + + **Reporting Missing Tools or Functionality** + + To report a missing tool or capability, use the missing_tool tool from safeoutputs. + + **Reporting Missing Data** + + To report missing data required to achieve a goal, use the missing_data tool from safeoutputs. + + + + + The following GitHub context information is available for this workflow: + {{#if __GH_AW_GITHUB_ACTOR__ }} + - **actor**: __GH_AW_GITHUB_ACTOR__ + {{/if}} + {{#if __GH_AW_GITHUB_REPOSITORY__ }} + - **repository**: __GH_AW_GITHUB_REPOSITORY__ + {{/if}} + {{#if __GH_AW_GITHUB_WORKSPACE__ }} + - **workspace**: __GH_AW_GITHUB_WORKSPACE__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_ISSUE_NUMBER__ }} + - **issue-number**: #__GH_AW_GITHUB_EVENT_ISSUE_NUMBER__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__ }} + - **discussion-number**: #__GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__ }} + - **pull-request-number**: #__GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_COMMENT_ID__ }} + - **comment-id**: __GH_AW_GITHUB_EVENT_COMMENT_ID__ + {{/if}} + {{#if __GH_AW_GITHUB_RUN_ID__ }} + - **workflow-run-id**: __GH_AW_GITHUB_RUN_ID__ + {{/if}} + + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + ## MCP Servers + + - **`generate_agents_md`** — generates a summary of the repository's structure, conventions, and coding guidelines from AGENTS.md and related files. Call at the start of every workflow to get repo context. + - **`search_code`** — grep-style search across public GitHub repositories. Use for finding usage patterns in upstream libraries, reference implementations, or examples in open-source projects. This searches *public GitHub repos*, not the local codebase — if available you can use `grep` and file reading for local code. + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + ## Formatting Guidelines + + - Lead with the most important information — your first sentence should be the key takeaway + - Be concise and actionable — no filler or praise + - Use `
` and `` tags for long sections to keep responses scannable + - Wrap branch names and @-references in backticks to avoid pinging users + - Include code snippets with file paths and line numbers when referencing the codebase + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + ## Rigor + + **Silence is better than noise. A false positive wastes a human's time and erodes trust in every future report.** + + - If you claim something is missing or broken, show the exact evidence in the code — file path, line number, and what you observed. + - If a conclusion depends on assumptions you haven't confirmed, do not assert it. Verify first; if you cannot verify, do not report. + - "I don't know" is better than a wrong answer. `noop` is better than a speculative finding. + - It's worth the time to verify now versus guessing and forcing someone else to verify later. + - Before filing any issue or opening any PR, re-read your own output as a skeptical reviewer. Ask: "Would a senior engineer on this team find this useful, or would they close it immediately?" If the answer is "close," call `noop` instead. + - Only report findings you would confidently defend in a code review. If you feel the need to hedge with "might," "could," or "possibly," the finding is not ready to file. + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + ## MCP Pagination + + MCP tool responses have a **25,000 token limit**. When responses exceed this limit, the call fails and you must retry with pagination — wasting turns and tokens. Use proactive pagination to stay under the limit. + + ### Recommended `perPage` Values + + - **5-10**: For detailed items (PR diffs, files with patches, issues with comments) + - **20-30**: For medium-detail lists (commits, review comments, issue lists) + - **50-100**: For simple list operations (branches, labels, tags) + + ### Pagination Pattern + + When you need all results from a paginated API: + + 1. Fetch the first page with a conservative `perPage` value + 2. Process the results before fetching the next page + 3. Continue fetching pages until you receive fewer results than `perPage` (indicating the last page) + + ### Error Recovery + + If you see an error like: + - `MCP tool response exceeds maximum allowed tokens (25000)` + - `Response too large for tool [tool_name]` + + Retry the same call with a smaller `perPage` value (halve it). + + ### Tips + + - **Start small**: It's better to make multiple small requests than one that fails + - **Fetch incrementally**: Get an overview first, then details for specific items + - **Use filters**: Combine `perPage` with state, label, or date filters to reduce result size + - **Process as you go**: Don't accumulate all pages before acting — process each batch immediately + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + ## Message Footer + + A footer is automatically appended to all comments and reviews. Do not add your own footer or sign-off — the runtime handles this. + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + ## create-issue Limitations + + - **Title**: Max 128 characters. Sanitized (special characters escaped). + - **Labels**: Max 10 labels per issue. Each label max 64 characters. Labels containing only `-` are rejected. + - **Assignees**: Max 5 assignees per issue. + - **Body**: No strict character limit beyond GitHub's API limit (~65,536 characters), but fields over 16,000 tokens are written to a file reference instead of inlined. + - **Bot triggers**: References like `fixes #123` or `closes #456` in the body are neutralized to prevent unintended issue closures. + - **Mentions**: `@mentions` in the body are neutralized (backticked) by default. + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + You are an agent for __GH_AW_GITHUB_REPOSITORY__. You run on a schedule to investigate the repository and file an issue when something needs attention. Your specific assignment is described in the **Report Assignment** section below. + + ## Context + + - **Repository**: __GH_AW_GITHUB_REPOSITORY__ + + ## Constraints + + This workflow is for detection and reporting only. You can read files, search code, run commands, and read PR/issue details — but your only output is either a single issue or a noop. + + ## Process + + Follow these steps in order. + + ### Step 1: Gather Context + + 1. Call `generate_agents_md` to get the repository's coding guidelines and conventions. If this fails, continue without it. + 2. Follow the data gathering instructions in the **Report Assignment** section. + + ### Step 2: Analyze + + Follow the analysis instructions in the **Report Assignment** section to determine whether an issue should be filed. The Report Assignment defines: + - What data to gather and how + - What to look for + - What constitutes a finding worth reporting + - What to skip or ignore + + ### Step 3: Self-Review (Quality Gate) + + Before filing anything, critically evaluate every finding against these criteria: + + 1. **Evidence is concrete** — you can point to exact file paths, line numbers, commit SHAs, or command outputs. No "I believe" or "it seems." + 2. **Finding is actionable** — a maintainer reading the issue can act on it without re-investigating from scratch. + 3. **Finding is not already tracked** — you checked open issues and recent PRs for duplicates. + 4. **Finding is worth a human's time** — the issue is material enough that a maintainer would thank you for filing it, not close it as noise. + + If zero findings pass all four criteria, call `noop` with a brief reason and stop. **Noop is the expected outcome most days.** Filing nothing is a success when there is nothing worth filing. + + ### Step 4: Report + + If there are findings that pass the quality gate, call `create_issue` with a structured report. Use the issue format specified in the Report Assignment if one is provided, otherwise use this default format: + + **Issue title:** Brief summary of findings + + **Issue body:** + + > ## Findings + > + > ### 1. [Brief description] + > + > **Evidence:** [Links, references, or data supporting the finding] + > **Action needed:** [What should be done] + > + > ## Suggested Actions + > + > - [ ] [Actionable checkbox for each finding] + + **Guidelines:** + - Group related findings together + - Be specific about what needs to happen + - Include links and references where possible + - Make suggested actions concrete enough to act on without re-investigating + - If a finding is ambiguous, it does not pass the quality gate — drop it + + **Report Assignment:** + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + Find typos, unclear error messages, and awkward user-facing text that are low-effort to fix, and file a single improvement issue. + + **The bar is high: only report concrete, unambiguous text problems.** Most runs should end with `noop` — that means user-facing text is clean. + + ## Edit Level Configuration + + The following edit levels are configured for this run. Each dimension is independent. + + | Dimension | Level | Meaning | + | --- | --- | --- | + | **typos** | `__GH_AW_EXPR_7193CB58__` | How aggressively to flag typos and misspellings | + | **grammar** | `__GH_AW_EXPR_CFC1B138__` | How aggressively to flag grammar and sentence construction issues | + | **clarity** | `__GH_AW_EXPR_FEB6148B__` | How aggressively to flag unclear user-facing text | + | **terminology** | `__GH_AW_EXPR_118A0B98__` | How aggressively to flag inconsistent naming for the same concept | + | **misleading-text** | `__GH_AW_EXPR_A0224D4D__` | How aggressively to flag text that no longer matches behavior | + + Level semantics: + - **`high`** — apply best judgment proactively within this dimension + - **`low`** — report only concrete, unambiguous issues + - **`none`** — skip this dimension entirely + + ### Data Gathering + + 1. Identify user-facing text sources — scan the repository for: + - CLI output strings, error messages, and help text + - Log messages shown to users (not debug-level internal logs) + - README, CONTRIBUTING, DEVELOPING, and other markdown documentation + - UI strings, notification templates, and user-visible configuration descriptions + - Code comments in public APIs that appear in generated documentation + 2. Read the identified files and search for text issues. + + ### What to Look For by Dimension + + Use each dimension's configured level to determine whether to report findings. + + #### Typos (`__GH_AW_EXPR_7193CB58__`) + + - **`high`**: Flag typos/misspellings proactively and include nearby consistency fixes when they are obviously beneficial. + - **`low`**: Flag only clear spelling errors (for example, `recieve` → `receive`), not style variants. + - **`none`**: Skip typo checks. + + #### Grammar (`__GH_AW_EXPR_CFC1B138__`) + + - **`high`**: Flag grammar and sentence construction issues that reduce readability, including awkward or fragmented sentences. + - **`low`**: Flag only clear grammatical errors (subject-verb disagreement, missing articles, broken sentence structure). + - **`none`**: Skip grammar checks. + + #### Clarity (`__GH_AW_EXPR_FEB6148B__`) + + - **`high`**: Proactively flag unclear user-facing text and suggest concrete rewrites, especially for errors/help text. + - **`low`**: Flag only clearly ambiguous or incomplete user-facing text (for example, `"Error: failed"` with no actionable context). + - **`none`**: Skip clarity checks. + + #### Terminology (`__GH_AW_EXPR_118A0B98__`) + + - **`high`**: Proactively flag inconsistent naming for the same concept across user-facing surfaces. + - **`low`**: Flag only unambiguous inconsistencies where the same concept is clearly referred to by different terms. + - **`none`**: Skip terminology checks. + + #### Misleading Text (`__GH_AW_EXPR_A0224D4D__`) + + - **`high`**: Proactively flag text likely to have drifted from behavior. + - **`low`**: Flag only direct, verifiable contradictions between text and current code behavior. + - **`none`**: Skip behavior-alignment checks. + + ### What to Skip + + - **Style preferences** — do not flag Oxford comma usage, line length, or prose style unless it causes ambiguity + - **Internal-only text** — debug logs, developer-only comments, test fixtures + - **Intentional abbreviations** — short forms that are standard in the project + - **Generated or vendored files** — do not scan auto-generated code, lock files, or third-party content + - **Issues already tracked** — check open issues before filing + - **Findings that require design decisions** — if fixing the text requires deciding on new terminology or restructuring content, skip it + + ### Quality Gate — When to Noop + + Call `noop` if any of these are true: + - All edit dimensions are set to `none` + - No concrete text problems were found + - All findings are style preferences rather than clear errors + - The problems found are in generated or vendored files + - A similar issue is already open + - The fixes would require design decisions or significant rewording beyond simple corrections + + ### Issue Format + + **Issue title:** Brief summary of text improvements found + + **Issue body:** + + > ## Text Improvements + > + > The following user-facing text issues were found in the repository. Each is a low-effort fix. + > + > ### 1. [Brief description] + > + > **File:** `path/to/file` (line N) + > **Current text:** `the existing text with the problem` + > **Suggested fix:** `the corrected text` + > **Why:** [Brief explanation — typo, grammar, unclear error, etc.] + > + > ### 2. [Next finding...] + > + > ## Suggested Actions + > + > - [ ] [Specific, actionable checkbox for each fix] + + ### Labeling + + - If the `text-auditor` label exists (check with `github-get_label`), include it in the `create_issue` call; otherwise, rely on the `[text-auditor]` title prefix only. + + __GH_AW_EXPR_49B959F1__ + + GH_AW_PROMPT_EOF + - name: Interpolate variables and render templates + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} + GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} + GH_AW_EXPR_FEB6148B: ${{ inputs.edit-clarity }} + GH_AW_EXPR_CFC1B138: ${{ inputs.edit-grammar }} + GH_AW_EXPR_A0224D4D: ${{ inputs.edit-misleading-text }} + GH_AW_EXPR_118A0B98: ${{ inputs.edit-terminology }} + GH_AW_EXPR_7193CB58: ${{ inputs.edit-typos }} + 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/interpolate_prompt.cjs'); + await main(); + - name: Substitute placeholders + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_EXPR_118A0B98: ${{ inputs.edit-terminology }} + GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} + GH_AW_EXPR_7193CB58: ${{ inputs.edit-typos }} + GH_AW_EXPR_A0224D4D: ${{ inputs.edit-misleading-text }} + GH_AW_EXPR_CFC1B138: ${{ inputs.edit-grammar }} + GH_AW_EXPR_FEB6148B: ${{ inputs.edit-clarity }} + GH_AW_GITHUB_ACTOR: ${{ github.actor }} + GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} + GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} + GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} + 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'); + setupGlobals(core, github, context, exec, io); + + const substitutePlaceholders = require('/opt/gh-aw/actions/substitute_placeholders.cjs'); + + // Call the substitution function + return await substitutePlaceholders({ + file: process.env.GH_AW_PROMPT, + substitutions: { + GH_AW_EXPR_118A0B98: process.env.GH_AW_EXPR_118A0B98, + GH_AW_EXPR_49B959F1: process.env.GH_AW_EXPR_49B959F1, + GH_AW_EXPR_7193CB58: process.env.GH_AW_EXPR_7193CB58, + GH_AW_EXPR_A0224D4D: process.env.GH_AW_EXPR_A0224D4D, + GH_AW_EXPR_CFC1B138: process.env.GH_AW_EXPR_CFC1B138, + GH_AW_EXPR_FEB6148B: process.env.GH_AW_EXPR_FEB6148B, + GH_AW_GITHUB_ACTOR: process.env.GH_AW_GITHUB_ACTOR, + GH_AW_GITHUB_EVENT_COMMENT_ID: process.env.GH_AW_GITHUB_EVENT_COMMENT_ID, + GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: process.env.GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER, + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: process.env.GH_AW_GITHUB_EVENT_ISSUE_NUMBER, + 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_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 + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + run: bash /opt/gh-aw/actions/validate_prompt_placeholders.sh + - name: Print prompt + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + run: bash /opt/gh-aw/actions/print_prompt_summary.sh + - name: Upload prompt artifact + if: success() + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: prompt + path: /tmp/gh-aw/aw-prompts/prompt.txt + retention-days: 1 + + agent: + needs: activation + runs-on: ubuntu-latest + permissions: + contents: read + issues: read + pull-requests: read + concurrency: + group: "gh-aw-copilot-${{ github.workflow }}" + env: + DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} + GH_AW_ASSETS_ALLOWED_EXTS: "" + GH_AW_ASSETS_BRANCH: "" + GH_AW_ASSETS_MAX_SIZE_KB: 0 + GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs + 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: ghawtextauditor + outputs: + checkout_pr_success: ${{ steps.checkout-pr.outputs.checkout_pr_success || 'true' }} + has_patch: ${{ steps.collect_output.outputs.has_patch }} + model: ${{ steps.generate_aw_info.outputs.model }} + output: ${{ steps.collect_output.outputs.output }} + output_types: ${{ steps.collect_output.outputs.output_types }} + secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 + with: + destination: /opt/gh-aw/actions + - name: Checkout repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + - name: Create gh-aw temp directory + run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh + - if: hashFiles('go.mod') != '' + name: Setup Go + uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5 + with: + cache: true + go-version-file: go.mod + - if: hashFiles('.python-version') != '' + name: Setup Python + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 + with: + python-version-file: .python-version + - if: hashFiles('.node-version') != '' + name: Setup Node.js (.node-version) + uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6 + with: + node-version-file: .node-version + - if: hashFiles('.node-version') == '' && hashFiles('.nvmrc') != '' + name: Setup Node.js (.nvmrc) + uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6 + with: + node-version-file: .nvmrc + - if: hashFiles('.ruby-version') != '' + name: Setup Ruby + uses: ruby/setup-ruby@09a7688d3b55cf0e976497ff046b70949eeaccfd # v1 + with: + bundler-cache: true + ruby-version: .ruby-version + - id: setup-uv + if: hashFiles('pyproject.toml', 'uv.lock') != '' + name: Setup uv + uses: astral-sh/setup-uv@e58605a9b6da7c637471fab8847a5e5a6b8df081 # v5 + - env: + UV_PATH: ${{ steps.setup-uv.outputs.uv-path }} + WORKSPACE: ${{ github.workspace }} + if: hashFiles('pyproject.toml', 'uv.lock') != '' + name: Expose uv in workspace + run: |- + set -euo pipefail + install_dir="$WORKSPACE/.gh-aw-tools/bin" + mkdir -p "$install_dir" + cp "$UV_PATH" "$install_dir/uv" + chmod +x "$install_dir/uv" + echo "$install_dir" >> "$GITHUB_PATH" + shell: bash + - env: + SETUP_COMMANDS: ${{ inputs.setup-commands }} + if: ${{ inputs.setup-commands != '' }} + name: Repo-specific setup + run: eval "$SETUP_COMMANDS" + + - name: Configure Git credentials + env: + REPO_NAME: ${{ github.repository }} + SERVER_URL: ${{ github.server_url }} + run: | + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git config --global user.name "github-actions[bot]" + # Re-authenticate git with GitHub token + SERVER_URL_STRIPPED="${SERVER_URL#https://}" + git remote set-url origin "https://x-access-token:${{ github.token }}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" + echo "Git configured with standard GitHub Actions identity" + - name: Checkout PR branch + id: checkout-pr + if: | + github.event.pull_request + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + with: + github-token: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/checkout_pr_branch.cjs'); + await main(); + - name: Generate agentic run info + id: generate_aw_info + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + with: + script: | + const fs = require('fs'); + + const awInfo = { + engine_id: "copilot", + engine_name: "GitHub Copilot CLI", + model: "${{ inputs.model }}", + version: "", + agent_version: "0.0.412", + workflow_name: "Text Auditor", + experimental: false, + supports_tools_allowlist: true, + run_id: context.runId, + run_number: context.runNumber, + run_attempt: process.env.GITHUB_RUN_ATTEMPT, + repository: context.repo.owner + '/' + context.repo.repo, + ref: context.ref, + sha: context.sha, + actor: context.actor, + event_name: context.eventName, + staged: false, + allowed_domains: ["agents-md-generator.fastmcp.app","artifacts.elastic.co","cloud.elastic.co","defaults","ela.st","elastic.co","github","go","node","public-code-search.fastmcp.app","python","ruby","www.elastic.co"], + firewall_enabled: true, + awf_version: "v0.20.2", + awmg_version: "v0.1.4", + steps: { + firewall: "squid" + }, + created_at: new Date().toISOString() + }; + + // Write to /tmp/gh-aw directory to avoid inclusion in PR + const tmpPath = '/tmp/gh-aw/aw_info.json'; + fs.writeFileSync(tmpPath, JSON.stringify(awInfo, null, 2)); + console.log('Generated aw_info.json at:', tmpPath); + console.log(JSON.stringify(awInfo, null, 2)); + + // Set model as output for reuse in other steps/jobs + core.setOutput('model', awInfo.model); + - name: Validate COPILOT_GITHUB_TOKEN secret + id: validate-secret + run: /opt/gh-aw/actions/validate_multi_secret.sh COPILOT_GITHUB_TOKEN 'GitHub Copilot CLI' https://github.github.com/gh-aw/reference/engines/#github-copilot-default + env: + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + - name: Install GitHub Copilot CLI + run: /opt/gh-aw/actions/install_copilot_cli.sh 0.0.412 + - name: Install awf binary + run: bash /opt/gh-aw/actions/install_awf_binary.sh v0.20.2 + - name: Determine automatic lockdown mode for GitHub MCP Server + id: determine-automatic-lockdown + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} + GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} + with: + script: | + 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.20.2 ghcr.io/github/gh-aw-firewall/api-proxy:0.20.2 ghcr.io/github/gh-aw-firewall/squid:0.20.2 ghcr.io/github/gh-aw-mcpg:v0.1.4 ghcr.io/github/github-mcp-server:v0.31.0 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' + {"create_issue":{"expires":168,"max":1},"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 \"[text-auditor] \".", + "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": "Report that a tool or capability needed to complete the task is not available, or share any information you deem important about missing functionality or limitations. Use this when you cannot accomplish what was requested because the required functionality is missing or access is restricted.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "alternatives": { + "description": "Any workarounds, manual steps, or alternative approaches the user could take (max 256 characters).", + "type": "string" + }, + "reason": { + "description": "Explanation of why this tool is needed or what information you want to share about the limitation (max 256 characters).", + "type": "string" + }, + "tool": { + "description": "Optional: Name or description of the missing tool or capability (max 128 characters). Be specific about what functionality is needed.", + "type": "string" + } + }, + "required": [ + "reason" + ], + "type": "object" + }, + "name": "missing_tool" + }, + { + "description": "Log a transparency message when no significant actions are needed. Use this to confirm workflow completion and provide visibility when analysis is complete but no changes or outputs are required (e.g., 'No issues found', 'All checks passed'). This ensures the workflow produces human-visible output even when no other actions are taken.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "message": { + "description": "Status or completion message to log. Should explain what was analyzed and the outcome (e.g., 'Code review complete - no issues found', 'Analysis complete - all tests passing').", + "type": "string" + } + }, + "required": [ + "message" + ], + "type": "object" + }, + "name": "noop" + }, + { + "description": "Report that data or information needed to complete the task is not available. Use this when you cannot accomplish what was requested because required data, context, or information is missing.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "alternatives": { + "description": "Any workarounds, manual steps, or alternative approaches the user could take (max 256 characters).", + "type": "string" + }, + "context": { + "description": "Additional context about the missing data or where it should come from (max 256 characters).", + "type": "string" + }, + "data_type": { + "description": "Type or description of the missing data or information (max 128 characters). Be specific about what data is needed.", + "type": "string" + }, + "reason": { + "description": "Explanation of why this data is needed to complete the task (max 256 characters).", + "type": "string" + } + }, + "required": [], + "type": "object" + }, + "name": "missing_data" + } + ] + GH_AW_SAFE_OUTPUTS_TOOLS_EOF + cat > /opt/gh-aw/safeoutputs/validation.json << 'GH_AW_SAFE_OUTPUTS_VALIDATION_EOF' + { + "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_data": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "context": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "data_type": { + "type": "string", + "sanitize": true, + "maxLength": 128 + }, + "reason": { + "type": "string", + "sanitize": true, + "maxLength": 256 + } + } + }, + "missing_tool": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 512 + }, + "reason": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "tool": { + "type": "string", + "sanitize": true, + "maxLength": 128 + } + } + }, + "noop": { + "defaultMax": 1, + "fields": { + "message": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + } + } + } + } + GH_AW_SAFE_OUTPUTS_VALIDATION_EOF + - name: Generate Safe Outputs MCP Server Config + id: safe-outputs-config + run: | + # Generate a secure random API key (360 bits of entropy, 40+ chars) + # Mask immediately to prevent timing vulnerabilities + API_KEY=$(openssl rand -base64 45 | tr -d '/+=') + echo "::add-mask::${API_KEY}" + + PORT=3001 + + # Set outputs for next steps + { + echo "safe_outputs_api_key=${API_KEY}" + echo "safe_outputs_port=${PORT}" + } >> "$GITHUB_OUTPUT" + + echo "Safe Outputs MCP server will run on port ${PORT}" + + - name: Start Safe Outputs MCP HTTP Server + id: safe-outputs-start + env: + DEBUG: '*' + GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-config.outputs.safe_outputs_port }} + GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-config.outputs.safe_outputs_api_key }} + GH_AW_SAFE_OUTPUTS_TOOLS_PATH: /opt/gh-aw/safeoutputs/tools.json + GH_AW_SAFE_OUTPUTS_CONFIG_PATH: /opt/gh-aw/safeoutputs/config.json + GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs + run: | + # Environment variables are set above to prevent template injection + export DEBUG + export GH_AW_SAFE_OUTPUTS_PORT + export GH_AW_SAFE_OUTPUTS_API_KEY + export GH_AW_SAFE_OUTPUTS_TOOLS_PATH + export GH_AW_SAFE_OUTPUTS_CONFIG_PATH + export GH_AW_MCP_LOG_DIR + + bash /opt/gh-aw/actions/start_safe_outputs_server.sh + + - name: Start MCP Gateway + id: start-mcp-gateway + env: + GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} + GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-start.outputs.api_key }} + GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-start.outputs.port }} + GITHUB_MCP_LOCKDOWN: ${{ steps.determine-automatic-lockdown.outputs.lockdown == 'true' && '1' || '0' }} + GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + run: | + set -eo pipefail + mkdir -p /tmp/gh-aw/mcp-config + + # Export gateway environment variables for MCP config and gateway script + export MCP_GATEWAY_PORT="80" + export MCP_GATEWAY_DOMAIN="host.docker.internal" + MCP_GATEWAY_API_KEY=$(openssl rand -base64 45 | tr -d '/+=') + echo "::add-mask::${MCP_GATEWAY_API_KEY}" + export MCP_GATEWAY_API_KEY + export MCP_GATEWAY_PAYLOAD_DIR="/tmp/gh-aw/mcp-payloads" + mkdir -p "${MCP_GATEWAY_PAYLOAD_DIR}" + export DEBUG="*" + + export GH_AW_ENGINE="copilot" + 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 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_LOCKDOWN -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.1.4' + + mkdir -p /home/runner/.copilot + cat << GH_AW_MCP_CONFIG_EOF | bash /opt/gh-aw/actions/start_mcp_gateway.sh + { + "mcpServers": { + "agents-md-generator": { + "type": "http", + "url": "https://agents-md-generator.fastmcp.app/mcp", + "tools": [ + "generate_agents_md" + ] + }, + "github": { + "type": "stdio", + "container": "ghcr.io/github/github-mcp-server:v0.31.0", + "env": { + "GITHUB_LOCKDOWN_MODE": "$GITHUB_MCP_LOCKDOWN", + "GITHUB_PERSONAL_ACCESS_TOKEN": "\${GITHUB_MCP_SERVER_TOKEN}", + "GITHUB_READ_ONLY": "1", + "GITHUB_TOOLSETS": "repos,issues,pull_requests,search,labels" + } + }, + "public-code-search": { + "type": "http", + "url": "https://public-code-search.fastmcp.app/mcp", + "tools": [ + "search_code" + ] + }, + "safeoutputs": { + "type": "http", + "url": "http://host.docker.internal:$GH_AW_SAFE_OUTPUTS_PORT", + "headers": { + "Authorization": "\${GH_AW_SAFE_OUTPUTS_API_KEY}" + } + } + }, + "gateway": { + "port": $MCP_GATEWAY_PORT, + "domain": "${MCP_GATEWAY_DOMAIN}", + "apiKey": "${MCP_GATEWAY_API_KEY}", + "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" + } + } + GH_AW_MCP_CONFIG_EOF + - name: Generate workflow overview + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + with: + script: | + const { generateWorkflowOverview } = require('/opt/gh-aw/actions/generate_workflow_overview.cjs'); + await generateWorkflowOverview(core); + - name: Download prompt artifact + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 + with: + name: prompt + path: /tmp/gh-aw/aw-prompts + - name: Clean git credentials + run: bash /opt/gh-aw/actions/clean_git_credentials.sh + - name: Execute GitHub Copilot CLI + id: agentic_execution + # Copilot CLI tool arguments (sorted): + timeout-minutes: 90 + run: | + set -o pipefail + sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --allow-domains '*.githubusercontent.com,*.jsr.io,*.pythonhosted.org,*.rvm.io,agents-md-generator.fastmcp.app,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.rubygems.org,api.snapcraft.io,archive.ubuntu.com,artifacts.elastic.co,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,bun.sh,bundler.rubygems.org,cache.ruby-lang.org,cdn.jsdelivr.net,cloud.elastic.co,codeload.github.com,conda.anaconda.org,conda.binstar.org,crates.io,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,deb.nodesource.com,deno.land,ela.st,elastic.co,esm.sh,files.pythonhosted.org,gems.rubyforge.org,gems.rubyonrails.org,get.pnpm.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,host.docker.internal,index.crates.io,index.rubygems.org,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,lfs.github.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,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,pip.pypa.io,pkg.go.dev,ppa.launchpad.net,proxy.golang.org,public-code-search.fastmcp.app,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.bower.io,registry.npmjs.com,registry.npmjs.org,registry.yarnpkg.com,repo.anaconda.com,repo.continuum.io,repo.yarnpkg.com,rubygems.org,rubygems.pkg.github.com,s.symcb.com,s.symcd.com,security.ubuntu.com,skimdb.npmjs.com,static.crates.io,storage.googleapis.com,sum.golang.org,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.elastic.co,www.npmjs.com,www.npmjs.org,yarnpkg.com' --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.20.2 --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 --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log + env: + COPILOT_AGENT_RUNNER_TYPE: STANDALONE + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} + GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} + GITHUB_HEAD_REF: ${{ github.head_ref }} + GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + GITHUB_REF_NAME: ${{ github.ref_name }} + GITHUB_STEP_SUMMARY: ${{ env.GITHUB_STEP_SUMMARY }} + GITHUB_WORKSPACE: ${{ github.workspace }} + XDG_CONFIG_HOME: /home/runner + - name: Configure Git credentials + env: + REPO_NAME: ${{ github.repository }} + SERVER_URL: ${{ github.server_url }} + run: | + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git config --global user.name "github-actions[bot]" + # Re-authenticate git with GitHub token + SERVER_URL_STRIPPED="${SERVER_URL#https://}" + git remote set-url origin "https://x-access-token:${{ github.token }}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" + echo "Git configured with standard GitHub Actions identity" + - name: Copy Copilot session state files to logs + if: always() + continue-on-error: true + run: | + # Copy Copilot session state files to logs folder for artifact collection + # This ensures they are in /tmp/gh-aw/ where secret redaction can scan them + SESSION_STATE_DIR="$HOME/.copilot/session-state" + LOGS_DIR="/tmp/gh-aw/sandbox/agent/logs" + + if [ -d "$SESSION_STATE_DIR" ]; then + echo "Copying Copilot session state files from $SESSION_STATE_DIR to $LOGS_DIR" + mkdir -p "$LOGS_DIR" + cp -v "$SESSION_STATE_DIR"/*.jsonl "$LOGS_DIR/" 2>/dev/null || true + echo "Session state files copied successfully" + else + echo "No session-state directory found at $SESSION_STATE_DIR" + fi + - name: Stop MCP Gateway + if: always() + continue-on-error: true + env: + MCP_GATEWAY_PORT: ${{ steps.start-mcp-gateway.outputs.gateway-port }} + MCP_GATEWAY_API_KEY: ${{ steps.start-mcp-gateway.outputs.gateway-api-key }} + GATEWAY_PID: ${{ steps.start-mcp-gateway.outputs.gateway-pid }} + run: | + bash /opt/gh-aw/actions/stop_mcp_gateway.sh "$GATEWAY_PID" + - name: Redact secrets in logs + if: always() + 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/redact_secrets.cjs'); + await main(); + env: + GH_AW_SECRET_NAMES: 'COPILOT_GITHUB_TOKEN,GH_AW_GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,GITHUB_TOKEN' + SECRET_COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + SECRET_GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} + SECRET_GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} + SECRET_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Upload Safe Outputs + if: always() + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: safe-output + path: ${{ env.GH_AW_SAFE_OUTPUTS }} + if-no-files-found: warn + - name: Ingest agent output + id: collect_output + if: always() + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} + GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,*.jsr.io,*.pythonhosted.org,*.rvm.io,agents-md-generator.fastmcp.app,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.rubygems.org,api.snapcraft.io,archive.ubuntu.com,artifacts.elastic.co,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,bun.sh,bundler.rubygems.org,cache.ruby-lang.org,cdn.jsdelivr.net,cloud.elastic.co,codeload.github.com,conda.anaconda.org,conda.binstar.org,crates.io,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,deb.nodesource.com,deno.land,ela.st,elastic.co,esm.sh,files.pythonhosted.org,gems.rubyforge.org,gems.rubyonrails.org,get.pnpm.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,host.docker.internal,index.crates.io,index.rubygems.org,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,lfs.github.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,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,pip.pypa.io,pkg.go.dev,ppa.launchpad.net,proxy.golang.org,public-code-search.fastmcp.app,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.bower.io,registry.npmjs.com,registry.npmjs.org,registry.yarnpkg.com,repo.anaconda.com,repo.continuum.io,repo.yarnpkg.com,rubygems.org,rubygems.pkg.github.com,s.symcb.com,s.symcd.com,security.ubuntu.com,skimdb.npmjs.com,static.crates.io,storage.googleapis.com,sum.golang.org,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.elastic.co,www.npmjs.com,www.npmjs.org,yarnpkg.com" + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_API_URL: ${{ github.api_url }} + 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/collect_ndjson_output.cjs'); + await main(); + - name: Upload sanitized agent output + if: always() && env.GH_AW_AGENT_OUTPUT + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: agent-output + path: ${{ env.GH_AW_AGENT_OUTPUT }} + if-no-files-found: warn + - name: Upload engine output files + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: agent_outputs + path: | + /tmp/gh-aw/sandbox/agent/logs/ + /tmp/gh-aw/redacted-urls.log + if-no-files-found: ignore + - name: Parse agent logs for step summary + if: always() + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: /tmp/gh-aw/sandbox/agent/logs/ + 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/parse_copilot_log.cjs'); + await main(); + - name: Parse MCP Gateway logs for step summary + if: always() + 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/parse_mcp_gateway_log.cjs'); + await main(); + - name: Print firewall logs + if: always() + continue-on-error: true + env: + AWF_LOGS_DIR: /tmp/gh-aw/sandbox/firewall/logs + run: | + # Fix permissions on firewall logs so they can be uploaded as artifacts + # AWF runs with sudo, creating files owned by root + sudo chmod -R a+r /tmp/gh-aw/sandbox/firewall/logs 2>/dev/null || true + # Only run awf logs summary if awf command exists (it may not be installed if workflow failed before install step) + if command -v awf &> /dev/null; then + awf logs summary | tee -a "$GITHUB_STEP_SUMMARY" + else + echo 'AWF binary not installed, skipping firewall log summary' + fi + - name: Upload agent artifacts + if: always() + continue-on-error: true + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: agent-artifacts + path: | + /tmp/gh-aw/aw-prompts/prompt.txt + /tmp/gh-aw/aw_info.json + /tmp/gh-aw/mcp-logs/ + /tmp/gh-aw/sandbox/firewall/logs/ + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/agent/ + if-no-files-found: ignore + + conclusion: + needs: + - activation + - agent + - detection + - safe_outputs + if: (always()) && (needs.agent.result != 'skipped') + runs-on: ubuntu-slim + permissions: + contents: read + issues: write + outputs: + noop_message: ${{ steps.noop.outputs.noop_message }} + tools_reported: ${{ steps.missing_tool.outputs.tools_reported }} + total_count: ${{ steps.missing_tool.outputs.total_count }} + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 + with: + destination: /opt/gh-aw/actions + - name: Download agent output artifact + continue-on-error: true + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 + with: + name: agent-output + path: /tmp/gh-aw/safeoutputs/ + - name: Setup agent output environment variable + run: | + mkdir -p /tmp/gh-aw/safeoutputs/ + find "/tmp/gh-aw/safeoutputs/" -type f -print + echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/safeoutputs/agent_output.json" >> "$GITHUB_ENV" + - name: Process No-Op Messages + id: noop + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_NOOP_MAX: 1 + GH_AW_WORKFLOW_NAME: "Text Auditor" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/noop.cjs'); + await main(); + - name: Record Missing Tool + id: missing_tool + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_WORKFLOW_NAME: "Text Auditor" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/missing_tool.cjs'); + await main(); + - name: Handle Agent Failure + id: handle_agent_failure + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_WORKFLOW_NAME: "Text Auditor" + 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: "gh-aw-text-auditor" + GH_AW_SECRET_VERIFICATION_RESULT: ${{ needs.agent.outputs.secret_verification_result }} + GH_AW_CHECKOUT_PR_SUCCESS: ${{ needs.agent.outputs.checkout_pr_success }} + GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\"}" + GH_AW_GROUP_REPORTS: "false" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/handle_agent_failure.cjs'); + await main(); + - name: Handle No-Op Message + id: handle_noop_message + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_WORKFLOW_NAME: "Text Auditor" + 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 }} + GH_AW_NOOP_REPORT_AS_ISSUE: "true" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/handle_noop_message.cjs'); + await main(); + + detection: + needs: agent + if: needs.agent.outputs.output_types != '' || needs.agent.outputs.has_patch == 'true' + runs-on: ubuntu-latest + permissions: {} + concurrency: + group: "gh-aw-copilot-${{ github.workflow }}" + timeout-minutes: 10 + outputs: + success: ${{ steps.parse_results.outputs.success }} + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 + with: + destination: /opt/gh-aw/actions + - name: Download agent artifacts + continue-on-error: true + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 + with: + name: agent-artifacts + path: /tmp/gh-aw/threat-detection/ + - name: Download agent output artifact + continue-on-error: true + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 + with: + name: agent-output + path: /tmp/gh-aw/threat-detection/ + - name: Print agent output types + env: + AGENT_OUTPUT_TYPES: ${{ needs.agent.outputs.output_types }} + run: | + echo "Agent output-types: $AGENT_OUTPUT_TYPES" + - name: Setup threat detection + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + WORKFLOW_NAME: "Text Auditor" + WORKFLOW_DESCRIPTION: "Find typos, unclear error messages, and awkward user-facing text, then file an improvement issue" + HAS_PATCH: ${{ needs.agent.outputs.has_patch }} + 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/setup_threat_detection.cjs'); + await main(); + - name: Ensure threat-detection directory and log + run: | + mkdir -p /tmp/gh-aw/threat-detection + touch /tmp/gh-aw/threat-detection/detection.log + - name: Validate COPILOT_GITHUB_TOKEN secret + id: validate-secret + run: /opt/gh-aw/actions/validate_multi_secret.sh COPILOT_GITHUB_TOKEN 'GitHub Copilot CLI' https://github.github.com/gh-aw/reference/engines/#github-copilot-default + env: + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + - name: Install GitHub Copilot CLI + run: /opt/gh-aw/actions/install_copilot_cli.sh 0.0.412 + - name: Execute GitHub Copilot CLI + id: agentic_execution + # Copilot CLI tool arguments (sorted): + # --allow-tool shell(cat) + # --allow-tool shell(grep) + # --allow-tool shell(head) + # --allow-tool shell(jq) + # --allow-tool shell(ls) + # --allow-tool shell(tail) + # --allow-tool shell(wc) + timeout-minutes: 20 + run: | + set -o pipefail + COPILOT_CLI_INSTRUCTION="$(cat /tmp/gh-aw/aw-prompts/prompt.txt)" + mkdir -p /tmp/ + mkdir -p /tmp/gh-aw/ + mkdir -p /tmp/gh-aw/agent/ + mkdir -p /tmp/gh-aw/sandbox/agent/logs/ + copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log + env: + COPILOT_AGENT_RUNNER_TYPE: STANDALONE + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GITHUB_HEAD_REF: ${{ github.head_ref }} + GITHUB_REF_NAME: ${{ github.ref_name }} + GITHUB_STEP_SUMMARY: ${{ env.GITHUB_STEP_SUMMARY }} + GITHUB_WORKSPACE: ${{ github.workspace }} + XDG_CONFIG_HOME: /home/runner + - name: Parse threat detection results + id: parse_results + 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/parse_threat_detection_results.cjs'); + await main(); + - name: Upload threat detection log + if: always() + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: threat-detection.log + path: /tmp/gh-aw/threat-detection/detection.log + if-no-files-found: ignore + + pre_activation: + runs-on: ubuntu-slim + outputs: + activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 + with: + destination: /opt/gh-aw/actions + - name: Check team membership for workflow + id: check_membership + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_REQUIRED_ROLES: admin,maintainer,write + GH_AW_ALLOWED_BOTS: ${{ inputs.allowed-bot-users }} + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + 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_membership.cjs'); + await main(); + + safe_outputs: + needs: + - agent + - detection + if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (needs.detection.outputs.success == 'true') + runs-on: ubuntu-slim + permissions: + contents: read + issues: write + timeout-minutes: 15 + env: + GH_AW_ENGINE_ID: "copilot" + GH_AW_ENGINE_MODEL: "${{ inputs.model }}" + GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\"}" + GH_AW_WORKFLOW_ID: "gh-aw-text-auditor" + GH_AW_WORKFLOW_NAME: "Text Auditor" + outputs: + create_discussion_error_count: ${{ steps.process_safe_outputs.outputs.create_discussion_error_count }} + create_discussion_errors: ${{ steps.process_safe_outputs.outputs.create_discussion_errors }} + process_safe_outputs_processed_count: ${{ steps.process_safe_outputs.outputs.processed_count }} + process_safe_outputs_temporary_id_map: ${{ steps.process_safe_outputs.outputs.temporary_id_map }} + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 + with: + destination: /opt/gh-aw/actions + - name: Download agent output artifact + continue-on-error: true + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 + with: + name: agent-output + path: /tmp/gh-aw/safeoutputs/ + - name: Setup agent output environment variable + run: | + mkdir -p /tmp/gh-aw/safeoutputs/ + find "/tmp/gh-aw/safeoutputs/" -type f -print + echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/safeoutputs/agent_output.json" >> "$GITHUB_ENV" + - name: Process Safe Outputs + id: process_safe_outputs + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_issue\":{\"close_older_issues\":true,\"expires\":168,\"max\":1,\"title_prefix\":\"[text-auditor] \"},\"missing_data\":{},\"missing_tool\":{}}" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/safe_output_handler_manager.cjs'); + await main(); + - name: Upload safe output items manifest + if: always() + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: safe-output-items + path: /tmp/safe-output-items.jsonl + if-no-files-found: warn + diff --git a/.github/workflows/gh-aw-text-auditor.md b/.github/workflows/gh-aw-text-auditor.md new file mode 100644 index 00000000..057167b9 --- /dev/null +++ b/.github/workflows/gh-aw-text-auditor.md @@ -0,0 +1,224 @@ +--- +inlined-imports: true +name: "Text Auditor" +description: "Find typos, unclear error messages, and awkward user-facing text, then file an improvement issue" +imports: + - gh-aw-fragments/elastic-tools.md + - gh-aw-fragments/runtime-setup.md + - gh-aw-fragments/formatting.md + - gh-aw-fragments/rigor.md + - gh-aw-fragments/mcp-pagination.md + - gh-aw-fragments/messages-footer.md + - gh-aw-fragments/safe-output-create-issue.md + - gh-aw-fragments/scheduled-audit.md +engine: + id: copilot + model: ${{ inputs.model }} +on: + workflow_call: + inputs: + model: + description: "AI model to use" + type: string + required: false + default: "gpt-5.3-codex" + additional-instructions: + description: "Repo-specific instructions appended to the agent prompt" + type: string + required: false + default: "" + setup-commands: + description: "Shell commands to run before the agent starts (dependency install, build, etc.)" + type: string + required: false + default: "" + allowed-bot-users: + description: "Allowlisted bot actor usernames (comma-separated)" + type: string + required: false + default: "github-actions[bot]" + messages-footer: + description: "Footer appended to all agent comments and reviews" + type: string + required: false + default: "" + edit-typos: + description: "How aggressively to flag typos and misspellings. 'high' = suggest broad consistency fixes, 'low' = flag only clear spelling errors, 'none' = skip typo checks" + type: string + required: false + default: "low" + edit-grammar: + description: "How aggressively to flag grammar and sentence construction problems. 'high' = improve awkward sentence structure, 'low' = flag only clear grammatical errors, 'none' = skip grammar checks" + type: string + required: false + default: "low" + edit-clarity: + description: "How aggressively to flag unclear user-facing text, especially error/help messages. 'high' = proactively suggest clearer phrasing, 'low' = flag only clearly ambiguous text, 'none' = skip clarity checks" + type: string + required: false + default: "low" + edit-terminology: + description: "How aggressively to flag inconsistent terminology for the same concept. 'high' = proactively normalize wording, 'low' = flag only unambiguous inconsistencies, 'none' = skip terminology checks" + type: string + required: false + default: "low" + edit-misleading-text: + description: "How aggressively to flag text that conflicts with current behavior. 'high' = proactively flag likely drift, 'low' = flag only direct contradictions, 'none' = skip behavior-alignment checks" + type: string + required: false + default: "low" + secrets: + COPILOT_GITHUB_TOKEN: + required: true + roles: [admin, maintainer, write] + bots: + - "${{ inputs.allowed-bot-users }}" +concurrency: + group: text-auditor + cancel-in-progress: true +permissions: + contents: read + issues: read + pull-requests: read +tools: + github: + toolsets: [repos, issues, pull_requests, search, labels] + bash: true + web-fetch: +network: + allowed: + - defaults + - github + - go + - node + - python + - ruby +strict: false +safe-outputs: + noop: + create-issue: + max: 1 + title-prefix: "[text-auditor] " + close-older-issues: true + expires: 7d +timeout-minutes: 90 +steps: + - name: Repo-specific setup + if: ${{ inputs.setup-commands != '' }} + env: + SETUP_COMMANDS: ${{ inputs.setup-commands }} + run: eval "$SETUP_COMMANDS" +--- + +Find typos, unclear error messages, and awkward user-facing text that are low-effort to fix, and file a single improvement issue. + +**The bar is high: only report concrete, unambiguous text problems.** Most runs should end with `noop` — that means user-facing text is clean. + +## Edit Level Configuration + +The following edit levels are configured for this run. Each dimension is independent. + +| Dimension | Level | Meaning | +| --- | --- | --- | +| **typos** | `${{ inputs.edit-typos }}` | How aggressively to flag typos and misspellings | +| **grammar** | `${{ inputs.edit-grammar }}` | How aggressively to flag grammar and sentence construction issues | +| **clarity** | `${{ inputs.edit-clarity }}` | How aggressively to flag unclear user-facing text | +| **terminology** | `${{ inputs.edit-terminology }}` | How aggressively to flag inconsistent naming for the same concept | +| **misleading-text** | `${{ inputs.edit-misleading-text }}` | How aggressively to flag text that no longer matches behavior | + +Level semantics: +- **`high`** — apply best judgment proactively within this dimension +- **`low`** — report only concrete, unambiguous issues +- **`none`** — skip this dimension entirely + +### Data Gathering + +1. Identify user-facing text sources — scan the repository for: + - CLI output strings, error messages, and help text + - Log messages shown to users (not debug-level internal logs) + - README, CONTRIBUTING, DEVELOPING, and other markdown documentation + - UI strings, notification templates, and user-visible configuration descriptions + - Code comments in public APIs that appear in generated documentation +2. Read the identified files and search for text issues. + +### What to Look For by Dimension + +Use each dimension's configured level to determine whether to report findings. + +#### Typos (`${{ inputs.edit-typos }}`) + +- **`high`**: Flag typos/misspellings proactively and include nearby consistency fixes when they are obviously beneficial. +- **`low`**: Flag only clear spelling errors (for example, `recieve` → `receive`), not style variants. +- **`none`**: Skip typo checks. + +#### Grammar (`${{ inputs.edit-grammar }}`) + +- **`high`**: Flag grammar and sentence construction issues that reduce readability, including awkward or fragmented sentences. +- **`low`**: Flag only clear grammatical errors (subject-verb disagreement, missing articles, broken sentence structure). +- **`none`**: Skip grammar checks. + +#### Clarity (`${{ inputs.edit-clarity }}`) + +- **`high`**: Proactively flag unclear user-facing text and suggest concrete rewrites, especially for errors/help text. +- **`low`**: Flag only clearly ambiguous or incomplete user-facing text (for example, `"Error: failed"` with no actionable context). +- **`none`**: Skip clarity checks. + +#### Terminology (`${{ inputs.edit-terminology }}`) + +- **`high`**: Proactively flag inconsistent naming for the same concept across user-facing surfaces. +- **`low`**: Flag only unambiguous inconsistencies where the same concept is clearly referred to by different terms. +- **`none`**: Skip terminology checks. + +#### Misleading Text (`${{ inputs.edit-misleading-text }}`) + +- **`high`**: Proactively flag text likely to have drifted from behavior. +- **`low`**: Flag only direct, verifiable contradictions between text and current code behavior. +- **`none`**: Skip behavior-alignment checks. + +### What to Skip + +- **Style preferences** — do not flag Oxford comma usage, line length, or prose style unless it causes ambiguity +- **Internal-only text** — debug logs, developer-only comments, test fixtures +- **Intentional abbreviations** — short forms that are standard in the project +- **Generated or vendored files** — do not scan auto-generated code, lock files, or third-party content +- **Issues already tracked** — check open issues before filing +- **Findings that require design decisions** — if fixing the text requires deciding on new terminology or restructuring content, skip it + +### Quality Gate — When to Noop + +Call `noop` if any of these are true: +- All edit dimensions are set to `none` +- No concrete text problems were found +- All findings are style preferences rather than clear errors +- The problems found are in generated or vendored files +- A similar issue is already open +- The fixes would require design decisions or significant rewording beyond simple corrections + +### Issue Format + +**Issue title:** Brief summary of text improvements found + +**Issue body:** + +> ## Text Improvements +> +> The following user-facing text issues were found in the repository. Each is a low-effort fix. +> +> ### 1. [Brief description] +> +> **File:** `path/to/file` (line N) +> **Current text:** `the existing text with the problem` +> **Suggested fix:** `the corrected text` +> **Why:** [Brief explanation — typo, grammar, unclear error, etc.] +> +> ### 2. [Next finding...] +> +> ## Suggested Actions +> +> - [ ] [Specific, actionable checkbox for each fix] + +### Labeling + +- If the `text-auditor` label exists (check with `github-get_label`), include it in the `create_issue` call; otherwise, rely on the `[text-auditor]` title prefix only. + +${{ inputs.additional-instructions }} diff --git a/.github/workflows/gh-aw-text-beautifier.lock.yml b/.github/workflows/gh-aw-text-beautifier.lock.yml index 69d59439..e6a8cb4b 100644 --- a/.github/workflows/gh-aw-text-beautifier.lock.yml +++ b/.github/workflows/gh-aw-text-beautifier.lock.yml @@ -21,7 +21,7 @@ # # For more information: https://github.github.com/gh-aw/introduction/overview/ # -# Find typos, unclear error messages, and awkward user-facing text, then file an improvement issue +# Fix text-auditor issues by opening a focused PR with text improvements # # Resolved workflow manifest: # Imports: @@ -31,10 +31,13 @@ # - gh-aw-fragments/messages-footer.md # - gh-aw-fragments/rigor.md # - gh-aw-fragments/runtime-setup.md -# - gh-aw-fragments/safe-output-create-issue.md -# - gh-aw-fragments/scheduled-report.md +# - gh-aw-fragments/safe-output-create-pr.md +# - gh-aw-fragments/scheduled-fix.md +# - gh-aw-fragments/workflow-edit-guardrails.md # -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"94e0ef170b5dcfb1db15ea8c5d82f50384a1a9bd9bef1a34975791473b4eeb49"} +# inlined-imports: true +# +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"a1121a70c3e10592769073ae4d7b04b6707d0edb359aaf0deaede0735374b870"} name: "Text Beautifier" "on": @@ -61,6 +64,11 @@ name: "Text Beautifier" description: Footer appended to all agent comments and reviews required: false type: string + model: + default: gpt-5.3-codex + description: AI model to use + required: false + type: string setup-commands: default: "" description: Shell commands to run before the agent starts (dependency install, build, etc.) @@ -90,7 +98,7 @@ jobs: comment_repo: "" steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Validate context variables @@ -167,6 +175,30 @@ jobs: **Critical**: Tool calls write structured data that downstream jobs process. Without tool calls, follow-up actions will be skipped. **Note**: If you made no other safe output tool calls during this workflow execution, call the "noop" tool to provide a status message indicating completion or that no actions were needed. + + --- + + ## Creating a Pull Request, Reporting Missing Tools or Functionality, Reporting Missing Data + + **IMPORTANT**: To perform the actions listed above, use the **safeoutputs** tools. Do NOT use `gh`, do NOT call the GitHub API directly. You do not have write access to the GitHub repository. + + **Creating a Pull Request** + + To create a pull request: + 1. Make any file changes directly in the working directory. + 2. If you haven't done so already, create a local branch using an appropriate unique name. + 3. Add and commit your changes to the branch. Be careful to add exactly the files you intend, and check there are no extra files left un-added. Verify you haven't deleted or changed any files you didn't intend to. + 4. Do not push your changes. That will be done by the tool. + 5. Create the pull request with the create_pull_request tool from safeoutputs. + + **Reporting Missing Tools or Functionality** + + To report a missing tool or capability, use the missing_tool tool from safeoutputs. + + **Reporting Missing Data** + + To report missing data required to achieve a goal, use the missing_data tool from safeoutputs. + @@ -267,6 +299,13 @@ jobs: - **Use filters**: Combine `perPage` with state, label, or date filters to reduce result size - **Process as you go**: Don't accumulate all pages before acting — process each batch immediately + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + ## Workflow Editing Guardrails + + - Do not modify files under `.github/workflows/`. + - If asked to change workflow files, place a copy under `github/` (no leading dot) and note that a maintainer must relocate it into `.github/workflows/`. + GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" ## Message Footer @@ -274,19 +313,21 @@ jobs: A footer is automatically appended to all comments and reviews. Do not add your own footer or sign-off — the runtime handles this. GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - ## create-issue Limitations - - - **Title**: Max 128 characters. Sanitized (special characters escaped). - - **Labels**: Max 10 labels per issue. Each label max 64 characters. Labels containing only `-` are rejected. - - **Assignees**: Max 5 assignees per issue. - - **Body**: No strict character limit beyond GitHub's API limit (~65,536 characters), but fields over 16,000 tokens are written to a file reference instead of inlined. - - **Bot triggers**: References like `fixes #123` or `closes #456` in the body are neutralized to prevent unintended issue closures. - - **Mentions**: `@mentions` in the body are neutralized (backticked) by default. + Before calling `create_pull_request`, call `ready_to_make_pr` and apply its checklist. + + ## create-pull-request Limitations + + - **Patch files**: Max 100 files per PR. If changes span more files, split into multiple focused PRs. + - **Patch size**: Max 1,024 KB by default. Keep changes focused. + - **Title**: Max 128 characters. Sanitized. + - **Body**: No explicit mention/link limits, but bot triggers (`fixes #123`, `closes #456`) are neutralized. + - **Committed changes required**: You must have locally committed changes before creating a PR (unless `allow_empty` is configured). + - **Base branch**: Must be configured in the safe-output config. The PR targets this branch. + - **Max per run**: Typically 1 PR creation per workflow run. + - You may not submit code that modifies files in `.github/workflows/`. Doing so will cause the submission to be rejected. If asked to modify workflow files, propose the change in a copy placed in a `github/` folder (without the leading period) and note in the PR that the file needs to be relocated by someone with workflow write access. GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - # Scheduled Report Agent - - You are a report agent for __GH_AW_GITHUB_REPOSITORY__. You run on a schedule to investigate the repository and file an issue when something needs attention. Your specific assignment is described in the **Report Assignment** section below. + You are an agent for __GH_AW_GITHUB_REPOSITORY__. You run on a schedule to pick up an open issue and create a focused pull request that addresses it. Your specific assignment is described in the **Fix Assignment** section below. ## Context @@ -294,136 +335,81 @@ jobs: ## Constraints - This workflow is for detection and reporting only. You can read files, search code, run commands, and read PR/issue details — but your only output is either a single issue or a noop. + - **CAN**: Read files, search code, modify files locally, run tests and commands, create a pull request. + - **CANNOT**: Directly push to the repository — use `create_pull_request`. + - **Only one PR per run.** + - If no suitable issue is found, call `noop` with a brief reason. + - **Most runs should end with `noop`.** Only open a PR when the fix is clearly correct, tested, and small enough for quick review. ## Process Follow these steps in order. - ### Step 1: Gather Context + ### Step 1: Gather Candidates 1. Call `generate_agents_md` to get the repository's coding guidelines and conventions. If this fails, continue without it. - 2. Follow the data gathering instructions in the **Report Assignment** section. + 2. Follow the candidate gathering instructions in the **Fix Assignment** section. + 3. For each candidate, read the full issue and comments using `issue_read` (methods `get` and `get_comments`). - ### Step 2: Analyze + ### Step 2: Select a Target - Follow the analysis instructions in the **Report Assignment** section to determine whether an issue should be filed. The Report Assignment defines: - - What data to gather and how - - What to look for - - What constitutes a finding worth reporting - - What to skip or ignore + Choose one issue with: - ### Step 3: Self-Review (Quality Gate) + - Concrete, actionable instructions (file paths, function names, suggested changes) + - A well-scoped fix that doesn't require design decisions + - No active discussion suggesting the fix should go a different direction - Before filing anything, critically evaluate every finding against these criteria: + Skip any issue where the suggested fix is ambiguous, controversial, or too large for a single PR. - 1. **Evidence is concrete** — you can point to exact file paths, line numbers, commit SHAs, or command outputs. No "I believe" or "it seems." - 2. **Finding is actionable** — a maintainer reading the issue can act on it without re-investigating from scratch. - 3. **Finding is not already tracked** — you checked open issues and recent PRs for duplicates. - 4. **Finding is worth a human's time** — the issue is material enough that a maintainer would thank you for filing it, not close it as noise. + ### Step 3: Implement - If zero findings pass all four criteria, call `noop` with a brief reason and stop. **Noop is the expected outcome most days.** Filing nothing is a success when there is nothing worth filing. + Follow the implementation instructions in the **Fix Assignment** section. The Fix Assignment defines: + - What kind of changes to make + - What tools to use + - Any domain-specific constraints - ### Step 4: Report + ### Step 4: Quality Gate — Self-Review - If there are findings that pass the quality gate, call `create_issue` with a structured report. Use the issue format specified in the Report Assignment if one is provided, otherwise use this default format: + Before creating the PR, verify: - **Issue title:** Brief summary of findings + 1. **Fix is correct** — the change directly addresses the issue. + 2. **Tests pass** — you ran the most relevant tests and they pass. + 3. **Scope is minimal** — only changes needed for the fix, no scope creep. + 4. **No regressions** — linters pass, no formatting broken, no new warnings. - **Issue body:** + If any check fails, call `noop` with a brief reason. - > ## Findings - > - > ### 1. [Brief description] - > - > **Evidence:** [Links, references, or data supporting the finding] - > **Action needed:** [What should be done] - > - > ## Suggested Actions - > - > - [ ] [Actionable checkbox for each finding] + ### Step 5: Create the PR - **Guidelines:** - - Group related findings together - - Be specific about what needs to happen - - Include links and references where possible - - Make suggested actions concrete enough to act on without re-investigating - - If a finding is ambiguous, it does not pass the quality gate — drop it + Call `create_pull_request` with: + - A concise summary of the changes + - A link to the source issue (e.g., "Fixes #123") + - The specific tests that were run and passed + - A note on any items from the issue that were skipped (if any) - ## Report Assignment + **Fix Assignment:** GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - Find typos, unclear error messages, and awkward user-facing text that are low-effort to fix, and file a single improvement issue. + ### Candidate Search - **The bar is high: only report concrete, unambiguous text problems.** Most runs should end with `noop` — that means user-facing text is clean. + Search for open Text Auditor issues: - ### Data Gathering + ````text + github-search_issues: query="repo:{owner}/{repo} is:issue is:open (label:text-auditor OR in:title \"[text-auditor]\") sort:updated-asc" + ```` - 1. Call `generate_agents_md` to get repository conventions. If it fails, continue. - 2. Identify user-facing text sources — scan the repository for: - - CLI output strings, error messages, and help text - - Log messages shown to users (not debug-level internal logs) - - README, CONTRIBUTING, DEVELOPING, and other markdown documentation - - UI strings, notification templates, and user-visible configuration descriptions - - Code comments in public APIs that appear in generated documentation - 3. Read the identified files and search for text issues. + ### Implementation - ### What to Look For + 1. Read each file mentioned in the issue. + 2. Apply the suggested text corrections. For each fix: + - Verify the current text matches what the issue describes + - Apply the suggested replacement + - If the current text has changed since the issue was filed, skip that fix + 3. Run any available linters or formatters to verify the changes don't break anything. + 4. Commit the changes locally. - Focus on **concrete, unambiguous problems** in user-facing text: - - 1. **Typos and misspellings** — real spelling errors, not style preferences (e.g., `recieve` → `receive`, `occurence` → `occurrence`) - 2. **Grammatical errors** — subject-verb disagreement, missing articles, broken sentences - 3. **Unclear error messages** — errors that do not tell the user what went wrong or what to do next (e.g., `"Error: failed"` with no context) - 4. **Inconsistent terminology** — the same concept referred to by different names in different places (e.g., `workspace` vs `project` vs `repo` for the same thing) - 5. **Broken or incomplete sentences** — truncated messages, dangling phrases, copy-paste artifacts - 6. **Misleading text** — messages that describe behavior that no longer matches the code - - ### What to Skip - - - **Style preferences** — do not flag Oxford comma usage, line length, or prose style unless it causes ambiguity - - **Internal-only text** — debug logs, developer-only comments, test fixtures - - **Intentional abbreviations** — short forms that are standard in the project - - **Generated or vendored files** — do not scan auto-generated code, lock files, or third-party content - - **Issues already tracked** — check open issues before filing - - **Findings that require design decisions** — if fixing the text requires deciding on new terminology or restructuring content, skip it - - ### Quality Gate — When to Noop - - Call `noop` if any of these are true: - - No concrete text problems were found - - All findings are style preferences rather than clear errors - - The problems found are in generated or vendored files - - A similar issue is already open - - The fixes would require design decisions or significant rewording beyond simple corrections - - ### Issue Format - - **Issue title:** Brief summary of text improvements found - - **Issue body:** - - > ## Text Improvements - > - > The following user-facing text issues were found in the repository. Each is a low-effort fix. - > - > ### 1. [Brief description] - > - > **File:** `path/to/file` (line N) - > **Current text:** `the existing text with the problem` - > **Suggested fix:** `the corrected text` - > **Why:** [Brief explanation — typo, grammar, unclear error, etc.] - > - > ### 2. [Next finding...] - > - > ## Suggested Actions - > - > - [ ] [Specific, actionable checkbox for each fix] - - ### Labeling - - - If the `text-beautifier` label exists (check with `github-get_label`), include it in the `create_issue` call; otherwise, rely on the `[text-beautifier]` title prefix only. + Only text changes — no logic, no refactoring, no new features. __GH_AW_EXPR_49B959F1__ @@ -523,7 +509,7 @@ jobs: secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Checkout repository @@ -617,7 +603,7 @@ jobs: const awInfo = { engine_id: "copilot", engine_name: "GitHub Copilot CLI", - model: "gpt-5.3-codex", + model: "${{ inputs.model }}", version: "", agent_version: "0.0.412", workflow_name: "Text Beautifier", @@ -677,40 +663,36 @@ jobs: 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' - {"create_issue":{"expires":168,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1}} + {"create_pull_request":{"max":1},"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 \"[text-beautifier] \".", + "description": "Create a new GitHub pull request to propose code changes. Use this after making file edits to submit them for review and merging. The PR will be created from the current branch with your committed changes. For code review comments on an existing PR, use create_pull_request_review_comment instead. CONSTRAINTS: Maximum 1 pull request(s) can be created.", "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.", + "description": "Detailed PR description in Markdown. Include what changes were made, why, testing notes, and any breaking changes. Do NOT repeat the title as a heading.", + "type": "string" + }, + "branch": { + "description": "Source branch name containing the changes. If omitted, uses the current working branch.", "type": "string" }, + "draft": { + "description": "Whether to create the PR as a draft. Draft PRs cannot be merged until marked as ready for review. Use mark_pull_request_as_ready_for_review to convert a draft PR. Default: true.", + "type": "boolean" + }, "labels": { - "description": "Labels to categorize the issue (e.g., 'bug', 'enhancement'). Labels must exist in the repository.", + "description": "Labels to categorize the PR (e.g., 'enhancement', 'bugfix'). 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.", + "description": "Concise PR title describing the changes. Follow repository conventions (e.g., conventional commits). The title appears as the main heading.", "type": "string" } }, @@ -720,7 +702,7 @@ jobs: ], "type": "object" }, - "name": "create_issue" + "name": "create_pull_request" }, { "description": "Report that a tool or capability needed to complete the task is not available, or share any information you deem important about missing functionality or limitations. Use this when you cannot accomplish what was requested because the required functionality is missing or access is restricted.", @@ -795,7 +777,7 @@ jobs: GH_AW_SAFE_OUTPUTS_TOOLS_EOF cat > /opt/gh-aw/safeoutputs/validation.json << 'GH_AW_SAFE_OUTPUTS_VALIDATION_EOF' { - "create_issue": { + "create_pull_request": { "defaultMax": 1, "fields": { "body": { @@ -804,22 +786,25 @@ jobs: "sanitize": true, "maxLength": 65000 }, + "branch": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "draft": { + "type": "boolean" + }, "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", @@ -828,6 +813,31 @@ jobs: } } }, + "missing_data": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "context": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "data_type": { + "type": "string", + "sanitize": true, + "maxLength": 128 + }, + "reason": { + "type": "string", + "sanitize": true, + "maxLength": 256 + } + } + }, "missing_tool": { "defaultMax": 20, "fields": { @@ -900,9 +910,99 @@ jobs: bash /opt/gh-aw/actions/start_safe_outputs_server.sh + - name: Setup Safe Inputs Config + run: | + mkdir -p /opt/gh-aw/safe-inputs/logs + cat > /opt/gh-aw/safe-inputs/tools.json << 'GH_AW_SAFE_INPUTS_TOOLS_EOF' + { + "serverName": "safeinputs", + "version": "1.0.0", + "logDir": "/opt/gh-aw/safe-inputs/logs", + "tools": [ + { + "name": "ready-to-make-pr", + "description": "Run the PR readiness checklist before creating or updating a PR", + "inputSchema": { + "properties": {}, + "type": "object" + }, + "handler": "ready-to-make-pr.cjs", + "timeout": 60 + } + ] + } + GH_AW_SAFE_INPUTS_TOOLS_EOF + cat > /opt/gh-aw/safe-inputs/mcp-server.cjs << 'GH_AW_SAFE_INPUTS_SERVER_EOF' + const path = require("path"); + const { startHttpServer } = require("./safe_inputs_mcp_server_http.cjs"); + const configPath = path.join(__dirname, "tools.json"); + const port = parseInt(process.env.GH_AW_SAFE_INPUTS_PORT || "3000", 10); + const apiKey = process.env.GH_AW_SAFE_INPUTS_API_KEY || ""; + startHttpServer(configPath, { + port: port, + stateless: true, + logDir: "/opt/gh-aw/safe-inputs/logs" + }).catch(error => { + console.error("Failed to start safe-inputs HTTP server:", error); + process.exit(1); + }); + GH_AW_SAFE_INPUTS_SERVER_EOF + chmod +x /opt/gh-aw/safe-inputs/mcp-server.cjs + + - name: Setup Safe Inputs Tool Files + run: | + cat > /opt/gh-aw/safe-inputs/ready-to-make-pr.cjs << 'GH_AW_SAFE_INPUTS_JS_READY-TO-MAKE-PR_EOF' + async function execute(inputs) { + const fs = require('fs'); + const find = (...paths) => paths.find(p => fs.existsSync(p)) || null; + const contributing = find('CONTRIBUTING.md', 'CONTRIBUTING.rst', 'docs/CONTRIBUTING.md', 'docs/contributing.md'); + const prTemplate = find('.github/pull_request_template.md', '.github/PULL_REQUEST_TEMPLATE.md', '.github/PULL_REQUEST_TEMPLATE/pull_request_template.md'); + const checklist = []; + if (contributing) checklist.push(`Review the contributing guide (${contributing}) before opening or updating a PR.`); + if (prTemplate) checklist.push(`Follow the PR template (${prTemplate}) for title, description, and validation notes.`); + checklist.push('Confirm the requested task is fully completed and validated before creating or pushing PR changes.'); + return { status: 'ok', checklist, contributing_guide: contributing, pr_template: prTemplate }; + } + module.exports = { execute }; + GH_AW_SAFE_INPUTS_JS_READY-TO-MAKE-PR_EOF + + - name: Generate Safe Inputs MCP Server Config + id: safe-inputs-config + run: | + # Generate a secure random API key (360 bits of entropy, 40+ chars) + # Mask immediately to prevent timing vulnerabilities + API_KEY=$(openssl rand -base64 45 | tr -d '/+=') + echo "::add-mask::${API_KEY}" + + PORT=3000 + + # Set outputs for next steps + { + echo "safe_inputs_api_key=${API_KEY}" + echo "safe_inputs_port=${PORT}" + } >> "$GITHUB_OUTPUT" + + echo "Safe Inputs MCP server will run on port ${PORT}" + + - name: Start Safe Inputs MCP HTTP Server + id: safe-inputs-start + env: + DEBUG: '*' + GH_AW_SAFE_INPUTS_PORT: ${{ steps.safe-inputs-config.outputs.safe_inputs_port }} + GH_AW_SAFE_INPUTS_API_KEY: ${{ steps.safe-inputs-config.outputs.safe_inputs_api_key }} + run: | + # Environment variables are set above to prevent template injection + export DEBUG + export GH_AW_SAFE_INPUTS_PORT + export GH_AW_SAFE_INPUTS_API_KEY + + bash /opt/gh-aw/actions/start_safe_inputs_server.sh + - name: Start MCP Gateway id: start-mcp-gateway env: + GH_AW_SAFE_INPUTS_API_KEY: ${{ steps.safe-inputs-start.outputs.api_key }} + GH_AW_SAFE_INPUTS_PORT: ${{ steps.safe-inputs-start.outputs.port }} GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-start.outputs.api_key }} GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-start.outputs.port }} @@ -923,7 +1023,7 @@ jobs: export DEBUG="*" export GH_AW_ENGINE="copilot" - 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 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_LOCKDOWN -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.1.4' + 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 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_LOCKDOWN -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_INPUTS_PORT -e GH_AW_SAFE_INPUTS_API_KEY -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.1.4' mkdir -p /home/runner/.copilot cat << GH_AW_MCP_CONFIG_EOF | bash /opt/gh-aw/actions/start_mcp_gateway.sh @@ -943,7 +1043,7 @@ jobs: "GITHUB_LOCKDOWN_MODE": "$GITHUB_MCP_LOCKDOWN", "GITHUB_PERSONAL_ACCESS_TOKEN": "\${GITHUB_MCP_SERVER_TOKEN}", "GITHUB_READ_ONLY": "1", - "GITHUB_TOOLSETS": "repos,issues,pull_requests,search,labels" + "GITHUB_TOOLSETS": "repos,issues,pull_requests,search" } }, "public-code-search": { @@ -953,6 +1053,13 @@ jobs: "search_code" ] }, + "safeinputs": { + "type": "http", + "url": "http://host.docker.internal:$GH_AW_SAFE_INPUTS_PORT", + "headers": { + "Authorization": "\${GH_AW_SAFE_INPUTS_API_KEY}" + } + }, "safeoutputs": { "type": "http", "url": "http://host.docker.internal:$GH_AW_SAFE_OUTPUTS_PORT", @@ -989,10 +1096,11 @@ jobs: run: | set -o pipefail sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --allow-domains '*.githubusercontent.com,*.jsr.io,*.pythonhosted.org,*.rvm.io,agents-md-generator.fastmcp.app,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.rubygems.org,api.snapcraft.io,archive.ubuntu.com,artifacts.elastic.co,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,bun.sh,bundler.rubygems.org,cache.ruby-lang.org,cdn.jsdelivr.net,cloud.elastic.co,codeload.github.com,conda.anaconda.org,conda.binstar.org,crates.io,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,deb.nodesource.com,deno.land,ela.st,elastic.co,esm.sh,files.pythonhosted.org,gems.rubyforge.org,gems.rubyonrails.org,get.pnpm.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,host.docker.internal,index.crates.io,index.rubygems.org,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,lfs.github.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,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,pip.pypa.io,pkg.go.dev,ppa.launchpad.net,proxy.golang.org,public-code-search.fastmcp.app,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.bower.io,registry.npmjs.com,registry.npmjs.org,registry.yarnpkg.com,repo.anaconda.com,repo.continuum.io,repo.yarnpkg.com,rubygems.org,rubygems.pkg.github.com,s.symcb.com,s.symcd.com,security.ubuntu.com,skimdb.npmjs.com,static.crates.io,storage.googleapis.com,sum.golang.org,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.elastic.co,www.npmjs.com,www.npmjs.org,yarnpkg.com' --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.20.2 --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 --model gpt-5.3-codex --allow-all-tools --allow-all-paths --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log + -- /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 --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} @@ -1102,6 +1210,15 @@ jobs: setupGlobals(core, github, context, exec, io); const { main } = require('/opt/gh-aw/actions/parse_copilot_log.cjs'); await main(); + - name: Parse Safe Inputs logs for step summary + if: always() + 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/parse_safe_inputs_logs.cjs'); + await main(); - name: Parse MCP Gateway logs for step summary if: always() uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 @@ -1136,9 +1253,11 @@ jobs: /tmp/gh-aw/aw-prompts/prompt.txt /tmp/gh-aw/aw_info.json /tmp/gh-aw/mcp-logs/ + /tmp/gh-aw/safe-inputs/logs/ /tmp/gh-aw/sandbox/firewall/logs/ /tmp/gh-aw/agent-stdio.log /tmp/gh-aw/agent/ + /tmp/gh-aw/aw-*.patch if-no-files-found: ignore conclusion: @@ -1150,15 +1269,16 @@ jobs: if: (always()) && (needs.agent.result != 'skipped') runs-on: ubuntu-slim permissions: - contents: read + contents: write issues: write + pull-requests: write outputs: noop_message: ${{ steps.noop.outputs.noop_message }} tools_reported: ${{ steps.missing_tool.outputs.tools_reported }} total_count: ${{ steps.missing_tool.outputs.total_count }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent output artifact @@ -1236,6 +1356,20 @@ jobs: setupGlobals(core, github, context, exec, io); const { main } = require('/opt/gh-aw/actions/handle_noop_message.cjs'); await main(); + - name: Handle Create Pull Request Error + id: handle_create_pr_error + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_WORKFLOW_NAME: "Text Beautifier" + GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/handle_create_pr_error.cjs'); + await main(); detection: needs: agent @@ -1249,7 +1383,7 @@ jobs: success: ${{ steps.parse_results.outputs.success }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent artifacts @@ -1273,7 +1407,7 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: WORKFLOW_NAME: "Text Beautifier" - WORKFLOW_DESCRIPTION: "Find typos, unclear error messages, and awkward user-facing text, then file an improvement issue" + WORKFLOW_DESCRIPTION: "Fix text-auditor issues by opening a focused PR with text improvements" HAS_PATCH: ${{ needs.agent.outputs.has_patch }} with: script: | @@ -1310,10 +1444,11 @@ jobs: mkdir -p /tmp/gh-aw/ mkdir -p /tmp/gh-aw/agent/ mkdir -p /tmp/gh-aw/sandbox/agent/logs/ - copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --model gpt-5.3-codex --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log + copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_REF_NAME: ${{ github.ref_name }} @@ -1343,7 +1478,7 @@ jobs: activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Check team membership for workflow @@ -1362,17 +1497,19 @@ jobs: safe_outputs: needs: + - activation - agent - detection if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (needs.detection.outputs.success == 'true') runs-on: ubuntu-slim permissions: - contents: read + contents: write issues: write + pull-requests: write timeout-minutes: 15 env: GH_AW_ENGINE_ID: "copilot" - GH_AW_ENGINE_MODEL: "gpt-5.3-codex" + GH_AW_ENGINE_MODEL: "${{ inputs.model }}" GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\"}" GH_AW_WORKFLOW_ID: "gh-aw-text-beautifier" GH_AW_WORKFLOW_NAME: "Text Beautifier" @@ -1383,7 +1520,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@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent output artifact @@ -1397,12 +1534,39 @@ jobs: mkdir -p /tmp/gh-aw/safeoutputs/ find "/tmp/gh-aw/safeoutputs/" -type f -print echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/safeoutputs/agent_output.json" >> "$GITHUB_ENV" + - name: Download patch artifact + continue-on-error: true + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6 + with: + name: agent-artifacts + path: /tmp/gh-aw/ + - name: Checkout repository + if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + ref: ${{ github.base_ref || github.ref_name }} + token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + persist-credentials: false + fetch-depth: 1 + - name: Configure Git credentials + if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) + env: + REPO_NAME: ${{ github.repository }} + SERVER_URL: ${{ github.server_url }} + GIT_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + run: | + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git config --global user.name "github-actions[bot]" + # Re-authenticate git with GitHub token + SERVER_URL_STRIPPED="${SERVER_URL#https://}" + git remote set-url origin "https://x-access-token:${GIT_TOKEN}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" + echo "Git configured with standard GitHub Actions identity" - name: Process Safe Outputs id: process_safe_outputs uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_issue\":{\"close_older_issues\":true,\"expires\":168,\"max\":1,\"title_prefix\":\"[text-beautifier] \"},\"missing_data\":{},\"missing_tool\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_pull_request\":{\"base_branch\":\"${{ github.base_ref || github.ref_name }}\",\"max\":1,\"max_patch_size\":1024},\"missing_data\":{},\"missing_tool\":{}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/gh-aw-text-beautifier.md b/.github/workflows/gh-aw-text-beautifier.md index 6371cd71..b8ba1748 100644 --- a/.github/workflows/gh-aw-text-beautifier.md +++ b/.github/workflows/gh-aw-text-beautifier.md @@ -1,21 +1,28 @@ --- +inlined-imports: true name: "Text Beautifier" -description: "Find typos, unclear error messages, and awkward user-facing text, then file an improvement issue" +description: "Fix text-auditor issues by opening a focused PR with text improvements" imports: - gh-aw-fragments/elastic-tools.md - gh-aw-fragments/runtime-setup.md - gh-aw-fragments/formatting.md - gh-aw-fragments/rigor.md - gh-aw-fragments/mcp-pagination.md + - gh-aw-fragments/workflow-edit-guardrails.md - gh-aw-fragments/messages-footer.md - - gh-aw-fragments/safe-output-create-issue.md - - gh-aw-fragments/scheduled-report.md + - gh-aw-fragments/safe-output-create-pr.md + - gh-aw-fragments/scheduled-fix.md engine: id: copilot - model: gpt-5.3-codex + model: ${{ inputs.model }} on: workflow_call: inputs: + model: + description: "AI model to use" + type: string + required: false + default: "gpt-5.3-codex" additional-instructions: description: "Repo-specific instructions appended to the agent prompt" type: string @@ -36,31 +43,6 @@ on: type: string required: false default: "" - edit-typos: - description: "How aggressively to flag typos and misspellings. 'high' = suggest broad consistency fixes, 'low' = flag only clear spelling errors, 'none' = skip typo checks" - type: string - required: false - default: "low" - edit-grammar: - description: "How aggressively to flag grammar and sentence construction problems. 'high' = improve awkward sentence structure, 'low' = flag only clear grammatical errors, 'none' = skip grammar checks" - type: string - required: false - default: "low" - edit-clarity: - description: "How aggressively to flag unclear user-facing text, especially error/help messages. 'high' = proactively suggest clearer phrasing, 'low' = flag only clearly ambiguous text, 'none' = skip clarity checks" - type: string - required: false - default: "low" - edit-terminology: - description: "How aggressively to flag inconsistent terminology for the same concept. 'high' = proactively normalize wording, 'low' = flag only unambiguous inconsistencies, 'none' = skip terminology checks" - type: string - required: false - default: "low" - edit-misleading-text: - description: "How aggressively to flag text that conflicts with current behavior. 'high' = proactively flag likely drift, 'low' = flag only direct contradictions, 'none' = skip behavior-alignment checks" - type: string - required: false - default: "low" secrets: COPILOT_GITHUB_TOKEN: required: true @@ -76,7 +58,7 @@ permissions: pull-requests: read tools: github: - toolsets: [repos, issues, pull_requests, search, labels] + toolsets: [repos, issues, pull_requests, search] bash: true web-fetch: network: @@ -90,11 +72,6 @@ network: strict: false safe-outputs: noop: - create-issue: - max: 1 - title-prefix: "[text-beautifier] " - close-older-issues: true - expires: 7d timeout-minutes: 90 steps: - name: Repo-specific setup @@ -104,116 +81,24 @@ steps: run: eval "$SETUP_COMMANDS" --- -Find typos, unclear error messages, and awkward user-facing text that are low-effort to fix, and file a single improvement issue. - -**The bar is high: only report concrete, unambiguous text problems.** Most runs should end with `noop` — that means user-facing text is clean. - -## Edit Level Configuration - -The following edit levels are configured for this run. Each dimension is independent. - -| Dimension | Level | Meaning | -| --- | --- | --- | -| **typos** | `${{ inputs.edit-typos }}` | How aggressively to flag typos and misspellings | -| **grammar** | `${{ inputs.edit-grammar }}` | How aggressively to flag grammar and sentence construction issues | -| **clarity** | `${{ inputs.edit-clarity }}` | How aggressively to flag unclear user-facing text | -| **terminology** | `${{ inputs.edit-terminology }}` | How aggressively to flag inconsistent naming for the same concept | -| **misleading-text** | `${{ inputs.edit-misleading-text }}` | How aggressively to flag text that no longer matches behavior | - -Level semantics: -- **`high`** — apply best judgment proactively within this dimension -- **`low`** — report only concrete, unambiguous issues -- **`none`** — skip this dimension entirely - -### Data Gathering - -1. Call `generate_agents_md` to get repository conventions. If it fails, continue. -2. Identify user-facing text sources — scan the repository for: - - CLI output strings, error messages, and help text - - Log messages shown to users (not debug-level internal logs) - - README, CONTRIBUTING, DEVELOPING, and other markdown documentation - - UI strings, notification templates, and user-visible configuration descriptions - - Code comments in public APIs that appear in generated documentation -3. Read the identified files and search for text issues. - -### What to Look For by Dimension - -Use each dimension's configured level to determine whether to report findings. - -#### Typos (`${{ inputs.edit-typos }}`) - -- **`high`**: Flag typos/misspellings proactively and include nearby consistency fixes when they are obviously beneficial. -- **`low`**: Flag only clear spelling errors (for example, `recieve` → `receive`), not style variants. -- **`none`**: Skip typo checks. - -#### Grammar (`${{ inputs.edit-grammar }}`) - -- **`high`**: Flag grammar and sentence construction issues that reduce readability, including awkward or fragmented sentences. -- **`low`**: Flag only clear grammatical errors (subject-verb disagreement, missing articles, broken sentence structure). -- **`none`**: Skip grammar checks. - -#### Clarity (`${{ inputs.edit-clarity }}`) - -- **`high`**: Proactively flag unclear user-facing text and suggest concrete rewrites, especially for errors/help text. -- **`low`**: Flag only clearly ambiguous or incomplete user-facing text (for example, `"Error: failed"` with no actionable context). -- **`none`**: Skip clarity checks. - -#### Terminology (`${{ inputs.edit-terminology }}`) - -- **`high`**: Proactively flag inconsistent naming for the same concept across user-facing surfaces. -- **`low`**: Flag only unambiguous inconsistencies where the same concept is clearly referred to by different terms. -- **`none`**: Skip terminology checks. - -#### Misleading Text (`${{ inputs.edit-misleading-text }}`) - -- **`high`**: Proactively flag text likely to have drifted from behavior. -- **`low`**: Flag only direct, verifiable contradictions between text and current code behavior. -- **`none`**: Skip behavior-alignment checks. - -### What to Skip - -- **Style preferences** — do not flag Oxford comma usage, line length, or prose style unless it causes ambiguity -- **Internal-only text** — debug logs, developer-only comments, test fixtures -- **Intentional abbreviations** — short forms that are standard in the project -- **Generated or vendored files** — do not scan auto-generated code, lock files, or third-party content -- **Issues already tracked** — check open issues before filing -- **Findings that require design decisions** — if fixing the text requires deciding on new terminology or restructuring content, skip it - -### Quality Gate — When to Noop - -Call `noop` if any of these are true: -- All edit dimensions are set to `none` -- No concrete text problems were found -- All findings are style preferences rather than clear errors -- The problems found are in generated or vendored files -- A similar issue is already open -- The fixes would require design decisions or significant rewording beyond simple corrections - -### Issue Format +### Candidate Search -**Issue title:** Brief summary of text improvements found +Search for open Text Auditor issues: -**Issue body:** +````text +github-search_issues: query="repo:{owner}/{repo} is:issue is:open (label:text-auditor OR in:title \"[text-auditor]\") sort:updated-asc" +```` -> ## Text Improvements -> -> The following user-facing text issues were found in the repository. Each is a low-effort fix. -> -> ### 1. [Brief description] -> -> **File:** `path/to/file` (line N) -> **Current text:** `the existing text with the problem` -> **Suggested fix:** `the corrected text` -> **Why:** [Brief explanation — typo, grammar, unclear error, etc.] -> -> ### 2. [Next finding...] -> -> ## Suggested Actions -> -> - [ ] [Specific, actionable checkbox for each fix] +### Implementation -### Labeling +1. Read each file mentioned in the issue. +2. Apply the suggested text corrections. For each fix: + - Verify the current text matches what the issue describes + - Apply the suggested replacement + - If the current text has changed since the issue was filed, skip that fix +3. Run any available linters or formatters to verify the changes don't break anything. +4. Commit the changes locally. -- If the `text-beautifier` label exists (check with `github-get_label`), include it in the `create_issue` call; otherwise, rely on the `[text-beautifier]` title prefix only. +Only text changes — no logic, no refactoring, no new features. ${{ inputs.additional-instructions }} diff --git a/.github/workflows/gh-aw-update-pr-body.lock.yml b/.github/workflows/gh-aw-update-pr-body.lock.yml index 38ca584f..fb61aa4a 100644 --- a/.github/workflows/gh-aw-update-pr-body.lock.yml +++ b/.github/workflows/gh-aw-update-pr-body.lock.yml @@ -28,12 +28,13 @@ # - gh-aw-fragments/elastic-tools.md # - gh-aw-fragments/formatting.md # - gh-aw-fragments/mcp-pagination.md -# - gh-aw-fragments/messages-footer.md # - gh-aw-fragments/rigor.md # - gh-aw-fragments/runtime-setup.md # - gh-aw-fragments/safe-output-update-pr.md # -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"ee26c6c71c3207562bd3ea1f1c2c6635ca4ad6d9e79fa7a258601245d7ce0092"} +# inlined-imports: true +# +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"0cd6c25ae12724564b43601b3b0ec1cbb275b6455e3699664ed22557178ae108"} name: "Update PR Body" "on": @@ -75,9 +76,9 @@ name: "Update PR Body" description: How aggressively to improve writing style and clarity. 'high' = rewrite for clarity, conciseness, and professionalism, 'low' = fix only confusing or misleading phrasing, 'none' = do not touch style required: false type: string - messages-footer: - default: "" - description: Footer appended to all agent comments and reviews + model: + default: gpt-5.3-codex + description: AI model to use required: false type: string setup-commands: @@ -109,7 +110,7 @@ jobs: comment_repo: "" steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Validate context variables @@ -193,6 +194,25 @@ jobs: **Critical**: Tool calls write structured data that downstream jobs process. Without tool calls, follow-up actions will be skipped. **Note**: If you made no other safe output tool calls during this workflow execution, call the "noop" tool to provide a status message indicating completion or that no actions were needed. + + --- + + ## Updating a Pull Request, Reporting Missing Tools or Functionality, Reporting Missing Data + + **IMPORTANT**: To perform the actions listed above, use the **safeoutputs** tools. Do NOT use `gh`, do NOT call the GitHub API directly. You do not have write access to the GitHub repository. + + **Updating a Pull Request** + + To update a pull request title or body, use the update_pull_request tool from safeoutputs. + + **Reporting Missing Tools or Functionality** + + To report a missing tool or capability, use the missing_tool tool from safeoutputs. + + **Reporting Missing Data** + + To report missing data required to achieve a goal, use the missing_data tool from safeoutputs. + @@ -293,11 +313,6 @@ jobs: - **Use filters**: Combine `perPage` with state, label, or date filters to reduce result size - **Process as you go**: Don't accumulate all pages before acting — process each batch immediately - GH_AW_PROMPT_EOF - cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - ## Message Footer - - A footer is automatically appended to all comments and reviews. Do not add your own footer or sign-off — the runtime handles this. GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" ## update-pull-request Limitations @@ -396,6 +411,13 @@ jobs: - An update would erase useful context (motivation, design decisions, issue links) the author provided - The body is a reasonable high-level summary even if some details differ + **Never willingly add any of the following to the PR body** (even in `high` mode): + - Commit counts, file counts, or insertion/deletion statistics (e.g., "2 commits, 143 files changed, 12,613 insertions") + - Scope or size summaries — the reviewer can see these in the GitHub UI + - Lists of every file changed — link to relevant code instead + - Boilerplate sections with no substantive content (e.g., empty "Testing" or "Screenshots" headers) + - Agent attribution or footers — the runtime handles this + ### Step 5: Update or Noop **If any changes are warranted:** @@ -530,7 +552,7 @@ jobs: secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Checkout repository @@ -624,7 +646,7 @@ jobs: const awInfo = { engine_id: "copilot", engine_name: "GitHub Copilot CLI", - model: "gpt-5.3-codex", + model: "${{ inputs.model }}", version: "", agent_version: "0.0.412", workflow_name: "Update PR Body", @@ -697,6 +719,10 @@ jobs: "description": "Pull request body content in Markdown. For 'replace', this becomes the entire body. For 'append'/'prepend', this is added with a separator.", "type": "string" }, + "draft": { + "description": "Whether the PR should be a draft (true) or ready for review (false). Use to convert between draft and ready states.", + "type": "boolean" + }, "operation": { "description": "How to update the PR body: 'replace' (default - completely overwrite), 'append' (add to end with separator), or 'prepend' (add to start with separator). Title is always replaced.", "enum": [ @@ -795,6 +821,31 @@ jobs: GH_AW_SAFE_OUTPUTS_TOOLS_EOF cat > /opt/gh-aw/safeoutputs/validation.json << 'GH_AW_SAFE_OUTPUTS_VALIDATION_EOF' { + "missing_data": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "context": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "data_type": { + "type": "string", + "sanitize": true, + "maxLength": 128 + }, + "reason": { + "type": "string", + "sanitize": true, + "maxLength": 256 + } + } + }, "missing_tool": { "defaultMax": 20, "fields": { @@ -835,6 +886,9 @@ jobs: "sanitize": true, "maxLength": 65000 }, + "draft": { + "type": "boolean" + }, "operation": { "type": "string", "enum": [ @@ -846,6 +900,10 @@ jobs: "pull_request_number": { "issueOrPRNumber": true }, + "repo": { + "type": "string", + "maxLength": 256 + }, "title": { "type": "string", "sanitize": true, @@ -983,10 +1041,11 @@ jobs: run: | set -o pipefail sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --allow-domains '*.githubusercontent.com,*.jsr.io,*.pythonhosted.org,*.rvm.io,agents-md-generator.fastmcp.app,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.rubygems.org,api.snapcraft.io,archive.ubuntu.com,artifacts.elastic.co,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,bun.sh,bundler.rubygems.org,cache.ruby-lang.org,cdn.jsdelivr.net,cloud.elastic.co,codeload.github.com,conda.anaconda.org,conda.binstar.org,crates.io,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,deb.nodesource.com,deno.land,ela.st,elastic.co,esm.sh,files.pythonhosted.org,gems.rubyforge.org,gems.rubyonrails.org,get.pnpm.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,host.docker.internal,index.crates.io,index.rubygems.org,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,lfs.github.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,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,pip.pypa.io,pkg.go.dev,ppa.launchpad.net,proxy.golang.org,public-code-search.fastmcp.app,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.bower.io,registry.npmjs.com,registry.npmjs.org,registry.yarnpkg.com,repo.anaconda.com,repo.continuum.io,repo.yarnpkg.com,rubygems.org,rubygems.pkg.github.com,s.symcb.com,s.symcd.com,security.ubuntu.com,skimdb.npmjs.com,static.crates.io,storage.googleapis.com,sum.golang.org,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.elastic.co,www.npmjs.com,www.npmjs.org,yarnpkg.com' --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.20.2 --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 --model gpt-5.3-codex --allow-all-tools --allow-all-paths --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log + -- /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 --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} @@ -1152,7 +1211,7 @@ jobs: total_count: ${{ steps.missing_tool.outputs.total_count }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent output artifact @@ -1204,7 +1263,7 @@ jobs: GH_AW_WORKFLOW_ID: "gh-aw-update-pr-body" GH_AW_SECRET_VERIFICATION_RESULT: ${{ needs.agent.outputs.secret_verification_result }} GH_AW_CHECKOUT_PR_SUCCESS: ${{ needs.agent.outputs.checkout_pr_success }} - GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\"}" + GH_AW_SAFE_OUTPUT_MESSAGES: "{}" GH_AW_GROUP_REPORTS: "false" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} @@ -1243,7 +1302,7 @@ jobs: success: ${{ steps.parse_results.outputs.success }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent artifacts @@ -1304,10 +1363,11 @@ jobs: mkdir -p /tmp/gh-aw/ mkdir -p /tmp/gh-aw/agent/ mkdir -p /tmp/gh-aw/sandbox/agent/logs/ - copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --model gpt-5.3-codex --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log + copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ inputs.model }} GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_REF_NAME: ${{ github.ref_name }} @@ -1337,7 +1397,7 @@ jobs: activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Check team membership for workflow @@ -1366,8 +1426,8 @@ jobs: timeout-minutes: 15 env: GH_AW_ENGINE_ID: "copilot" - GH_AW_ENGINE_MODEL: "gpt-5.3-codex" - GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || '---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.' }}\"}" + GH_AW_ENGINE_MODEL: "${{ inputs.model }}" + GH_AW_SAFE_OUTPUT_MESSAGES: "{}" GH_AW_WORKFLOW_ID: "gh-aw-update-pr-body" GH_AW_WORKFLOW_NAME: "Update PR Body" outputs: @@ -1377,7 +1437,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@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent output artifact diff --git a/.github/workflows/gh-aw-update-pr-body.md b/.github/workflows/gh-aw-update-pr-body.md index 31bfd612..1bd374b6 100644 --- a/.github/workflows/gh-aw-update-pr-body.md +++ b/.github/workflows/gh-aw-update-pr-body.md @@ -1,4 +1,5 @@ --- +inlined-imports: true name: "Update PR Body" description: "Keep pull request bodies in sync with the code changes on every commit" imports: @@ -7,16 +8,20 @@ imports: - gh-aw-fragments/formatting.md - gh-aw-fragments/rigor.md - gh-aw-fragments/mcp-pagination.md - - gh-aw-fragments/messages-footer.md - gh-aw-fragments/safe-output-update-pr.md engine: id: copilot - model: gpt-5.3-codex + model: ${{ inputs.model }} concurrency: group: "gh-aw-copilot-update-pr-body-${{ github.event.pull_request.number }}" on: workflow_call: inputs: + model: + description: "AI model to use" + type: string + required: false + default: "gpt-5.3-codex" additional-instructions: description: "Repo-specific instructions appended to the agent prompt" type: string @@ -32,11 +37,6 @@ on: type: string required: false default: "github-actions[bot]" - messages-footer: - description: "Footer appended to all agent comments and reviews" - type: string - required: false - default: "" edit-accuracy: description: "How aggressively to fix factual inaccuracies in the PR body. 'high' = fix everything that could mislead, 'low' = fix only clear-cut inaccuracies, 'none' = do not change accuracy-related content" type: string @@ -84,6 +84,9 @@ network: - python - ruby strict: false +safe-outputs: + messages: + footer: "" timeout-minutes: 30 steps: - name: Repo-specific setup @@ -179,6 +182,13 @@ Do **not** propose changes when: - An update would erase useful context (motivation, design decisions, issue links) the author provided - The body is a reasonable high-level summary even if some details differ +**Never willingly add any of the following to the PR body** (even in `high` mode): +- Commit counts, file counts, or insertion/deletion statistics (e.g., "2 commits, 143 files changed, 12,613 insertions") +- Scope or size summaries — the reviewer can see these in the GitHub UI +- Lists of every file changed — link to relevant code instead +- Boilerplate sections with no substantive content (e.g., empty "Testing" or "Screenshots" headers) +- Agent attribution or footers — the runtime handles this + ### Step 5: Update or Noop **If any changes are warranted:** diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5b99c3f8..fd7c34ed 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -34,15 +34,15 @@ jobs: run: | # Get the tag name (e.g., v1.2.3) TAG="${GITHUB_REF#refs/tags/}" - echo "tag=$TAG" >> $GITHUB_OUTPUT + echo "tag=$TAG" >> "$GITHUB_OUTPUT" # Extract major version (e.g., v1) MAJOR=$(echo "$TAG" | grep -oE '^v[0-9]+') - echo "major=$MAJOR" >> $GITHUB_OUTPUT + echo "major=$MAJOR" >> "$GITHUB_OUTPUT" # Get the full commit SHA SHA="${GITHUB_SHA}" - echo "sha=$SHA" >> $GITHUB_OUTPUT + echo "sha=$SHA" >> "$GITHUB_OUTPUT" echo "Creating release for $TAG (major: $MAJOR, sha: $SHA)" diff --git a/.github/workflows/smoke-test-install.yml b/.github/workflows/smoke-test-install.yml index f6eee1e6..ef9481da 100644 --- a/.github/workflows/smoke-test-install.yml +++ b/.github/workflows/smoke-test-install.yml @@ -9,6 +9,8 @@ jobs: smoke-test: name: Install and compile all workflows runs-on: ubuntu-latest + env: + GH_AW_VERSION: "v0.48.1" steps: - name: Set up Go uses: actions/setup-go@v5 @@ -16,12 +18,13 @@ jobs: go-version: "1.25" cache: false - - name: Install gh-aw extension + - name: Install pinned gh-aw CLI env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | - gh extension install github/gh-aw - gh aw version + GOBIN="$HOME/.local/bin" go install "github.com/github/gh-aw/cmd/gh-aw@${GH_AW_VERSION}" + echo "$HOME/.local/bin" >> "$GITHUB_PATH" + "$HOME/.local/bin/gh-aw" version - name: Create a fresh repo run: | @@ -39,25 +42,49 @@ jobs: set -euo pipefail WORKFLOWS=( - pr-review + agent-efficiency + agent-suggestions + breaking-change-detector + bug-exterminator + bug-hunter + code-duplication-detector + code-duplication-fixer + code-simplifier + docs-patrol + docs-patrol-external + docs-pr-review + downstream-health + duplicate-issue-detector + flaky-test-investigator + issue-fixer issue-triage mention-in-issue mention-in-pr - docs-drift - docs-drift-external - docs-new-contributor-review - docs-pr-review - docs-new-contributor-review-external - downstream-health + newbie-contributor-fixer + newbie-contributor-patrol + newbie-contributor-patrol-external + performance-profiler + pr-actions-detective + pr-actions-fixer + pr-buildkite-detective + pr-review + project-summary + release-update + scheduled-audit + scheduled-fix + small-problem-fixer stale-issues - agent-efficiency + test-improver + text-auditor + text-beautifier + update-pr-body ) FAILED=0 for wf in "${WORKFLOWS[@]}"; do echo "::group::Installing ${wf}" - if gh aw add "elastic/ai-github-actions/gh-agent-workflows/${wf}.md" --non-interactive; then + if gh-aw add "elastic/ai-github-actions/.github/workflows/gh-aw-${wf}.md" --non-interactive; then echo "::endgroup::" else echo "::endgroup::" diff --git a/.github/workflows/trigger-breaking-change-detect.yml b/.github/workflows/trigger-breaking-change-detector.yml similarity index 67% rename from .github/workflows/trigger-breaking-change-detect.yml rename to .github/workflows/trigger-breaking-change-detector.yml index 1af8b72a..0b6c2293 100644 --- a/.github/workflows/trigger-breaking-change-detect.yml +++ b/.github/workflows/trigger-breaking-change-detector.yml @@ -1,4 +1,4 @@ -name: Trigger Breaking Change Detect +name: Trigger Breaking Change Detector on: schedule: - cron: "0 13 * * 1-5" @@ -11,6 +11,6 @@ permissions: jobs: run: - uses: ./.github/workflows/gh-aw-breaking-change-detect.lock.yml + uses: ./.github/workflows/gh-aw-breaking-change-detector.lock.yml secrets: COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} diff --git a/.github/workflows/trigger-semantic-function-clustering.yml b/.github/workflows/trigger-code-duplication-detector.yml similarity index 70% rename from .github/workflows/trigger-semantic-function-clustering.yml rename to .github/workflows/trigger-code-duplication-detector.yml index 9f7aedbb..1b46695a 100644 --- a/.github/workflows/trigger-semantic-function-clustering.yml +++ b/.github/workflows/trigger-code-duplication-detector.yml @@ -1,4 +1,4 @@ -name: Trigger Semantic Function Clustering +name: Trigger Code Duplication Detector on: schedule: - cron: "0 12 * * 1-5" @@ -11,7 +11,7 @@ permissions: jobs: run: - uses: ./.github/workflows/gh-aw-semantic-function-clustering.lock.yml + uses: ./.github/workflows/gh-aw-code-duplication-detector.lock.yml with: languages: "go,python,typescript" secrets: diff --git a/.github/workflows/trigger-performance-profiler.yml b/.github/workflows/trigger-code-duplication-fixer.yml similarity index 56% rename from .github/workflows/trigger-performance-profiler.yml rename to .github/workflows/trigger-code-duplication-fixer.yml index 6a3bf683..543365bd 100644 --- a/.github/workflows/trigger-performance-profiler.yml +++ b/.github/workflows/trigger-code-duplication-fixer.yml @@ -1,4 +1,4 @@ -name: Trigger Performance Profiler +name: Trigger Code Duplication Fixer on: schedule: - cron: "0 14 * * 1-5" @@ -6,11 +6,11 @@ on: permissions: contents: read - issues: write - pull-requests: read + issues: read + pull-requests: write jobs: run: - uses: ./.github/workflows/gh-aw-performance-profiler.lock.yml + uses: ./.github/workflows/gh-aw-code-duplication-fixer.lock.yml secrets: COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} diff --git a/.github/workflows/trigger-docs-new-contributor-review-external.yml b/.github/workflows/trigger-docs-new-contributor-review-external.yml deleted file mode 100644 index 0cd051f5..00000000 --- a/.github/workflows/trigger-docs-new-contributor-review-external.yml +++ /dev/null @@ -1,16 +0,0 @@ -name: Trigger Docs New Contributor Review External -on: - schedule: - - cron: "0 14 * * 1" - workflow_dispatch: - -permissions: - contents: read - issues: write - pull-requests: read - -jobs: - run: - uses: ./.github/workflows/gh-aw-docs-new-contributor-review-external.lock.yml - secrets: - COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} diff --git a/.github/workflows/trigger-docs-drift.yml b/.github/workflows/trigger-docs-patrol.yml similarity index 72% rename from .github/workflows/trigger-docs-drift.yml rename to .github/workflows/trigger-docs-patrol.yml index 84aa7b23..d6bac064 100644 --- a/.github/workflows/trigger-docs-drift.yml +++ b/.github/workflows/trigger-docs-patrol.yml @@ -1,4 +1,4 @@ -name: Trigger Docs Drift +name: Trigger Docs Patrol on: schedule: - cron: "0 14 * * 1-5" @@ -11,6 +11,6 @@ permissions: jobs: run: - uses: ./.github/workflows/gh-aw-docs-drift.lock.yml + uses: ./.github/workflows/gh-aw-docs-patrol.lock.yml secrets: COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} diff --git a/.github/workflows/trigger-downstream-users.yml b/.github/workflows/trigger-downstream-users.yml deleted file mode 100644 index 9fe114f7..00000000 --- a/.github/workflows/trigger-downstream-users.yml +++ /dev/null @@ -1,16 +0,0 @@ -name: Trigger Downstream Users -on: - schedule: - - cron: "0 9 * * 1-5" - workflow_dispatch: - -permissions: - contents: write - issues: read - pull-requests: write - -jobs: - run: - uses: ./.github/workflows/gh-aw-downstream-users.lock.yml - secrets: - COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} diff --git a/.github/workflows/trigger-newbie-contributor-fixer.yml b/.github/workflows/trigger-newbie-contributor-fixer.yml new file mode 100644 index 00000000..862698a7 --- /dev/null +++ b/.github/workflows/trigger-newbie-contributor-fixer.yml @@ -0,0 +1,16 @@ +name: Trigger Newbie Contributor Fixer +on: + schedule: + - cron: "0 14 * * 1-5" + workflow_dispatch: + +permissions: + contents: write + issues: write + pull-requests: write + +jobs: + run: + uses: ./.github/workflows/gh-aw-newbie-contributor-fixer.lock.yml + secrets: + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} diff --git a/.github/workflows/trigger-docs-drift-external.yml b/.github/workflows/trigger-newbie-contributor-patrol.yml similarity index 59% rename from .github/workflows/trigger-docs-drift-external.yml rename to .github/workflows/trigger-newbie-contributor-patrol.yml index df717e1d..7f74a476 100644 --- a/.github/workflows/trigger-docs-drift-external.yml +++ b/.github/workflows/trigger-newbie-contributor-patrol.yml @@ -1,7 +1,7 @@ -name: Trigger Docs Drift External +name: Trigger Newbie Contributor Patrol on: schedule: - - cron: "0 14 * * 1-5" + - cron: "0 11 * * 1" workflow_dispatch: permissions: @@ -11,6 +11,6 @@ permissions: jobs: run: - uses: ./.github/workflows/gh-aw-docs-drift-external.lock.yml + uses: ./.github/workflows/gh-aw-newbie-contributor-patrol.lock.yml secrets: COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} diff --git a/.github/workflows/trigger-pr-ci-detective.yml b/.github/workflows/trigger-pr-actions-detective.yml similarity index 79% rename from .github/workflows/trigger-pr-ci-detective.yml rename to .github/workflows/trigger-pr-actions-detective.yml index 9a2bf194..fddc2f10 100644 --- a/.github/workflows/trigger-pr-ci-detective.yml +++ b/.github/workflows/trigger-pr-actions-detective.yml @@ -1,4 +1,4 @@ -name: Trigger PR CI Detective +name: Trigger PR Actions Detective on: workflow_run: workflows: ["CI", "Build", "Test"] @@ -15,6 +15,6 @@ jobs: if: >- github.event.workflow_run.conclusion == 'failure' && toJSON(github.event.workflow_run.pull_requests) != '[]' - uses: ./.github/workflows/gh-aw-pr-ci-detective.lock.yml + uses: ./.github/workflows/gh-aw-pr-actions-detective.lock.yml secrets: COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} diff --git a/.github/workflows/trigger-pr-ci-fixer.yml b/.github/workflows/trigger-pr-actions-fixer.yml similarity index 76% rename from .github/workflows/trigger-pr-ci-fixer.yml rename to .github/workflows/trigger-pr-actions-fixer.yml index 760aa71b..60389d3b 100644 --- a/.github/workflows/trigger-pr-ci-fixer.yml +++ b/.github/workflows/trigger-pr-actions-fixer.yml @@ -1,4 +1,4 @@ -name: Trigger PR CI Fixer +name: Trigger PR Actions Fixer on: workflow_dispatch: inputs: @@ -11,11 +11,11 @@ permissions: actions: read contents: write issues: write - pull-requests: read + pull-requests: write jobs: run: - uses: ./.github/workflows/gh-aw-pr-ci-fixer.lock.yml + uses: ./.github/workflows/gh-aw-pr-actions-fixer.lock.yml with: workflow-run-id: ${{ inputs.workflow-run-id }} secrets: diff --git a/.github/workflows/trigger-test-improvement.yml b/.github/workflows/trigger-test-improver.yml similarity index 70% rename from .github/workflows/trigger-test-improvement.yml rename to .github/workflows/trigger-test-improver.yml index d15c803c..7ad4262c 100644 --- a/.github/workflows/trigger-test-improvement.yml +++ b/.github/workflows/trigger-test-improver.yml @@ -1,4 +1,4 @@ -name: Trigger Test Improvement +name: Trigger Test Improver on: schedule: - cron: "0 9 * * 1" @@ -11,6 +11,6 @@ permissions: jobs: run: - uses: ./.github/workflows/gh-aw-test-improvement.lock.yml + uses: ./.github/workflows/gh-aw-test-improver.lock.yml secrets: COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} diff --git a/.github/workflows/trigger-text-auditor.yml b/.github/workflows/trigger-text-auditor.yml new file mode 100644 index 00000000..05bb39eb --- /dev/null +++ b/.github/workflows/trigger-text-auditor.yml @@ -0,0 +1,22 @@ +name: Trigger Text Auditor +on: + schedule: + - cron: "0 13 * * 1-5" + workflow_dispatch: + +permissions: + contents: read + issues: write + pull-requests: read + +jobs: + run: + uses: ./.github/workflows/gh-aw-text-auditor.lock.yml + with: + edit-typos: high + edit-grammar: high + edit-clarity: high + edit-terminology: high + edit-misleading-text: high + secrets: + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} diff --git a/.github/workflows/trigger-text-beautifier.yml b/.github/workflows/trigger-text-beautifier.yml index 5310bcb3..90a5fec0 100644 --- a/.github/workflows/trigger-text-beautifier.yml +++ b/.github/workflows/trigger-text-beautifier.yml @@ -1,22 +1,16 @@ name: Trigger Text Beautifier on: schedule: - - cron: "0 13 * * 1-5" + - cron: "0 14 * * 1-5" workflow_dispatch: permissions: contents: read - issues: write - pull-requests: read + issues: read + pull-requests: write jobs: run: uses: ./.github/workflows/gh-aw-text-beautifier.lock.yml - with: - edit-typos: high - edit-grammar: high - edit-clarity: high - edit-terminology: high - edit-misleading-text: high secrets: COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} diff --git a/.github/workflows/gh-aw-upgrade-check.lock.yml b/.github/workflows/upgrade-check.lock.yml similarity index 95% rename from .github/workflows/gh-aw-upgrade-check.lock.yml rename to .github/workflows/upgrade-check.lock.yml index 1b3fe227..7a5d2491 100644 --- a/.github/workflows/gh-aw-upgrade-check.lock.yml +++ b/.github/workflows/upgrade-check.lock.yml @@ -31,9 +31,11 @@ # - gh-aw-fragments/rigor.md # - gh-aw-fragments/runtime-setup.md # - gh-aw-fragments/safe-output-create-issue.md -# - gh-aw-fragments/scheduled-report.md +# - gh-aw-fragments/scheduled-audit.md # -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"1e269a49ecfc3701a0a79d6ffa2f339591c3121f55bfcbef222b4312e3153608"} +# inlined-imports: true +# +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"d85bf62cf7a9ed448e8c9f549210273fe939479eef73873eed65cdcc9a669735"} name: "Upgrade Check" "on": @@ -44,7 +46,7 @@ name: "Upgrade Check" # - maintainer # Roles processed as role check in pre-activation job # - write # Roles processed as role check in pre-activation job schedule: - - cron: "17 14 * * 1-5" + - cron: "48 13 * * 1-5" # Friendly format: daily around 14:00 on weekdays (scattered) workflow_dispatch: @@ -52,7 +54,7 @@ permissions: {} concurrency: cancel-in-progress: true - group: gh-aw-upgrade-check + group: upgrade-check run-name: "Upgrade Check" @@ -66,7 +68,7 @@ jobs: comment_repo: "" steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Validate context variables @@ -88,7 +90,7 @@ jobs: - name: Check workflow file timestamps uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: - GH_AW_WORKFLOW_FILE: "gh-aw-upgrade-check.lock.yml" + GH_AW_WORKFLOW_FILE: "upgrade-check.lock.yml" with: script: | const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); @@ -142,6 +144,25 @@ jobs: **Critical**: Tool calls write structured data that downstream jobs process. Without tool calls, follow-up actions will be skipped. **Note**: If you made no other safe output tool calls during this workflow execution, call the "noop" tool to provide a status message indicating completion or that no actions were needed. + + --- + + ## Creating an Issue, Reporting Missing Tools or Functionality, Reporting Missing Data + + **IMPORTANT**: To perform the actions listed above, use the **safeoutputs** tools. Do NOT use `gh`, do NOT call the GitHub API directly. You do not have write access to the GitHub repository. + + **Creating an Issue** + + To create an issue, use the create_issue tool from safeoutputs. + + **Reporting Missing Tools or Functionality** + + To report a missing tool or capability, use the missing_tool tool from safeoutputs. + + **Reporting Missing Data** + + To report missing data required to achieve a goal, use the missing_data tool from safeoutputs. + @@ -254,9 +275,7 @@ jobs: - **Mentions**: `@mentions` in the body are neutralized (backticked) by default. GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - # Scheduled Report Agent - - You are a report agent for __GH_AW_GITHUB_REPOSITORY__. You run on a schedule to investigate the repository and file an issue when something needs attention. Your specific assignment is described in the **Report Assignment** section below. + You are an agent for __GH_AW_GITHUB_REPOSITORY__. You run on a schedule to investigate the repository and file an issue when something needs attention. Your specific assignment is described in the **Report Assignment** section below. ## Context @@ -320,7 +339,7 @@ jobs: - Make suggested actions concrete enough to act on without re-investigating - If a finding is ambiguous, it does not pass the quality gate — drop it - ## Report Assignment + **Report Assignment:** GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" @@ -481,7 +500,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: ghawupgradecheck + GH_AW_WORKFLOW_ID_SANITIZED: upgradecheck outputs: checkout_pr_success: ${{ steps.checkout-pr.outputs.checkout_pr_success || 'true' }} has_patch: ${{ steps.collect_output.outputs.has_patch }} @@ -491,7 +510,7 @@ jobs: secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Checkout repository @@ -580,7 +599,7 @@ jobs: const awInfo = { engine_id: "copilot", engine_name: "GitHub Copilot CLI", - model: "claude-opus-4.6", + model: "gpt-5.3-codex", version: "", agent_version: "0.0.412", workflow_name: "Upgrade Check", @@ -791,6 +810,31 @@ jobs: } } }, + "missing_data": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "context": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "data_type": { + "type": "string", + "sanitize": true, + "maxLength": 128 + }, + "reason": { + "type": "string", + "sanitize": true, + "maxLength": 256 + } + } + }, "missing_tool": { "defaultMax": 20, "fields": { @@ -952,10 +996,11 @@ jobs: run: | set -o pipefail sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --allow-domains '*.githubusercontent.com,agents-md-generator.fastmcp.app,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,artifacts.elastic.co,azure.archive.ubuntu.com,cloud.elastic.co,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,ela.st,elastic.co,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,public-code-search.fastmcp.app,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.elastic.co' --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.20.2 --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 --model claude-opus-4.6 --allow-all-tools --allow-all-paths --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log + -- /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 --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: gpt-5.3-codex GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} @@ -1121,7 +1166,7 @@ jobs: total_count: ${{ steps.missing_tool.outputs.total_count }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent output artifact @@ -1170,10 +1215,9 @@ jobs: GH_AW_WORKFLOW_NAME: "Upgrade Check" 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: "gh-aw-upgrade-check" + GH_AW_WORKFLOW_ID: "upgrade-check" GH_AW_SECRET_VERIFICATION_RESULT: ${{ needs.agent.outputs.secret_verification_result }} GH_AW_CHECKOUT_PR_SUCCESS: ${{ needs.agent.outputs.checkout_pr_success }} - GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.\"}" GH_AW_GROUP_REPORTS: "false" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} @@ -1212,7 +1256,7 @@ jobs: success: ${{ steps.parse_results.outputs.success }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent artifacts @@ -1273,10 +1317,11 @@ jobs: mkdir -p /tmp/gh-aw/ mkdir -p /tmp/gh-aw/agent/ mkdir -p /tmp/gh-aw/sandbox/agent/logs/ - copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --model claude-opus-4.6 --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log + copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: gpt-5.3-codex GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_REF_NAME: ${{ github.ref_name }} @@ -1312,9 +1357,8 @@ jobs: timeout-minutes: 15 env: GH_AW_ENGINE_ID: "copilot" - GH_AW_ENGINE_MODEL: "claude-opus-4.6" - GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.\"}" - GH_AW_WORKFLOW_ID: "gh-aw-upgrade-check" + GH_AW_ENGINE_MODEL: "gpt-5.3-codex" + GH_AW_WORKFLOW_ID: "upgrade-check" GH_AW_WORKFLOW_NAME: "Upgrade Check" outputs: create_discussion_error_count: ${{ steps.process_safe_outputs.outputs.create_discussion_error_count }} @@ -1323,7 +1367,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@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent output artifact diff --git a/.github/workflows/gh-aw-upgrade-check.md b/.github/workflows/upgrade-check.md similarity index 93% rename from .github/workflows/gh-aw-upgrade-check.md rename to .github/workflows/upgrade-check.md index c48b7ddb..f5dfffee 100644 --- a/.github/workflows/gh-aw-upgrade-check.md +++ b/.github/workflows/upgrade-check.md @@ -1,4 +1,5 @@ --- +inlined-imports: true name: "Upgrade Check" description: "Check for gh-aw releases and assess whether our workflows need upgrading" imports: @@ -8,10 +9,10 @@ imports: - gh-aw-fragments/rigor.md - gh-aw-fragments/mcp-pagination.md - gh-aw-fragments/safe-output-create-issue.md - - gh-aw-fragments/scheduled-report.md + - gh-aw-fragments/scheduled-audit.md engine: id: copilot - model: claude-opus-4.6 + model: gpt-5.3-codex on: schedule: - cron: "daily around 14:00 on weekdays" @@ -20,7 +21,7 @@ on: bots: - "github-actions[bot]" concurrency: - group: gh-aw-upgrade-check + group: upgrade-check cancel-in-progress: true permissions: contents: read @@ -37,8 +38,6 @@ network: - github strict: false safe-outputs: - messages: - footer: "---\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\n\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not." noop: create-issue: max: 1 diff --git a/.github/workflows/gh-aw-workflow-drift.lock.yml b/.github/workflows/workflow-patrol.lock.yml similarity index 94% rename from .github/workflows/gh-aw-workflow-drift.lock.yml rename to .github/workflows/workflow-patrol.lock.yml index 17d1a307..b38f9251 100644 --- a/.github/workflows/gh-aw-workflow-drift.lock.yml +++ b/.github/workflows/workflow-patrol.lock.yml @@ -31,11 +31,13 @@ # - gh-aw-fragments/rigor.md # - gh-aw-fragments/runtime-setup.md # - gh-aw-fragments/safe-output-create-issue.md -# - gh-aw-fragments/scheduled-report.md +# - gh-aw-fragments/scheduled-audit.md # -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"a5f7daa503d97c2ce3d73b0b516d96b56afe7e1122dcbe141fc6d0d854d346d9"} +# inlined-imports: true +# +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"f9c1b3b00c0a586f3a7c4c72d9cfb13ffc496fc7665b012c2c5699108bb28a86"} -name: "Workflow Drift" +name: "Workflow Patrol" "on": # bots: # Bots processed as bot check in pre-activation job # - github-actions[bot] # Bots processed as bot check in pre-activation job @@ -44,7 +46,7 @@ name: "Workflow Drift" # - maintainer # Roles processed as role check in pre-activation job # - write # Roles processed as role check in pre-activation job schedule: - - cron: "41 13 * * 1-5" + - cron: "45 14 * * 1-5" # Friendly format: daily around 14:00 on weekdays (scattered) workflow_dispatch: @@ -52,9 +54,9 @@ permissions: {} concurrency: cancel-in-progress: true - group: gh-aw-workflow-drift + group: workflow-patrol -run-name: "Workflow Drift" +run-name: "Workflow Patrol" jobs: activation: @@ -66,7 +68,7 @@ jobs: comment_repo: "" steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Validate context variables @@ -88,7 +90,7 @@ jobs: - name: Check workflow file timestamps uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: - GH_AW_WORKFLOW_FILE: "gh-aw-workflow-drift.lock.yml" + GH_AW_WORKFLOW_FILE: "workflow-patrol.lock.yml" with: script: | const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); @@ -142,6 +144,25 @@ jobs: **Critical**: Tool calls write structured data that downstream jobs process. Without tool calls, follow-up actions will be skipped. **Note**: If you made no other safe output tool calls during this workflow execution, call the "noop" tool to provide a status message indicating completion or that no actions were needed. + + --- + + ## Creating an Issue, Reporting Missing Tools or Functionality, Reporting Missing Data + + **IMPORTANT**: To perform the actions listed above, use the **safeoutputs** tools. Do NOT use `gh`, do NOT call the GitHub API directly. You do not have write access to the GitHub repository. + + **Creating an Issue** + + To create an issue, use the create_issue tool from safeoutputs. + + **Reporting Missing Tools or Functionality** + + To report a missing tool or capability, use the missing_tool tool from safeoutputs. + + **Reporting Missing Data** + + To report missing data required to achieve a goal, use the missing_data tool from safeoutputs. + @@ -254,9 +275,7 @@ jobs: - **Mentions**: `@mentions` in the body are neutralized (backticked) by default. GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" - # Scheduled Report Agent - - You are a report agent for __GH_AW_GITHUB_REPOSITORY__. You run on a schedule to investigate the repository and file an issue when something needs attention. Your specific assignment is described in the **Report Assignment** section below. + You are an agent for __GH_AW_GITHUB_REPOSITORY__. You run on a schedule to investigate the repository and file an issue when something needs attention. Your specific assignment is described in the **Report Assignment** section below. ## Context @@ -320,7 +339,7 @@ jobs: - Make suggested actions concrete enough to act on without re-investigating - If a finding is ambiguous, it does not pass the quality gate — drop it - ## Report Assignment + **Report Assignment:** GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" @@ -336,7 +355,7 @@ jobs: - **Consumer example**: `gh-agent-workflows//example.yml` (external caller template) - **README**: `gh-agent-workflows//README.md` - Internal-only workflows (`upgrade-check`, `downstream-users`, `workflow-drift`, `downstream-health`) intentionally skip the trigger/example/README files and use `schedule`/`workflow_dispatch` instead of `workflow_call`. Exclude them from comparisons against public workflows. + Internal-only workflows (`upgrade-check`, `downstream-users`, `workflow-patrol`) intentionally skip the trigger/example/README files and use `schedule`/`workflow_dispatch` instead of `workflow_call`. Exclude them from comparisons against public workflows. Shared fragments live in `.github/workflows/gh-aw-fragments/`. @@ -347,7 +366,7 @@ jobs: 1. Read all `.github/workflows/gh-aw-*.md` files (the workflow sources — not the lock files). 2. Read all `.github/workflows/gh-aw-fragments/*.md` files (the shared fragments). 3. Read all `.github/workflows/trigger-*.yml` files and all `gh-agent-workflows/*/example.yml` files. - 4. Check for open issues with the `[workflow-drift]` title prefix to avoid duplicating already-tracked findings. + 4. Check for open issues with the `[workflow-patrol]` title prefix to avoid duplicating already-tracked findings. #### Step 2: Discover majority patterns @@ -366,7 +385,7 @@ jobs: - The pattern is followed by **>= 75%** of comparable workflows (compare `workflow_call` workflows against each other, scheduled workflows against each other) - The deviation is not obviously intentional (e.g., a workflow that genuinely doesn't need a particular input or fragment) - - The finding is not already tracked in an open `[workflow-drift]` issue + - The finding is not already tracked in an open `[workflow-patrol]` issue #### Step 4: Report or noop @@ -469,7 +488,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: ghawworkflowdrift + GH_AW_WORKFLOW_ID_SANITIZED: workflowpatrol outputs: checkout_pr_success: ${{ steps.checkout-pr.outputs.checkout_pr_success || 'true' }} has_patch: ${{ steps.collect_output.outputs.has_patch }} @@ -479,7 +498,7 @@ jobs: secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Checkout repository @@ -568,10 +587,10 @@ jobs: const awInfo = { engine_id: "copilot", engine_name: "GitHub Copilot CLI", - model: "claude-opus-4.6", + model: "gpt-5.3-codex", version: "", agent_version: "0.0.412", - workflow_name: "Workflow Drift", + workflow_name: "Workflow Patrol", experimental: false, supports_tools_allowlist: true, run_id: context.runId, @@ -633,7 +652,7 @@ jobs: 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 \"[workflow-drift] \".", + "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 \"[workflow-patrol] \".", "inputSchema": { "additionalProperties": false, "properties": { @@ -779,6 +798,31 @@ jobs: } } }, + "missing_data": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "context": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "data_type": { + "type": "string", + "sanitize": true, + "maxLength": 128 + }, + "reason": { + "type": "string", + "sanitize": true, + "maxLength": 256 + } + } + }, "missing_tool": { "defaultMax": 20, "fields": { @@ -940,10 +984,11 @@ jobs: run: | set -o pipefail sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --allow-domains '*.githubusercontent.com,agents-md-generator.fastmcp.app,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,artifacts.elastic.co,azure.archive.ubuntu.com,cloud.elastic.co,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,ela.st,elastic.co,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,public-code-search.fastmcp.app,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.elastic.co' --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.20.2 --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 --model claude-opus-4.6 --allow-all-tools --allow-all-paths --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log + -- /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 --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: gpt-5.3-codex GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} @@ -1109,7 +1154,7 @@ jobs: total_count: ${{ steps.missing_tool.outputs.total_count }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent output artifact @@ -1129,7 +1174,7 @@ jobs: env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} GH_AW_NOOP_MAX: 1 - GH_AW_WORKFLOW_NAME: "Workflow Drift" + GH_AW_WORKFLOW_NAME: "Workflow Patrol" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | @@ -1142,7 +1187,7 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_WORKFLOW_NAME: "Workflow Drift" + GH_AW_WORKFLOW_NAME: "Workflow Patrol" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | @@ -1155,13 +1200,12 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_WORKFLOW_NAME: "Workflow Drift" + GH_AW_WORKFLOW_NAME: "Workflow Patrol" 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: "gh-aw-workflow-drift" + GH_AW_WORKFLOW_ID: "workflow-patrol" GH_AW_SECRET_VERIFICATION_RESULT: ${{ needs.agent.outputs.secret_verification_result }} GH_AW_CHECKOUT_PR_SUCCESS: ${{ needs.agent.outputs.checkout_pr_success }} - GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.\"}" GH_AW_GROUP_REPORTS: "false" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} @@ -1175,7 +1219,7 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_WORKFLOW_NAME: "Workflow Drift" + GH_AW_WORKFLOW_NAME: "Workflow Patrol" 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 }} @@ -1200,7 +1244,7 @@ jobs: success: ${{ steps.parse_results.outputs.success }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent artifacts @@ -1223,7 +1267,7 @@ jobs: - name: Setup threat detection uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: - WORKFLOW_NAME: "Workflow Drift" + WORKFLOW_NAME: "Workflow Patrol" WORKFLOW_DESCRIPTION: "Detect workflow drift — where one or more workflows have fallen behind a pattern adopted by most others" HAS_PATCH: ${{ needs.agent.outputs.has_patch }} with: @@ -1261,10 +1305,11 @@ jobs: mkdir -p /tmp/gh-aw/ mkdir -p /tmp/gh-aw/agent/ mkdir -p /tmp/gh-aw/sandbox/agent/logs/ - copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --model claude-opus-4.6 --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log + copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --prompt "$COPILOT_CLI_INSTRUCTION" 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: gpt-5.3-codex GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_REF_NAME: ${{ github.ref_name }} @@ -1300,10 +1345,9 @@ jobs: timeout-minutes: 15 env: GH_AW_ENGINE_ID: "copilot" - GH_AW_ENGINE_MODEL: "claude-opus-4.6" - GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.\"}" - GH_AW_WORKFLOW_ID: "gh-aw-workflow-drift" - GH_AW_WORKFLOW_NAME: "Workflow Drift" + GH_AW_ENGINE_MODEL: "gpt-5.3-codex" + GH_AW_WORKFLOW_ID: "workflow-patrol" + GH_AW_WORKFLOW_NAME: "Workflow Patrol" outputs: create_discussion_error_count: ${{ steps.process_safe_outputs.outputs.create_discussion_error_count }} create_discussion_errors: ${{ steps.process_safe_outputs.outputs.create_discussion_errors }} @@ -1311,7 +1355,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@da463a765059a5eed4cc345a003ecfc71c45ec49 # v0.47.4 + uses: github/gh-aw/actions/setup@26b6572ae210580303087bc3142fe58d140bf65c # v0.48.1 with: destination: /opt/gh-aw/actions - name: Download agent output artifact @@ -1330,7 +1374,7 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_issue\":{\"close_older_issues\":true,\"expires\":168,\"max\":1,\"title_prefix\":\"[workflow-drift] \"},\"missing_data\":{},\"missing_tool\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_issue\":{\"close_older_issues\":true,\"expires\":168,\"max\":1,\"title_prefix\":\"[workflow-patrol] \"},\"missing_data\":{},\"missing_tool\":{}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/gh-aw-workflow-drift.md b/.github/workflows/workflow-patrol.md similarity index 83% rename from .github/workflows/gh-aw-workflow-drift.md rename to .github/workflows/workflow-patrol.md index c80bbbd8..dcbe695a 100644 --- a/.github/workflows/gh-aw-workflow-drift.md +++ b/.github/workflows/workflow-patrol.md @@ -1,5 +1,6 @@ --- -name: "Workflow Drift" +inlined-imports: true +name: "Workflow Patrol" description: "Detect workflow drift — where one or more workflows have fallen behind a pattern adopted by most others" imports: - gh-aw-fragments/elastic-tools.md @@ -8,10 +9,10 @@ imports: - gh-aw-fragments/rigor.md - gh-aw-fragments/mcp-pagination.md - gh-aw-fragments/safe-output-create-issue.md - - gh-aw-fragments/scheduled-report.md + - gh-aw-fragments/scheduled-audit.md engine: id: copilot - model: claude-opus-4.6 + model: gpt-5.3-codex on: schedule: - cron: "daily around 14:00 on weekdays" @@ -20,7 +21,7 @@ on: bots: - "github-actions[bot]" concurrency: - group: gh-aw-workflow-drift + group: workflow-patrol cancel-in-progress: true permissions: contents: read @@ -37,12 +38,10 @@ network: - github strict: false safe-outputs: - messages: - footer: "---\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {workflow_name}]({run_url})\n\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not." noop: create-issue: max: 1 - title-prefix: "[workflow-drift] " + title-prefix: "[workflow-patrol] " close-older-issues: true expires: 7d timeout-minutes: 90 @@ -60,7 +59,7 @@ This is the `elastic/ai-github-actions` repository. It ships reusable GitHub Act - **Consumer example**: `gh-agent-workflows//example.yml` (external caller template) - **README**: `gh-agent-workflows//README.md` -Internal-only workflows (`upgrade-check`, `downstream-users`, `workflow-drift`, `downstream-health`) intentionally skip the trigger/example/README files and use `schedule`/`workflow_dispatch` instead of `workflow_call`. Exclude them from comparisons against public workflows. +Internal-only workflows (`upgrade-check`, `downstream-users`, `workflow-patrol`) intentionally skip the trigger/example/README files and use `schedule`/`workflow_dispatch` instead of `workflow_call`. Exclude them from comparisons against public workflows. Shared fragments live in `.github/workflows/gh-aw-fragments/`. @@ -71,7 +70,7 @@ Shared fragments live in `.github/workflows/gh-aw-fragments/`. 1. Read all `.github/workflows/gh-aw-*.md` files (the workflow sources — not the lock files). 2. Read all `.github/workflows/gh-aw-fragments/*.md` files (the shared fragments). 3. Read all `.github/workflows/trigger-*.yml` files and all `gh-agent-workflows/*/example.yml` files. -4. Check for open issues with the `[workflow-drift]` title prefix to avoid duplicating already-tracked findings. +4. Check for open issues with the `[workflow-patrol]` title prefix to avoid duplicating already-tracked findings. #### Step 2: Discover majority patterns @@ -90,7 +89,7 @@ For each pattern you discovered, find workflows that deviate. A deviation is dri - The pattern is followed by **>= 75%** of comparable workflows (compare `workflow_call` workflows against each other, scheduled workflows against each other) - The deviation is not obviously intentional (e.g., a workflow that genuinely doesn't need a particular input or fragment) -- The finding is not already tracked in an open `[workflow-drift]` issue +- The finding is not already tracked in an open `[workflow-patrol]` issue #### Step 4: Report or noop diff --git a/AGENTS.md b/AGENTS.md index c691e09b..7481d7d2 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -2,6 +2,7 @@ @README.md @DEVELOPING.md +@docs/upgrading.md ## Automation Runtime diff --git a/DEVELOPING.md b/DEVELOPING.md index 9c8139b9..9f1cc2db 100644 --- a/DEVELOPING.md +++ b/DEVELOPING.md @@ -8,7 +8,7 @@ | `gh-agent-workflows/` | Per-workflow READMEs, `example.yml` triggers, and optional `dogfood-with.yml` overrides | [DEVELOPING.md](gh-agent-workflows/DEVELOPING.md) | | `claude-workflows/` | Composite actions wrapping Claude Code | [DEVELOPING.md](claude-workflows/DEVELOPING.md) | -Internal-only workflows (e.g., `gh-aw-upgrade-check.md`, `ci.yml`, `release.yml`) also live in `.github/workflows/`. See [gh-agent-workflows/DEVELOPING.md](gh-agent-workflows/DEVELOPING.md) for the full architecture. +Internal-only workflows (e.g., `upgrade-check.md`, `workflow-patrol.md`, `ci.yml`, `release.yml`) also live in `.github/workflows/`. Published workflows use the `gh-aw-` prefix; internal-only ones omit it. See [gh-agent-workflows/DEVELOPING.md](gh-agent-workflows/DEVELOPING.md) for the full architecture. ## Quick Start diff --git a/Makefile b/Makefile index 39dc85a0..ee0f0c24 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ # Tool versions ACTIONLINT_VERSION := 1.7.10 ACTION_VALIDATOR_VERSION := 0.8.0 -GH_AW_VERSION := v0.47.4 +GH_AW_VERSION := v0.48.1 # Helper: Detect OS and architecture (sets OS and ARCH variables) # Usage: $(DETECT_OS_ARCH) @@ -111,30 +111,25 @@ setup-gh-debian: setup-gh-aw: @echo "Setting up gh-aw compiler..." - @if command -v go >/dev/null 2>&1; then \ - mkdir -p .bin && \ - if [ -f .bin/gh-aw ]; then \ - echo "✓ gh-aw already installed"; \ - else \ - echo "Cloning strawgate/gh-aw@feature/inline-prompt..."; \ - TMPDIR=$$(mktemp -d) && \ - git clone --depth 1 --branch feature/inline-prompt https://github.com/strawgate/gh-aw.git "$$TMPDIR/gh-aw" && \ - cd "$$TMPDIR/gh-aw" && \ - GOBIN="$(CURDIR)/.bin" go install ./cmd/gh-aw && \ - rm -rf "$$TMPDIR" && \ - echo "✓ gh-aw installed to .bin/gh-aw"; \ - fi; \ - else \ - echo "⚠ Go not found. Install Go first: https://go.dev/dl/"; \ + @mkdir -p .bin + @if ! command -v go >/dev/null 2>&1; then \ + echo "Error: Go is required to install gh-aw compiler."; \ + echo "Install Go: https://go.dev/dl/"; \ exit 1; \ + elif [ -x ".bin/gh-aw" ] && .bin/gh-aw version 2>/dev/null | grep -q "$(GH_AW_VERSION)"; then \ + echo "✓ gh-aw compiler already installed: $(GH_AW_VERSION)"; \ + else \ + echo "Installing gh-aw compiler $(GH_AW_VERSION) from github/gh-aw..."; \ + GOBIN="$(CURDIR)/.bin" go install github.com/github/gh-aw/cmd/gh-aw@$(GH_AW_VERSION) && \ + echo "✓ gh-aw compiler installed: $$(.bin/gh-aw version)"; \ fi sync: @./scripts/dogfood.sh -compile: setup-gh-aw +compile: setup-gh-aw sync @echo "Compiling agentic workflows..." - @.bin/gh-aw compile --inline-prompt --action-mode release --action-tag $(GH_AW_VERSION) + @.bin/gh-aw compile --action-mode release --action-tag $(GH_AW_VERSION) setup-actionlint: @echo "Setting up actionlint..." @@ -155,7 +150,14 @@ setup-actionlint: lint-workflows: setup-actionlint @echo "Validating GitHub Actions workflow files..." @ACTIONLINT="bin/actionlint"; \ - find claude-workflows .github/workflows -name "example.yml" -o -name "example.yaml" 2>/dev/null | while read -r file; do \ + ( \ + find claude-workflows -name "example.yml" -o -name "example.yaml"; \ + find .github/workflows -maxdepth 1 \( \ + -name "trigger-*.yml" -o -name "trigger-*.yaml" -o \ + -name "agentics-maintenance.yml" -o -name "ci.yml" -o \ + -name "release.yml" -o -name "smoke-test-install.yml" \ + \); \ + ) 2>/dev/null | while read -r file; do \ echo "Checking $$file..."; \ $$ACTIONLINT "$$file" || exit 1; \ done diff --git a/README.md b/README.md index 5e783f62..5a16a508 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,7 @@ Full documentation lives at https://elastic.github.io/ai-github-actions/. - Legacy Claude Composite Actions: https://elastic.github.io/ai-github-actions/workflows/claude-workflows/ - Developing: https://elastic.github.io/ai-github-actions/developing/ - Security: https://elastic.github.io/ai-github-actions/security/ +- Upgrading: https://elastic.github.io/ai-github-actions/upgrading/ - Release process: https://elastic.github.io/ai-github-actions/release/ - Contributing: [CONTRIBUTING.md](CONTRIBUTING.md) diff --git a/docs/developing.md b/docs/developing.md index b3d4414a..02bdf1fb 100644 --- a/docs/developing.md +++ b/docs/developing.md @@ -8,7 +8,7 @@ | `gh-agent-workflows/` | Per-workflow READMEs, `example.yml` triggers, and optional `dogfood-with.yml` overrides | https://github.com/elastic/ai-github-actions/blob/main/gh-agent-workflows/DEVELOPING.md | | `claude-workflows/` | Composite actions wrapping Claude Code | https://github.com/elastic/ai-github-actions/blob/main/claude-workflows/DEVELOPING.md | -Internal-only workflows (e.g., `gh-aw-upgrade-check.md`, `ci.yml`, `release.yml`) also live in `.github/workflows/`. +Internal-only workflows (e.g., `upgrade-check.md`, `workflow-patrol.md`, `ci.yml`, `release.yml`) also live in `.github/workflows/`. Published workflows use the `gh-aw-` prefix; internal-only ones omit it. ## Quick start diff --git a/docs/upgrading.md b/docs/upgrading.md new file mode 100644 index 00000000..6a03d1ee --- /dev/null +++ b/docs/upgrading.md @@ -0,0 +1,62 @@ +# Upgrading + +## v0.2.5 → v0.2.6 + +### Breaking changes — workflow renames + +The following workflows have been renamed. Consumers referencing the old `uses:` path must update their trigger files. Symlinks are provided for the four most widely adopted workflows (marked below); the rest require a manual rename. + +| Old name | New name | Symlink? | +| --- | --- | --- | +| `breaking-change-detect` | `breaking-change-detector` | Yes | +| `docs-drift` | `docs-patrol` | Yes | +| `pr-ci-detective` | `pr-actions-detective` | Yes | +| `test-improvement` | `test-improver` | Yes | +| `docs-new-contributor-review` | `newbie-contributor-patrol` | No | +| `flaky-test-triage` | `flaky-test-investigator` | No | +| `issue-triage-pr` | `issue-fixer` | No | +| `pr-ci-fixer` | `pr-actions-fixer` | No | +| `semantic-function-clustering` | `code-duplication-detector` | No | + +**How to update:** In your trigger workflow file, change the `uses:` line: + +```yaml +# Before +uses: elastic/ai-github-actions/.github/workflows/gh-aw-docs-drift.lock.yml@v0 + +# After +uses: elastic/ai-github-actions/.github/workflows/gh-aw-docs-patrol.lock.yml@v0 +``` + +### Breaking changes — removed workflows + +| Workflow | Replacement | +| --- | --- | +| `pr-checks-fix` | Use `pr-actions-fixer` instead (manual `workflow_dispatch` trigger) | + +### Permission changes + +The following workflows have updated permissions. If you copied the original `example.yml`, update your trigger file to match. + +| Workflow | Change | +| --- | --- | +| `pr-actions-detective` (was `pr-ci-detective`) | Removed `discussions: write`; changed `pull-requests: write` → `pull-requests: read` | +| `pr-actions-fixer` (was `pr-ci-fixer`) | Removed `discussions: write` | +| `issue-triage` | Added `actions: read` | +| `mention-in-issue` | Added `actions: read` | +| `mention-in-pr` | Added `actions: read` | + +### Other changes + +- All workflows now accept a `model` input (default: `gpt-5.3-codex`) to select the AI model. +- All workflows now accept `setup-commands`, `allowed-bot-users`, and `messages-footer` inputs. +- Switched to upstream `github/gh-aw` compiler (v0.48.1). +- New shared fragments: `scheduled-audit.md` and `scheduled-fix.md` for building custom detector/fixer workflows. + +### Migration checklist + +1. [ ] Update renamed workflow `uses:` paths in your trigger files +2. [ ] Update permissions to match the new examples (see table above) +3. [ ] Remove any `pr-checks-fix` trigger (replace with `pr-actions-fixer` if needed) +4. [ ] Optionally adopt new workflows (`text-auditor`, `code-duplication-fixer`, etc.) +5. [ ] Test by running `workflow_dispatch` on updated triggers diff --git a/docs/workflows/gh-agent-workflows.md b/docs/workflows/gh-agent-workflows.md index 7e5c0565..9c8e0f3d 100644 --- a/docs/workflows/gh-agent-workflows.md +++ b/docs/workflows/gh-agent-workflows.md @@ -23,42 +23,64 @@ Each workflow directory contains an `example.yml` starter and a README for trigg ## Available workflows +### Base workflows + +Two generic base workflows let you build custom detectors and fixers without writing a full workflow from scratch. Provide your domain-specific instructions via `additional-instructions`: + +| Workflow | Role | Output | +| --- | --- | --- | +| [Scheduled Audit](gh-agent-workflows/scheduled-audit.md) | Detect issues and file reports | `create-issue` | +| [Scheduled Fix](gh-agent-workflows/scheduled-fix.md) | Fix reported issues | `create-pull-request` | + +These pair together: a Scheduled Audit finds problems, a Scheduled Fix resolves them. The specialized workflows below are built on top of these base fragments. + ### Human-coordinated workflows | Workflow | Trigger | Description | | --- | --- | --- | | [Docs PR Review](gh-agent-workflows/docs-pr-review.md) | `/docs-review` on PRs | Review docs for style guide, `applies_to`, and consistency | +| [Duplicate Issue Detector](gh-agent-workflows/duplicate-issue-detector.md) | New issues | Detect duplicate issues and comment with links | | [Issue Triage](gh-agent-workflows/issue-triage.md) | New issues | Investigate and provide implementation plans | -| [Issue Triage (with PR)](gh-agent-workflows/issue-triage-pr.md) | New issues | Triage plus automatic draft PR for straightforward fixes | +| [Issue Fixer](gh-agent-workflows/issue-fixer.md) | New issues | Triage plus automatic draft PR for straightforward fixes | | [Mention in Issue](gh-agent-workflows/mention-in-issue.md) | `/ai` in issues | Answer questions, debug, create PRs | | [Mention in PR](gh-agent-workflows/mention-in-pr.md) | `/ai` in PRs | Review, fix code, push changes | +| [PR Actions Detective](gh-agent-workflows/pr-actions-detective.md) | Failed PR checks | Diagnose failures and recommend fixes | +| [PR Actions Fixer](gh-agent-workflows/pr-actions-fixer.md) | Manual (workflow_dispatch) | Opt-in fixes for failed PR checks | | [PR Buildkite Detective](gh-agent-workflows/pr-buildkite-detective.md) | Failed PR checks | Diagnose Buildkite failures and recommend fixes | -| [PR CI Detective](gh-agent-workflows/pr-ci-detective.md) | Failed PR checks | Diagnose failures and recommend fixes | -| [PR CI Fixer](gh-agent-workflows/pr-ci-fixer.md) | Manual (workflow_dispatch) | Opt-in fixes for failed PR checks | | [PR Review](gh-agent-workflows/pr-review.md) | PR opened/updated | AI code review with inline comments | +| [PR Review (Fork)](gh-agent-workflows/pr-review-fork.md) | PR opened/updated (`pull_request_target`) | AI code review for fork PRs — **private repos or trusted contributors only** | +| [Update PR Body](gh-agent-workflows/update-pr-body.md) | PR opened / updated / ready for review | Auto-populate PR description from diff and linked issues | + +### Detector / fixer pairs + +Many scheduled workflows follow a **detector / fixer** pattern: the detector finds issues and files reports, then the fixer picks up those reports and creates PRs to resolve them. Install both for a fully autonomous loop, or use the detector alone for human-in-the-loop review. + +| Detector | Fixer | Domain | +| --- | --- | --- | +| [Bug Hunter](gh-agent-workflows/bug-hunter.md) | [Bug Exterminator](gh-agent-workflows/bug-exterminator.md) | Reproducible bugs | +| [Code Duplication Detector](gh-agent-workflows/code-duplication-detector.md) | [Code Duplication Fixer](gh-agent-workflows/code-duplication-fixer.md) | Duplicate / clustered code | +| [Docs Patrol](gh-agent-workflows/docs-patrol.md) | — | Stale internal documentation | +| [Docs Patrol External](gh-agent-workflows/docs-patrol-external.md) | — | Stale published Elastic docs | +| [Newbie Contributor Patrol](gh-agent-workflows/newbie-contributor-patrol.md) | [Newbie Contributor Fixer](gh-agent-workflows/newbie-contributor-fixer.md) | Onboarding documentation gaps | +| [Newbie Contributor Patrol External](gh-agent-workflows/newbie-contributor-patrol-external.md) | — | Cross-referencing published docs | +| [Text Auditor](gh-agent-workflows/text-auditor.md) | [Text Beautifier](gh-agent-workflows/text-beautifier.md) | User-facing text quality | -### Continuous improvement / agent factory workflows +### Standalone scheduled workflows | Workflow | Trigger | Description | | --- | --- | --- | | [Agent Efficiency](gh-agent-workflows/agent-efficiency.md) | Weekday schedule | Analyze agent logs for inefficiencies | | [Agent Suggestions](gh-agent-workflows/agent-suggestions.md) | Weekly schedule | Suggest new agent workflows based on repo and downstream needs | -| [Breaking Change Detect](gh-agent-workflows/breaking-change-detect.md) | Weekday schedule | Detect undocumented public breaking changes | -| [Bug Exterminator](gh-agent-workflows/bug-exterminator.md) | Weekday schedule | Fix bug-hunter issues and open a focused PR | -| [Bug Hunter](gh-agent-workflows/bug-hunter.md) | Weekday schedule | Find reproducible bugs and file reports | +| [Breaking Change Detector](gh-agent-workflows/breaking-change-detector.md) | Weekday schedule | Detect undocumented public breaking changes | | [Code Simplifier](gh-agent-workflows/code-simplifier.md) | Weekday schedule | Simplify overcomplicated code with high-confidence refactors | -| [Docs Drift](gh-agent-workflows/docs-drift.md) | Weekday schedule | Detect code changes needing doc updates | -| [Docs Drift External](gh-agent-workflows/docs-drift-external.md) | Weekday schedule | Detect code changes needing published Elastic doc updates | -| [Docs New Contributor Review](gh-agent-workflows/docs-new-contributor-review.md) | Weekly schedule | Review docs from a new contributor perspective | -| [Docs New Contributor Review External](gh-agent-workflows/docs-new-contributor-review-external.md) | Weekly schedule | Review docs cross-referencing published Elastic documentation | | [Downstream Health](gh-agent-workflows/downstream-health.md) | Daily schedule | Monitor downstream repo quality | -| [Flaky Test Triage](gh-agent-workflows/flaky-test-triage.md) | Weekday schedule + failed CI runs | Identify repeated flaky failures and file root-cause-first triage reports | +| [Flaky Test Investigator](gh-agent-workflows/flaky-test-investigator.md) | Weekday schedule + failed CI runs | Identify repeated flaky failures and file root-cause-first triage reports | +| [Performance Profiler](gh-agent-workflows/performance-profiler.md) | Weekday schedule | Profile performance hotspots | | [Project Summary](gh-agent-workflows/project-summary.md) | Daily schedule | Summarize recent activity and priorities | | [Release Update Check](gh-agent-workflows/release-update.md) | Weekly schedule | Open a PR updating pinned ai-github-actions workflow SHAs and suggest workflow changes | -| [Semantic Function Clustering](gh-agent-workflows/semantic-function-clustering.md) | Weekday schedule | Identify function clustering refactor opportunities | | [Small Problem Fixer](gh-agent-workflows/small-problem-fixer.md) | Weekday schedule | Fix small, related issues and open a focused PR | | [Stale Issues](gh-agent-workflows/stale-issues.md) | Weekday schedule | Find resolved issues that can be closed | -| [Test Improvement](gh-agent-workflows/test-improvement.md) | Weekly schedule | Add targeted tests and clean up redundant coverage | +| [Test Improver](gh-agent-workflows/test-improver.md) | Weekly schedule | Add targeted tests and clean up redundant coverage | ## Secrets @@ -123,6 +145,6 @@ setup-commands: | Each workflow has two layers: 1. **Workflow** (`gh-aw-*.md` -> `gh-aw-*.lock.yml`): The agent logic, compiled by `gh-aw`. Triggers only on `workflow_call` with standard inputs (`additional-instructions`, `setup-commands`) and a `COPILOT_GITHUB_TOKEN` secret. -2. **Trigger** (`/example.yml`): A plain YAML file that defines the actual event triggers (schedule, PR events, slash commands, etc.) and calls the compiled `.lock.yml` via `uses:`. These serve as both examples for consumers and dogfood for this repo (copied to `.github/workflows/trigger-*.yml` by `scripts/dogfood.sh` for workflows not listed in `EXCLUDED_WORKFLOWS`, currently `flaky-test-triage` and `issue-triage-pr`). +2. **Trigger** (`/example.yml`): A plain YAML file that defines the actual event triggers (schedule, PR events, slash commands, etc.) and calls the compiled `.lock.yml` via `uses:`. These serve as both examples for consumers and dogfood for this repo (copied to `.github/workflows/trigger-*.yml` by `scripts/dogfood.sh` for workflows not listed in `EXCLUDED_WORKFLOWS`). Consumer repos copy a workflow's `example.yml`, change the `uses:` path if needed, and customize the `with:` inputs. Updates propagate automatically when this repo updates the `v0` tag on release. diff --git a/docs/workflows/gh-agent-workflows/bugs.md b/docs/workflows/gh-agent-workflows/bugs.md new file mode 100644 index 00000000..8322d975 --- /dev/null +++ b/docs/workflows/gh-agent-workflows/bugs.md @@ -0,0 +1,119 @@ +# Bug Hunting + +Find reproducible bugs and automatically fix them. + +**Bug Hunter** finds user-impacting bugs by reviewing recent git history, writing minimal reproduction scripts, and filing a report issue only when the bug is concretely confirmed. **Bug Exterminator** picks up those reports, reproduces the bug locally, and opens a PR with a minimal fix. Most runs of either workflow end with `noop`. + +## Quick install + +### Detector only + +Install Bug Hunter alone if you want to review bug reports before acting on them. + +```bash +mkdir -p .github/workflows && curl -sL \ + https://raw.githubusercontent.com/elastic/ai-github-actions/v0/gh-agent-workflows/bug-hunter/example.yml \ + -o .github/workflows/bug-hunter.yml +``` + +### Full loop (detector + fixer) + +Install both for a fully autonomous bug-finding and fixing pipeline. + +```bash +mkdir -p .github/workflows && \ +curl -sL https://raw.githubusercontent.com/elastic/ai-github-actions/v0/gh-agent-workflows/bug-hunter/example.yml \ + -o .github/workflows/bug-hunter.yml && \ +curl -sL https://raw.githubusercontent.com/elastic/ai-github-actions/v0/gh-agent-workflows/bug-exterminator/example.yml \ + -o .github/workflows/bug-exterminator.yml +``` + +--- + +## Bug Hunter (detector) + +Reviews 28 days of git history for user-facing changes that could introduce bugs. For each candidate, writes a new minimal reproduction script and runs it — filing a report only when the bug is concretely confirmed. + +### Trigger + +| Event | Schedule | +| --- | --- | +| `schedule` | Weekdays | +| `workflow_dispatch` | Manual | + +### Inputs + +| Input | Description | Default | +| --- | --- | --- | +| `additional-instructions` | Repo-specific instructions appended to the agent prompt | `""` | +| `setup-commands` | Shell commands run before the agent starts | `""` | + +### Safe outputs + +- `create-issue` — file a bug report (max 1, auto-closes older reports) + +### Example workflow + +```yaml +name: Bug Hunter +on: + schedule: + - cron: "0 11 * * 1-5" + workflow_dispatch: + +permissions: + contents: read + issues: write + pull-requests: read + +jobs: + run: + uses: elastic/ai-github-actions/.github/workflows/gh-aw-bug-hunter.lock.yml@v0 + secrets: + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} +``` + +--- + +## Bug Exterminator (fixer) + +Searches for open issues labeled `bug-hunter` or titled `[bug-hunter]`. For each candidate, attempts to reproduce the bug locally — if reproduction succeeds and a minimal fix is safe to apply, it opens a PR. + +### Trigger + +| Event | Schedule | +| --- | --- | +| `schedule` | Weekdays | +| `workflow_dispatch` | Manual | + +### Inputs + +| Input | Description | Default | +| --- | --- | --- | +| `additional-instructions` | Repo-specific instructions appended to the agent prompt | `""` | +| `setup-commands` | Shell commands run before the agent starts | `""` | + +### Safe outputs + +- `create-pull-request` — open a PR with the fix + +### Example workflow + +```yaml +name: Bug Exterminator +on: + schedule: + - cron: "0 13 * * 1-5" + workflow_dispatch: + +permissions: + contents: write + issues: write + pull-requests: write + +jobs: + run: + uses: elastic/ai-github-actions/.github/workflows/gh-aw-bug-exterminator.lock.yml@v0 + secrets: + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} +``` diff --git a/docs/workflows/gh-agent-workflows/code-duplication.md b/docs/workflows/gh-agent-workflows/code-duplication.md new file mode 100644 index 00000000..f395417f --- /dev/null +++ b/docs/workflows/gh-agent-workflows/code-duplication.md @@ -0,0 +1,123 @@ +# Code Duplication + +Find duplicate and misplaced functions, then consolidate them automatically. + +**Code Duplication Detector** scans source files to find semantically related functions that live in different files, duplicate implementations of the same logic, and functions that belong in a different module. **Code Duplication Fixer** picks up those reports and opens a PR with behavior-preserving refactors. Most runs of either workflow end with `noop`. + +## Quick install + +### Detector only + +Install the detector alone if you want to review refactoring recommendations before acting. + +```bash +mkdir -p .github/workflows && curl -sL \ + https://raw.githubusercontent.com/elastic/ai-github-actions/v0/gh-agent-workflows/code-duplication-detector/example.yml \ + -o .github/workflows/code-duplication-detector.yml +``` + +### Full loop (detector + fixer) + +Install both for autonomous detection and consolidation. + +```bash +mkdir -p .github/workflows && \ +curl -sL https://raw.githubusercontent.com/elastic/ai-github-actions/v0/gh-agent-workflows/code-duplication-detector/example.yml \ + -o .github/workflows/code-duplication-detector.yml && \ +curl -sL https://raw.githubusercontent.com/elastic/ai-github-actions/v0/gh-agent-workflows/code-duplication-fixer/example.yml \ + -o .github/workflows/code-duplication-fixer.yml +``` + +--- + +## Code Duplication Detector + +Scans source files (by language or custom glob) to find semantically related functions in different files, duplicate implementations, and functions that belong in a different module. Files a report with specific refactoring recommendations. + +### Trigger + +| Event | Schedule | +| --- | --- | +| `schedule` | Weekdays | +| `workflow_dispatch` | Manual | + +### Inputs + +| Input | Description | Default | +| --- | --- | --- | +| `languages` | Comma-separated languages to analyze (ignored if `file-globs` is set) | `"go"` | +| `file-globs` | Comma-separated file globs to analyze (overrides `languages`) | `""` | +| `additional-instructions` | Repo-specific instructions appended to the agent prompt | `""` | +| `setup-commands` | Shell commands run before the agent starts | `""` | + +### Safe outputs + +- `create-issue` — file a refactoring report (max 1, auto-closes older reports) + +### Example workflow + +```yaml +name: Code Duplication Detector +on: + schedule: + - cron: "0 12 * * 1-5" + workflow_dispatch: + +permissions: + contents: read + issues: write + pull-requests: read + +jobs: + run: + uses: elastic/ai-github-actions/.github/workflows/gh-aw-code-duplication-detector.lock.yml@v0 + with: + languages: "go,python,typescript" + secrets: + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} +``` + +--- + +## Code Duplication Fixer + +Picks up open issues filed by the detector (labeled `refactor` or with `[refactor]` in the title), selects one well-scoped finding, refactors the duplicate or misplaced code, runs tests, and opens a PR. Only acts on safe, behavior-preserving refactors. + +### Trigger + +| Event | Schedule | +| --- | --- | +| `schedule` | Weekdays | +| `workflow_dispatch` | Manual | + +### Inputs + +| Input | Description | Default | +| --- | --- | --- | +| `additional-instructions` | Repo-specific instructions appended to the agent prompt | `""` | +| `setup-commands` | Shell commands run before the agent starts | `""` | + +### Safe outputs + +- `create-pull-request` — open a PR with the refactor (max 1) + +### Example workflow + +```yaml +name: Code Duplication Fixer +on: + schedule: + - cron: "0 14 * * 1-5" + workflow_dispatch: + +permissions: + contents: read + issues: read + pull-requests: write + +jobs: + run: + uses: elastic/ai-github-actions/.github/workflows/gh-aw-code-duplication-fixer.lock.yml@v0 + secrets: + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} +``` diff --git a/docs/workflows/gh-agent-workflows/docs-patrol-overview.md b/docs/workflows/gh-agent-workflows/docs-patrol-overview.md new file mode 100644 index 00000000..a49ed058 --- /dev/null +++ b/docs/workflows/gh-agent-workflows/docs-patrol-overview.md @@ -0,0 +1,117 @@ +# Docs Patrol + +Detect code changes that require documentation updates — both internal and published. + +Two variants cover different documentation scopes: **Docs Patrol** checks internal documentation (READMEs, CONTRIBUTING, etc.) against recent code changes, while **Docs Patrol External** focuses on published Elastic documentation on `elastic.co/docs`. Both scan recent commits for public API or behavioral changes not reflected in documentation. Most runs end with `noop`. + +## Quick install + +### Internal docs only + +```bash +mkdir -p .github/workflows && curl -sL \ + https://raw.githubusercontent.com/elastic/ai-github-actions/v0/gh-agent-workflows/docs-patrol/example.yml \ + -o .github/workflows/docs-patrol.yml +``` + +### Both internal and external + +```bash +mkdir -p .github/workflows && \ +curl -sL https://raw.githubusercontent.com/elastic/ai-github-actions/v0/gh-agent-workflows/docs-patrol/example.yml \ + -o .github/workflows/docs-patrol.yml && \ +curl -sL https://raw.githubusercontent.com/elastic/ai-github-actions/v0/gh-agent-workflows/docs-patrol-external/example.yml \ + -o .github/workflows/docs-patrol-external.yml +``` + +--- + +## Docs Patrol (internal) + +Scans recent commits (7-day lookback by default) for public API or behavioral changes not reflected in nearby documentation. Checks READMEs, contribution guides, and other discovered markdown files before filing. + +### Trigger + +| Event | Schedule | +| --- | --- | +| `schedule` | Weekdays | +| `workflow_dispatch` | Manual | + +### Inputs + +| Input | Description | Default | +| --- | --- | --- | +| `lookback-window` | Git lookback window for detecting recent commits | `"7 days ago"` | +| `additional-instructions` | Repo-specific instructions appended to the agent prompt | `""` | +| `setup-commands` | Shell commands run before the agent starts | `""` | + +### Safe outputs + +- `create-issue` — file a docs patrol report (max 1, auto-closes older reports) + +### Example workflow + +```yaml +name: Docs Patrol +on: + schedule: + - cron: "0 14 * * 1-5" + workflow_dispatch: + +permissions: + contents: read + issues: write + pull-requests: read + +jobs: + run: + uses: elastic/ai-github-actions/.github/workflows/gh-aw-docs-patrol.lock.yml@v0 + secrets: + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} +``` + +--- + +## Docs Patrol External + +Like Docs Patrol, but focuses on changes that require updates to published Elastic documentation on `elastic.co/docs`. Also flags features that need `applies_to` tag updates or documentation backports to earlier release branches. + +### Trigger + +| Event | Schedule | +| --- | --- | +| `schedule` | Weekdays | +| `workflow_dispatch` | Manual | + +### Inputs + +| Input | Description | Default | +| --- | --- | --- | +| `lookback-window` | Git lookback window for detecting recent commits | `"7 days ago"` | +| `additional-instructions` | Repo-specific instructions appended to the agent prompt | `""` | +| `setup-commands` | Shell commands run before the agent starts | `""` | + +### Safe outputs + +- `create-issue` — file an external docs patrol report (max 1, auto-closes older reports) + +### Example workflow + +```yaml +name: Docs Patrol External +on: + schedule: + - cron: "0 14 * * 1-5" + workflow_dispatch: + +permissions: + contents: read + issues: write + pull-requests: read + +jobs: + run: + uses: elastic/ai-github-actions/.github/workflows/gh-aw-docs-patrol-external.lock.yml@v0 + secrets: + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} +``` diff --git a/docs/workflows/gh-agent-workflows/newbie-contributor.md b/docs/workflows/gh-agent-workflows/newbie-contributor.md new file mode 100644 index 00000000..654cc838 --- /dev/null +++ b/docs/workflows/gh-agent-workflows/newbie-contributor.md @@ -0,0 +1,172 @@ +# Newbie Contributor + +Review documentation from a new contributor's perspective and automatically fix gaps. + +**Newbie Contributor Patrol** reads all contributor-facing documentation as if it were a new contributor's first encounter with the project — following getting-started paths, checking for missing prerequisites, and flagging blocking gaps. An **External** variant also cross-references published Elastic documentation. **Newbie Contributor Fixer** picks up patrol issues and opens PRs with documentation improvements. Most runs end with `noop`. + +## Quick install + +### Patrol only (human reviews issues) + +```bash +mkdir -p .github/workflows && curl -sL \ + https://raw.githubusercontent.com/elastic/ai-github-actions/v0/gh-agent-workflows/newbie-contributor-patrol/example.yml \ + -o .github/workflows/newbie-contributor-patrol.yml +``` + +### Full loop (patrol + fixer) + +```bash +mkdir -p .github/workflows && \ +curl -sL https://raw.githubusercontent.com/elastic/ai-github-actions/v0/gh-agent-workflows/newbie-contributor-patrol/example.yml \ + -o .github/workflows/newbie-contributor-patrol.yml && \ +curl -sL https://raw.githubusercontent.com/elastic/ai-github-actions/v0/gh-agent-workflows/newbie-contributor-fixer/example.yml \ + -o .github/workflows/newbie-contributor-fixer.yml +``` + +### All three (patrol + external + fixer) + +```bash +mkdir -p .github/workflows && \ +curl -sL https://raw.githubusercontent.com/elastic/ai-github-actions/v0/gh-agent-workflows/newbie-contributor-patrol/example.yml \ + -o .github/workflows/newbie-contributor-patrol.yml && \ +curl -sL https://raw.githubusercontent.com/elastic/ai-github-actions/v0/gh-agent-workflows/newbie-contributor-patrol-external/example.yml \ + -o .github/workflows/newbie-contributor-patrol-external.yml && \ +curl -sL https://raw.githubusercontent.com/elastic/ai-github-actions/v0/gh-agent-workflows/newbie-contributor-fixer/example.yml \ + -o .github/workflows/newbie-contributor-fixer.yml +``` + +--- + +## Newbie Contributor Patrol (detector) + +Reads all contributor-facing documentation (README, CONTRIBUTING, DEVELOPING, etc.) as if it were a new contributor's first encounter with the project. Follows getting-started paths, checks for missing prerequisites, and flags blocking gaps. Only files issues for high-impact problems. + +### Trigger + +| Event | Schedule | +| --- | --- | +| `schedule` | Weekly (Monday) | +| `workflow_dispatch` | Manual | + +### Inputs + +| Input | Description | Default | +| --- | --- | --- | +| `additional-instructions` | Repo-specific instructions appended to the agent prompt | `""` | +| `setup-commands` | Shell commands run before the agent starts | `""` | + +### Safe outputs + +- `create-issue` — file a new contributor docs review (max 1, auto-closes older reports) + +### Example workflow + +```yaml +name: Newbie Contributor Patrol +on: + schedule: + - cron: "0 11 * * 1" + workflow_dispatch: + +permissions: + contents: read + issues: write + pull-requests: read + +jobs: + run: + uses: elastic/ai-github-actions/.github/workflows/gh-aw-newbie-contributor-patrol.lock.yml@v0 + secrets: + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} +``` + +--- + +## Newbie Contributor Patrol External (detector variant) + +Like Newbie Contributor Patrol, but also cross-references the repo's documentation against published Elastic documentation on `elastic.co/docs`. Contradictions between the repo and published docs are treated as blocking issues. + +### Trigger + +| Event | Schedule | +| --- | --- | +| `schedule` | Weekly (Monday) | +| `workflow_dispatch` | Manual | + +### Inputs + +| Input | Description | Default | +| --- | --- | --- | +| `additional-instructions` | Repo-specific instructions appended to the agent prompt | `""` | +| `setup-commands` | Shell commands run before the agent starts | `""` | + +### Safe outputs + +- `create-issue` — file an external new contributor docs review (max 1, auto-closes older reports) + +### Example workflow + +```yaml +name: Newbie Contributor Patrol External +on: + schedule: + - cron: "0 11 * * 1" + workflow_dispatch: + +permissions: + contents: read + issues: write + pull-requests: read + +jobs: + run: + uses: elastic/ai-github-actions/.github/workflows/gh-aw-newbie-contributor-patrol-external.lock.yml@v0 + secrets: + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} +``` + +--- + +## Newbie Contributor Fixer + +Picks up open issues filed by the patrol (labeled `newbie-contributor` or with `[newbie-contributor]` in the title), applies the suggested documentation improvements, and opens a PR. Focuses on filling gaps in the contributor onboarding path — missing prerequisites, broken commands, undocumented requirements. + +### Trigger + +| Event | Schedule | +| --- | --- | +| `schedule` | Weekdays | +| `workflow_dispatch` | Manual | + +### Inputs + +| Input | Description | Default | +| --- | --- | --- | +| `additional-instructions` | Repo-specific instructions appended to the agent prompt | `""` | +| `setup-commands` | Shell commands run before the agent starts | `""` | + +### Safe outputs + +- `create-pull-request` — open a PR with documentation fixes (max 1) + +### Example workflow + +```yaml +name: Newbie Contributor Fixer +on: + schedule: + - cron: "0 14 * * 1-5" + workflow_dispatch: + +permissions: + contents: read + issues: read + pull-requests: write + +jobs: + run: + uses: elastic/ai-github-actions/.github/workflows/gh-aw-newbie-contributor-fixer.lock.yml@v0 + secrets: + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} +``` diff --git a/docs/workflows/gh-agent-workflows/text-quality.md b/docs/workflows/gh-agent-workflows/text-quality.md new file mode 100644 index 00000000..a7829eab --- /dev/null +++ b/docs/workflows/gh-agent-workflows/text-quality.md @@ -0,0 +1,126 @@ +# Text Quality + +Find text issues and automatically fix them. + +**Text Auditor** scans user-facing text sources — CLI output, error messages, documentation, and help text — for typos, grammatical errors, unclear messages, and inconsistent terminology. **Text Beautifier** picks up those reports and opens a PR with concrete fixes. Most runs of either workflow end with `noop`. + +## Quick install + +### Auditor only (human reviews issues) + +```bash +mkdir -p .github/workflows && curl -sL \ + https://raw.githubusercontent.com/elastic/ai-github-actions/v0/gh-agent-workflows/text-auditor/example.yml \ + -o .github/workflows/text-auditor.yml +``` + +### Full loop (auditor + beautifier) + +```bash +mkdir -p .github/workflows && \ +curl -sL https://raw.githubusercontent.com/elastic/ai-github-actions/v0/gh-agent-workflows/text-auditor/example.yml \ + -o .github/workflows/text-auditor.yml && \ +curl -sL https://raw.githubusercontent.com/elastic/ai-github-actions/v0/gh-agent-workflows/text-beautifier/example.yml \ + -o .github/workflows/text-beautifier.yml +``` + +--- + +## Text Auditor (detector) + +Scans user-facing text sources for typos, grammatical errors, unclear error messages, and inconsistent terminology. Files a single issue with concrete, low-effort fixes. + +### Trigger + +| Event | Schedule | +| --- | --- | +| `schedule` | Weekdays | +| `workflow_dispatch` | Manual | + +### Inputs + +| Input | Description | Default | +| --- | --- | --- | +| `edit-typos` | How aggressively to flag typos and misspellings (`high`/`low`/`none`) | `low` | +| `edit-grammar` | How aggressively to flag grammar problems (`high`/`low`/`none`) | `low` | +| `edit-clarity` | How aggressively to flag unclear text (`high`/`low`/`none`) | `low` | +| `edit-terminology` | How aggressively to flag inconsistent terminology (`high`/`low`/`none`) | `low` | +| `edit-misleading-text` | How aggressively to flag text that conflicts with behavior (`high`/`low`/`none`) | `low` | +| `additional-instructions` | Repo-specific instructions appended to the agent prompt | `""` | +| `setup-commands` | Shell commands run before the agent starts | `""` | + +### Safe outputs + +- `create-issue` — file a text improvement report (max 1, auto-closes older reports) + +### Example workflow + +```yaml +name: Text Auditor +on: + schedule: + - cron: "0 13 * * 1-5" + workflow_dispatch: + +permissions: + contents: read + issues: write + pull-requests: read + +jobs: + run: + uses: elastic/ai-github-actions/.github/workflows/gh-aw-text-auditor.lock.yml@v0 + with: + # edit-typos: low + # edit-grammar: low + # edit-clarity: low + # edit-terminology: low + # edit-misleading-text: low + secrets: + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} +``` + +--- + +## Text Beautifier (fixer) + +Picks up open issues filed by the Text Auditor (labeled `text-auditor` or with `[text-auditor]` in the title), applies the suggested text fixes, and opens a PR. Only acts on concrete, unambiguous fixes — skips anything requiring design decisions. + +### Trigger + +| Event | Schedule | +| --- | --- | +| `schedule` | Weekdays | +| `workflow_dispatch` | Manual | + +### Inputs + +| Input | Description | Default | +| --- | --- | --- | +| `additional-instructions` | Repo-specific instructions appended to the agent prompt | `""` | +| `setup-commands` | Shell commands run before the agent starts | `""` | + +### Safe outputs + +- `create-pull-request` — open a PR with text fixes (max 1) + +### Example workflow + +```yaml +name: Text Beautifier +on: + schedule: + - cron: "0 14 * * 1-5" + workflow_dispatch: + +permissions: + contents: read + issues: read + pull-requests: write + +jobs: + run: + uses: elastic/ai-github-actions/.github/workflows/gh-aw-text-beautifier.lock.yml@v0 + secrets: + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} +``` diff --git a/gh-agent-workflows/DEVELOPING.md b/gh-agent-workflows/DEVELOPING.md index 797b1c85..2faa438b 100644 --- a/gh-agent-workflows/DEVELOPING.md +++ b/gh-agent-workflows/DEVELOPING.md @@ -23,24 +23,25 @@ gh-agent-workflows/ │ ├── formatting.md │ ├── rigor.md │ ├── mcp-pagination.md -│ ├── scheduled-report.md # Shared scheduled report prompt +│ ├── scheduled-audit.md # Shared audit framework (detect and report) +│ ├── scheduled-fix.md # Shared fix framework (pick up issue and PR) │ └── safe-output-*.md ├── gh-aw-pr-review.md # Workflow: self-contained (prompt + config) ├── gh-aw-pr-review.lock.yml # Compiled output ├── trigger-pr-review.yml # Copied from gh-agent-workflows/pr-review/example.yml ├── ... -└── gh-aw-upgrade-check.md # Internal-only scheduled check +└── upgrade-check.md # Internal-only scheduled check (no gh-aw- prefix) ``` **Workflows** (`.github/workflows/gh-aw-*.md`) are self-contained agent workflow definitions. Each file contains the engine, `workflow_call` trigger (with standard inputs), permissions, concurrency, roles, description, tools, network, safe-outputs, and the full agent prompt. Workflows import only shared fragments from `gh-aw-fragments/`. They trigger **only** on `workflow_call` — they do not have schedule, event, or dispatch triggers directly. -**Triggers** (`gh-agent-workflows//example.yml`) are plain YAML files that define the actual event triggers (schedule, PR events, slash commands, etc.) and call the compiled `.lock.yml` via `uses:`. When copied to `.github/workflows/` by `scripts/dogfood.sh`, they become `trigger-.yml` (e.g., `pr-review/example.yml` → `trigger-pr-review.yml`) for workflows not listed in `EXCLUDED_WORKFLOWS` (`flaky-test-triage`, `issue-triage-pr`). They serve two purposes: (1) dogfood for running workflows in this repo, and (2) examples for consumer repos to copy and adapt. Triggers are NOT compiled by `gh-aw` — they are plain GitHub Actions YAML. +**Triggers** (`gh-agent-workflows//example.yml`) are plain YAML files that define the actual event triggers (schedule, PR events, slash commands, etc.) and call the compiled `.lock.yml` via `uses:`. When copied to `.github/workflows/` by `scripts/dogfood.sh`, they become `trigger-.yml` (e.g., `pr-review/example.yml` → `trigger-pr-review.yml`) for workflows not listed in `EXCLUDED_WORKFLOWS`. They serve two purposes: (1) dogfood for running workflows in this repo, and (2) examples for consumer repos to copy and adapt. Triggers are NOT compiled by `gh-aw` — they are plain GitHub Actions YAML. **Dogfood overrides** (`gh-agent-workflows//dogfood-with.yml`) are optional files containing `with:` input values that the dogfood script injects into the generated trigger. This lets us run workflows at different settings in this repo (e.g., `intensity: aggressive`) while keeping the examples at conservative defaults for consumers. If no `dogfood-with.yml` exists, the trigger is copied as-is from the example. Each workflow directory also contains a `README.md` with trigger details, inputs, and safe outputs. -**Shared fragments** (`.github/workflows/gh-aw-fragments/`) provide cross-workflow configuration and guidance. Fragments live directly in this directory — no symlinks. No `on:` field — validated but never compiled standalone. For example, `scheduled-report.md` provides a shared framework for scheduled report workflows. +**Shared fragments** (`.github/workflows/gh-aw-fragments/`) provide cross-workflow configuration and guidance. Fragments live directly in this directory — no symlinks. No `on:` field — validated but never compiled standalone. For example, `scheduled-audit.md` provides a shared framework for scheduled audit workflows. ## Import Structure @@ -55,17 +56,28 @@ workflow (gh-aw-pr-review.md) └── gh-aw-fragments/review-process.md ``` -For scheduled reports: +For scheduled audits (detectors): ```text -workflow (gh-aw-docs-drift.md) - ├── gh-aw-fragments/scheduled-report.md # shared report framework +workflow (gh-aw-docs-patrol.md) + ├── gh-aw-fragments/scheduled-audit.md # shared audit framework ├── gh-aw-fragments/elastic-tools.md ├── gh-aw-fragments/formatting.md └── ... ``` -`gh-aw-upgrade-check` is an **internal-only** workflow — its shim lives directly in `.github/workflows/` (not in `gh-agent-workflows/`) so it is not installable via `gh aw add`. It runs on weekdays to check for new `gh-aw` releases and files issues tagged `[gh-aw-upgrade]`. +For scheduled fixes (fixers): + +```text +workflow (gh-aw-text-beautifier.md) + ├── gh-aw-fragments/scheduled-fix.md # shared fix framework + ├── gh-aw-fragments/workflow-edit-guardrails.md + ├── gh-aw-fragments/safe-output-create-pr.md + ├── gh-aw-fragments/elastic-tools.md + └── ... +``` + +`upgrade-check` is an **internal-only** workflow — it lives directly in `.github/workflows/` without the `gh-aw-` prefix (not in `gh-agent-workflows/`) so it is not installable via `gh aw add`. Internal-only workflows (`upgrade-check`, `workflow-patrol`, `downstream-users`) omit the `gh-aw-` prefix to distinguish them from published workflows. ### Shared fragments @@ -77,7 +89,8 @@ Fragments live in `.github/workflows/gh-aw-fragments/`. Workflows import them us | [gh-aw-fragments/formatting.md](../.github/workflows/gh-aw-fragments/formatting.md) | Response formatting rules | | [gh-aw-fragments/rigor.md](../.github/workflows/gh-aw-fragments/rigor.md) | Accuracy & evidence standards | | [gh-aw-fragments/mcp-pagination.md](../.github/workflows/gh-aw-fragments/mcp-pagination.md) | MCP token limit guidance and pagination patterns | -| [gh-aw-fragments/scheduled-report.md](../.github/workflows/gh-aw-fragments/scheduled-report.md) | Shared scheduled report framework | +| [gh-aw-fragments/scheduled-audit.md](../.github/workflows/gh-aw-fragments/scheduled-audit.md) | Shared scheduled audit framework (detect and report) | +| [gh-aw-fragments/scheduled-fix.md](../.github/workflows/gh-aw-fragments/scheduled-fix.md) | Shared scheduled fix framework (pick up issue and create PR) | | [gh-aw-fragments/review-process.md](../.github/workflows/gh-aw-fragments/review-process.md) | Shared code review process, comment format, severity classification, and review criteria | | [gh-aw-fragments/messages-footer.md](../.github/workflows/gh-aw-fragments/messages-footer.md) | Wires the `messages-footer` input to `safe-outputs.messages.footer`; consumers override the footer via the workflow input | | [gh-aw-fragments/safe-output-add-comment.md](../.github/workflows/gh-aw-fragments/safe-output-add-comment.md) | Limitations for `add-comment` (body length, mentions, links) | @@ -99,25 +112,26 @@ Fragments live in `.github/workflows/gh-aw-fragments/`. Workflows import them us ### How compilation works -The `gh-aw` compiler processes `.md` files in `.github/workflows/`. `make sync` (which runs `scripts/dogfood.sh`) copies `example.yml` files from `gh-agent-workflows/*/` to `.github/workflows/trigger-*.yml` for workflows not listed in `EXCLUDED_WORKFLOWS` (`flaky-test-triage`, `issue-triage-pr`), injecting any `dogfood-with.yml` overrides. Workflow `.md` files and `gh-aw-fragments/` live directly in `.github/workflows/` — no symlinks. `gh-aw-fragments/` is a real directory. +The `gh-aw` compiler processes `.md` files in `.github/workflows/`. `make sync` (which runs `scripts/dogfood.sh`) copies `example.yml` files from `gh-agent-workflows/*/` to `.github/workflows/trigger-*.yml` for workflows not listed in `EXCLUDED_WORKFLOWS`, injecting any `dogfood-with.yml` overrides. Workflow `.md` files and `gh-aw-fragments/` live directly in `.github/workflows/` — no symlinks. `gh-aw-fragments/` is a real directory. ```text .github/workflows/ ├── gh-aw-fragments/ # Shared fragments (real directory) │ ├── elastic-tools.md -│ ├── scheduled-report.md +│ ├── scheduled-audit.md +│ ├── scheduled-fix.md │ └── ... ├── gh-aw-pr-review.md # Workflow (self-contained) ├── gh-aw-pr-review.lock.yml # compiled output ├── trigger-pr-review.yml # copied from gh-agent-workflows/pr-review/example.yml -├── gh-aw-docs-drift.md -├── gh-aw-docs-drift.lock.yml -├── trigger-docs-drift.yml -├── gh-aw-docs-new-contributor-review.md -├── gh-aw-docs-new-contributor-review.lock.yml -├── trigger-docs-new-contributor-review.yml -├── gh-aw-upgrade-check.md # repo-specific internal workflow -├── gh-aw-upgrade-check.lock.yml +├── gh-aw-docs-patrol.md +├── gh-aw-docs-patrol.lock.yml +├── trigger-docs-patrol.yml +├── gh-aw-newbie-contributor-patrol.md +├── gh-aw-newbie-contributor-patrol.lock.yml +├── trigger-newbie-contributor-patrol.yml +├── upgrade-check.md # internal-only (no gh-aw- prefix) +├── upgrade-check.lock.yml └── ... ``` @@ -182,7 +196,7 @@ Consumer repos call the compiled `.lock.yml` via `uses:` in a plain YAML workflo ### Trigger files -Each non-internal workflow has a corresponding `example.yml` in `gh-agent-workflows//` that defines the actual event triggers and calls the compiled `.lock.yml`. These are plain YAML (not compiled by gh-aw) and are copied to `.github/workflows/trigger-.yml` by `scripts/dogfood.sh` for dogfooding when the workflow is not listed in `EXCLUDED_WORKFLOWS`. +Each non-internal workflow has a corresponding `example.yml` in `gh-agent-workflows//` that defines the actual event triggers and calls the compiled `.lock.yml`. These are plain YAML (not compiled by gh-aw) and are copied to `.github/workflows/trigger-.yml` by `scripts/dogfood.sh` for dogfooding when the workflow is not listed in `EXCLUDED_WORKFLOWS` (see `scripts/dogfood.sh` for the current list). Consumer repos copy a workflow's `example.yml` into their `.github/workflows/` directory and customize the `with:` inputs. The `uses:` path already points to the remote compiled workflow. diff --git a/gh-agent-workflows/README.md b/gh-agent-workflows/README.md index d4f7d835..a103f37e 100644 --- a/gh-agent-workflows/README.md +++ b/gh-agent-workflows/README.md @@ -7,6 +7,34 @@ https://elastic.github.io/ai-github-actions/workflows/gh-agent-workflows/ Each workflow folder includes an `example.yml` trigger and a README covering inputs and safe outputs. +## Base Workflows + +Two generic base workflows let you build custom detectors and fixers without writing a full workflow from scratch. Provide your domain-specific instructions via `additional-instructions`: + +| Workflow | Role | Output | +| --- | --- | --- | +| [Scheduled Audit](scheduled-audit/) | Detect issues and file reports | `create-issue` | +| [Scheduled Fix](scheduled-fix/) | Fix reported issues | `create-pull-request` | + +These pair together: a Scheduled Audit finds problems, a Scheduled Fix resolves them. + +## Specialized Workflows + +Pre-built workflows with domain-specific prompts. These import the same base fragments (`scheduled-audit.md` / `scheduled-fix.md`) and layer specialized instructions on top. + +**Detectors** (file issues): +- [Bug Hunter](bug-hunter/) — find reproducible bugs +- [Text Auditor](text-auditor/) — find text quality issues +- [Code Duplication Detector](code-duplication-detector/) — find duplicate code +- [Breaking Change Detector](breaking-change-detector/) — find breaking changes +- [Docs Patrol](docs-patrol/) — detect stale documentation +- [Stale Issues](stale-issues/) — detect stale issues + +**Fixers** (create PRs): +- [Bug Exterminator](bug-exterminator/) — fix bug-hunter issues +- [Text Beautifier](text-beautifier/) — fix text-auditor issues +- [Code Duplication Fixer](code-duplication-fixer/) — fix code-duplication-detector issues + ## Quick setup script Run from the repository you want to configure: @@ -24,7 +52,7 @@ Default workflows: - `issue-triage` - `mention-in-issue` - `mention-in-pr` -- `pr-ci-detective` +- `pr-actions-detective` Use `--workflows` (comma-separated) to override the defaults, `--skip-secret` to set the secret manually, `--continuous-improvement` to also install selected continuous improvement @@ -34,11 +62,11 @@ workflows, or `--repo OWNER/REPO` when auto-detection is not available. - `bug-hunter` - `bug-exterminator` - `code-simplifier` -- `docs-drift` -- `docs-new-contributor-review` +- `docs-patrol` +- `newbie-contributor-patrol` - `small-problem-fixer` - `stale-issues` -- `test-improvement` -- `breaking-change-detect` -- `semantic-function-clustering` +- `test-improver` +- `breaking-change-detector` +- `code-duplication-detector` - `update-pr-body` diff --git a/gh-agent-workflows/breaking-change-detect/README.md b/gh-agent-workflows/breaking-change-detector/README.md similarity index 88% rename from gh-agent-workflows/breaking-change-detect/README.md rename to gh-agent-workflows/breaking-change-detector/README.md index ad4469a7..b6315fbb 100644 --- a/gh-agent-workflows/breaking-change-detect/README.md +++ b/gh-agent-workflows/breaking-change-detector/README.md @@ -1,4 +1,4 @@ -# Breaking Change Detect +# Breaking Change Detector Detect undocumented breaking changes in public interfaces. @@ -10,8 +10,8 @@ Scans recent commits (1-day lookback, 3-day on Mondays) for public interface or ```bash mkdir -p .github/workflows && curl -sL \ - https://raw.githubusercontent.com/elastic/ai-github-actions/v0/gh-agent-workflows/breaking-change-detect/example.yml \ - -o .github/workflows/breaking-change-detect.yml + https://raw.githubusercontent.com/elastic/ai-github-actions/v0/gh-agent-workflows/breaking-change-detector/example.yml \ + -o .github/workflows/breaking-change-detector.yml ``` See [example.yml](example.yml) for the full workflow file. diff --git a/gh-agent-workflows/breaking-change-detect/example.yml b/gh-agent-workflows/breaking-change-detector/example.yml similarity index 81% rename from gh-agent-workflows/breaking-change-detect/example.yml rename to gh-agent-workflows/breaking-change-detector/example.yml index 2ac23351..9e269edf 100644 --- a/gh-agent-workflows/breaking-change-detect/example.yml +++ b/gh-agent-workflows/breaking-change-detector/example.yml @@ -1,4 +1,4 @@ -name: Breaking Change Detect +name: Breaking Change Detector on: schedule: - cron: "0 13 * * 1-5" @@ -11,6 +11,6 @@ permissions: jobs: run: - uses: elastic/ai-github-actions/.github/workflows/gh-aw-breaking-change-detect.lock.yml@v0 + uses: elastic/ai-github-actions/.github/workflows/gh-aw-breaking-change-detector.lock.yml@v0 secrets: COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} diff --git a/gh-agent-workflows/semantic-function-clustering/README.md b/gh-agent-workflows/code-duplication-detector/README.md similarity index 89% rename from gh-agent-workflows/semantic-function-clustering/README.md rename to gh-agent-workflows/code-duplication-detector/README.md index 05bb860e..d3ec3293 100644 --- a/gh-agent-workflows/semantic-function-clustering/README.md +++ b/gh-agent-workflows/code-duplication-detector/README.md @@ -1,4 +1,4 @@ -# Semantic Function Clustering +# Code Duplication Detector Analyze code for semantic function clustering and refactoring opportunities. @@ -10,8 +10,8 @@ Scans source files (by language or custom glob) to find semantically related fun ```bash mkdir -p .github/workflows && curl -sL \ - https://raw.githubusercontent.com/elastic/ai-github-actions/v0/gh-agent-workflows/semantic-function-clustering/example.yml \ - -o .github/workflows/semantic-function-clustering.yml + https://raw.githubusercontent.com/elastic/ai-github-actions/v0/gh-agent-workflows/code-duplication-detector/example.yml \ + -o .github/workflows/code-duplication-detector.yml ``` See [example.yml](example.yml) for the full workflow file. diff --git a/gh-agent-workflows/semantic-function-clustering/example.yml b/gh-agent-workflows/code-duplication-detector/example.yml similarity index 66% rename from gh-agent-workflows/semantic-function-clustering/example.yml rename to gh-agent-workflows/code-duplication-detector/example.yml index 43cce569..6f6de478 100644 --- a/gh-agent-workflows/semantic-function-clustering/example.yml +++ b/gh-agent-workflows/code-duplication-detector/example.yml @@ -1,4 +1,4 @@ -name: Semantic Function Clustering +name: Code Duplication Detector on: schedule: - cron: "0 12 * * 1-5" @@ -11,7 +11,7 @@ permissions: jobs: run: - uses: elastic/ai-github-actions/.github/workflows/gh-aw-semantic-function-clustering.lock.yml@v0 + uses: elastic/ai-github-actions/.github/workflows/gh-aw-code-duplication-detector.lock.yml@v0 with: languages: "go,python,typescript" secrets: diff --git a/gh-agent-workflows/code-duplication-fixer/README.md b/gh-agent-workflows/code-duplication-fixer/README.md new file mode 100644 index 00000000..5133c883 --- /dev/null +++ b/gh-agent-workflows/code-duplication-fixer/README.md @@ -0,0 +1,40 @@ +# Code Duplication Fixer + +Fix code-duplication-detector issues by consolidating duplicate functions and opening a focused PR. + +## How it works + +Picks up open issues filed by the Code Duplication Detector (labeled `refactor` or with `[refactor]` in the title), selects one well-scoped finding, refactors the duplicate or misplaced code, runs tests, and opens a PR. Only acts on safe, behavior-preserving refactors. Most runs end with `noop`. + +## Quick Install + +```bash +mkdir -p .github/workflows && curl -sL \ + https://raw.githubusercontent.com/elastic/ai-github-actions/v0/gh-agent-workflows/code-duplication-fixer/example.yml \ + -o .github/workflows/code-duplication-fixer.yml +``` + +See [example.yml](example.yml) for the full workflow file. + +## Trigger + +| Event | Schedule | +| --- | --- | +| `schedule` | Weekdays | +| `workflow_dispatch` | Manual | + +## Inputs + +| Input | Description | Required | Default | +| --- | --- | --- | --- | +| `additional-instructions` | Repo-specific instructions appended to the agent prompt | No | `""` | +| `setup-commands` | Shell commands run before the agent starts | No | `""` | +| `allowed-bot-users` | Allowlisted bot actor usernames (comma-separated) | No | `github-actions[bot]` | + +## Safe Outputs + +- `create-pull-request` — open a PR with the refactor (max 1) + +## Pairing + +This workflow is the read-write companion to [Code Duplication Detector](../code-duplication-detector/). The detector finds issues; the fixer consolidates the duplicates. diff --git a/gh-agent-workflows/code-duplication-fixer/example.yml b/gh-agent-workflows/code-duplication-fixer/example.yml new file mode 100644 index 00000000..2473247c --- /dev/null +++ b/gh-agent-workflows/code-duplication-fixer/example.yml @@ -0,0 +1,16 @@ +name: Code Duplication Fixer +on: + schedule: + - cron: "0 14 * * 1-5" + workflow_dispatch: + +permissions: + contents: read + issues: read + pull-requests: write + +jobs: + run: + uses: elastic/ai-github-actions/.github/workflows/gh-aw-code-duplication-fixer.lock.yml@v0 + secrets: + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} diff --git a/gh-agent-workflows/docs-new-contributor-review-external/example.yml b/gh-agent-workflows/docs-new-contributor-review-external/example.yml deleted file mode 100644 index 5ecae7ad..00000000 --- a/gh-agent-workflows/docs-new-contributor-review-external/example.yml +++ /dev/null @@ -1,16 +0,0 @@ -name: Docs New Contributor Review External -on: - schedule: - - cron: "0 14 * * 1" - workflow_dispatch: - -permissions: - contents: read - issues: write - pull-requests: read - -jobs: - run: - uses: elastic/ai-github-actions/.github/workflows/gh-aw-docs-new-contributor-review-external.lock.yml@v0 - secrets: - COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} diff --git a/gh-agent-workflows/docs-drift-external/README.md b/gh-agent-workflows/docs-patrol-external/README.md similarity index 67% rename from gh-agent-workflows/docs-drift-external/README.md rename to gh-agent-workflows/docs-patrol-external/README.md index 741bf9b0..bb262cf0 100644 --- a/gh-agent-workflows/docs-drift-external/README.md +++ b/gh-agent-workflows/docs-patrol-external/README.md @@ -1,17 +1,17 @@ -# Docs Drift External +# Docs Patrol External Detect code changes that require updates to published Elastic documentation, `applies_to` tags, or backports. ## How it works -Like Docs Drift, but focuses on changes that require updates to published Elastic documentation on `elastic.co/docs`. Also flags features that need `applies_to` tag updates or documentation backports to earlier release branches. +Like Docs Patrol, but focuses on changes that require updates to published Elastic documentation on `elastic.co/docs`. Also flags features that need `applies_to` tag updates or documentation backports to earlier release branches. ## Quick Install ```bash mkdir -p .github/workflows && curl -sL \ - https://raw.githubusercontent.com/elastic/ai-github-actions/v0/gh-agent-workflows/docs-drift-external/example.yml \ - -o .github/workflows/docs-drift-external.yml + https://raw.githubusercontent.com/elastic/ai-github-actions/v0/gh-agent-workflows/docs-patrol-external/example.yml \ + -o .github/workflows/docs-patrol-external.yml ``` See [example.yml](example.yml) for the full workflow file. @@ -34,4 +34,4 @@ See [example.yml](example.yml) for the full workflow file. ## Safe Outputs -- `create-issue` — file an external docs drift report (max 1, auto-closes older reports) +- `create-issue` — file an external docs patrol report (max 1, auto-closes older reports) diff --git a/gh-agent-workflows/docs-drift-external/example.yml b/gh-agent-workflows/docs-patrol-external/example.yml similarity index 83% rename from gh-agent-workflows/docs-drift-external/example.yml rename to gh-agent-workflows/docs-patrol-external/example.yml index 4d5af2cc..62003801 100644 --- a/gh-agent-workflows/docs-drift-external/example.yml +++ b/gh-agent-workflows/docs-patrol-external/example.yml @@ -1,4 +1,4 @@ -name: Docs Drift External +name: Docs Patrol External on: schedule: - cron: "0 14 * * 1-5" @@ -11,6 +11,6 @@ permissions: jobs: run: - uses: elastic/ai-github-actions/.github/workflows/gh-aw-docs-drift-external.lock.yml@v0 + uses: elastic/ai-github-actions/.github/workflows/gh-aw-docs-patrol-external.lock.yml@v0 secrets: COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} diff --git a/gh-agent-workflows/docs-drift/README.md b/gh-agent-workflows/docs-patrol/README.md similarity index 86% rename from gh-agent-workflows/docs-drift/README.md rename to gh-agent-workflows/docs-patrol/README.md index cfdbc07a..9f759b90 100644 --- a/gh-agent-workflows/docs-drift/README.md +++ b/gh-agent-workflows/docs-patrol/README.md @@ -1,4 +1,4 @@ -# Docs Drift +# Docs Patrol Detect code changes that require documentation updates and file issues. @@ -10,8 +10,8 @@ Scans recent commits (7-day lookback by default) for public API or behavioral ch ```bash mkdir -p .github/workflows && curl -sL \ - https://raw.githubusercontent.com/elastic/ai-github-actions/v0/gh-agent-workflows/docs-drift/example.yml \ - -o .github/workflows/docs-drift.yml + https://raw.githubusercontent.com/elastic/ai-github-actions/v0/gh-agent-workflows/docs-patrol/example.yml \ + -o .github/workflows/docs-patrol.yml ``` See [example.yml](example.yml) for the full workflow file. @@ -34,4 +34,4 @@ See [example.yml](example.yml) for the full workflow file. ## Safe Outputs -- `create-issue` — file a docs drift report (max 1, auto-closes older reports) +- `create-issue` — file a docs patrol report (max 1, auto-closes older reports) diff --git a/gh-agent-workflows/docs-drift/example.yml b/gh-agent-workflows/docs-patrol/example.yml similarity index 88% rename from gh-agent-workflows/docs-drift/example.yml rename to gh-agent-workflows/docs-patrol/example.yml index fa6ed85a..9e926993 100644 --- a/gh-agent-workflows/docs-drift/example.yml +++ b/gh-agent-workflows/docs-patrol/example.yml @@ -1,4 +1,4 @@ -name: Docs Drift +name: Docs Patrol on: schedule: - cron: "0 14 * * 1-5" @@ -11,6 +11,6 @@ permissions: jobs: run: - uses: elastic/ai-github-actions/.github/workflows/gh-aw-docs-drift.lock.yml@v0 + uses: elastic/ai-github-actions/.github/workflows/gh-aw-docs-patrol.lock.yml@v0 secrets: COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} diff --git a/gh-agent-workflows/flaky-test-triage/README.md b/gh-agent-workflows/flaky-test-investigator/README.md similarity index 90% rename from gh-agent-workflows/flaky-test-triage/README.md rename to gh-agent-workflows/flaky-test-investigator/README.md index 517f3246..2212fb73 100644 --- a/gh-agent-workflows/flaky-test-triage/README.md +++ b/gh-agent-workflows/flaky-test-investigator/README.md @@ -1,4 +1,4 @@ -# Flaky Test Triage +# Flaky Test Investigator Investigate flaky tests using open issues and failed CI runs, then file a single triage report issue with root-cause-first recommendations. @@ -10,8 +10,8 @@ Discovers flakiness labels, searches open issues for flaky-test reports, and ins ````bash mkdir -p .github/workflows && curl -sL \ - https://raw.githubusercontent.com/elastic/ai-github-actions/v0/gh-agent-workflows/flaky-test-triage/example.yml \ - -o .github/workflows/flaky-test-triage.yml + https://raw.githubusercontent.com/elastic/ai-github-actions/v0/gh-agent-workflows/flaky-test-investigator/example.yml \ + -o .github/workflows/flaky-test-investigator.yml ```` See [example.yml](example.yml) for the full workflow file. diff --git a/gh-agent-workflows/flaky-test-triage/example.yml b/gh-agent-workflows/flaky-test-investigator/example.yml similarity index 90% rename from gh-agent-workflows/flaky-test-triage/example.yml rename to gh-agent-workflows/flaky-test-investigator/example.yml index 39c64ed4..67ba337e 100644 --- a/gh-agent-workflows/flaky-test-triage/example.yml +++ b/gh-agent-workflows/flaky-test-investigator/example.yml @@ -1,4 +1,4 @@ -name: Flaky Test Triage +name: Flaky Test Investigator on: schedule: - cron: "0 14 * * 1-5" @@ -19,6 +19,6 @@ jobs: github.event_name != 'workflow_run' || (github.event.workflow_run.conclusion == 'failure' && toJSON(github.event.workflow_run.pull_requests) != '[]') - uses: elastic/ai-github-actions/.github/workflows/gh-aw-flaky-test-triage.lock.yml@v0 + uses: elastic/ai-github-actions/.github/workflows/gh-aw-flaky-test-investigator.lock.yml@v0 secrets: COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} diff --git a/gh-agent-workflows/issue-triage-pr/README.md b/gh-agent-workflows/issue-fixer/README.md similarity index 89% rename from gh-agent-workflows/issue-triage-pr/README.md rename to gh-agent-workflows/issue-fixer/README.md index a9dd4f74..d7f0c9dc 100644 --- a/gh-agent-workflows/issue-triage-pr/README.md +++ b/gh-agent-workflows/issue-fixer/README.md @@ -1,4 +1,4 @@ -# Issue Triage (with PR) +# Issue Fixer Investigate new issues and provide actionable triage analysis. For straightforward fixes, implement and open a draft PR. @@ -10,8 +10,8 @@ Same as Issue Triage, but also implements the fix and opens a draft PR when the ```bash mkdir -p .github/workflows && curl -sL \ - https://raw.githubusercontent.com/elastic/ai-github-actions/v0/gh-agent-workflows/issue-triage-pr/example.yml \ - -o .github/workflows/issue-triage-pr.yml + https://raw.githubusercontent.com/elastic/ai-github-actions/v0/gh-agent-workflows/issue-fixer/example.yml \ + -o .github/workflows/issue-fixer.yml ``` See [example.yml](example.yml) for the full workflow file. diff --git a/gh-agent-workflows/issue-triage-pr/example.yml b/gh-agent-workflows/issue-fixer/example.yml similarity index 84% rename from gh-agent-workflows/issue-triage-pr/example.yml rename to gh-agent-workflows/issue-fixer/example.yml index 0c6ee060..375f049c 100644 --- a/gh-agent-workflows/issue-triage-pr/example.yml +++ b/gh-agent-workflows/issue-fixer/example.yml @@ -1,4 +1,4 @@ -name: Issue Triage (with PR) +name: Issue Fixer on: issues: types: [opened] @@ -11,6 +11,6 @@ permissions: jobs: run: - uses: elastic/ai-github-actions/.github/workflows/gh-aw-issue-triage-pr.lock.yml@v0 + uses: elastic/ai-github-actions/.github/workflows/gh-aw-issue-fixer.lock.yml@v0 secrets: COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} diff --git a/gh-agent-workflows/newbie-contributor-fixer/README.md b/gh-agent-workflows/newbie-contributor-fixer/README.md new file mode 100644 index 00000000..269fafb6 --- /dev/null +++ b/gh-agent-workflows/newbie-contributor-fixer/README.md @@ -0,0 +1,40 @@ +# Newbie Contributor Fixer + +Fix newbie-contributor-patrol issues by improving documentation and opening a focused PR. + +## How it works + +Picks up open issues filed by the Newbie Contributor Patrol (labeled `newbie-contributor` or with `[newbie-contributor]` in the title), applies the suggested documentation improvements, and opens a PR. Focuses on filling gaps in the contributor onboarding path — missing prerequisites, broken commands, undocumented requirements. Most runs end with `noop`. + +## Quick Install + +```bash +mkdir -p .github/workflows && curl -sL \ + https://raw.githubusercontent.com/elastic/ai-github-actions/v0/gh-agent-workflows/newbie-contributor-fixer/example.yml \ + -o .github/workflows/newbie-contributor-fixer.yml +``` + +See [example.yml](example.yml) for the full workflow file. + +## Trigger + +| Event | Schedule | +| --- | --- | +| `schedule` | Weekdays | +| `workflow_dispatch` | Manual | + +## Inputs + +| Input | Description | Required | Default | +| --- | --- | --- | --- | +| `additional-instructions` | Repo-specific instructions appended to the agent prompt | No | `""` | +| `setup-commands` | Shell commands run before the agent starts | No | `""` | +| `allowed-bot-users` | Allowlisted bot actor usernames (comma-separated) | No | `github-actions[bot]` | + +## Safe Outputs + +- `create-pull-request` — open a PR with documentation fixes (max 1) + +## Pairing + +This workflow is the fixer half. Pair with [Newbie Contributor Patrol](../newbie-contributor-patrol/) to detect the issues it fixes. diff --git a/gh-agent-workflows/newbie-contributor-fixer/example.yml b/gh-agent-workflows/newbie-contributor-fixer/example.yml new file mode 100644 index 00000000..2e747899 --- /dev/null +++ b/gh-agent-workflows/newbie-contributor-fixer/example.yml @@ -0,0 +1,16 @@ +name: Newbie Contributor Fixer +on: + schedule: + - cron: "0 14 * * 1-5" + workflow_dispatch: + +permissions: + contents: write + issues: write + pull-requests: write + +jobs: + run: + uses: elastic/ai-github-actions/.github/workflows/gh-aw-newbie-contributor-fixer.lock.yml@v0 + secrets: + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} diff --git a/gh-agent-workflows/docs-new-contributor-review-external/README.md b/gh-agent-workflows/newbie-contributor-patrol-external/README.md similarity index 56% rename from gh-agent-workflows/docs-new-contributor-review-external/README.md rename to gh-agent-workflows/newbie-contributor-patrol-external/README.md index 81e0b2a3..f5217ca7 100644 --- a/gh-agent-workflows/docs-new-contributor-review-external/README.md +++ b/gh-agent-workflows/newbie-contributor-patrol-external/README.md @@ -1,17 +1,17 @@ -# Docs New Contributor Review External +# Newbie Contributor Patrol External -Review docs from a new contributor perspective, cross-referencing against published Elastic documentation. +Review docs from a new contributor perspective, cross-referencing published Elastic documentation. ## How it works -Same as Docs New Contributor Review, but also cross-references the repo's documentation against published Elastic docs on `elastic.co/docs`, flagging contradictions that would block an external contributor. +Like Newbie Contributor Patrol, but also cross-references the repo's documentation against published Elastic documentation on `elastic.co/docs`. Contradictions between the repo and published docs are treated as blocking issues. ## Quick Install ```bash mkdir -p .github/workflows && curl -sL \ - https://raw.githubusercontent.com/elastic/ai-github-actions/v0/gh-agent-workflows/docs-new-contributor-review-external/example.yml \ - -o .github/workflows/docs-new-contributor-review-external.yml + https://raw.githubusercontent.com/elastic/ai-github-actions/v0/gh-agent-workflows/newbie-contributor-patrol-external/example.yml \ + -o .github/workflows/newbie-contributor-patrol-external.yml ``` See [example.yml](example.yml) for the full workflow file. @@ -20,7 +20,7 @@ See [example.yml](example.yml) for the full workflow file. | Event | Schedule | | --- | --- | -| `schedule` | Weekly | +| `schedule` | Weekly (Monday) | | `workflow_dispatch` | Manual | ## Inputs @@ -33,4 +33,4 @@ See [example.yml](example.yml) for the full workflow file. ## Safe Outputs -- `create-issue` — file a docs improvement report with external docs findings (max 1, auto-closes older reports) +- `create-issue` — file an external new contributor docs review (max 1, auto-closes older reports) diff --git a/gh-agent-workflows/docs-new-contributor-review/example.yml b/gh-agent-workflows/newbie-contributor-patrol-external/example.yml similarity index 53% rename from gh-agent-workflows/docs-new-contributor-review/example.yml rename to gh-agent-workflows/newbie-contributor-patrol-external/example.yml index 962b7cbb..a969b23a 100644 --- a/gh-agent-workflows/docs-new-contributor-review/example.yml +++ b/gh-agent-workflows/newbie-contributor-patrol-external/example.yml @@ -1,7 +1,7 @@ -name: Docs New Contributor Review +name: Newbie Contributor Patrol External on: schedule: - - cron: "0 14 * * 1" + - cron: "0 11 * * 1" workflow_dispatch: permissions: @@ -11,6 +11,6 @@ permissions: jobs: run: - uses: elastic/ai-github-actions/.github/workflows/gh-aw-docs-new-contributor-review.lock.yml@v0 + uses: elastic/ai-github-actions/.github/workflows/gh-aw-newbie-contributor-patrol-external.lock.yml@v0 secrets: COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} diff --git a/gh-agent-workflows/docs-new-contributor-review/README.md b/gh-agent-workflows/newbie-contributor-patrol/README.md similarity index 50% rename from gh-agent-workflows/docs-new-contributor-review/README.md rename to gh-agent-workflows/newbie-contributor-patrol/README.md index 0554874f..fe68c004 100644 --- a/gh-agent-workflows/docs-new-contributor-review/README.md +++ b/gh-agent-workflows/newbie-contributor-patrol/README.md @@ -1,17 +1,17 @@ -# Docs New Contributor Review +# Newbie Contributor Patrol Review docs from a new contributor perspective and file high-impact issues. ## How it works -Simulates the onboarding experience of a first-time contributor — reading setup docs and following the quick-start path as far as possible without secrets or admin privileges. Only files an issue for **high-impact** blockers (missing steps, broken commands, undocumented prerequisites). +Reads all contributor-facing documentation (README, CONTRIBUTING, DEVELOPING, etc.) as if it were a new contributor's first encounter with the project. Follows getting-started paths, checks for missing prerequisites, and flags blocking gaps. Only files issues for high-impact problems; most runs end with `noop`. ## Quick Install ```bash mkdir -p .github/workflows && curl -sL \ - https://raw.githubusercontent.com/elastic/ai-github-actions/v0/gh-agent-workflows/docs-new-contributor-review/example.yml \ - -o .github/workflows/docs-new-contributor-review.yml + https://raw.githubusercontent.com/elastic/ai-github-actions/v0/gh-agent-workflows/newbie-contributor-patrol/example.yml \ + -o .github/workflows/newbie-contributor-patrol.yml ``` See [example.yml](example.yml) for the full workflow file. @@ -20,7 +20,7 @@ See [example.yml](example.yml) for the full workflow file. | Event | Schedule | | --- | --- | -| `schedule` | Weekly | +| `schedule` | Weekly (Monday) | | `workflow_dispatch` | Manual | ## Inputs @@ -33,4 +33,8 @@ See [example.yml](example.yml) for the full workflow file. ## Safe Outputs -- `create-issue` — file a docs improvement report (max 1, auto-closes older reports) +- `create-issue` — file a new contributor docs review (max 1, auto-closes older reports) + +## Pairing + +This workflow is the detector half. Pair with [Newbie Contributor Fixer](../newbie-contributor-fixer/) to automatically fix the issues it finds. diff --git a/.github/workflows/trigger-docs-new-contributor-review.yml b/gh-agent-workflows/newbie-contributor-patrol/example.yml similarity index 55% rename from .github/workflows/trigger-docs-new-contributor-review.yml rename to gh-agent-workflows/newbie-contributor-patrol/example.yml index b3e55884..7d14046f 100644 --- a/.github/workflows/trigger-docs-new-contributor-review.yml +++ b/gh-agent-workflows/newbie-contributor-patrol/example.yml @@ -1,7 +1,7 @@ -name: Trigger Docs New Contributor Review +name: Newbie Contributor Patrol on: schedule: - - cron: "0 14 * * 1" + - cron: "0 11 * * 1" workflow_dispatch: permissions: @@ -11,6 +11,6 @@ permissions: jobs: run: - uses: ./.github/workflows/gh-aw-docs-new-contributor-review.lock.yml + uses: elastic/ai-github-actions/.github/workflows/gh-aw-newbie-contributor-patrol.lock.yml@v0 secrets: COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} diff --git a/gh-agent-workflows/pr-ci-detective/README.md b/gh-agent-workflows/pr-actions-detective/README.md similarity index 89% rename from gh-agent-workflows/pr-ci-detective/README.md rename to gh-agent-workflows/pr-actions-detective/README.md index 5aa2e653..702584b3 100644 --- a/gh-agent-workflows/pr-ci-detective/README.md +++ b/gh-agent-workflows/pr-actions-detective/README.md @@ -1,4 +1,4 @@ -# PR CI Detective +# PR Actions Detective Analyze failed PR checks and report findings (read-only). @@ -10,8 +10,8 @@ Triggered automatically when a CI workflow fails on a PR. Reads the failed job l ````bash mkdir -p .github/workflows && curl -sL \ - https://raw.githubusercontent.com/elastic/ai-github-actions/v0/gh-agent-workflows/pr-ci-detective/example.yml \ - -o .github/workflows/pr-ci-detective.yml + https://raw.githubusercontent.com/elastic/ai-github-actions/v0/gh-agent-workflows/pr-actions-detective/example.yml \ + -o .github/workflows/pr-actions-detective.yml ```` See [example.yml](example.yml) for the full workflow file. diff --git a/gh-agent-workflows/pr-ci-detective/example.yml b/gh-agent-workflows/pr-actions-detective/example.yml similarity index 76% rename from gh-agent-workflows/pr-ci-detective/example.yml rename to gh-agent-workflows/pr-actions-detective/example.yml index 08a9b2ec..cd6666ad 100644 --- a/gh-agent-workflows/pr-ci-detective/example.yml +++ b/gh-agent-workflows/pr-actions-detective/example.yml @@ -1,4 +1,4 @@ -name: PR CI Detective +name: PR Actions Detective on: workflow_run: workflows: ["CI", "Build", "Test"] @@ -15,6 +15,6 @@ jobs: if: >- github.event.workflow_run.conclusion == 'failure' && toJSON(github.event.workflow_run.pull_requests) != '[]' - uses: elastic/ai-github-actions/.github/workflows/gh-aw-pr-ci-detective.lock.yml@v0 + uses: elastic/ai-github-actions/.github/workflows/gh-aw-pr-actions-detective.lock.yml@v0 secrets: COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} diff --git a/gh-agent-workflows/pr-ci-fixer/README.md b/gh-agent-workflows/pr-actions-fixer/README.md similarity index 91% rename from gh-agent-workflows/pr-ci-fixer/README.md rename to gh-agent-workflows/pr-actions-fixer/README.md index f8001620..ff8376f5 100644 --- a/gh-agent-workflows/pr-ci-fixer/README.md +++ b/gh-agent-workflows/pr-actions-fixer/README.md @@ -1,4 +1,4 @@ -# PR CI Fixer +# PR Actions Fixer Opt-in fixer for failed PR checks that can push safe, targeted changes. @@ -10,8 +10,8 @@ Manually triggered with a specific failed workflow run ID. Reads the failed job ````bash mkdir -p .github/workflows && curl -sL \ - https://raw.githubusercontent.com/elastic/ai-github-actions/v0/gh-agent-workflows/pr-ci-fixer/example.yml \ - -o .github/workflows/pr-ci-fixer.yml + https://raw.githubusercontent.com/elastic/ai-github-actions/v0/gh-agent-workflows/pr-actions-fixer/example.yml \ + -o .github/workflows/pr-actions-fixer.yml ```` See [example.yml](example.yml) for the full workflow file. diff --git a/gh-agent-workflows/pr-ci-fixer/example.yml b/gh-agent-workflows/pr-actions-fixer/example.yml similarity index 73% rename from gh-agent-workflows/pr-ci-fixer/example.yml rename to gh-agent-workflows/pr-actions-fixer/example.yml index 8fda869c..4fcbfc64 100644 --- a/gh-agent-workflows/pr-ci-fixer/example.yml +++ b/gh-agent-workflows/pr-actions-fixer/example.yml @@ -1,4 +1,4 @@ -name: PR CI Fixer +name: PR Actions Fixer on: workflow_dispatch: inputs: @@ -11,11 +11,11 @@ permissions: actions: read contents: write issues: write - pull-requests: read + pull-requests: write jobs: run: - uses: elastic/ai-github-actions/.github/workflows/gh-aw-pr-ci-fixer.lock.yml@v0 + uses: elastic/ai-github-actions/.github/workflows/gh-aw-pr-actions-fixer.lock.yml@v0 with: workflow-run-id: ${{ inputs.workflow-run-id }} secrets: diff --git a/gh-agent-workflows/pr-review-fork/README.md b/gh-agent-workflows/pr-review-fork/README.md index af7b69b2..1a3a6349 100644 --- a/gh-agent-workflows/pr-review-fork/README.md +++ b/gh-agent-workflows/pr-review-fork/README.md @@ -43,7 +43,7 @@ See [example.yml](example.yml) for the full workflow file. | `additional-instructions` | Repo-specific instructions appended to the agent prompt | No | `""` | | `setup-commands` | Shell commands run before the agent starts — **do not run fork code here** | No | `""` | | `intensity` | Review intensity (`conservative`, `balanced`, `aggressive`) | No | `balanced` | -| `minimum-severity` | Minimum severity for inline comments (`critical`, `high`, `medium`, `low`, `nitpick`) | No | `low` | +| `minimum_severity` | Minimum severity for inline comments (`critical`, `high`, `medium`, `low`, `nitpick`) | No | `low` | ## Safe Outputs diff --git a/gh-agent-workflows/pr-review/README.md b/gh-agent-workflows/pr-review/README.md index 4121f88e..fd945a04 100644 --- a/gh-agent-workflows/pr-review/README.md +++ b/gh-agent-workflows/pr-review/README.md @@ -30,7 +30,7 @@ See [example.yml](example.yml) for the full workflow file. | `setup-commands` | Shell commands run before the agent starts | No | `""` | | `allowed-bot-users` | Allowlisted bot actor usernames (comma-separated) | No | `github-actions[bot]` | | `intensity` | Review intensity (`conservative`, `balanced`, `aggressive`) | No | `balanced` | -| `minimum-severity` | Minimum severity for inline comments (`critical`, `high`, `medium`, `low`, `nitpick`) | No | `low` | +| `minimum_severity` | Minimum severity for inline comments (`critical`, `high`, `medium`, `low`, `nitpick`) | No | `low` | ## Safe Outputs diff --git a/gh-agent-workflows/scheduled-audit/README.md b/gh-agent-workflows/scheduled-audit/README.md new file mode 100644 index 00000000..c08623f8 --- /dev/null +++ b/gh-agent-workflows/scheduled-audit/README.md @@ -0,0 +1,44 @@ +# Scheduled Audit + +Generic base workflow for scheduled audits — investigate the repository and file an issue when something needs attention. + +## How it works + +The audit agent follows a standard 4-step process (gather context, analyze, quality gate, report) defined by the `scheduled-audit` fragment. You provide the **Report Assignment** via the `additional-instructions` input, which tells the agent what to investigate, what to look for, and how to report findings. + +This is the base workflow. For domain-specific audits, see the specialized workflows: +- [Bug Hunter](../bug-hunter/) — find reproducible bugs +- [Text Auditor](../text-auditor/) — find text quality issues +- [Code Duplication Detector](../code-duplication-detector/) — find duplicate code +- [Breaking Change Detector](../breaking-change-detector/) — find breaking changes + +## Quick Install + +```bash +mkdir -p .github/workflows && curl -sL \ + https://raw.githubusercontent.com/elastic/ai-github-actions/v0/gh-agent-workflows/scheduled-audit/example.yml \ + -o .github/workflows/scheduled-audit.yml +``` + +See [example.yml](example.yml) for the full workflow file. You **must** customize the `additional-instructions` input. + +## Trigger + +| Event | Schedule | +| --- | --- | +| `schedule` | Weekdays | +| `workflow_dispatch` | Manual | + +## Inputs + +| Input | Description | Required | Default | +| --- | --- | --- | --- | +| `additional-instructions` | What the audit agent should investigate (the Report Assignment) | **Yes** | — | +| `issue-title-prefix` | Title prefix for created issues, e.g. `[my-audit]` | **Yes** | — | +| `issue-label` | Label to apply to created issues | No | `""` | +| `setup-commands` | Shell commands run before the agent starts | No | `""` | +| `allowed-bot-users` | Allowlisted bot actor usernames (comma-separated) | No | `github-actions[bot]` | + +## Safe Outputs + +- `create-issue` — file an audit report (max 1, auto-closes older reports) diff --git a/gh-agent-workflows/scheduled-audit/example.yml b/gh-agent-workflows/scheduled-audit/example.yml new file mode 100644 index 00000000..31f70ced --- /dev/null +++ b/gh-agent-workflows/scheduled-audit/example.yml @@ -0,0 +1,30 @@ +name: Scheduled Audit +on: + schedule: + - cron: "0 11 * * 1-5" + workflow_dispatch: + +permissions: + contents: read + issues: write + pull-requests: read + +jobs: + run: + uses: elastic/ai-github-actions/.github/workflows/gh-aw-scheduled-audit.lock.yml@v0 + with: + issue-title-prefix: "[my-audit]" + issue-label: "my-audit" + additional-instructions: | + Describe what the audit agent should investigate here. + + ### Data Gathering + - What to examine (recent commits, open PRs, config files, etc.) + + ### What to Look For + - What constitutes a finding worth reporting + + ### What to Skip + - What to ignore + secrets: + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} diff --git a/gh-agent-workflows/scheduled-fix/README.md b/gh-agent-workflows/scheduled-fix/README.md new file mode 100644 index 00000000..96bd5399 --- /dev/null +++ b/gh-agent-workflows/scheduled-fix/README.md @@ -0,0 +1,48 @@ +# Scheduled Fix + +Generic base workflow for scheduled fixers — pick up an open issue and create a focused PR that addresses it. + +## How it works + +The fix agent follows a standard 5-step process (gather candidates, select target, implement, quality gate, create PR) defined by the `scheduled-fix` fragment. You provide the **Fix Assignment** via the `additional-instructions` input, which tells the agent how to find issues, what kind of changes to make, and any domain-specific constraints. + +This is the base workflow. For domain-specific fixers, see the specialized workflows: +- [Bug Exterminator](../bug-exterminator/) — fix bug-hunter issues +- [Text Beautifier](../text-beautifier/) — fix text-auditor issues +- [Code Duplication Fixer](../code-duplication-fixer/) — fix code-duplication-detector issues + +## Quick Install + +```bash +mkdir -p .github/workflows && curl -sL \ + https://raw.githubusercontent.com/elastic/ai-github-actions/v0/gh-agent-workflows/scheduled-fix/example.yml \ + -o .github/workflows/scheduled-fix.yml +``` + +See [example.yml](example.yml) for the full workflow file. You **must** customize the `additional-instructions` input. + +## Trigger + +| Event | Schedule | +| --- | --- | +| `schedule` | Weekdays | +| `workflow_dispatch` | Manual | + +## Inputs + +| Input | Description | Required | Default | +| --- | --- | --- | --- | +| `additional-instructions` | Domain-specific fix instructions (the Fix Assignment) | **Yes** | — | +| `issue-title-prefix` | Title prefix to search for in open issues, e.g. `[my-audit]` | **Yes** | — | +| `issue-label` | Label to search for in open issues | No | `""` | +| `setup-commands` | Shell commands run before the agent starts | No | `""` | +| `allowed-bot-users` | Allowlisted bot actor usernames (comma-separated) | No | `github-actions[bot]` | +| `draft-prs` | Create PRs as draft (true/false) | No | `true` | + +## Safe Outputs + +- `create-pull-request` — open a PR with the fix (max 1) + +## Pairing + +Pair this with a [Scheduled Audit](../scheduled-audit/) workflow. The audit detects issues; the fix resolves them. diff --git a/gh-agent-workflows/scheduled-fix/example.yml b/gh-agent-workflows/scheduled-fix/example.yml new file mode 100644 index 00000000..b9d6c89d --- /dev/null +++ b/gh-agent-workflows/scheduled-fix/example.yml @@ -0,0 +1,33 @@ +name: Scheduled Fix +on: + schedule: + - cron: "0 14 * * 1-5" + workflow_dispatch: + +permissions: + contents: read + issues: read + pull-requests: write + +jobs: + run: + uses: elastic/ai-github-actions/.github/workflows/gh-aw-scheduled-fix.lock.yml@v0 + with: + issue-title-prefix: "[my-audit]" + issue-label: "my-audit" + additional-instructions: | + Describe domain-specific fix instructions here. + + ### Candidate Search + Search for open issues matching your detector: + ``` + github-search_issues: query="repo:{owner}/{repo} is:issue is:open label:my-audit sort:updated-asc" + ``` + + ### Implementation + 1. Read the affected files + 2. Apply the fix described in the issue + 3. Run tests + 4. Commit locally + secrets: + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} diff --git a/gh-agent-workflows/test-improvement/README.md b/gh-agent-workflows/test-improver/README.md similarity index 90% rename from gh-agent-workflows/test-improvement/README.md rename to gh-agent-workflows/test-improver/README.md index 1b7c1ea3..e69eec1d 100644 --- a/gh-agent-workflows/test-improvement/README.md +++ b/gh-agent-workflows/test-improver/README.md @@ -1,4 +1,4 @@ -# Test Improvement +# Test Improver Add focused tests for under-tested code and clean up redundant tests. @@ -10,8 +10,8 @@ Identifies code paths with no or minimal test coverage, adds focused tests that ```bash mkdir -p .github/workflows && curl -sL \ - https://raw.githubusercontent.com/elastic/ai-github-actions/v0/gh-agent-workflows/test-improvement/example.yml \ - -o .github/workflows/test-improvement.yml + https://raw.githubusercontent.com/elastic/ai-github-actions/v0/gh-agent-workflows/test-improver/example.yml \ + -o .github/workflows/test-improver.yml ``` See [example.yml](example.yml) for the full workflow file. diff --git a/gh-agent-workflows/test-improvement/example.yml b/gh-agent-workflows/test-improver/example.yml similarity index 85% rename from gh-agent-workflows/test-improvement/example.yml rename to gh-agent-workflows/test-improver/example.yml index 539f7631..77d51b22 100644 --- a/gh-agent-workflows/test-improvement/example.yml +++ b/gh-agent-workflows/test-improver/example.yml @@ -1,4 +1,4 @@ -name: Test Improvement +name: Test Improver on: schedule: - cron: "0 9 * * 1" @@ -11,6 +11,6 @@ permissions: jobs: run: - uses: elastic/ai-github-actions/.github/workflows/gh-aw-test-improvement.lock.yml@v0 + uses: elastic/ai-github-actions/.github/workflows/gh-aw-test-improver.lock.yml@v0 secrets: COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} diff --git a/gh-agent-workflows/text-auditor/README.md b/gh-agent-workflows/text-auditor/README.md new file mode 100644 index 00000000..9385e47e --- /dev/null +++ b/gh-agent-workflows/text-auditor/README.md @@ -0,0 +1,51 @@ +# Text Auditor + +Find typos, unclear error messages, and awkward user-facing text, then file an improvement issue. + +## How it works + +Scans user-facing text sources — CLI output, error messages, documentation, and help text — for typos, grammatical errors, unclear error messages, and inconsistent terminology. Files a single issue with concrete, low-effort fixes. Most runs end with `noop`. + +## Quick Install + +```bash +mkdir -p .github/workflows && curl -sL \ + https://raw.githubusercontent.com/elastic/ai-github-actions/v0/gh-agent-workflows/text-auditor/example.yml \ + -o .github/workflows/text-auditor.yml +``` + +See [example.yml](example.yml) for the full workflow file. + +## Trigger + +| Event | Schedule | +| --- | --- | +| `schedule` | Weekdays | +| `workflow_dispatch` | Manual | + +## Inputs + +| Input | Description | Required | Default | +| --- | --- | --- | --- | +| `additional-instructions` | Repo-specific instructions appended to the agent prompt | No | `""` | +| `setup-commands` | Shell commands run before the agent starts | No | `""` | +| `allowed-bot-users` | Allowlisted bot actor usernames (comma-separated) | No | `github-actions[bot]` | +| `edit-typos` | How aggressively to flag typos and misspellings (`high`/`low`/`none`) | No | `low` | +| `edit-grammar` | How aggressively to flag grammar and sentence construction problems (`high`/`low`/`none`) | No | `low` | +| `edit-clarity` | How aggressively to flag unclear user-facing text (`high`/`low`/`none`) | No | `low` | +| `edit-terminology` | How aggressively to flag inconsistent terminology (`high`/`low`/`none`) | No | `low` | +| `edit-misleading-text` | How aggressively to flag text that conflicts with behavior (`high`/`low`/`none`) | No | `low` | + +### Edit Levels + +Each edit dimension accepts one of three levels: + +| Level | Meaning | +| --- | --- | +| `high` | Apply best judgment proactively within this dimension | +| `low` | Report only concrete, unambiguous problems in this dimension | +| `none` | Skip this dimension entirely | + +## Safe Outputs + +- `create-issue` — file a text improvement report (max 1, auto-closes older reports) diff --git a/gh-agent-workflows/text-beautifier/dogfood-with.yml b/gh-agent-workflows/text-auditor/dogfood-with.yml similarity index 100% rename from gh-agent-workflows/text-beautifier/dogfood-with.yml rename to gh-agent-workflows/text-auditor/dogfood-with.yml diff --git a/gh-agent-workflows/text-auditor/example.yml b/gh-agent-workflows/text-auditor/example.yml new file mode 100644 index 00000000..c05c048d --- /dev/null +++ b/gh-agent-workflows/text-auditor/example.yml @@ -0,0 +1,22 @@ +name: Text Auditor +on: + schedule: + - cron: "0 13 * * 1-5" + workflow_dispatch: + +permissions: + contents: read + issues: write + pull-requests: read + +jobs: + run: + uses: elastic/ai-github-actions/.github/workflows/gh-aw-text-auditor.lock.yml@v0 + with: + # edit-typos: low + # edit-grammar: low + # edit-clarity: low + # edit-terminology: low + # edit-misleading-text: low + secrets: + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} diff --git a/gh-agent-workflows/text-beautifier/README.md b/gh-agent-workflows/text-beautifier/README.md index 5a885907..88396d1f 100644 --- a/gh-agent-workflows/text-beautifier/README.md +++ b/gh-agent-workflows/text-beautifier/README.md @@ -1,10 +1,10 @@ # Text Beautifier -Find typos, unclear error messages, and awkward user-facing text, then file an improvement issue. +Fix text-auditor issues by opening a focused PR with text improvements. ## How it works -Scans user-facing text sources — CLI output, error messages, documentation, and help text — for typos, grammatical errors, unclear error messages, and inconsistent terminology. Files a single issue with concrete, low-effort fixes. Most runs end with `noop`. +Picks up open issues filed by the Text Auditor (labeled `text-auditor` or with `[text-auditor]` in the title), applies the suggested text fixes, and opens a PR. Only acts on concrete, unambiguous fixes — skips anything requiring design decisions. Most runs end with `noop`. ## Quick Install @@ -30,22 +30,11 @@ See [example.yml](example.yml) for the full workflow file. | `additional-instructions` | Repo-specific instructions appended to the agent prompt | No | `""` | | `setup-commands` | Shell commands run before the agent starts | No | `""` | | `allowed-bot-users` | Allowlisted bot actor usernames (comma-separated) | No | `github-actions[bot]` | -| `edit-typos` | How aggressively to flag typos and misspellings (`high`/`low`/`none`) | No | `low` | -| `edit-grammar` | How aggressively to flag grammar and sentence construction problems (`high`/`low`/`none`) | No | `low` | -| `edit-clarity` | How aggressively to flag unclear user-facing text (`high`/`low`/`none`) | No | `low` | -| `edit-terminology` | How aggressively to flag inconsistent terminology (`high`/`low`/`none`) | No | `low` | -| `edit-misleading-text` | How aggressively to flag text that conflicts with behavior (`high`/`low`/`none`) | No | `low` | -### Edit Levels - -Each edit dimension accepts one of three levels: +## Safe Outputs -| Level | Meaning | -| --- | --- | -| `high` | Apply best judgment proactively within this dimension | -| `low` | Report only concrete, unambiguous problems in this dimension | -| `none` | Skip this dimension entirely | +- `create-pull-request` — open a PR with text fixes (max 1) -## Safe Outputs +## Pairing -- `create-issue` — file a text improvement report (max 1, auto-closes older reports) +This workflow is the read-write companion to [Text Auditor](../text-auditor/). The auditor finds issues; the beautifier fixes them. diff --git a/gh-agent-workflows/text-beautifier/example.yml b/gh-agent-workflows/text-beautifier/example.yml index 2b3a69f4..57725750 100644 --- a/gh-agent-workflows/text-beautifier/example.yml +++ b/gh-agent-workflows/text-beautifier/example.yml @@ -1,22 +1,16 @@ name: Text Beautifier on: schedule: - - cron: "0 13 * * 1-5" + - cron: "0 14 * * 1-5" workflow_dispatch: permissions: contents: read - issues: write - pull-requests: read + issues: read + pull-requests: write jobs: run: uses: elastic/ai-github-actions/.github/workflows/gh-aw-text-beautifier.lock.yml@v0 - with: - # edit-typos: low - # edit-grammar: low - # edit-clarity: low - # edit-terminology: low - # edit-misleading-text: low secrets: COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} diff --git a/mkdocs.yml b/mkdocs.yml index 04c57e87..bd72cd67 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -13,40 +13,45 @@ nav: - Workflows: - GitHub Agent Workflows: - Overview: workflows/gh-agent-workflows.md + - Base Workflows: + - Scheduled Audit: workflows/gh-agent-workflows/scheduled-audit.md + - Scheduled Fix: workflows/gh-agent-workflows/scheduled-fix.md - Human-coordinated: - Docs PR Review: workflows/gh-agent-workflows/docs-pr-review.md - Duplicate Issue Detector: workflows/gh-agent-workflows/duplicate-issue-detector.md - Issue Triage: workflows/gh-agent-workflows/issue-triage.md - - Issue Triage (with PR): workflows/gh-agent-workflows/issue-triage-pr.md + - Issue Fixer: workflows/gh-agent-workflows/issue-fixer.md - Mention in Issue: workflows/gh-agent-workflows/mention-in-issue.md - Mention in PR: workflows/gh-agent-workflows/mention-in-pr.md - - PR CI Detective: workflows/gh-agent-workflows/pr-ci-detective.md - - PR CI Fixer: workflows/gh-agent-workflows/pr-ci-fixer.md + - PR Actions Detective: workflows/gh-agent-workflows/pr-actions-detective.md + - PR Actions Fixer: workflows/gh-agent-workflows/pr-actions-fixer.md + - PR Buildkite Detective: workflows/gh-agent-workflows/pr-buildkite-detective.md - PR Review: workflows/gh-agent-workflows/pr-review.md + - PR Review (Fork): workflows/gh-agent-workflows/pr-review-fork.md - Update PR Body: workflows/gh-agent-workflows/update-pr-body.md - - Scheduled / Agent Factory: + - Detector / Fixer Pairs: + - Bug Hunting: workflows/gh-agent-workflows/bugs.md + - Code Duplication: workflows/gh-agent-workflows/code-duplication.md + - Docs Patrol: workflows/gh-agent-workflows/docs-patrol-overview.md + - Newbie Contributor: workflows/gh-agent-workflows/newbie-contributor.md + - Text Quality: workflows/gh-agent-workflows/text-quality.md + - Standalone Scheduled: - Agent Efficiency: workflows/gh-agent-workflows/agent-efficiency.md - Agent Suggestions: workflows/gh-agent-workflows/agent-suggestions.md - - Breaking Change Detect: workflows/gh-agent-workflows/breaking-change-detect.md - - Bug Exterminator: workflows/gh-agent-workflows/bug-exterminator.md - - Bug Hunter: workflows/gh-agent-workflows/bug-hunter.md + - Breaking Change Detector: workflows/gh-agent-workflows/breaking-change-detector.md - Code Simplifier: workflows/gh-agent-workflows/code-simplifier.md - - Docs Drift: workflows/gh-agent-workflows/docs-drift.md - - Docs Drift External: workflows/gh-agent-workflows/docs-drift-external.md - - Docs New Contributor Review: workflows/gh-agent-workflows/docs-new-contributor-review.md - - Docs New Contributor Review External: workflows/gh-agent-workflows/docs-new-contributor-review-external.md - Downstream Health: workflows/gh-agent-workflows/downstream-health.md - - Flaky Test Triage: workflows/gh-agent-workflows/flaky-test-triage.md + - Flaky Test Investigator: workflows/gh-agent-workflows/flaky-test-investigator.md - Performance Profiler: workflows/gh-agent-workflows/performance-profiler.md - Project Summary: workflows/gh-agent-workflows/project-summary.md - Release Update Check: workflows/gh-agent-workflows/release-update.md - - Semantic Function Clustering: workflows/gh-agent-workflows/semantic-function-clustering.md - Small Problem Fixer: workflows/gh-agent-workflows/small-problem-fixer.md - Stale Issues: workflows/gh-agent-workflows/stale-issues.md - - Test Improvement: workflows/gh-agent-workflows/test-improvement.md + - Test Improver: workflows/gh-agent-workflows/test-improver.md - Legacy: - Claude Composite Actions: workflows/claude-workflows.md - Developing: developing.md + - Upgrading: upgrading.md - Security: security.md - Release: release.md markdown_extensions: diff --git a/scripts/dogfood.sh b/scripts/dogfood.sh index e58220ed..6af57a30 100755 --- a/scripts/dogfood.sh +++ b/scripts/dogfood.sh @@ -18,9 +18,14 @@ cd "$REPO_ROOT" # Workflows that are not dogfooded in this repository. EXCLUDED_WORKFLOWS=( - "flaky-test-triage" - "issue-triage-pr" + "docs-patrol-external" + "newbie-contributor-patrol-external" + "flaky-test-investigator" + "issue-fixer" + "performance-profiler" "pr-review-fork" + "scheduled-audit" + "scheduled-fix" ) echo "Syncing workflow files..." diff --git a/scripts/quick-setup.sh b/scripts/quick-setup.sh index e0f6cbcf..513d4a4b 100755 --- a/scripts/quick-setup.sh +++ b/scripts/quick-setup.sh @@ -123,19 +123,19 @@ default_workflows=( issue-triage mention-in-issue mention-in-pr - pr-ci-detective + pr-actions-detective ) continuous_improvement_workflows=( bug-hunter bug-exterminator code-simplifier - docs-drift - docs-new-contributor-review + docs-patrol + newbie-contributor-patrol small-problem-fixer stale-issues - test-improvement - breaking-change-detect - semantic-function-clustering + test-improver + breaking-change-detector + code-duplication-detector update-pr-body ) diff --git a/scripts/trigger-ci-workflows.sh b/scripts/trigger-ci-workflows.sh new file mode 100755 index 00000000..6d4324a7 --- /dev/null +++ b/scripts/trigger-ci-workflows.sh @@ -0,0 +1,145 @@ +#!/usr/bin/env bash +# Trigger continuous-improvement workflows via workflow_dispatch. +# +# Usage: +# ./scripts/trigger-ci-workflows.sh # trigger all categories +# ./scripts/trigger-ci-workflows.sh detectors # trigger one category +# ./scripts/trigger-ci-workflows.sh improvers monitors # trigger multiple categories +# ./scripts/trigger-ci-workflows.sh --dry-run # show what would be triggered +# ./scripts/trigger-ci-workflows.sh --list # list workflows by category + +set -euo pipefail + +REPO="elastic/ai-github-actions" +REF="main" + +# --- Categories --- + +DETECTORS=( + "Trigger Breaking Change Detector" + "Trigger Bug Hunter" + "Trigger Docs Patrol" + "Trigger Newbie Contributor Patrol" + "Trigger Code Duplication Detector" + "Trigger Stale Issues" + "Trigger Text Auditor" +) + +IMPROVERS=( + "Trigger Bug Exterminator" + "Trigger Code Duplication Fixer" + "Trigger Code Simplifier" + "Trigger Newbie Contributor Fixer" + "Trigger Small Problem Fixer" + "Trigger Test Improver" + "Trigger Text Beautifier" +) + +MONITORS=( + "Trigger Agent Efficiency" + "Trigger Agent Suggestions" + "Trigger Downstream Health" + "Trigger Project Summary" + "Trigger Release Update Check" +) + +ALL_CATEGORIES=(detectors improvers monitors) + +# --- Argument parsing --- + +DRY_RUN=false +LIST_ONLY=false +CATEGORIES=() + +for arg in "$@"; do + case "$arg" in + --dry-run) DRY_RUN=true ;; + --list) LIST_ONLY=true ;; + --help|-h) + echo "Usage: $0 [--dry-run] [--list] [category ...]" + echo "" + echo "Categories: detectors, improvers, monitors" + echo " detectors — find issues, drift, stale items, breaking changes" + echo " improvers — fix bugs, simplify code, improve tests/text/perf" + echo " monitors — efficiency reports, downstream health, project summaries" + echo "" + echo " --dry-run Show what would be triggered without dispatching" + echo " --list List workflows by category" + echo "" + echo "If no categories are specified, all are triggered." + exit 0 + ;; + detectors|improvers|monitors) + CATEGORIES+=("$arg") + ;; + *) + echo "Unknown argument: $arg (expected: detectors, improvers, monitors, --dry-run, --list)" >&2 + exit 1 + ;; + esac +done + +if [[ ${#CATEGORIES[@]} -eq 0 ]]; then + CATEGORIES=("${ALL_CATEGORIES[@]}") +fi + +# --- Helpers --- + +get_workflows() { + local category="$1" + case "$category" in + detectors) printf '%s\n' "${DETECTORS[@]}" ;; + improvers) printf '%s\n' "${IMPROVERS[@]}" ;; + monitors) printf '%s\n' "${MONITORS[@]}" ;; + esac +} + +capitalize() { + echo "$1" | awk '{print toupper(substr($0,1,1)) substr($0,2)}' +} + +# --- Main --- + +if [[ "$LIST_ONLY" == "true" ]]; then + for category in "${CATEGORIES[@]}"; do + echo "## $(capitalize "$category")" + get_workflows "$category" | while read -r name; do + echo " $name" + done + echo "" + done + exit 0 +fi + +total=0 +succeeded=0 +failed=0 + +for category in "${CATEGORIES[@]}"; do + echo "## $(capitalize "$category")" + echo "" + + get_workflows "$category" | while read -r name; do + if [[ "$DRY_RUN" == "true" ]]; then + echo " [dry-run] $name" + elif gh workflow run "$name" --repo "$REPO" --ref "$REF" 2>/dev/null; then + echo " ✓ $name" + else + echo " ✗ $name (dispatch failed)" >&2 + fi + done + + echo "" +done + +if [[ "$DRY_RUN" == "false" ]]; then + # Re-count for summary (subshell above doesn't propagate counts) + for category in "${CATEGORIES[@]}"; do + case "$category" in + detectors) total=$((total + ${#DETECTORS[@]})) ;; + improvers) total=$((total + ${#IMPROVERS[@]})) ;; + monitors) total=$((total + ${#MONITORS[@]})) ;; + esac + done + echo "Dispatched $total workflows across ${#CATEGORIES[@]} category(s)." +fi