microsoft/typespec

Public

mirrored from https://github.com/microsoft/typespecAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
cd27a87d48102f7ee25218755038ddf207a13ff5

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

.github/workflows/issue-triage.lock.yml

1216lines · modecode

1#
2# ___ _ _
3# / _ \ | | (_)
4# | |_| | __ _ ___ _ __ | |_ _ ___
5# | _ |/ _` |/ _ \ '_ \| __| |/ __|
6# | | | | (_| | __/ | | | |_| | (__
7# \_| |_/\__, |\___|_| |_|\__|_|\___|
8# __/ |
9# _ _ |___/
10# | | | | / _| |
11# | | | | ___ _ __ _ __| |_| | _____ ____
12# | |/\| |/ _ \ '__| |/ /| _| |/ _ \ \ /\ / / ___|
13# \ /\ / (_) | | | | ( | | | | (_) \ V V /\__ \
14# \/ \/ \___/|_| |_|\_\|_| |_|\___/ \_/\_/ |___/
15#
16# This file was automatically generated by gh-aw (v0.57.2). DO NOT EDIT.
17#
18# To update this file, edit githubnext/agentics/workflows/issue-triage.md@346204513ecfa08b81566450d7d599556807389f and run:
19# gh aw compile
20# Not all edits will cause changes to this file.
21#
22# For more information: https://github.github.com/gh-aw/introduction/overview/
23#
24# Intelligent issue triage assistant that processes new and reopened issues.
25# Analyzes issue content, selects appropriate labels, detects spam, gathers context
26# from similar issues, and provides analysis notes including debugging strategies,
27# reproduction steps, and resource links. Helps maintainers quickly understand and
28# prioritize incoming issues.
29#
30# Source: githubnext/agentics/workflows/issue-triage.md@346204513ecfa08b81566450d7d599556807389f
31#
32# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"f3414646cbbee1ca051a87fb8e9788cbac6662cdf37b204a2b76bbb06d263aed","compiler_version":"v0.57.2","strict":true}
33
34name: "Agentic Triage"
35"on":
36 issues:
37 types:
38 - opened
39 - reopened
40 workflow_dispatch:
41 inputs:
42 issue-number:
43 description: Issue number to triage
44 required: true
45
46permissions: {}
47
48concurrency:
49 group: "gh-aw-${{ github.workflow }}-${{ github.event.issue.number || github.run_id }}"
50
51run-name: "Agentic Triage"
52
53jobs:
54 activation:
55 needs: pre_activation
56 if: needs.pre_activation.outputs.activated == 'true'
57 runs-on: ubuntu-slim
58 permissions:
59 contents: read
60 discussions: write
61 issues: write
62 pull-requests: write
63 outputs:
64 body: ${{ steps.sanitized.outputs.body }}
65 comment_id: ""
66 comment_repo: ""
67 model: ${{ steps.generate_aw_info.outputs.model }}
68 secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }}
69 text: ${{ steps.sanitized.outputs.text }}
70 title: ${{ steps.sanitized.outputs.title }}
71 steps:
72 - name: Setup Scripts
73 uses: github/gh-aw/actions/setup@32b3a711a9ee97d38e3989c90af0385aff0066a7 # v0.57.2
74 with:
75 destination: /opt/gh-aw/actions
76 - name: Generate agentic run info
77 id: generate_aw_info
78 env:
79 GH_AW_INFO_ENGINE_ID: "copilot"
80 GH_AW_INFO_ENGINE_NAME: "GitHub Copilot CLI"
81 GH_AW_INFO_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || '' }}
82 GH_AW_INFO_VERSION: ""
83 GH_AW_INFO_AGENT_VERSION: "latest"
84 GH_AW_INFO_CLI_VERSION: "v0.57.2"
85 GH_AW_INFO_WORKFLOW_NAME: "Agentic Triage"
86 GH_AW_INFO_EXPERIMENTAL: "false"
87 GH_AW_INFO_SUPPORTS_TOOLS_ALLOWLIST: "true"
88 GH_AW_INFO_STAGED: "false"
89 GH_AW_INFO_ALLOWED_DOMAINS: '["defaults"]'
90 GH_AW_INFO_FIREWALL_ENABLED: "true"
91 GH_AW_INFO_AWF_VERSION: "v0.23.0"
92 GH_AW_INFO_AWMG_VERSION: ""
93 GH_AW_INFO_FIREWALL_TYPE: "squid"
94 GH_AW_COMPILED_STRICT: "true"
95 uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
96 with:
97 script: |
98 const { main } = require('/opt/gh-aw/actions/generate_aw_info.cjs');
99 await main(core, context);
100 - name: Validate COPILOT_GITHUB_TOKEN secret
101 id: validate-secret
102 run: /opt/gh-aw/actions/validate_multi_secret.sh COPILOT_GITHUB_TOKEN 'GitHub Copilot CLI' https://github.github.com/gh-aw/reference/engines/#github-copilot-default
103 env:
104 COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
105 - name: Checkout .github and .agents folders
106 uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
107 with:
108 persist-credentials: false
109 sparse-checkout: |
110 .github
111 .agents
112 sparse-checkout-cone-mode: true
113 fetch-depth: 1
114 - name: Add eyes reaction for immediate feedback
115 id: react
116 if: github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment' || (github.event_name == 'pull_request') && (github.event.pull_request.head.repo.id == github.repository_id)
117 uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
118 env:
119 GH_AW_REACTION: "eyes"
120 with:
121 github-token: ${{ secrets.GITHUB_TOKEN }}
122 script: |
123 const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs');
124 setupGlobals(core, github, context, exec, io);
125 const { main } = require('/opt/gh-aw/actions/add_reaction.cjs');
126 await main();
127 - name: Check workflow file timestamps
128 uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
129 env:
130 GH_AW_WORKFLOW_FILE: "issue-triage.lock.yml"
131 with:
132 script: |
133 const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs');
134 setupGlobals(core, github, context, exec, io);
135 const { main } = require('/opt/gh-aw/actions/check_workflow_timestamp_api.cjs');
136 await main();
137 - name: Compute current body text
138 id: sanitized
139 uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
140 with:
141 script: |
142 const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs');
143 setupGlobals(core, github, context, exec, io);
144 const { main } = require('/opt/gh-aw/actions/compute_text.cjs');
145 await main();
146 - name: Create prompt with built-in context
147 env:
148 GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
149 GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }}
150 GH_AW_EXPR_A77E2879: ${{ github.event.issue.number || inputs.issue-number }}
151 GH_AW_GITHUB_ACTOR: ${{ github.actor }}
152 GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }}
153 GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }}
154 GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }}
155 GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }}
156 GH_AW_GITHUB_REPOSITORY: ${{ github.repository }}
157 GH_AW_GITHUB_RUN_ID: ${{ github.run_id }}
158 GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }}
159 run: |
160 bash /opt/gh-aw/actions/create_prompt_first.sh
161 {
162 cat << 'GH_AW_PROMPT_EOF'
163 <system>
164 GH_AW_PROMPT_EOF
165 cat "/opt/gh-aw/prompts/xpia.md"
166 cat "/opt/gh-aw/prompts/temp_folder_prompt.md"
167 cat "/opt/gh-aw/prompts/markdown.md"
168 cat "/opt/gh-aw/prompts/safe_outputs_prompt.md"
169 cat << 'GH_AW_PROMPT_EOF'
170 <safe-output-tools>
171 Tools: add_comment, add_labels, missing_tool, missing_data, noop
172 </safe-output-tools>
173 <github-context>
174 The following GitHub context information is available for this workflow:
175 {{#if __GH_AW_GITHUB_ACTOR__ }}
176 - **actor**: __GH_AW_GITHUB_ACTOR__
177 {{/if}}
178 {{#if __GH_AW_GITHUB_REPOSITORY__ }}
179 - **repository**: __GH_AW_GITHUB_REPOSITORY__
180 {{/if}}
181 {{#if __GH_AW_GITHUB_WORKSPACE__ }}
182 - **workspace**: __GH_AW_GITHUB_WORKSPACE__
183 {{/if}}
184 {{#if __GH_AW_GITHUB_EVENT_ISSUE_NUMBER__ }}
185 - **issue-number**: #__GH_AW_GITHUB_EVENT_ISSUE_NUMBER__
186 {{/if}}
187 {{#if __GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__ }}
188 - **discussion-number**: #__GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__
189 {{/if}}
190 {{#if __GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__ }}
191 - **pull-request-number**: #__GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__
192 {{/if}}
193 {{#if __GH_AW_GITHUB_EVENT_COMMENT_ID__ }}
194 - **comment-id**: __GH_AW_GITHUB_EVENT_COMMENT_ID__
195 {{/if}}
196 {{#if __GH_AW_GITHUB_RUN_ID__ }}
197 - **workflow-run-id**: __GH_AW_GITHUB_RUN_ID__
198 {{/if}}
199 </github-context>
200
201 GH_AW_PROMPT_EOF
202 cat << 'GH_AW_PROMPT_EOF'
203 </system>
204 GH_AW_PROMPT_EOF
205 cat << 'GH_AW_PROMPT_EOF'
206 {{#runtime-import .github/workflows/issue-triage.md}}
207 GH_AW_PROMPT_EOF
208 } > "$GH_AW_PROMPT"
209 - name: Interpolate variables and render templates
210 uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
211 env:
212 GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
213 GH_AW_EXPR_A77E2879: ${{ github.event.issue.number || inputs.issue-number }}
214 with:
215 script: |
216 const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs');
217 setupGlobals(core, github, context, exec, io);
218 const { main } = require('/opt/gh-aw/actions/interpolate_prompt.cjs');
219 await main();
220 - name: Substitute placeholders
221 uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
222 env:
223 GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
224 GH_AW_EXPR_A77E2879: ${{ github.event.issue.number || inputs.issue-number }}
225 GH_AW_GITHUB_ACTOR: ${{ github.actor }}
226 GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }}
227 GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }}
228 GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }}
229 GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }}
230 GH_AW_GITHUB_REPOSITORY: ${{ github.repository }}
231 GH_AW_GITHUB_RUN_ID: ${{ github.run_id }}
232 GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }}
233 GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED: ${{ needs.pre_activation.outputs.activated }}
234 with:
235 script: |
236 const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs');
237 setupGlobals(core, github, context, exec, io);
238
239 const substitutePlaceholders = require('/opt/gh-aw/actions/substitute_placeholders.cjs');
240
241 // Call the substitution function
242 return await substitutePlaceholders({
243 file: process.env.GH_AW_PROMPT,
244 substitutions: {
245 GH_AW_EXPR_A77E2879: process.env.GH_AW_EXPR_A77E2879,
246 GH_AW_GITHUB_ACTOR: process.env.GH_AW_GITHUB_ACTOR,
247 GH_AW_GITHUB_EVENT_COMMENT_ID: process.env.GH_AW_GITHUB_EVENT_COMMENT_ID,
248 GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: process.env.GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER,
249 GH_AW_GITHUB_EVENT_ISSUE_NUMBER: process.env.GH_AW_GITHUB_EVENT_ISSUE_NUMBER,
250 GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: process.env.GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER,
251 GH_AW_GITHUB_REPOSITORY: process.env.GH_AW_GITHUB_REPOSITORY,
252 GH_AW_GITHUB_RUN_ID: process.env.GH_AW_GITHUB_RUN_ID,
253 GH_AW_GITHUB_WORKSPACE: process.env.GH_AW_GITHUB_WORKSPACE,
254 GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED: process.env.GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED
255 }
256 });
257 - name: Validate prompt placeholders
258 env:
259 GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
260 run: bash /opt/gh-aw/actions/validate_prompt_placeholders.sh
261 - name: Print prompt
262 env:
263 GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
264 run: bash /opt/gh-aw/actions/print_prompt_summary.sh
265 - name: Upload activation artifact
266 if: success()
267 uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
268 with:
269 name: activation
270 path: |
271 /tmp/gh-aw/aw_info.json
272 /tmp/gh-aw/aw-prompts/prompt.txt
273 retention-days: 1
274
275 agent:
276 needs: activation
277 runs-on: ubuntu-latest
278 permissions: read-all
279 env:
280 DEFAULT_BRANCH: ${{ github.event.repository.default_branch }}
281 GH_AW_ASSETS_ALLOWED_EXTS: ""
282 GH_AW_ASSETS_BRANCH: ""
283 GH_AW_ASSETS_MAX_SIZE_KB: 0
284 GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs
285 GH_AW_SAFE_OUTPUTS: /opt/gh-aw/safeoutputs/outputs.jsonl
286 GH_AW_SAFE_OUTPUTS_CONFIG_PATH: /opt/gh-aw/safeoutputs/config.json
287 GH_AW_SAFE_OUTPUTS_TOOLS_PATH: /opt/gh-aw/safeoutputs/tools.json
288 GH_AW_WORKFLOW_ID_SANITIZED: issuetriage
289 outputs:
290 checkout_pr_success: ${{ steps.checkout-pr.outputs.checkout_pr_success || 'true' }}
291 detection_conclusion: ${{ steps.detection_conclusion.outputs.conclusion }}
292 detection_success: ${{ steps.detection_conclusion.outputs.success }}
293 has_patch: ${{ steps.collect_output.outputs.has_patch }}
294 inference_access_error: ${{ steps.detect-inference-error.outputs.inference_access_error || 'false' }}
295 model: ${{ needs.activation.outputs.model }}
296 output: ${{ steps.collect_output.outputs.output }}
297 output_types: ${{ steps.collect_output.outputs.output_types }}
298 steps:
299 - name: Setup Scripts
300 uses: github/gh-aw/actions/setup@32b3a711a9ee97d38e3989c90af0385aff0066a7 # v0.57.2
301 with:
302 destination: /opt/gh-aw/actions
303 - name: Checkout repository
304 uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
305 with:
306 persist-credentials: false
307 - name: Create gh-aw temp directory
308 run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh
309 - name: Configure Git credentials
310 env:
311 REPO_NAME: ${{ github.repository }}
312 SERVER_URL: ${{ github.server_url }}
313 run: |
314 git config --global user.email "github-actions[bot]@users.noreply.github.com"
315 git config --global user.name "github-actions[bot]"
316 git config --global am.keepcr true
317 # Re-authenticate git with GitHub token
318 SERVER_URL_STRIPPED="${SERVER_URL#https://}"
319 git remote set-url origin "https://x-access-token:${{ github.token }}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git"
320 echo "Git configured with standard GitHub Actions identity"
321 - name: Checkout PR branch
322 id: checkout-pr
323 if: |
324 (github.event.pull_request) || (github.event.issue.pull_request)
325 uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
326 env:
327 GH_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
328 with:
329 github-token: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
330 script: |
331 const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs');
332 setupGlobals(core, github, context, exec, io);
333 const { main } = require('/opt/gh-aw/actions/checkout_pr_branch.cjs');
334 await main();
335 - name: Install GitHub Copilot CLI
336 run: /opt/gh-aw/actions/install_copilot_cli.sh latest
337 - name: Install awf binary
338 run: bash /opt/gh-aw/actions/install_awf_binary.sh v0.23.0
339 - name: Download container images
340 run: bash /opt/gh-aw/actions/download_docker_images.sh ghcr.io/github/gh-aw-firewall/agent:0.23.0 ghcr.io/github/gh-aw-firewall/api-proxy:0.23.0 ghcr.io/github/gh-aw-firewall/squid:0.23.0 ghcr.io/github/gh-aw-mcpg:v0.1.8 ghcr.io/github/github-mcp-server:v0.32.0 node:lts-alpine
341 - name: Write Safe Outputs Config
342 run: |
343 mkdir -p /opt/gh-aw/safeoutputs
344 mkdir -p /tmp/gh-aw/safeoutputs
345 mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs
346 cat > /opt/gh-aw/safeoutputs/config.json << 'GH_AW_SAFE_OUTPUTS_CONFIG_EOF'
347 {"add_comment":{"max":1},"add_labels":{"max":5},"missing_data":{},"missing_tool":{},"noop":{"max":1}}
348 GH_AW_SAFE_OUTPUTS_CONFIG_EOF
349 cat > /opt/gh-aw/safeoutputs/tools.json << 'GH_AW_SAFE_OUTPUTS_TOOLS_EOF'
350 [
351 {
352 "description": "Add a comment to an existing GitHub issue, pull request, or discussion. Use this to provide feedback, answer questions, or add information to an existing conversation. For creating new items, use create_issue, create_discussion, or create_pull_request instead. IMPORTANT: Comments are subject to validation constraints enforced by the MCP server - maximum 65536 characters for the complete comment (including footer which is added automatically), 10 mentions (@username), and 50 links. Exceeding these limits will result in an immediate error with specific guidance. NOTE: By default, this tool requires discussions:write permission. If your GitHub App lacks Discussions permission, set 'discussions: false' in the workflow's safe-outputs.add-comment configuration to exclude this permission. CONSTRAINTS: Maximum 1 comment(s) can be added.",
353 "inputSchema": {
354 "additionalProperties": false,
355 "properties": {
356 "body": {
357 "description": "The comment text in Markdown format. This is the 'body' field - do not use 'comment_body' or other variations. Provide helpful, relevant information that adds value to the conversation. CONSTRAINTS: The complete comment (your body text + automatically added footer) must not exceed 65536 characters total. Maximum 10 mentions (@username), maximum 50 links (http/https URLs). A footer (~200-500 characters) is automatically appended with workflow attribution, so leave adequate space. If these limits are exceeded, the tool call will fail with a detailed error message indicating which constraint was violated.",
358 "type": "string"
359 },
360 "integrity": {
361 "description": "Trustworthiness level of the message source (e.g., \"low\", \"medium\", \"high\").",
362 "type": "string"
363 },
364 "item_number": {
365 "description": "The issue, pull request, or discussion number to comment on. This is the numeric ID from the GitHub URL (e.g., 123 in github.com/owner/repo/issues/123). Can also be a temporary_id (e.g., 'aw_abc123') from a previously created issue in the same workflow run. If omitted, the tool auto-targets the issue, PR, or discussion that triggered this workflow. Auto-targeting only works for issue, pull_request, discussion, and comment event triggers — it does NOT work for schedule, workflow_dispatch, push, or workflow_run triggers. For those trigger types, always provide item_number explicitly, or the tool call will fail with an error.",
366 "type": [
367 "number",
368 "string"
369 ]
370 },
371 "secrecy": {
372 "description": "Confidentiality level of the message content (e.g., \"public\", \"internal\", \"private\").",
373 "type": "string"
374 },
375 "temporary_id": {
376 "description": "Unique temporary identifier for this comment. Format: 'aw_' followed by 3 to 12 alphanumeric characters (e.g., 'aw_abc1', 'aw_Test123'). Auto-generated if not provided. The temporary ID is returned in the tool response so you can reference this comment later.",
377 "pattern": "^aw_[A-Za-z0-9]{3,12}$",
378 "type": "string"
379 }
380 },
381 "required": [
382 "body"
383 ],
384 "type": "object"
385 },
386 "name": "add_comment"
387 },
388 {
389 "description": "Add labels to an existing GitHub issue or pull request for categorization and filtering. Labels must already exist in the repository. For creating new issues with labels, use create_issue with the labels property instead. CONSTRAINTS: Maximum 5 label(s) can be added.",
390 "inputSchema": {
391 "additionalProperties": false,
392 "properties": {
393 "integrity": {
394 "description": "Trustworthiness level of the message source (e.g., \"low\", \"medium\", \"high\").",
395 "type": "string"
396 },
397 "item_number": {
398 "description": "Issue or PR number to add labels to. This is the numeric ID from the GitHub URL (e.g., 456 in github.com/owner/repo/issues/456). If omitted, adds labels to the issue or PR that triggered this workflow. Only works for issue or pull_request event triggers. For schedule, workflow_dispatch, or other triggers, item_number is required — omitting it will silently skip the label operation.",
399 "type": "number"
400 },
401 "labels": {
402 "description": "Label names to add (e.g., ['bug', 'priority-high']). Labels must exist in the repository.",
403 "items": {
404 "type": "string"
405 },
406 "type": "array"
407 },
408 "secrecy": {
409 "description": "Confidentiality level of the message content (e.g., \"public\", \"internal\", \"private\").",
410 "type": "string"
411 }
412 },
413 "type": "object"
414 },
415 "name": "add_labels"
416 },
417 {
418 "description": "Report that a tool or capability needed to complete the task is not available, or share any information you deem important about missing functionality or limitations. Use this when you cannot accomplish what was requested because the required functionality is missing or access is restricted.",
419 "inputSchema": {
420 "additionalProperties": false,
421 "properties": {
422 "alternatives": {
423 "description": "Any workarounds, manual steps, or alternative approaches the user could take (max 256 characters).",
424 "type": "string"
425 },
426 "integrity": {
427 "description": "Trustworthiness level of the message source (e.g., \"low\", \"medium\", \"high\").",
428 "type": "string"
429 },
430 "reason": {
431 "description": "Explanation of why this tool is needed or what information you want to share about the limitation (max 256 characters).",
432 "type": "string"
433 },
434 "secrecy": {
435 "description": "Confidentiality level of the message content (e.g., \"public\", \"internal\", \"private\").",
436 "type": "string"
437 },
438 "tool": {
439 "description": "Optional: Name or description of the missing tool or capability (max 128 characters). Be specific about what functionality is needed.",
440 "type": "string"
441 }
442 },
443 "required": [
444 "reason"
445 ],
446 "type": "object"
447 },
448 "name": "missing_tool"
449 },
450 {
451 "description": "Log a transparency message when no significant actions are needed. Use this to confirm workflow completion and provide visibility when analysis is complete but no changes or outputs are required (e.g., 'No issues found', 'All checks passed'). This ensures the workflow produces human-visible output even when no other actions are taken.",
452 "inputSchema": {
453 "additionalProperties": false,
454 "properties": {
455 "integrity": {
456 "description": "Trustworthiness level of the message source (e.g., \"low\", \"medium\", \"high\").",
457 "type": "string"
458 },
459 "message": {
460 "description": "Status or completion message to log. Should explain what was analyzed and the outcome (e.g., 'Code review complete - no issues found', 'Analysis complete - all tests passing').",
461 "type": "string"
462 },
463 "secrecy": {
464 "description": "Confidentiality level of the message content (e.g., \"public\", \"internal\", \"private\").",
465 "type": "string"
466 }
467 },
468 "required": [
469 "message"
470 ],
471 "type": "object"
472 },
473 "name": "noop"
474 },
475 {
476 "description": "Report that data or information needed to complete the task is not available. Use this when you cannot accomplish what was requested because required data, context, or information is missing.",
477 "inputSchema": {
478 "additionalProperties": false,
479 "properties": {
480 "alternatives": {
481 "description": "Any workarounds, manual steps, or alternative approaches the user could take (max 256 characters).",
482 "type": "string"
483 },
484 "context": {
485 "description": "Additional context about the missing data or where it should come from (max 256 characters).",
486 "type": "string"
487 },
488 "data_type": {
489 "description": "Type or description of the missing data or information (max 128 characters). Be specific about what data is needed.",
490 "type": "string"
491 },
492 "integrity": {
493 "description": "Trustworthiness level of the message source (e.g., \"low\", \"medium\", \"high\").",
494 "type": "string"
495 },
496 "reason": {
497 "description": "Explanation of why this data is needed to complete the task (max 256 characters).",
498 "type": "string"
499 },
500 "secrecy": {
501 "description": "Confidentiality level of the message content (e.g., \"public\", \"internal\", \"private\").",
502 "type": "string"
503 }
504 },
505 "required": [],
506 "type": "object"
507 },
508 "name": "missing_data"
509 }
510 ]
511 GH_AW_SAFE_OUTPUTS_TOOLS_EOF
512 cat > /opt/gh-aw/safeoutputs/validation.json << 'GH_AW_SAFE_OUTPUTS_VALIDATION_EOF'
513 {
514 "add_comment": {
515 "defaultMax": 1,
516 "fields": {
517 "body": {
518 "required": true,
519 "type": "string",
520 "sanitize": true,
521 "maxLength": 65000
522 },
523 "item_number": {
524 "issueOrPRNumber": true
525 },
526 "repo": {
527 "type": "string",
528 "maxLength": 256
529 }
530 }
531 },
532 "add_labels": {
533 "defaultMax": 5,
534 "fields": {
535 "item_number": {
536 "issueOrPRNumber": true
537 },
538 "labels": {
539 "required": true,
540 "type": "array",
541 "itemType": "string",
542 "itemSanitize": true,
543 "itemMaxLength": 128
544 },
545 "repo": {
546 "type": "string",
547 "maxLength": 256
548 }
549 }
550 },
551 "missing_data": {
552 "defaultMax": 20,
553 "fields": {
554 "alternatives": {
555 "type": "string",
556 "sanitize": true,
557 "maxLength": 256
558 },
559 "context": {
560 "type": "string",
561 "sanitize": true,
562 "maxLength": 256
563 },
564 "data_type": {
565 "type": "string",
566 "sanitize": true,
567 "maxLength": 128
568 },
569 "reason": {
570 "type": "string",
571 "sanitize": true,
572 "maxLength": 256
573 }
574 }
575 },
576 "missing_tool": {
577 "defaultMax": 20,
578 "fields": {
579 "alternatives": {
580 "type": "string",
581 "sanitize": true,
582 "maxLength": 512
583 },
584 "reason": {
585 "required": true,
586 "type": "string",
587 "sanitize": true,
588 "maxLength": 256
589 },
590 "tool": {
591 "type": "string",
592 "sanitize": true,
593 "maxLength": 128
594 }
595 }
596 },
597 "noop": {
598 "defaultMax": 1,
599 "fields": {
600 "message": {
601 "required": true,
602 "type": "string",
603 "sanitize": true,
604 "maxLength": 65000
605 }
606 }
607 }
608 }
609 GH_AW_SAFE_OUTPUTS_VALIDATION_EOF
610 - name: Generate Safe Outputs MCP Server Config
611 id: safe-outputs-config
612 run: |
613 # Generate a secure random API key (360 bits of entropy, 40+ chars)
614 # Mask immediately to prevent timing vulnerabilities
615 API_KEY=$(openssl rand -base64 45 | tr -d '/+=')
616 echo "::add-mask::${API_KEY}"
617
618 PORT=3001
619
620 # Set outputs for next steps
621 {
622 echo "safe_outputs_api_key=${API_KEY}"
623 echo "safe_outputs_port=${PORT}"
624 } >> "$GITHUB_OUTPUT"
625
626 echo "Safe Outputs MCP server will run on port ${PORT}"
627
628 - name: Start Safe Outputs MCP HTTP Server
629 id: safe-outputs-start
630 env:
631 DEBUG: '*'
632 GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-config.outputs.safe_outputs_port }}
633 GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-config.outputs.safe_outputs_api_key }}
634 GH_AW_SAFE_OUTPUTS_TOOLS_PATH: /opt/gh-aw/safeoutputs/tools.json
635 GH_AW_SAFE_OUTPUTS_CONFIG_PATH: /opt/gh-aw/safeoutputs/config.json
636 GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs
637 run: |
638 # Environment variables are set above to prevent template injection
639 export DEBUG
640 export GH_AW_SAFE_OUTPUTS_PORT
641 export GH_AW_SAFE_OUTPUTS_API_KEY
642 export GH_AW_SAFE_OUTPUTS_TOOLS_PATH
643 export GH_AW_SAFE_OUTPUTS_CONFIG_PATH
644 export GH_AW_MCP_LOG_DIR
645
646 bash /opt/gh-aw/actions/start_safe_outputs_server.sh
647
648 - name: Start MCP Gateway
649 id: start-mcp-gateway
650 env:
651 GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }}
652 GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-start.outputs.api_key }}
653 GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-start.outputs.port }}
654 GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
655 run: |
656 set -eo pipefail
657 mkdir -p /tmp/gh-aw/mcp-config
658
659 # Export gateway environment variables for MCP config and gateway script
660 export MCP_GATEWAY_PORT="80"
661 export MCP_GATEWAY_DOMAIN="host.docker.internal"
662 MCP_GATEWAY_API_KEY=$(openssl rand -base64 45 | tr -d '/+=')
663 echo "::add-mask::${MCP_GATEWAY_API_KEY}"
664 export MCP_GATEWAY_API_KEY
665 export MCP_GATEWAY_PAYLOAD_DIR="/tmp/gh-aw/mcp-payloads"
666 mkdir -p "${MCP_GATEWAY_PAYLOAD_DIR}"
667 export MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD="524288"
668 export DEBUG="*"
669
670 export GH_AW_ENGINE="copilot"
671 export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host -v /var/run/docker.sock:/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_API_KEY -e MCP_GATEWAY_PAYLOAD_DIR -e MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -e DEBUG -e MCP_GATEWAY_LOG_DIR -e GH_AW_MCP_LOG_DIR -e GH_AW_SAFE_OUTPUTS -e GH_AW_SAFE_OUTPUTS_CONFIG_PATH -e GH_AW_SAFE_OUTPUTS_TOOLS_PATH -e GH_AW_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_LOCKDOWN -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.1.8'
672
673 mkdir -p /home/runner/.copilot
674 cat << GH_AW_MCP_CONFIG_EOF | bash /opt/gh-aw/actions/start_mcp_gateway.sh
675 {
676 "mcpServers": {
677 "github": {
678 "type": "stdio",
679 "container": "ghcr.io/github/github-mcp-server:v0.32.0",
680 "env": {
681 "GITHUB_PERSONAL_ACCESS_TOKEN": "\${GITHUB_MCP_SERVER_TOKEN}",
682 "GITHUB_READ_ONLY": "1",
683 "GITHUB_TOOLSETS": "issues,repos"
684 }
685 },
686 "safeoutputs": {
687 "type": "http",
688 "url": "http://host.docker.internal:$GH_AW_SAFE_OUTPUTS_PORT",
689 "headers": {
690 "Authorization": "\${GH_AW_SAFE_OUTPUTS_API_KEY}"
691 }
692 }
693 },
694 "gateway": {
695 "port": $MCP_GATEWAY_PORT,
696 "domain": "${MCP_GATEWAY_DOMAIN}",
697 "apiKey": "${MCP_GATEWAY_API_KEY}",
698 "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}"
699 }
700 }
701 GH_AW_MCP_CONFIG_EOF
702 - name: Download activation artifact
703 uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8
704 with:
705 name: activation
706 path: /tmp/gh-aw
707 - name: Clean git credentials
708 run: bash /opt/gh-aw/actions/clean_git_credentials.sh
709 - name: Execute GitHub Copilot CLI
710 id: agentic_execution
711 # Copilot CLI tool arguments (sorted):
712 timeout-minutes: 10
713 run: |
714 set -o pipefail
715 touch /tmp/gh-aw/agent-step-summary.md
716 # shellcheck disable=SC1003
717 sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --allow-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" --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.23.0 --skip-pull --enable-api-proxy \
718 -- /bin/bash -c '/usr/local/bin/copilot --add-dir /tmp/gh-aw/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --add-dir "${GITHUB_WORKSPACE}" --disable-builtin-mcps --allow-all-tools --allow-all-paths --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log
719 env:
720 COPILOT_AGENT_RUNNER_TYPE: STANDALONE
721 COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
722 COPILOT_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || '' }}
723 GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json
724 GH_AW_PHASE: agent
725 GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
726 GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }}
727 GH_AW_VERSION: v0.57.2
728 GITHUB_API_URL: ${{ github.api_url }}
729 GITHUB_AW: true
730 GITHUB_HEAD_REF: ${{ github.head_ref }}
731 GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
732 GITHUB_REF_NAME: ${{ github.ref_name }}
733 GITHUB_SERVER_URL: ${{ github.server_url }}
734 GITHUB_STEP_SUMMARY: /tmp/gh-aw/agent-step-summary.md
735 GITHUB_WORKSPACE: ${{ github.workspace }}
736 GIT_AUTHOR_EMAIL: github-actions[bot]@users.noreply.github.com
737 GIT_AUTHOR_NAME: github-actions[bot]
738 GIT_COMMITTER_EMAIL: github-actions[bot]@users.noreply.github.com
739 GIT_COMMITTER_NAME: github-actions[bot]
740 XDG_CONFIG_HOME: /home/runner
741 - name: Detect inference access error
742 id: detect-inference-error
743 if: always()
744 continue-on-error: true
745 run: bash /opt/gh-aw/actions/detect_inference_access_error.sh
746 - name: Configure Git credentials
747 env:
748 REPO_NAME: ${{ github.repository }}
749 SERVER_URL: ${{ github.server_url }}
750 run: |
751 git config --global user.email "github-actions[bot]@users.noreply.github.com"
752 git config --global user.name "github-actions[bot]"
753 git config --global am.keepcr true
754 # Re-authenticate git with GitHub token
755 SERVER_URL_STRIPPED="${SERVER_URL#https://}"
756 git remote set-url origin "https://x-access-token:${{ github.token }}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git"
757 echo "Git configured with standard GitHub Actions identity"
758 - name: Copy Copilot session state files to logs
759 if: always()
760 continue-on-error: true
761 run: |
762 # Copy Copilot session state files to logs folder for artifact collection
763 # This ensures they are in /tmp/gh-aw/ where secret redaction can scan them
764 SESSION_STATE_DIR="$HOME/.copilot/session-state"
765 LOGS_DIR="/tmp/gh-aw/sandbox/agent/logs"
766
767 if [ -d "$SESSION_STATE_DIR" ]; then
768 echo "Copying Copilot session state files from $SESSION_STATE_DIR to $LOGS_DIR"
769 mkdir -p "$LOGS_DIR"
770 cp -v "$SESSION_STATE_DIR"/*.jsonl "$LOGS_DIR/" 2>/dev/null || true
771 echo "Session state files copied successfully"
772 else
773 echo "No session-state directory found at $SESSION_STATE_DIR"
774 fi
775 - name: Stop MCP Gateway
776 if: always()
777 continue-on-error: true
778 env:
779 MCP_GATEWAY_PORT: ${{ steps.start-mcp-gateway.outputs.gateway-port }}
780 MCP_GATEWAY_API_KEY: ${{ steps.start-mcp-gateway.outputs.gateway-api-key }}
781 GATEWAY_PID: ${{ steps.start-mcp-gateway.outputs.gateway-pid }}
782 run: |
783 bash /opt/gh-aw/actions/stop_mcp_gateway.sh "$GATEWAY_PID"
784 - name: Redact secrets in logs
785 if: always()
786 uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
787 with:
788 script: |
789 const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs');
790 setupGlobals(core, github, context, exec, io);
791 const { main } = require('/opt/gh-aw/actions/redact_secrets.cjs');
792 await main();
793 env:
794 GH_AW_SECRET_NAMES: 'COPILOT_GITHUB_TOKEN,GH_AW_GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,GITHUB_TOKEN'
795 SECRET_COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
796 SECRET_GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }}
797 SECRET_GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }}
798 SECRET_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
799 - name: Append agent step summary
800 if: always()
801 run: bash /opt/gh-aw/actions/append_agent_step_summary.sh
802 - name: Upload Safe Outputs
803 if: always()
804 uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
805 with:
806 name: safe-output
807 path: ${{ env.GH_AW_SAFE_OUTPUTS }}
808 if-no-files-found: warn
809 - name: Ingest agent output
810 id: collect_output
811 if: always()
812 uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
813 env:
814 GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }}
815 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"
816 GITHUB_SERVER_URL: ${{ github.server_url }}
817 GITHUB_API_URL: ${{ github.api_url }}
818 with:
819 script: |
820 const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs');
821 setupGlobals(core, github, context, exec, io);
822 const { main } = require('/opt/gh-aw/actions/collect_ndjson_output.cjs');
823 await main();
824 - name: Upload sanitized agent output
825 if: always() && env.GH_AW_AGENT_OUTPUT
826 uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
827 with:
828 name: agent-output
829 path: ${{ env.GH_AW_AGENT_OUTPUT }}
830 if-no-files-found: warn
831 - name: Upload engine output files
832 uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
833 with:
834 name: agent_outputs
835 path: |
836 /tmp/gh-aw/sandbox/agent/logs/
837 /tmp/gh-aw/redacted-urls.log
838 if-no-files-found: ignore
839 - name: Parse agent logs for step summary
840 if: always()
841 uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
842 env:
843 GH_AW_AGENT_OUTPUT: /tmp/gh-aw/sandbox/agent/logs/
844 with:
845 script: |
846 const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs');
847 setupGlobals(core, github, context, exec, io);
848 const { main } = require('/opt/gh-aw/actions/parse_copilot_log.cjs');
849 await main();
850 - name: Parse MCP Gateway logs for step summary
851 if: always()
852 uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
853 with:
854 script: |
855 const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs');
856 setupGlobals(core, github, context, exec, io);
857 const { main } = require('/opt/gh-aw/actions/parse_mcp_gateway_log.cjs');
858 await main();
859 - name: Print firewall logs
860 if: always()
861 continue-on-error: true
862 env:
863 AWF_LOGS_DIR: /tmp/gh-aw/sandbox/firewall/logs
864 run: |
865 # Fix permissions on firewall logs so they can be uploaded as artifacts
866 # AWF runs with sudo, creating files owned by root
867 sudo chmod -R a+r /tmp/gh-aw/sandbox/firewall/logs 2>/dev/null || true
868 # Only run awf logs summary if awf command exists (it may not be installed if workflow failed before install step)
869 if command -v awf &> /dev/null; then
870 awf logs summary | tee -a "$GITHUB_STEP_SUMMARY"
871 else
872 echo 'AWF binary not installed, skipping firewall log summary'
873 fi
874 - name: Upload agent artifacts
875 if: always()
876 continue-on-error: true
877 uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
878 with:
879 name: agent-artifacts
880 path: |
881 /tmp/gh-aw/aw-prompts/prompt.txt
882 /tmp/gh-aw/mcp-logs/
883 /tmp/gh-aw/sandbox/firewall/logs/
884 /tmp/gh-aw/agent-stdio.log
885 /tmp/gh-aw/agent/
886 if-no-files-found: ignore
887 # --- Threat Detection (inline) ---
888 - name: Check if detection needed
889 id: detection_guard
890 if: always()
891 env:
892 OUTPUT_TYPES: ${{ steps.collect_output.outputs.output_types }}
893 HAS_PATCH: ${{ steps.collect_output.outputs.has_patch }}
894 run: |
895 if [[ -n "$OUTPUT_TYPES" || "$HAS_PATCH" == "true" ]]; then
896 echo "run_detection=true" >> "$GITHUB_OUTPUT"
897 echo "Detection will run: output_types=$OUTPUT_TYPES, has_patch=$HAS_PATCH"
898 else
899 echo "run_detection=false" >> "$GITHUB_OUTPUT"
900 echo "Detection skipped: no agent outputs or patches to analyze"
901 fi
902 - name: Clear MCP configuration for detection
903 if: always() && steps.detection_guard.outputs.run_detection == 'true'
904 run: |
905 rm -f /tmp/gh-aw/mcp-config/mcp-servers.json
906 rm -f /home/runner/.copilot/mcp-config.json
907 rm -f "$GITHUB_WORKSPACE/.gemini/settings.json"
908 - name: Prepare threat detection files
909 if: always() && steps.detection_guard.outputs.run_detection == 'true'
910 run: |
911 mkdir -p /tmp/gh-aw/threat-detection/aw-prompts
912 cp /tmp/gh-aw/aw-prompts/prompt.txt /tmp/gh-aw/threat-detection/aw-prompts/prompt.txt 2>/dev/null || true
913 cp /tmp/gh-aw/agent_output.json /tmp/gh-aw/threat-detection/agent_output.json 2>/dev/null || true
914 for f in /tmp/gh-aw/aw-*.patch; do
915 [ -f "$f" ] && cp "$f" /tmp/gh-aw/threat-detection/ 2>/dev/null || true
916 done
917 echo "Prepared threat detection files:"
918 ls -la /tmp/gh-aw/threat-detection/ 2>/dev/null || true
919 - name: Setup threat detection
920 if: always() && steps.detection_guard.outputs.run_detection == 'true'
921 uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
922 env:
923 WORKFLOW_NAME: "Agentic Triage"
924 WORKFLOW_DESCRIPTION: "Intelligent issue triage assistant that processes new and reopened issues.\nAnalyzes issue content, selects appropriate labels, detects spam, gathers context\nfrom similar issues, and provides analysis notes including debugging strategies,\nreproduction steps, and resource links. Helps maintainers quickly understand and\nprioritize incoming issues."
925 HAS_PATCH: ${{ steps.collect_output.outputs.has_patch }}
926 with:
927 script: |
928 const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs');
929 setupGlobals(core, github, context, exec, io);
930 const { main } = require('/opt/gh-aw/actions/setup_threat_detection.cjs');
931 await main();
932 - name: Ensure threat-detection directory and log
933 if: always() && steps.detection_guard.outputs.run_detection == 'true'
934 run: |
935 mkdir -p /tmp/gh-aw/threat-detection
936 touch /tmp/gh-aw/threat-detection/detection.log
937 - name: Execute GitHub Copilot CLI
938 if: always() && steps.detection_guard.outputs.run_detection == 'true'
939 id: detection_agentic_execution
940 # Copilot CLI tool arguments (sorted):
941 # --allow-tool shell(cat)
942 # --allow-tool shell(grep)
943 # --allow-tool shell(head)
944 # --allow-tool shell(jq)
945 # --allow-tool shell(ls)
946 # --allow-tool shell(tail)
947 # --allow-tool shell(wc)
948 timeout-minutes: 20
949 run: |
950 set -o pipefail
951 touch /tmp/gh-aw/agent-step-summary.md
952 # shellcheck disable=SC1003
953 sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --allow-domains "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,github.com,host.docker.internal,raw.githubusercontent.com,registry.npmjs.org,telemetry.enterprise.githubcopilot.com" --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.23.0 --skip-pull --enable-api-proxy \
954 -- /bin/bash -c '/usr/local/bin/copilot --add-dir /tmp/gh-aw/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --add-dir "${GITHUB_WORKSPACE}" --disable-builtin-mcps --allow-tool '\''shell(cat)'\'' --allow-tool '\''shell(grep)'\'' --allow-tool '\''shell(head)'\'' --allow-tool '\''shell(jq)'\'' --allow-tool '\''shell(ls)'\'' --allow-tool '\''shell(tail)'\'' --allow-tool '\''shell(wc)'\'' --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/threat-detection/detection.log
955 env:
956 COPILOT_AGENT_RUNNER_TYPE: STANDALONE
957 COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
958 COPILOT_MODEL: ${{ vars.GH_AW_MODEL_DETECTION_COPILOT || '' }}
959 GH_AW_PHASE: detection
960 GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
961 GH_AW_VERSION: v0.57.2
962 GITHUB_API_URL: ${{ github.api_url }}
963 GITHUB_AW: true
964 GITHUB_HEAD_REF: ${{ github.head_ref }}
965 GITHUB_REF_NAME: ${{ github.ref_name }}
966 GITHUB_SERVER_URL: ${{ github.server_url }}
967 GITHUB_STEP_SUMMARY: /tmp/gh-aw/agent-step-summary.md
968 GITHUB_WORKSPACE: ${{ github.workspace }}
969 GIT_AUTHOR_EMAIL: github-actions[bot]@users.noreply.github.com
970 GIT_AUTHOR_NAME: github-actions[bot]
971 GIT_COMMITTER_EMAIL: github-actions[bot]@users.noreply.github.com
972 GIT_COMMITTER_NAME: github-actions[bot]
973 XDG_CONFIG_HOME: /home/runner
974 - name: Parse threat detection results
975 id: parse_detection_results
976 if: always() && steps.detection_guard.outputs.run_detection == 'true'
977 uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
978 with:
979 script: |
980 const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs');
981 setupGlobals(core, github, context, exec, io);
982 const { main } = require('/opt/gh-aw/actions/parse_threat_detection_results.cjs');
983 await main();
984 - name: Upload threat detection log
985 if: always() && steps.detection_guard.outputs.run_detection == 'true'
986 uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
987 with:
988 name: threat-detection.log
989 path: /tmp/gh-aw/threat-detection/detection.log
990 if-no-files-found: ignore
991 - name: Set detection conclusion
992 id: detection_conclusion
993 if: always()
994 env:
995 RUN_DETECTION: ${{ steps.detection_guard.outputs.run_detection }}
996 DETECTION_SUCCESS: ${{ steps.parse_detection_results.outputs.success }}
997 run: |
998 if [[ "$RUN_DETECTION" != "true" ]]; then
999 echo "conclusion=skipped" >> "$GITHUB_OUTPUT"
1000 echo "success=true" >> "$GITHUB_OUTPUT"
1001 echo "Detection was not needed, marking as skipped"
1002 elif [[ "$DETECTION_SUCCESS" == "true" ]]; then
1003 echo "conclusion=success" >> "$GITHUB_OUTPUT"
1004 echo "success=true" >> "$GITHUB_OUTPUT"
1005 echo "Detection passed successfully"
1006 else
1007 echo "conclusion=failure" >> "$GITHUB_OUTPUT"
1008 echo "success=false" >> "$GITHUB_OUTPUT"
1009 echo "Detection found issues"
1010 fi
1011
1012 conclusion:
1013 needs:
1014 - activation
1015 - agent
1016 - safe_outputs
1017 if: (always()) && (needs.agent.result != 'skipped')
1018 runs-on: ubuntu-slim
1019 permissions:
1020 contents: read
1021 discussions: write
1022 issues: write
1023 pull-requests: write
1024 concurrency:
1025 group: "gh-aw-conclusion-issue-triage"
1026 cancel-in-progress: false
1027 outputs:
1028 noop_message: ${{ steps.noop.outputs.noop_message }}
1029 tools_reported: ${{ steps.missing_tool.outputs.tools_reported }}
1030 total_count: ${{ steps.missing_tool.outputs.total_count }}
1031 steps:
1032 - name: Setup Scripts
1033 uses: github/gh-aw/actions/setup@32b3a711a9ee97d38e3989c90af0385aff0066a7 # v0.57.2
1034 with:
1035 destination: /opt/gh-aw/actions
1036 - name: Download agent output artifact
1037 id: download-agent-output
1038 continue-on-error: true
1039 uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8
1040 with:
1041 name: agent-output
1042 path: /tmp/gh-aw/safeoutputs/
1043 - name: Setup agent output environment variable
1044 if: steps.download-agent-output.outcome == 'success'
1045 run: |
1046 mkdir -p /tmp/gh-aw/safeoutputs/
1047 find "/tmp/gh-aw/safeoutputs/" -type f -print
1048 echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/safeoutputs/agent_output.json" >> "$GITHUB_ENV"
1049 - name: Process No-Op Messages
1050 id: noop
1051 uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
1052 env:
1053 GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }}
1054 GH_AW_NOOP_MAX: "1"
1055 GH_AW_WORKFLOW_NAME: "Agentic Triage"
1056 GH_AW_WORKFLOW_SOURCE: "githubnext/agentics/workflows/issue-triage.md@346204513ecfa08b81566450d7d599556807389f"
1057 GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/githubnext/agentics/tree/346204513ecfa08b81566450d7d599556807389f/workflows/issue-triage.md"
1058 with:
1059 github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
1060 script: |
1061 const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs');
1062 setupGlobals(core, github, context, exec, io);
1063 const { main } = require('/opt/gh-aw/actions/noop.cjs');
1064 await main();
1065 - name: Record Missing Tool
1066 id: missing_tool
1067 uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
1068 env:
1069 GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }}
1070 GH_AW_WORKFLOW_NAME: "Agentic Triage"
1071 GH_AW_WORKFLOW_SOURCE: "githubnext/agentics/workflows/issue-triage.md@346204513ecfa08b81566450d7d599556807389f"
1072 GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/githubnext/agentics/tree/346204513ecfa08b81566450d7d599556807389f/workflows/issue-triage.md"
1073 with:
1074 github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
1075 script: |
1076 const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs');
1077 setupGlobals(core, github, context, exec, io);
1078 const { main } = require('/opt/gh-aw/actions/missing_tool.cjs');
1079 await main();
1080 - name: Handle Agent Failure
1081 id: handle_agent_failure
1082 uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
1083 env:
1084 GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }}
1085 GH_AW_WORKFLOW_NAME: "Agentic Triage"
1086 GH_AW_WORKFLOW_SOURCE: "githubnext/agentics/workflows/issue-triage.md@346204513ecfa08b81566450d7d599556807389f"
1087 GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/githubnext/agentics/tree/346204513ecfa08b81566450d7d599556807389f/workflows/issue-triage.md"
1088 GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
1089 GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }}
1090 GH_AW_WORKFLOW_ID: "issue-triage"
1091 GH_AW_SECRET_VERIFICATION_RESULT: ${{ needs.activation.outputs.secret_verification_result }}
1092 GH_AW_CHECKOUT_PR_SUCCESS: ${{ needs.agent.outputs.checkout_pr_success }}
1093 GH_AW_INFERENCE_ACCESS_ERROR: ${{ needs.agent.outputs.inference_access_error }}
1094 GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"\\u003e Generated by [{workflow_name}]({run_url})\",\"footerInstall\":\"\\u003c!-- --\\u003e\"}"
1095 GH_AW_GROUP_REPORTS: "false"
1096 GH_AW_FAILURE_REPORT_AS_ISSUE: "true"
1097 GH_AW_TIMEOUT_MINUTES: "10"
1098 with:
1099 github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
1100 script: |
1101 const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs');
1102 setupGlobals(core, github, context, exec, io);
1103 const { main } = require('/opt/gh-aw/actions/handle_agent_failure.cjs');
1104 await main();
1105 - name: Handle No-Op Message
1106 id: handle_noop_message
1107 uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
1108 env:
1109 GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }}
1110 GH_AW_WORKFLOW_NAME: "Agentic Triage"
1111 GH_AW_WORKFLOW_SOURCE: "githubnext/agentics/workflows/issue-triage.md@346204513ecfa08b81566450d7d599556807389f"
1112 GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/githubnext/agentics/tree/346204513ecfa08b81566450d7d599556807389f/workflows/issue-triage.md"
1113 GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
1114 GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }}
1115 GH_AW_NOOP_MESSAGE: ${{ steps.noop.outputs.noop_message }}
1116 GH_AW_NOOP_REPORT_AS_ISSUE: "true"
1117 with:
1118 github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
1119 script: |
1120 const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs');
1121 setupGlobals(core, github, context, exec, io);
1122 const { main } = require('/opt/gh-aw/actions/handle_noop_message.cjs');
1123 await main();
1124
1125 pre_activation:
1126 runs-on: ubuntu-slim
1127 outputs:
1128 activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }}
1129 matched_command: ''
1130 steps:
1131 - name: Setup Scripts
1132 uses: github/gh-aw/actions/setup@32b3a711a9ee97d38e3989c90af0385aff0066a7 # v0.57.2
1133 with:
1134 destination: /opt/gh-aw/actions
1135 - name: Check team membership for workflow
1136 id: check_membership
1137 uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
1138 env:
1139 GH_AW_REQUIRED_ROLES: admin,maintainer,write
1140 with:
1141 github-token: ${{ secrets.GITHUB_TOKEN }}
1142 script: |
1143 const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs');
1144 setupGlobals(core, github, context, exec, io);
1145 const { main } = require('/opt/gh-aw/actions/check_membership.cjs');
1146 await main();
1147
1148 safe_outputs:
1149 needs: agent
1150 if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (needs.agent.outputs.detection_success == 'true')
1151 runs-on: ubuntu-slim
1152 permissions:
1153 contents: read
1154 discussions: write
1155 issues: write
1156 pull-requests: write
1157 timeout-minutes: 15
1158 env:
1159 GH_AW_CALLER_WORKFLOW_ID: "${{ github.repository }}/issue-triage"
1160 GH_AW_ENGINE_ID: "copilot"
1161 GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"\\u003e Generated by [{workflow_name}]({run_url})\",\"footerInstall\":\"\\u003c!-- --\\u003e\"}"
1162 GH_AW_WORKFLOW_ID: "issue-triage"
1163 GH_AW_WORKFLOW_NAME: "Agentic Triage"
1164 GH_AW_WORKFLOW_SOURCE: "githubnext/agentics/workflows/issue-triage.md@346204513ecfa08b81566450d7d599556807389f"
1165 GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/githubnext/agentics/tree/346204513ecfa08b81566450d7d599556807389f/workflows/issue-triage.md"
1166 outputs:
1167 code_push_failure_count: ${{ steps.process_safe_outputs.outputs.code_push_failure_count }}
1168 code_push_failure_errors: ${{ steps.process_safe_outputs.outputs.code_push_failure_errors }}
1169 comment_id: ${{ steps.process_safe_outputs.outputs.comment_id }}
1170 comment_url: ${{ steps.process_safe_outputs.outputs.comment_url }}
1171 create_discussion_error_count: ${{ steps.process_safe_outputs.outputs.create_discussion_error_count }}
1172 create_discussion_errors: ${{ steps.process_safe_outputs.outputs.create_discussion_errors }}
1173 process_safe_outputs_processed_count: ${{ steps.process_safe_outputs.outputs.processed_count }}
1174 process_safe_outputs_temporary_id_map: ${{ steps.process_safe_outputs.outputs.temporary_id_map }}
1175 steps:
1176 - name: Setup Scripts
1177 uses: github/gh-aw/actions/setup@32b3a711a9ee97d38e3989c90af0385aff0066a7 # v0.57.2
1178 with:
1179 destination: /opt/gh-aw/actions
1180 - name: Download agent output artifact
1181 id: download-agent-output
1182 continue-on-error: true
1183 uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8
1184 with:
1185 name: agent-output
1186 path: /tmp/gh-aw/safeoutputs/
1187 - name: Setup agent output environment variable
1188 if: steps.download-agent-output.outcome == 'success'
1189 run: |
1190 mkdir -p /tmp/gh-aw/safeoutputs/
1191 find "/tmp/gh-aw/safeoutputs/" -type f -print
1192 echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/safeoutputs/agent_output.json" >> "$GITHUB_ENV"
1193 - name: Process Safe Outputs
1194 id: process_safe_outputs
1195 uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
1196 env:
1197 GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }}
1198 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"
1199 GITHUB_SERVER_URL: ${{ github.server_url }}
1200 GITHUB_API_URL: ${{ github.api_url }}
1201 GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_comment\":{\"max\":1},\"add_labels\":{\"max\":5},\"missing_data\":{},\"missing_tool\":{}}"
1202 with:
1203 github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
1204 script: |
1205 const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs');
1206 setupGlobals(core, github, context, exec, io);
1207 const { main } = require('/opt/gh-aw/actions/safe_output_handler_manager.cjs');
1208 await main();
1209 - name: Upload safe output items manifest
1210 if: always()
1211 uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
1212 with:
1213 name: safe-output-items
1214 path: /tmp/safe-output-items.jsonl
1215 if-no-files-found: warn
1216
1217