mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-08-29 10:09:43 +02:00
## Summary - run AI issue triage only when an issue is opened or its original title/body is edited - do not run issue triage for comments or reopen events - store deterministic issue evidence in the agent-visible runner temp directory - expose structured safe-output publication through the restricted CLI proxy while keeping shell, edit, and GitHub API tools disabled - skip PR intake jobs for draft pull requests and run intake when they become ready for review - replace the `Needs-Review` lifecycle label with `Ready for review`, migrating the legacy label on subsequent intake runs Closes #49917 ## Validation - `gh aw compile issue-triage` - `python -m unittest discover .github\scripts\issue-triage\tests -v` (46 tests) - `node --test .github\scripts\pr-intake\tests\pr-intake.test.mjs` (32 tests) - `git diff --check` on committed files --------- Copilot-Session: 3067a641-aa79-4f96-8d9f-eaa1c6d9b3cf
2264 lines
134 KiB
YAML
Generated
2264 lines
134 KiB
YAML
Generated
# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"c34da18b80b755b3ec6437d94fc2038fab07c4c89532e1894d3d1c2ca6199c7c","body_hash":"0b82e73d1d8939f77acf5de1cb8478fc91d567984938585dd6e032cb185ef5f3","compiler_version":"v0.86.2","strict":true,"agent_id":"copilot","agent_model":"small","engine_versions":{"copilot":"1.0.79"}}
|
||
# gh-aw-manifest: {"version":1,"secrets":["GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/cache/restore","sha":"55cc8345863c7cc4c66a329aec7e433d2d1c52a9","version":"v6.1.0"},{"repo":"actions/cache/save","sha":"55cc8345863c7cc4c66a329aec7e433d2d1c52a9","version":"v6.1.0"},{"repo":"actions/checkout","sha":"3d3c42e5aac5ba805825da76410c181273ba90b1","version":"v7.0.1"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"820762786026740c76f36085b0efc47a31fe5020","version":"v7.0.0"},{"repo":"actions/setup-python","sha":"5fda3b95a4ea91299a34e894583c3862153e4b97","version":"v7.0.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"6aab9e5b5c91c615506061f09bedd81a23babe3c","version":"v0.86.2"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.27.44","digest":"sha256:0d727725c737b58c7bdf51f640cffb928385ec46517e0917c7f1a02f1bada8b4","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.27.44@sha256:0d727725c737b58c7bdf51f640cffb928385ec46517e0917c7f1a02f1bada8b4"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.44","digest":"sha256:b50fbadba138f6e9aba94aca09711335c489bb3b15861220cb66f6092e042dc7","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.44@sha256:b50fbadba138f6e9aba94aca09711335c489bb3b15861220cb66f6092e042dc7"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.27.44","digest":"sha256:83e48bbe12c634be8c228a576832fe45f66c529ac3659db92bddbcf2eeb6d627","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.27.44@sha256:83e48bbe12c634be8c228a576832fe45f66c529ac3659db92bddbcf2eeb6d627"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.4.9","digest":"sha256:e5a1569aeaf41820fa7bdee3e94468cae448133cdbf00119ad24f5b74db1ab9f","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.4.9@sha256:e5a1569aeaf41820fa7bdee3e94468cae448133cdbf00119ad24f5b74db1ab9f"},{"image":"ghcr.io/github/gh-aw-node","digest":"sha256:0d9f1fb5fd6610c0ac1f5194a38e45a8a1e81f8a390d5142d8e4e6f26a4b3196","pinned_image":"ghcr.io/github/gh-aw-node@sha256:0d9f1fb5fd6610c0ac1f5194a38e45a8a1e81f8a390d5142d8e4e6f26a4b3196"}]}
|
||
# This file was automatically generated by gh-aw (v0.86.2). DO NOT EDIT. To debug this workflow, load the skill at https://github.com/github/gh-aw/blob/main/debug.md
|
||
#
|
||
# ___ _ _
|
||
# / _ \ | | (_)
|
||
# | |_| | __ _ ___ _ __ | |_ _ ___
|
||
# | _ |/ _` |/ _ \ '_ \| __| |/ __|
|
||
# | | | | (_| | __/ | | | |_| | (__
|
||
# \_| |_/\__, |\___|_| |_|\__|_|\___|
|
||
# __/ |
|
||
# _ _ |___/
|
||
# | | | | / _| |
|
||
# | | | | ___ _ __ _ __| |_| | _____ ____
|
||
# | |/\| |/ _ \ '__| |/ /| _| |/ _ \ \ /\ / / ___|
|
||
# \ /\ / (_) | | | | ( | | | | (_) \ V V /\__ \
|
||
# \/ \/ \___/|_| |_|\_\|_| |_|\___/ \_/\_/ |___/
|
||
#
|
||
#
|
||
# 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/
|
||
#
|
||
# Maintain one concise issue summary with likely duplicates and missing-information guidance.
|
||
#
|
||
# Secrets used:
|
||
# - GH_AW_GITHUB_MCP_SERVER_TOKEN
|
||
# - GH_AW_GITHUB_TOKEN
|
||
# - GITHUB_TOKEN
|
||
#
|
||
# Custom actions used:
|
||
# - actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
||
# - actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
||
# - actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||
# - actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||
# - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||
# - actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
|
||
# - actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
||
# - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||
# - github/gh-aw-actions/setup@6aab9e5b5c91c615506061f09bedd81a23babe3c # v0.86.2
|
||
#
|
||
# Container images used:
|
||
# - ghcr.io/github/gh-aw-firewall/agent:0.27.44@sha256:0d727725c737b58c7bdf51f640cffb928385ec46517e0917c7f1a02f1bada8b4
|
||
# - ghcr.io/github/gh-aw-firewall/api-proxy:0.27.44@sha256:b50fbadba138f6e9aba94aca09711335c489bb3b15861220cb66f6092e042dc7
|
||
# - ghcr.io/github/gh-aw-firewall/squid:0.27.44@sha256:83e48bbe12c634be8c228a576832fe45f66c529ac3659db92bddbcf2eeb6d627
|
||
# - ghcr.io/github/gh-aw-mcpg:v0.4.9@sha256:e5a1569aeaf41820fa7bdee3e94468cae448133cdbf00119ad24f5b74db1ab9f
|
||
# - ghcr.io/github/gh-aw-node@sha256:0d9f1fb5fd6610c0ac1f5194a38e45a8a1e81f8a390d5142d8e4e6f26a4b3196
|
||
|
||
name: "AI Issue Triage"
|
||
on:
|
||
issues:
|
||
types:
|
||
- opened
|
||
- edited
|
||
# roles: all # Roles processed as role check in pre-activation job
|
||
|
||
permissions: {}
|
||
|
||
concurrency:
|
||
cancel-in-progress: true
|
||
group: issue-triage-${{ github.event.issue.number }}
|
||
|
||
run-name: "AI Issue Triage"
|
||
|
||
jobs:
|
||
activation:
|
||
needs: pre_activation
|
||
if: needs.pre_activation.outputs.activated == 'true'
|
||
runs-on: ubuntu-slim
|
||
permissions:
|
||
actions: read
|
||
contents: read
|
||
env:
|
||
GH_AW_MAX_DAILY_AI_CREDITS: "300"
|
||
GH_AW_RUNTIME_FEATURES: ${{ vars.GH_AW_RUNTIME_FEATURES }}
|
||
outputs:
|
||
body: ${{ steps.sanitized.outputs.body }}
|
||
comment_id: ""
|
||
comment_repo: ""
|
||
daily_ai_credits_exceeded: ${{ steps.daily-effective-workflow-guardrail.outputs.daily_ai_credits_exceeded == 'true' }}
|
||
daily_ai_credits_guardrail_status: ${{ steps.daily-effective-workflow-guardrail.outputs.daily_ai_credits_guardrail_status || '' }}
|
||
daily_ai_credits_threshold: ${{ steps.daily-effective-workflow-guardrail.outputs.daily_ai_credits_threshold || '' }}
|
||
daily_ai_credits_total_effective_tokens: ${{ steps.daily-effective-workflow-guardrail.outputs.daily_ai_credits_total_effective_tokens || '' }}
|
||
engine_id: ${{ steps.generate_aw_info.outputs.engine_id }}
|
||
lockdown_check_failed: ${{ steps.generate_aw_info.outputs.lockdown_check_failed == 'true' }}
|
||
model: ${{ steps.generate_aw_info.outputs.model }}
|
||
oauth_token_check_failed: ${{ steps.check-oauth-tokens.outputs.oauth_token_check_failed == 'true' }}
|
||
setup-parent-span-id: ${{ steps.setup.outputs.parent-span-id || steps.setup.outputs.span-id }}
|
||
setup-span-id: ${{ steps.setup.outputs.span-id }}
|
||
setup-trace-id: ${{ steps.setup.outputs.trace-id }}
|
||
stale_lock_file_failed: ${{ steps.check-lock-file.outputs.stale_lock_file_failed == 'true' }}
|
||
text: ${{ steps.sanitized.outputs.text }}
|
||
title: ${{ steps.sanitized.outputs.title }}
|
||
steps:
|
||
- name: Setup Scripts
|
||
id: setup
|
||
uses: github/gh-aw-actions/setup@6aab9e5b5c91c615506061f09bedd81a23babe3c # v0.86.2
|
||
with:
|
||
destination: ${{ runner.temp }}/gh-aw/actions
|
||
job-name: ${{ github.job }}
|
||
trace-id: ${{ needs.pre_activation.outputs.setup-trace-id }}
|
||
parent-span-id: ${{ needs.pre_activation.outputs.setup-parent-span-id || needs.pre_activation.outputs.setup-span-id }}
|
||
safe-output-artifact-client: ${{ env.GH_AW_MAX_DAILY_AI_CREDITS != '' }}
|
||
env:
|
||
GH_AW_SETUP_WORKFLOW_NAME: "AI Issue Triage"
|
||
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-triage.lock.yml@${{ github.ref }}
|
||
GH_AW_INFO_VERSION: "1.0.79"
|
||
GH_AW_INFO_AWF_VERSION: "v0.27.44"
|
||
GH_AW_INFO_ENGINE_ID: "copilot"
|
||
- name: Generate agentic run info
|
||
id: generate_aw_info
|
||
env:
|
||
GH_AW_INFO_ENGINE_ID: "copilot"
|
||
GH_AW_INFO_ENGINE_NAME: "GitHub Copilot CLI"
|
||
GH_AW_INFO_MODEL: "small"
|
||
GH_AW_INFO_VERSION: "1.0.79"
|
||
GH_AW_INFO_AGENT_VERSION: "1.0.79"
|
||
GH_AW_INFO_CLI_VERSION: "v0.86.2"
|
||
GH_AW_INFO_WORKFLOW_NAME: "AI Issue Triage"
|
||
GH_AW_INFO_EXPERIMENTAL: "false"
|
||
GH_AW_INFO_SUPPORTS_TOOLS_ALLOWLIST: "true"
|
||
GH_AW_INFO_STAGED: "false"
|
||
GH_AW_INFO_ALLOWED_DOMAINS: '["defaults"]'
|
||
GH_AW_INFO_FIREWALL_ENABLED: "true"
|
||
GH_AW_INFO_AWF_VERSION: "v0.27.44"
|
||
GH_AW_INFO_AWMG_VERSION: ""
|
||
GH_AW_INFO_FIREWALL_TYPE: "squid"
|
||
GH_AW_INFO_AGENT_RUNTIME: ""
|
||
GH_AW_INFO_FRONTMATTER_EMOJI: "📌"
|
||
GH_AW_COMPILED_STRICT: "true"
|
||
GH_AW_INFO_FEATURES: '{"issue-intents":true}'
|
||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||
with:
|
||
script: |
|
||
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
|
||
setupGlobals(core, github, context, exec, io, getOctokit);
|
||
const { main } = require('${{ runner.temp }}/gh-aw/actions/generate_aw_info.cjs');
|
||
await main(core, context);
|
||
- name: Restore daily AIC usage cache
|
||
id: restore-daily-aic-cache
|
||
if: ${{ env.GH_AW_MAX_DAILY_AI_CREDITS != '' }}
|
||
continue-on-error: true
|
||
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
||
with:
|
||
key: agentic-workflow-usage-issuetriage-${{ github.run_id }}
|
||
restore-keys: agentic-workflow-usage-issuetriage-
|
||
path: /tmp/gh-aw/agentic-workflow-usage-cache.jsonl
|
||
- name: Restore daily AIC usage cache (artifact fallback)
|
||
id: restore-daily-aic-cache-fallback
|
||
if: ${{ env.GH_AW_MAX_DAILY_AI_CREDITS != '' }}
|
||
continue-on-error: true
|
||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||
env:
|
||
GH_AW_RESTORE_DAILY_AIC_CACHE_HIT: ${{ steps.restore-daily-aic-cache.outputs.cache-hit }}
|
||
GH_AW_RESTORE_DAILY_AIC_CACHE_MATCHED_KEY: ${{ steps.restore-daily-aic-cache.outputs.cache-matched-key }}
|
||
with:
|
||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||
script: |
|
||
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
|
||
setupGlobals(core, github, context, exec, io, getOctokit);
|
||
const { main } = require('${{ runner.temp }}/gh-aw/actions/restore_aic_usage_cache_fallback.cjs');
|
||
await main();
|
||
- name: Check daily workflow token guardrail
|
||
id: daily-effective-workflow-guardrail
|
||
if: ${{ env.GH_AW_MAX_DAILY_AI_CREDITS != '' }}
|
||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||
env:
|
||
GH_AW_WORKFLOW_NAME: "AI Issue Triage"
|
||
GH_AW_WORKFLOW_ID: "issue-triage"
|
||
GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||
GH_AW_WORKFLOW_DISPATCH_AW_CONTEXT: ${{ github.event.inputs.aw_context || '' }}
|
||
GH_AW_HAS_SLASH_COMMAND: "false"
|
||
GH_AW_HAS_LABEL_COMMAND: "false"
|
||
GH_AW_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||
GH_AW_MAX_DAILY_AI_CREDITS: "300"
|
||
with:
|
||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||
script: |
|
||
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
|
||
setupGlobals(core, github, context, exec, io, getOctokit);
|
||
const { main } = require('${{ runner.temp }}/gh-aw/actions/check_daily_aic_workflow_guardrail.cjs');
|
||
await main();
|
||
- name: Check for OAuth tokens
|
||
id: check-oauth-tokens
|
||
run: bash "${RUNNER_TEMP}/gh-aw/actions/check_oauth_tokens.sh"
|
||
env:
|
||
GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }}
|
||
GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }}
|
||
- name: Checkout .github and .agents folders
|
||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||
with:
|
||
persist-credentials: false
|
||
sparse-checkout: |
|
||
.github
|
||
.agents
|
||
.claude
|
||
.codex
|
||
.gemini
|
||
.pi
|
||
sparse-checkout-cone-mode: true
|
||
fetch-depth: 1
|
||
- name: Save agent config folders for base branch restoration
|
||
env:
|
||
GH_AW_AGENT_FOLDERS: ".agents .github"
|
||
GH_AW_AGENT_FILES: "AGENTS.md"
|
||
run: |
|
||
bash "${RUNNER_TEMP}/gh-aw/actions/save_base_github_folders.sh"
|
||
- name: Check workflow lock file
|
||
id: check-lock-file
|
||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||
env:
|
||
GH_AW_WORKFLOW_FILE: "issue-triage.lock.yml"
|
||
GH_AW_CONTEXT_WORKFLOW_REF: "${{ github.workflow_ref }}"
|
||
with:
|
||
script: |
|
||
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
|
||
setupGlobals(core, github, context, exec, io, getOctokit);
|
||
const { main } = require('${{ runner.temp }}/gh-aw/actions/check_workflow_timestamp_api.cjs');
|
||
await main();
|
||
- name: Check compile-agentic version
|
||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||
env:
|
||
GH_AW_COMPILED_VERSION: "v0.86.2"
|
||
with:
|
||
script: |
|
||
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
|
||
setupGlobals(core, github, context, exec, io, getOctokit);
|
||
const { main } = require('${{ runner.temp }}/gh-aw/actions/check_version_updates.cjs');
|
||
await main();
|
||
- name: Compute current body text
|
||
id: sanitized
|
||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||
env:
|
||
GH_AW_ALLOWED_DOMAINS: "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com"
|
||
with:
|
||
script: |
|
||
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
|
||
setupGlobals(core, github, context, exec, io, getOctokit);
|
||
const { main } = require('${{ runner.temp }}/gh-aw/actions/compute_text.cjs');
|
||
await main();
|
||
- name: Log runtime features
|
||
if: ${{ contains(toJSON(vars), '"GH_AW_RUNTIME_FEATURES":') }}
|
||
run: bash "${RUNNER_TEMP}/gh-aw/actions/log_runtime_features_summary.sh"
|
||
- name: Create prompt with built-in context
|
||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||
env:
|
||
GH_AW_ACTIONS_DIR: ${{ runner.temp }}/gh-aw/actions
|
||
GH_AW_PROMPT: ${{ runner.temp }}/gh-aw/aw-prompts/prompt.txt
|
||
GH_AW_SAFE_OUTPUTS: ${{ runner.temp }}/gh-aw/safeoutputs/outputs.jsonl
|
||
GH_AW_PROMPT_CONFIG: "{\"items\":[{\"content_env\":\"GH_AW_PROMPT_CONTENT_0000\"},{\"file\":\"xpia.md\"},{\"file\":\"temp_folder_prompt.md\"},{\"file\":\"markdown.md\"},{\"file\":\"safe_outputs_prompt.md\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0001\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0002\"},{\"file\":\"mcp_cli_tools_prompt.md\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0003\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0004\"}]}"
|
||
GH_AW_PROMPT_CONTENT_0000: "<system>\n"
|
||
GH_AW_PROMPT_CONTENT_0001: "<safe-output-tools>\nTools: missing_tool, missing_data, noop, publish_triage_summary\n"
|
||
GH_AW_PROMPT_CONTENT_0002: "</safe-output-tools>\n"
|
||
GH_AW_PROMPT_CONTENT_0003: "</system>\n"
|
||
GH_AW_PROMPT_CONTENT_0004: "{{#runtime-import .github/workflows/issue-triage.md}}\n"
|
||
with:
|
||
script: |
|
||
const { setupGlobals } = require(process.env.GH_AW_ACTIONS_DIR + '/setup_globals.cjs');
|
||
setupGlobals(core, github, context, exec, io, getOctokit);
|
||
const { main } = require(process.env.GH_AW_ACTIONS_DIR + '/create_prompt.cjs');
|
||
await main(core);
|
||
- name: Interpolate variables and render templates
|
||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||
env:
|
||
GH_AW_PROMPT: ${{ runner.temp }}/gh-aw/aw-prompts/prompt.txt
|
||
GH_AW_ENGINE_ID: "copilot"
|
||
with:
|
||
script: |
|
||
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
|
||
setupGlobals(core, github, context, exec, io, getOctokit);
|
||
const { main } = require('${{ runner.temp }}/gh-aw/actions/interpolate_prompt.cjs');
|
||
await main();
|
||
- name: Substitute placeholders
|
||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||
env:
|
||
GH_AW_PROMPT: ${{ runner.temp }}/gh-aw/aw-prompts/prompt.txt
|
||
GH_AW_MCP_CLI_SERVERS_LIST: '- `safeoutputs` — run `safeoutputs --help` to see available tools'
|
||
GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED: ${{ needs.pre_activation.outputs.activated }}
|
||
with:
|
||
script: |
|
||
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
|
||
setupGlobals(core, github, context, exec, io, getOctokit);
|
||
|
||
const substitutePlaceholders = require('${{ runner.temp }}/gh-aw/actions/substitute_placeholders.cjs');
|
||
|
||
// Call the substitution function
|
||
return await substitutePlaceholders({
|
||
file: process.env.GH_AW_PROMPT,
|
||
substitutions: {
|
||
GH_AW_MCP_CLI_SERVERS_LIST: process.env.GH_AW_MCP_CLI_SERVERS_LIST,
|
||
GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED: process.env.GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED
|
||
}
|
||
});
|
||
- name: Validate prompt placeholders
|
||
env:
|
||
GH_AW_PROMPT: ${{ runner.temp }}/gh-aw/aw-prompts/prompt.txt
|
||
run: |
|
||
bash "${RUNNER_TEMP}/gh-aw/actions/validate_prompt_placeholders.sh"
|
||
- name: Print prompt
|
||
env:
|
||
GH_AW_PROMPT: ${{ runner.temp }}/gh-aw/aw-prompts/prompt.txt
|
||
run: |
|
||
bash "${RUNNER_TEMP}/gh-aw/actions/print_prompt_summary.sh"
|
||
- name: Stage prompt files for artifact upload
|
||
run: |
|
||
mkdir -p /tmp/gh-aw/aw-prompts
|
||
cp -a "${RUNNER_TEMP}/gh-aw/aw-prompts/." /tmp/gh-aw/aw-prompts/
|
||
- name: Upload activation artifact
|
||
if: success()
|
||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||
with:
|
||
name: activation
|
||
include-hidden-files: true
|
||
path: |
|
||
/tmp/gh-aw/aw_info.json
|
||
/tmp/gh-aw/models.json
|
||
/tmp/gh-aw/aw-prompts/prompt.txt
|
||
/tmp/gh-aw/aw-prompts/prompt-template.txt
|
||
/tmp/gh-aw/aw-prompts/prompt-import-tree.json
|
||
/tmp/gh-aw/github_rate_limits.jsonl
|
||
/tmp/gh-aw/base
|
||
/tmp/gh-aw/.github/agents
|
||
/tmp/gh-aw/.github/skills
|
||
if-no-files-found: ignore
|
||
retention-days: 1
|
||
|
||
agent:
|
||
needs: activation
|
||
if: needs.activation.outputs.daily_ai_credits_exceeded != 'true'
|
||
runs-on: ubuntu-latest
|
||
permissions:
|
||
contents: read
|
||
copilot-requests: write
|
||
issues: 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_RUNTIME_FEATURES: ${{ vars.GH_AW_RUNTIME_FEATURES }}
|
||
GH_AW_WORKFLOW_ID_SANITIZED: issuetriage
|
||
outputs:
|
||
agentic_engine_timeout: ${{ steps.detect-agent-errors.outputs.agentic_engine_timeout || 'false' }}
|
||
ai_credits_rate_limit_error: ${{ steps.parse-mcp-gateway.outputs.ai_credits_rate_limit_error || 'false' }}
|
||
aic: ${{ steps.parse-mcp-gateway.outputs.aic }}
|
||
ambient_context: ${{ steps.parse-mcp-gateway.outputs.ambient_context }}
|
||
checkout_pr_success: ${{ steps.checkout-pr.outputs.checkout_pr_success || 'true' }}
|
||
effective_tokens: ${{ steps.parse-mcp-gateway.outputs.effective_tokens }}
|
||
has_patch: ${{ steps.collect_output.outputs.has_patch }}
|
||
http_400_response_error: ${{ steps.detect-agent-errors.outputs.http_400_response_error || 'false' }}
|
||
inference_access_error: ${{ steps.detect-agent-errors.outputs.inference_access_error || 'false' }}
|
||
invocation_cap_exceeded: ${{ steps.detect-agent-errors.outputs.invocation_cap_exceeded || 'false' }}
|
||
max_cache_misses_exceeded: ${{ steps.detect-agent-errors.outputs.max_cache_misses_exceeded || 'false' }}
|
||
mcp_policy_error: ${{ steps.detect-agent-errors.outputs.mcp_policy_error || 'false' }}
|
||
missing_model_pricing_error: ${{ steps.detect-agent-errors.outputs.missing_model_pricing_error || 'false' }}
|
||
missing_model_pricing_model_name: ${{ steps.detect-agent-errors.outputs.missing_model_pricing_model_name || '' }}
|
||
model: ${{ needs.activation.outputs.model }}
|
||
model_not_supported_error: ${{ steps.detect-agent-errors.outputs.model_not_supported_error || 'false' }}
|
||
output: ${{ steps.collect_output.outputs.output }}
|
||
output_types: ${{ steps.collect_output.outputs.output_types }}
|
||
setup-parent-span-id: ${{ steps.setup.outputs.parent-span-id || steps.setup.outputs.span-id }}
|
||
setup-span-id: ${{ steps.setup.outputs.span-id }}
|
||
setup-trace-id: ${{ steps.setup.outputs.trace-id }}
|
||
unknown_model_ai_credits: ${{ steps.parse-mcp-gateway.outputs.unknown_model_ai_credits || 'false' }}
|
||
steps:
|
||
- name: Setup Scripts
|
||
id: setup
|
||
uses: github/gh-aw-actions/setup@6aab9e5b5c91c615506061f09bedd81a23babe3c # v0.86.2
|
||
with:
|
||
destination: ${{ runner.temp }}/gh-aw/actions
|
||
job-name: ${{ github.job }}
|
||
trace-id: ${{ needs.activation.outputs.setup-trace-id }}
|
||
parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }}
|
||
env:
|
||
GH_AW_SETUP_WORKFLOW_NAME: "AI Issue Triage"
|
||
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-triage.lock.yml@${{ github.ref }}
|
||
GH_AW_INFO_VERSION: "1.0.79"
|
||
GH_AW_INFO_AWF_VERSION: "v0.27.44"
|
||
GH_AW_INFO_ENGINE_ID: "copilot"
|
||
- name: Set runtime paths
|
||
id: set-runtime-paths
|
||
run: |
|
||
{
|
||
echo "GH_AW_SAFE_OUTPUTS=${RUNNER_TEMP}/gh-aw/safeoutputs/outputs.jsonl"
|
||
echo "GH_AW_SAFE_OUTPUTS_CONFIG_PATH=${RUNNER_TEMP}/gh-aw/safeoutputs/config.json"
|
||
echo "GH_AW_SAFE_OUTPUTS_TOOLS_PATH=${RUNNER_TEMP}/gh-aw/safeoutputs/tools.json"
|
||
} >> "$GITHUB_OUTPUT"
|
||
- name: Checkout repository
|
||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||
with:
|
||
persist-credentials: false
|
||
- name: Setup Python
|
||
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
||
with:
|
||
python-version: '3.12'
|
||
- name: Create gh-aw temp directory
|
||
run: bash "${RUNNER_TEMP}/gh-aw/actions/create_gh_aw_tmp_dir.sh"
|
||
- name: Configure gh CLI for GitHub Enterprise
|
||
run: bash "${RUNNER_TEMP}/gh-aw/actions/configure_gh_for_ghe.sh"
|
||
env:
|
||
GH_TOKEN: ${{ github.token }}
|
||
- name: Download activation artifact
|
||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||
with:
|
||
name: activation
|
||
path: /tmp/gh-aw
|
||
- env:
|
||
GH_AW_SAFE_OUTPUTS: ${{ runner.temp }}/gh-aw/safeoutputs/outputs.jsonl
|
||
GITHUB_TOKEN: ${{ github.token }}
|
||
id: prepare
|
||
name: Prepare deterministic issue evidence
|
||
run: python .github/scripts/issue-triage/issue-context.py "$GITHUB_EVENT_PATH" "/tmp/gh-aw/issue-context.md" "/tmp/gh-aw/triage-event.json"
|
||
- if: steps.prepare.outputs.should_process == 'true'
|
||
name: Prepare sanitized bug report context
|
||
run: python .github/scripts/issue-triage/bug-report-analyzer.py "/tmp/gh-aw/triage-event.json" "/tmp/gh-aw/bug-report-context.md"
|
||
|
||
- name: Configure Git credentials
|
||
env:
|
||
GITHUB_REPOSITORY: ${{ github.repository }}
|
||
GITHUB_SERVER_URL: ${{ github.server_url }}
|
||
GITHUB_TOKEN: ${{ github.token }}
|
||
run: bash "${RUNNER_TEMP}/gh-aw/actions/configure_git_credentials.sh"
|
||
- name: Checkout PR branch
|
||
id: checkout-pr
|
||
if: |
|
||
github.event.pull_request || github.event.issue.pull_request || github.event_name == 'workflow_dispatch' && fromJSON(github.event.inputs.aw_context || '{}').item_type == 'pull_request'
|
||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||
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('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
|
||
setupGlobals(core, github, context, exec, io, getOctokit);
|
||
const { main } = require('${{ runner.temp }}/gh-aw/actions/checkout_pr_branch.cjs');
|
||
await main();
|
||
- name: Install ripgrep
|
||
run: bash "${RUNNER_TEMP}/gh-aw/actions/install_ripgrep.sh"
|
||
- name: Install GitHub Copilot CLI
|
||
run: bash "${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh"
|
||
env:
|
||
GH_HOST: github.com
|
||
GH_AW_COMPILED_VERSION: v0.86.2
|
||
- name: Install AWF binary
|
||
run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.27.44 --rootless
|
||
- name: Restore agent config folders from base branch
|
||
if: steps.checkout-pr.outcome == 'success'
|
||
env:
|
||
GH_AW_AGENT_FOLDERS: ".agents .github"
|
||
GH_AW_AGENT_FILES: "AGENTS.md"
|
||
run: bash "${RUNNER_TEMP}/gh-aw/actions/restore_base_github_folders.sh"
|
||
- name: Restore inline sub-agents from activation artifact
|
||
env:
|
||
GH_AW_SUB_AGENT_DIR: ".github/agents"
|
||
GH_AW_SUB_AGENT_EXT: ".agent.md"
|
||
run: bash "${RUNNER_TEMP}/gh-aw/actions/restore_inline_sub_agents.sh"
|
||
- name: Restore inline skills from activation artifact
|
||
env:
|
||
GH_AW_SKILL_DIR: ".github/skills"
|
||
run: bash "${RUNNER_TEMP}/gh-aw/actions/restore_inline_skills.sh"
|
||
- name: Download container images
|
||
run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.27.44@sha256:0d727725c737b58c7bdf51f640cffb928385ec46517e0917c7f1a02f1bada8b4 ghcr.io/github/gh-aw-firewall/api-proxy:0.27.44@sha256:b50fbadba138f6e9aba94aca09711335c489bb3b15861220cb66f6092e042dc7 ghcr.io/github/gh-aw-firewall/squid:0.27.44@sha256:83e48bbe12c634be8c228a576832fe45f66c529ac3659db92bddbcf2eeb6d627 ghcr.io/github/gh-aw-mcpg:v0.4.9@sha256:e5a1569aeaf41820fa7bdee3e94468cae448133cdbf00119ad24f5b74db1ab9f ghcr.io/github/gh-aw-node@sha256:0d9f1fb5fd6610c0ac1f5194a38e45a8a1e81f8a390d5142d8e4e6f26a4b3196
|
||
- name: Generate Safe Outputs Config
|
||
run: |
|
||
mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs"
|
||
mkdir -p /tmp/gh-aw/safeoutputs
|
||
mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs
|
||
cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_ba2e2f4afffc129c_EOF'
|
||
{"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"false"},"publish-triage-summary":{"description":"Create or update the canonical triage summary for the triggering issue.","inputs":{"bug_report_confidence":{"default":null,"description":"Confidence in the diagnostic findings.","options":["HIGH","MEDIUM","LOW","NONE"],"required":true,"type":"choice"},"bug_report_findings":{"default":null,"description":"Concise evidence-based diagnostic findings, or a short status explanation.","required":true,"type":"string"},"bug_report_requirement":{"default":null,"description":"Whether a diagnostic report is required, recommended, optional, or not applicable.","options":["REQUIRED","RECOMMENDED","OPTIONAL","NOT_APPLICABLE"],"required":true,"type":"choice"},"bug_report_status":{"default":null,"description":"Processing status copied from the sanitized bug report context.","options":["ANALYZED","NOT_FOUND","REJECTED","NOT_APPLICABLE"],"required":true,"type":"choice"},"duplicate_candidates_json":{"default":null,"description":"JSON array of up to five objects with integer number, short reason, and HIGH/MEDIUM/LOW confidence fields, or [].","required":true,"type":"string"},"has_missing_information":{"default":null,"description":"Whether important information needed to investigate the issue is missing.","required":true,"type":"boolean"},"input_sha256":{"default":null,"description":"The exact Input SHA-256 value copied from the deterministic issue evidence.","required":true,"type":"string"},"issue_kind":{"default":null,"description":"BUG when the issue follows the PowerToys bug-report template, otherwise OTHER.","options":["BUG","OTHER"],"required":true,"type":"choice"},"issue_language":{"default":null,"description":"Whether the author-written issue title and description are English.","options":["ENGLISH","NON_ENGLISH","UNCERTAIN"],"required":true,"type":"choice"},"missing_information":{"default":null,"description":"A concise sentence naming only the important missing information, or None.","required":true,"type":"string"},"powertoys_version":{"default":null,"description":"The normalized PowerToys version from the bug template, or Not provided.","required":true,"type":"string"},"product_label":{"default":null,"description":"The exact existing Product-* label matching the issue area, or None.","required":true,"type":"string"},"reproduction_quality":{"default":null,"description":"Whether bug reproduction steps are sufficient for investigation.","options":["SUFFICIENT","INSUFFICIENT","NOT_APPLICABLE"],"required":true,"type":"choice"},"suggested_area":{"default":null,"description":"The most likely PowerToys product area or Unknown when unclear.","required":true,"type":"string"},"summary":{"default":null,"description":"A concise one- or two-sentence summary of the reported problem or request.","required":true,"type":"string"}},"output":"The canonical triage summary was published."},"report_incomplete":{}}
|
||
GH_AW_SAFE_OUTPUTS_CONFIG_ba2e2f4afffc129c_EOF
|
||
- name: Generate Safe Outputs Tools
|
||
env:
|
||
GH_AW_TOOLS_META_JSON: |
|
||
{
|
||
"description_suffixes": {},
|
||
"repo_params": {},
|
||
"dynamic_tools": [
|
||
{
|
||
"description": "Create or update the canonical triage summary for the triggering issue.",
|
||
"inputSchema": {
|
||
"additionalProperties": false,
|
||
"properties": {
|
||
"bug_report_confidence": {
|
||
"description": "Confidence in the diagnostic findings.",
|
||
"enum": [
|
||
"HIGH",
|
||
"MEDIUM",
|
||
"LOW",
|
||
"NONE"
|
||
],
|
||
"type": "string"
|
||
},
|
||
"bug_report_findings": {
|
||
"description": "Concise evidence-based diagnostic findings, or a short status explanation.",
|
||
"type": "string"
|
||
},
|
||
"bug_report_requirement": {
|
||
"description": "Whether a diagnostic report is required, recommended, optional, or not applicable.",
|
||
"enum": [
|
||
"REQUIRED",
|
||
"RECOMMENDED",
|
||
"OPTIONAL",
|
||
"NOT_APPLICABLE"
|
||
],
|
||
"type": "string"
|
||
},
|
||
"bug_report_status": {
|
||
"description": "Processing status copied from the sanitized bug report context.",
|
||
"enum": [
|
||
"ANALYZED",
|
||
"NOT_FOUND",
|
||
"REJECTED",
|
||
"NOT_APPLICABLE"
|
||
],
|
||
"type": "string"
|
||
},
|
||
"duplicate_candidates_json": {
|
||
"description": "JSON array of up to five objects with integer number, short reason, and HIGH/MEDIUM/LOW confidence fields, or [].",
|
||
"type": "string"
|
||
},
|
||
"has_missing_information": {
|
||
"description": "Whether important information needed to investigate the issue is missing.",
|
||
"type": "boolean"
|
||
},
|
||
"input_sha256": {
|
||
"description": "The exact Input SHA-256 value copied from the deterministic issue evidence.",
|
||
"type": "string"
|
||
},
|
||
"issue_kind": {
|
||
"description": "BUG when the issue follows the PowerToys bug-report template, otherwise OTHER.",
|
||
"enum": [
|
||
"BUG",
|
||
"OTHER"
|
||
],
|
||
"type": "string"
|
||
},
|
||
"issue_language": {
|
||
"description": "Whether the author-written issue title and description are English.",
|
||
"enum": [
|
||
"ENGLISH",
|
||
"NON_ENGLISH",
|
||
"UNCERTAIN"
|
||
],
|
||
"type": "string"
|
||
},
|
||
"missing_information": {
|
||
"description": "A concise sentence naming only the important missing information, or None.",
|
||
"type": "string"
|
||
},
|
||
"powertoys_version": {
|
||
"description": "The normalized PowerToys version from the bug template, or Not provided.",
|
||
"type": "string"
|
||
},
|
||
"product_label": {
|
||
"description": "The exact existing Product-* label matching the issue area, or None.",
|
||
"type": "string"
|
||
},
|
||
"reproduction_quality": {
|
||
"description": "Whether bug reproduction steps are sufficient for investigation.",
|
||
"enum": [
|
||
"SUFFICIENT",
|
||
"INSUFFICIENT",
|
||
"NOT_APPLICABLE"
|
||
],
|
||
"type": "string"
|
||
},
|
||
"suggested_area": {
|
||
"description": "The most likely PowerToys product area or Unknown when unclear.",
|
||
"type": "string"
|
||
},
|
||
"summary": {
|
||
"description": "A concise one- or two-sentence summary of the reported problem or request.",
|
||
"type": "string"
|
||
}
|
||
},
|
||
"required": [
|
||
"bug_report_confidence",
|
||
"bug_report_findings",
|
||
"bug_report_requirement",
|
||
"bug_report_status",
|
||
"duplicate_candidates_json",
|
||
"has_missing_information",
|
||
"input_sha256",
|
||
"issue_kind",
|
||
"issue_language",
|
||
"missing_information",
|
||
"powertoys_version",
|
||
"product_label",
|
||
"reproduction_quality",
|
||
"suggested_area",
|
||
"summary"
|
||
],
|
||
"type": "object"
|
||
},
|
||
"name": "publish_triage_summary"
|
||
}
|
||
]
|
||
}
|
||
GH_AW_VALIDATION_JSON: |
|
||
{
|
||
"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
|
||
}
|
||
}
|
||
},
|
||
"report_incomplete": {
|
||
"defaultMax": 5,
|
||
"fields": {
|
||
"details": {
|
||
"type": "string",
|
||
"sanitize": true,
|
||
"maxLength": 65000
|
||
},
|
||
"reason": {
|
||
"required": true,
|
||
"type": "string",
|
||
"sanitize": true,
|
||
"maxLength": 1024
|
||
}
|
||
}
|
||
}
|
||
}
|
||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||
with:
|
||
script: |
|
||
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
|
||
setupGlobals(core, github, context, exec, io, getOctokit);
|
||
const { main } = require('${{ runner.temp }}/gh-aw/actions/generate_safe_outputs_tools.cjs');
|
||
await main();
|
||
- name: Start MCP Gateway
|
||
id: start-mcp-gateway
|
||
env:
|
||
GH_AW_POLICY_ALLOW_CREATE_PULL_REQUEST: ${{ vars.GH_AW_POLICY_ALLOW_CREATE_PULL_REQUEST || 'true' }}
|
||
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
|
||
GH_AW_SAFE_OUTPUTS_CONFIG_PATH: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS_CONFIG_PATH }}
|
||
GH_AW_SAFE_OUTPUTS_TOOLS_PATH: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS_TOOLS_PATH }}
|
||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||
run: |
|
||
set -eo pipefail
|
||
mkdir -p "${RUNNER_TEMP}/gh-aw/mcp-config"
|
||
|
||
# Export gateway environment variables for MCP config and gateway script
|
||
export MCP_GATEWAY_PORT="8080"
|
||
export MCP_GATEWAY_DOMAIN="awmg-mcpg"
|
||
export MCP_GATEWAY_HOST_DOMAIN="localhost"
|
||
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 MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD="524288"
|
||
export MCP_GATEWAY_ALLOWED_MOUNT_ROOTS="${GITHUB_WORKSPACE}:rw,${RUNNER_TEMP}/gh-aw:ro,${RUNNER_TEMP}/gh-aw/safeoutputs:rw,/opt:ro,/tmp:rw,/usr/bin/gh:ro"
|
||
export DEBUG="*"
|
||
|
||
export GH_AW_ENGINE="copilot"
|
||
export GH_AW_MCP_CLI_SERVERS='["safeoutputs"]'
|
||
MCP_GATEWAY_UID=$(id -u 2>/dev/null || echo '0')
|
||
MCP_GATEWAY_GID=$(id -g 2>/dev/null || echo '0')
|
||
source "${RUNNER_TEMP}/gh-aw/actions/resolve_docker_socket_gid.sh"
|
||
export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network bridge -p 127.0.0.1:'"${MCP_GATEWAY_PORT}"':'"${MCP_GATEWAY_PORT}"' --name awmg-mcpg --add-host host.docker.internal:host-gateway --user '"${MCP_GATEWAY_UID}"':'"${MCP_GATEWAY_GID}"' --group-add '"${DOCKER_SOCK_GID}"' -v '"${DOCKER_SOCK_PATH}"':/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_API_KEY -e MCP_GATEWAY_PAYLOAD_DIR -e MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -e DOCKER_HOST=unix:///var/run/docker.sock -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_POLICY_ALLOW_CREATE_PULL_REQUEST -e GH_AW_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GH_AW_SINK_VISIBILITY -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 RUNNER_TEMP -e MCP_GATEWAY_ALLOWED_MOUNT_ROOTS -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 -v '"${RUNNER_TEMP}"'/gh-aw/safeoutputs:'"${RUNNER_TEMP}"'/gh-aw/safeoutputs:rw ghcr.io/github/gh-aw-mcpg:v0.4.9'
|
||
|
||
mkdir -p "$HOME/.copilot"
|
||
GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node)
|
||
cat << GH_AW_MCP_CONFIG_948d9cbdbcfa4bfe_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs"
|
||
{
|
||
"mcpServers": {
|
||
"safeoutputs": {
|
||
"type": "stdio",
|
||
"container": "ghcr.io/github/gh-aw-node",
|
||
"mounts": ["\${GITHUB_WORKSPACE}:\${GITHUB_WORKSPACE}:rw", "${RUNNER_TEMP}/gh-aw/safeoutputs:${RUNNER_TEMP}/gh-aw/safeoutputs:rw", "/tmp/gh-aw:/tmp/gh-aw:rw"],
|
||
"args": ["-w", "\${GITHUB_WORKSPACE}"],
|
||
"entrypoint": "sh",
|
||
"entrypointArgs": ["-c", "sh ${RUNNER_TEMP}/gh-aw/safeoutputs/start_safe_outputs_mcp.sh"],
|
||
"env": {
|
||
"DEBUG": "*",
|
||
"DEFAULT_BRANCH": "\${DEFAULT_BRANCH}",
|
||
"GH_AW_ASSETS_ALLOWED_EXTS": "\${GH_AW_ASSETS_ALLOWED_EXTS}",
|
||
"GH_AW_ASSETS_BRANCH": "\${GH_AW_ASSETS_BRANCH}",
|
||
"GH_AW_ASSETS_MAX_SIZE_KB": "\${GH_AW_ASSETS_MAX_SIZE_KB}",
|
||
"GH_AW_MCP_LOG_DIR": "\${GH_AW_MCP_LOG_DIR}",
|
||
"GH_AW_SAFE_OUTPUTS": "\${GH_AW_SAFE_OUTPUTS}",
|
||
"GH_AW_SAFE_OUTPUTS_CONFIG_PATH": "\${GH_AW_SAFE_OUTPUTS_CONFIG_PATH}",
|
||
"GH_AW_SAFE_OUTPUTS_TOOLS_PATH": "\${GH_AW_SAFE_OUTPUTS_TOOLS_PATH}",
|
||
"GH_AW_POLICY_ALLOW_CREATE_PULL_REQUEST": "\${GH_AW_POLICY_ALLOW_CREATE_PULL_REQUEST}",
|
||
"GITHUB_REPOSITORY": "\${GITHUB_REPOSITORY}",
|
||
"GITHUB_SHA": "\${GITHUB_SHA}",
|
||
"GITHUB_TOKEN": "\${GITHUB_TOKEN}",
|
||
"GITHUB_WORKSPACE": "\${GITHUB_WORKSPACE}",
|
||
"RUNNER_TEMP": "\${RUNNER_TEMP}"
|
||
}
|
||
}
|
||
},
|
||
"gateway": {
|
||
"port": $MCP_GATEWAY_PORT,
|
||
"domain": "${MCP_GATEWAY_DOMAIN}",
|
||
"apiKey": "${MCP_GATEWAY_API_KEY}",
|
||
"payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}",
|
||
"startupTimeout": 120
|
||
}
|
||
}
|
||
GH_AW_MCP_CONFIG_948d9cbdbcfa4bfe_EOF
|
||
- name: Mount MCP servers as CLIs
|
||
id: mount-mcp-clis
|
||
continue-on-error: true
|
||
env:
|
||
MCP_GATEWAY_API_KEY: ${{ steps.start-mcp-gateway.outputs.gateway-api-key }}
|
||
MCP_GATEWAY_DOMAIN: ${{ steps.start-mcp-gateway.outputs.gateway-domain }}
|
||
MCP_GATEWAY_PORT: ${{ steps.start-mcp-gateway.outputs.gateway-port }}
|
||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||
with:
|
||
script: |
|
||
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
|
||
setupGlobals(core, github, context, exec, io);
|
||
const { main } = require('${{ runner.temp }}/gh-aw/actions/mount_mcp_as_cli.cjs');
|
||
await main();
|
||
- name: Clean credentials
|
||
continue-on-error: true
|
||
run: bash "${RUNNER_TEMP}/gh-aw/actions/clean_git_credentials.sh"
|
||
- name: Audit pre-agent workspace
|
||
id: pre_agent_audit
|
||
continue-on-error: true
|
||
run: bash "${RUNNER_TEMP}/gh-aw/actions/audit_pre_agent_workspace.sh"
|
||
- name: Execute GitHub Copilot CLI
|
||
id: agentic_execution
|
||
# Copilot CLI tool arguments (sorted):
|
||
# --allow-tool safeoutputs
|
||
# --allow-tool shell(cat)
|
||
# --allow-tool shell(date)
|
||
# --allow-tool shell(echo)
|
||
# --allow-tool shell(grep)
|
||
# --allow-tool shell(head)
|
||
# --allow-tool shell(ls)
|
||
# --allow-tool shell(printf)
|
||
# --allow-tool shell(pwd)
|
||
# --allow-tool shell(safeoutputs)
|
||
# --allow-tool shell(safeoutputs:*)
|
||
# --allow-tool shell(sort)
|
||
# --allow-tool shell(tail)
|
||
# --allow-tool shell(uniq)
|
||
# --allow-tool shell(wc)
|
||
# --allow-tool shell(yq)
|
||
# --allow-tool write
|
||
timeout-minutes: 20
|
||
run: |
|
||
set -o pipefail
|
||
printf '%s' "$(date +%s%3N)" > /tmp/gh-aw/agent_cli_start_ms.txt
|
||
trap 'gh_aw_exit_code=$?; mkdir -p /tmp/gh-aw >/dev/null 2>&1 || true; printf "%s" "$gh_aw_exit_code" > /tmp/gh-aw/agent_execution_exit_code.txt || true; rm -f "$HOME/.copilot/settings.json"' EXIT
|
||
mkdir -p "$HOME/.copilot"
|
||
printf '%s' '{"builtInAgents":{"rubberDuck":false}}' > "$HOME/.copilot/settings.json"
|
||
export XDG_CONFIG_HOME="$HOME"
|
||
export GH_AW_MCP_CONFIG="$HOME/.copilot/mcp-config.json"
|
||
GH_AW_COPILOT_SRC="$(command -v copilot 2>/dev/null || true)"
|
||
if [ -z "$GH_AW_COPILOT_SRC" ] || [ ! -x "$GH_AW_COPILOT_SRC" ]; then
|
||
echo "GitHub Copilot CLI executable not found on PATH after installation" >&2
|
||
exit 127
|
||
fi
|
||
GH_AW_COPILOT_BIN="${RUNNER_TEMP}/gh-aw/bin/copilot"
|
||
mkdir -p "${RUNNER_TEMP}/gh-aw/bin"
|
||
if [ "$GH_AW_COPILOT_SRC" != "$GH_AW_COPILOT_BIN" ]; then
|
||
cp "$GH_AW_COPILOT_SRC" "$GH_AW_COPILOT_BIN"
|
||
fi
|
||
chmod 755 "$GH_AW_COPILOT_BIN"
|
||
|
||
touch /tmp/gh-aw/agent-step-summary.md
|
||
GH_AW_NODE_BIN=$(command -v node 2>/dev/null || true)
|
||
export GH_AW_NODE_BIN
|
||
export COPILOT_API_KEY="$COPILOT_DUMMY_BYOK"
|
||
(umask 177 && touch /tmp/gh-aw/agent-stdio.log)
|
||
# shellcheck disable=SC2016
|
||
printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.27.44/awf-config.schema.json","network":{"allowDomains":["api.business.githubcopilot.com","api.enterprise.githubcopilot.com","api.github.com","api.githubcopilot.com","api.individual.githubcopilot.com","api.snapcraft.io","archive.ubuntu.com","azure.archive.ubuntu.com","crl.geotrust.com","crl.globalsign.com","crl.identrust.com","crl.sectigo.com","crl.thawte.com","crl.usertrust.com","crl.verisign.com","crl3.digicert.com","crl4.digicert.com","crls.ssl.com","github.com","host.docker.internal","json-schema.org","json.schemastore.org","keyserver.ubuntu.com","ocsp.digicert.com","ocsp.geotrust.com","ocsp.globalsign.com","ocsp.identrust.com","ocsp.sectigo.com","ocsp.ssl.com","ocsp.thawte.com","ocsp.usertrust.com","ocsp.verisign.com","packagecloud.io","packages.cloud.google.com","packages.microsoft.com","ppa.launchpad.net","raw.githubusercontent.com","registry.npmjs.org","s.symcb.com","s.symcd.com","security.ubuntu.com","telemetry.enterprise.githubcopilot.com","ts-crl.ws.symantec.com","ts-ocsp.ws.symantec.com","www.googleapis.com"],"isolation":true,"topologyAttach":["awmg-mcpg"]},"apiProxy":{"enabled":true,"enableTokenSteering":true,"maxRuns":5,"maxCacheMisses":5,"maxAiCredits":10,"models":{"agent":["sonnet-6x","gpt-5.4","gpt-5.5","gpt-5.6","gpt-5.3","gemini-pro","any"],"antigravity":["copilot/antigravity*","google/antigravity*","gemini/antigravity*"],"any":["copilot/*","anthropic/*","openai/*","google/*","gemini/*"],"auto":["copilot/auto","large"],"claude":["agent"],"codex":["agent"],"coding":["copilot/gpt-5*codex*","openai/gpt-5*codex*","gpt-5-codex","kimi"],"computer-use":["copilot/*computer-use*","google/*computer-use*","gemini/*computer-use*","openai/*computer-use*"],"copilot":["agent"],"deep-research":["copilot/deep-research*","copilot/o3-deep-research*","copilot/o4-mini-deep-research*","google/deep-research*","gemini/deep-research*","openai/o3-deep-research*","openai/o4-mini-deep-research*"],"detection":["small"],"evals":["small"],"fable":["copilot/*fable*","anthropic/*fable*"],"gemini":["agent"],"gemini-3-flash":["copilot/gemini-3*flash*","google/gemini-3*flash*","gemini/gemini-3*flash*"],"gemini-3-pro":["copilot/gemini-3*pro*","google/gemini-3*pro*","google/nano-banana*","gemini/gemini-3*pro*"],"gemini-3.1-flash":["copilot/gemini-3.1*flash*","google/gemini-3.1*flash*","gemini/gemini-3.1*flash*"],"gemini-3.1-pro":["copilot/gemini-3.1*pro*","google/gemini-3.1*pro*","gemini/gemini-3.1*pro*"],"gemini-3.5-flash":["copilot/gemini-3.5*flash*","google/gemini-3.5*flash*","gemini/gemini-3.5*flash*"],"gemini-3.6-flash":["copilot/gemini-3.6*flash*","google/gemini-3.6*flash*","gemini/gemini-3.6*flash*"],"gemini-flash":["copilot/gemini-*flash*","google/gemini-*flash*","gemini/gemini-*flash*"],"gemini-flash-lite":["copilot/gemini-*flash*lite*","google/gemini-*flash*lite*","gemini/gemini-*flash*lite*"],"gemini-omni":["copilot/gemini-omni*","google/gemini-omni*","gemini/gemini-omni*"],"gemini-pro":["copilot/gemini-*pro*","google/gemini-*pro*","gemini/gemini-*pro*"],"gemma":["copilot/gemma*","google/gemma*","gemini/gemma*"],"gpt-5":["copilot/gpt-5*","openai/gpt-5*"],"gpt-5-codex":["copilot/gpt-5*codex*","openai/gpt-5*codex*"],"gpt-5-mini":["copilot/gpt-5*mini*","openai/gpt-5*mini*"],"gpt-5-nano":["copilot/gpt-5*nano*","openai/gpt-5*nano*"],"gpt-5-pro":["copilot/gpt-5*pro*","openai/gpt-5*pro*"],"gpt-5.1":["copilot/gpt-5.1*","openai/gpt-5.1*"],"gpt-5.2":["copilot/gpt-5.2*","openai/gpt-5.2*"],"gpt-5.3":["copilot/gpt-5.3*","openai/gpt-5.3*"],"gpt-5.4":["copilot/gpt-5.4*","openai/gpt-5.4*"],"gpt-5.5":["copilot/gpt-5.5*","openai/gpt-5.5*"],"gpt-5.6":["copilot/gpt-5.6*","openai/gpt-5.6*"],"grok":["copilot/*grok*","openai/*grok*"],"haiku":["copilot/*haiku*","anthropic/*haiku*"],"image-generation":["copilot/gpt-image*","openai/gpt-image*","openai/chatgpt-image*","copilot/gemini-*image*","google/gemini-*image*","gemini/gemini-*image*","google/imagen*"],"kimi":["copilot/kimi*","openai/kimi*"],"kiwi":["copilot/kiwi*","openai/kiwi*"],"large":["sonnet","gpt-5-pro","gpt-5","gemini-pro"],"lyria":["google/lyria*","gemini/lyria*","copilot/lyria*"],"mai-code":["copilot/MAI-Code*","copilot/mai-code*","openai/MAI-Code*"],"mai-code-1-flash-picker":["copilot/MAI-Code-1-Flash-picker*","copilot/mai-code-1-flash-picker*","openai/MAI-Code-1-Flash-picker*"],"mini":["haiku","gpt-5-mini","gpt-5-nano","gemini-flash-lite"],"nano-banana":["copilot/nano-banana*","google/nano-banana*","gemini/nano-banana*"],"opus":["copilot/*opus*","anthropic/*opus*"],"opusplan":["opus?effort=high"],"raptor-mini":["copilot/raptor*","openai/raptor*"],"reasoning":["copilot/o1*","copilot/o3*","copilot/o4*","openai/o1*","openai/o3*","openai/o4*"],"robotics":["copilot/*robotics*","google/*robotics*","gemini/*robotics*"],"small":["mini"],"small-agent":["haiku","gpt-5-mini","gemini-flash"],"sonnet":["copilot/*sonnet*","anthropic/*sonnet*"],"sonnet-6x":["copilot/*sonnet-4.5*","copilot/*sonnet-4.6*","copilot/*sonnet-5*","copilot/*sonnet-4-5-*","anthropic/*sonnet-4-5-*","copilot/*sonnet-4-6*","anthropic/*sonnet-4-6*","anthropic/*sonnet-5*"],"summarization":["haiku","gpt-5-mini","gemini-flash-lite","mini"],"veo":["google/veo*","gemini/veo*"],"vision":["copilot/gemini-*image*","google/gemini-*image*","gemini/gemini-*image*","copilot/gemini-*flash*","google/gemini-*flash*","gemini/gemini-*flash*"]}},"container":{"imageTag":"0.27.44,squid=sha256:83e48bbe12c634be8c228a576832fe45f66c529ac3659db92bddbcf2eeb6d627,agent=sha256:0d727725c737b58c7bdf51f640cffb928385ec46517e0917c7f1a02f1bada8b4,api-proxy=sha256:b50fbadba138f6e9aba94aca09711335c489bb3b15861220cb66f6092e042dc7,cli-proxy=sha256:c064d15974f7c933ec7d3f7b4038f4fd203547b3154bdc821afd379144887eff"},"logging":{"proxyLogsDir":"/tmp/gh-aw/sandbox/firewall/logs","auditDir":"/tmp/gh-aw/sandbox/firewall/audit"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json"
|
||
cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json
|
||
export GH_AW_MODELS_JSON_PATH="/tmp/gh-aw/models.json"
|
||
GH_AW_DOCKER_HOST=""
|
||
if [[ "${DOCKER_HOST:-}" =~ ^tcp:// ]]; then
|
||
GH_AW_DOCKER_HOST="${DOCKER_HOST}"
|
||
fi
|
||
if [[ "${DOCKER_HOST:-}" =~ ^tcp:// ]]; then
|
||
GH_AW_CHROOT_BINARIES_SOURCE_PATH="${RUNNER_TEMP}/gh-aw" GH_AW_CHROOT_IDENTITY_HOME="${RUNNER_TEMP}/gh-aw/home" node "${RUNNER_TEMP}/gh-aw/actions/patch_awf_chroot_config.cjs"
|
||
fi
|
||
GH_AW_TOOL_CACHE_MOUNT=""
|
||
GH_AW_TOOL_CACHE="${RUNNER_TOOL_CACHE:?RUNNER_TOOL_CACHE must be set}"
|
||
if [ -d "$GH_AW_TOOL_CACHE" ]; then
|
||
if [[ "$GH_AW_TOOL_CACHE" != /opt/* ]]; then
|
||
GH_AW_TOOL_CACHE_MOUNT="$GH_AW_TOOL_CACHE:$GH_AW_TOOL_CACHE:ro"
|
||
fi
|
||
fi
|
||
# shellcheck disable=SC1003,SC2016,SC2086
|
||
awf --config "${RUNNER_TEMP}/gh-aw/awf-config.json" --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" ${GH_AW_TOOL_CACHE_MOUNT:+--mount "$GH_AW_TOOL_CACHE_MOUNT"} ${GH_AW_DOCKER_HOST:+--docker-host "$GH_AW_DOCKER_HOST"} --env-all --exclude-env ACTIONS_ID_TOKEN_REQUEST_TOKEN --exclude-env ACTIONS_ID_TOKEN_REQUEST_URL --exclude-env COPILOT_GITHUB_TOKEN --exclude-env MCP_GATEWAY_API_KEY --mount /tmp/gh-aw:/tmp/gh-aw:rw --log-level info --skip-pull \
|
||
-- /bin/bash -c 'set +o histexpand; export PATH="${RUNNER_TEMP}/gh-aw/mcp-cli/bin:$PATH" && : "${RUNNER_TOOL_CACHE:?RUNNER_TOOL_CACHE must be set}"; GH_AW_TOOL_CACHE="$RUNNER_TOOL_CACHE"; export PATH="$(find "$GH_AW_TOOL_CACHE" -maxdepth 5 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true; [ -n "$ERLANG_HOME" ] && export PATH="$ERLANG_HOME/bin:$PATH" || true && GH_AW_NODE_EXEC="${GH_AW_NODE_BIN:-}"; if [ -z "$GH_AW_NODE_EXEC" ] || [ ! -x "$GH_AW_NODE_EXEC" ]; then GH_AW_NODE_EXEC="$(command -v node 2>/dev/null || true)"; fi; if [ -z "$GH_AW_NODE_EXEC" ]; then echo "node runtime missing on this runner — check runtimes.node in workflow YAML" >&2; exit 127; fi; GH_AW_NPM_GLOBAL_ROOT="$(npm root -g 2>/dev/null || true)"; if [ -n "$GH_AW_NPM_GLOBAL_ROOT" ]; then export NODE_PATH="${GH_AW_NPM_GLOBAL_ROOT}${NODE_PATH:+:${NODE_PATH}}"; fi; "$GH_AW_NODE_EXEC" "${RUNNER_TEMP}/gh-aw/actions/copilot_harness.cjs" "${RUNNER_TEMP}/gh-aw/bin/copilot" --add-dir /tmp/gh-aw/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --no-ask-user --allow-tool safeoutputs --allow-tool '\''shell(cat)'\'' --allow-tool '\''shell(date)'\'' --allow-tool '\''shell(echo)'\'' --allow-tool '\''shell(grep)'\'' --allow-tool '\''shell(head)'\'' --allow-tool '\''shell(ls)'\'' --allow-tool '\''shell(printf)'\'' --allow-tool '\''shell(pwd)'\'' --allow-tool '\''shell(safeoutputs)'\'' --allow-tool '\''shell(safeoutputs:*)'\'' --allow-tool '\''shell(sort)'\'' --allow-tool '\''shell(tail)'\'' --allow-tool '\''shell(uniq)'\'' --allow-tool '\''shell(wc)'\'' --allow-tool '\''shell(yq)'\'' --allow-tool write --deny-tool write --deny-tool '\''shell(cat)'\'' --deny-tool '\''shell(date)'\'' --deny-tool '\''shell(echo)'\'' --deny-tool '\''shell(grep)'\'' --deny-tool '\''shell(head)'\'' --deny-tool '\''shell(ls)'\'' --deny-tool '\''shell(printf)'\'' --deny-tool '\''shell(pwd)'\'' --deny-tool '\''shell(sort)'\'' --deny-tool '\''shell(tail)'\'' --deny-tool '\''shell(uniq)'\'' --deny-tool '\''shell(wc)'\'' --deny-tool '\''shell(yq)'\'' --add-dir "${GITHUB_WORKSPACE}" --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log
|
||
env:
|
||
AWF_REFLECT_ENABLED: 1
|
||
COPILOT_AGENT_RUNNER_TYPE: STANDALONE
|
||
COPILOT_DUMMY_BYOK: dummy-byok-key-for-offline-mode
|
||
COPILOT_GITHUB_TOKEN: ${{ github.token }}
|
||
COPILOT_MODEL: small
|
||
GH_AW_LLM_PROVIDER: github
|
||
GH_AW_MAX_TURNS: 5
|
||
GH_AW_PHASE: agent
|
||
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
|
||
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
|
||
GH_AW_TIMEOUT_MINUTES: 20
|
||
GH_AW_VERSION: v0.86.2
|
||
GITHUB_API_URL: ${{ github.api_url }}
|
||
GITHUB_AW: true
|
||
GITHUB_COPILOT_INTEGRATION_ID: agentic-workflows
|
||
GITHUB_HEAD_REF: ${{ github.head_ref }}
|
||
GITHUB_REF_NAME: ${{ github.ref_name }}
|
||
GITHUB_SERVER_URL: ${{ github.server_url }}
|
||
GITHUB_STEP_SUMMARY: /tmp/gh-aw/agent-step-summary.md
|
||
GITHUB_WORKSPACE: ${{ github.workspace }}
|
||
GIT_AUTHOR_EMAIL: github-actions[bot]@users.noreply.github.com
|
||
GIT_AUTHOR_NAME: github-actions[bot]
|
||
GIT_COMMITTER_EMAIL: github-actions[bot]@users.noreply.github.com
|
||
GIT_COMMITTER_NAME: github-actions[bot]
|
||
RUNNER_TEMP: ${{ runner.temp }}
|
||
S2STOKENS: true
|
||
TRACEPARENT: ${{ env.GITHUB_AW_OTEL_TRACE_ID != '' && env.GITHUB_AW_OTEL_PARENT_SPAN_ID != '' && format('00-{0}-{1}-01', env.GITHUB_AW_OTEL_TRACE_ID, env.GITHUB_AW_OTEL_PARENT_SPAN_ID) || '' }}
|
||
- name: Detect agent errors
|
||
if: always()
|
||
id: detect-agent-errors
|
||
continue-on-error: true
|
||
run: node "${RUNNER_TEMP}/gh-aw/actions/detect_agent_errors.cjs"
|
||
- name: Configure Git credentials
|
||
env:
|
||
GITHUB_REPOSITORY: ${{ github.repository }}
|
||
GITHUB_SERVER_URL: ${{ github.server_url }}
|
||
GITHUB_TOKEN: ${{ github.token }}
|
||
run: bash "${RUNNER_TEMP}/gh-aw/actions/configure_git_credentials.sh"
|
||
- name: Copy Copilot session state files to logs
|
||
if: always()
|
||
continue-on-error: true
|
||
run: bash "${RUNNER_TEMP}/gh-aw/actions/copy_copilot_session_state.sh"
|
||
- 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 "${RUNNER_TEMP}/gh-aw/actions/stop_mcp_gateway.sh" "$GATEWAY_PID"
|
||
- name: Redact secrets in logs
|
||
if: always()
|
||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||
with:
|
||
script: |
|
||
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
|
||
setupGlobals(core, github, context, exec, io, getOctokit);
|
||
const { main } = require('${{ runner.temp }}/gh-aw/actions/redact_secrets.cjs');
|
||
await main();
|
||
env:
|
||
GH_AW_SECRET_NAMES: 'GH_AW_GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,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: Append agent step summary
|
||
if: always()
|
||
run: bash "${RUNNER_TEMP}/gh-aw/actions/append_agent_step_summary.sh"
|
||
- name: Copy Safe Outputs
|
||
if: always()
|
||
env:
|
||
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
|
||
run: |
|
||
mkdir -p /tmp/gh-aw
|
||
cp "$GH_AW_SAFE_OUTPUTS" /tmp/gh-aw/safeoutputs.jsonl 2>/dev/null || true
|
||
- name: Ingest agent output
|
||
id: collect_output
|
||
if: always()
|
||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||
env:
|
||
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
|
||
GH_AW_ALLOWED_DOMAINS: "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com"
|
||
GITHUB_SERVER_URL: ${{ github.server_url }}
|
||
GITHUB_API_URL: ${{ github.api_url }}
|
||
with:
|
||
script: |
|
||
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
|
||
setupGlobals(core, github, context, exec, io, getOctokit);
|
||
const { main } = require('${{ runner.temp }}/gh-aw/actions/collect_ndjson_output.cjs');
|
||
await main();
|
||
- name: Parse agent logs for step summary
|
||
if: always()
|
||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||
env:
|
||
GH_AW_AGENT_OUTPUT: /tmp/gh-aw/sandbox/agent/logs/
|
||
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
|
||
with:
|
||
script: |
|
||
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
|
||
setupGlobals(core, github, context, exec, io, getOctokit);
|
||
const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_copilot_log.cjs');
|
||
await main();
|
||
- name: Parse MCP Gateway logs for step summary
|
||
if: always()
|
||
id: parse-mcp-gateway
|
||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||
with:
|
||
script: |
|
||
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
|
||
setupGlobals(core, github, context, exec, io, getOctokit);
|
||
const { main } = require('${{ runner.temp }}/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: bash "${RUNNER_TEMP}/gh-aw/actions/print_firewall_logs.sh" --rootless
|
||
- name: Parse token usage for step summary
|
||
if: always()
|
||
continue-on-error: true
|
||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||
with:
|
||
script: |
|
||
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
|
||
setupGlobals(core, github, context, exec, io, getOctokit);
|
||
const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_token_usage.cjs');
|
||
await main();
|
||
- name: Print AWF reflect summary
|
||
if: always()
|
||
continue-on-error: true
|
||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||
with:
|
||
script: |
|
||
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
|
||
setupGlobals(core, github, context, exec, io, getOctokit);
|
||
const { main } = require('${{ runner.temp }}/gh-aw/actions/awf_reflect_summary.cjs');
|
||
await main();
|
||
- name: Write agent output placeholder if missing
|
||
if: always()
|
||
run: |
|
||
if [ ! -f /tmp/gh-aw/agent_output.json ]; then
|
||
echo '{"items":[]}' > /tmp/gh-aw/agent_output.json
|
||
fi
|
||
- name: Upload agent artifacts
|
||
if: always()
|
||
continue-on-error: true
|
||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||
with:
|
||
name: agent
|
||
path: |
|
||
/tmp/gh-aw/aw-prompts/prompt.txt
|
||
/tmp/gh-aw/sandbox/agent/logs/
|
||
/tmp/gh-aw/redacted-urls.log
|
||
/tmp/gh-aw/mcp-logs/
|
||
/tmp/gh-aw/agent_usage.json
|
||
/tmp/gh-aw/agent-stdio.log
|
||
/tmp/gh-aw/pre-agent-audit.txt
|
||
/tmp/gh-aw/agent/
|
||
/tmp/gh-aw/github_rate_limits.jsonl
|
||
/tmp/gh-aw/safeoutputs.jsonl
|
||
/tmp/gh-aw/agent_output.json
|
||
/tmp/gh-aw/aw-*.patch
|
||
/tmp/gh-aw/aw-*.bundle
|
||
/tmp/gh-aw/awf-config.json
|
||
/tmp/gh-aw/sandbox/firewall/logs/
|
||
/tmp/gh-aw/sandbox/firewall/audit/
|
||
/tmp/gh-aw/sandbox/firewall/awf-reflect.json
|
||
if-no-files-found: ignore
|
||
|
||
conclusion:
|
||
needs:
|
||
- activation
|
||
- agent
|
||
- detection
|
||
- publish_triage_summary
|
||
- safe_outputs
|
||
if: >
|
||
always() && (needs.agent.result != 'skipped' || needs.activation.outputs.lockdown_check_failed == 'true' ||
|
||
needs.activation.outputs.oauth_token_check_failed == 'true' || needs.activation.outputs.stale_lock_file_failed == 'true' ||
|
||
needs.activation.outputs.daily_ai_credits_exceeded == 'true')
|
||
runs-on: ubuntu-slim
|
||
permissions:
|
||
actions: read
|
||
issues: write
|
||
concurrency:
|
||
group: "gh-aw-conclusion-issue-triage"
|
||
cancel-in-progress: false
|
||
queue: max
|
||
env:
|
||
GH_AW_RUNTIME_FEATURES: ${{ vars.GH_AW_RUNTIME_FEATURES }}
|
||
outputs:
|
||
incomplete_count: ${{ steps.report_incomplete.outputs.incomplete_count }}
|
||
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
|
||
id: setup
|
||
uses: github/gh-aw-actions/setup@6aab9e5b5c91c615506061f09bedd81a23babe3c # v0.86.2
|
||
with:
|
||
destination: ${{ runner.temp }}/gh-aw/actions
|
||
job-name: ${{ github.job }}
|
||
trace-id: ${{ needs.activation.outputs.setup-trace-id }}
|
||
parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }}
|
||
env:
|
||
GH_AW_SETUP_WORKFLOW_NAME: "AI Issue Triage"
|
||
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-triage.lock.yml@${{ github.ref }}
|
||
GH_AW_INFO_VERSION: "1.0.79"
|
||
GH_AW_INFO_AWF_VERSION: "v0.27.44"
|
||
GH_AW_INFO_ENGINE_ID: "copilot"
|
||
- name: Download agent output artifact
|
||
id: download-agent-output
|
||
continue-on-error: true
|
||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||
with:
|
||
name: agent
|
||
path: /tmp/gh-aw/
|
||
- name: Setup agent output environment variable
|
||
id: setup-agent-output-env
|
||
if: steps.download-agent-output.outcome == 'success'
|
||
run: |
|
||
mkdir -p /tmp/gh-aw/
|
||
find "/tmp/gh-aw/" -type f -print
|
||
echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT"
|
||
- name: Download Safe Outputs Items Manifest
|
||
id: download-safe-outputs-manifest
|
||
if: always()
|
||
continue-on-error: true
|
||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||
with:
|
||
name: safe-outputs-items
|
||
path: /tmp/gh-aw/
|
||
- name: Collect usage artifact files
|
||
if: always()
|
||
continue-on-error: true
|
||
run: bash "${RUNNER_TEMP}/gh-aw/actions/collect_usage_artifact_files.sh"
|
||
- name: Upload usage artifact
|
||
if: always()
|
||
continue-on-error: true
|
||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||
with:
|
||
name: usage
|
||
path: |
|
||
/tmp/gh-aw/usage/aw_info.json
|
||
/tmp/gh-aw/usage/aw-info.jsonl
|
||
/tmp/gh-aw/usage/agent_usage.json
|
||
/tmp/gh-aw/usage/agent_usage.jsonl
|
||
/tmp/gh-aw/usage/detection_usage.jsonl
|
||
/tmp/gh-aw/usage/evals.jsonl
|
||
/tmp/gh-aw/usage/github_rate_limits.jsonl
|
||
/tmp/gh-aw/usage/agent/token_usage.jsonl
|
||
/tmp/gh-aw/usage/detection/token_usage.jsonl
|
||
/tmp/gh-aw/usage/activity/summary.json
|
||
if-no-files-found: ignore
|
||
- name: Restore daily AIC usage cache
|
||
id: restore-daily-aic-cache-conclusion
|
||
if: always()
|
||
continue-on-error: true
|
||
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
||
with:
|
||
key: agentic-workflow-usage-issuetriage-${{ github.run_id }}
|
||
restore-keys: agentic-workflow-usage-issuetriage-
|
||
path: /tmp/gh-aw/agentic-workflow-usage-cache.jsonl
|
||
- name: Write daily AIC usage cache entry
|
||
id: write-daily-aic-cache
|
||
if: always()
|
||
continue-on-error: true
|
||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||
with:
|
||
github-token: ${{ github.token }}
|
||
script: |
|
||
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
|
||
setupGlobals(core, github, context);
|
||
const { main } = require('${{ runner.temp }}/gh-aw/actions/write_daily_aic_usage_cache.cjs');
|
||
await main();
|
||
- name: Save daily AIC usage cache
|
||
id: save-daily-aic-cache
|
||
if: always()
|
||
continue-on-error: true
|
||
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
||
with:
|
||
key: agentic-workflow-usage-issuetriage-${{ github.run_id }}
|
||
path: /tmp/gh-aw/agentic-workflow-usage-cache.jsonl
|
||
- name: Upload daily AIC usage cache artifact
|
||
id: upload-daily-aic-cache
|
||
if: always()
|
||
continue-on-error: true
|
||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||
with:
|
||
name: aic-usage-cache
|
||
path: /tmp/gh-aw/agentic-workflow-usage-cache.jsonl
|
||
if-no-files-found: ignore
|
||
retention-days: 7
|
||
- name: Process no-op messages
|
||
id: noop
|
||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||
env:
|
||
GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }}
|
||
GH_AW_NOOP_MAX: "1"
|
||
GH_AW_WORKFLOW_NAME: "AI Issue Triage"
|
||
GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/issue-triage.md"
|
||
GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||
GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }}
|
||
GH_AW_NOOP_REPORT_AS_ISSUE: "false"
|
||
GH_AW_AIC: ${{ needs.agent.outputs.aic }}
|
||
GH_AW_THREAT_DETECTION_AIC: ${{ needs.detection.outputs.aic }}
|
||
GH_AW_AMBIENT_CONTEXT: ${{ needs.agent.outputs.ambient_context }}
|
||
GH_AW_WORKFLOW_ID: "issue-triage"
|
||
with:
|
||
github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
||
script: |
|
||
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
|
||
setupGlobals(core, github, context, exec, io, getOctokit);
|
||
const { main } = require('${{ runner.temp }}/gh-aw/actions/handle_noop_message.cjs');
|
||
await main();
|
||
- name: Log detection run
|
||
id: detection_runs
|
||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||
env:
|
||
GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }}
|
||
GH_AW_WORKFLOW_NAME: "AI Issue Triage"
|
||
GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/issue-triage.md"
|
||
GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||
GH_AW_DETECTION_CONCLUSION: ${{ needs.detection.outputs.detection_conclusion }}
|
||
GH_AW_DETECTION_REASON: ${{ needs.detection.outputs.detection_reason }}
|
||
with:
|
||
github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
||
script: |
|
||
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
|
||
setupGlobals(core, github, context, exec, io, getOctokit);
|
||
const { main } = require('${{ runner.temp }}/gh-aw/actions/handle_detection_runs.cjs');
|
||
await main();
|
||
- name: Record missing tool
|
||
id: missing_tool
|
||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||
env:
|
||
GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }}
|
||
GH_AW_MISSING_TOOL_CREATE_ISSUE: "true"
|
||
GH_AW_WORKFLOW_NAME: "AI Issue Triage"
|
||
GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/issue-triage.md"
|
||
with:
|
||
github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
||
script: |
|
||
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
|
||
setupGlobals(core, github, context, exec, io, getOctokit);
|
||
const { main } = require('${{ runner.temp }}/gh-aw/actions/missing_tool.cjs');
|
||
await main();
|
||
- name: Record incomplete
|
||
id: report_incomplete
|
||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||
env:
|
||
GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }}
|
||
GH_AW_REPORT_INCOMPLETE_CREATE_ISSUE: "true"
|
||
GH_AW_WORKFLOW_NAME: "AI Issue Triage"
|
||
GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/issue-triage.md"
|
||
with:
|
||
github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
||
script: |
|
||
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
|
||
setupGlobals(core, github, context, exec, io, getOctokit);
|
||
const { main } = require('${{ runner.temp }}/gh-aw/actions/report_incomplete_handler.cjs');
|
||
await main();
|
||
- name: Handle agent failure
|
||
id: handle_agent_failure
|
||
if: always()
|
||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||
env:
|
||
GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }}
|
||
GH_AW_WORKFLOW_NAME: "AI Issue Triage"
|
||
GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/issue-triage.md"
|
||
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: "issue-triage"
|
||
GH_AW_ACTION_FAILURE_ISSUE_EXPIRES_HOURS: "168"
|
||
GH_AW_ENGINE_ID: "copilot"
|
||
GH_AW_CHECKOUT_PR_SUCCESS: ${{ needs.agent.outputs.checkout_pr_success }}
|
||
GH_AW_EFFECTIVE_TOKENS: ${{ needs.agent.outputs.effective_tokens || '' }}
|
||
GH_AW_AI_CREDITS_RATE_LIMIT_ERROR: ${{ needs.agent.outputs.ai_credits_rate_limit_error || 'false' }}
|
||
GH_AW_UNKNOWN_MODEL_AI_CREDITS: ${{ needs.agent.outputs.unknown_model_ai_credits || 'false' }}
|
||
GH_AW_AIC: ${{ needs.agent.outputs.aic }}
|
||
GH_AW_THREAT_DETECTION_AIC: ${{ needs.detection.outputs.aic }}
|
||
GH_AW_MAX_AI_CREDITS: "10"
|
||
GH_AW_INFERENCE_ACCESS_ERROR: ${{ needs.agent.outputs.inference_access_error }}
|
||
GH_AW_MCP_POLICY_ERROR: ${{ needs.agent.outputs.mcp_policy_error }}
|
||
GH_AW_AGENTIC_ENGINE_TIMEOUT: ${{ needs.agent.outputs.agentic_engine_timeout }}
|
||
GH_AW_MODEL_NOT_SUPPORTED_ERROR: ${{ needs.agent.outputs.model_not_supported_error }}
|
||
GH_AW_HTTP_400_RESPONSE_ERROR: ${{ needs.agent.outputs.http_400_response_error }}
|
||
GH_AW_MAX_CACHE_MISSES_EXCEEDED: ${{ needs.agent.outputs.max_cache_misses_exceeded }}
|
||
GH_AW_MISSING_MODEL_PRICING_ERROR: ${{ needs.agent.outputs.missing_model_pricing_error }}
|
||
GH_AW_MISSING_MODEL_PRICING_MODEL_NAME: ${{ needs.agent.outputs.missing_model_pricing_model_name }}
|
||
GH_AW_ENGINE_API_HOSTS: "api.enterprise.githubcopilot.com,api.githubcopilot.com,api.business.githubcopilot.com,api.individual.githubcopilot.com"
|
||
GH_AW_LOCKDOWN_CHECK_FAILED: ${{ needs.activation.outputs.lockdown_check_failed }}
|
||
GH_AW_OAUTH_TOKEN_CHECK_FAILED: ${{ needs.activation.outputs.oauth_token_check_failed }}
|
||
GH_AW_STALE_LOCK_FILE_FAILED: ${{ needs.activation.outputs.stale_lock_file_failed }}
|
||
GH_AW_DAILY_AI_CREDITS_EXCEEDED: ${{ needs.activation.outputs.daily_ai_credits_exceeded }}
|
||
GH_AW_DAILY_AI_CREDITS_TOTAL_EFFECTIVE_TOKENS: ${{ needs.activation.outputs.daily_ai_credits_total_effective_tokens }}
|
||
GH_AW_DAILY_AI_CREDITS_THRESHOLD: ${{ needs.activation.outputs.daily_ai_credits_threshold }}
|
||
GH_AW_GROUP_REPORTS: "false"
|
||
GH_AW_FAILURE_REPORT_AS_ISSUE: "false"
|
||
GH_AW_MISSING_TOOL_REPORT_AS_FAILURE: "true"
|
||
GH_AW_MISSING_DATA_REPORT_AS_FAILURE: "true"
|
||
GH_AW_TIMEOUT_MINUTES: "20"
|
||
with:
|
||
github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
||
script: |
|
||
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
|
||
setupGlobals(core, github, context, exec, io, getOctokit);
|
||
const { main } = require('${{ runner.temp }}/gh-aw/actions/handle_agent_failure.cjs');
|
||
await main();
|
||
- name: Report failed jobs
|
||
id: report_failed_jobs
|
||
if: always()
|
||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||
env:
|
||
GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }}
|
||
GH_AW_WORKFLOW_NAME: "AI Issue Triage"
|
||
GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/issue-triage.md"
|
||
GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||
GH_AW_REPORT_FAILED_JOBS: "true"
|
||
with:
|
||
github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
||
script: |
|
||
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
|
||
setupGlobals(core, github, context, exec, io, getOctokit);
|
||
const { main } = require('${{ runner.temp }}/gh-aw/actions/report_failed_jobs.cjs');
|
||
await main();
|
||
|
||
detection:
|
||
needs:
|
||
- activation
|
||
- agent
|
||
if: always() && needs.agent.result != 'skipped'
|
||
runs-on: ubuntu-latest
|
||
permissions:
|
||
contents: read
|
||
copilot-requests: write
|
||
env:
|
||
GH_AW_RUNTIME_FEATURES: ${{ vars.GH_AW_RUNTIME_FEATURES }}
|
||
outputs:
|
||
aic: ${{ steps.parse_detection_token_usage.outputs.aic }}
|
||
detection_conclusion: ${{ steps.detection_conclusion.outputs.conclusion }}
|
||
detection_reason: ${{ steps.detection_conclusion.outputs.reason }}
|
||
detection_success: ${{ steps.detection_conclusion.outputs.success }}
|
||
steps:
|
||
- name: Setup Scripts
|
||
id: setup
|
||
uses: github/gh-aw-actions/setup@6aab9e5b5c91c615506061f09bedd81a23babe3c # v0.86.2
|
||
with:
|
||
destination: ${{ runner.temp }}/gh-aw/actions
|
||
job-name: ${{ github.job }}
|
||
trace-id: ${{ needs.activation.outputs.setup-trace-id }}
|
||
parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }}
|
||
env:
|
||
GH_AW_SETUP_WORKFLOW_NAME: "AI Issue Triage"
|
||
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-triage.lock.yml@${{ github.ref }}
|
||
GH_AW_INFO_VERSION: "1.0.79"
|
||
GH_AW_INFO_AWF_VERSION: "v0.27.44"
|
||
GH_AW_INFO_ENGINE_ID: "copilot"
|
||
- name: Download agent output artifact
|
||
id: download-agent-output
|
||
continue-on-error: true
|
||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||
with:
|
||
name: agent
|
||
path: /tmp/gh-aw/
|
||
- name: Setup agent output environment variable
|
||
id: setup-agent-output-env
|
||
if: steps.download-agent-output.outcome == 'success'
|
||
run: |
|
||
mkdir -p /tmp/gh-aw/
|
||
find "/tmp/gh-aw/" -type f -print
|
||
echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT"
|
||
- name: Checkout repository for patch context
|
||
if: needs.agent.outputs.has_patch == 'true'
|
||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||
with:
|
||
persist-credentials: false
|
||
# --- Threat Detection ---
|
||
- name: Clean stale firewall files from agent artifact
|
||
run: |
|
||
rm -rf /tmp/gh-aw/sandbox/firewall/logs
|
||
rm -rf /tmp/gh-aw/sandbox/firewall/audit
|
||
- name: Download container images
|
||
run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.27.44@sha256:0d727725c737b58c7bdf51f640cffb928385ec46517e0917c7f1a02f1bada8b4 ghcr.io/github/gh-aw-firewall/api-proxy:0.27.44@sha256:b50fbadba138f6e9aba94aca09711335c489bb3b15861220cb66f6092e042dc7 ghcr.io/github/gh-aw-firewall/squid:0.27.44@sha256:83e48bbe12c634be8c228a576832fe45f66c529ac3659db92bddbcf2eeb6d627
|
||
- name: Check if detection needed
|
||
id: detection_guard
|
||
if: always()
|
||
env:
|
||
OUTPUT_TYPES: ${{ needs.agent.outputs.output_types }}
|
||
HAS_PATCH: ${{ needs.agent.outputs.has_patch }}
|
||
run: |
|
||
if [[ -n "$OUTPUT_TYPES" || "$HAS_PATCH" == "true" ]]; then
|
||
echo "run_detection=true" >> "$GITHUB_OUTPUT"
|
||
echo "Detection will run: output_types=$OUTPUT_TYPES, has_patch=$HAS_PATCH"
|
||
else
|
||
echo "run_detection=false" >> "$GITHUB_OUTPUT"
|
||
echo "Detection skipped: no agent outputs or patches to analyze"
|
||
fi
|
||
- name: Clear MCP Config for detection
|
||
if: always() && steps.detection_guard.outputs.run_detection == 'true'
|
||
run: |
|
||
rm -f "${RUNNER_TEMP}/gh-aw/mcp-config/mcp-servers.json"
|
||
rm -f "$HOME/.copilot/mcp-config.json"
|
||
rm -f "$GITHUB_WORKSPACE/.gemini/settings.json"
|
||
- name: Prepare threat detection files
|
||
if: always() && steps.detection_guard.outputs.run_detection == 'true'
|
||
run: |
|
||
bash "${RUNNER_TEMP}/gh-aw/actions/prepare_threat_detection_files.sh"
|
||
- name: Setup threat detection
|
||
if: always() && steps.detection_guard.outputs.run_detection == 'true'
|
||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||
env:
|
||
WORKFLOW_NAME: "AI Issue Triage"
|
||
WORKFLOW_DESCRIPTION: "Maintain one concise issue summary with likely duplicates and missing-information guidance."
|
||
HAS_PATCH: ${{ needs.agent.outputs.has_patch }}
|
||
GH_AW_DETECTION_CONTINUE_ON_ERROR: "true"
|
||
with:
|
||
script: |
|
||
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
|
||
setupGlobals(core, github, context, exec, io, getOctokit);
|
||
const { main } = require('${{ runner.temp }}/gh-aw/actions/setup_threat_detection.cjs');
|
||
await main();
|
||
- name: Ensure threat-detection directory and log
|
||
if: always() && steps.detection_guard.outputs.run_detection == 'true'
|
||
run: |
|
||
mkdir -p /tmp/gh-aw/threat-detection
|
||
touch /tmp/gh-aw/threat-detection/detection.log
|
||
rm -f /tmp/gh-aw/step-summary.md
|
||
touch /tmp/gh-aw/step-summary.md
|
||
- name: Setup Node.js
|
||
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
|
||
with:
|
||
node-version: '24'
|
||
package-manager-cache: false
|
||
- name: Install ripgrep
|
||
run: bash "${RUNNER_TEMP}/gh-aw/actions/install_ripgrep.sh"
|
||
- name: Install GitHub Copilot CLI
|
||
run: bash "${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh"
|
||
env:
|
||
GH_HOST: github.com
|
||
GH_AW_COMPILED_VERSION: v0.86.2
|
||
- name: Install AWF binary
|
||
run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.27.44
|
||
- name: Execute GitHub Copilot CLI
|
||
if: always() && steps.detection_guard.outputs.run_detection == 'true'
|
||
continue-on-error: true
|
||
id: detection_agentic_execution
|
||
# Copilot CLI tool arguments (sorted):
|
||
timeout-minutes: 20
|
||
run: |
|
||
set -o pipefail
|
||
printf '%s' "$(date +%s%3N)" > /tmp/gh-aw/agent_cli_start_ms.txt
|
||
trap 'gh_aw_exit_code=$?; mkdir -p /tmp/gh-aw >/dev/null 2>&1 || true; printf "%s" "$gh_aw_exit_code" > /tmp/gh-aw/agent_execution_exit_code.txt || true; rm -f "$HOME/.copilot/settings.json"' EXIT
|
||
mkdir -p "$HOME/.copilot"
|
||
printf '%s' '{"builtInAgents":{"rubberDuck":false}}' > "$HOME/.copilot/settings.json"
|
||
export XDG_CONFIG_HOME="$HOME"
|
||
GH_AW_COPILOT_SRC="$(command -v copilot 2>/dev/null || true)"
|
||
if [ -z "$GH_AW_COPILOT_SRC" ] || [ ! -x "$GH_AW_COPILOT_SRC" ]; then
|
||
echo "GitHub Copilot CLI executable not found on PATH after installation" >&2
|
||
exit 127
|
||
fi
|
||
GH_AW_COPILOT_BIN="${RUNNER_TEMP}/gh-aw/bin/copilot"
|
||
mkdir -p "${RUNNER_TEMP}/gh-aw/bin"
|
||
if [ "$GH_AW_COPILOT_SRC" != "$GH_AW_COPILOT_BIN" ]; then
|
||
cp "$GH_AW_COPILOT_SRC" "$GH_AW_COPILOT_BIN"
|
||
fi
|
||
chmod 755 "$GH_AW_COPILOT_BIN"
|
||
|
||
touch /tmp/gh-aw/agent-step-summary.md
|
||
GH_AW_NODE_BIN=$(command -v node 2>/dev/null || true)
|
||
export GH_AW_NODE_BIN
|
||
export COPILOT_API_KEY="$COPILOT_DUMMY_BYOK"
|
||
(umask 177 && touch /tmp/gh-aw/threat-detection/detection.log)
|
||
GH_AW_MAX_AI_CREDITS="${GH_AW_MAX_AI_CREDITS:-400}"
|
||
printf '%s\n' "{\"\$schema\":\"https://github.com/github/gh-aw-firewall/releases/download/v0.27.44/awf-config.schema.json\",\"network\":{\"allowDomains\":[\"api.business.githubcopilot.com\",\"api.enterprise.githubcopilot.com\",\"api.github.com\",\"api.githubcopilot.com\",\"api.individual.githubcopilot.com\",\"github.com\",\"host.docker.internal\",\"registry.npmjs.org\",\"telemetry.enterprise.githubcopilot.com\"]},\"apiProxy\":{\"enabled\":true,\"enableTokenSteering\":true,\"maxRuns\":500,\"maxAiCredits\":${GH_AW_MAX_AI_CREDITS},\"maxCacheMisses\":5,\"models\":{\"agent\":[\"sonnet-6x\",\"gpt-5.4\",\"gpt-5.5\",\"gpt-5.6\",\"gpt-5.3\",\"gemini-pro\",\"any\"],\"antigravity\":[\"copilot/antigravity*\",\"google/antigravity*\",\"gemini/antigravity*\"],\"any\":[\"copilot/*\",\"anthropic/*\",\"openai/*\",\"google/*\",\"gemini/*\"],\"auto\":[\"copilot/auto\",\"large\"],\"claude\":[\"agent\"],\"codex\":[\"agent\"],\"coding\":[\"copilot/gpt-5*codex*\",\"openai/gpt-5*codex*\",\"gpt-5-codex\",\"kimi\"],\"computer-use\":[\"copilot/*computer-use*\",\"google/*computer-use*\",\"gemini/*computer-use*\",\"openai/*computer-use*\"],\"copilot\":[\"agent\"],\"deep-research\":[\"copilot/deep-research*\",\"copilot/o3-deep-research*\",\"copilot/o4-mini-deep-research*\",\"google/deep-research*\",\"gemini/deep-research*\",\"openai/o3-deep-research*\",\"openai/o4-mini-deep-research*\"],\"detection\":[\"small\"],\"evals\":[\"small\"],\"fable\":[\"copilot/*fable*\",\"anthropic/*fable*\"],\"gemini\":[\"agent\"],\"gemini-3-flash\":[\"copilot/gemini-3*flash*\",\"google/gemini-3*flash*\",\"gemini/gemini-3*flash*\"],\"gemini-3-pro\":[\"copilot/gemini-3*pro*\",\"google/gemini-3*pro*\",\"google/nano-banana*\",\"gemini/gemini-3*pro*\"],\"gemini-3.1-flash\":[\"copilot/gemini-3.1*flash*\",\"google/gemini-3.1*flash*\",\"gemini/gemini-3.1*flash*\"],\"gemini-3.1-pro\":[\"copilot/gemini-3.1*pro*\",\"google/gemini-3.1*pro*\",\"gemini/gemini-3.1*pro*\"],\"gemini-3.5-flash\":[\"copilot/gemini-3.5*flash*\",\"google/gemini-3.5*flash*\",\"gemini/gemini-3.5*flash*\"],\"gemini-3.6-flash\":[\"copilot/gemini-3.6*flash*\",\"google/gemini-3.6*flash*\",\"gemini/gemini-3.6*flash*\"],\"gemini-flash\":[\"copilot/gemini-*flash*\",\"google/gemini-*flash*\",\"gemini/gemini-*flash*\"],\"gemini-flash-lite\":[\"copilot/gemini-*flash*lite*\",\"google/gemini-*flash*lite*\",\"gemini/gemini-*flash*lite*\"],\"gemini-omni\":[\"copilot/gemini-omni*\",\"google/gemini-omni*\",\"gemini/gemini-omni*\"],\"gemini-pro\":[\"copilot/gemini-*pro*\",\"google/gemini-*pro*\",\"gemini/gemini-*pro*\"],\"gemma\":[\"copilot/gemma*\",\"google/gemma*\",\"gemini/gemma*\"],\"gpt-5\":[\"copilot/gpt-5*\",\"openai/gpt-5*\"],\"gpt-5-codex\":[\"copilot/gpt-5*codex*\",\"openai/gpt-5*codex*\"],\"gpt-5-mini\":[\"copilot/gpt-5*mini*\",\"openai/gpt-5*mini*\"],\"gpt-5-nano\":[\"copilot/gpt-5*nano*\",\"openai/gpt-5*nano*\"],\"gpt-5-pro\":[\"copilot/gpt-5*pro*\",\"openai/gpt-5*pro*\"],\"gpt-5.1\":[\"copilot/gpt-5.1*\",\"openai/gpt-5.1*\"],\"gpt-5.2\":[\"copilot/gpt-5.2*\",\"openai/gpt-5.2*\"],\"gpt-5.3\":[\"copilot/gpt-5.3*\",\"openai/gpt-5.3*\"],\"gpt-5.4\":[\"copilot/gpt-5.4*\",\"openai/gpt-5.4*\"],\"gpt-5.5\":[\"copilot/gpt-5.5*\",\"openai/gpt-5.5*\"],\"gpt-5.6\":[\"copilot/gpt-5.6*\",\"openai/gpt-5.6*\"],\"grok\":[\"copilot/*grok*\",\"openai/*grok*\"],\"haiku\":[\"copilot/*haiku*\",\"anthropic/*haiku*\"],\"image-generation\":[\"copilot/gpt-image*\",\"openai/gpt-image*\",\"openai/chatgpt-image*\",\"copilot/gemini-*image*\",\"google/gemini-*image*\",\"gemini/gemini-*image*\",\"google/imagen*\"],\"kimi\":[\"copilot/kimi*\",\"openai/kimi*\"],\"kiwi\":[\"copilot/kiwi*\",\"openai/kiwi*\"],\"large\":[\"sonnet\",\"gpt-5-pro\",\"gpt-5\",\"gemini-pro\"],\"lyria\":[\"google/lyria*\",\"gemini/lyria*\",\"copilot/lyria*\"],\"mai-code\":[\"copilot/MAI-Code*\",\"copilot/mai-code*\",\"openai/MAI-Code*\"],\"mai-code-1-flash-picker\":[\"copilot/MAI-Code-1-Flash-picker*\",\"copilot/mai-code-1-flash-picker*\",\"openai/MAI-Code-1-Flash-picker*\"],\"mini\":[\"haiku\",\"gpt-5-mini\",\"gpt-5-nano\",\"gemini-flash-lite\"],\"nano-banana\":[\"copilot/nano-banana*\",\"google/nano-banana*\",\"gemini/nano-banana*\"],\"opus\":[\"copilot/*opus*\",\"anthropic/*opus*\"],\"opusplan\":[\"opus?effort=high\"],\"raptor-mini\":[\"copilot/raptor*\",\"openai/raptor*\"],\"reasoning\":[\"copilot/o1*\",\"copilot/o3*\",\"copilot/o4*\",\"openai/o1*\",\"openai/o3*\",\"openai/o4*\"],\"robotics\":[\"copilot/*robotics*\",\"google/*robotics*\",\"gemini/*robotics*\"],\"small\":[\"mini\"],\"small-agent\":[\"haiku\",\"gpt-5-mini\",\"gemini-flash\"],\"sonnet\":[\"copilot/*sonnet*\",\"anthropic/*sonnet*\"],\"sonnet-6x\":[\"copilot/*sonnet-4.5*\",\"copilot/*sonnet-4.6*\",\"copilot/*sonnet-5*\",\"copilot/*sonnet-4-5-*\",\"anthropic/*sonnet-4-5-*\",\"copilot/*sonnet-4-6*\",\"anthropic/*sonnet-4-6*\",\"anthropic/*sonnet-5*\"],\"summarization\":[\"haiku\",\"gpt-5-mini\",\"gemini-flash-lite\",\"mini\"],\"veo\":[\"google/veo*\",\"gemini/veo*\"],\"vision\":[\"copilot/gemini-*image*\",\"google/gemini-*image*\",\"gemini/gemini-*image*\",\"copilot/gemini-*flash*\",\"google/gemini-*flash*\",\"gemini/gemini-*flash*\"]}},\"container\":{\"imageTag\":\"0.27.44,squid=sha256:83e48bbe12c634be8c228a576832fe45f66c529ac3659db92bddbcf2eeb6d627,agent=sha256:0d727725c737b58c7bdf51f640cffb928385ec46517e0917c7f1a02f1bada8b4,api-proxy=sha256:b50fbadba138f6e9aba94aca09711335c489bb3b15861220cb66f6092e042dc7,cli-proxy=sha256:c064d15974f7c933ec7d3f7b4038f4fd203547b3154bdc821afd379144887eff\"},\"logging\":{\"proxyLogsDir\":\"/tmp/gh-aw/sandbox/firewall/logs\",\"auditDir\":\"/tmp/gh-aw/sandbox/firewall/audit\"}}" > "${RUNNER_TEMP}/gh-aw/awf-config.json"
|
||
cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json
|
||
export GH_AW_MODELS_JSON_PATH="/tmp/gh-aw/models.json"
|
||
GH_AW_DOCKER_HOST=""
|
||
if [[ "${DOCKER_HOST:-}" =~ ^tcp:// ]]; then
|
||
GH_AW_DOCKER_HOST="${DOCKER_HOST}"
|
||
fi
|
||
if [[ "${DOCKER_HOST:-}" =~ ^tcp:// ]]; then
|
||
_GH_AW_CHROOT_JSON=$(jq -c --arg src "${RUNNER_TEMP}/gh-aw" --arg user "$(id -un)" --argjson uid "$(id -u)" --argjson gid "$(id -g)" --arg home "${RUNNER_TEMP}/gh-aw/home" '.chroot={"binariesSourcePath":$src,"identity":{"user":$user,"uid":$uid,"gid":$gid,"home":$home}}' "${RUNNER_TEMP}/gh-aw/awf-config.json") || { echo "chroot config patch failed" >&2; exit 1; }
|
||
printf '%s\n' "$_GH_AW_CHROOT_JSON" > "${RUNNER_TEMP}/gh-aw/awf-config.json"
|
||
printf '%s\n' "$_GH_AW_CHROOT_JSON" > "${RUNNER_TEMP}/gh-aw/awf-config.json"
|
||
fi
|
||
GH_AW_TOOL_CACHE_MOUNT=""
|
||
GH_AW_TOOL_CACHE="${RUNNER_TOOL_CACHE:?RUNNER_TOOL_CACHE must be set}"
|
||
if [ -d "$GH_AW_TOOL_CACHE" ]; then
|
||
if [[ "$GH_AW_TOOL_CACHE" != /opt/* ]]; then
|
||
GH_AW_TOOL_CACHE_MOUNT="$GH_AW_TOOL_CACHE:$GH_AW_TOOL_CACHE:ro"
|
||
fi
|
||
fi
|
||
# shellcheck disable=SC1003,SC2016,SC2086
|
||
awf --config "${RUNNER_TEMP}/gh-aw/awf-config.json" --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" ${GH_AW_TOOL_CACHE_MOUNT:+--mount "$GH_AW_TOOL_CACHE_MOUNT"} ${GH_AW_DOCKER_HOST:+--docker-host "$GH_AW_DOCKER_HOST"} --env-all --exclude-env ACTIONS_ID_TOKEN_REQUEST_TOKEN --exclude-env ACTIONS_ID_TOKEN_REQUEST_URL --exclude-env COPILOT_GITHUB_TOKEN --mount /tmp/gh-aw:/tmp/gh-aw:rw --log-level info --skip-pull \
|
||
-- /bin/bash -c 'set +o histexpand; : "${RUNNER_TOOL_CACHE:?RUNNER_TOOL_CACHE must be set}"; GH_AW_TOOL_CACHE="$RUNNER_TOOL_CACHE"; export PATH="$(find "$GH_AW_TOOL_CACHE" -maxdepth 5 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true; [ -n "$ERLANG_HOME" ] && export PATH="$ERLANG_HOME/bin:$PATH" || true && GH_AW_NODE_EXEC="${GH_AW_NODE_BIN:-}"; if [ -z "$GH_AW_NODE_EXEC" ] || [ ! -x "$GH_AW_NODE_EXEC" ]; then GH_AW_NODE_EXEC="$(command -v node 2>/dev/null || true)"; fi; if [ -z "$GH_AW_NODE_EXEC" ]; then echo "node runtime missing on this runner — check runtimes.node in workflow YAML" >&2; exit 127; fi; GH_AW_NPM_GLOBAL_ROOT="$(npm root -g 2>/dev/null || true)"; if [ -n "$GH_AW_NPM_GLOBAL_ROOT" ]; then export NODE_PATH="${GH_AW_NPM_GLOBAL_ROOT}${NODE_PATH:+:${NODE_PATH}}"; fi; "$GH_AW_NODE_EXEC" "${RUNNER_TEMP}/gh-aw/actions/copilot_harness.cjs" "${RUNNER_TEMP}/gh-aw/bin/copilot" --add-dir /tmp/gh-aw/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --no-ask-user --allow-all-tools --deny-tool write --deny-tool '\''shell(cat)'\'' --deny-tool '\''shell(date)'\'' --deny-tool '\''shell(echo)'\'' --deny-tool '\''shell(grep)'\'' --deny-tool '\''shell(head)'\'' --deny-tool '\''shell(ls)'\'' --deny-tool '\''shell(printf)'\'' --deny-tool '\''shell(pwd)'\'' --deny-tool '\''shell(sort)'\'' --deny-tool '\''shell(tail)'\'' --deny-tool '\''shell(uniq)'\'' --deny-tool '\''shell(wc)'\'' --deny-tool '\''shell(yq)'\'' --add-dir "${GITHUB_WORKSPACE}" --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' 2>&1 | tee -a /tmp/gh-aw/threat-detection/detection.log
|
||
env:
|
||
GITHUB_STEP_SUMMARY: /tmp/gh-aw/step-summary.md
|
||
AWF_REFLECT_ENABLED: 1
|
||
COPILOT_AGENT_RUNNER_TYPE: STANDALONE
|
||
COPILOT_DUMMY_BYOK: dummy-byok-key-for-offline-mode
|
||
COPILOT_GITHUB_TOKEN: ${{ github.token }}
|
||
COPILOT_MODEL: small
|
||
GH_AW_LLM_PROVIDER: github
|
||
GH_AW_MAX_AI_CREDITS: ${{ vars.GH_AW_DEFAULT_DETECTION_MAX_AI_CREDITS || '400' }}
|
||
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
|
||
GH_AW_PHASE: detection
|
||
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
|
||
GH_AW_TIMEOUT_MINUTES: 20
|
||
GH_AW_VERSION: v0.86.2
|
||
GITHUB_API_URL: ${{ github.api_url }}
|
||
GITHUB_AW: true
|
||
GITHUB_COPILOT_INTEGRATION_ID: agentic-workflows
|
||
GITHUB_HEAD_REF: ${{ github.head_ref }}
|
||
GITHUB_REF_NAME: ${{ github.ref_name }}
|
||
GITHUB_SERVER_URL: ${{ github.server_url }}
|
||
GITHUB_WORKSPACE: ${{ github.workspace }}
|
||
GIT_AUTHOR_EMAIL: github-actions[bot]@users.noreply.github.com
|
||
GIT_AUTHOR_NAME: github-actions[bot]
|
||
GIT_COMMITTER_EMAIL: github-actions[bot]@users.noreply.github.com
|
||
GIT_COMMITTER_NAME: github-actions[bot]
|
||
RUNNER_TEMP: ${{ runner.temp }}
|
||
S2STOKENS: true
|
||
TRACEPARENT: ${{ env.GITHUB_AW_OTEL_TRACE_ID != '' && env.GITHUB_AW_OTEL_PARENT_SPAN_ID != '' && format('00-{0}-{1}-01', env.GITHUB_AW_OTEL_TRACE_ID, env.GITHUB_AW_OTEL_PARENT_SPAN_ID) || '' }}
|
||
- name: Echo detection step summary
|
||
if: always() && steps.detection_guard.outputs.run_detection == 'true'
|
||
continue-on-error: true
|
||
run: |
|
||
if [ -s /tmp/gh-aw/step-summary.md ]; then
|
||
cat /tmp/gh-aw/step-summary.md
|
||
fi
|
||
- name: Render detection log
|
||
if: always() && steps.detection_guard.outputs.run_detection == 'true'
|
||
continue-on-error: true
|
||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||
with:
|
||
script: |
|
||
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
|
||
setupGlobals(core, github, context, exec, io, getOctokit);
|
||
const { main } = require('${{ runner.temp }}/gh-aw/actions/render_detection_log.cjs');
|
||
await main();
|
||
- name: Parse threat detection token usage for step summary
|
||
id: parse_detection_token_usage
|
||
if: always()
|
||
continue-on-error: true
|
||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||
env:
|
||
GH_AW_TOKEN_USAGE_SUMMARY_TITLE: Threat Detection Token Usage
|
||
with:
|
||
script: |
|
||
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
|
||
setupGlobals(core, github, context, exec, io, getOctokit);
|
||
const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_token_usage.cjs');
|
||
await main();
|
||
- name: Upload threat detection log
|
||
if: always() && steps.detection_guard.outputs.run_detection == 'true'
|
||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||
with:
|
||
name: detection
|
||
path: /tmp/gh-aw/threat-detection/detection.log
|
||
if-no-files-found: ignore
|
||
- name: Parse and conclude threat detection
|
||
id: detection_conclusion
|
||
if: always()
|
||
continue-on-error: true
|
||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||
env:
|
||
RUN_DETECTION: ${{ steps.detection_guard.outputs.run_detection }}
|
||
DETECTION_AGENTIC_EXECUTION_OUTCOME: ${{ steps.detection_agentic_execution.outcome }}
|
||
GH_AW_DETECTION_CONTINUE_ON_ERROR: "true"
|
||
with:
|
||
script: |
|
||
try {
|
||
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
|
||
setupGlobals(core, github, context, exec, io, getOctokit);
|
||
const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_threat_detection_results.cjs');
|
||
await main();
|
||
} catch (loadErr) {
|
||
const continueOnError = process.env.GH_AW_DETECTION_CONTINUE_ON_ERROR !== 'false';
|
||
const detectionExecutionFailed = process.env.DETECTION_AGENTIC_EXECUTION_OUTCOME === 'failure';
|
||
const msg = 'ERR_SYSTEM: \u274C Unexpected error loading threat detection module: ' + (loadErr && loadErr.message ? loadErr.message : String(loadErr));
|
||
core.error(msg);
|
||
core.setOutput('reason', 'parse_error');
|
||
if (continueOnError && !detectionExecutionFailed) {
|
||
core.warning('\u26A0\uFE0F ' + msg);
|
||
core.setOutput('conclusion', 'warning');
|
||
core.setOutput('success', 'false');
|
||
} else {
|
||
core.setOutput('conclusion', 'failure');
|
||
core.setOutput('success', 'false');
|
||
core.setFailed(msg);
|
||
}
|
||
}
|
||
|
||
pre_activation:
|
||
runs-on: ubuntu-slim
|
||
permissions:
|
||
actions: read
|
||
env:
|
||
GH_AW_RUNTIME_FEATURES: ${{ vars.GH_AW_RUNTIME_FEATURES }}
|
||
outputs:
|
||
activated: ${{ steps.check_rate_limit.outputs.rate_limit_ok == 'true' }}
|
||
matched_command: ''
|
||
setup-parent-span-id: ${{ steps.setup.outputs.parent-span-id || steps.setup.outputs.span-id }}
|
||
setup-span-id: ${{ steps.setup.outputs.span-id }}
|
||
setup-trace-id: ${{ steps.setup.outputs.trace-id }}
|
||
steps:
|
||
- name: Setup Scripts
|
||
id: setup
|
||
uses: github/gh-aw-actions/setup@6aab9e5b5c91c615506061f09bedd81a23babe3c # v0.86.2
|
||
with:
|
||
destination: ${{ runner.temp }}/gh-aw/actions
|
||
job-name: ${{ github.job }}
|
||
env:
|
||
GH_AW_SETUP_WORKFLOW_NAME: "AI Issue Triage"
|
||
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-triage.lock.yml@${{ github.ref }}
|
||
GH_AW_INFO_VERSION: "1.0.79"
|
||
GH_AW_INFO_AWF_VERSION: "v0.27.44"
|
||
GH_AW_INFO_ENGINE_ID: "copilot"
|
||
- name: Check user rate limit
|
||
id: check_rate_limit
|
||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||
env:
|
||
GH_AW_RATE_LIMIT_MAX: "5"
|
||
GH_AW_RATE_LIMIT_WINDOW: "60"
|
||
GH_AW_RATE_LIMIT_EVENTS: "issues"
|
||
GH_AW_RATE_LIMIT_IGNORED_ROLES: "admin,maintain,write"
|
||
with:
|
||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||
script: |
|
||
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
|
||
setupGlobals(core, github, context, exec, io, getOctokit);
|
||
const { main } = require('${{ runner.temp }}/gh-aw/actions/check_rate_limit.cjs');
|
||
await main();
|
||
|
||
publish_triage_summary:
|
||
needs:
|
||
- agent
|
||
- detection
|
||
if: >
|
||
(!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'publish_triage_summary') &&
|
||
(needs.detection.result == 'success' && needs.detection.outputs.detection_success == 'true')
|
||
runs-on: ubuntu-slim
|
||
permissions:
|
||
contents: read
|
||
issues: write
|
||
steps:
|
||
- name: Download agent output artifact
|
||
continue-on-error: true
|
||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||
with:
|
||
name: agent
|
||
path: ${{ runner.temp }}/gh-aw/safe-jobs/
|
||
- name: Check out trusted workflow source
|
||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||
env:
|
||
GH_AW_AGENT_OUTPUT: ${{ runner.temp }}/gh-aw/safe-jobs/agent_output.json
|
||
with:
|
||
persist-credentials: false
|
||
ref: ${{ github.sha }}
|
||
- name: Set up Python
|
||
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
||
env:
|
||
GH_AW_AGENT_OUTPUT: ${{ runner.temp }}/gh-aw/safe-jobs/agent_output.json
|
||
with:
|
||
python-version: "3.12"
|
||
- name: Rebuild current deterministic evidence
|
||
run: python .github/scripts/issue-triage/issue-context.py "$GITHUB_EVENT_PATH" "$RUNNER_TEMP/verified-issue-context.md" "$RUNNER_TEMP/verified-triage-event.json" "$RUNNER_TEMP/verified-evidence.json"
|
||
env:
|
||
GH_AW_AGENT_OUTPUT: ${{ runner.temp }}/gh-aw/safe-jobs/agent_output.json
|
||
GITHUB_TOKEN: ${{ github.token }}
|
||
ISSUE_TRIAGE_FORCE_EVIDENCE: "true"
|
||
- name: Rebuild sanitized bug report context
|
||
run: python .github/scripts/issue-triage/bug-report-analyzer.py "$RUNNER_TEMP/verified-triage-event.json" "$RUNNER_TEMP/verified-bug-report-context.md"
|
||
env:
|
||
GH_AW_AGENT_OUTPUT: ${{ runner.temp }}/gh-aw/safe-jobs/agent_output.json
|
||
- name: Verify agent output against current evidence
|
||
run: python .github/scripts/issue-triage/verify-agent-output.py "$GH_AW_AGENT_OUTPUT" "$RUNNER_TEMP/verified-evidence.json" "$RUNNER_TEMP/verified-bug-report-context.md" "$RUNNER_TEMP/verified-triage-output.json"
|
||
env:
|
||
GH_AW_AGENT_OUTPUT: ${{ runner.temp }}/gh-aw/safe-jobs/agent_output.json
|
||
- name: Upsert canonical triage summary
|
||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||
env:
|
||
GH_AW_AGENT_OUTPUT: ${{ runner.temp }}/gh-aw/safe-jobs/agent_output.json
|
||
ISSUE_TRIAGE_VERIFIED_OUTPUT: ${{ runner.temp }}/verified-triage-output.json
|
||
with:
|
||
script: |
|
||
const fs = require('fs');
|
||
|
||
const marker = '<!-- powertoys-ai-triage:canonical:v1 -->';
|
||
const outputPath = process.env.GH_AW_AGENT_OUTPUT;
|
||
if (!outputPath || !fs.existsSync(outputPath)) {
|
||
core.setFailed('Agent output is unavailable');
|
||
return;
|
||
}
|
||
|
||
const output = JSON.parse(fs.readFileSync(outputPath, 'utf8'));
|
||
const item = output.items?.find(
|
||
candidate => candidate.type === 'publish_triage_summary'
|
||
);
|
||
if (!item) {
|
||
core.setFailed('The agent did not provide a triage summary');
|
||
return;
|
||
}
|
||
const verifiedPath = process.env.ISSUE_TRIAGE_VERIFIED_OUTPUT;
|
||
if (!verifiedPath || !fs.existsSync(verifiedPath)) {
|
||
core.setFailed('Verified triage output is unavailable');
|
||
return;
|
||
}
|
||
const verified = JSON.parse(fs.readFileSync(verifiedPath, 'utf8'));
|
||
|
||
const bounded = (value, max, fallback) => {
|
||
if (typeof value !== 'string') return fallback;
|
||
const normalized = value.replace(/\0/g, '').trim();
|
||
return normalized ? normalized.slice(0, max) : fallback;
|
||
};
|
||
const escapeMarkdown = value => String(value)
|
||
.replaceAll('\\', '\\\\')
|
||
.replaceAll('&', '&')
|
||
.replaceAll('<', '<')
|
||
.replaceAll('>', '>')
|
||
.replaceAll('@', '@\u200B')
|
||
.replace(/([`*_{}\[\]()#+.!|~-])/g, '\\$1')
|
||
.replace(/\r?\n+/g, ' ')
|
||
.trim();
|
||
const formatTechnicalMarkdown = value => {
|
||
const tokens = [];
|
||
const withPlaceholders = String(value)
|
||
.replace(/\0/g, '')
|
||
.replace(
|
||
/\b(?:0x[0-9a-f]{6,}|[\w.-]+\.(?:xaml\.cs|dll|exe|json|log|xaml|cs))\b/gi,
|
||
token => {
|
||
const placeholder = `GHCODETOKEN${tokens.length}GH`;
|
||
tokens.push(token);
|
||
return placeholder;
|
||
}
|
||
);
|
||
let formatted = escapeMarkdown(withPlaceholders);
|
||
tokens.forEach((token, index) => {
|
||
formatted = formatted.replace(
|
||
`GHCODETOKEN${index}GH`,
|
||
`\`${token.replaceAll('`', '')}\``
|
||
);
|
||
});
|
||
return formatted;
|
||
};
|
||
const redactDiagnostic = value => String(value)
|
||
.replace(/\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/gi, '<email>')
|
||
.replace(/\b(?:25[0-5]|2[0-4]\d|1?\d?\d)(?:\.(?:25[0-5]|2[0-4]\d|1?\d?\d)){3}\b/g, '<ip-address>')
|
||
.replace(/[A-Z]:\\Users\\[^\\\s"']+/gi, '<user-profile>')
|
||
.replace(/\/(?:home|Users)\/[^/\s"']+/gi, '/<user>')
|
||
.replace(/\b[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}\b/gi, '<guid>')
|
||
.replace(/\bS-1-5-(?:\d+-){1,14}\d+\b/g, '<sid>')
|
||
.replace(/\bhttps?:\/\/[^\s<>"]+/gi, '<url>')
|
||
.replace(/\b(token|secret|password|securitykey)\b\s*[:=]\s*[^\s,;]+/gi, '$1=<redacted>')
|
||
.replace(/\b(?:machine|computer|user)(?:name)?\b\s*[:=]\s*[^\s,;]+/gi, '<identity>=<redacted>');
|
||
|
||
const summary = bounded(item.summary, 800, 'The issue needs maintainer review.');
|
||
const inputSha256 = verified.input_sha256;
|
||
const area = verified.suggested_area;
|
||
const requestedProductLabel = verified.product_label;
|
||
const powertoysVersion = verified.powertoys_version;
|
||
const reportedVersion =
|
||
powertoysVersion === 'Not provided' ? null : powertoysVersion;
|
||
const numericVersion = value => {
|
||
const match = String(value || '').match(
|
||
/\b(?:v)?(\d+(?:\.\d+){1,3})(?:-[A-Za-z0-9.-]+)?\b/
|
||
);
|
||
return match
|
||
? match[1].split('.').map(part => Number(part))
|
||
: null;
|
||
};
|
||
const compareVersions = (left, right) => {
|
||
const leftParts = numericVersion(left);
|
||
const rightParts = numericVersion(right);
|
||
if (!leftParts || !rightParts) return null;
|
||
const width = Math.max(leftParts.length, rightParts.length);
|
||
for (let index = 0; index < width; index += 1) {
|
||
const difference =
|
||
(leftParts[index] || 0) - (rightParts[index] || 0);
|
||
if (difference !== 0) return Math.sign(difference);
|
||
}
|
||
return 0;
|
||
};
|
||
let latestStableVersion = null;
|
||
let latestStableUrl = null;
|
||
try {
|
||
const latestRelease = await github.request(
|
||
'GET /repos/{owner}/{repo}/releases/latest',
|
||
{ owner: 'microsoft', repo: 'PowerToys' }
|
||
);
|
||
if (!latestRelease.data?.prerelease) {
|
||
latestStableVersion = String(
|
||
latestRelease.data?.tag_name || ''
|
||
).match(
|
||
/\b(?:v)?(\d+(?:\.\d+){1,3}(?:-[A-Za-z0-9.-]+)?)\b/
|
||
)?.[1] || null;
|
||
latestStableUrl = /^https:\/\/github\.com\/microsoft\/PowerToys\/releases\/tag\/[^/\s]+$/.test(
|
||
String(latestRelease.data?.html_url || '')
|
||
)
|
||
? latestRelease.data.html_url
|
||
: null;
|
||
}
|
||
} catch (error) {
|
||
core.warning(
|
||
`Latest stable PowerToys release could not be checked: ${error.message}`
|
||
);
|
||
}
|
||
const isOutdated =
|
||
reportedVersion &&
|
||
latestStableVersion &&
|
||
compareVersions(reportedVersion, latestStableVersion) === -1;
|
||
let hasMissingInformation =
|
||
item.has_missing_information === true ||
|
||
item.has_missing_information === 'true';
|
||
let missingInformation = bounded(
|
||
item.missing_information,
|
||
800,
|
||
hasMissingInformation ? 'Additional investigation details are needed.' : 'None'
|
||
);
|
||
const issueKind = verified.issue_kind;
|
||
if (
|
||
issueKind === 'OTHER' &&
|
||
/\b(?:bug report|report ZIP|ZIP file)\b/i.test(missingInformation)
|
||
) {
|
||
hasMissingInformation = false;
|
||
missingInformation = 'None';
|
||
}
|
||
const reproductionQuality = verified.reproduction_quality;
|
||
const bugReportRequirement = verified.bug_report_requirement;
|
||
const bugReportStatus = verified.bug_report_status;
|
||
const requestedBugReportConfidence = String(
|
||
item.bug_report_confidence || ''
|
||
).toUpperCase();
|
||
const bugReportConfidence = ['HIGH', 'MEDIUM', 'LOW', 'NONE'].includes(
|
||
requestedBugReportConfidence
|
||
) ? requestedBugReportConfidence : 'NONE';
|
||
const requestedIssueLanguage = String(
|
||
item.issue_language || ''
|
||
).toUpperCase();
|
||
const issueLanguage = [
|
||
'ENGLISH', 'NON_ENGLISH', 'UNCERTAIN'
|
||
].includes(requestedIssueLanguage)
|
||
? requestedIssueLanguage
|
||
: 'UNCERTAIN';
|
||
const needsEnglishTranslation = issueLanguage === 'NON_ENGLISH';
|
||
const bugReportFindings = bounded(
|
||
redactDiagnostic(
|
||
typeof item.bug_report_findings === 'string'
|
||
? item.bug_report_findings
|
||
: ''
|
||
),
|
||
1200,
|
||
'No diagnostic findings were provided.'
|
||
);
|
||
if (issueKind === 'BUG') {
|
||
const missingReproduction =
|
||
!needsEnglishTranslation &&
|
||
reproductionQuality !== 'SUFFICIENT';
|
||
const missingReport =
|
||
bugReportRequirement === 'REQUIRED' &&
|
||
bugReportStatus !== 'ANALYZED';
|
||
hasMissingInformation = missingReproduction || missingReport;
|
||
if (!hasMissingInformation) {
|
||
missingInformation = 'None';
|
||
} else if (missingReproduction && missingReport) {
|
||
missingInformation = bugReportStatus === 'REJECTED'
|
||
? 'Please provide concrete steps to reproduce and attach a newly generated PowerToys bug report ZIP.'
|
||
: 'Please provide concrete steps to reproduce and attach the PowerToys bug report ZIP.';
|
||
} else if (missingReproduction) {
|
||
missingInformation = 'Please provide concrete steps to reproduce the issue.';
|
||
} else {
|
||
missingInformation = bugReportStatus === 'REJECTED'
|
||
? 'Please attach a newly generated PowerToys bug report ZIP.'
|
||
: 'Please attach the PowerToys bug report ZIP.';
|
||
}
|
||
}
|
||
|
||
let requestedDuplicates;
|
||
try {
|
||
requestedDuplicates = JSON.parse(item.duplicate_candidates_json);
|
||
} catch {
|
||
core.setFailed('duplicate_candidates_json is not valid JSON');
|
||
return;
|
||
}
|
||
if (!Array.isArray(requestedDuplicates) || requestedDuplicates.length > 5) {
|
||
core.setFailed('duplicate_candidates_json must be an array with at most five items');
|
||
return;
|
||
}
|
||
|
||
const issueNumber = context.issue.number;
|
||
const allowedDuplicateNumbers = new Set(
|
||
verified.requested_duplicate_numbers
|
||
);
|
||
const verifiedDuplicates = [];
|
||
const seen = new Set();
|
||
for (const candidate of requestedDuplicates) {
|
||
const number = Number(candidate?.number);
|
||
if (!Number.isSafeInteger(number) || number <= 0 ||
|
||
number === issueNumber || seen.has(number) ||
|
||
!allowedDuplicateNumbers.has(number)) {
|
||
continue;
|
||
}
|
||
seen.add(number);
|
||
try {
|
||
const response = await github.rest.issues.get({
|
||
...context.repo,
|
||
issue_number: number
|
||
});
|
||
if (response.data.pull_request) continue;
|
||
verifiedDuplicates.push({
|
||
number,
|
||
id: response.data.id,
|
||
title: bounded(response.data.title, 300, `Issue ${number}`),
|
||
reason: bounded(candidate?.reason, 300, 'Describes the same underlying report.'),
|
||
confidence: ['HIGH', 'MEDIUM', 'LOW'].includes(
|
||
String(candidate?.confidence || '').toUpperCase()
|
||
) ? String(candidate.confidence).toUpperCase() : 'MEDIUM'
|
||
});
|
||
} catch (error) {
|
||
if (error.status !== 404) throw error;
|
||
}
|
||
}
|
||
const confidenceRank = { HIGH: 3, MEDIUM: 2, LOW: 1 };
|
||
verifiedDuplicates.sort(
|
||
(left, right) =>
|
||
confidenceRank[right.confidence] - confidenceRank[left.confidence] ||
|
||
left.number - right.number
|
||
);
|
||
|
||
const duplicateSection = verifiedDuplicates.length
|
||
? verifiedDuplicates.map(candidate =>
|
||
[
|
||
'<details>',
|
||
`<summary>#${candidate.number} — ${formatTechnicalMarkdown(candidate.title)}</summary>`,
|
||
'',
|
||
`**Why this may be a duplicate:** ${formatTechnicalMarkdown(candidate.reason)}`,
|
||
'</details>'
|
||
].join('\n')
|
||
).join('\n\n')
|
||
: '';
|
||
const author = verified.issue_author;
|
||
const authorActions = [];
|
||
if (hasMissingInformation) {
|
||
authorActions.push(
|
||
`**Needed:** ${formatTechnicalMarkdown(missingInformation)}`
|
||
);
|
||
}
|
||
if (needsEnglishTranslation) {
|
||
authorActions.push(
|
||
'**Needed:** Please translate the issue title and description to English.'
|
||
);
|
||
}
|
||
const updateRecommendation =
|
||
isOutdated
|
||
? [
|
||
'**Recommended:** Please update PowerToys',
|
||
`from \`${reportedVersion.replaceAll('`', '')}\``,
|
||
latestStableUrl
|
||
? `to the latest stable release, [\`${latestStableVersion.replaceAll('`', '')}\`](${latestStableUrl}),`
|
||
: `to the latest stable release, \`${latestStableVersion.replaceAll('`', '')}\`,`,
|
||
'and confirm whether the issue still reproduces.'
|
||
].join(' ')
|
||
: '';
|
||
if (updateRecommendation) {
|
||
authorActions.push(updateRecommendation);
|
||
}
|
||
const authorSection = authorActions.length
|
||
? [
|
||
author
|
||
? `@${author}, please review the following:`
|
||
: 'Issue author, please review the following:',
|
||
'',
|
||
...authorActions.map(action => `- ${action}`)
|
||
]
|
||
: [];
|
||
|
||
const repositoryLabels = await github.paginate(
|
||
github.rest.issues.listLabelsForRepo,
|
||
{ ...context.repo, per_page: 100 }
|
||
);
|
||
const productLabels = repositoryLabels
|
||
.map(label => label.name)
|
||
.filter(name => name.startsWith('Product-'));
|
||
const versionLabels = repositoryLabels
|
||
.map(label => label.name)
|
||
.filter(name => /^\d+\.\d+(?:\.\d+)?(?:-.+)?$/.test(name));
|
||
const normalizeLabel = value => String(value)
|
||
.toLowerCase()
|
||
.replace(/[^a-z0-9]+/g, '');
|
||
const desiredProductLabel =
|
||
productLabels.find(
|
||
label =>
|
||
normalizeLabel(label.slice('Product-'.length)) ===
|
||
normalizeLabel(area)
|
||
) ||
|
||
productLabels.find(
|
||
label => label.toLowerCase() === requestedProductLabel.toLowerCase()
|
||
) ||
|
||
null;
|
||
const desiredVersionLabel =
|
||
versionLabels.find(
|
||
label => label.toLowerCase() === powertoysVersion.toLowerCase()
|
||
) ||
|
||
null;
|
||
|
||
const bodyLines = [
|
||
marker,
|
||
`<!-- powertoys-ai-triage:input-sha256:${inputSha256} -->`,
|
||
'## 🧭 Triage summary',
|
||
''
|
||
];
|
||
|
||
if (authorSection.length) {
|
||
bodyLines.push(
|
||
'### 🙋 For the issue author',
|
||
'',
|
||
...authorSection,
|
||
''
|
||
);
|
||
}
|
||
|
||
bodyLines.push(
|
||
'### 🛠️ For the PowerToys team',
|
||
'',
|
||
[
|
||
desiredProductLabel
|
||
? `**🧩 ${escapeMarkdown(desiredProductLabel.slice('Product-'.length))}**`
|
||
: `**🧩 ${escapeMarkdown(area === 'Unknown' ? 'Unclassified' : area)}**`,
|
||
issueKind === 'BUG' ? '**🐞 Bug**' : '**📌 Issue**',
|
||
powertoysVersion !== 'Not provided'
|
||
? `**📦 PowerToys \`${powertoysVersion.replaceAll('`', '')}\`**`
|
||
: null
|
||
].filter(Boolean).join(' · '),
|
||
'',
|
||
formatTechnicalMarkdown(summary),
|
||
''
|
||
);
|
||
if (issueKind === 'BUG' && bugReportStatus === 'ANALYZED') {
|
||
bodyLines.push(
|
||
'### 🔎 Diagnostic finding',
|
||
'',
|
||
`${formatTechnicalMarkdown(bugReportFindings)} _(${bugReportConfidence.toLowerCase()} confidence)_`,
|
||
''
|
||
);
|
||
} else if (issueKind === 'BUG' && bugReportStatus === 'REJECTED') {
|
||
bodyLines.push(
|
||
'### ⚠️ Bug report',
|
||
'',
|
||
`The attached report could not be safely analyzed: ${formatTechnicalMarkdown(bugReportFindings)}`,
|
||
''
|
||
);
|
||
}
|
||
if (verifiedDuplicates.length) {
|
||
bodyLines.push('### 🔁 Possible duplicates', '', duplicateSection, '');
|
||
}
|
||
if (issueKind === 'BUG') {
|
||
const reportDetail = bugReportStatus === 'ANALYZED'
|
||
? '✅ Analyzed from a sanitized diagnostic subset; the raw archive was discarded.'
|
||
: bugReportRequirement === 'REQUIRED'
|
||
? `⚠️ Required for this failure type; ${bugReportStatus.replaceAll('_', ' ').toLowerCase()}`
|
||
: bugReportRequirement === 'OPTIONAL'
|
||
? 'ℹ️ Not attached; optional for this clear UI/visual report.'
|
||
: 'ℹ️ Not attached; may help later but does not block triage.';
|
||
const reproductionDetail = reproductionQuality === 'SUFFICIENT'
|
||
? '✅ Sufficient'
|
||
: needsEnglishTranslation
|
||
? '⏳ Reassess after English translation'
|
||
: reproductionQuality === 'INSUFFICIENT'
|
||
? '⚠️ Needs more detail'
|
||
: 'Not applicable';
|
||
bodyLines.push(
|
||
'<details>',
|
||
'<summary>🧪 Investigation details</summary>',
|
||
'',
|
||
`- **Reproduction:** ${reproductionDetail}`,
|
||
`- **Bug report:** ${reportDetail}`,
|
||
'</details>',
|
||
''
|
||
);
|
||
}
|
||
bodyLines.push(
|
||
'_AI-assisted automated triage; PowerToys maintainers make final decisions._',
|
||
'',
|
||
'<!-- gh-aw-workflow-id: issue-triage -->'
|
||
);
|
||
const body = bodyLines.join('\n');
|
||
|
||
const comments = await github.paginate(github.rest.issues.listComments, {
|
||
...context.repo,
|
||
issue_number: issueNumber,
|
||
per_page: 100
|
||
});
|
||
const canonical = comments
|
||
.filter(comment =>
|
||
comment.user?.login === 'github-actions[bot]' &&
|
||
typeof comment.body === 'string' &&
|
||
comment.body.includes(marker)
|
||
)
|
||
.sort((left, right) => left.id - right.id)[0];
|
||
|
||
let comment;
|
||
if (canonical) {
|
||
comment = await github.rest.issues.updateComment({
|
||
...context.repo,
|
||
comment_id: canonical.id,
|
||
body
|
||
});
|
||
} else {
|
||
comment = await github.rest.issues.createComment({
|
||
...context.repo,
|
||
issue_number: issueNumber,
|
||
body
|
||
});
|
||
}
|
||
|
||
if (comment.data.pin != null) {
|
||
await github.request(
|
||
'DELETE /repos/{owner}/{repo}/issues/comments/{comment_id}/pin',
|
||
{ ...context.repo, comment_id: comment.data.id }
|
||
);
|
||
}
|
||
|
||
const needsAuthorFeedback =
|
||
needsEnglishTranslation || hasMissingInformation;
|
||
const currentLabels = new Set(
|
||
verified.current_labels
|
||
);
|
||
if (needsAuthorFeedback && !currentLabels.has('Needs-Author-Feedback')) {
|
||
await github.rest.issues.addLabels({
|
||
...context.repo,
|
||
issue_number: issueNumber,
|
||
labels: ['Needs-Author-Feedback']
|
||
});
|
||
} else if (!needsAuthorFeedback && currentLabels.has('Needs-Author-Feedback')) {
|
||
try {
|
||
await github.rest.issues.removeLabel({
|
||
...context.repo,
|
||
issue_number: issueNumber,
|
||
name: 'Needs-Author-Feedback'
|
||
});
|
||
} catch (error) {
|
||
if (error.status !== 404) throw error;
|
||
}
|
||
}
|
||
|
||
if (desiredProductLabel && !currentLabels.has(desiredProductLabel)) {
|
||
await github.rest.issues.addLabels({
|
||
...context.repo,
|
||
issue_number: issueNumber,
|
||
labels: [desiredProductLabel]
|
||
});
|
||
}
|
||
for (const currentLabel of currentLabels) {
|
||
if (
|
||
versionLabels.includes(currentLabel) &&
|
||
currentLabel !== desiredVersionLabel
|
||
) {
|
||
try {
|
||
await github.rest.issues.removeLabel({
|
||
...context.repo,
|
||
issue_number: issueNumber,
|
||
name: currentLabel
|
||
});
|
||
} catch (error) {
|
||
if (error.status !== 404) throw error;
|
||
}
|
||
}
|
||
}
|
||
if (desiredVersionLabel && !currentLabels.has(desiredVersionLabel)) {
|
||
await github.rest.issues.addLabels({
|
||
...context.repo,
|
||
issue_number: issueNumber,
|
||
labels: [desiredVersionLabel]
|
||
});
|
||
}
|
||
if (verifiedDuplicates.length) {
|
||
const strongest = verifiedDuplicates[0];
|
||
const response = await github.request(
|
||
'PATCH /repos/{owner}/{repo}/issues/{issue_number}',
|
||
{
|
||
...context.repo,
|
||
issue_number: issueNumber,
|
||
state: {
|
||
value: 'closed',
|
||
rationale:
|
||
`${strongest.reason} Suggested canonical issue: #${strongest.number}.`,
|
||
confidence: strongest.confidence,
|
||
suggest: true
|
||
},
|
||
state_reason: 'duplicate',
|
||
duplicate_issue_id: strongest.id,
|
||
headers: {
|
||
accept: 'application/vnd.github+json',
|
||
'X-GitHub-Api-Version': '2026-03-10'
|
||
}
|
||
}
|
||
);
|
||
|
||
if (response.data?.state === 'closed') {
|
||
await github.rest.issues.update({
|
||
...context.repo,
|
||
issue_number: issueNumber,
|
||
state: 'open'
|
||
});
|
||
core.setFailed(
|
||
'GitHub applied the close instead of holding it for review; the issue was reopened'
|
||
);
|
||
}
|
||
}
|
||
|
||
safe_outputs:
|
||
needs:
|
||
- activation
|
||
- agent
|
||
- detection
|
||
if: (!cancelled()) && needs.agent.result != 'skipped' && needs.detection.result == 'success'
|
||
runs-on: ubuntu-slim
|
||
permissions:
|
||
issues: write
|
||
timeout-minutes: 45
|
||
env:
|
||
GH_AW_AGENT_AIC: ${{ needs.agent.outputs.aic }}
|
||
GH_AW_AIC: ${{ needs.agent.outputs.aic }}
|
||
GH_AW_AMBIENT_CONTEXT: ${{ needs.agent.outputs.ambient_context }}
|
||
GH_AW_CALLER_WORKFLOW_ID: "${{ github.repository }}/issue-triage"
|
||
GH_AW_DETECTION_CONCLUSION: ${{ needs.detection.outputs.detection_conclusion }}
|
||
GH_AW_DETECTION_REASON: ${{ needs.detection.outputs.detection_reason }}
|
||
GH_AW_EFFECTIVE_TOKENS: ${{ needs.agent.outputs.effective_tokens }}
|
||
GH_AW_ENGINE_ID: "copilot"
|
||
GH_AW_ENGINE_MODEL: "small"
|
||
GH_AW_RUNTIME_FEATURES: ${{ vars.GH_AW_RUNTIME_FEATURES }}
|
||
GH_AW_THREAT_DETECTION_AIC: ${{ needs.detection.outputs.aic }}
|
||
GH_AW_WORKFLOW_EMOJI: "📌"
|
||
GH_AW_WORKFLOW_ID: "issue-triage"
|
||
GH_AW_WORKFLOW_NAME: "AI Issue Triage"
|
||
GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/issue-triage.md"
|
||
outputs:
|
||
code_push_failure_count: ${{ steps.process_safe_outputs.outputs.code_push_failure_count }}
|
||
code_push_failure_errors: ${{ steps.process_safe_outputs.outputs.code_push_failure_errors }}
|
||
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_items_applied: ${{ steps.process_safe_outputs.outputs.items_applied }}
|
||
process_safe_outputs_items_cancelled: ${{ steps.process_safe_outputs.outputs.items_cancelled }}
|
||
process_safe_outputs_items_deferred: ${{ steps.process_safe_outputs.outputs.items_deferred }}
|
||
process_safe_outputs_items_failed: ${{ steps.process_safe_outputs.outputs.items_failed }}
|
||
process_safe_outputs_items_skipped: ${{ steps.process_safe_outputs.outputs.items_skipped }}
|
||
process_safe_outputs_items_succeeded: ${{ steps.process_safe_outputs.outputs.items_succeeded }}
|
||
process_safe_outputs_items_warnings: ${{ steps.process_safe_outputs.outputs.items_warnings }}
|
||
process_safe_outputs_processed_count: ${{ steps.process_safe_outputs.outputs.processed_count }}
|
||
process_safe_outputs_status: ${{ steps.process_safe_outputs.outputs.status }}
|
||
process_safe_outputs_temporary_id_map: ${{ steps.process_safe_outputs.outputs.temporary_id_map }}
|
||
steps:
|
||
- name: Setup Scripts
|
||
id: setup
|
||
uses: github/gh-aw-actions/setup@6aab9e5b5c91c615506061f09bedd81a23babe3c # v0.86.2
|
||
with:
|
||
destination: ${{ runner.temp }}/gh-aw/actions
|
||
job-name: ${{ github.job }}
|
||
trace-id: ${{ needs.activation.outputs.setup-trace-id }}
|
||
parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }}
|
||
env:
|
||
GH_AW_SETUP_WORKFLOW_NAME: "AI Issue Triage"
|
||
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-triage.lock.yml@${{ github.ref }}
|
||
GH_AW_INFO_VERSION: "1.0.79"
|
||
GH_AW_INFO_AWF_VERSION: "v0.27.44"
|
||
GH_AW_INFO_ENGINE_ID: "copilot"
|
||
- name: Download agent output artifact
|
||
id: download-agent-output
|
||
continue-on-error: true
|
||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||
with:
|
||
name: agent
|
||
path: /tmp/gh-aw/
|
||
- name: Setup agent output environment variable
|
||
id: setup-agent-output-env
|
||
if: steps.download-agent-output.outcome == 'success'
|
||
run: |
|
||
mkdir -p /tmp/gh-aw/
|
||
find "/tmp/gh-aw/" -type f -print
|
||
echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT"
|
||
- name: Configure GH_HOST for enterprise compatibility
|
||
id: ghes-host-config
|
||
shell: bash
|
||
run: | # zizmor: ignore[github-env] - GITHUB_SERVER_URL is set by GitHub Actions, not user input.
|
||
# Derive GH_HOST from GITHUB_SERVER_URL so the gh CLI targets the correct
|
||
# GitHub instance (GHES/GHEC). On github.com this is a harmless no-op.
|
||
GH_HOST="${GITHUB_SERVER_URL#https://}"
|
||
GH_HOST="${GH_HOST#http://}"
|
||
echo "GH_HOST=${GH_HOST}" >> "$GITHUB_ENV"
|
||
- name: Process Safe Outputs
|
||
id: process_safe_outputs
|
||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||
env:
|
||
GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }}
|
||
GH_AW_COMMENT_ID: ${{ needs.activation.outputs.comment_id }}
|
||
GH_AW_ALLOWED_DOMAINS: "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com"
|
||
GITHUB_SERVER_URL: ${{ github.server_url }}
|
||
GITHUB_API_URL: ${{ github.api_url }}
|
||
GH_AW_SAFE_OUTPUT_JOBS: "{\"publish_triage_summary\":\"\"}"
|
||
GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_report_incomplete_issue\":{},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"false\"},\"report_incomplete\":{}}"
|
||
with:
|
||
github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
||
script: |
|
||
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
|
||
setupGlobals(core, github, context, exec, io, getOctokit);
|
||
const { main } = require('${{ runner.temp }}/gh-aw/actions/process_safe_outputs.cjs');
|
||
await main();
|
||
- name: Upload Safe Outputs Items
|
||
if: always()
|
||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||
with:
|
||
name: safe-outputs-items
|
||
path: |
|
||
/tmp/gh-aw/safe-output-items.jsonl
|
||
/tmp/gh-aw/temporary-id-map.json
|
||
if-no-files-found: ignore
|