diff --git a/.github/actions/select-tests/action.yml b/.github/actions/select-tests/action.yml
index 2dd69bc290a..0aade3856d6 100644
--- a/.github/actions/select-tests/action.yml
+++ b/.github/actions/select-tests/action.yml
@@ -12,7 +12,7 @@ inputs:
setupDotNet:
required: false
default: 'true'
- description: 'Whether to bootstrap the .NET SDK (./dotnet.sh --version). Set false when the caller already installed the SDK in the same job. Selection only needs the SDK -- not a full repo restore -- because it builds an MSBuild ProjectGraph, which auto-resolves SDKs.'
+ description: 'Whether to bootstrap the .NET SDK and the runtime required by SelectTests. Set false when the caller already installed the toolchain in the same job. Selection does not require a full repo restore because it builds an MSBuild ProjectGraph, which auto-resolves SDKs.'
enforce:
required: false
default: 'false'
@@ -83,14 +83,23 @@ runs:
with:
persist-credentials: false
- # Minimal SDK bootstrap -- not a full ./restore.sh. dotnet.sh -> InitializeDotNetCli installs only
- # the SDK into repo-local .dotnet (no runtime toolsets, no project restore). SelectTests then builds
- # its MSBuild ProjectGraph over the solution on this SDK (MSBuild SDKs auto-resolve) -- selection
- # does not need the repo restored.
- - name: Install SDK (minimal)
+ # Minimal toolchain bootstrap -- not a full ./restore.sh. The repo SDK is .NET 11 while
+ # SelectTests intentionally targets .NET 10 for its Microsoft.Build ProjectGraph dependency,
+ # so install that one pinned runtime without restoring the rest of the repo toolsets.
+ - name: Install toolchain (minimal)
if: ${{ inputs.setupDotNet == 'true' }}
shell: bash
- run: ./dotnet.sh --version
+ run: |
+ set -euo pipefail
+ ./dotnet.sh --version
+ runtime_version="$(sed -n 's:.*\(.*\).*:\1:p' eng/Versions.props)"
+ if [ -z "$runtime_version" ]; then
+ echo "::error::Could not read DotNetRuntimeNet10VersionForTesting from eng/Versions.props." >&2
+ exit 1
+ fi
+ ./eng/common/dotnet-install.sh \
+ -runtime dotnet \
+ -version "$runtime_version"
- name: Select relevant tests
id: select
diff --git a/.github/aw/actions-lock.json b/.github/aw/actions-lock.json
index 46b087737fc..0157ba505b2 100644
--- a/.github/aw/actions-lock.json
+++ b/.github/aw/actions-lock.json
@@ -65,15 +65,10 @@
"version": "v7.0.1",
"sha": "043fb46d1a93c77aae656e7c1c64a875d1fc6a0a"
},
- "github/gh-aw-actions/setup-cli@v0.85.4": {
- "repo": "github/gh-aw-actions/setup-cli",
- "version": "v0.85.4",
- "sha": "2709137ea6c5b0e19aa621454dc643ea8dc526b1"
- },
- "github/gh-aw-actions/setup@v0.85.4": {
+ "github/gh-aw-actions/setup@v0.86.2": {
"repo": "github/gh-aw-actions/setup",
- "version": "v0.85.4",
- "sha": "2709137ea6c5b0e19aa621454dc643ea8dc526b1"
+ "version": "v0.86.2",
+ "sha": "6aab9e5b5c91c615506061f09bedd81a23babe3c"
}
},
"containers": {
diff --git a/.github/workflows/analyze-ci-failure.lock.yml b/.github/workflows/analyze-ci-failure.lock.yml
index 0c65b3b7d12..b3bcb79e0fa 100644
--- a/.github/workflows/analyze-ci-failure.lock.yml
+++ b/.github/workflows/analyze-ci-failure.lock.yml
@@ -1,6 +1,6 @@
-# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"c44db4d6b9d3eb5fcff0743f5be77375e66dec9b1c263c8d33deea9dcb257240","body_hash":"e9f3545ccbe75e728bdac1140123f0ebea921e69ff4b3a44a28fa977bf00ba74","compiler_version":"v0.85.4","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.78"}}
-# gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","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":"34e114876b0b11c390a56381ad16ebd13914f8d5","version":"v4"},{"repo":"actions/checkout","sha":"3d3c42e5aac5ba805825da76410c181273ba90b1","version":"v7.0.1"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/download-artifact","sha":"d3f86a106a0bac45b974a628896c90dbdf5c8093","version":"v4"},{"repo":"actions/github-script","sha":"373c709c69115d41ff229c7e5df9f8788daa9553","version":"v9"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"820762786026740c76f36085b0efc47a31fe5020","version":"v7.0.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"actions/upload-artifact","sha":"ea165f8d65b6e75b540449e92b4886f43607fa02","version":"v4"},{"repo":"github/gh-aw-actions/setup","sha":"2709137ea6c5b0e19aa621454dc643ea8dc526b1","version":"v0.85.4"}],"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.8","digest":"sha256:38bbea36cdb46a3c9d04d1db05e672966f5239b431a2022eb35881688e5721d8","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.4.8@sha256:38bbea36cdb46a3c9d04d1db05e672966f5239b431a2022eb35881688e5721d8"},{"image":"ghcr.io/github/gh-aw-node","digest":"sha256:0d9f1fb5fd6610c0ac1f5194a38e45a8a1e81f8a390d5142d8e4e6f26a4b3196","pinned_image":"ghcr.io/github/gh-aw-node@sha256:0d9f1fb5fd6610c0ac1f5194a38e45a8a1e81f8a390d5142d8e4e6f26a4b3196"},{"image":"ghcr.io/github/github-mcp-server:v1.8.0","digest":"sha256:d5a18c04b92714c309eb46a2305087e91a4dbd80420f6e462656699f95093520","pinned_image":"ghcr.io/github/github-mcp-server:v1.8.0@sha256:d5a18c04b92714c309eb46a2305087e91a4dbd80420f6e462656699f95093520"}]}
-# This file was automatically generated by gh-aw (v0.85.4). DO NOT EDIT. To debug this workflow, load the skill at https://github.com/github/gh-aw/blob/main/debug.md
+# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"c44db4d6b9d3eb5fcff0743f5be77375e66dec9b1c263c8d33deea9dcb257240","body_hash":"e9f3545ccbe75e728bdac1140123f0ebea921e69ff4b3a44a28fa977bf00ba74","compiler_version":"v0.86.2","strict":true,"agent_id":"copilot","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":"34e114876b0b11c390a56381ad16ebd13914f8d5","version":"v4"},{"repo":"actions/checkout","sha":"3d3c42e5aac5ba805825da76410c181273ba90b1","version":"v7.0.1"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/download-artifact","sha":"d3f86a106a0bac45b974a628896c90dbdf5c8093","version":"v4"},{"repo":"actions/github-script","sha":"373c709c69115d41ff229c7e5df9f8788daa9553","version":"v9"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"820762786026740c76f36085b0efc47a31fe5020","version":"v7.0.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"actions/upload-artifact","sha":"ea165f8d65b6e75b540449e92b4886f43607fa02","version":"v4"},{"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"},{"image":"ghcr.io/github/github-mcp-server:v1.9.0","digest":"sha256:881b53d6f75f69bdbc1b5b10fc2f1361717c19054143b3a8529fb5c32061a50e","pinned_image":"ghcr.io/github/github-mcp-server:v1.9.0@sha256:881b53d6f75f69bdbc1b5b10fc2f1361717c19054143b3a8529fb5c32061a50e"}]}
+# 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
#
# ___ _ _
# / _ \ | | (_)
@@ -34,7 +34,6 @@
# - ENABLE_RERUN: (main workflow)
#
# Secrets used:
-# - COPILOT_GITHUB_TOKEN
# - GH_AW_GITHUB_MCP_SERVER_TOKEN
# - GH_AW_GITHUB_TOKEN
# - GITHUB_TOKEN
@@ -51,15 +50,15 @@
# - actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
# - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
# - actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
-# - github/gh-aw-actions/setup@2709137ea6c5b0e19aa621454dc643ea8dc526b1 # v0.85.4
+# - 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.8@sha256:38bbea36cdb46a3c9d04d1db05e672966f5239b431a2022eb35881688e5721d8
+# - ghcr.io/github/gh-aw-mcpg:v0.4.9@sha256:e5a1569aeaf41820fa7bdee3e94468cae448133cdbf00119ad24f5b74db1ab9f
# - ghcr.io/github/gh-aw-node@sha256:0d9f1fb5fd6610c0ac1f5194a38e45a8a1e81f8a390d5142d8e4e6f26a4b3196
-# - ghcr.io/github/github-mcp-server:v1.8.0@sha256:d5a18c04b92714c309eb46a2305087e91a4dbd80420f6e462656699f95093520
+# - ghcr.io/github/github-mcp-server:v1.9.0@sha256:881b53d6f75f69bdbc1b5b10fc2f1361717c19054143b3a8529fb5c32061a50e
name: "Analyze CI Failure"
on:
@@ -126,7 +125,7 @@ jobs:
steps:
- name: Setup Scripts
id: setup
- uses: github/gh-aw-actions/setup@2709137ea6c5b0e19aa621454dc643ea8dc526b1 # v0.85.4
+ uses: github/gh-aw-actions/setup@6aab9e5b5c91c615506061f09bedd81a23babe3c # v0.86.2
with:
destination: ${{ runner.temp }}/gh-aw/actions
job-name: ${{ github.job }}
@@ -136,7 +135,7 @@ jobs:
env:
GH_AW_SETUP_WORKFLOW_NAME: "Analyze CI Failure"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/analyze-ci-failure.lock.yml@${{ github.ref }}
- GH_AW_INFO_VERSION: "1.0.78"
+ 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
@@ -145,9 +144,9 @@ jobs:
GH_AW_INFO_ENGINE_ID: "copilot"
GH_AW_INFO_ENGINE_NAME: "GitHub Copilot CLI"
GH_AW_INFO_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || vars.GH_AW_DEFAULT_MODEL_COPILOT || 'auto' }}
- GH_AW_INFO_VERSION: "1.0.78"
- GH_AW_INFO_AGENT_VERSION: "1.0.78"
- GH_AW_INFO_CLI_VERSION: "v0.85.4"
+ 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: "Analyze CI Failure"
GH_AW_INFO_EXPERIMENTAL: "false"
GH_AW_INFO_SUPPORTS_TOOLS_ALLOWLIST: "true"
@@ -157,6 +156,7 @@ jobs:
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_COMPILED_STRICT: "true"
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
@@ -213,7 +213,6 @@ jobs:
id: check-oauth-tokens
run: bash "${RUNNER_TEMP}/gh-aw/actions/check_oauth_tokens.sh"
env:
- COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
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
@@ -233,8 +232,8 @@ jobs:
env:
GH_AW_AGENT_FOLDERS: ".agents .github"
GH_AW_AGENT_FILES: "AGENTS.md"
- # poutine:ignore untrusted_checkout_exec
- run: bash "${RUNNER_TEMP}/gh-aw/actions/save_base_github_folders.sh"
+ 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
@@ -250,7 +249,7 @@ jobs:
- name: Check compile-agentic version
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
- GH_AW_COMPILED_VERSION: "v0.85.4"
+ GH_AW_COMPILED_VERSION: "v0.86.2"
with:
script: |
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
@@ -261,9 +260,12 @@ jobs:
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_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ 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\"},{\"file\":\"github_mcp_tools_with_safeoutputs_prompt.md\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0004\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0005\"}]}"
GH_AW_EXPR_1A3A194A: ${{ github.event.discussion.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'discussion' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }}
GH_AW_EXPR_463A214A: ${{ github.event.pull_request.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'pull_request' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }}
GH_AW_EXPR_802A9F6A: ${{ github.event.issue.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'issue' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }}
@@ -272,63 +274,22 @@ jobs:
GH_AW_GITHUB_REPOSITORY: ${{ github.repository }}
GH_AW_GITHUB_RUN_ID: ${{ github.run_id }}
GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }}
- # poutine:ignore untrusted_checkout_exec
- run: |
- bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh"
- {
- cat << 'GH_AW_PROMPT_56ae825d04a19e36_EOF'
-
- GH_AW_PROMPT_56ae825d04a19e36_EOF
- cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md"
- cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md"
- cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md"
- cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md"
- cat << 'GH_AW_PROMPT_56ae825d04a19e36_EOF'
-
- Tools: missing_tool, missing_data, noop, publish_data, rerun_failed_jobs
-
- GH_AW_PROMPT_56ae825d04a19e36_EOF
- cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md"
- cat << 'GH_AW_PROMPT_56ae825d04a19e36_EOF'
-
- The following GitHub context information is available for this workflow:
- {{#if github.actor}}
- - **actor**: __GH_AW_GITHUB_ACTOR__
- {{/if}}
- {{#if github.repository}}
- - **repository**: __GH_AW_GITHUB_REPOSITORY__
- {{/if}}
- {{#if github.workspace}}
- - **workspace**: __GH_AW_GITHUB_WORKSPACE__
- {{/if}}
- {{#if github.event.issue.number || (github.aw.context.item_type == 'issue' && github.aw.context.item_number)}}
- - **issue-number**: #__GH_AW_EXPR_802A9F6A__
- {{/if}}
- {{#if github.event.discussion.number || (github.aw.context.item_type == 'discussion' && github.aw.context.item_number)}}
- - **discussion-number**: #__GH_AW_EXPR_1A3A194A__
- {{/if}}
- {{#if github.event.pull_request.number || (github.aw.context.item_type == 'pull_request' && github.aw.context.item_number)}}
- - **pull-request-number**: #__GH_AW_EXPR_463A214A__
- {{/if}}
- {{#if github.event.comment.id || github.aw.context.comment_id}}
- - **comment-id**: __GH_AW_EXPR_FF1D34CE__
- {{/if}}
- {{#if github.run_id}}
- - **workflow-run-id**: __GH_AW_GITHUB_RUN_ID__
- {{/if}}
-
-
- GH_AW_PROMPT_56ae825d04a19e36_EOF
- cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md"
- cat << 'GH_AW_PROMPT_56ae825d04a19e36_EOF'
-
- {{#runtime-import .github/workflows/analyze-ci-failure.md}}
- GH_AW_PROMPT_56ae825d04a19e36_EOF
- } > "$GH_AW_PROMPT"
+ GH_AW_PROMPT_CONTENT_0000: "\n"
+ GH_AW_PROMPT_CONTENT_0001: "\nTools: missing_tool, missing_data, noop, publish_data, rerun_failed_jobs\n"
+ GH_AW_PROMPT_CONTENT_0002: "\n"
+ GH_AW_PROMPT_CONTENT_0003: "\nThe following GitHub context information is available for this workflow:\n{{#if github.actor}}\n- **actor**: __GH_AW_GITHUB_ACTOR__\n{{/if}}\n{{#if github.repository}}\n- **repository**: __GH_AW_GITHUB_REPOSITORY__\n{{/if}}\n{{#if github.workspace}}\n- **workspace**: __GH_AW_GITHUB_WORKSPACE__\n{{/if}}\n{{#if github.event.issue.number || (github.aw.context.item_type == 'issue' && github.aw.context.item_number)}}\n- **issue-number**: #__GH_AW_EXPR_802A9F6A__\n{{/if}}\n{{#if github.event.discussion.number || (github.aw.context.item_type == 'discussion' && github.aw.context.item_number)}}\n- **discussion-number**: #__GH_AW_EXPR_1A3A194A__\n{{/if}}\n{{#if github.event.pull_request.number || (github.aw.context.item_type == 'pull_request' && github.aw.context.item_number)}}\n- **pull-request-number**: #__GH_AW_EXPR_463A214A__\n{{/if}}\n{{#if github.event.comment.id || github.aw.context.comment_id}}\n- **comment-id**: __GH_AW_EXPR_FF1D34CE__\n{{/if}}\n{{#if github.run_id}}\n- **workflow-run-id**: __GH_AW_GITHUB_RUN_ID__\n{{/if}}\n\n\n"
+ GH_AW_PROMPT_CONTENT_0004: "\n"
+ GH_AW_PROMPT_CONTENT_0005: "{{#runtime-import .github/workflows/analyze-ci-failure.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: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_PROMPT: ${{ runner.temp }}/gh-aw/aw-prompts/prompt.txt
GH_AW_ENGINE_ID: "copilot"
with:
script: |
@@ -339,7 +300,7 @@ jobs:
- name: Substitute placeholders
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
- GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_PROMPT: ${{ runner.temp }}/gh-aw/aw-prompts/prompt.txt
GH_AW_EXPR_1A3A194A: ${{ github.event.discussion.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'discussion' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }}
GH_AW_EXPR_463A214A: ${{ github.event.pull_request.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'pull_request' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }}
GH_AW_EXPR_802A9F6A: ${{ github.event.issue.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'issue' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }}
@@ -375,14 +336,18 @@ jobs:
});
- name: Validate prompt placeholders
env:
- GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
- # poutine:ignore untrusted_checkout_exec
- run: bash "${RUNNER_TEMP}/gh-aw/actions/validate_prompt_placeholders.sh"
+ 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: /tmp/gh-aw/aw-prompts/prompt.txt
- # poutine:ignore untrusted_checkout_exec
- run: bash "${RUNNER_TEMP}/gh-aw/actions/print_prompt_summary.sh"
+ 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
@@ -452,7 +417,7 @@ jobs:
steps:
- name: Setup Scripts
id: setup
- uses: github/gh-aw-actions/setup@2709137ea6c5b0e19aa621454dc643ea8dc526b1 # v0.85.4
+ uses: github/gh-aw-actions/setup@6aab9e5b5c91c615506061f09bedd81a23babe3c # v0.86.2
with:
destination: ${{ runner.temp }}/gh-aw/actions
job-name: ${{ github.job }}
@@ -461,7 +426,7 @@ jobs:
env:
GH_AW_SETUP_WORKFLOW_NAME: "Analyze CI Failure"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/analyze-ci-failure.lock.yml@${{ github.ref }}
- GH_AW_INFO_VERSION: "1.0.78"
+ 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
@@ -512,11 +477,13 @@ jobs:
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.85.4
+ 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: Determine automatic lockdown mode for GitHub MCP Server
@@ -545,7 +512,7 @@ jobs:
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.8@sha256:38bbea36cdb46a3c9d04d1db05e672966f5239b431a2022eb35881688e5721d8 ghcr.io/github/gh-aw-node@sha256:0d9f1fb5fd6610c0ac1f5194a38e45a8a1e81f8a390d5142d8e4e6f26a4b3196 ghcr.io/github/github-mcp-server:v1.8.0@sha256:d5a18c04b92714c309eb46a2305087e91a4dbd80420f6e462656699f95093520
+ 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 ghcr.io/github/github-mcp-server:v1.9.0@sha256:881b53d6f75f69bdbc1b5b10fc2f1361717c19054143b3a8529fb5c32061a50e
- name: Generate Safe Outputs Config
run: |
mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs"
@@ -721,22 +688,23 @@ jobs:
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"
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 -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.8'
+ 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_bd6748a39fe70b8b_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs"
+ cat << GH_AW_MCP_CONFIG_e26f23cc8d0ae67e_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs"
{
"mcpServers": {
"github": {
"type": "stdio",
- "container": "ghcr.io/github/github-mcp-server:v1.8.0",
+ "container": "ghcr.io/github/github-mcp-server:v1.9.0",
"env": {
"GITHUB_FEATURES": "fields_param",
"GITHUB_HOST": "${GITHUB_SERVER_URL}",
@@ -793,7 +761,7 @@ jobs:
"startupTimeout": 120
}
}
- GH_AW_MCP_CONFIG_bd6748a39fe70b8b_EOF
+ GH_AW_MCP_CONFIG_e26f23cc8d0ae67e_EOF
- name: Mount MCP servers as CLIs
id: mount-mcp-clis
continue-on-error: true
@@ -827,6 +795,18 @@ jobs:
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
@@ -851,8 +831,8 @@ jobs:
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 GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_API_KEY --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 /usr/local/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 --allow-all-paths --add-dir "${GITHUB_WORKSPACE}" --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log
+ 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 GITHUB_MCP_SERVER_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-all-tools --allow-all-paths --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
@@ -866,7 +846,7 @@ jobs:
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.85.4
+ GH_AW_VERSION: v0.86.2
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
GITHUB_COPILOT_INTEGRATION_ID: agentic-workflows
@@ -1457,7 +1437,7 @@ jobs:
steps:
- name: Setup Scripts
id: setup
- uses: github/gh-aw-actions/setup@2709137ea6c5b0e19aa621454dc643ea8dc526b1 # v0.85.4
+ uses: github/gh-aw-actions/setup@6aab9e5b5c91c615506061f09bedd81a23babe3c # v0.86.2
with:
destination: ${{ runner.temp }}/gh-aw/actions
job-name: ${{ github.job }}
@@ -1466,7 +1446,7 @@ jobs:
env:
GH_AW_SETUP_WORKFLOW_NAME: "Analyze CI Failure"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/analyze-ci-failure.lock.yml@${{ github.ref }}
- GH_AW_INFO_VERSION: "1.0.78"
+ 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
@@ -1705,7 +1685,7 @@ jobs:
steps:
- name: Setup Scripts
id: setup
- uses: github/gh-aw-actions/setup@2709137ea6c5b0e19aa621454dc643ea8dc526b1 # v0.85.4
+ uses: github/gh-aw-actions/setup@6aab9e5b5c91c615506061f09bedd81a23babe3c # v0.86.2
with:
destination: ${{ runner.temp }}/gh-aw/actions
job-name: ${{ github.job }}
@@ -1714,7 +1694,7 @@ jobs:
env:
GH_AW_SETUP_WORKFLOW_NAME: "Analyze CI Failure"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/analyze-ci-failure.lock.yml@${{ github.ref }}
- GH_AW_INFO_VERSION: "1.0.78"
+ 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
@@ -1766,25 +1746,7 @@ jobs:
- name: Prepare threat detection files
if: always() && steps.detection_guard.outputs.run_detection == 'true'
run: |
- mkdir -p /tmp/gh-aw/threat-detection/aw-prompts
- rm -f /tmp/gh-aw/agent_usage.json
- cp /tmp/gh-aw/aw-prompts/prompt.txt /tmp/gh-aw/threat-detection/aw-prompts/prompt.txt 2>/dev/null || true
- if [ ! -s /tmp/gh-aw/threat-detection/aw-prompts/prompt.txt ]; then
- echo "::warning::ERR_VALIDATION: Missing or empty detection context prompt at /tmp/gh-aw/threat-detection/aw-prompts/prompt.txt. Ensure the agent artifact includes /tmp/gh-aw/aw-prompts/prompt.txt. Detection will continue with fallback workflow context."
- fi
- cp /tmp/gh-aw/agent_output.json /tmp/gh-aw/threat-detection/agent_output.json 2>/dev/null || true
- for f in /tmp/gh-aw/aw-*.patch; do
- if [ -f "$f" ]; then
- cp "$f" /tmp/gh-aw/threat-detection/ 2>/dev/null || true
- fi
- done
- for f in /tmp/gh-aw/aw-*.bundle; do
- if [ -f "$f" ]; then
- cp "$f" /tmp/gh-aw/threat-detection/ 2>/dev/null || true
- fi
- done
- echo "Prepared threat detection files:"
- ls -la /tmp/gh-aw/threat-detection/ 2>/dev/null || true
+ 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
@@ -1804,18 +1766,20 @@ jobs:
run: |
mkdir -p /tmp/gh-aw/threat-detection
touch /tmp/gh-aw/threat-detection/detection.log
- rm -f /tmp/gh-aw/threat-detection/step-summary.md
- touch /tmp/gh-aw/threat-detection/step-summary.md
+ 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.85.4
+ 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
@@ -1831,6 +1795,18 @@ jobs:
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
@@ -1857,9 +1833,10 @@ jobs:
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 --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 /usr/local/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 --add-dir "${GITHUB_WORKSPACE}" --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' 2>&1 | tee -a /tmp/gh-aw/threat-detection/detection.log
+ 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 --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
@@ -1871,14 +1848,13 @@ jobs:
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_TIMEOUT_MINUTES: 20
- GH_AW_VERSION: v0.85.4
+ 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]
@@ -1887,6 +1863,23 @@ jobs:
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()
@@ -1953,14 +1946,14 @@ jobs:
steps:
- name: Setup Scripts
id: setup
- uses: github/gh-aw-actions/setup@2709137ea6c5b0e19aa621454dc643ea8dc526b1 # v0.85.4
+ 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: "Analyze CI Failure"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/analyze-ci-failure.lock.yml@${{ github.ref }}
- GH_AW_INFO_VERSION: "1.0.78"
+ GH_AW_INFO_VERSION: "1.0.79"
GH_AW_INFO_AWF_VERSION: "v0.27.44"
GH_AW_INFO_ENGINE_ID: "copilot"
- name: Check team membership for workflow
@@ -2478,15 +2471,20 @@ jobs:
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@2709137ea6c5b0e19aa621454dc643ea8dc526b1 # v0.85.4
+ uses: github/gh-aw-actions/setup@6aab9e5b5c91c615506061f09bedd81a23babe3c # v0.86.2
with:
destination: ${{ runner.temp }}/gh-aw/actions
job-name: ${{ github.job }}
@@ -2495,7 +2493,7 @@ jobs:
env:
GH_AW_SETUP_WORKFLOW_NAME: "Analyze CI Failure"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/analyze-ci-failure.lock.yml@${{ github.ref }}
- GH_AW_INFO_VERSION: "1.0.78"
+ 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
diff --git a/.github/workflows/build-cli-native-archives.yml b/.github/workflows/build-cli-native-archives.yml
index dc313770b40..f6bdbaa3e1a 100644
--- a/.github/workflows/build-cli-native-archives.yml
+++ b/.github/workflows/build-cli-native-archives.yml
@@ -16,12 +16,14 @@ on:
Defaults to all platforms (linux-x64, linux-arm64, win-x64, win-arm64, osx-arm64).
required: false
type: string
+ # Use the VS 2026 ARM preview image for its newer native linker. The VS 2022 ARM image
+ # fails to link Aspire.Dashboard.obj with LNK1322.
default: >-
[
{"os": "ubuntu-latest", "runner": "8-core-ubuntu-latest", "rids": "linux-x64"},
{"os": "ubuntu-latest", "runner": "ubuntu-24.04-arm", "rids": "linux-arm64"},
{"os": "windows-latest", "runner": "windows-latest", "rids": "win-x64"},
- {"os": "windows-latest", "runner": "windows-11-arm", "rids": "win-arm64"},
+ {"os": "windows-latest", "runner": "windows-11-vs2026-arm", "rids": "win-arm64"},
{"os": "macos-latest", "runner": "macos-latest", "rids": "osx-arm64"}
]
@@ -99,6 +101,16 @@ jobs:
/bl:${{ github.workspace }}/artifacts/log/${{ inputs.configuration }}/BundlePayload.binlog
${{ inputs.versionOverrideArg }}
+ - name: Smoke test Native AOT Dashboard
+ # osx-x64 is cross-compiled on an Apple Silicon runner and cannot be executed there
+ # without introducing an undeclared Rosetta dependency.
+ if: ${{ matrix.targets.rids != 'osx-x64' }}
+ shell: pwsh
+ run: |
+ $extension = if ('${{ runner.os }}' -eq 'Windows') { '.exe' } else { '' }
+ $dashboardPath = (Join-Path '${{ github.workspace }}' 'artifacts/bin/Aspire.Dashboard/${{ matrix.targets.rids }}/${{ inputs.configuration }}/net11.0/${{ matrix.targets.rids }}/publish/Aspire.Dashboard') + $extension
+ ./eng/scripts/test-native-dashboard.ps1 -DashboardPath $dashboardPath
+
- name: Build CLI packages
run: >
${{ runner.os == 'Windows' && './build.cmd' || './build.sh' }}
diff --git a/.github/workflows/daily-repo-status.lock.yml b/.github/workflows/daily-repo-status.lock.yml
index bc992a9ca48..5ebcec53570 100644
--- a/.github/workflows/daily-repo-status.lock.yml
+++ b/.github/workflows/daily-repo-status.lock.yml
@@ -1,6 +1,6 @@
-# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"441fe3ce33beb847f81893da0670b20aa6d9f12cbf046a62a860e475a3293533","body_hash":"936610a6392f840bf4485eb4a73d30c1247401e93bd19a693e47a50cc24a7496","compiler_version":"v0.85.4","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.78"}}
-# gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","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":"373c709c69115d41ff229c7e5df9f8788daa9553","version":"v9"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"820762786026740c76f36085b0efc47a31fe5020","version":"v7.0.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"2709137ea6c5b0e19aa621454dc643ea8dc526b1","version":"v0.85.4"}],"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.8","digest":"sha256:38bbea36cdb46a3c9d04d1db05e672966f5239b431a2022eb35881688e5721d8","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.4.8@sha256:38bbea36cdb46a3c9d04d1db05e672966f5239b431a2022eb35881688e5721d8"},{"image":"ghcr.io/github/gh-aw-node","digest":"sha256:0d9f1fb5fd6610c0ac1f5194a38e45a8a1e81f8a390d5142d8e4e6f26a4b3196","pinned_image":"ghcr.io/github/gh-aw-node@sha256:0d9f1fb5fd6610c0ac1f5194a38e45a8a1e81f8a390d5142d8e4e6f26a4b3196"},{"image":"ghcr.io/github/github-mcp-server:v1.8.0","digest":"sha256:d5a18c04b92714c309eb46a2305087e91a4dbd80420f6e462656699f95093520","pinned_image":"ghcr.io/github/github-mcp-server:v1.8.0@sha256:d5a18c04b92714c309eb46a2305087e91a4dbd80420f6e462656699f95093520"}]}
-# This file was automatically generated by gh-aw (v0.85.4). DO NOT EDIT. To debug this workflow, load the skill at https://github.com/github/gh-aw/blob/main/debug.md
+# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"441fe3ce33beb847f81893da0670b20aa6d9f12cbf046a62a860e475a3293533","body_hash":"936610a6392f840bf4485eb4a73d30c1247401e93bd19a693e47a50cc24a7496","compiler_version":"v0.86.2","strict":true,"agent_id":"copilot","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":"373c709c69115d41ff229c7e5df9f8788daa9553","version":"v9"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"820762786026740c76f36085b0efc47a31fe5020","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"},{"image":"ghcr.io/github/github-mcp-server:v1.9.0","digest":"sha256:881b53d6f75f69bdbc1b5b10fc2f1361717c19054143b3a8529fb5c32061a50e","pinned_image":"ghcr.io/github/github-mcp-server:v1.9.0@sha256:881b53d6f75f69bdbc1b5b10fc2f1361717c19054143b3a8529fb5c32061a50e"}]}
+# 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
#
# ___ _ _
# / _ \ | | (_)
@@ -29,7 +29,6 @@
# a 7-day burndown chart using cached daily snapshots.
#
# Secrets used:
-# - COPILOT_GITHUB_TOKEN
# - GH_AW_GITHUB_MCP_SERVER_TOKEN
# - GH_AW_GITHUB_TOKEN
# - GITHUB_TOKEN
@@ -43,15 +42,15 @@
# - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
# - actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
# - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
-# - github/gh-aw-actions/setup@2709137ea6c5b0e19aa621454dc643ea8dc526b1 # v0.85.4
+# - 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.8@sha256:38bbea36cdb46a3c9d04d1db05e672966f5239b431a2022eb35881688e5721d8
+# - ghcr.io/github/gh-aw-mcpg:v0.4.9@sha256:e5a1569aeaf41820fa7bdee3e94468cae448133cdbf00119ad24f5b74db1ab9f
# - ghcr.io/github/gh-aw-node@sha256:0d9f1fb5fd6610c0ac1f5194a38e45a8a1e81f8a390d5142d8e4e6f26a4b3196
-# - ghcr.io/github/github-mcp-server:v1.8.0@sha256:d5a18c04b92714c309eb46a2305087e91a4dbd80420f6e462656699f95093520
+# - ghcr.io/github/github-mcp-server:v1.9.0@sha256:881b53d6f75f69bdbc1b5b10fc2f1361717c19054143b3a8529fb5c32061a50e
name: "13.3 Release Burndown Report"
on:
@@ -95,14 +94,14 @@ jobs:
steps:
- name: Setup Scripts
id: setup
- uses: github/gh-aw-actions/setup@2709137ea6c5b0e19aa621454dc643ea8dc526b1 # v0.85.4
+ 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: "13.3 Release Burndown Report"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/daily-repo-status.lock.yml@${{ github.ref }}
- GH_AW_INFO_VERSION: "1.0.78"
+ 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
@@ -111,9 +110,9 @@ jobs:
GH_AW_INFO_ENGINE_ID: "copilot"
GH_AW_INFO_ENGINE_NAME: "GitHub Copilot CLI"
GH_AW_INFO_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || vars.GH_AW_DEFAULT_MODEL_COPILOT || 'auto' }}
- GH_AW_INFO_VERSION: "1.0.78"
- GH_AW_INFO_AGENT_VERSION: "1.0.78"
- GH_AW_INFO_CLI_VERSION: "v0.85.4"
+ 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: "13.3 Release Burndown Report"
GH_AW_INFO_EXPERIMENTAL: "false"
GH_AW_INFO_SUPPORTS_TOOLS_ALLOWLIST: "true"
@@ -123,6 +122,7 @@ jobs:
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_COMPILED_STRICT: "true"
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
@@ -135,7 +135,6 @@ jobs:
id: check-oauth-tokens
run: bash "${RUNNER_TEMP}/gh-aw/actions/check_oauth_tokens.sh"
env:
- COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
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
@@ -155,8 +154,8 @@ jobs:
env:
GH_AW_AGENT_FOLDERS: ".agents .github"
GH_AW_AGENT_FILES: "AGENTS.md"
- # poutine:ignore untrusted_checkout_exec
- run: bash "${RUNNER_TEMP}/gh-aw/actions/save_base_github_folders.sh"
+ 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
@@ -172,7 +171,7 @@ jobs:
- name: Check compile-agentic version
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
- GH_AW_COMPILED_VERSION: "v0.85.4"
+ GH_AW_COMPILED_VERSION: "v0.86.2"
with:
script: |
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
@@ -183,9 +182,12 @@ jobs:
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_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ 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\":\"cache_memory_prompt.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\"},{\"file\":\"github_mcp_tools_with_safeoutputs_prompt.md\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0004\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0005\"}]}"
GH_AW_EXPR_1A3A194A: ${{ github.event.discussion.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'discussion' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }}
GH_AW_EXPR_463A214A: ${{ github.event.pull_request.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'pull_request' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }}
GH_AW_EXPR_802A9F6A: ${{ github.event.issue.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'issue' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }}
@@ -194,64 +196,22 @@ jobs:
GH_AW_GITHUB_REPOSITORY: ${{ github.repository }}
GH_AW_GITHUB_RUN_ID: ${{ github.run_id }}
GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }}
- # poutine:ignore untrusted_checkout_exec
- run: |
- bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh"
- {
- cat << 'GH_AW_PROMPT_67a087ba6d97491a_EOF'
-
- GH_AW_PROMPT_67a087ba6d97491a_EOF
- cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md"
- cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md"
- cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md"
- cat "${RUNNER_TEMP}/gh-aw/prompts/cache_memory_prompt.md"
- cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md"
- cat << 'GH_AW_PROMPT_67a087ba6d97491a_EOF'
-
- Tools: create_issue, missing_tool, missing_data, noop
-
- GH_AW_PROMPT_67a087ba6d97491a_EOF
- cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md"
- cat << 'GH_AW_PROMPT_67a087ba6d97491a_EOF'
-
- The following GitHub context information is available for this workflow:
- {{#if github.actor}}
- - **actor**: __GH_AW_GITHUB_ACTOR__
- {{/if}}
- {{#if github.repository}}
- - **repository**: __GH_AW_GITHUB_REPOSITORY__
- {{/if}}
- {{#if github.workspace}}
- - **workspace**: __GH_AW_GITHUB_WORKSPACE__
- {{/if}}
- {{#if github.event.issue.number || (github.aw.context.item_type == 'issue' && github.aw.context.item_number)}}
- - **issue-number**: #__GH_AW_EXPR_802A9F6A__
- {{/if}}
- {{#if github.event.discussion.number || (github.aw.context.item_type == 'discussion' && github.aw.context.item_number)}}
- - **discussion-number**: #__GH_AW_EXPR_1A3A194A__
- {{/if}}
- {{#if github.event.pull_request.number || (github.aw.context.item_type == 'pull_request' && github.aw.context.item_number)}}
- - **pull-request-number**: #__GH_AW_EXPR_463A214A__
- {{/if}}
- {{#if github.event.comment.id || github.aw.context.comment_id}}
- - **comment-id**: __GH_AW_EXPR_FF1D34CE__
- {{/if}}
- {{#if github.run_id}}
- - **workflow-run-id**: __GH_AW_GITHUB_RUN_ID__
- {{/if}}
-
-
- GH_AW_PROMPT_67a087ba6d97491a_EOF
- cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md"
- cat << 'GH_AW_PROMPT_67a087ba6d97491a_EOF'
-
- {{#runtime-import .github/workflows/daily-repo-status.md}}
- GH_AW_PROMPT_67a087ba6d97491a_EOF
- } > "$GH_AW_PROMPT"
+ GH_AW_PROMPT_CONTENT_0000: "\n"
+ GH_AW_PROMPT_CONTENT_0001: "\nTools: create_issue, missing_tool, missing_data, noop\n"
+ GH_AW_PROMPT_CONTENT_0002: "\n"
+ GH_AW_PROMPT_CONTENT_0003: "\nThe following GitHub context information is available for this workflow:\n{{#if github.actor}}\n- **actor**: __GH_AW_GITHUB_ACTOR__\n{{/if}}\n{{#if github.repository}}\n- **repository**: __GH_AW_GITHUB_REPOSITORY__\n{{/if}}\n{{#if github.workspace}}\n- **workspace**: __GH_AW_GITHUB_WORKSPACE__\n{{/if}}\n{{#if github.event.issue.number || (github.aw.context.item_type == 'issue' && github.aw.context.item_number)}}\n- **issue-number**: #__GH_AW_EXPR_802A9F6A__\n{{/if}}\n{{#if github.event.discussion.number || (github.aw.context.item_type == 'discussion' && github.aw.context.item_number)}}\n- **discussion-number**: #__GH_AW_EXPR_1A3A194A__\n{{/if}}\n{{#if github.event.pull_request.number || (github.aw.context.item_type == 'pull_request' && github.aw.context.item_number)}}\n- **pull-request-number**: #__GH_AW_EXPR_463A214A__\n{{/if}}\n{{#if github.event.comment.id || github.aw.context.comment_id}}\n- **comment-id**: __GH_AW_EXPR_FF1D34CE__\n{{/if}}\n{{#if github.run_id}}\n- **workflow-run-id**: __GH_AW_GITHUB_RUN_ID__\n{{/if}}\n\n\n"
+ GH_AW_PROMPT_CONTENT_0004: "\n"
+ GH_AW_PROMPT_CONTENT_0005: "{{#runtime-import .github/workflows/daily-repo-status.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: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_PROMPT: ${{ runner.temp }}/gh-aw/aw-prompts/prompt.txt
GH_AW_ENGINE_ID: "copilot"
with:
script: |
@@ -262,7 +222,7 @@ jobs:
- name: Substitute placeholders
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
- GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_PROMPT: ${{ runner.temp }}/gh-aw/aw-prompts/prompt.txt
GH_AW_ALLOWED_EXTENSIONS: ''
GH_AW_CACHE_DESCRIPTION: ''
GH_AW_CACHE_DIR: '/tmp/gh-aw/cache-memory/'
@@ -302,14 +262,18 @@ jobs:
});
- name: Validate prompt placeholders
env:
- GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
- # poutine:ignore untrusted_checkout_exec
- run: bash "${RUNNER_TEMP}/gh-aw/actions/validate_prompt_placeholders.sh"
+ 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: /tmp/gh-aw/aw-prompts/prompt.txt
- # poutine:ignore untrusted_checkout_exec
- run: bash "${RUNNER_TEMP}/gh-aw/actions/print_prompt_summary.sh"
+ 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
@@ -377,7 +341,7 @@ jobs:
steps:
- name: Setup Scripts
id: setup
- uses: github/gh-aw-actions/setup@2709137ea6c5b0e19aa621454dc643ea8dc526b1 # v0.85.4
+ uses: github/gh-aw-actions/setup@6aab9e5b5c91c615506061f09bedd81a23babe3c # v0.86.2
with:
destination: ${{ runner.temp }}/gh-aw/actions
job-name: ${{ github.job }}
@@ -386,7 +350,7 @@ jobs:
env:
GH_AW_SETUP_WORKFLOW_NAME: "13.3 Release Burndown Report"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/daily-repo-status.lock.yml@${{ github.ref }}
- GH_AW_INFO_VERSION: "1.0.78"
+ 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
@@ -448,11 +412,13 @@ jobs:
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.85.4
+ 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: Determine automatic lockdown mode for GitHub MCP Server
@@ -481,7 +447,7 @@ jobs:
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.8@sha256:38bbea36cdb46a3c9d04d1db05e672966f5239b431a2022eb35881688e5721d8 ghcr.io/github/gh-aw-node@sha256:0d9f1fb5fd6610c0ac1f5194a38e45a8a1e81f8a390d5142d8e4e6f26a4b3196 ghcr.io/github/github-mcp-server:v1.8.0@sha256:d5a18c04b92714c309eb46a2305087e91a4dbd80420f6e462656699f95093520
+ 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 ghcr.io/github/github-mcp-server:v1.9.0@sha256:881b53d6f75f69bdbc1b5b10fc2f1361717c19054143b3a8529fb5c32061a50e
- name: Generate Safe Outputs Config
run: |
mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs"
@@ -646,22 +612,23 @@ jobs:
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"
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 -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.8'
+ 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_b9a84583d08a9e5d_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs"
+ cat << GH_AW_MCP_CONFIG_8ce5941148a2fcea_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs"
{
"mcpServers": {
"github": {
"type": "stdio",
- "container": "ghcr.io/github/github-mcp-server:v1.8.0",
+ "container": "ghcr.io/github/github-mcp-server:v1.9.0",
"env": {
"GITHUB_FEATURES": "fields_param",
"GITHUB_HOST": "${GITHUB_SERVER_URL}",
@@ -718,7 +685,7 @@ jobs:
"startupTimeout": 120
}
}
- GH_AW_MCP_CONFIG_b9a84583d08a9e5d_EOF
+ GH_AW_MCP_CONFIG_8ce5941148a2fcea_EOF
- name: Mount MCP servers as CLIs
id: mount-mcp-clis
continue-on-error: true
@@ -752,6 +719,18 @@ jobs:
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
@@ -776,8 +755,8 @@ jobs:
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 GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_API_KEY --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 /usr/local/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 --add-dir /tmp/gh-aw/cache-memory/ --allow-all-paths --add-dir "${GITHUB_WORKSPACE}" --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log
+ 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 GITHUB_MCP_SERVER_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-all-tools --add-dir /tmp/gh-aw/cache-memory/ --allow-all-paths --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
@@ -791,7 +770,7 @@ jobs:
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.85.4
+ GH_AW_VERSION: v0.86.2
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
GITHUB_COPILOT_INTEGRATION_ID: agentic-workflows
@@ -997,7 +976,7 @@ jobs:
steps:
- name: Setup Scripts
id: setup
- uses: github/gh-aw-actions/setup@2709137ea6c5b0e19aa621454dc643ea8dc526b1 # v0.85.4
+ uses: github/gh-aw-actions/setup@6aab9e5b5c91c615506061f09bedd81a23babe3c # v0.86.2
with:
destination: ${{ runner.temp }}/gh-aw/actions
job-name: ${{ github.job }}
@@ -1006,7 +985,7 @@ jobs:
env:
GH_AW_SETUP_WORKFLOW_NAME: "13.3 Release Burndown Report"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/daily-repo-status.lock.yml@${{ github.ref }}
- GH_AW_INFO_VERSION: "1.0.78"
+ 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
@@ -1206,7 +1185,7 @@ jobs:
steps:
- name: Setup Scripts
id: setup
- uses: github/gh-aw-actions/setup@2709137ea6c5b0e19aa621454dc643ea8dc526b1 # v0.85.4
+ uses: github/gh-aw-actions/setup@6aab9e5b5c91c615506061f09bedd81a23babe3c # v0.86.2
with:
destination: ${{ runner.temp }}/gh-aw/actions
job-name: ${{ github.job }}
@@ -1215,7 +1194,7 @@ jobs:
env:
GH_AW_SETUP_WORKFLOW_NAME: "13.3 Release Burndown Report"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/daily-repo-status.lock.yml@${{ github.ref }}
- GH_AW_INFO_VERSION: "1.0.78"
+ 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
@@ -1267,25 +1246,7 @@ jobs:
- name: Prepare threat detection files
if: always() && steps.detection_guard.outputs.run_detection == 'true'
run: |
- mkdir -p /tmp/gh-aw/threat-detection/aw-prompts
- rm -f /tmp/gh-aw/agent_usage.json
- cp /tmp/gh-aw/aw-prompts/prompt.txt /tmp/gh-aw/threat-detection/aw-prompts/prompt.txt 2>/dev/null || true
- if [ ! -s /tmp/gh-aw/threat-detection/aw-prompts/prompt.txt ]; then
- echo "::warning::ERR_VALIDATION: Missing or empty detection context prompt at /tmp/gh-aw/threat-detection/aw-prompts/prompt.txt. Ensure the agent artifact includes /tmp/gh-aw/aw-prompts/prompt.txt. Detection will continue with fallback workflow context."
- fi
- cp /tmp/gh-aw/agent_output.json /tmp/gh-aw/threat-detection/agent_output.json 2>/dev/null || true
- for f in /tmp/gh-aw/aw-*.patch; do
- if [ -f "$f" ]; then
- cp "$f" /tmp/gh-aw/threat-detection/ 2>/dev/null || true
- fi
- done
- for f in /tmp/gh-aw/aw-*.bundle; do
- if [ -f "$f" ]; then
- cp "$f" /tmp/gh-aw/threat-detection/ 2>/dev/null || true
- fi
- done
- echo "Prepared threat detection files:"
- ls -la /tmp/gh-aw/threat-detection/ 2>/dev/null || true
+ 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
@@ -1305,18 +1266,20 @@ jobs:
run: |
mkdir -p /tmp/gh-aw/threat-detection
touch /tmp/gh-aw/threat-detection/detection.log
- rm -f /tmp/gh-aw/threat-detection/step-summary.md
- touch /tmp/gh-aw/threat-detection/step-summary.md
+ 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.85.4
+ 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
@@ -1332,6 +1295,18 @@ jobs:
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
@@ -1358,9 +1333,10 @@ jobs:
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 --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 /usr/local/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 --add-dir "${GITHUB_WORKSPACE}" --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' 2>&1 | tee -a /tmp/gh-aw/threat-detection/detection.log
+ 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 --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
@@ -1372,14 +1348,13 @@ jobs:
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_TIMEOUT_MINUTES: 20
- GH_AW_VERSION: v0.85.4
+ 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]
@@ -1388,6 +1363,23 @@ jobs:
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()
@@ -1473,15 +1465,20 @@ jobs:
create_discussion_errors: ${{ steps.process_safe_outputs.outputs.create_discussion_errors }}
created_issue_number: ${{ steps.process_safe_outputs.outputs.created_issue_number }}
created_issue_url: ${{ steps.process_safe_outputs.outputs.created_issue_url }}
+ 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@2709137ea6c5b0e19aa621454dc643ea8dc526b1 # v0.85.4
+ uses: github/gh-aw-actions/setup@6aab9e5b5c91c615506061f09bedd81a23babe3c # v0.86.2
with:
destination: ${{ runner.temp }}/gh-aw/actions
job-name: ${{ github.job }}
@@ -1490,7 +1487,7 @@ jobs:
env:
GH_AW_SETUP_WORKFLOW_NAME: "13.3 Release Burndown Report"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/daily-repo-status.lock.yml@${{ github.ref }}
- GH_AW_INFO_VERSION: "1.0.78"
+ 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
@@ -1558,7 +1555,7 @@ jobs:
steps:
- name: Setup Scripts
id: setup
- uses: github/gh-aw-actions/setup@2709137ea6c5b0e19aa621454dc643ea8dc526b1 # v0.85.4
+ uses: github/gh-aw-actions/setup@6aab9e5b5c91c615506061f09bedd81a23babe3c # v0.86.2
with:
destination: ${{ runner.temp }}/gh-aw/actions
job-name: ${{ github.job }}
@@ -1567,7 +1564,7 @@ jobs:
env:
GH_AW_SETUP_WORKFLOW_NAME: "13.3 Release Burndown Report"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/daily-repo-status.lock.yml@${{ github.ref }}
- GH_AW_INFO_VERSION: "1.0.78"
+ GH_AW_INFO_VERSION: "1.0.79"
GH_AW_INFO_AWF_VERSION: "v0.27.44"
GH_AW_INFO_ENGINE_ID: "copilot"
- name: Download cache-memory artifact (default)
diff --git a/.github/workflows/extension-changelog.lock.yml b/.github/workflows/extension-changelog.lock.yml
index 13120b573a3..a776fcfef71 100644
--- a/.github/workflows/extension-changelog.lock.yml
+++ b/.github/workflows/extension-changelog.lock.yml
@@ -1,6 +1,6 @@
-# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"00b41866a84336e24032b2ba011fbfb10196acc2a595a4413b872377cea24492","body_hash":"d1d30916ad32257baf6fd20c2ca97dcef138c4b94fb18a9b98f0538a4a6a41e6","compiler_version":"v0.85.4","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.78"}}
-# gh-aw-manifest: {"version":1,"secrets":["ASPIRE_BOT_APP_ID","ASPIRE_BOT_PRIVATE_KEY","COPILOT_GITHUB_TOKEN","GH_AW_CI_TRIGGER_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/checkout","sha":"3d3c42e5aac5ba805825da76410c181273ba90b1","version":"v7.0.1"},{"repo":"actions/create-github-app-token","sha":"bcd2ba49218906704ab6c1aa796996da409d3eb1","version":"v3.2.0"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"373c709c69115d41ff229c7e5df9f8788daa9553","version":"v9"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"820762786026740c76f36085b0efc47a31fe5020","version":"v7.0.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"2709137ea6c5b0e19aa621454dc643ea8dc526b1","version":"v0.85.4"}],"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.8","digest":"sha256:38bbea36cdb46a3c9d04d1db05e672966f5239b431a2022eb35881688e5721d8","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.4.8@sha256:38bbea36cdb46a3c9d04d1db05e672966f5239b431a2022eb35881688e5721d8"},{"image":"ghcr.io/github/gh-aw-node","digest":"sha256:0d9f1fb5fd6610c0ac1f5194a38e45a8a1e81f8a390d5142d8e4e6f26a4b3196","pinned_image":"ghcr.io/github/gh-aw-node@sha256:0d9f1fb5fd6610c0ac1f5194a38e45a8a1e81f8a390d5142d8e4e6f26a4b3196"},{"image":"ghcr.io/github/github-mcp-server:v1.8.0","digest":"sha256:d5a18c04b92714c309eb46a2305087e91a4dbd80420f6e462656699f95093520","pinned_image":"ghcr.io/github/github-mcp-server:v1.8.0@sha256:d5a18c04b92714c309eb46a2305087e91a4dbd80420f6e462656699f95093520"}],"has_pull_request":true}
-# This file was automatically generated by gh-aw (v0.85.4). DO NOT EDIT. To debug this workflow, load the skill at https://github.com/github/gh-aw/blob/main/debug.md
+# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"30af2e1cbb577dc33f216092e83b27456f3a110ba3e668ca328826f13238a18e","body_hash":"2154bfa969f45e7df0b83b79adea2a74f0fcdf6fff84c848e012b8c32551d65d","compiler_version":"v0.86.2","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.79"}}
+# gh-aw-manifest: {"version":1,"secrets":["ASPIRE_BOT_APP_ID","ASPIRE_BOT_PRIVATE_KEY","GH_AW_CI_TRIGGER_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/checkout","sha":"3d3c42e5aac5ba805825da76410c181273ba90b1","version":"v7.0.1"},{"repo":"actions/create-github-app-token","sha":"bcd2ba49218906704ab6c1aa796996da409d3eb1","version":"v3.2.0"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"373c709c69115d41ff229c7e5df9f8788daa9553","version":"v9"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"820762786026740c76f36085b0efc47a31fe5020","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"},{"image":"ghcr.io/github/github-mcp-server:v1.9.0","digest":"sha256:881b53d6f75f69bdbc1b5b10fc2f1361717c19054143b3a8529fb5c32061a50e","pinned_image":"ghcr.io/github/github-mcp-server:v1.9.0@sha256:881b53d6f75f69bdbc1b5b10fc2f1361717c19054143b3a8529fb5c32061a50e"}],"has_pull_request":true}
+# 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
#
# ___ _ _
# / _ \ | | (_)
@@ -38,7 +38,6 @@
# Secrets used:
# - ASPIRE_BOT_APP_ID
# - ASPIRE_BOT_PRIVATE_KEY
-# - COPILOT_GITHUB_TOKEN
# - GH_AW_CI_TRIGGER_TOKEN
# - GH_AW_GITHUB_MCP_SERVER_TOKEN
# - GH_AW_GITHUB_TOKEN
@@ -52,15 +51,15 @@
# - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
# - actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
# - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
-# - github/gh-aw-actions/setup@2709137ea6c5b0e19aa621454dc643ea8dc526b1 # v0.85.4
+# - 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.8@sha256:38bbea36cdb46a3c9d04d1db05e672966f5239b431a2022eb35881688e5721d8
+# - ghcr.io/github/gh-aw-mcpg:v0.4.9@sha256:e5a1569aeaf41820fa7bdee3e94468cae448133cdbf00119ad24f5b74db1ab9f
# - ghcr.io/github/gh-aw-node@sha256:0d9f1fb5fd6610c0ac1f5194a38e45a8a1e81f8a390d5142d8e4e6f26a4b3196
-# - ghcr.io/github/github-mcp-server:v1.8.0@sha256:d5a18c04b92714c309eb46a2305087e91a4dbd80420f6e462656699f95093520
+# - ghcr.io/github/github-mcp-server:v1.9.0@sha256:881b53d6f75f69bdbc1b5b10fc2f1361717c19054143b3a8529fb5c32061a50e
name: "Generate the VS Code extension changelog for a release PR"
on:
@@ -109,7 +108,7 @@ jobs:
steps:
- name: Setup Scripts
id: setup
- uses: github/gh-aw-actions/setup@2709137ea6c5b0e19aa621454dc643ea8dc526b1 # v0.85.4
+ uses: github/gh-aw-actions/setup@6aab9e5b5c91c615506061f09bedd81a23babe3c # v0.86.2
with:
destination: ${{ runner.temp }}/gh-aw/actions
job-name: ${{ github.job }}
@@ -118,7 +117,7 @@ jobs:
env:
GH_AW_SETUP_WORKFLOW_NAME: "Generate the VS Code extension changelog for a release PR"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/extension-changelog.lock.yml@${{ github.ref }}
- GH_AW_INFO_VERSION: "1.0.78"
+ 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
@@ -127,9 +126,9 @@ jobs:
GH_AW_INFO_ENGINE_ID: "copilot"
GH_AW_INFO_ENGINE_NAME: "GitHub Copilot CLI"
GH_AW_INFO_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || vars.GH_AW_DEFAULT_MODEL_COPILOT || 'auto' }}
- GH_AW_INFO_VERSION: "1.0.78"
- GH_AW_INFO_AGENT_VERSION: "1.0.78"
- GH_AW_INFO_CLI_VERSION: "v0.85.4"
+ 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: "Generate the VS Code extension changelog for a release PR"
GH_AW_INFO_EXPERIMENTAL: "false"
GH_AW_INFO_SUPPORTS_TOOLS_ALLOWLIST: "true"
@@ -139,6 +138,7 @@ jobs:
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_COMPILED_STRICT: "true"
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
@@ -151,7 +151,6 @@ jobs:
id: check-oauth-tokens
run: bash "${RUNNER_TEMP}/gh-aw/actions/check_oauth_tokens.sh"
env:
- COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
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
@@ -171,12 +170,12 @@ jobs:
env:
GH_AW_AGENT_FOLDERS: ".agents .github"
GH_AW_AGENT_FILES: "AGENTS.md"
- # poutine:ignore untrusted_checkout_exec
- run: bash "${RUNNER_TEMP}/gh-aw/actions/save_base_github_folders.sh"
+ run: |
+ bash "${RUNNER_TEMP}/gh-aw/actions/save_base_github_folders.sh"
- name: Check compile-agentic version
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
- GH_AW_COMPILED_VERSION: "v0.85.4"
+ GH_AW_COMPILED_VERSION: "v0.86.2"
with:
script: |
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
@@ -199,9 +198,12 @@ jobs:
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_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ 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\"},{\"file\":\"safe_outputs_push_to_pr_branch.md\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0002\"},{\"file\":\"mcp_cli_tools_prompt.md\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0003\"},{\"file\":\"github_mcp_tools_with_safeoutputs_prompt.md\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0004\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0005\"}]}"
GH_AW_EXPR_1A3A194A: ${{ github.event.discussion.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'discussion' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }}
GH_AW_EXPR_463A214A: ${{ github.event.pull_request.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'pull_request' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }}
GH_AW_EXPR_802A9F6A: ${{ github.event.issue.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'issue' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }}
@@ -212,66 +214,22 @@ jobs:
GH_AW_GITHUB_REPOSITORY: ${{ github.repository }}
GH_AW_GITHUB_RUN_ID: ${{ github.run_id }}
GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }}
- # poutine:ignore untrusted_checkout_exec
- run: |
- bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh"
- {
- cat << 'GH_AW_PROMPT_b61177b961ebf0ea_EOF'
-
- GH_AW_PROMPT_b61177b961ebf0ea_EOF
- cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md"
- cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md"
- cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md"
- cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md"
- cat << 'GH_AW_PROMPT_b61177b961ebf0ea_EOF'
-
- Tools: push_to_pull_request_branch, missing_tool, missing_data, noop
- GH_AW_PROMPT_b61177b961ebf0ea_EOF
- cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_push_to_pr_branch.md"
- cat << 'GH_AW_PROMPT_b61177b961ebf0ea_EOF'
-
- GH_AW_PROMPT_b61177b961ebf0ea_EOF
- cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md"
- cat << 'GH_AW_PROMPT_b61177b961ebf0ea_EOF'
-
- The following GitHub context information is available for this workflow:
- {{#if github.actor}}
- - **actor**: __GH_AW_GITHUB_ACTOR__
- {{/if}}
- {{#if github.repository}}
- - **repository**: __GH_AW_GITHUB_REPOSITORY__
- {{/if}}
- {{#if github.workspace}}
- - **workspace**: __GH_AW_GITHUB_WORKSPACE__
- {{/if}}
- {{#if github.event.issue.number || (github.aw.context.item_type == 'issue' && github.aw.context.item_number)}}
- - **issue-number**: #__GH_AW_EXPR_802A9F6A__
- {{/if}}
- {{#if github.event.discussion.number || (github.aw.context.item_type == 'discussion' && github.aw.context.item_number)}}
- - **discussion-number**: #__GH_AW_EXPR_1A3A194A__
- {{/if}}
- {{#if github.event.pull_request.number || (github.aw.context.item_type == 'pull_request' && github.aw.context.item_number)}}
- - **pull-request-number**: #__GH_AW_EXPR_463A214A__
- {{/if}}
- {{#if github.event.comment.id || github.aw.context.comment_id}}
- - **comment-id**: __GH_AW_EXPR_FF1D34CE__
- {{/if}}
- {{#if github.run_id}}
- - **workflow-run-id**: __GH_AW_GITHUB_RUN_ID__
- {{/if}}
-
-
- GH_AW_PROMPT_b61177b961ebf0ea_EOF
- cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md"
- cat << 'GH_AW_PROMPT_b61177b961ebf0ea_EOF'
-
- {{#runtime-import .github/workflows/extension-changelog.md}}
- GH_AW_PROMPT_b61177b961ebf0ea_EOF
- } > "$GH_AW_PROMPT"
+ GH_AW_PROMPT_CONTENT_0000: "\n"
+ GH_AW_PROMPT_CONTENT_0001: "\nTools: push_to_pull_request_branch, missing_tool, missing_data, noop\n"
+ GH_AW_PROMPT_CONTENT_0002: "\n"
+ GH_AW_PROMPT_CONTENT_0003: "\nThe following GitHub context information is available for this workflow:\n{{#if github.actor}}\n- **actor**: __GH_AW_GITHUB_ACTOR__\n{{/if}}\n{{#if github.repository}}\n- **repository**: __GH_AW_GITHUB_REPOSITORY__\n{{/if}}\n{{#if github.workspace}}\n- **workspace**: __GH_AW_GITHUB_WORKSPACE__\n{{/if}}\n{{#if github.event.issue.number || (github.aw.context.item_type == 'issue' && github.aw.context.item_number)}}\n- **issue-number**: #__GH_AW_EXPR_802A9F6A__\n{{/if}}\n{{#if github.event.discussion.number || (github.aw.context.item_type == 'discussion' && github.aw.context.item_number)}}\n- **discussion-number**: #__GH_AW_EXPR_1A3A194A__\n{{/if}}\n{{#if github.event.pull_request.number || (github.aw.context.item_type == 'pull_request' && github.aw.context.item_number)}}\n- **pull-request-number**: #__GH_AW_EXPR_463A214A__\n{{/if}}\n{{#if github.event.comment.id || github.aw.context.comment_id}}\n- **comment-id**: __GH_AW_EXPR_FF1D34CE__\n{{/if}}\n{{#if github.run_id}}\n- **workflow-run-id**: __GH_AW_GITHUB_RUN_ID__\n{{/if}}\n\n\n"
+ GH_AW_PROMPT_CONTENT_0004: "\n"
+ GH_AW_PROMPT_CONTENT_0005: "{{#runtime-import .github/workflows/extension-changelog.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: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_PROMPT: ${{ runner.temp }}/gh-aw/aw-prompts/prompt.txt
GH_AW_ENGINE_ID: "copilot"
GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }}
GH_AW_GITHUB_EVENT_NAME: ${{ github.event_name }}
@@ -284,7 +242,7 @@ jobs:
- name: Substitute placeholders
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
- GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_PROMPT: ${{ runner.temp }}/gh-aw/aw-prompts/prompt.txt
GH_AW_EXPR_1A3A194A: ${{ github.event.discussion.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'discussion' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }}
GH_AW_EXPR_463A214A: ${{ github.event.pull_request.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'pull_request' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }}
GH_AW_EXPR_802A9F6A: ${{ github.event.issue.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'issue' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }}
@@ -324,14 +282,18 @@ jobs:
});
- name: Validate prompt placeholders
env:
- GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
- # poutine:ignore untrusted_checkout_exec
- run: bash "${RUNNER_TEMP}/gh-aw/actions/validate_prompt_placeholders.sh"
+ 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: /tmp/gh-aw/aw-prompts/prompt.txt
- # poutine:ignore untrusted_checkout_exec
- run: bash "${RUNNER_TEMP}/gh-aw/actions/print_prompt_summary.sh"
+ 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
@@ -392,7 +354,7 @@ jobs:
steps:
- name: Setup Scripts
id: setup
- uses: github/gh-aw-actions/setup@2709137ea6c5b0e19aa621454dc643ea8dc526b1 # v0.85.4
+ uses: github/gh-aw-actions/setup@6aab9e5b5c91c615506061f09bedd81a23babe3c # v0.86.2
with:
destination: ${{ runner.temp }}/gh-aw/actions
job-name: ${{ github.job }}
@@ -401,7 +363,7 @@ jobs:
env:
GH_AW_SETUP_WORKFLOW_NAME: "Generate the VS Code extension changelog for a release PR"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/extension-changelog.lock.yml@${{ github.ref }}
- GH_AW_INFO_VERSION: "1.0.78"
+ 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
@@ -447,11 +409,13 @@ jobs:
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.85.4
+ 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: Generate GitHub App token
@@ -500,10 +464,10 @@ jobs:
GH_AW_SKILL_DIR: ".github/skills"
run: bash "${RUNNER_TEMP}/gh-aw/actions/restore_inline_skills.sh"
- name: Preload authoritative marker range for local changelog enumeration
- run: "set -euo pipefail\n\nCHANGELOG=extension/CHANGELOG.md\nif [ ! -f \"${CHANGELOG}\" ]; then\n echo \"No ${CHANGELOG} file in this checkout; skipping authoritative range preload.\"\n exit 0\nfi\n\nmapfile -t MARKERS < <(grep '$'\nif [[ ! \"${MARKER_LINE}\" =~ ${MARKER_REGEX} ]]; then\n echo \"::error::Could not parse authoritative marker: ${MARKER_LINE}\"\n exit 1\nfi\n\nFROM_SHA=\"${BASH_REMATCH[1]}\"\nTO_SHA=\"${BASH_REMATCH[2]}\"\nCURRENT_BRANCH=\"$(git branch --show-current)\"\nif [ -z \"${CURRENT_BRANCH}\" ]; then\n echo \"::error::Could not determine the checked-out PR branch for authoritative range preload.\"\n exit 1\nfi\n\nrange_is_available() {\n git cat-file -e \"${FROM_SHA}^{commit}\" 2>/dev/null \\\n && git cat-file -e \"${TO_SHA}^{commit}\" 2>/dev/null \\\n && git merge-base --is-ancestor \"${FROM_SHA}\" \"${TO_SHA}\" 2>/dev/null \\\n && git log --format='%H%x09%s' --no-merges \"${FROM_SHA}..${TO_SHA}\" -- extension/ >/dev/null 2>&1\n}\n\nif range_is_available; then\n echo \"Authoritative marker range ${FROM_SHA}..${TO_SHA} is already locally enumerable.\"\n exit 0\nfi\n\nDEEPEN_BY=128\nATTEMPT=0\nwhile [ \"$(git rev-parse --is-shallow-repository)\" = \"true\" ]; do\n ATTEMPT=$((ATTEMPT + 1))\n if [ \"${ATTEMPT}\" -le 6 ]; then\n echo \"Deepening ${CURRENT_BRANCH} by ${DEEPEN_BY} commits to preload ${FROM_SHA}..${TO_SHA}.\"\n git fetch --no-tags --deepen=\"${DEEPEN_BY}\" origin \"${CURRENT_BRANCH}\"\n DEEPEN_BY=$((DEEPEN_BY * 2))\n else\n echo \"Unshallowing ${CURRENT_BRANCH} to preload ${FROM_SHA}..${TO_SHA}.\"\n git fetch --no-tags --unshallow origin \"${CURRENT_BRANCH}\"\n fi\n\n if range_is_available; then\n echo \"Preloaded authoritative marker range ${FROM_SHA}..${TO_SHA} for local changelog enumeration.\"\n exit 0\n fi\ndone\n\nif range_is_available; then\n echo \"Preloaded authoritative marker range ${FROM_SHA}..${TO_SHA} for local changelog enumeration.\"\n exit 0\nfi\n\necho \"::error::Failed to preload authoritative marker range ${FROM_SHA}..${TO_SHA} for local changelog enumeration.\"\nexit 1"
+ run: "set -euo pipefail\n\nCHANGELOG=extension/CHANGELOG.md\nif [ ! -f \"${CHANGELOG}\" ]; then\n echo \"No ${CHANGELOG} file in this checkout; skipping authoritative range preload.\"\n exit 0\nfi\n\nmapfile -t MARKERS < <(grep '$'\nif [[ ! \"${MARKER_LINE}\" =~ ${MARKER_REGEX} ]]; then\n echo \"::error::Could not parse authoritative marker: ${MARKER_LINE}\"\n exit 1\nfi\n\nFROM_SHA=\"${BASH_REMATCH[1]}\"\nTO_SHA=\"${BASH_REMATCH[2]}\"\nCANDIDATES_FILE=\"${RUNNER_TEMP}/gh-aw/extension-changelog-candidates.tsv\"\nmkdir -p \"${RUNNER_TEMP}/gh-aw\"\nrm -f \"${CANDIDATES_FILE}\"\nCURRENT_BRANCH=\"$(git branch --show-current)\"\nif [ -z \"${CURRENT_BRANCH}\" ]; then\n echo \"::error::Could not determine the checked-out PR branch for authoritative range preload.\"\n exit 1\nfi\n\nmaterialize_candidate_set() {\n if ! git cat-file -e \"${FROM_SHA}^{commit}\" 2>/dev/null \\\n || ! git cat-file -e \"${TO_SHA}^{commit}\" 2>/dev/null \\\n || ! git merge-base --is-ancestor \"${FROM_SHA}\" \"${TO_SHA}\" 2>/dev/null; then\n return 1\n fi\n\n if ! git log --format='%H%x09%s' --no-merges \\\n \"${FROM_SHA}..${TO_SHA}\" -- extension/ > \"${CANDIDATES_FILE}\"; then\n rm -f \"${CANDIDATES_FILE}\"\n return 1\n fi\n\n local candidate_count\n candidate_count=\"$(wc -l < \"${CANDIDATES_FILE}\")\"\n echo \"Materialized ${candidate_count} authoritative extension changelog candidates in ${CANDIDATES_FILE}.\"\n}\n\nif materialize_candidate_set; then\n echo \"Authoritative marker range ${FROM_SHA}..${TO_SHA} is already locally enumerable.\"\n exit 0\nfi\n\nDEEPEN_BY=128\nATTEMPT=0\nwhile [ \"$(git rev-parse --is-shallow-repository)\" = \"true\" ]; do\n ATTEMPT=$((ATTEMPT + 1))\n if [ \"${ATTEMPT}\" -le 6 ]; then\n echo \"Deepening ${CURRENT_BRANCH} by ${DEEPEN_BY} commits to preload ${FROM_SHA}..${TO_SHA}.\"\n git fetch --no-tags --deepen=\"${DEEPEN_BY}\" origin \"${CURRENT_BRANCH}\"\n DEEPEN_BY=$((DEEPEN_BY * 2))\n else\n echo \"Unshallowing ${CURRENT_BRANCH} to preload ${FROM_SHA}..${TO_SHA}.\"\n git fetch --no-tags --unshallow origin \"${CURRENT_BRANCH}\"\n fi\n\n if materialize_candidate_set; then\n echo \"Preloaded authoritative marker range ${FROM_SHA}..${TO_SHA} for local changelog enumeration.\"\n exit 0\n fi\ndone\n\nif materialize_candidate_set; then\n echo \"Preloaded authoritative marker range ${FROM_SHA}..${TO_SHA} for local changelog enumeration.\"\n exit 0\nfi\n\necho \"::error::Failed to preload authoritative marker range ${FROM_SHA}..${TO_SHA} for local changelog enumeration.\"\nexit 1"
- 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.8@sha256:38bbea36cdb46a3c9d04d1db05e672966f5239b431a2022eb35881688e5721d8 ghcr.io/github/gh-aw-node@sha256:0d9f1fb5fd6610c0ac1f5194a38e45a8a1e81f8a390d5142d8e4e6f26a4b3196 ghcr.io/github/github-mcp-server:v1.8.0@sha256:d5a18c04b92714c309eb46a2305087e91a4dbd80420f6e462656699f95093520
+ 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 ghcr.io/github/github-mcp-server:v1.9.0@sha256:881b53d6f75f69bdbc1b5b10fc2f1361717c19054143b3a8529fb5c32061a50e
- name: Generate Safe Outputs Config
run: |
mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs"
@@ -597,6 +561,10 @@ jobs:
},
"pull_request_number": {
"issueOrPRNumber": true
+ },
+ "repo": {
+ "type": "string",
+ "maxLength": 256
}
}
},
@@ -648,22 +616,23 @@ jobs:
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"
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 -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.8'
+ 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_c3984b671fa9f53f_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs"
+ cat << GH_AW_MCP_CONFIG_5614418005a60134_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs"
{
"mcpServers": {
"github": {
"type": "stdio",
- "container": "ghcr.io/github/github-mcp-server:v1.8.0",
+ "container": "ghcr.io/github/github-mcp-server:v1.9.0",
"env": {
"GITHUB_FEATURES": "fields_param",
"GITHUB_HOST": "${GITHUB_SERVER_URL}",
@@ -725,7 +694,7 @@ jobs:
"startupTimeout": 120
}
}
- GH_AW_MCP_CONFIG_c3984b671fa9f53f_EOF
+ GH_AW_MCP_CONFIG_5614418005a60134_EOF
- name: Mount MCP servers as CLIs
id: mount-mcp-clis
continue-on-error: true
@@ -750,6 +719,32 @@ jobs:
- name: Execute GitHub Copilot CLI
id: agentic_execution
# Copilot CLI tool arguments (sorted):
+ # --allow-tool github
+ # --allow-tool safeoutputs
+ # --allow-tool shell(cat)
+ # --allow-tool shell(date)
+ # --allow-tool shell(echo)
+ # --allow-tool shell(git add:*)
+ # --allow-tool shell(git branch:*)
+ # --allow-tool shell(git checkout:*)
+ # --allow-tool shell(git commit:*)
+ # --allow-tool shell(git merge:*)
+ # --allow-tool shell(git rm:*)
+ # --allow-tool shell(git status)
+ # --allow-tool shell(git switch:*)
+ # --allow-tool shell(github:*)
+ # --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(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
@@ -759,6 +754,18 @@ jobs:
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
@@ -783,8 +790,8 @@ jobs:
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 GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_API_KEY --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 /usr/local/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 --allow-all-paths --add-dir "${GITHUB_WORKSPACE}" --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log
+ 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 GITHUB_MCP_SERVER_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 github --allow-tool safeoutputs --allow-tool '\''shell(cat)'\'' --allow-tool '\''shell(date)'\'' --allow-tool '\''shell(echo)'\'' --allow-tool '\''shell(git add:*)'\'' --allow-tool '\''shell(git branch:*)'\'' --allow-tool '\''shell(git checkout:*)'\'' --allow-tool '\''shell(git commit:*)'\'' --allow-tool '\''shell(git merge:*)'\'' --allow-tool '\''shell(git rm:*)'\'' --allow-tool '\''shell(git status)'\'' --allow-tool '\''shell(git switch:*)'\'' --allow-tool '\''shell(github:*)'\'' --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(sort)'\'' --allow-tool '\''shell(tail)'\'' --allow-tool '\''shell(uniq)'\'' --allow-tool '\''shell(wc)'\'' --allow-tool '\''shell(yq)'\'' --allow-tool write --allow-all-paths --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
@@ -798,7 +805,7 @@ jobs:
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.85.4
+ GH_AW_VERSION: v0.86.2
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
GITHUB_COPILOT_INTEGRATION_ID: agentic-workflows
@@ -991,7 +998,7 @@ jobs:
steps:
- name: Setup Scripts
id: setup
- uses: github/gh-aw-actions/setup@2709137ea6c5b0e19aa621454dc643ea8dc526b1 # v0.85.4
+ uses: github/gh-aw-actions/setup@6aab9e5b5c91c615506061f09bedd81a23babe3c # v0.86.2
with:
destination: ${{ runner.temp }}/gh-aw/actions
job-name: ${{ github.job }}
@@ -1000,7 +1007,7 @@ jobs:
env:
GH_AW_SETUP_WORKFLOW_NAME: "Generate the VS Code extension changelog for a release PR"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/extension-changelog.lock.yml@${{ github.ref }}
- GH_AW_INFO_VERSION: "1.0.78"
+ GH_AW_INFO_VERSION: "1.0.79"
GH_AW_INFO_AWF_VERSION: "v0.27.44"
GH_AW_INFO_ENGINE_ID: "copilot"
- name: Generate GitHub App token
@@ -1213,7 +1220,7 @@ jobs:
steps:
- name: Setup Scripts
id: setup
- uses: github/gh-aw-actions/setup@2709137ea6c5b0e19aa621454dc643ea8dc526b1 # v0.85.4
+ uses: github/gh-aw-actions/setup@6aab9e5b5c91c615506061f09bedd81a23babe3c # v0.86.2
with:
destination: ${{ runner.temp }}/gh-aw/actions
job-name: ${{ github.job }}
@@ -1222,7 +1229,7 @@ jobs:
env:
GH_AW_SETUP_WORKFLOW_NAME: "Generate the VS Code extension changelog for a release PR"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/extension-changelog.lock.yml@${{ github.ref }}
- GH_AW_INFO_VERSION: "1.0.78"
+ 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
@@ -1274,25 +1281,7 @@ jobs:
- name: Prepare threat detection files
if: always() && steps.detection_guard.outputs.run_detection == 'true'
run: |
- mkdir -p /tmp/gh-aw/threat-detection/aw-prompts
- rm -f /tmp/gh-aw/agent_usage.json
- cp /tmp/gh-aw/aw-prompts/prompt.txt /tmp/gh-aw/threat-detection/aw-prompts/prompt.txt 2>/dev/null || true
- if [ ! -s /tmp/gh-aw/threat-detection/aw-prompts/prompt.txt ]; then
- echo "::warning::ERR_VALIDATION: Missing or empty detection context prompt at /tmp/gh-aw/threat-detection/aw-prompts/prompt.txt. Ensure the agent artifact includes /tmp/gh-aw/aw-prompts/prompt.txt. Detection will continue with fallback workflow context."
- fi
- cp /tmp/gh-aw/agent_output.json /tmp/gh-aw/threat-detection/agent_output.json 2>/dev/null || true
- for f in /tmp/gh-aw/aw-*.patch; do
- if [ -f "$f" ]; then
- cp "$f" /tmp/gh-aw/threat-detection/ 2>/dev/null || true
- fi
- done
- for f in /tmp/gh-aw/aw-*.bundle; do
- if [ -f "$f" ]; then
- cp "$f" /tmp/gh-aw/threat-detection/ 2>/dev/null || true
- fi
- done
- echo "Prepared threat detection files:"
- ls -la /tmp/gh-aw/threat-detection/ 2>/dev/null || true
+ 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
@@ -1312,18 +1301,20 @@ jobs:
run: |
mkdir -p /tmp/gh-aw/threat-detection
touch /tmp/gh-aw/threat-detection/detection.log
- rm -f /tmp/gh-aw/threat-detection/step-summary.md
- touch /tmp/gh-aw/threat-detection/step-summary.md
+ 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.85.4
+ 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
@@ -1339,6 +1330,18 @@ jobs:
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
@@ -1365,9 +1368,10 @@ jobs:
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 --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 /usr/local/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 --add-dir "${GITHUB_WORKSPACE}" --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' 2>&1 | tee -a /tmp/gh-aw/threat-detection/detection.log
+ 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 --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
@@ -1379,14 +1383,13 @@ jobs:
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_TIMEOUT_MINUTES: 20
- GH_AW_VERSION: v0.85.4
+ 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]
@@ -1395,6 +1398,23 @@ jobs:
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()
@@ -1466,14 +1486,14 @@ jobs:
steps:
- name: Setup Scripts
id: setup
- uses: github/gh-aw-actions/setup@2709137ea6c5b0e19aa621454dc643ea8dc526b1 # v0.85.4
+ 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: "Generate the VS Code extension changelog for a release PR"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/extension-changelog.lock.yml@${{ github.ref }}
- GH_AW_INFO_VERSION: "1.0.78"
+ GH_AW_INFO_VERSION: "1.0.79"
GH_AW_INFO_AWF_VERSION: "v0.27.44"
GH_AW_INFO_ENGINE_ID: "copilot"
- name: Check team membership for workflow
@@ -1524,8 +1544,13 @@ jobs:
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 }}
@@ -1534,7 +1559,7 @@ jobs:
steps:
- name: Setup Scripts
id: setup
- uses: github/gh-aw-actions/setup@2709137ea6c5b0e19aa621454dc643ea8dc526b1 # v0.85.4
+ uses: github/gh-aw-actions/setup@6aab9e5b5c91c615506061f09bedd81a23babe3c # v0.86.2
with:
destination: ${{ runner.temp }}/gh-aw/actions
job-name: ${{ github.job }}
@@ -1543,7 +1568,7 @@ jobs:
env:
GH_AW_SETUP_WORKFLOW_NAME: "Generate the VS Code extension changelog for a release PR"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/extension-changelog.lock.yml@${{ github.ref }}
- GH_AW_INFO_VERSION: "1.0.78"
+ 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
diff --git a/.github/workflows/extension-changelog.md b/.github/workflows/extension-changelog.md
index aeaef29043e..b6c3cecac30 100644
--- a/.github/workflows/extension-changelog.md
+++ b/.github/workflows/extension-changelog.md
@@ -118,6 +118,10 @@ safe-outputs:
repositories: ["aspire"]
tools:
+ # Shell access is explicit because the unfiltered GitHub integrity setting
+ # requires an intentional allowlist. The agent reads the candidate set
+ # materialized by the trusted pre-agent step and inspects the changelog.
+ bash: ["cat", "grep", "head", "tail", "wc"]
github:
# `repos` exposes the commit-comparison and file-content APIs used to gather
# the extension change set. `pull_requests` and `search` enrich commits with
@@ -171,20 +175,34 @@ pre-agent-steps:
FROM_SHA="${BASH_REMATCH[1]}"
TO_SHA="${BASH_REMATCH[2]}"
+ CANDIDATES_FILE="${RUNNER_TEMP}/gh-aw/extension-changelog-candidates.tsv"
+ mkdir -p "${RUNNER_TEMP}/gh-aw"
+ rm -f "${CANDIDATES_FILE}"
CURRENT_BRANCH="$(git branch --show-current)"
if [ -z "${CURRENT_BRANCH}" ]; then
echo "::error::Could not determine the checked-out PR branch for authoritative range preload."
exit 1
fi
- range_is_available() {
- git cat-file -e "${FROM_SHA}^{commit}" 2>/dev/null \
- && git cat-file -e "${TO_SHA}^{commit}" 2>/dev/null \
- && git merge-base --is-ancestor "${FROM_SHA}" "${TO_SHA}" 2>/dev/null \
- && git log --format='%H%x09%s' --no-merges "${FROM_SHA}..${TO_SHA}" -- extension/ >/dev/null 2>&1
+ materialize_candidate_set() {
+ if ! git cat-file -e "${FROM_SHA}^{commit}" 2>/dev/null \
+ || ! git cat-file -e "${TO_SHA}^{commit}" 2>/dev/null \
+ || ! git merge-base --is-ancestor "${FROM_SHA}" "${TO_SHA}" 2>/dev/null; then
+ return 1
+ fi
+
+ if ! git log --format='%H%x09%s' --no-merges \
+ "${FROM_SHA}..${TO_SHA}" -- extension/ > "${CANDIDATES_FILE}"; then
+ rm -f "${CANDIDATES_FILE}"
+ return 1
+ fi
+
+ local candidate_count
+ candidate_count="$(wc -l < "${CANDIDATES_FILE}")"
+ echo "Materialized ${candidate_count} authoritative extension changelog candidates in ${CANDIDATES_FILE}."
}
- if range_is_available; then
+ if materialize_candidate_set; then
echo "Authoritative marker range ${FROM_SHA}..${TO_SHA} is already locally enumerable."
exit 0
fi
@@ -202,13 +220,13 @@ pre-agent-steps:
git fetch --no-tags --unshallow origin "${CURRENT_BRANCH}"
fi
- if range_is_available; then
+ if materialize_candidate_set; then
echo "Preloaded authoritative marker range ${FROM_SHA}..${TO_SHA} for local changelog enumeration."
exit 0
fi
done
- if range_is_available; then
+ if materialize_candidate_set; then
echo "Preloaded authoritative marker range ${FROM_SHA}..${TO_SHA} for local changelog enumeration."
exit 0
fi
@@ -314,18 +332,19 @@ The PR body, description, and deterministic fallback notes are presentation-only
and MUST NOT be used to discover the change set. The validated marker range is
the only authoritative source.
-A deterministic pre-agent step already preloaded the authoritative marker range
-and history into this checkout. Do not perform any network fetch in the agent
-step. If the local range is missing or cannot be enumerated, treat that as a
-workflow error and fail with a diagnostic instead of trying to repair it here.
+A deterministic pre-agent step already validated and materialized the
+authoritative marker range as
+`${RUNNER_TEMP}/gh-aw/extension-changelog-candidates.tsv`. Do not run `git` or
+perform any network fetch in the agent step. If the candidate file cannot be
+read, treat that as a workflow error and fail with a diagnostic instead of
+trying to repair it here.
-Use local git as the authoritative source for the exact candidate set:
+Treat that file as the authoritative source for the exact candidate set:
-1. Run `git log --format='%H%x09%s' --no-merges .. -- extension/`
- locally and treat the full output of that command as the exact candidate set.
-2. Count the candidates produced by that command and keep that count in mind
- while you work.
-3. Consider and classify **every** candidate from that full local set before you
+1. Read every line in the file. Each line contains the 40-character commit SHA,
+ a tab, and its first-line subject.
+2. Count every line and keep that exact candidate count in mind while you work.
+3. Consider and classify **every** candidate from that full set before you
write notes. You may group related user-facing commits into one final note
and exclude internal-only commits, but you MUST NOT stop after a fixed number
of commits and MUST NOT use only the newest page, partial list, PR body, or
@@ -404,7 +423,7 @@ editing `extension/CHANGELOG.md`, emit a single push request as your final
output so gh-aw commits the change to the triggering PR's head branch with a
clear commit message (for example
`Generate extension changelog for v`). Do not include any other file in
-the change. Then write a short success line to the run summary. The summary must be auditable: report the exact candidate count from Step 4, how many candidates were included in the final notes and how many were excluded, and ensure the included/excluded totals (or equivalent auditable classification totals) account for every candidate from the local git range:
+the change. Then write a short success line to the run summary. The summary must be auditable: report the exact candidate count from Step 4, how many candidates were included in the final notes and how many were excluded, and ensure the included/excluded totals (or equivalent auditable classification totals) account for every candidate from the pre-agent candidate file:
> Replaced the placeholder `extension/CHANGELOG.md` entry for **v``**
> on PR #`${{ github.event.pull_request.number }}`. Range: ``..``.
@@ -431,9 +450,9 @@ no-op when no request is emitted.
- More than one marker present (Step 2).
- Malformed `from`/`to` SHAs, or SHAs that don't resolve in `microsoft/aspire`
(Step 3).
-- The local git range still cannot be enumerated after the pre-agent history
- preload, or required enrichment searches fail outright so you cannot produce
- notes.
+- The authoritative candidate file is missing or unreadable after pre-agent
+ materialization, or required enrichment searches fail outright so you cannot
+ produce notes.
For these, exit non-zero so the run shows a red X, and write the failing API,
the marker contents, and the error to the run summary so a maintainer can
diff --git a/.github/workflows/extension-e2e-tests.yml b/.github/workflows/extension-e2e-tests.yml
index 5558d3d4ada..01bbfa89645 100644
--- a/.github/workflows/extension-e2e-tests.yml
+++ b/.github/workflows/extension-e2e-tests.yml
@@ -75,7 +75,9 @@ jobs:
name: VS Code extension E2E (${{ matrix.name }}, ${{ matrix.shardName }})
needs: verify_extester_feed
runs-on: ${{ matrix.runner }}
- timeout-minutes: 75
+ # The Java AppHost shard imports a multi-project Gradle build and then runs the whole
+ # application under a debugger, so it needs more than the shared budget.
+ timeout-minutes: ${{ matrix.timeoutMinutes || 75 }}
env:
NPM_REGISTRY: https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/
COREPACK_ENABLE_DOWNLOAD_PROMPT: 0
@@ -132,6 +134,22 @@ jobs:
archivePattern: aspire-cli-win-x64*.zip
cliBinary: aspire.exe
useXvfb: false
+ - name: Linux
+ shardName: dynamic-debug-configuration
+ spec: out/test-e2e/test-e2e/dynamicDebugConfiguration.e2e.test.js
+ runner: ubuntu-latest
+ rid: linux-x64
+ archivePattern: aspire-cli-linux-x64*.tar.gz
+ cliBinary: aspire
+ useXvfb: true
+ - name: Windows
+ shardName: dynamic-debug-configuration
+ spec: out/test-e2e/test-e2e/dynamicDebugConfiguration.e2e.test.js
+ runner: windows-latest
+ rid: win-x64
+ archivePattern: aspire-cli-win-x64*.zip
+ cliBinary: aspire.exe
+ useXvfb: false
- name: Linux
shardName: apphost-tree
advisoryIssue: https://github.com/microsoft/aspire/issues/19282
@@ -248,6 +266,68 @@ jobs:
archivePattern: aspire-cli-win-x64*.zip
cliBinary: aspire.exe
useXvfb: false
+ - name: Linux
+ shardName: java-apphost
+ spec: out/test-e2e/test-e2e/javaAppHost.e2e.test.js
+ runner: ubuntu-latest
+ rid: linux-x64
+ archivePattern: aspire-cli-linux-x64*.tar.gz
+ cliBinary: aspire
+ useXvfb: true
+ installJava: true
+ timeoutMinutes: 110
+ - name: Linux
+ shardName: java-apphost-debug-startup-timeout
+ spec: out/test-e2e/test-e2e/javaAppHostDebugStartupTimeout.e2e.test.js
+ runner: ubuntu-latest
+ rid: linux-x64
+ archivePattern: aspire-cli-linux-x64*.tar.gz
+ cliBinary: aspire
+ useXvfb: true
+ installJava: true
+ timeoutMinutes: 110
+ unsetCliStartTimeout: true
+ - name: Linux
+ shardName: java-codelens
+ spec: out/test-e2e/test-e2e/javaCodeLens.e2e.test.js
+ runner: ubuntu-latest
+ rid: linux-x64
+ archivePattern: aspire-cli-linux-x64*.tar.gz
+ cliBinary: aspire
+ useXvfb: true
+ installJava: true
+ - name: Linux
+ shardName: workspace-target-proof
+ spec: out/test-e2e/test-e2e/workspaceTargetProof.e2e.test.js
+ runner: ubuntu-latest
+ rid: linux-x64
+ archivePattern: aspire-cli-linux-x64*.tar.gz
+ cliBinary: aspire
+ useXvfb: true
+ - name: Linux
+ shardName: cli-path-resolution
+ spec: out/test-e2e/test-e2e/cliPathResolution.e2e.test.js
+ runner: ubuntu-latest
+ rid: linux-x64
+ archivePattern: aspire-cli-linux-x64*.tar.gz
+ cliBinary: aspire
+ useXvfb: true
+ - name: Linux
+ shardName: cli-path-rejection
+ spec: out/test-e2e/test-e2e/cliPathRejectionNotification.e2e.test.js
+ runner: ubuntu-latest
+ rid: linux-x64
+ archivePattern: aspire-cli-linux-x64*.tar.gz
+ cliBinary: aspire
+ useXvfb: true
+ - name: Windows
+ shardName: cli-path-rejection
+ spec: out/test-e2e/test-e2e/cliPathRejectionNotification.e2e.test.js
+ runner: windows-latest
+ rid: win-x64
+ archivePattern: aspire-cli-win-x64*.zip
+ cliBinary: aspire.exe
+ useXvfb: false
- name: Linux
shardName: edge-cases
spec: out/test-e2e/test-e2e/edgeCases.e2e.test.js
@@ -434,6 +514,137 @@ jobs:
echo 'FUNCTIONS_CORE_TOOLS_TELEMETRY_OPTOUT=1'
} >> "$GITHUB_ENV"
+ - name: Set up the JDK for the Java E2E specs
+ if: ${{ matrix.installJava }}
+ uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5.7.0
+ with:
+ distribution: temurin
+ # The CLI compiles a scaffolded Java AppHost with `javac --release 25`, because the AppHost
+ # uses an instance main method in an implicitly declared class (JEP 512, finalized in 25).
+ # Hosted runner images ship 17 and 21, so neither the AppHost nor the playground's Gradle
+ # toolchain resolves without this.
+ java-version: '25'
+
+ - name: Cache Java dependencies for the Java E2E specs
+ if: ${{ matrix.installJava }}
+ uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
+ with:
+ # The Java specs launch real Spring Boot resources, so a cold runner otherwise downloads the
+ # whole Spring dependency tree inside the test's readiness budget. Cache the user-level Maven
+ # and Gradle stores rather than a per-project directory: the specs run out of a generated
+ # workspace copied from the playground, so only the shared caches survive the copy.
+ #
+ # `~/.m2/wrapper` holds the Maven distribution itself, which `mvnw` downloads from
+ # repo.maven.apache.org into `${MAVEN_USER_HOME}/wrapper/dists` because these projects pin
+ # `distributionType=only-script`. Without it cached, every run re-fetched Maven from Maven
+ # Central, so a single outage there failed the shard - the `~/.gradle/wrapper` entry below
+ # already gave Gradle the equivalent protection.
+ path: |
+ ~/.m2/repository
+ ~/.m2/wrapper
+ ~/.gradle/caches
+ ~/.gradle/wrapper
+ # `maven-wrapper.properties` participates in the key for the same reason
+ # `gradle-wrapper.properties` does: it carries the pinned `distributionUrl`, so the entry has
+ # to rotate when the Maven version changes. Otherwise the key would still hit exactly after a
+ # version bump, actions/cache would skip the save, and the newly downloaded distribution would
+ # never make it into the cache.
+ key: java-e2e-${{ runner.os }}-${{ hashFiles('playground/JavaSpringBoot/**/pom.xml', 'playground/JavaSpringBoot/**/build.gradle*', 'playground/JavaSpringBoot/**/gradle-wrapper.properties', 'playground/JavaSpringBoot/**/maven-wrapper.properties') }}
+ restore-keys: |
+ java-e2e-${{ runner.os }}-
+
+ - name: Warm the Java dependency caches
+ if: ${{ matrix.installJava }}
+ shell: bash
+ run: |
+ set -euo pipefail
+
+ # Resolving dependencies here rather than inside the specs keeps a cold cache from being
+ # charged against the in-test wait for a resource endpoint, which is what made these shards
+ # time out on cache misses. The AppHost project is deliberately excluded: it compiles against
+ # the Aspire Java SDK that the CLI generates later, during the E2E run itself.
+ #
+ # A resolution failure must not fail the job - it only means the specs pay the download cost
+ # they paid before this step existed.
+ #
+ # Retry before giving up, though. Both wrappers fetch their own distribution on a cold cache,
+ # and a failure there is not merely a slower run: it leaves no Maven on the runner at all, so
+ # the build inside the spec exits 1, the resource never starts, and the shard fails 15 minutes
+ # later as "Timed out after 900000ms waiting for an HTTP endpoint for resource 'catalog'"
+ # rather than as the download error it actually is.
+ warm() {
+ local description=$1
+ local directory=$2
+ shift 2
+
+ local attempt
+ for attempt in 1 2 3; do
+ if ( cd "$directory" && "$@" ); then
+ return 0
+ fi
+
+ if [ "$attempt" -lt 3 ]; then
+ echo "warning: pre-resolving $description failed (attempt $attempt/3), retrying"
+ sleep $((attempt * 15))
+ fi
+ done
+
+ echo "warning: could not pre-resolve $description"
+ }
+
+ cd playground/JavaSpringBoot
+ for maven_project in catalog worker; do
+ # `dependency:go-offline` resolves the dependency tree but not every plugin a real build
+ # runs, so compiling here is what actually leaves `~/.m2` - the directory this job caches -
+ # holding the compiler, resources and Spring Boot plugins. The build output itself is
+ # deliberately not reused: the specs copy the playground without `target/` so each run
+ # builds clean, which is the same reason the Gradle project below is compiled rather than
+ # only resolved.
+ warm "Maven dependencies for $maven_project" "$maven_project" \
+ ./mvnw --batch-mode --no-transfer-progress -q dependency:go-offline compile
+ done
+ warm "Gradle dependencies for orders" orders \
+ ./gradlew --no-daemon --quiet compileJava
+
+ - name: Install Java E2E prerequisites
+ if: ${{ matrix.installJava }}
+ shell: bash
+ run: |
+ set -euo pipefail
+
+ # The E2E VS Code instance runs offline, and the extension only advertises the `java`
+ # capability - which is what makes the CLI hand a Java AppHost back to the extension to
+ # launch and debug, instead of spawning `java` itself - when redhat.java and
+ # vscjava.vscode-java-debug are both installed. vscode-java-dependency is a hard activation
+ # dependency of the debug extension. Versions and digests are pinned so a marketplace
+ # release cannot change what these shards are testing.
+ #
+ # redhat.java also publishes platform-specific builds that embed a JRE; the universal build
+ # is a third of the size and runs on the JDK installed above.
+ java_language_vsix="$RUNNER_TEMP/redhat-java-1.55.0.vsix"
+ curl --fail --location --compressed --retry 3 --retry-all-errors \
+ --output "$java_language_vsix" \
+ 'https://marketplace.visualstudio.com/_apis/public/gallery/publishers/redhat/vsextensions/java/1.55.0/vspackage'
+ echo '011639c3ee347b9591895bfc77d8cf28f836c053d0a49ae4a83efe9dc473a603 '"$java_language_vsix" | sha256sum --check -
+
+ java_debug_vsix="$RUNNER_TEMP/vscjava-vscode-java-debug-0.59.0.vsix"
+ curl --fail --location --compressed --retry 3 --retry-all-errors \
+ --output "$java_debug_vsix" \
+ 'https://marketplace.visualstudio.com/_apis/public/gallery/publishers/vscjava/vsextensions/vscode-java-debug/0.59.0/vspackage'
+ echo 'e5973fcd763a984ea4d6e57644ccf8f5fe6caa80c0e589f29403f00c9ace3920 '"$java_debug_vsix" | sha256sum --check -
+
+ java_dependency_vsix="$RUNNER_TEMP/vscjava-vscode-java-dependency-0.27.6.vsix"
+ curl --fail --location --compressed --retry 3 --retry-all-errors \
+ --output "$java_dependency_vsix" \
+ 'https://marketplace.visualstudio.com/_apis/public/gallery/publishers/vscjava/vsextensions/vscode-java-dependency/0.27.6/vspackage'
+ echo 'e4e7c8b90953e62c8ebcedaaafb88b3c42ddec3fcc9e37f268ac3203427d9fa0 '"$java_dependency_vsix" | sha256sum --check -
+
+ {
+ echo "ASPIRE_EXTENSION_E2E_JAVA_VSIX=$java_language_vsix:$java_debug_vsix:$java_dependency_vsix"
+ } >> "$GITHUB_ENV"
+
+ java -version
+
- name: Prepare Aspire CLI and package hive
id: prepare_cli
run: |
@@ -465,6 +676,33 @@ jobs:
}
& $cli.FullName setup
+ # pwsh does not stop on a native command's exit code, so an unchecked failure here left the
+ # shard running without the orchestration component and failing minutes later with a debug
+ # startup timeout instead of the real reason - "The Aspire orchestration component is not
+ # installed at ~/.nuget/packages/microsoft.developercontrolplane.//tools/dcp".
+ if ($LASTEXITCODE -ne 0) { throw "aspire setup failed with exit code $LASTEXITCODE." }
+
+ # A zero exit code only means setup ran, not that it produced an orchestration component. The
+ # shards resolve DCP from this bundle rather than from ~/.nuget/packages, because a
+ # guest-language AppHost never restores the Microsoft.DeveloperControlPlane. package.
+ # Assert it is really here so a missing DCP fails on this line, naming the component, instead
+ # of surfacing minutes later as an unexplained debug startup timeout.
+ #
+ # `aspire setup` extracts to SetupCommand.GetDefaultInstallPath(processPath), which is the
+ # *parent of the parent* of the CLI binary - not the directory the archive was unpacked into.
+ # With the CLI at artifacts/bundle//aspire that install path is artifacts/bundle, so DCP
+ # lands beside $bundleDir rather than inside it. Derive the same path the CLI derives instead
+ # of assuming a layout, otherwise this assertion fails on every shard even when setup worked.
+ $cliDir = Split-Path -Path $cli.FullName -Parent
+ $installPath = Split-Path -Path $cliDir -Parent
+ $dcpExecutable = if ('${{ runner.os }}' -eq 'Windows') { 'dcp.exe' } else { 'dcp' }
+ $dcp = Get-ChildItem -Path $installPath -Recurse -File -Filter $dcpExecutable -ErrorAction SilentlyContinue | Select-Object -First 1
+ if ($null -eq $dcp) {
+ Get-ChildItem -Path $installPath -Recurse -Directory -ErrorAction SilentlyContinue | Select-Object -ExpandProperty FullName
+ throw "'aspire setup' succeeded but no $dcpExecutable exists under $installPath, so every AppHost in this shard would fail to orchestrate."
+ }
+ Write-Host "Orchestration component: $($dcp.FullName)"
+ "ASPIRE_DCP_PATH=$($dcp.Directory.FullName)" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
$shippingDir = Join-Path '${{ github.workspace }}' 'artifacts/nugets/Debug/Shipping'
if (-not (Test-Path $shippingDir)) {
@@ -509,12 +747,54 @@ jobs:
- name: Install E2E recorder
if: ${{ matrix.useXvfb }}
run: |
+ # ffmpeg only powers the diagnostic screen recordings, and run-e2e.js already skips
+ # recording with a warning when the binary is missing. So this step must never be able to
+ # fail or stall a shard: it is strictly a nice-to-have for debugging flakes after the fact.
+ #
+ # It used to call apt-get unguarded, which talks to the Azure Ubuntu mirrors. That is a
+ # network dependency with no timeout, and a degraded mirror has hung this step past the
+ # job timeout - taking down shards (including ones with no Java or recording relevance)
+ # that were otherwise healthy. Bound every call and give up quietly instead.
if (Get-Command ffmpeg -ErrorAction SilentlyContinue) {
ffmpeg -version | Select-Object -First 1
- } else {
- sudo apt-get update
- sudo apt-get install -y --no-install-recommends ffmpeg
}
+ else {
+ $installed = $false
+ $attempts = 2
+
+ for ($attempt = 1; $attempt -le $attempts; $attempt++) {
+ # `timeout` (coreutils) bounds a stalled child and exits 124, which is what converts an
+ # unresponsive mirror into a retryable failure rather than an open-ended wait.
+ # `--kill-after` matters: plain `timeout` only sends SIGTERM, and apt/dpkg block or
+ # defer signals around critical sections, so without the escalation to SIGKILL a
+ # wedged child could still outlive its own timeout.
+ sudo timeout --kill-after=30 180 apt-get update
+
+ # Only the install decides success: `apt-get update` can time out while the install
+ # still succeeds from the indices already on the runner image.
+ sudo timeout --kill-after=30 180 apt-get install -y --no-install-recommends ffmpeg
+ if ($LASTEXITCODE -eq 0) {
+ $installed = $true
+ break
+ }
+
+ if ($attempt -lt $attempts) {
+ Write-Host "::warning::Attempt $attempt to install ffmpeg failed; retrying."
+ Start-Sleep -Seconds 15
+ }
+ }
+
+ if (-not $installed) {
+ Write-Host '::warning::ffmpeg could not be installed; E2E screen recordings are disabled for this shard.'
+ }
+ }
+
+ # GitHub's pwsh wrapper appends `if ((Test-Path variable:/LASTEXITCODE)) { exit $LASTEXITCODE }`,
+ # so a failed apt-get would otherwise fail this step through the leftover exit code and take
+ # the shard down over a missing diagnostic recorder. Exit explicitly to hold the
+ # "this step must never fail the job" contract.
+ # https://docs.github.com/actions/reference/workflows-and-actions/workflow-syntax#exit-codes-and-error-action-preference
+ exit 0
- name: Run extension E2E tests
working-directory: extension
diff --git a/.github/workflows/extension-release.yml b/.github/workflows/extension-release.yml
index cff47687c18..1587995244c 100644
--- a/.github/workflows/extension-release.yml
+++ b/.github/workflows/extension-release.yml
@@ -456,7 +456,6 @@ jobs:
echo " | \`SkipNpmPointerPublish\` | \`true\` |"
echo " | \`SkipChannelPromotion\` | \`true\` |"
echo " | \`SkipWinGetPublish\` | \`true\` |"
- echo " | \`SkipHomebrewValidation\` | \`true\` |"
echo " | \`SkipGitHubTasks\` | \`true\` |"
echo " | \`SkipReleaseAssets\` | \`true\` |"
echo " | \`SkipNixPackageUpdate\` | \`true\` |"
diff --git a/.github/workflows/homebrew-validate-release.yml b/.github/workflows/homebrew-validate-release.yml
new file mode 100644
index 00000000000..0cedb0c4c64
--- /dev/null
+++ b/.github/workflows/homebrew-validate-release.yml
@@ -0,0 +1,143 @@
+# Validate the Homebrew cask against a freshly-published Aspire release.
+#
+# Runs the full upstream-equivalent cask validation (`brew audit --cask
+# --online --signing` + a real `brew install`/`brew uninstall` cycle)
+# against the cask file generated from the just-published release's
+# aspire-cli-osx-* archives. This is the same validation that used to
+# run as HomebrewValidateJob inside eng/pipelines/release-publish-nuget.yml.
+# It was moved out because the AzDO release pipeline now creates the
+# GitHub release as a draft (to be compatible with GitHub's immutable
+# releases — see docs/release-process.md), and draft assets are not
+# served from the public github.com/.../releases/download/v/...
+# URL that `brew audit --online` and `brew install` need. The validation
+# therefore has to wait until the release manager publishes the draft.
+#
+# Trigger semantics: we subscribe to `release: [published]` rather than
+# `[released]`. Under the draft-then-publish flow the release manager
+# publishes an existing draft, and GitHub only reliably fires `published`
+# for that transition — `released` can be skipped when a release moves
+# from draft to published (see
+# https://docs.github.com/en/actions/reference/workflows-and-actions/events-that-trigger-workflows#release).
+# `published` fires the moment the asset URLs become reachable. Prereleases
+# and drafts are skipped via the `if:` guard since the Homebrew cask we ship
+# is stable-only.
+#
+# History: when changing this workflow, please ping @radical (Ankit) for
+# review — he set up the original HomebrewValidateJob in the AzDO
+# pipeline and knows the cross-channel implications best.
+
+name: Validate Homebrew Cask against released GitHub Release
+
+on:
+ release:
+ types: [published]
+ workflow_dispatch:
+ inputs:
+ release_version:
+ description: 'Release version to validate (e.g. 13.4.3). Required for manual runs.'
+ required: true
+ type: string
+
+# Avoid double-validating the same tag if both the `release: published`
+# event and a manual workflow_dispatch fire near each other.
+concurrency:
+ group: homebrew-validate-${{ github.event.release.tag_name || github.event.inputs.release_version }}
+ cancel-in-progress: false
+
+permissions:
+ contents: read
+
+jobs:
+ validate:
+ name: Validate cask against live release
+ # `release: published` fires for any published release, so check
+ # explicitly for a stable, non-draft, non-prerelease release here (this
+ # also covers workflow_dispatch, which can be aimed at any version). We
+ # also gate on the repo to make sure forks don't try to validate against
+ # microsoft/aspire releases.
+ if: >-
+ github.repository == 'microsoft/aspire'
+ && (
+ (github.event_name == 'release' && github.event.release.prerelease == false && github.event.release.draft == false)
+ || github.event_name == 'workflow_dispatch'
+ )
+ runs-on: macos-latest
+ timeout-minutes: 30
+ steps:
+ - name: Checkout repo
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
+ with:
+ fetch-depth: 1
+
+ - name: Resolve release version
+ id: resolve
+ env:
+ EVENT_VERSION: ${{ github.event.release.tag_name }}
+ INPUT_VERSION: ${{ github.event.inputs.release_version }}
+ run: |
+ set -euo pipefail
+
+ # release.tag_name comes in as "vX.Y.Z" for our tags; the
+ # workflow_dispatch input is supplied without the leading "v"
+ # (matching docs/release-process.md). Normalize to bare X.Y.Z.
+ if [[ -n "${EVENT_VERSION:-}" ]]; then
+ version="${EVENT_VERSION#v}"
+ else
+ version="${INPUT_VERSION#v}"
+ fi
+
+ if [[ -z "$version" ]]; then
+ echo "::error::Could not determine release version from event or inputs"
+ exit 1
+ fi
+
+ # Aspire's tags are vMAJOR.MINOR.PATCH for stable. The Homebrew
+ # cask we ship targets stable only — refuse anything else.
+ if ! [[ "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
+ echo "::error::Version '$version' does not match X.Y.Z (stable). Homebrew validation is stable-only."
+ exit 1
+ fi
+
+ echo "version=$version" >> "$GITHUB_OUTPUT"
+ echo "Resolved release version: $version"
+
+ - name: Generate cask file for released version
+ id: cask
+ run: |
+ set -euo pipefail
+ version="${{ steps.resolve.outputs.version }}"
+ out_dir="$RUNNER_TEMP/homebrew-cask"
+ mkdir -p "$out_dir"
+
+ # generate-cask.sh computes SHA256s by downloading the
+ # aspire-cli-osx-{arm64,x64}-.tar.gz tarballs from the
+ # public github.com/.../releases/download/v/... URL,
+ # then renders eng/homebrew/aspire.rb.template with the
+ # resulting hashes. This depends on the release assets being
+ # public, which is why this workflow runs on release: [published]
+ # (when the human publishes the draft) rather than at
+ # draft-creation time, when the asset URLs don't resolve yet.
+ #
+ # NOTE (@radical, please review): the old AzDO HomebrewValidateJob
+ # consumed the cask file emitted by the source build directly
+ # (download artifact: homebrew-cask-stable). This workflow
+ # regenerates the cask from scratch instead, which means
+ # generate-cask.sh becomes the de-facto source of truth for the
+ # cask shape. If the source build ever customizes the cask
+ # template (custom test do block, per-build tweaks), the
+ # validation here will silently diverge from what ships. See
+ # eng/homebrew/README.md for the trade-off and aspire#18068
+ # for the discussion that introduced this change.
+ eng/homebrew/generate-cask.sh \
+ --version "$version" \
+ --output "$out_dir/aspire.rb"
+
+ echo "cask_file=$out_dir/aspire.rb" >> "$GITHUB_OUTPUT"
+
+ - name: Validate cask against live GitHub release
+ run: |
+ set -euo pipefail
+ eng/homebrew/validate-cask-artifact.sh \
+ --cask-file "${{ steps.cask.outputs.cask_file }}" \
+ --channel stable \
+ --validation-mode LiveRelease
diff --git a/.github/workflows/milestone-changelog.lock.yml b/.github/workflows/milestone-changelog.lock.yml
index 006feb62ab8..b144023d6fc 100644
--- a/.github/workflows/milestone-changelog.lock.yml
+++ b/.github/workflows/milestone-changelog.lock.yml
@@ -1,6 +1,6 @@
-# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"a5b8f2169fdf09e15e5bf5c018e3a1f6671b92949456bf59f483f53f15440765","body_hash":"57136f88b12a8ca98c6913fe6de4eaed46719adb4880b9625eae320e26cbfd2e","compiler_version":"v0.85.4","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.78"}}
-# gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/checkout","sha":"3d3c42e5aac5ba805825da76410c181273ba90b1","version":"v7.0.1"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/download-artifact","sha":"d3f86a106a0bac45b974a628896c90dbdf5c8093","version":"v4"},{"repo":"actions/github-script","sha":"373c709c69115d41ff229c7e5df9f8788daa9553","version":"v9"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"820762786026740c76f36085b0efc47a31fe5020","version":"v7.0.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"actions/upload-artifact","sha":"ea165f8d65b6e75b540449e92b4886f43607fa02","version":"v4"},{"repo":"github/gh-aw-actions/setup","sha":"2709137ea6c5b0e19aa621454dc643ea8dc526b1","version":"v0.85.4"}],"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.8","digest":"sha256:38bbea36cdb46a3c9d04d1db05e672966f5239b431a2022eb35881688e5721d8","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.4.8@sha256:38bbea36cdb46a3c9d04d1db05e672966f5239b431a2022eb35881688e5721d8"},{"image":"ghcr.io/github/gh-aw-node","digest":"sha256:0d9f1fb5fd6610c0ac1f5194a38e45a8a1e81f8a390d5142d8e4e6f26a4b3196","pinned_image":"ghcr.io/github/gh-aw-node@sha256:0d9f1fb5fd6610c0ac1f5194a38e45a8a1e81f8a390d5142d8e4e6f26a4b3196"},{"image":"ghcr.io/github/github-mcp-server:v1.8.0","digest":"sha256:d5a18c04b92714c309eb46a2305087e91a4dbd80420f6e462656699f95093520","pinned_image":"ghcr.io/github/github-mcp-server:v1.8.0@sha256:d5a18c04b92714c309eb46a2305087e91a4dbd80420f6e462656699f95093520"}]}
-# This file was automatically generated by gh-aw (v0.85.4). DO NOT EDIT. To debug this workflow, load the skill at https://github.com/github/gh-aw/blob/main/debug.md
+# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"a5b8f2169fdf09e15e5bf5c018e3a1f6671b92949456bf59f483f53f15440765","body_hash":"57136f88b12a8ca98c6913fe6de4eaed46719adb4880b9625eae320e26cbfd2e","compiler_version":"v0.86.2","strict":true,"agent_id":"copilot","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/checkout","sha":"3d3c42e5aac5ba805825da76410c181273ba90b1","version":"v7.0.1"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/download-artifact","sha":"d3f86a106a0bac45b974a628896c90dbdf5c8093","version":"v4"},{"repo":"actions/github-script","sha":"373c709c69115d41ff229c7e5df9f8788daa9553","version":"v9"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"820762786026740c76f36085b0efc47a31fe5020","version":"v7.0.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"actions/upload-artifact","sha":"ea165f8d65b6e75b540449e92b4886f43607fa02","version":"v4"},{"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"},{"image":"ghcr.io/github/github-mcp-server:v1.9.0","digest":"sha256:881b53d6f75f69bdbc1b5b10fc2f1361717c19054143b3a8529fb5c32061a50e","pinned_image":"ghcr.io/github/github-mcp-server:v1.9.0@sha256:881b53d6f75f69bdbc1b5b10fc2f1361717c19054143b3a8529fb5c32061a50e"}]}
+# 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
#
# ___ _ _
# / _ \ | | (_)
@@ -40,7 +40,6 @@
# - REPO: (main workflow)
#
# Secrets used:
-# - COPILOT_GITHUB_TOKEN
# - GH_AW_GITHUB_MCP_SERVER_TOKEN
# - GH_AW_GITHUB_TOKEN
# - GITHUB_TOKEN
@@ -54,15 +53,15 @@
# - actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
# - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
# - actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
-# - github/gh-aw-actions/setup@2709137ea6c5b0e19aa621454dc643ea8dc526b1 # v0.85.4
+# - 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.8@sha256:38bbea36cdb46a3c9d04d1db05e672966f5239b431a2022eb35881688e5721d8
+# - ghcr.io/github/gh-aw-mcpg:v0.4.9@sha256:e5a1569aeaf41820fa7bdee3e94468cae448133cdbf00119ad24f5b74db1ab9f
# - ghcr.io/github/gh-aw-node@sha256:0d9f1fb5fd6610c0ac1f5194a38e45a8a1e81f8a390d5142d8e4e6f26a4b3196
-# - ghcr.io/github/github-mcp-server:v1.8.0@sha256:d5a18c04b92714c309eb46a2305087e91a4dbd80420f6e462656699f95093520
+# - ghcr.io/github/github-mcp-server:v1.9.0@sha256:881b53d6f75f69bdbc1b5b10fc2f1361717c19054143b3a8529fb5c32061a50e
name: "Milestone Changelog Generator"
on:
@@ -115,14 +114,14 @@ jobs:
steps:
- name: Setup Scripts
id: setup
- uses: github/gh-aw-actions/setup@2709137ea6c5b0e19aa621454dc643ea8dc526b1 # v0.85.4
+ 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: "Milestone Changelog Generator"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/milestone-changelog.lock.yml@${{ github.ref }}
- GH_AW_INFO_VERSION: "1.0.78"
+ 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
@@ -131,9 +130,9 @@ jobs:
GH_AW_INFO_ENGINE_ID: "copilot"
GH_AW_INFO_ENGINE_NAME: "GitHub Copilot CLI"
GH_AW_INFO_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || vars.GH_AW_DEFAULT_MODEL_COPILOT || 'auto' }}
- GH_AW_INFO_VERSION: "1.0.78"
- GH_AW_INFO_AGENT_VERSION: "1.0.78"
- GH_AW_INFO_CLI_VERSION: "v0.85.4"
+ 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: "Milestone Changelog Generator"
GH_AW_INFO_EXPERIMENTAL: "false"
GH_AW_INFO_SUPPORTS_TOOLS_ALLOWLIST: "true"
@@ -143,6 +142,7 @@ jobs:
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_COMPILED_STRICT: "true"
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
@@ -155,7 +155,6 @@ jobs:
id: check-oauth-tokens
run: bash "${RUNNER_TEMP}/gh-aw/actions/check_oauth_tokens.sh"
env:
- COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
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
@@ -175,8 +174,8 @@ jobs:
env:
GH_AW_AGENT_FOLDERS: ".agents .github"
GH_AW_AGENT_FILES: "AGENTS.md"
- # poutine:ignore untrusted_checkout_exec
- run: bash "${RUNNER_TEMP}/gh-aw/actions/save_base_github_folders.sh"
+ 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
@@ -192,7 +191,7 @@ jobs:
- name: Check compile-agentic version
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
- GH_AW_COMPILED_VERSION: "v0.85.4"
+ GH_AW_COMPILED_VERSION: "v0.86.2"
with:
script: |
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
@@ -203,9 +202,12 @@ jobs:
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_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ 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\"},{\"file\":\"github_mcp_tools_with_safeoutputs_prompt.md\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0004\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0005\"}]}"
GH_AW_EXPR_1A3A194A: ${{ github.event.discussion.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'discussion' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }}
GH_AW_EXPR_463A214A: ${{ github.event.pull_request.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'pull_request' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }}
GH_AW_EXPR_802A9F6A: ${{ github.event.issue.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'issue' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }}
@@ -214,63 +216,22 @@ jobs:
GH_AW_GITHUB_REPOSITORY: ${{ github.repository }}
GH_AW_GITHUB_RUN_ID: ${{ github.run_id }}
GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }}
- # poutine:ignore untrusted_checkout_exec
- run: |
- bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh"
- {
- cat << 'GH_AW_PROMPT_8db497e5a3cf9f7b_EOF'
-
- GH_AW_PROMPT_8db497e5a3cf9f7b_EOF
- cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md"
- cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md"
- cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md"
- cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md"
- cat << 'GH_AW_PROMPT_8db497e5a3cf9f7b_EOF'
-
- Tools: missing_tool, missing_data, noop, publish
-
- GH_AW_PROMPT_8db497e5a3cf9f7b_EOF
- cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md"
- cat << 'GH_AW_PROMPT_8db497e5a3cf9f7b_EOF'
-
- The following GitHub context information is available for this workflow:
- {{#if github.actor}}
- - **actor**: __GH_AW_GITHUB_ACTOR__
- {{/if}}
- {{#if github.repository}}
- - **repository**: __GH_AW_GITHUB_REPOSITORY__
- {{/if}}
- {{#if github.workspace}}
- - **workspace**: __GH_AW_GITHUB_WORKSPACE__
- {{/if}}
- {{#if github.event.issue.number || (github.aw.context.item_type == 'issue' && github.aw.context.item_number)}}
- - **issue-number**: #__GH_AW_EXPR_802A9F6A__
- {{/if}}
- {{#if github.event.discussion.number || (github.aw.context.item_type == 'discussion' && github.aw.context.item_number)}}
- - **discussion-number**: #__GH_AW_EXPR_1A3A194A__
- {{/if}}
- {{#if github.event.pull_request.number || (github.aw.context.item_type == 'pull_request' && github.aw.context.item_number)}}
- - **pull-request-number**: #__GH_AW_EXPR_463A214A__
- {{/if}}
- {{#if github.event.comment.id || github.aw.context.comment_id}}
- - **comment-id**: __GH_AW_EXPR_FF1D34CE__
- {{/if}}
- {{#if github.run_id}}
- - **workflow-run-id**: __GH_AW_GITHUB_RUN_ID__
- {{/if}}
-
-
- GH_AW_PROMPT_8db497e5a3cf9f7b_EOF
- cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md"
- cat << 'GH_AW_PROMPT_8db497e5a3cf9f7b_EOF'
-
- {{#runtime-import .github/workflows/milestone-changelog.md}}
- GH_AW_PROMPT_8db497e5a3cf9f7b_EOF
- } > "$GH_AW_PROMPT"
+ GH_AW_PROMPT_CONTENT_0000: "\n"
+ GH_AW_PROMPT_CONTENT_0001: "\nTools: missing_tool, missing_data, noop, publish\n"
+ GH_AW_PROMPT_CONTENT_0002: "\n"
+ GH_AW_PROMPT_CONTENT_0003: "\nThe following GitHub context information is available for this workflow:\n{{#if github.actor}}\n- **actor**: __GH_AW_GITHUB_ACTOR__\n{{/if}}\n{{#if github.repository}}\n- **repository**: __GH_AW_GITHUB_REPOSITORY__\n{{/if}}\n{{#if github.workspace}}\n- **workspace**: __GH_AW_GITHUB_WORKSPACE__\n{{/if}}\n{{#if github.event.issue.number || (github.aw.context.item_type == 'issue' && github.aw.context.item_number)}}\n- **issue-number**: #__GH_AW_EXPR_802A9F6A__\n{{/if}}\n{{#if github.event.discussion.number || (github.aw.context.item_type == 'discussion' && github.aw.context.item_number)}}\n- **discussion-number**: #__GH_AW_EXPR_1A3A194A__\n{{/if}}\n{{#if github.event.pull_request.number || (github.aw.context.item_type == 'pull_request' && github.aw.context.item_number)}}\n- **pull-request-number**: #__GH_AW_EXPR_463A214A__\n{{/if}}\n{{#if github.event.comment.id || github.aw.context.comment_id}}\n- **comment-id**: __GH_AW_EXPR_FF1D34CE__\n{{/if}}\n{{#if github.run_id}}\n- **workflow-run-id**: __GH_AW_GITHUB_RUN_ID__\n{{/if}}\n\n\n"
+ GH_AW_PROMPT_CONTENT_0004: "\n"
+ GH_AW_PROMPT_CONTENT_0005: "{{#runtime-import .github/workflows/milestone-changelog.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: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_PROMPT: ${{ runner.temp }}/gh-aw/aw-prompts/prompt.txt
GH_AW_ENGINE_ID: "copilot"
with:
script: |
@@ -281,7 +242,7 @@ jobs:
- name: Substitute placeholders
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
- GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_PROMPT: ${{ runner.temp }}/gh-aw/aw-prompts/prompt.txt
GH_AW_EXPR_1A3A194A: ${{ github.event.discussion.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'discussion' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }}
GH_AW_EXPR_463A214A: ${{ github.event.pull_request.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'pull_request' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }}
GH_AW_EXPR_802A9F6A: ${{ github.event.issue.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'issue' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }}
@@ -315,14 +276,18 @@ jobs:
});
- name: Validate prompt placeholders
env:
- GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
- # poutine:ignore untrusted_checkout_exec
- run: bash "${RUNNER_TEMP}/gh-aw/actions/validate_prompt_placeholders.sh"
+ 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: /tmp/gh-aw/aw-prompts/prompt.txt
- # poutine:ignore untrusted_checkout_exec
- run: bash "${RUNNER_TEMP}/gh-aw/actions/print_prompt_summary.sh"
+ 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
@@ -390,7 +355,7 @@ jobs:
steps:
- name: Setup Scripts
id: setup
- uses: github/gh-aw-actions/setup@2709137ea6c5b0e19aa621454dc643ea8dc526b1 # v0.85.4
+ uses: github/gh-aw-actions/setup@6aab9e5b5c91c615506061f09bedd81a23babe3c # v0.86.2
with:
destination: ${{ runner.temp }}/gh-aw/actions
job-name: ${{ github.job }}
@@ -399,7 +364,7 @@ jobs:
env:
GH_AW_SETUP_WORKFLOW_NAME: "Milestone Changelog Generator"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/milestone-changelog.lock.yml@${{ github.ref }}
- GH_AW_INFO_VERSION: "1.0.78"
+ 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
@@ -450,11 +415,13 @@ jobs:
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.85.4
+ 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: Determine automatic lockdown mode for GitHub MCP Server
@@ -491,7 +458,7 @@ jobs:
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.8@sha256:38bbea36cdb46a3c9d04d1db05e672966f5239b431a2022eb35881688e5721d8 ghcr.io/github/gh-aw-node@sha256:0d9f1fb5fd6610c0ac1f5194a38e45a8a1e81f8a390d5142d8e4e6f26a4b3196 ghcr.io/github/github-mcp-server:v1.8.0@sha256:d5a18c04b92714c309eb46a2305087e91a4dbd80420f6e462656699f95093520
+ 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 ghcr.io/github/github-mcp-server:v1.9.0@sha256:881b53d6f75f69bdbc1b5b10fc2f1361717c19054143b3a8529fb5c32061a50e
- name: Generate Safe Outputs Config
run: |
mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs"
@@ -625,22 +592,23 @@ jobs:
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"
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 -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.8'
+ 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_b300e50cd08d2fb5_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs"
+ cat << GH_AW_MCP_CONFIG_fecaa78952dd2e64_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs"
{
"mcpServers": {
"github": {
"type": "stdio",
- "container": "ghcr.io/github/github-mcp-server:v1.8.0",
+ "container": "ghcr.io/github/github-mcp-server:v1.9.0",
"env": {
"GITHUB_FEATURES": "fields_param",
"GITHUB_HOST": "${GITHUB_SERVER_URL}",
@@ -700,7 +668,7 @@ jobs:
"startupTimeout": 120
}
}
- GH_AW_MCP_CONFIG_b300e50cd08d2fb5_EOF
+ GH_AW_MCP_CONFIG_fecaa78952dd2e64_EOF
- name: Mount MCP servers as CLIs
id: mount-mcp-clis
continue-on-error: true
@@ -762,6 +730,18 @@ jobs:
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
@@ -786,8 +766,8 @@ jobs:
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 GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_API_KEY --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 /usr/local/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 github --allow-tool safeoutputs --allow-tool '\''shell(cat)'\'' --allow-tool '\''shell(cd)'\'' --allow-tool '\''shell(cp)'\'' --allow-tool '\''shell(date)'\'' --allow-tool '\''shell(echo)'\'' --allow-tool '\''shell(gh:*)'\'' --allow-tool '\''shell(github:*)'\'' --allow-tool '\''shell(grep)'\'' --allow-tool '\''shell(head)'\'' --allow-tool '\''shell(jq)'\'' --allow-tool '\''shell(ls)'\'' --allow-tool '\''shell(mkdir)'\'' --allow-tool '\''shell(mv)'\'' --allow-tool '\''shell(printf)'\'' --allow-tool '\''shell(pwd)'\'' --allow-tool '\''shell(python3)'\'' --allow-tool '\''shell(rm)'\'' --allow-tool '\''shell(safeoutputs:*)'\'' --allow-tool '\''shell(sort)'\'' --allow-tool '\''shell(tail)'\'' --allow-tool '\''shell(uniq)'\'' --allow-tool '\''shell(wc)'\'' --allow-tool '\''shell(xargs)'\'' --allow-tool '\''shell(xxd)'\'' --allow-tool '\''shell(yq)'\'' --allow-tool write --allow-all-paths --add-dir "${GITHUB_WORKSPACE}" --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log
+ 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 GITHUB_MCP_SERVER_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 github --allow-tool safeoutputs --allow-tool '\''shell(cat)'\'' --allow-tool '\''shell(cd)'\'' --allow-tool '\''shell(cp)'\'' --allow-tool '\''shell(date)'\'' --allow-tool '\''shell(echo)'\'' --allow-tool '\''shell(gh:*)'\'' --allow-tool '\''shell(github:*)'\'' --allow-tool '\''shell(grep)'\'' --allow-tool '\''shell(head)'\'' --allow-tool '\''shell(jq)'\'' --allow-tool '\''shell(ls)'\'' --allow-tool '\''shell(mkdir)'\'' --allow-tool '\''shell(mv)'\'' --allow-tool '\''shell(printf)'\'' --allow-tool '\''shell(pwd)'\'' --allow-tool '\''shell(python3)'\'' --allow-tool '\''shell(rm)'\'' --allow-tool '\''shell(safeoutputs:*)'\'' --allow-tool '\''shell(sort)'\'' --allow-tool '\''shell(tail)'\'' --allow-tool '\''shell(uniq)'\'' --allow-tool '\''shell(wc)'\'' --allow-tool '\''shell(xargs)'\'' --allow-tool '\''shell(xxd)'\'' --allow-tool '\''shell(yq)'\'' --allow-tool write --allow-all-paths --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
@@ -801,7 +781,7 @@ jobs:
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: 30
- GH_AW_VERSION: v0.85.4
+ GH_AW_VERSION: v0.86.2
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
GITHUB_COPILOT_INTEGRATION_ID: agentic-workflows
@@ -992,7 +972,7 @@ jobs:
steps:
- name: Setup Scripts
id: setup
- uses: github/gh-aw-actions/setup@2709137ea6c5b0e19aa621454dc643ea8dc526b1 # v0.85.4
+ uses: github/gh-aw-actions/setup@6aab9e5b5c91c615506061f09bedd81a23babe3c # v0.86.2
with:
destination: ${{ runner.temp }}/gh-aw/actions
job-name: ${{ github.job }}
@@ -1001,7 +981,7 @@ jobs:
env:
GH_AW_SETUP_WORKFLOW_NAME: "Milestone Changelog Generator"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/milestone-changelog.lock.yml@${{ github.ref }}
- GH_AW_INFO_VERSION: "1.0.78"
+ 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
@@ -1198,7 +1178,7 @@ jobs:
steps:
- name: Setup Scripts
id: setup
- uses: github/gh-aw-actions/setup@2709137ea6c5b0e19aa621454dc643ea8dc526b1 # v0.85.4
+ uses: github/gh-aw-actions/setup@6aab9e5b5c91c615506061f09bedd81a23babe3c # v0.86.2
with:
destination: ${{ runner.temp }}/gh-aw/actions
job-name: ${{ github.job }}
@@ -1207,7 +1187,7 @@ jobs:
env:
GH_AW_SETUP_WORKFLOW_NAME: "Milestone Changelog Generator"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/milestone-changelog.lock.yml@${{ github.ref }}
- GH_AW_INFO_VERSION: "1.0.78"
+ 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
@@ -1259,25 +1239,7 @@ jobs:
- name: Prepare threat detection files
if: always() && steps.detection_guard.outputs.run_detection == 'true'
run: |
- mkdir -p /tmp/gh-aw/threat-detection/aw-prompts
- rm -f /tmp/gh-aw/agent_usage.json
- cp /tmp/gh-aw/aw-prompts/prompt.txt /tmp/gh-aw/threat-detection/aw-prompts/prompt.txt 2>/dev/null || true
- if [ ! -s /tmp/gh-aw/threat-detection/aw-prompts/prompt.txt ]; then
- echo "::warning::ERR_VALIDATION: Missing or empty detection context prompt at /tmp/gh-aw/threat-detection/aw-prompts/prompt.txt. Ensure the agent artifact includes /tmp/gh-aw/aw-prompts/prompt.txt. Detection will continue with fallback workflow context."
- fi
- cp /tmp/gh-aw/agent_output.json /tmp/gh-aw/threat-detection/agent_output.json 2>/dev/null || true
- for f in /tmp/gh-aw/aw-*.patch; do
- if [ -f "$f" ]; then
- cp "$f" /tmp/gh-aw/threat-detection/ 2>/dev/null || true
- fi
- done
- for f in /tmp/gh-aw/aw-*.bundle; do
- if [ -f "$f" ]; then
- cp "$f" /tmp/gh-aw/threat-detection/ 2>/dev/null || true
- fi
- done
- echo "Prepared threat detection files:"
- ls -la /tmp/gh-aw/threat-detection/ 2>/dev/null || true
+ 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
@@ -1297,18 +1259,20 @@ jobs:
run: |
mkdir -p /tmp/gh-aw/threat-detection
touch /tmp/gh-aw/threat-detection/detection.log
- rm -f /tmp/gh-aw/threat-detection/step-summary.md
- touch /tmp/gh-aw/threat-detection/step-summary.md
+ 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.85.4
+ 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
@@ -1324,6 +1288,18 @@ jobs:
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
@@ -1350,9 +1326,10 @@ jobs:
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 --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 /usr/local/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 --add-dir "${GITHUB_WORKSPACE}" --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' 2>&1 | tee -a /tmp/gh-aw/threat-detection/detection.log
+ 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 --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
@@ -1364,14 +1341,13 @@ jobs:
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_TIMEOUT_MINUTES: 20
- GH_AW_VERSION: v0.85.4
+ 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]
@@ -1380,6 +1356,23 @@ jobs:
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()
@@ -1863,15 +1856,20 @@ jobs:
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@2709137ea6c5b0e19aa621454dc643ea8dc526b1 # v0.85.4
+ uses: github/gh-aw-actions/setup@6aab9e5b5c91c615506061f09bedd81a23babe3c # v0.86.2
with:
destination: ${{ runner.temp }}/gh-aw/actions
job-name: ${{ github.job }}
@@ -1880,7 +1878,7 @@ jobs:
env:
GH_AW_SETUP_WORKFLOW_NAME: "Milestone Changelog Generator"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/milestone-changelog.lock.yml@${{ github.ref }}
- GH_AW_INFO_VERSION: "1.0.78"
+ 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
diff --git a/.github/workflows/pr-docs-check.lock.yml b/.github/workflows/pr-docs-check.lock.yml
index 0c2f06b88f3..58297552eeb 100644
--- a/.github/workflows/pr-docs-check.lock.yml
+++ b/.github/workflows/pr-docs-check.lock.yml
@@ -1,6 +1,6 @@
-# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"25e0fe19c95e8ba536dd030e20724e289d3c9025acf55d08d90d78d24ac03077","body_hash":"43bd509e196c1c74c40d28da32a72b91cea8a64165f8c1a40e9adb414848b8b6","compiler_version":"v0.85.4","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.78"}}
-# gh-aw-manifest: {"version":1,"secrets":["ASPIRE_BOT_APP_ID","ASPIRE_BOT_PRIVATE_KEY","COPILOT_GITHUB_TOKEN","GH_AW_CI_TRIGGER_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/checkout","sha":"34e114876b0b11c390a56381ad16ebd13914f8d5","version":"v4"},{"repo":"actions/checkout","sha":"3d3c42e5aac5ba805825da76410c181273ba90b1","version":"v7.0.1"},{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"de0fac2e4500dabe0009e67214ff5f5447ce83dd"},{"repo":"actions/create-github-app-token","sha":"1b10c78c7865c340bc4f6099eb2f838309f1e8c3","version":"v3.1.1"},{"repo":"actions/create-github-app-token","sha":"bcd2ba49218906704ab6c1aa796996da409d3eb1","version":"v3.2.0"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/download-artifact","sha":"d3f86a106a0bac45b974a628896c90dbdf5c8093","version":"v4"},{"repo":"actions/github-script","sha":"373c709c69115d41ff229c7e5df9f8788daa9553","version":"v9"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"820762786026740c76f36085b0efc47a31fe5020","version":"v7.0.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"2709137ea6c5b0e19aa621454dc643ea8dc526b1","version":"v0.85.4"}],"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.8","digest":"sha256:38bbea36cdb46a3c9d04d1db05e672966f5239b431a2022eb35881688e5721d8","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.4.8@sha256:38bbea36cdb46a3c9d04d1db05e672966f5239b431a2022eb35881688e5721d8"},{"image":"ghcr.io/github/gh-aw-node","digest":"sha256:0d9f1fb5fd6610c0ac1f5194a38e45a8a1e81f8a390d5142d8e4e6f26a4b3196","pinned_image":"ghcr.io/github/gh-aw-node@sha256:0d9f1fb5fd6610c0ac1f5194a38e45a8a1e81f8a390d5142d8e4e6f26a4b3196"},{"image":"ghcr.io/github/github-mcp-server:v1.8.0","digest":"sha256:d5a18c04b92714c309eb46a2305087e91a4dbd80420f6e462656699f95093520","pinned_image":"ghcr.io/github/github-mcp-server:v1.8.0@sha256:d5a18c04b92714c309eb46a2305087e91a4dbd80420f6e462656699f95093520"}],"has_pull_request":true}
-# This file was automatically generated by gh-aw (v0.85.4). DO NOT EDIT. To debug this workflow, load the skill at https://github.com/github/gh-aw/blob/main/debug.md
+# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"96ed6ed956aad627b8c1756b9aa47854ca342449bda6cd60e40c6fb38a71cb0b","body_hash":"43bd509e196c1c74c40d28da32a72b91cea8a64165f8c1a40e9adb414848b8b6","compiler_version":"v0.86.2","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.79"}}
+# gh-aw-manifest: {"version":1,"secrets":["ASPIRE_BOT_APP_ID","ASPIRE_BOT_PRIVATE_KEY","GH_AW_CI_TRIGGER_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/checkout","sha":"34e114876b0b11c390a56381ad16ebd13914f8d5","version":"v4"},{"repo":"actions/checkout","sha":"3d3c42e5aac5ba805825da76410c181273ba90b1","version":"v7.0.1"},{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"de0fac2e4500dabe0009e67214ff5f5447ce83dd"},{"repo":"actions/create-github-app-token","sha":"1b10c78c7865c340bc4f6099eb2f838309f1e8c3","version":"v3.1.1"},{"repo":"actions/create-github-app-token","sha":"bcd2ba49218906704ab6c1aa796996da409d3eb1","version":"v3.2.0"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/download-artifact","sha":"d3f86a106a0bac45b974a628896c90dbdf5c8093","version":"v4"},{"repo":"actions/github-script","sha":"373c709c69115d41ff229c7e5df9f8788daa9553","version":"v9"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"820762786026740c76f36085b0efc47a31fe5020","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"},{"image":"ghcr.io/github/github-mcp-server:v1.9.0","digest":"sha256:881b53d6f75f69bdbc1b5b10fc2f1361717c19054143b3a8529fb5c32061a50e","pinned_image":"ghcr.io/github/github-mcp-server:v1.9.0@sha256:881b53d6f75f69bdbc1b5b10fc2f1361717c19054143b3a8529fb5c32061a50e"}],"has_pull_request":true}
+# 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
#
# ___ _ _
# / _ \ | | (_)
@@ -37,7 +37,6 @@
# Secrets used:
# - ASPIRE_BOT_APP_ID
# - ASPIRE_BOT_PRIVATE_KEY
-# - COPILOT_GITHUB_TOKEN
# - GH_AW_CI_TRIGGER_TOKEN
# - GH_AW_GITHUB_MCP_SERVER_TOKEN
# - GH_AW_GITHUB_TOKEN
@@ -55,15 +54,15 @@
# - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
# - actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
# - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
-# - github/gh-aw-actions/setup@2709137ea6c5b0e19aa621454dc643ea8dc526b1 # v0.85.4
+# - 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.8@sha256:38bbea36cdb46a3c9d04d1db05e672966f5239b431a2022eb35881688e5721d8
+# - ghcr.io/github/gh-aw-mcpg:v0.4.9@sha256:e5a1569aeaf41820fa7bdee3e94468cae448133cdbf00119ad24f5b74db1ab9f
# - ghcr.io/github/gh-aw-node@sha256:0d9f1fb5fd6610c0ac1f5194a38e45a8a1e81f8a390d5142d8e4e6f26a4b3196
-# - ghcr.io/github/github-mcp-server:v1.8.0@sha256:d5a18c04b92714c309eb46a2305087e91a4dbd80420f6e462656699f95093520
+# - ghcr.io/github/github-mcp-server:v1.9.0@sha256:881b53d6f75f69bdbc1b5b10fc2f1361717c19054143b3a8529fb5c32061a50e
name: "PR Documentation Check"
on:
@@ -123,7 +122,7 @@ jobs:
steps:
- name: Setup Scripts
id: setup
- uses: github/gh-aw-actions/setup@2709137ea6c5b0e19aa621454dc643ea8dc526b1 # v0.85.4
+ uses: github/gh-aw-actions/setup@6aab9e5b5c91c615506061f09bedd81a23babe3c # v0.86.2
with:
destination: ${{ runner.temp }}/gh-aw/actions
job-name: ${{ github.job }}
@@ -132,7 +131,7 @@ jobs:
env:
GH_AW_SETUP_WORKFLOW_NAME: "PR Documentation Check"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/pr-docs-check.lock.yml@${{ github.ref }}
- GH_AW_INFO_VERSION: "1.0.78"
+ 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
@@ -141,9 +140,9 @@ jobs:
GH_AW_INFO_ENGINE_ID: "copilot"
GH_AW_INFO_ENGINE_NAME: "GitHub Copilot CLI"
GH_AW_INFO_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || vars.GH_AW_DEFAULT_MODEL_COPILOT || 'auto' }}
- GH_AW_INFO_VERSION: "1.0.78"
- GH_AW_INFO_AGENT_VERSION: "1.0.78"
- GH_AW_INFO_CLI_VERSION: "v0.85.4"
+ 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: "PR Documentation Check"
GH_AW_INFO_EXPERIMENTAL: "false"
GH_AW_INFO_SUPPORTS_TOOLS_ALLOWLIST: "true"
@@ -153,6 +152,7 @@ jobs:
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_COMPILED_STRICT: "true"
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
@@ -165,7 +165,6 @@ jobs:
id: check-oauth-tokens
run: bash "${RUNNER_TEMP}/gh-aw/actions/check_oauth_tokens.sh"
env:
- COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
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
@@ -185,12 +184,12 @@ jobs:
env:
GH_AW_AGENT_FOLDERS: ".agents .github"
GH_AW_AGENT_FILES: "AGENTS.md"
- # poutine:ignore untrusted_checkout_exec
- run: bash "${RUNNER_TEMP}/gh-aw/actions/save_base_github_folders.sh"
+ run: |
+ bash "${RUNNER_TEMP}/gh-aw/actions/save_base_github_folders.sh"
- name: Check compile-agentic version
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
- GH_AW_COMPILED_VERSION: "v0.85.4"
+ GH_AW_COMPILED_VERSION: "v0.86.2"
with:
script: |
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
@@ -212,9 +211,12 @@ jobs:
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_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ 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\"},{\"file\":\"safe_outputs_create_pull_request.md\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0002\"},{\"file\":\"mcp_cli_tools_prompt.md\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0003\"},{\"file\":\"github_mcp_tools_with_safeoutputs_prompt.md\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0004\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0005\"}]}"
GH_AW_EXPR_1A3A194A: ${{ github.event.discussion.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'discussion' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }}
GH_AW_EXPR_2697560F: ${{ github.event.pull_request.number || github.event.inputs.pr_number }}
GH_AW_EXPR_463A214A: ${{ github.event.pull_request.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'pull_request' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }}
@@ -225,79 +227,22 @@ jobs:
GH_AW_GITHUB_REPOSITORY: ${{ github.repository }}
GH_AW_GITHUB_RUN_ID: ${{ github.run_id }}
GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }}
- # poutine:ignore untrusted_checkout_exec
- run: |
- bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh"
- {
- cat << 'GH_AW_PROMPT_c924f63d142a5e34_EOF'
-
- GH_AW_PROMPT_c924f63d142a5e34_EOF
- cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md"
- cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md"
- cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md"
- cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md"
- cat << 'GH_AW_PROMPT_c924f63d142a5e34_EOF'
-
- Tools: create_pull_request, missing_tool, missing_data, noop, notify_source_pr
- GH_AW_PROMPT_c924f63d142a5e34_EOF
- cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_create_pull_request.md"
- cat << 'GH_AW_PROMPT_c924f63d142a5e34_EOF'
-
- GH_AW_PROMPT_c924f63d142a5e34_EOF
- cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md"
- cat << 'GH_AW_PROMPT_c924f63d142a5e34_EOF'
-
- The following GitHub context information is available for this workflow:
- {{#if github.actor}}
- - **actor**: __GH_AW_GITHUB_ACTOR__
- {{/if}}
- {{#if github.repository}}
- - **repository**: __GH_AW_GITHUB_REPOSITORY__
- {{/if}}
- {{#if github.workspace}}
- - **workspace**: __GH_AW_GITHUB_WORKSPACE__
- {{/if}}
- {{#if github.event.issue.number || (github.aw.context.item_type == 'issue' && github.aw.context.item_number)}}
- - **issue-number**: #__GH_AW_EXPR_802A9F6A__
- {{/if}}
- {{#if github.event.discussion.number || (github.aw.context.item_type == 'discussion' && github.aw.context.item_number)}}
- - **discussion-number**: #__GH_AW_EXPR_1A3A194A__
- {{/if}}
- {{#if github.event.pull_request.number || (github.aw.context.item_type == 'pull_request' && github.aw.context.item_number)}}
- - **pull-request-number**: #__GH_AW_EXPR_463A214A__
- {{/if}}
- {{#if github.event.comment.id || github.aw.context.comment_id}}
- - **comment-id**: __GH_AW_EXPR_FF1D34CE__
- {{/if}}
- {{#if github.run_id}}
- - **workflow-run-id**: __GH_AW_GITHUB_RUN_ID__
- {{/if}}
- - **checkouts**: The following repositories have been checked out and are available in the workspace:
- - repo `microsoft/aspire.dev` → `$GITHUB_WORKSPACE` (cwd) (**current** - this is the repository you are working on; use this as the target for all GitHub operations unless otherwise specified) [shallow clone, fetch-depth=1 (default)]
- - **Note**: If a branch you need is not in the list above and is not listed as an additional fetched ref, it has NOT been checked out. For private repositories you cannot fetch it. If the branch is required and not available, exit with an error and ask the user to add it to the `fetch:` option of the `checkout:` configuration (e.g., `fetch: ["refs/pulls/open/*"]` for all open PR refs, or `fetch: ["main", "feature/my-branch"]` for specific branches).
- - **Warning: No git credentials are available to the agent.** Credentials are
- intentionally removed after the checkout step for security. This means any git
- operation that needs to authenticate to the remote will fail. In private repositories, that includes:
- - `git fetch`, `git pull`, `git clone`, and `git push` (direct push, not via safe-output tools)
- - Checking out or switching to a remote branch that is not already fetched
- - Deepening a shallow clone (`git fetch --unshallow`)
- - On-demand blob fetches in partial/blobless clones (operations on files not in the initial checkout)
- Do NOT attempt to configure credentials, run `git credential fill`, or modify `.gitconfig` —
- authentication will not succeed. If you encounter credential prompts or authentication errors,
- stop immediately and report the limitation rather than spending turns trying to work around it.
-
-
- GH_AW_PROMPT_c924f63d142a5e34_EOF
- cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md"
- cat << 'GH_AW_PROMPT_c924f63d142a5e34_EOF'
-
- {{#runtime-import .github/workflows/pr-docs-check.md}}
- GH_AW_PROMPT_c924f63d142a5e34_EOF
- } > "$GH_AW_PROMPT"
+ GH_AW_PROMPT_CONTENT_0000: "\n"
+ GH_AW_PROMPT_CONTENT_0001: "\nTools: create_pull_request, missing_tool, missing_data, noop, notify_source_pr\n"
+ GH_AW_PROMPT_CONTENT_0002: "\n"
+ GH_AW_PROMPT_CONTENT_0003: "\nThe following GitHub context information is available for this workflow:\n{{#if github.actor}}\n- **actor**: __GH_AW_GITHUB_ACTOR__\n{{/if}}\n{{#if github.repository}}\n- **repository**: __GH_AW_GITHUB_REPOSITORY__\n{{/if}}\n{{#if github.workspace}}\n- **workspace**: __GH_AW_GITHUB_WORKSPACE__\n{{/if}}\n{{#if github.event.issue.number || (github.aw.context.item_type == 'issue' && github.aw.context.item_number)}}\n- **issue-number**: #__GH_AW_EXPR_802A9F6A__\n{{/if}}\n{{#if github.event.discussion.number || (github.aw.context.item_type == 'discussion' && github.aw.context.item_number)}}\n- **discussion-number**: #__GH_AW_EXPR_1A3A194A__\n{{/if}}\n{{#if github.event.pull_request.number || (github.aw.context.item_type == 'pull_request' && github.aw.context.item_number)}}\n- **pull-request-number**: #__GH_AW_EXPR_463A214A__\n{{/if}}\n{{#if github.event.comment.id || github.aw.context.comment_id}}\n- **comment-id**: __GH_AW_EXPR_FF1D34CE__\n{{/if}}\n{{#if github.run_id}}\n- **workflow-run-id**: __GH_AW_GITHUB_RUN_ID__\n{{/if}}\n- **checkouts**: The following repositories have been checked out and are available in the workspace:\n - repo `microsoft/aspire.dev` → `$GITHUB_WORKSPACE` (cwd) (**current** - this is the repository you are working on; use this as the target for all GitHub operations unless otherwise specified) [shallow clone, fetch-depth=1 (default)]\n - **Note**: If a branch you need is not in the list above and is not listed as an additional fetched ref, it has NOT been checked out. For private repositories you cannot fetch it. If the branch is required and not available, exit with an error and ask the user to add it to the `fetch:` option of the `checkout:` configuration (e.g., `fetch: [\"refs/pulls/open/*\"]` for all open PR refs, or `fetch: [\"main\", \"feature/my-branch\"]` for specific branches).\n - **Warning: No git credentials are available to the agent.** Credentials are\n intentionally removed after the checkout step for security. This means any git\n operation that needs to authenticate to the remote will fail. In private repositories, that includes:\n - `git fetch`, `git pull`, `git clone`, and `git push` (direct push, not via safe-output tools)\n - Checking out or switching to a remote branch that is not already fetched\n - Deepening a shallow clone (`git fetch --unshallow`)\n - On-demand blob fetches in partial/blobless clones (operations on files not in the initial checkout)\n Do NOT attempt to configure credentials, run `git credential fill`, or modify `.gitconfig` —\n authentication will not succeed. If you encounter credential prompts or authentication errors,\n stop immediately and report the limitation rather than spending turns trying to work around it.\n\n\n"
+ GH_AW_PROMPT_CONTENT_0004: "\n"
+ GH_AW_PROMPT_CONTENT_0005: "{{#runtime-import .github/workflows/pr-docs-check.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: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_PROMPT: ${{ runner.temp }}/gh-aw/aw-prompts/prompt.txt
GH_AW_ENGINE_ID: "copilot"
GH_AW_EXPR_2697560F: ${{ github.event.pull_request.number || github.event.inputs.pr_number }}
GH_AW_GITHUB_EVENT_PULL_REQUEST_TITLE: ${{ github.event.pull_request.title }}
@@ -310,7 +255,7 @@ jobs:
- name: Substitute placeholders
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
- GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_PROMPT: ${{ runner.temp }}/gh-aw/aw-prompts/prompt.txt
GH_AW_EXPR_1A3A194A: ${{ github.event.discussion.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'discussion' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }}
GH_AW_EXPR_2697560F: ${{ github.event.pull_request.number || github.event.inputs.pr_number }}
GH_AW_EXPR_463A214A: ${{ github.event.pull_request.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'pull_request' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }}
@@ -350,14 +295,18 @@ jobs:
});
- name: Validate prompt placeholders
env:
- GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
- # poutine:ignore untrusted_checkout_exec
- run: bash "${RUNNER_TEMP}/gh-aw/actions/validate_prompt_placeholders.sh"
+ 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: /tmp/gh-aw/aw-prompts/prompt.txt
- # poutine:ignore untrusted_checkout_exec
- run: bash "${RUNNER_TEMP}/gh-aw/actions/print_prompt_summary.sh"
+ 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
@@ -419,7 +368,7 @@ jobs:
steps:
- name: Setup Scripts
id: setup
- uses: github/gh-aw-actions/setup@2709137ea6c5b0e19aa621454dc643ea8dc526b1 # v0.85.4
+ uses: github/gh-aw-actions/setup@6aab9e5b5c91c615506061f09bedd81a23babe3c # v0.86.2
with:
destination: ${{ runner.temp }}/gh-aw/actions
job-name: ${{ github.job }}
@@ -428,7 +377,7 @@ jobs:
env:
GH_AW_SETUP_WORKFLOW_NAME: "PR Documentation Check"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/pr-docs-check.lock.yml@${{ github.ref }}
- GH_AW_INFO_VERSION: "1.0.78"
+ 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
@@ -504,11 +453,13 @@ jobs:
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.85.4
+ 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: Generate GitHub App token
@@ -559,19 +510,6 @@ jobs:
env:
GH_AW_SKILL_DIR: ".github/skills"
run: bash "${RUNNER_TEMP}/gh-aw/actions/restore_inline_skills.sh"
- - name: Stage GitHub Copilot CLI for agent execution
- run: |
- COPILOT_BIN="$(command -v copilot || true)"
- if [[ -z "${COPILOT_BIN}" || ! -x "${COPILOT_BIN}" ]]; then
- echo "::error::The GitHub Copilot CLI installer did not provide an executable."
- exit 1
- fi
-
- if [[ "${COPILOT_BIN}" != "/usr/local/bin/copilot" ]]; then
- sudo cp "${COPILOT_BIN}" /usr/local/bin/copilot
- sudo chmod 755 /usr/local/bin/copilot
- fi
- /usr/local/bin/copilot --version
- name: Check out pre-agent scripts
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
@@ -603,7 +541,7 @@ jobs:
run: "set -euo pipefail\n\nmkdir -p .pr-docs-check\nOUT=.pr-docs-check/signals.json\n\nif [ -z \"${PR_NUMBER}\" ]; then\n echo \"ERROR: PR_NUMBER is empty; cannot compute signals.\" >&2\n exit 1\nfi\n# Same input validation as the target-branch resolver above — reject\n# anything that isn't a positive integer so a bad `workflow_dispatch`\n# input fails loudly here rather than producing an opaque gh api error.\nif ! [[ \"${PR_NUMBER}\" =~ ^[1-9][0-9]*$ ]]; then\n echo \"ERROR: PR_NUMBER '${PR_NUMBER}' is not a positive integer.\" >&2\n exit 1\nfi\n\necho \"Computing user-facing signals for microsoft/aspire#${PR_NUMBER}\"\n\n# --- 1. Fetch PR metadata (body) and changed files (paths + patches) -\n# The files endpoint returns at most 30 files per page and is capped\n# at 300 files / 3000 lines total per the GitHub API; that's fine\n# for our purposes because signal detection only needs path patterns\n# and patch hunks, and any change large enough to overflow that cap\n# is almost certainly user-facing on path patterns alone. The\n# script also emits `diff_scan_skipped_due_to_missing_patch` when\n# the API omits a `patch` for a file matched by a diff trigger,\n# so very-large diffs gate conservatively.\n#\n# https://docs.github.com/en/rest/pulls/pulls#list-pull-requests-files\nPR_JSON=\"$(mktemp)\"\nFILES_JSON=\"$(mktemp)\"\nREVIEWS_JSON=\"$(mktemp)\"\ngh api \"/repos/microsoft/aspire/pulls/${PR_NUMBER}\" > \"${PR_JSON}\"\ngh api --paginate \"/repos/microsoft/aspire/pulls/${PR_NUMBER}/files?per_page=100\" \\\n | jq -s 'add // []' > \"${FILES_JSON}\"\n# Reviews drive SME resolution below. One paginated call here replaces a\n# GitHub tool round-trip the agent would otherwise make inside the loop.\ngh api --paginate \"/repos/microsoft/aspire/pulls/${PR_NUMBER}/reviews?per_page=100\" \\\n | jq -s 'add // []' > \"${REVIEWS_JSON}\"\n\nFILE_COUNT=\"$(jq 'length' \"${FILES_JSON}\")\"\necho \"Files in PR : ${FILE_COUNT}\"\n\n# --- 2. Run signal detection ----------------------------------------\n# The signal catalog lives in a standalone Python script (preinstalled\n# on ubuntu-latest) so a malformed regex fails the step loudly instead\n# of being silently absorbed by a shell pipeline, the catalog can be\n# reviewed with syntax highlighting, and it has its own unittest suite.\npython3 _repos/aspire/.github/workflows/pr-docs-check/compute_signals.py \\\n \"${PR_JSON}\" \"${FILES_JSON}\" \"${OUT}\"\n\n# --- 3. Build compact PR context ------------------------------------\n# Reuse the same PR + files payloads (already fetched above) to write\n# .pr-docs-check/pr.json — the curated metadata the agent reads in\n# Step 1 instead of re-gathering it with several GitHub tool calls.\n# That gathering is fully deterministic, so doing it once here removes\n# those round-trips and the verbose API responses they add to context.\n# See compute_pr_context.py.\nPR_CONTEXT_OUT=.pr-docs-check/pr.json\npython3 _repos/aspire/.github/workflows/pr-docs-check/compute_pr_context.py \\\n \"${PR_JSON}\" \"${FILES_JSON}\" \"${PR_CONTEXT_OUT}\"\n\n# --- 4. Resolve the subject-matter expert (SME) ---------------------\n# SME selection from assignees/reviews is a deterministic algorithm, so\n# it runs once here (reading the curated pr.json + reviews) instead of\n# inside the agent loop. The agent reads .pr-docs-check/sme.json in\n# Step 2. Only the fuzzy CODEOWNERS hint is left to the agent, signalled\n# via \"needs_codeowners_fallback\". See resolve_sme.py.\nSME_OUT=.pr-docs-check/sme.json\npython3 _repos/aspire/.github/workflows/pr-docs-check/resolve_sme.py \\\n \"${PR_CONTEXT_OUT}\" \"${REVIEWS_JSON}\" \"${SME_OUT}\"\n\nrm -f \"${PR_JSON}\" \"${FILES_JSON}\" \"${REVIEWS_JSON}\"\n\necho \"--- ${OUT} ---\"\ncat \"${OUT}\"\necho \"--- ${PR_CONTEXT_OUT} ---\"\ncat \"${PR_CONTEXT_OUT}\"\necho \"--- ${SME_OUT} ---\"\ncat \"${SME_OUT}\""
- 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.8@sha256:38bbea36cdb46a3c9d04d1db05e672966f5239b431a2022eb35881688e5721d8 ghcr.io/github/gh-aw-node@sha256:0d9f1fb5fd6610c0ac1f5194a38e45a8a1e81f8a390d5142d8e4e6f26a4b3196 ghcr.io/github/github-mcp-server:v1.8.0@sha256:d5a18c04b92714c309eb46a2305087e91a4dbd80420f6e462656699f95093520
+ 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 ghcr.io/github/github-mcp-server:v1.9.0@sha256:881b53d6f75f69bdbc1b5b10fc2f1361717c19054143b3a8529fb5c32061a50e
- name: Generate Safe Outputs Config
run: |
mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs"
@@ -693,6 +631,10 @@ jobs:
"type": "string",
"maxLength": 256
},
+ "temporary_id": {
+ "type": "string",
+ "pattern": "^#?aw_[A-Za-z0-9_]{3,12}$"
+ },
"title": {
"required": true,
"type": "string",
@@ -806,22 +748,23 @@ jobs:
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"
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 -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.8'
+ 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_b3c497501797fe3b_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs"
+ cat << GH_AW_MCP_CONFIG_0bde3c464be51648_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs"
{
"mcpServers": {
"github": {
"type": "stdio",
- "container": "ghcr.io/github/github-mcp-server:v1.8.0",
+ "container": "ghcr.io/github/github-mcp-server:v1.9.0",
"env": {
"GITHUB_FEATURES": "fields_param",
"GITHUB_HOST": "${GITHUB_SERVER_URL}",
@@ -883,7 +826,7 @@ jobs:
"startupTimeout": 120
}
}
- GH_AW_MCP_CONFIG_b3c497501797fe3b_EOF
+ GH_AW_MCP_CONFIG_0bde3c464be51648_EOF
- name: Mount MCP servers as CLIs
id: mount-mcp-clis
continue-on-error: true
@@ -917,6 +860,18 @@ jobs:
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
@@ -941,8 +896,8 @@ jobs:
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 GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_API_KEY --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 /usr/local/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 --allow-all-paths --add-dir "${GITHUB_WORKSPACE}" --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log
+ 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 GITHUB_MCP_SERVER_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-all-tools --allow-all-paths --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
@@ -956,7 +911,7 @@ jobs:
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.85.4
+ GH_AW_VERSION: v0.86.2
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
GITHUB_COPILOT_INTEGRATION_ID: agentic-workflows
@@ -1151,7 +1106,7 @@ jobs:
steps:
- name: Setup Scripts
id: setup
- uses: github/gh-aw-actions/setup@2709137ea6c5b0e19aa621454dc643ea8dc526b1 # v0.85.4
+ uses: github/gh-aw-actions/setup@6aab9e5b5c91c615506061f09bedd81a23babe3c # v0.86.2
with:
destination: ${{ runner.temp }}/gh-aw/actions
job-name: ${{ github.job }}
@@ -1160,7 +1115,7 @@ jobs:
env:
GH_AW_SETUP_WORKFLOW_NAME: "PR Documentation Check"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/pr-docs-check.lock.yml@${{ github.ref }}
- GH_AW_INFO_VERSION: "1.0.78"
+ GH_AW_INFO_VERSION: "1.0.79"
GH_AW_INFO_AWF_VERSION: "v0.27.44"
GH_AW_INFO_ENGINE_ID: "copilot"
- name: Generate GitHub App token
@@ -1375,7 +1330,7 @@ jobs:
steps:
- name: Setup Scripts
id: setup
- uses: github/gh-aw-actions/setup@2709137ea6c5b0e19aa621454dc643ea8dc526b1 # v0.85.4
+ uses: github/gh-aw-actions/setup@6aab9e5b5c91c615506061f09bedd81a23babe3c # v0.86.2
with:
destination: ${{ runner.temp }}/gh-aw/actions
job-name: ${{ github.job }}
@@ -1384,7 +1339,7 @@ jobs:
env:
GH_AW_SETUP_WORKFLOW_NAME: "PR Documentation Check"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/pr-docs-check.lock.yml@${{ github.ref }}
- GH_AW_INFO_VERSION: "1.0.78"
+ 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
@@ -1436,45 +1391,7 @@ jobs:
- name: Prepare threat detection files
if: always() && steps.detection_guard.outputs.run_detection == 'true'
run: |
- mkdir -p /tmp/gh-aw/threat-detection/aw-prompts
- rm -f /tmp/gh-aw/agent_usage.json
- cp /tmp/gh-aw/aw-prompts/prompt.txt /tmp/gh-aw/threat-detection/aw-prompts/prompt.txt 2>/dev/null || true
- if [ ! -s /tmp/gh-aw/threat-detection/aw-prompts/prompt.txt ]; then
- echo "::warning::ERR_VALIDATION: Missing or empty detection context prompt at /tmp/gh-aw/threat-detection/aw-prompts/prompt.txt. Ensure the agent artifact includes /tmp/gh-aw/aw-prompts/prompt.txt. Detection will continue with fallback workflow context."
- fi
- cp /tmp/gh-aw/agent_output.json /tmp/gh-aw/threat-detection/agent_output.json 2>/dev/null || true
- for f in /tmp/gh-aw/aw-*.patch; do
- if [ -f "$f" ]; then
- cp "$f" /tmp/gh-aw/threat-detection/ 2>/dev/null || true
- fi
- done
- for f in /tmp/gh-aw/aw-*.bundle; do
- if [ -f "$f" ]; then
- cp "$f" /tmp/gh-aw/threat-detection/ 2>/dev/null || true
- fi
- done
- echo "Prepared threat detection files:"
- ls -la /tmp/gh-aw/threat-detection/ 2>/dev/null || true
- - name: Install GitHub Copilot CLI for threat detection staging
- if: always() && steps.detection_guard.outputs.run_detection == 'true'
- run: bash "${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh"
- env:
- GH_AW_COMPILED_VERSION: v0.85.4
- GH_HOST: github.com
- - name: Stage GitHub Copilot CLI for threat detection
- if: always() && steps.detection_guard.outputs.run_detection == 'true'
- run: |
- COPILOT_BIN="$(command -v copilot || true)"
- if [[ -z "${COPILOT_BIN}" || ! -x "${COPILOT_BIN}" ]]; then
- echo "::error::The GitHub Copilot CLI installer did not provide an executable."
- exit 1
- fi
-
- if [[ "${COPILOT_BIN}" != "/usr/local/bin/copilot" ]]; then
- sudo cp "${COPILOT_BIN}" /usr/local/bin/copilot
- sudo chmod 755 /usr/local/bin/copilot
- fi
- /usr/local/bin/copilot --version
+ 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
@@ -1494,18 +1411,20 @@ jobs:
run: |
mkdir -p /tmp/gh-aw/threat-detection
touch /tmp/gh-aw/threat-detection/detection.log
- rm -f /tmp/gh-aw/threat-detection/step-summary.md
- touch /tmp/gh-aw/threat-detection/step-summary.md
+ 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.85.4
+ 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
@@ -1521,6 +1440,18 @@ jobs:
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
@@ -1547,9 +1478,10 @@ jobs:
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 --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 /usr/local/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 --add-dir "${GITHUB_WORKSPACE}" --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' 2>&1 | tee -a /tmp/gh-aw/threat-detection/detection.log
+ 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 --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
@@ -1561,14 +1493,13 @@ jobs:
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_TIMEOUT_MINUTES: 20
- GH_AW_VERSION: v0.85.4
+ 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]
@@ -1577,6 +1508,23 @@ jobs:
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()
@@ -1912,14 +1860,14 @@ jobs:
steps:
- name: Setup Scripts
id: setup
- uses: github/gh-aw-actions/setup@2709137ea6c5b0e19aa621454dc643ea8dc526b1 # v0.85.4
+ 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: "PR Documentation Check"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/pr-docs-check.lock.yml@${{ github.ref }}
- GH_AW_INFO_VERSION: "1.0.78"
+ GH_AW_INFO_VERSION: "1.0.79"
GH_AW_INFO_AWF_VERSION: "v0.27.44"
GH_AW_INFO_ENGINE_ID: "copilot"
- name: Check team membership for workflow
@@ -1971,15 +1919,20 @@ jobs:
create_discussion_errors: ${{ steps.process_safe_outputs.outputs.create_discussion_errors }}
created_pr_number: ${{ steps.process_safe_outputs.outputs.created_pr_number }}
created_pr_url: ${{ steps.process_safe_outputs.outputs.created_pr_url }}
+ 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@2709137ea6c5b0e19aa621454dc643ea8dc526b1 # v0.85.4
+ uses: github/gh-aw-actions/setup@6aab9e5b5c91c615506061f09bedd81a23babe3c # v0.86.2
with:
destination: ${{ runner.temp }}/gh-aw/actions
job-name: ${{ github.job }}
@@ -1988,7 +1941,7 @@ jobs:
env:
GH_AW_SETUP_WORKFLOW_NAME: "PR Documentation Check"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/pr-docs-check.lock.yml@${{ github.ref }}
- GH_AW_INFO_VERSION: "1.0.78"
+ 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
@@ -2096,16 +2049,33 @@ jobs:
f"found {len(create_items)}."
)
- base_branch = create_items[0].get("base_branch")
+ # gh-aw v0.86.2 records the supported tool input as:
+ # {"type":"create_pull_request","base":"release/13.5",...}
+ # Older outputs record the normalized value as "base_branch" instead.
+ create_item = create_items[0]
+ has_base = "base" in create_item
+ has_base_branch = "base_branch" in create_item
+ base = create_item.get("base")
+ base_branch = create_item.get("base_branch")
+ if has_base and not isinstance(base, str):
+ raise SystemExit("Canonical create_pull_request base is invalid.")
+ if has_base_branch and not isinstance(base_branch, str):
+ raise SystemExit("Canonical create_pull_request base_branch is invalid.")
+ if has_base and has_base_branch and base != base_branch:
+ raise SystemExit(
+ "Canonical create_pull_request base and base_branch disagree."
+ )
+
+ target_branch = base if has_base else base_branch
if (
- not isinstance(base_branch, str)
- or re.fullmatch(r"main|release/[0-9]+\.[0-9]+(?:\.[0-9]+)?", base_branch)
+ not isinstance(target_branch, str)
+ or re.fullmatch(r"main|release/[0-9]+\.[0-9]+(?:\.[0-9]+)?", target_branch)
is None
):
- raise SystemExit("Canonical create_pull_request base_branch is invalid.")
+ raise SystemExit("Canonical create_pull_request target branch is invalid.")
with open(sys.argv[1], "a", encoding="utf-8") as github_output:
- github_output.write(f"branch={base_branch}\n")
+ github_output.write(f"branch={target_branch}\n")
PY
- name: Process Safe Outputs
id: process_safe_outputs
diff --git a/.github/workflows/pr-docs-check.md b/.github/workflows/pr-docs-check.md
index d5d265d1880..38d207f3079 100644
--- a/.github/workflows/pr-docs-check.md
+++ b/.github/workflows/pr-docs-check.md
@@ -184,32 +184,6 @@ safe-outputs:
private-key: ${{ secrets.ASPIRE_BOT_PRIVATE_KEY }}
owner: "microsoft"
repositories: ["aspire.dev", "aspire"]
- # Work around https://github.com/github/gh-aw/issues/50906 in gh-aw v0.85.4.
- # Threat detection runs on a fresh runner, and its custom steps run before the
- # generated Copilot installer. Run the same verified installer here so the
- # following step can stage a cached CLI where the generated AWF command expects
- # it. Remove these steps after upgrading to a compiler containing
- # https://github.com/github/gh-aw/pull/50908.
- threat-detection:
- steps:
- - name: Install GitHub Copilot CLI for threat detection staging
- run: bash "${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh"
- env:
- GH_HOST: github.com
- GH_AW_COMPILED_VERSION: v0.85.4
- - name: Stage GitHub Copilot CLI for threat detection
- run: |
- COPILOT_BIN="$(command -v copilot || true)"
- if [[ -z "${COPILOT_BIN}" || ! -x "${COPILOT_BIN}" ]]; then
- echo "::error::The GitHub Copilot CLI installer did not provide an executable."
- exit 1
- fi
-
- if [[ "${COPILOT_BIN}" != "/usr/local/bin/copilot" ]]; then
- sudo cp "${COPILOT_BIN}" /usr/local/bin/copilot
- sudo chmod 755 /usr/local/bin/copilot
- fi
- /usr/local/bin/copilot --version
# gh-aw generates the target-repository checkout required by create-pull-request.
# An additional actions/checkout step would trigger https://github.com/github/gh-aw/issues/50905
# in v0.85.4 and downgrade the app token from contents: write to contents: read.
@@ -243,16 +217,33 @@ safe-outputs:
f"found {len(create_items)}."
)
- base_branch = create_items[0].get("base_branch")
+ # gh-aw v0.86.2 records the supported tool input as:
+ # {"type":"create_pull_request","base":"release/13.5",...}
+ # Older outputs record the normalized value as "base_branch" instead.
+ create_item = create_items[0]
+ has_base = "base" in create_item
+ has_base_branch = "base_branch" in create_item
+ base = create_item.get("base")
+ base_branch = create_item.get("base_branch")
+ if has_base and not isinstance(base, str):
+ raise SystemExit("Canonical create_pull_request base is invalid.")
+ if has_base_branch and not isinstance(base_branch, str):
+ raise SystemExit("Canonical create_pull_request base_branch is invalid.")
+ if has_base and has_base_branch and base != base_branch:
+ raise SystemExit(
+ "Canonical create_pull_request base and base_branch disagree."
+ )
+
+ target_branch = base if has_base else base_branch
if (
- not isinstance(base_branch, str)
- or re.fullmatch(r"main|release/[0-9]+\.[0-9]+(?:\.[0-9]+)?", base_branch)
+ not isinstance(target_branch, str)
+ or re.fullmatch(r"main|release/[0-9]+\.[0-9]+(?:\.[0-9]+)?", target_branch)
is None
):
- raise SystemExit("Canonical create_pull_request base_branch is invalid.")
+ raise SystemExit("Canonical create_pull_request target branch is invalid.")
with open(sys.argv[1], "a", encoding="utf-8") as github_output:
- github_output.write(f"branch={base_branch}\n")
+ github_output.write(f"branch={target_branch}\n")
PY
create-pull-request:
title-prefix: "[docs] "
@@ -573,22 +564,6 @@ safe-outputs:
# agent starts and writes the result to .pr-docs-check/target.json. The
# agent reads that file verbatim and never re-derives the branch.
pre-agent-steps:
- # gh-aw v0.85.4 can select a cached Copilot CLI but still hard-codes
- # /usr/local/bin/copilot in the AWF command. Stage the selected binary there
- # until the compiler includes https://github.com/github/gh-aw/pull/50908.
- - name: Stage GitHub Copilot CLI for agent execution
- run: |
- COPILOT_BIN="$(command -v copilot || true)"
- if [[ -z "${COPILOT_BIN}" || ! -x "${COPILOT_BIN}" ]]; then
- echo "::error::The GitHub Copilot CLI installer did not provide an executable."
- exit 1
- fi
-
- if [[ "${COPILOT_BIN}" != "/usr/local/bin/copilot" ]]; then
- sudo cp "${COPILOT_BIN}" /usr/local/bin/copilot
- sudo chmod 755 /usr/local/bin/copilot
- fi
- /usr/local/bin/copilot --version
- name: Check out pre-agent scripts
# The `checkout:` block above made microsoft/aspire.dev the current
# workspace because that's where the doc PR is authored. We need a sparse,
diff --git a/.github/workflows/pr-docs-check/test_validate_outcome.py b/.github/workflows/pr-docs-check/test_validate_outcome.py
index dd95fae355e..46c2dbb4f90 100644
--- a/.github/workflows/pr-docs-check/test_validate_outcome.py
+++ b/.github/workflows/pr-docs-check/test_validate_outcome.py
@@ -39,17 +39,18 @@ def payload(
}
-def create_pull_request_item(base_branch: object = "release/13.5") -> dict:
- return {
+def create_pull_request_item(**target_fields: object) -> dict:
+ item = {
"type": "create_pull_request",
"title": "Draft docs",
"body": "Docs",
- "base_branch": base_branch,
}
+ item.update(target_fields or {"base": "release/13.5"})
+ return item
class ValidateOutcomeTests(unittest.TestCase):
- def test_drafted_with_correct_actual_base_passes(self) -> None:
+ def test_drafted_with_current_base_passes(self) -> None:
drafted_payload = payload("drafted", target_branch="release/13.5")
drafted_payload["items"].append(create_pull_request_item())
@@ -65,6 +66,108 @@ def test_drafted_with_correct_actual_base_passes(self) -> None:
message,
)
+ def test_drafted_with_legacy_base_branch_passes(self) -> None:
+ drafted_payload = payload("drafted", target_branch="release/13.5")
+ drafted_payload["items"].append(
+ create_pull_request_item(base_branch="release/13.5")
+ )
+
+ message = validate_outcome(
+ drafted_payload,
+ "https://github.com/microsoft/aspire.dev/pull/1447",
+ EXPECTED_SOURCE_PR_NUMBER,
+ "release/13.5",
+ )
+
+ self.assertIn("Confirmed drafted documentation PR", message)
+
+ def test_drafted_with_agreeing_base_fields_passes(self) -> None:
+ drafted_payload = payload("drafted", target_branch="release/13.5")
+ drafted_payload["items"].append(
+ create_pull_request_item(
+ base="release/13.5",
+ base_branch="release/13.5",
+ )
+ )
+
+ message = validate_outcome(
+ drafted_payload,
+ "https://github.com/microsoft/aspire.dev/pull/1447",
+ EXPECTED_SOURCE_PR_NUMBER,
+ "release/13.5",
+ )
+
+ self.assertIn("Confirmed drafted documentation PR", message)
+
+ def test_drafted_with_disagreeing_base_fields_fails(self) -> None:
+ drafted_payload = payload("drafted", target_branch="release/13.5")
+ drafted_payload["items"].append(
+ create_pull_request_item(
+ base="release/13.5",
+ base_branch="main",
+ )
+ )
+
+ with self.assertRaisesRegex(
+ OutcomeValidationError,
+ "Canonical create_pull_request base and base_branch disagree",
+ ):
+ validate_outcome(
+ drafted_payload,
+ "https://github.com/microsoft/aspire.dev/pull/1447",
+ EXPECTED_SOURCE_PR_NUMBER,
+ "release/13.5",
+ )
+
+ def test_drafted_with_invalid_canonical_target_fails(self) -> None:
+ cases = {
+ "missing": {},
+ "invalid current base": {"base": "release/latest"},
+ "current base wrong type": {"base": 13.5},
+ "invalid legacy base": {"base_branch": "release/latest"},
+ "legacy base wrong type": {"base_branch": 13.5},
+ "invalid current base with valid legacy base": {
+ "base": "release/latest",
+ "base_branch": "release/13.5",
+ },
+ "valid current base with invalid legacy base": {
+ "base": "release/13.5",
+ "base_branch": "release/latest",
+ },
+ }
+ for name, target_fields in cases.items():
+ with self.subTest(name=name):
+ drafted_payload = payload("drafted", target_branch="release/13.5")
+ create_item = create_pull_request_item()
+ create_item.pop("base")
+ create_item.update(target_fields)
+ drafted_payload["items"].append(create_item)
+
+ with self.assertRaises(OutcomeValidationError):
+ validate_outcome(
+ drafted_payload,
+ "https://github.com/microsoft/aspire.dev/pull/1447",
+ EXPECTED_SOURCE_PR_NUMBER,
+ "release/13.5",
+ )
+
+ def test_drafted_with_duplicate_create_items_fails(self) -> None:
+ drafted_payload = payload("drafted", target_branch="release/13.5")
+ drafted_payload["items"].extend(
+ [create_pull_request_item(), create_pull_request_item()]
+ )
+
+ with self.assertRaisesRegex(
+ OutcomeValidationError,
+ "Expected exactly one create_pull_request item for a drafted outcome, found 2",
+ ):
+ validate_outcome(
+ drafted_payload,
+ "https://github.com/microsoft/aspire.dev/pull/1447",
+ EXPECTED_SOURCE_PR_NUMBER,
+ "release/13.5",
+ )
+
def test_drafted_with_actual_base_mismatch_fails(self) -> None:
drafted_payload = payload("drafted", target_branch="release/13.5")
drafted_payload["items"].append(create_pull_request_item())
@@ -72,7 +175,7 @@ def test_drafted_with_actual_base_mismatch_fails(self) -> None:
with self.assertRaisesRegex(
OutcomeValidationError,
"Drafted PR base branch main does not match canonical "
- "create_pull_request base_branch release/13.5",
+ "create_pull_request target branch release/13.5",
):
validate_outcome(
drafted_payload,
@@ -87,7 +190,7 @@ def test_drafted_with_notification_target_mismatch_fails(self) -> None:
with self.assertRaisesRegex(
OutcomeValidationError,
- "Canonical create_pull_request base_branch release/13.5 does not match "
+ "Canonical create_pull_request target branch release/13.5 does not match "
"notify_source_pr target_branch main",
):
validate_outcome(
diff --git a/.github/workflows/pr-docs-check/validate_outcome.py b/.github/workflows/pr-docs-check/validate_outcome.py
index bf1fe8ec77f..552110cdf8d 100644
--- a/.github/workflows/pr-docs-check/validate_outcome.py
+++ b/.github/workflows/pr-docs-check/validate_outcome.py
@@ -104,6 +104,37 @@ def _require_target_branch(value: object, field_name: str) -> str:
return value
+def _get_create_pull_request_target(payload: Any) -> str:
+ create_pull_request = _get_create_pull_request(payload)
+ has_base = "base" in create_pull_request
+ has_base_branch = "base_branch" in create_pull_request
+ if not has_base and not has_base_branch:
+ raise OutcomeValidationError(
+ "Canonical create_pull_request target branch is missing."
+ )
+
+ if has_base and has_base_branch:
+ base = _require_target_branch(
+ create_pull_request.get("base"),
+ "canonical create_pull_request base",
+ )
+ base_branch = _require_target_branch(
+ create_pull_request.get("base_branch"),
+ "canonical create_pull_request base_branch",
+ )
+ if base != base_branch:
+ raise OutcomeValidationError(
+ "Canonical create_pull_request base and base_branch disagree."
+ )
+ return base
+
+ field_name = "base" if has_base else "base_branch"
+ return _require_target_branch(
+ create_pull_request.get(field_name),
+ f"canonical create_pull_request {field_name}",
+ )
+
+
def _validate_drafted_base_contract(
payload: Any,
notification: dict[str, Any],
@@ -115,18 +146,14 @@ def _validate_drafted_base_contract(
"Safe outputs returned an invalid microsoft/aspire.dev pull request URL."
)
- create_pull_request = _get_create_pull_request(payload)
- canonical_base = _require_target_branch(
- create_pull_request.get("base_branch"),
- "canonical create_pull_request base_branch",
- )
+ canonical_base = _get_create_pull_request_target(payload)
notification_target = _require_target_branch(
notification.get("target_branch"),
"notify_source_pr target_branch",
)
if notification_target != canonical_base:
raise OutcomeValidationError(
- "Canonical create_pull_request base_branch "
+ "Canonical create_pull_request target branch "
f"{canonical_base} does not match notify_source_pr target_branch "
f"{notification_target}."
)
@@ -135,7 +162,7 @@ def _validate_drafted_base_contract(
if actual_base != canonical_base:
raise OutcomeValidationError(
f"Drafted PR base branch {actual_base} does not match canonical "
- f"create_pull_request base_branch {canonical_base}."
+ f"create_pull_request target branch {canonical_base}."
)
diff --git a/.github/workflows/release-github-tasks.yml b/.github/workflows/release-github-tasks.yml
index 136f31a8dbf..012aed2a16a 100644
--- a/.github/workflows/release-github-tasks.yml
+++ b/.github/workflows/release-github-tasks.yml
@@ -192,10 +192,10 @@ jobs:
# --- App token and checkout (shared by all subsequent steps) ----------
# Mint the aspire-repo-bot App installation token. Used by every step
# that needs to fire a downstream event (release create, PR create,
- # branch push). Using the App token instead of the default GITHUB_TOKEN
- # causes the `release: released` event to actually trigger
- # release-notes-generate.lock.yml (events fired by GITHUB_TOKEN do not
- # cascade into other workflow runs).
+ # branch push) and to dispatch release-notes-generate. Using the App
+ # token instead of the default GITHUB_TOKEN is what lets those actions
+ # cascade into other workflow runs (events fired by GITHUB_TOKEN do not
+ # trigger further workflows).
- name: Generate GitHub App Token
id: app-token
uses: actions/create-github-app-token@1b10c78c7865c340bc4f6099eb2f838309f1e8c3 # v3.1.1
@@ -284,11 +284,15 @@ jobs:
run: |
# Write a short placeholder. The real release notes are generated
# asynchronously by the release-notes-generate agentic workflow,
- # which fires on the `release: [released]` event once `gh release
- # create` below publishes the release, and edits this body in
- # place.
+ # which we dispatch explicitly (via workflow_dispatch) right after
+ # creating the draft release below. It edits this body in place while
+ # the release is still a draft. (We can't rely on the
+ # `release: [created]` event because GitHub Actions does not fire
+ # release events for draft releases.) The release manager publishes
+ # the draft as a final manual step once both the notes and the CLI
+ # assets are attached.
cat << EOF > release_notes.md
- *Release notes are being generated automatically and will be added to this release shortly. If they haven't appeared within a few hours, ping the Aspire team.*
+ *This release is currently a draft. Release notes are being generated automatically and CLI assets are being uploaded — both will appear here within a few minutes. Once everything looks correct, the release manager will publish the draft. If notes or assets are missing after ~30 minutes, ping the Aspire team.*
---
*Full commit: [${{ inputs.commit_sha }}](https://github.com/${{ github.repository }}/commit/${{ inputs.commit_sha }})*
@@ -296,13 +300,14 @@ jobs:
echo "Placeholder release notes generated"
- - name: Create GitHub Release
+ - name: Create GitHub Release (draft)
if: inputs.skip_github_release != true && steps.check-release.outputs.release_exists != 'true'
env:
- # Use the App token here so the `release: released` event is
- # authored by aspire-repo-bot and downstream workflows
- # (release-notes-generate.lock.yml) get triggered. Events fired by
- # GITHUB_TOKEN intentionally do NOT trigger other workflows.
+ # Use the App token so the draft release is authored by
+ # aspire-repo-bot, consistent with the rest of the release flow.
+ # (release-notes-generate is triggered by an explicit
+ # workflow_dispatch in the next step, not by a release event —
+ # draft releases don't fire release events.)
GH_TOKEN: ${{ steps.app-token.outputs.token }}
run: |
TAG_NAME="v${{ inputs.release_version }}"
@@ -312,12 +317,21 @@ jobs:
PRERELEASE_FLAG="--prerelease"
fi
+ # IMPORTANT: We always create the release as a draft. Immutable
+ # releases (https://docs.github.com/en/code-security/concepts/supply-chain-security/immutable-releases)
+ # lock assets and the tag at publish time, so every mutation
+ # (release-notes-generate agentic workflow rewriting the body,
+ # PublishReleaseAssetsJob uploading aspire-cli-* archives) must
+ # happen before publish. A human publishes the draft as the final
+ # step after reviewing it — see docs/release-process.md "Publish
+ # the draft release" for the procedure.
if [ "$DRY_RUN" == "true" ]; then
- echo "🔍 [DRY RUN] Would create GitHub Release:"
+ echo "🔍 [DRY RUN] Would create DRAFT GitHub Release:"
echo " Tag: $TAG_NAME"
echo " Title: Aspire ${{ inputs.release_version }}"
echo " Target: ${{ inputs.commit_sha }}"
echo " Prerelease: ${{ inputs.is_prerelease }}"
+ echo " Draft: true"
echo ""
echo " Release notes content:"
echo " ─────────────────────────────────────"
@@ -325,14 +339,49 @@ jobs:
echo " ─────────────────────────────────────"
else
gh release create "$TAG_NAME" \
+ --draft \
--title "Aspire ${{ inputs.release_version }}" \
--notes-file release_notes.md \
--target "${{ inputs.commit_sha }}" \
$PRERELEASE_FLAG
- echo "✓ Created GitHub Release: $TAG_NAME"
+ echo "✓ Created DRAFT GitHub Release: $TAG_NAME"
+ echo " Release manager must publish the draft manually after notes + assets are attached."
fi
+ - name: Dispatch release-notes-generate workflow
+ # Draft releases do not fire the `release: [created]` event, so we
+ # explicitly dispatch the release-notes-generate agentic workflow to
+ # rewrite the placeholder body while the release is still a draft.
+ #
+ # We dispatch on every eligible non-dry run — including reruns where the
+ # draft already existed — and deliberately do NOT gate on
+ # `release_exists`. If a first run created the draft but died before
+ # dispatching, gating on `release_exists` would permanently skip note
+ # generation on the rerun and leave the placeholder body in place.
+ # Re-dispatching is safe: release-notes-generate is idempotent (it exits
+ # early unless the body is still the exact placeholder, and exits if the
+ # release was already published or edited), so a duplicate dispatch is a
+ # guaranteed no-op. We still skip on dry runs and when GitHub-release
+ # creation was skipped entirely.
+ if: inputs.skip_github_release != true && inputs.dry_run != true
+ env:
+ # The App token (aspire-repo-bot) is used so the dispatch is authored
+ # by the same identity the gh-aw workflow's `bots:` allow-list and
+ # GitHub App integration expect. Dispatching with GITHUB_TOKEN would
+ # run it as github-actions[bot], which the workflow's activation gate
+ # is not configured for.
+ GH_TOKEN: ${{ steps.app-token.outputs.token }}
+ run: |
+ TAG_NAME="v${{ inputs.release_version }}"
+ echo "Dispatching release-notes-generate for $TAG_NAME"
+ # The runnable workflow is the gh-aw-compiled lock file; dispatch it
+ # on the default branch (where workflow_dispatch requires it to live).
+ gh workflow run release-notes-generate.lock.yml \
+ --repo "${{ github.repository }}" \
+ --field tag_name="$TAG_NAME"
+ echo "✓ Dispatched release-notes-generate (tag_name=$TAG_NAME)"
+
# ----------------------------------------------------------------------------
# merge-pr: runs in parallel with baseline-pr after the release job. A
# failure here must NOT block baseline-pr (and vice versa) — that matches
@@ -643,10 +692,33 @@ jobs:
| Job | Result |
|-----|--------|
- | Release Tasks (tag + GitHub release) | ${RELEASE_STATUS} |
+ | Release Tasks (tag + draft GitHub release) | ${RELEASE_STATUS} |
| Create Merge-Back PR | ${MERGE_STATUS} |
| Create Baseline Version Branch/PR | ${BASELINE_STATUS} |
+ ## ⚠️ Manual step required — publish the draft release
+
+ The GitHub release was created as a **draft** so the release-notes-generate
+ agentic workflow can rewrite its body and the AzDO pipeline's
+ PublishReleaseAssetsJob can attach the \`aspire-cli-*\` archives before
+ publish. This is required for compatibility with GitHub's
+ [immutable releases](https://docs.github.com/en/code-security/concepts/supply-chain-security/immutable-releases),
+ which lock assets and the tag at publish time.
+
+ The release manager must, after both notes and assets are in place:
+
+ 1. Open the [Releases page](https://github.com/${{ github.repository }}/releases)
+ and find the draft for \`v${{ inputs.release_version }}\` at the
+ top (drafts are assigned a random \`untagged-\` URL by
+ GitHub, so there is no stable deep link until publish).
+ 2. Confirm the auto-generated release notes look correct.
+ 3. Confirm the \`aspire-cli-*\` archives are attached.
+ 4. Click **Publish release**.
+
+ Publishing the draft fires \`release: [published]\`, which triggers
+ downstream workflows such as \`release-update-support-mdx\` and
+ \`homebrew-validate-release\`.
+
## Details
- **Tag**: v${{ inputs.release_version }}
- **Commit**: \`${{ inputs.commit_sha }}\`
@@ -659,6 +731,6 @@ jobs:
- **Skip Baseline PR**: ${{ inputs.skip_baseline_pr }}
## Links
- - [Release](https://github.com/${{ github.repository }}/releases/tag/v${{ inputs.release_version }})
+ - [Releases page](https://github.com/${{ github.repository }}/releases)
- [Tag](https://github.com/${{ github.repository }}/tree/v${{ inputs.release_version }})
EOF
diff --git a/.github/workflows/release-notes-generate.lock.yml b/.github/workflows/release-notes-generate.lock.yml
index d8fcd461b3e..7f8ddb325c1 100644
--- a/.github/workflows/release-notes-generate.lock.yml
+++ b/.github/workflows/release-notes-generate.lock.yml
@@ -1,6 +1,6 @@
-# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"0764c1d16c5a3103aeda0d7b3de60fb59c933d361a8ecd2005c32e1d6eaca96b","body_hash":"f38b4c1674fbbd210f225c757a6a63f2b91fc2c9c0d4fb151b38a01b56c75288","compiler_version":"v0.85.4","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.78"}}
-# gh-aw-manifest: {"version":1,"secrets":["ASPIRE_BOT_APP_ID","ASPIRE_BOT_PRIVATE_KEY","COPILOT_GITHUB_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/checkout","sha":"3d3c42e5aac5ba805825da76410c181273ba90b1","version":"v7.0.1"},{"repo":"actions/create-github-app-token","sha":"bcd2ba49218906704ab6c1aa796996da409d3eb1","version":"v3.2.0"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"373c709c69115d41ff229c7e5df9f8788daa9553","version":"v9"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"820762786026740c76f36085b0efc47a31fe5020","version":"v7.0.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"2709137ea6c5b0e19aa621454dc643ea8dc526b1","version":"v0.85.4"}],"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.8","digest":"sha256:38bbea36cdb46a3c9d04d1db05e672966f5239b431a2022eb35881688e5721d8","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.4.8@sha256:38bbea36cdb46a3c9d04d1db05e672966f5239b431a2022eb35881688e5721d8"},{"image":"ghcr.io/github/gh-aw-node","digest":"sha256:0d9f1fb5fd6610c0ac1f5194a38e45a8a1e81f8a390d5142d8e4e6f26a4b3196","pinned_image":"ghcr.io/github/gh-aw-node@sha256:0d9f1fb5fd6610c0ac1f5194a38e45a8a1e81f8a390d5142d8e4e6f26a4b3196"},{"image":"ghcr.io/github/github-mcp-server:v1.8.0","digest":"sha256:d5a18c04b92714c309eb46a2305087e91a4dbd80420f6e462656699f95093520","pinned_image":"ghcr.io/github/github-mcp-server:v1.8.0@sha256:d5a18c04b92714c309eb46a2305087e91a4dbd80420f6e462656699f95093520"}]}
-# This file was automatically generated by gh-aw (v0.85.4). DO NOT EDIT. To debug this workflow, load the skill at https://github.com/github/gh-aw/blob/main/debug.md
+# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"a87b12aa0df1dc9ee2e5fa0c594afe12d840a825eefeb8bc9fbf1bed393d52d8","body_hash":"5443873cf7068d805c1ed767019bf3b649566a8518529b47e55d789d953aeadf","compiler_version":"v0.86.2","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.79"}}
+# gh-aw-manifest: {"version":1,"secrets":["ASPIRE_BOT_APP_ID","ASPIRE_BOT_PRIVATE_KEY","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/checkout","sha":"3d3c42e5aac5ba805825da76410c181273ba90b1","version":"v7.0.1"},{"repo":"actions/create-github-app-token","sha":"bcd2ba49218906704ab6c1aa796996da409d3eb1","version":"v3.2.0"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"373c709c69115d41ff229c7e5df9f8788daa9553","version":"v9"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"820762786026740c76f36085b0efc47a31fe5020","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"},{"image":"ghcr.io/github/github-mcp-server:v1.9.0","digest":"sha256:881b53d6f75f69bdbc1b5b10fc2f1361717c19054143b3a8529fb5c32061a50e","pinned_image":"ghcr.io/github/github-mcp-server:v1.9.0@sha256:881b53d6f75f69bdbc1b5b10fc2f1361717c19054143b3a8529fb5c32061a50e"}]}
+# 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
#
# ___ _ _
# / _ \ | | (_)
@@ -33,7 +33,6 @@
# Secrets used:
# - ASPIRE_BOT_APP_ID
# - ASPIRE_BOT_PRIVATE_KEY
-# - COPILOT_GITHUB_TOKEN
# - GH_AW_GITHUB_MCP_SERVER_TOKEN
# - GH_AW_GITHUB_TOKEN
# - GITHUB_TOKEN
@@ -46,23 +45,20 @@
# - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
# - actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
# - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
-# - github/gh-aw-actions/setup@2709137ea6c5b0e19aa621454dc643ea8dc526b1 # v0.85.4
+# - 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.8@sha256:38bbea36cdb46a3c9d04d1db05e672966f5239b431a2022eb35881688e5721d8
+# - ghcr.io/github/gh-aw-mcpg:v0.4.9@sha256:e5a1569aeaf41820fa7bdee3e94468cae448133cdbf00119ad24f5b74db1ab9f
# - ghcr.io/github/gh-aw-node@sha256:0d9f1fb5fd6610c0ac1f5194a38e45a8a1e81f8a390d5142d8e4e6f26a4b3196
-# - ghcr.io/github/github-mcp-server:v1.8.0@sha256:d5a18c04b92714c309eb46a2305087e91a4dbd80420f6e462656699f95093520
+# - ghcr.io/github/github-mcp-server:v1.9.0@sha256:881b53d6f75f69bdbc1b5b10fc2f1361717c19054143b3a8529fb5c32061a50e
name: "Generate release notes for a new stable Aspire release"
on:
# bots: # Bots processed as bot check in pre-activation job
# - aspire-repo-bot # Bots processed as bot check in pre-activation job
- release:
- types:
- - published
# stale-check: false # Stale-check processed as frontmatter hash check step in activation job
workflow_dispatch:
inputs:
@@ -80,18 +76,14 @@ permissions: {}
concurrency:
cancel-in-progress: false
- group: release-notes-generate-${{ github.event.release.tag_name || github.event.inputs.tag_name }}
+ group: release-notes-generate-${{ github.event.inputs.tag_name }}
run-name: "Generate release notes for a new stable Aspire release"
jobs:
activation:
needs: pre_activation
- if: >
- needs.pre_activation.outputs.activated == 'true' && (github.repository == 'microsoft/aspire' && (
- (github.event_name == 'release' && github.event.release.prerelease == false && github.event.release.draft == false)
- || github.event_name == 'workflow_dispatch'
- ))
+ if: needs.pre_activation.outputs.activated == 'true' && (github.repository == 'microsoft/aspire')
runs-on: ubuntu-slim
permissions:
contents: read
@@ -110,7 +102,7 @@ jobs:
steps:
- name: Setup Scripts
id: setup
- uses: github/gh-aw-actions/setup@2709137ea6c5b0e19aa621454dc643ea8dc526b1 # v0.85.4
+ uses: github/gh-aw-actions/setup@6aab9e5b5c91c615506061f09bedd81a23babe3c # v0.86.2
with:
destination: ${{ runner.temp }}/gh-aw/actions
job-name: ${{ github.job }}
@@ -119,7 +111,7 @@ jobs:
env:
GH_AW_SETUP_WORKFLOW_NAME: "Generate release notes for a new stable Aspire release"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/release-notes-generate.lock.yml@${{ github.ref }}
- GH_AW_INFO_VERSION: "1.0.78"
+ 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
@@ -128,9 +120,9 @@ jobs:
GH_AW_INFO_ENGINE_ID: "copilot"
GH_AW_INFO_ENGINE_NAME: "GitHub Copilot CLI"
GH_AW_INFO_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || vars.GH_AW_DEFAULT_MODEL_COPILOT || 'auto' }}
- GH_AW_INFO_VERSION: "1.0.78"
- GH_AW_INFO_AGENT_VERSION: "1.0.78"
- GH_AW_INFO_CLI_VERSION: "v0.85.4"
+ 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: "Generate release notes for a new stable Aspire release"
GH_AW_INFO_EXPERIMENTAL: "false"
GH_AW_INFO_SUPPORTS_TOOLS_ALLOWLIST: "true"
@@ -140,6 +132,7 @@ jobs:
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_COMPILED_STRICT: "true"
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
@@ -152,7 +145,6 @@ jobs:
id: check-oauth-tokens
run: bash "${RUNNER_TEMP}/gh-aw/actions/check_oauth_tokens.sh"
env:
- COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
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
@@ -172,12 +164,12 @@ jobs:
env:
GH_AW_AGENT_FOLDERS: ".agents .github"
GH_AW_AGENT_FILES: "AGENTS.md"
- # poutine:ignore untrusted_checkout_exec
- run: bash "${RUNNER_TEMP}/gh-aw/actions/save_base_github_folders.sh"
+ run: |
+ bash "${RUNNER_TEMP}/gh-aw/actions/save_base_github_folders.sh"
- name: Check compile-agentic version
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
- GH_AW_COMPILED_VERSION: "v0.85.4"
+ GH_AW_COMPILED_VERSION: "v0.86.2"
with:
script: |
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
@@ -188,85 +180,39 @@ jobs:
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_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ 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\"},{\"file\":\"github_mcp_tools_with_safeoutputs_prompt.md\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0004\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0005\"}]}"
GH_AW_EXPR_1A3A194A: ${{ github.event.discussion.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'discussion' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }}
GH_AW_EXPR_463A214A: ${{ github.event.pull_request.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'pull_request' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }}
- GH_AW_EXPR_7F72DC02: ${{ github.event.release.tag_name || github.event.inputs.tag_name }}
GH_AW_EXPR_802A9F6A: ${{ github.event.issue.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'issue' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }}
GH_AW_EXPR_FF1D34CE: ${{ github.event.comment.id || fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').comment_id }}
GH_AW_GITHUB_ACTOR: ${{ github.actor }}
GH_AW_GITHUB_EVENT_INPUTS_TAG_NAME: ${{ github.event.inputs.tag_name }}
- GH_AW_GITHUB_EVENT_NAME: ${{ github.event_name }}
- GH_AW_GITHUB_EVENT_RELEASE_NAME: ${{ github.event.release.name }}
- GH_AW_GITHUB_EVENT_RELEASE_TAG_NAME: ${{ github.event.release.tag_name }}
GH_AW_GITHUB_REPOSITORY: ${{ github.repository }}
GH_AW_GITHUB_RUN_ID: ${{ github.run_id }}
GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }}
- # poutine:ignore untrusted_checkout_exec
- run: |
- bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh"
- {
- cat << 'GH_AW_PROMPT_79d56285e61f5d49_EOF'
-
- GH_AW_PROMPT_79d56285e61f5d49_EOF
- cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md"
- cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md"
- cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md"
- cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md"
- cat << 'GH_AW_PROMPT_79d56285e61f5d49_EOF'
-
- Tools: update_release, missing_tool, missing_data, noop
-
- GH_AW_PROMPT_79d56285e61f5d49_EOF
- cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md"
- cat << 'GH_AW_PROMPT_79d56285e61f5d49_EOF'
-
- The following GitHub context information is available for this workflow:
- {{#if github.actor}}
- - **actor**: __GH_AW_GITHUB_ACTOR__
- {{/if}}
- {{#if github.repository}}
- - **repository**: __GH_AW_GITHUB_REPOSITORY__
- {{/if}}
- {{#if github.workspace}}
- - **workspace**: __GH_AW_GITHUB_WORKSPACE__
- {{/if}}
- {{#if github.event.issue.number || (github.aw.context.item_type == 'issue' && github.aw.context.item_number)}}
- - **issue-number**: #__GH_AW_EXPR_802A9F6A__
- {{/if}}
- {{#if github.event.discussion.number || (github.aw.context.item_type == 'discussion' && github.aw.context.item_number)}}
- - **discussion-number**: #__GH_AW_EXPR_1A3A194A__
- {{/if}}
- {{#if github.event.pull_request.number || (github.aw.context.item_type == 'pull_request' && github.aw.context.item_number)}}
- - **pull-request-number**: #__GH_AW_EXPR_463A214A__
- {{/if}}
- {{#if github.event.comment.id || github.aw.context.comment_id}}
- - **comment-id**: __GH_AW_EXPR_FF1D34CE__
- {{/if}}
- {{#if github.run_id}}
- - **workflow-run-id**: __GH_AW_GITHUB_RUN_ID__
- {{/if}}
-
-
- GH_AW_PROMPT_79d56285e61f5d49_EOF
- cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md"
- cat << 'GH_AW_PROMPT_79d56285e61f5d49_EOF'
-
- {{#runtime-import .github/workflows/release-notes-generate.md}}
- GH_AW_PROMPT_79d56285e61f5d49_EOF
- } > "$GH_AW_PROMPT"
+ GH_AW_PROMPT_CONTENT_0000: "\n"
+ GH_AW_PROMPT_CONTENT_0001: "\nTools: update_release, missing_tool, missing_data, noop\n"
+ GH_AW_PROMPT_CONTENT_0002: "\n"
+ GH_AW_PROMPT_CONTENT_0003: "\nThe following GitHub context information is available for this workflow:\n{{#if github.actor}}\n- **actor**: __GH_AW_GITHUB_ACTOR__\n{{/if}}\n{{#if github.repository}}\n- **repository**: __GH_AW_GITHUB_REPOSITORY__\n{{/if}}\n{{#if github.workspace}}\n- **workspace**: __GH_AW_GITHUB_WORKSPACE__\n{{/if}}\n{{#if github.event.issue.number || (github.aw.context.item_type == 'issue' && github.aw.context.item_number)}}\n- **issue-number**: #__GH_AW_EXPR_802A9F6A__\n{{/if}}\n{{#if github.event.discussion.number || (github.aw.context.item_type == 'discussion' && github.aw.context.item_number)}}\n- **discussion-number**: #__GH_AW_EXPR_1A3A194A__\n{{/if}}\n{{#if github.event.pull_request.number || (github.aw.context.item_type == 'pull_request' && github.aw.context.item_number)}}\n- **pull-request-number**: #__GH_AW_EXPR_463A214A__\n{{/if}}\n{{#if github.event.comment.id || github.aw.context.comment_id}}\n- **comment-id**: __GH_AW_EXPR_FF1D34CE__\n{{/if}}\n{{#if github.run_id}}\n- **workflow-run-id**: __GH_AW_GITHUB_RUN_ID__\n{{/if}}\n\n\n"
+ GH_AW_PROMPT_CONTENT_0004: "\n"
+ GH_AW_PROMPT_CONTENT_0005: "{{#runtime-import .github/workflows/release-notes-generate.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: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_PROMPT: ${{ runner.temp }}/gh-aw/aw-prompts/prompt.txt
GH_AW_ENGINE_ID: "copilot"
GH_AW_GITHUB_EVENT_INPUTS_TAG_NAME: ${{ github.event.inputs.tag_name }}
- GH_AW_GITHUB_EVENT_RELEASE_NAME: ${{ github.event.release.name }}
- GH_AW_EXPR_7F72DC02: ${{ github.event.release.tag_name || github.event.inputs.tag_name }}
- GH_AW_GITHUB_EVENT_RELEASE_TAG_NAME: ${{ github.event.release.tag_name }}
- GH_AW_GITHUB_EVENT_NAME: ${{ github.event_name }}
with:
script: |
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
@@ -276,17 +222,13 @@ jobs:
- name: Substitute placeholders
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
- GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_PROMPT: ${{ runner.temp }}/gh-aw/aw-prompts/prompt.txt
GH_AW_EXPR_1A3A194A: ${{ github.event.discussion.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'discussion' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }}
GH_AW_EXPR_463A214A: ${{ github.event.pull_request.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'pull_request' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }}
- GH_AW_EXPR_7F72DC02: ${{ github.event.release.tag_name || github.event.inputs.tag_name }}
GH_AW_EXPR_802A9F6A: ${{ github.event.issue.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'issue' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }}
GH_AW_EXPR_FF1D34CE: ${{ github.event.comment.id || fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').comment_id }}
GH_AW_GITHUB_ACTOR: ${{ github.actor }}
GH_AW_GITHUB_EVENT_INPUTS_TAG_NAME: ${{ github.event.inputs.tag_name }}
- GH_AW_GITHUB_EVENT_NAME: ${{ github.event_name }}
- GH_AW_GITHUB_EVENT_RELEASE_NAME: ${{ github.event.release.name }}
- GH_AW_GITHUB_EVENT_RELEASE_TAG_NAME: ${{ github.event.release.tag_name }}
GH_AW_GITHUB_REPOSITORY: ${{ github.repository }}
GH_AW_GITHUB_RUN_ID: ${{ github.run_id }}
GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }}
@@ -305,14 +247,10 @@ jobs:
substitutions: {
GH_AW_EXPR_1A3A194A: process.env.GH_AW_EXPR_1A3A194A,
GH_AW_EXPR_463A214A: process.env.GH_AW_EXPR_463A214A,
- GH_AW_EXPR_7F72DC02: process.env.GH_AW_EXPR_7F72DC02,
GH_AW_EXPR_802A9F6A: process.env.GH_AW_EXPR_802A9F6A,
GH_AW_EXPR_FF1D34CE: process.env.GH_AW_EXPR_FF1D34CE,
GH_AW_GITHUB_ACTOR: process.env.GH_AW_GITHUB_ACTOR,
GH_AW_GITHUB_EVENT_INPUTS_TAG_NAME: process.env.GH_AW_GITHUB_EVENT_INPUTS_TAG_NAME,
- GH_AW_GITHUB_EVENT_NAME: process.env.GH_AW_GITHUB_EVENT_NAME,
- GH_AW_GITHUB_EVENT_RELEASE_NAME: process.env.GH_AW_GITHUB_EVENT_RELEASE_NAME,
- GH_AW_GITHUB_EVENT_RELEASE_TAG_NAME: process.env.GH_AW_GITHUB_EVENT_RELEASE_TAG_NAME,
GH_AW_GITHUB_REPOSITORY: process.env.GH_AW_GITHUB_REPOSITORY,
GH_AW_GITHUB_RUN_ID: process.env.GH_AW_GITHUB_RUN_ID,
GH_AW_GITHUB_WORKSPACE: process.env.GH_AW_GITHUB_WORKSPACE,
@@ -322,14 +260,18 @@ jobs:
});
- name: Validate prompt placeholders
env:
- GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
- # poutine:ignore untrusted_checkout_exec
- run: bash "${RUNNER_TEMP}/gh-aw/actions/validate_prompt_placeholders.sh"
+ 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: /tmp/gh-aw/aw-prompts/prompt.txt
- # poutine:ignore untrusted_checkout_exec
- run: bash "${RUNNER_TEMP}/gh-aw/actions/print_prompt_summary.sh"
+ 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
@@ -356,9 +298,6 @@ jobs:
contents: read
copilot-requests: write
pull-requests: read
- concurrency:
- group: "gh-aw-copilot-${{ github.workflow }}"
- queue: max
env:
DEFAULT_BRANCH: ${{ github.event.repository.default_branch }}
GH_AW_ASSETS_ALLOWED_EXTS: ""
@@ -393,7 +332,7 @@ jobs:
steps:
- name: Setup Scripts
id: setup
- uses: github/gh-aw-actions/setup@2709137ea6c5b0e19aa621454dc643ea8dc526b1 # v0.85.4
+ uses: github/gh-aw-actions/setup@6aab9e5b5c91c615506061f09bedd81a23babe3c # v0.86.2
with:
destination: ${{ runner.temp }}/gh-aw/actions
job-name: ${{ github.job }}
@@ -402,7 +341,7 @@ jobs:
env:
GH_AW_SETUP_WORKFLOW_NAME: "Generate release notes for a new stable Aspire release"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/release-notes-generate.lock.yml@${{ github.ref }}
- GH_AW_INFO_VERSION: "1.0.78"
+ 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
@@ -448,11 +387,13 @@ jobs:
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.85.4
+ 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: Generate GitHub App token
@@ -501,7 +442,7 @@ jobs:
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.8@sha256:38bbea36cdb46a3c9d04d1db05e672966f5239b431a2022eb35881688e5721d8 ghcr.io/github/gh-aw-node@sha256:0d9f1fb5fd6610c0ac1f5194a38e45a8a1e81f8a390d5142d8e4e6f26a4b3196 ghcr.io/github/github-mcp-server:v1.8.0@sha256:d5a18c04b92714c309eb46a2305087e91a4dbd80420f6e462656699f95093520
+ 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 ghcr.io/github/github-mcp-server:v1.9.0@sha256:881b53d6f75f69bdbc1b5b10fc2f1361717c19054143b3a8529fb5c32061a50e
- name: Generate Safe Outputs Config
run: |
mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs"
@@ -653,22 +594,23 @@ jobs:
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"
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 -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.8'
+ 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_c3984b671fa9f53f_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs"
+ cat << GH_AW_MCP_CONFIG_5614418005a60134_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs"
{
"mcpServers": {
"github": {
"type": "stdio",
- "container": "ghcr.io/github/github-mcp-server:v1.8.0",
+ "container": "ghcr.io/github/github-mcp-server:v1.9.0",
"env": {
"GITHUB_FEATURES": "fields_param",
"GITHUB_HOST": "${GITHUB_SERVER_URL}",
@@ -730,7 +672,7 @@ jobs:
"startupTimeout": 120
}
}
- GH_AW_MCP_CONFIG_c3984b671fa9f53f_EOF
+ GH_AW_MCP_CONFIG_5614418005a60134_EOF
- name: Mount MCP servers as CLIs
id: mount-mcp-clis
continue-on-error: true
@@ -755,6 +697,24 @@ jobs:
- name: Execute GitHub Copilot CLI
id: agentic_execution
# Copilot CLI tool arguments (sorted):
+ # --allow-tool github
+ # --allow-tool safeoutputs
+ # --allow-tool shell(cat)
+ # --allow-tool shell(date)
+ # --allow-tool shell(echo)
+ # --allow-tool shell(github:*)
+ # --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(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
@@ -764,6 +724,18 @@ jobs:
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
@@ -788,8 +760,8 @@ jobs:
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 GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_API_KEY --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 /usr/local/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 --allow-all-paths --add-dir "${GITHUB_WORKSPACE}" --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log
+ 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 GITHUB_MCP_SERVER_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 github --allow-tool safeoutputs --allow-tool '\''shell(cat)'\'' --allow-tool '\''shell(date)'\'' --allow-tool '\''shell(echo)'\'' --allow-tool '\''shell(github:*)'\'' --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(sort)'\'' --allow-tool '\''shell(tail)'\'' --allow-tool '\''shell(uniq)'\'' --allow-tool '\''shell(wc)'\'' --allow-tool '\''shell(yq)'\'' --allow-tool write --allow-all-paths --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
@@ -803,7 +775,7 @@ jobs:
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.85.4
+ GH_AW_VERSION: v0.86.2
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
GITHUB_COPILOT_INTEGRATION_ID: agentic-workflows
@@ -995,7 +967,7 @@ jobs:
steps:
- name: Setup Scripts
id: setup
- uses: github/gh-aw-actions/setup@2709137ea6c5b0e19aa621454dc643ea8dc526b1 # v0.85.4
+ uses: github/gh-aw-actions/setup@6aab9e5b5c91c615506061f09bedd81a23babe3c # v0.86.2
with:
destination: ${{ runner.temp }}/gh-aw/actions
job-name: ${{ github.job }}
@@ -1004,7 +976,7 @@ jobs:
env:
GH_AW_SETUP_WORKFLOW_NAME: "Generate release notes for a new stable Aspire release"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/release-notes-generate.lock.yml@${{ github.ref }}
- GH_AW_INFO_VERSION: "1.0.78"
+ 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
@@ -1201,7 +1173,7 @@ jobs:
steps:
- name: Setup Scripts
id: setup
- uses: github/gh-aw-actions/setup@2709137ea6c5b0e19aa621454dc643ea8dc526b1 # v0.85.4
+ uses: github/gh-aw-actions/setup@6aab9e5b5c91c615506061f09bedd81a23babe3c # v0.86.2
with:
destination: ${{ runner.temp }}/gh-aw/actions
job-name: ${{ github.job }}
@@ -1210,7 +1182,7 @@ jobs:
env:
GH_AW_SETUP_WORKFLOW_NAME: "Generate release notes for a new stable Aspire release"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/release-notes-generate.lock.yml@${{ github.ref }}
- GH_AW_INFO_VERSION: "1.0.78"
+ 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
@@ -1262,25 +1234,7 @@ jobs:
- name: Prepare threat detection files
if: always() && steps.detection_guard.outputs.run_detection == 'true'
run: |
- mkdir -p /tmp/gh-aw/threat-detection/aw-prompts
- rm -f /tmp/gh-aw/agent_usage.json
- cp /tmp/gh-aw/aw-prompts/prompt.txt /tmp/gh-aw/threat-detection/aw-prompts/prompt.txt 2>/dev/null || true
- if [ ! -s /tmp/gh-aw/threat-detection/aw-prompts/prompt.txt ]; then
- echo "::warning::ERR_VALIDATION: Missing or empty detection context prompt at /tmp/gh-aw/threat-detection/aw-prompts/prompt.txt. Ensure the agent artifact includes /tmp/gh-aw/aw-prompts/prompt.txt. Detection will continue with fallback workflow context."
- fi
- cp /tmp/gh-aw/agent_output.json /tmp/gh-aw/threat-detection/agent_output.json 2>/dev/null || true
- for f in /tmp/gh-aw/aw-*.patch; do
- if [ -f "$f" ]; then
- cp "$f" /tmp/gh-aw/threat-detection/ 2>/dev/null || true
- fi
- done
- for f in /tmp/gh-aw/aw-*.bundle; do
- if [ -f "$f" ]; then
- cp "$f" /tmp/gh-aw/threat-detection/ 2>/dev/null || true
- fi
- done
- echo "Prepared threat detection files:"
- ls -la /tmp/gh-aw/threat-detection/ 2>/dev/null || true
+ 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
@@ -1300,18 +1254,20 @@ jobs:
run: |
mkdir -p /tmp/gh-aw/threat-detection
touch /tmp/gh-aw/threat-detection/detection.log
- rm -f /tmp/gh-aw/threat-detection/step-summary.md
- touch /tmp/gh-aw/threat-detection/step-summary.md
+ 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.85.4
+ 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
@@ -1327,6 +1283,18 @@ jobs:
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
@@ -1353,9 +1321,10 @@ jobs:
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 --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 /usr/local/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 --add-dir "${GITHUB_WORKSPACE}" --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' 2>&1 | tee -a /tmp/gh-aw/threat-detection/detection.log
+ 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 --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
@@ -1367,14 +1336,13 @@ jobs:
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_TIMEOUT_MINUTES: 20
- GH_AW_VERSION: v0.85.4
+ 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]
@@ -1383,6 +1351,23 @@ jobs:
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()
@@ -1437,11 +1422,7 @@ jobs:
}
pre_activation:
- if: >
- github.repository == 'microsoft/aspire' && (
- (github.event_name == 'release' && github.event.release.prerelease == false && github.event.release.draft == false)
- || github.event_name == 'workflow_dispatch'
- )
+ if: github.repository == 'microsoft/aspire'
runs-on: ubuntu-slim
env:
GH_AW_RUNTIME_FEATURES: ${{ vars.GH_AW_RUNTIME_FEATURES }}
@@ -1454,14 +1435,14 @@ jobs:
steps:
- name: Setup Scripts
id: setup
- uses: github/gh-aw-actions/setup@2709137ea6c5b0e19aa621454dc643ea8dc526b1 # v0.85.4
+ 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: "Generate release notes for a new stable Aspire release"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/release-notes-generate.lock.yml@${{ github.ref }}
- GH_AW_INFO_VERSION: "1.0.78"
+ GH_AW_INFO_VERSION: "1.0.79"
GH_AW_INFO_AWF_VERSION: "v0.27.44"
GH_AW_INFO_ENGINE_ID: "copilot"
- name: Check team membership for workflow
@@ -1509,15 +1490,20 @@ jobs:
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@2709137ea6c5b0e19aa621454dc643ea8dc526b1 # v0.85.4
+ uses: github/gh-aw-actions/setup@6aab9e5b5c91c615506061f09bedd81a23babe3c # v0.86.2
with:
destination: ${{ runner.temp }}/gh-aw/actions
job-name: ${{ github.job }}
@@ -1526,7 +1512,7 @@ jobs:
env:
GH_AW_SETUP_WORKFLOW_NAME: "Generate release notes for a new stable Aspire release"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/release-notes-generate.lock.yml@${{ github.ref }}
- GH_AW_INFO_VERSION: "1.0.78"
+ 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
diff --git a/.github/workflows/release-notes-generate.md b/.github/workflows/release-notes-generate.md
index 33a2132fadb..92a147f7028 100644
--- a/.github/workflows/release-notes-generate.md
+++ b/.github/workflows/release-notes-generate.md
@@ -10,8 +10,16 @@ description: |
max-daily-ai-credits: -1
on:
- release:
- types: [published]
+ # Dispatched explicitly by .github/workflows/release-github-tasks.yml right
+ # after it creates the draft GitHub release. We deliberately do NOT use the
+ # `release: [created]` event: GitHub Actions does not fire release events for
+ # draft releases at all
+ # (https://docs.github.com/en/actions/reference/workflows-and-actions/events-that-trigger-workflows#release
+ # — "Workflows are not triggered for the created, edited, or deleted activity
+ # types for draft releases"). The placeholder body has to be rewritten while
+ # the release is still a draft, because immutable releases lock the release
+ # at publish time, so an explicit workflow_dispatch is the only workable
+ # trigger.
workflow_dispatch:
inputs:
tag_name:
@@ -29,18 +37,13 @@ on:
# other bot-triggered gh-aw workflows in this repo.
bots: [aspire-repo-bot]
-if: >-
- github.repository == 'microsoft/aspire'
- && (
- (github.event_name == 'release' && github.event.release.prerelease == false && github.event.release.draft == false)
- || github.event_name == 'workflow_dispatch'
- )
+if: github.repository == 'microsoft/aspire'
-# Serialize runs for the same tag so that a duplicate release event (or a
-# manual workflow_dispatch rerun on top of an in-flight automatic run) can't
-# race and double-edit the release body.
+# Serialize runs for the same tag so that a manual workflow_dispatch rerun on
+# top of an in-flight automatic dispatch can't race and double-edit the
+# release body.
concurrency:
- group: release-notes-generate-${{ github.event.release.tag_name || github.event.inputs.tag_name }}
+ group: release-notes-generate-${{ github.event.inputs.tag_name }}
cancel-in-progress: false
# Agent runs read-only; the release-body update is performed by a separate,
@@ -66,6 +69,9 @@ safe-outputs:
max: 1
tools:
+ # Shell access is explicit because the unfiltered GitHub integrity setting
+ # requires an intentional allowlist.
+ bash: ["cat", "ls", "grep", "head", "tail", "wc"]
github:
# `repos` exposes get_release_by_tag / list_releases and commit-comparison
# APIs. `pull_requests` and `search` are used to enrich commits with PR
@@ -93,46 +99,54 @@ timeout-minutes: 20
# Generate release notes for a new stable Aspire release
-The GitHub Release for this tag was just created by
+The GitHub Release for this tag was just created **as a draft** by
`.github/workflows/release-github-tasks.yml` with a short placeholder body.
Your job is to replace that placeholder with real, human-readable release
notes that match the tone and structure of recent stable Aspire releases.
-
-The release is already published, so for **benign no-op cases** (release
-missing, prerelease/draft, tag doesn't match `vX.Y.Z`, body has already
-been edited and no longer contains the placeholder phrase) write a clear
-diagnostic to the run summary and **exit successfully**. But for **real
-errors** when actually trying to update the release (API rejection,
-permission denied on `update_release`, malformed payload, etc.) **fail the
-workflow** — a maintainer needs to see a red X so they can investigate or
-manually backfill. Do **not** open issues to "ask a maintainer to paste
-notes" as a fallback; the workflow has no `create_issue` capability by
-design.
+The release manager will manually publish the draft as a final step once
+both notes and CLI assets are attached.
+
+The release is still a draft, so for **benign no-op cases** (release
+missing, prerelease, tag doesn't match `vX.Y.Z`, body has already been
+edited and no longer contains the placeholder phrase, **or the release is
+no longer a draft because the release manager already published it**)
+write a clear diagnostic to the run summary and **exit successfully**.
+But for **real errors** when actually trying to update the release (API
+rejection, permission denied on `update_release`, malformed payload, etc.)
+**fail the workflow** — a maintainer needs to see a red X so they can
+investigate or manually backfill. Do **not** open issues to "ask a
+maintainer to paste notes" as a fallback; the workflow has no
+`create_issue` capability by design.
## Context
- **Repository**: `microsoft/aspire`
-- **Trigger event**: `${{ github.event_name }}`
-- **Release tag**: `${{ github.event.release.tag_name || github.event.inputs.tag_name }}`
-- **Release name**: `${{ github.event.release.name }}`
+- **Release tag**: `${{ github.event.inputs.tag_name }}`
## Step 1: Resolve the release
-Determine the tag this run is processing:
-
-- If `github.event_name == 'release'`, the tag is in `${{ github.event.release.tag_name }}`.
-- If `github.event_name == 'workflow_dispatch'`, the tag is in `${{ github.event.inputs.tag_name }}`.
+The tag this run is processing is in `${{ github.event.inputs.tag_name }}`
+(this workflow is always dispatched via `workflow_dispatch` with that input).
Fetch the full release record for `microsoft/aspire` by tag
(`GET /repos/microsoft/aspire/releases/tags/`). Capture its `id`,
`tag_name`, `name`, `body`, `published_at`, `html_url`, `draft`, and
-`prerelease`.
+`prerelease`. The workflow runs with a GitHub App token that can see
+drafts in `microsoft/aspire`, so this call returns the draft record that
+`release-github-tasks.yml` created just before dispatching this workflow.
**Exit successfully with a diagnostic** if any of these are true (do not
-fail the run — the release is already live):
+fail the run — these are expected states the workflow shouldn't act on):
- The release can't be found.
-- `release.draft == true` or `release.prerelease == true`.
+- `release.draft == false` — the release manager has already published the
+ draft, so the body should no longer be overwritten by automation. If
+ this run was a `workflow_dispatch` rerun on a published release, the
+ expectation is that a human has reviewed the notes and explicitly chose
+ to publish; another rewrite would clobber human edits. Direct the
+ maintainer to edit the release body manually if a correction is needed.
+- `release.prerelease == true` — release-notes-generate is a stable-only
+ workflow.
- The tag does not match `^v\d+\.\d+\.\d+$`.
Parse the version: strip the leading `v` and split into
@@ -286,7 +300,9 @@ Two distinct failure classes — handle them differently:
These are the early-exit cases already covered by Steps 1 and 2:
- Release not found by tag.
-- `release.draft == true` or `release.prerelease == true`.
+- `release.draft == false` (release manager already published the draft —
+ body is no longer safe to overwrite by automation).
+- `release.prerelease == true`.
- Tag does not match `^v\d+\.\d+\.\d+$`.
- Release body has already been edited (does not contain the placeholder
phrase) — Step 2 idempotency check.
diff --git a/.github/workflows/release-update-support-mdx.lock.yml b/.github/workflows/release-update-support-mdx.lock.yml
index db093386e92..28507045105 100644
--- a/.github/workflows/release-update-support-mdx.lock.yml
+++ b/.github/workflows/release-update-support-mdx.lock.yml
@@ -1,6 +1,6 @@
-# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"8062e35148345efde4f53e5e42b964cde11e880ffc8e831241b7a9983028a0b9","body_hash":"ebac7ee631141acb8a4a1cd85e5a562c48891c52fee06cce3b5b10d02effa477","compiler_version":"v0.85.4","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.78"}}
-# gh-aw-manifest: {"version":1,"secrets":["ASPIRE_BOT_APP_ID","ASPIRE_BOT_PRIVATE_KEY","COPILOT_GITHUB_TOKEN","GH_AW_CI_TRIGGER_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/checkout","sha":"3d3c42e5aac5ba805825da76410c181273ba90b1","version":"v7.0.1"},{"repo":"actions/create-github-app-token","sha":"bcd2ba49218906704ab6c1aa796996da409d3eb1","version":"v3.2.0"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"373c709c69115d41ff229c7e5df9f8788daa9553","version":"v9"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"820762786026740c76f36085b0efc47a31fe5020","version":"v7.0.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"2709137ea6c5b0e19aa621454dc643ea8dc526b1","version":"v0.85.4"}],"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.8","digest":"sha256:38bbea36cdb46a3c9d04d1db05e672966f5239b431a2022eb35881688e5721d8","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.4.8@sha256:38bbea36cdb46a3c9d04d1db05e672966f5239b431a2022eb35881688e5721d8"},{"image":"ghcr.io/github/gh-aw-node","digest":"sha256:0d9f1fb5fd6610c0ac1f5194a38e45a8a1e81f8a390d5142d8e4e6f26a4b3196","pinned_image":"ghcr.io/github/gh-aw-node@sha256:0d9f1fb5fd6610c0ac1f5194a38e45a8a1e81f8a390d5142d8e4e6f26a4b3196"},{"image":"ghcr.io/github/github-mcp-server:v1.8.0","digest":"sha256:d5a18c04b92714c309eb46a2305087e91a4dbd80420f6e462656699f95093520","pinned_image":"ghcr.io/github/github-mcp-server:v1.8.0@sha256:d5a18c04b92714c309eb46a2305087e91a4dbd80420f6e462656699f95093520"}]}
-# This file was automatically generated by gh-aw (v0.85.4). DO NOT EDIT. To debug this workflow, load the skill at https://github.com/github/gh-aw/blob/main/debug.md
+# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"8062e35148345efde4f53e5e42b964cde11e880ffc8e831241b7a9983028a0b9","body_hash":"ebac7ee631141acb8a4a1cd85e5a562c48891c52fee06cce3b5b10d02effa477","compiler_version":"v0.86.2","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.79"}}
+# gh-aw-manifest: {"version":1,"secrets":["ASPIRE_BOT_APP_ID","ASPIRE_BOT_PRIVATE_KEY","GH_AW_CI_TRIGGER_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/checkout","sha":"3d3c42e5aac5ba805825da76410c181273ba90b1","version":"v7.0.1"},{"repo":"actions/create-github-app-token","sha":"bcd2ba49218906704ab6c1aa796996da409d3eb1","version":"v3.2.0"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"373c709c69115d41ff229c7e5df9f8788daa9553","version":"v9"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"820762786026740c76f36085b0efc47a31fe5020","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"},{"image":"ghcr.io/github/github-mcp-server:v1.9.0","digest":"sha256:881b53d6f75f69bdbc1b5b10fc2f1361717c19054143b3a8529fb5c32061a50e","pinned_image":"ghcr.io/github/github-mcp-server:v1.9.0@sha256:881b53d6f75f69bdbc1b5b10fc2f1361717c19054143b3a8529fb5c32061a50e"}]}
+# 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
#
# ___ _ _
# / _ \ | | (_)
@@ -36,7 +36,6 @@
# Secrets used:
# - ASPIRE_BOT_APP_ID
# - ASPIRE_BOT_PRIVATE_KEY
-# - COPILOT_GITHUB_TOKEN
# - GH_AW_CI_TRIGGER_TOKEN
# - GH_AW_GITHUB_MCP_SERVER_TOKEN
# - GH_AW_GITHUB_TOKEN
@@ -50,15 +49,15 @@
# - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
# - actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
# - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
-# - github/gh-aw-actions/setup@2709137ea6c5b0e19aa621454dc643ea8dc526b1 # v0.85.4
+# - 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.8@sha256:38bbea36cdb46a3c9d04d1db05e672966f5239b431a2022eb35881688e5721d8
+# - ghcr.io/github/gh-aw-mcpg:v0.4.9@sha256:e5a1569aeaf41820fa7bdee3e94468cae448133cdbf00119ad24f5b74db1ab9f
# - ghcr.io/github/gh-aw-node@sha256:0d9f1fb5fd6610c0ac1f5194a38e45a8a1e81f8a390d5142d8e4e6f26a4b3196
-# - ghcr.io/github/github-mcp-server:v1.8.0@sha256:d5a18c04b92714c309eb46a2305087e91a4dbd80420f6e462656699f95093520
+# - ghcr.io/github/github-mcp-server:v1.9.0@sha256:881b53d6f75f69bdbc1b5b10fc2f1361717c19054143b3a8529fb5c32061a50e
name: "Update aspire.dev support page for a new Aspire release"
on:
@@ -114,7 +113,7 @@ jobs:
steps:
- name: Setup Scripts
id: setup
- uses: github/gh-aw-actions/setup@2709137ea6c5b0e19aa621454dc643ea8dc526b1 # v0.85.4
+ uses: github/gh-aw-actions/setup@6aab9e5b5c91c615506061f09bedd81a23babe3c # v0.86.2
with:
destination: ${{ runner.temp }}/gh-aw/actions
job-name: ${{ github.job }}
@@ -123,7 +122,7 @@ jobs:
env:
GH_AW_SETUP_WORKFLOW_NAME: "Update aspire.dev support page for a new Aspire release"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/release-update-support-mdx.lock.yml@${{ github.ref }}
- GH_AW_INFO_VERSION: "1.0.78"
+ 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
@@ -132,9 +131,9 @@ jobs:
GH_AW_INFO_ENGINE_ID: "copilot"
GH_AW_INFO_ENGINE_NAME: "GitHub Copilot CLI"
GH_AW_INFO_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || vars.GH_AW_DEFAULT_MODEL_COPILOT || 'auto' }}
- GH_AW_INFO_VERSION: "1.0.78"
- GH_AW_INFO_AGENT_VERSION: "1.0.78"
- GH_AW_INFO_CLI_VERSION: "v0.85.4"
+ 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: "Update aspire.dev support page for a new Aspire release"
GH_AW_INFO_EXPERIMENTAL: "false"
GH_AW_INFO_SUPPORTS_TOOLS_ALLOWLIST: "true"
@@ -144,6 +143,7 @@ jobs:
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_COMPILED_STRICT: "true"
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
@@ -156,7 +156,6 @@ jobs:
id: check-oauth-tokens
run: bash "${RUNNER_TEMP}/gh-aw/actions/check_oauth_tokens.sh"
env:
- COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
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
@@ -176,12 +175,12 @@ jobs:
env:
GH_AW_AGENT_FOLDERS: ".agents .github"
GH_AW_AGENT_FILES: "AGENTS.md"
- # poutine:ignore untrusted_checkout_exec
- run: bash "${RUNNER_TEMP}/gh-aw/actions/save_base_github_folders.sh"
+ run: |
+ bash "${RUNNER_TEMP}/gh-aw/actions/save_base_github_folders.sh"
- name: Check compile-agentic version
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
- GH_AW_COMPILED_VERSION: "v0.85.4"
+ GH_AW_COMPILED_VERSION: "v0.86.2"
with:
script: |
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
@@ -192,9 +191,12 @@ jobs:
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_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ 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\"},{\"file\":\"safe_outputs_create_pull_request.md\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0002\"},{\"file\":\"mcp_cli_tools_prompt.md\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0003\"},{\"file\":\"github_mcp_tools_with_safeoutputs_prompt.md\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0004\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0005\"}]}"
GH_AW_EXPR_1A3A194A: ${{ github.event.discussion.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'discussion' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }}
GH_AW_EXPR_463A214A: ${{ github.event.pull_request.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'pull_request' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }}
GH_AW_EXPR_7F72DC02: ${{ github.event.release.tag_name || github.event.inputs.tag_name }}
@@ -208,79 +210,22 @@ jobs:
GH_AW_GITHUB_REPOSITORY: ${{ github.repository }}
GH_AW_GITHUB_RUN_ID: ${{ github.run_id }}
GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }}
- # poutine:ignore untrusted_checkout_exec
- run: |
- bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh"
- {
- cat << 'GH_AW_PROMPT_9129824896cac104_EOF'
-
- GH_AW_PROMPT_9129824896cac104_EOF
- cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md"
- cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md"
- cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md"
- cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md"
- cat << 'GH_AW_PROMPT_9129824896cac104_EOF'
-
- Tools: create_pull_request, missing_tool, missing_data, noop
- GH_AW_PROMPT_9129824896cac104_EOF
- cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_create_pull_request.md"
- cat << 'GH_AW_PROMPT_9129824896cac104_EOF'
-
- GH_AW_PROMPT_9129824896cac104_EOF
- cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md"
- cat << 'GH_AW_PROMPT_9129824896cac104_EOF'
-
- The following GitHub context information is available for this workflow:
- {{#if github.actor}}
- - **actor**: __GH_AW_GITHUB_ACTOR__
- {{/if}}
- {{#if github.repository}}
- - **repository**: __GH_AW_GITHUB_REPOSITORY__
- {{/if}}
- {{#if github.workspace}}
- - **workspace**: __GH_AW_GITHUB_WORKSPACE__
- {{/if}}
- {{#if github.event.issue.number || (github.aw.context.item_type == 'issue' && github.aw.context.item_number)}}
- - **issue-number**: #__GH_AW_EXPR_802A9F6A__
- {{/if}}
- {{#if github.event.discussion.number || (github.aw.context.item_type == 'discussion' && github.aw.context.item_number)}}
- - **discussion-number**: #__GH_AW_EXPR_1A3A194A__
- {{/if}}
- {{#if github.event.pull_request.number || (github.aw.context.item_type == 'pull_request' && github.aw.context.item_number)}}
- - **pull-request-number**: #__GH_AW_EXPR_463A214A__
- {{/if}}
- {{#if github.event.comment.id || github.aw.context.comment_id}}
- - **comment-id**: __GH_AW_EXPR_FF1D34CE__
- {{/if}}
- {{#if github.run_id}}
- - **workflow-run-id**: __GH_AW_GITHUB_RUN_ID__
- {{/if}}
- - **checkouts**: The following repositories have been checked out and are available in the workspace:
- - repo `microsoft/aspire.dev` → `$GITHUB_WORKSPACE` (cwd) (**current** - this is the repository you are working on; use this as the target for all GitHub operations unless otherwise specified) [shallow clone, fetch-depth=1 (default)]
- - **Note**: If a branch you need is not in the list above and is not listed as an additional fetched ref, it has NOT been checked out. For private repositories you cannot fetch it. If the branch is required and not available, exit with an error and ask the user to add it to the `fetch:` option of the `checkout:` configuration (e.g., `fetch: ["refs/pulls/open/*"]` for all open PR refs, or `fetch: ["main", "feature/my-branch"]` for specific branches).
- - **Warning: No git credentials are available to the agent.** Credentials are
- intentionally removed after the checkout step for security. This means any git
- operation that needs to authenticate to the remote will fail. In private repositories, that includes:
- - `git fetch`, `git pull`, `git clone`, and `git push` (direct push, not via safe-output tools)
- - Checking out or switching to a remote branch that is not already fetched
- - Deepening a shallow clone (`git fetch --unshallow`)
- - On-demand blob fetches in partial/blobless clones (operations on files not in the initial checkout)
- Do NOT attempt to configure credentials, run `git credential fill`, or modify `.gitconfig` —
- authentication will not succeed. If you encounter credential prompts or authentication errors,
- stop immediately and report the limitation rather than spending turns trying to work around it.
-
-
- GH_AW_PROMPT_9129824896cac104_EOF
- cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md"
- cat << 'GH_AW_PROMPT_9129824896cac104_EOF'
-
- {{#runtime-import .github/workflows/release-update-support-mdx.md}}
- GH_AW_PROMPT_9129824896cac104_EOF
- } > "$GH_AW_PROMPT"
+ GH_AW_PROMPT_CONTENT_0000: "\n"
+ GH_AW_PROMPT_CONTENT_0001: "\nTools: create_pull_request, missing_tool, missing_data, noop\n"
+ GH_AW_PROMPT_CONTENT_0002: "\n"
+ GH_AW_PROMPT_CONTENT_0003: "\nThe following GitHub context information is available for this workflow:\n{{#if github.actor}}\n- **actor**: __GH_AW_GITHUB_ACTOR__\n{{/if}}\n{{#if github.repository}}\n- **repository**: __GH_AW_GITHUB_REPOSITORY__\n{{/if}}\n{{#if github.workspace}}\n- **workspace**: __GH_AW_GITHUB_WORKSPACE__\n{{/if}}\n{{#if github.event.issue.number || (github.aw.context.item_type == 'issue' && github.aw.context.item_number)}}\n- **issue-number**: #__GH_AW_EXPR_802A9F6A__\n{{/if}}\n{{#if github.event.discussion.number || (github.aw.context.item_type == 'discussion' && github.aw.context.item_number)}}\n- **discussion-number**: #__GH_AW_EXPR_1A3A194A__\n{{/if}}\n{{#if github.event.pull_request.number || (github.aw.context.item_type == 'pull_request' && github.aw.context.item_number)}}\n- **pull-request-number**: #__GH_AW_EXPR_463A214A__\n{{/if}}\n{{#if github.event.comment.id || github.aw.context.comment_id}}\n- **comment-id**: __GH_AW_EXPR_FF1D34CE__\n{{/if}}\n{{#if github.run_id}}\n- **workflow-run-id**: __GH_AW_GITHUB_RUN_ID__\n{{/if}}\n- **checkouts**: The following repositories have been checked out and are available in the workspace:\n - repo `microsoft/aspire.dev` → `$GITHUB_WORKSPACE` (cwd) (**current** - this is the repository you are working on; use this as the target for all GitHub operations unless otherwise specified) [shallow clone, fetch-depth=1 (default)]\n - **Note**: If a branch you need is not in the list above and is not listed as an additional fetched ref, it has NOT been checked out. For private repositories you cannot fetch it. If the branch is required and not available, exit with an error and ask the user to add it to the `fetch:` option of the `checkout:` configuration (e.g., `fetch: [\"refs/pulls/open/*\"]` for all open PR refs, or `fetch: [\"main\", \"feature/my-branch\"]` for specific branches).\n - **Warning: No git credentials are available to the agent.** Credentials are\n intentionally removed after the checkout step for security. This means any git\n operation that needs to authenticate to the remote will fail. In private repositories, that includes:\n - `git fetch`, `git pull`, `git clone`, and `git push` (direct push, not via safe-output tools)\n - Checking out or switching to a remote branch that is not already fetched\n - Deepening a shallow clone (`git fetch --unshallow`)\n - On-demand blob fetches in partial/blobless clones (operations on files not in the initial checkout)\n Do NOT attempt to configure credentials, run `git credential fill`, or modify `.gitconfig` —\n authentication will not succeed. If you encounter credential prompts or authentication errors,\n stop immediately and report the limitation rather than spending turns trying to work around it.\n\n\n"
+ GH_AW_PROMPT_CONTENT_0004: "\n"
+ GH_AW_PROMPT_CONTENT_0005: "{{#runtime-import .github/workflows/release-update-support-mdx.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: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_PROMPT: ${{ runner.temp }}/gh-aw/aw-prompts/prompt.txt
GH_AW_ENGINE_ID: "copilot"
GH_AW_GITHUB_EVENT_INPUTS_TAG_NAME: ${{ github.event.inputs.tag_name }}
GH_AW_GITHUB_EVENT_RELEASE_NAME: ${{ github.event.release.name }}
@@ -296,7 +241,7 @@ jobs:
- name: Substitute placeholders
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
- GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_PROMPT: ${{ runner.temp }}/gh-aw/aw-prompts/prompt.txt
GH_AW_EXPR_1A3A194A: ${{ github.event.discussion.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'discussion' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }}
GH_AW_EXPR_463A214A: ${{ github.event.pull_request.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'pull_request' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }}
GH_AW_EXPR_7F72DC02: ${{ github.event.release.tag_name || github.event.inputs.tag_name }}
@@ -342,14 +287,18 @@ jobs:
});
- name: Validate prompt placeholders
env:
- GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
- # poutine:ignore untrusted_checkout_exec
- run: bash "${RUNNER_TEMP}/gh-aw/actions/validate_prompt_placeholders.sh"
+ 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: /tmp/gh-aw/aw-prompts/prompt.txt
- # poutine:ignore untrusted_checkout_exec
- run: bash "${RUNNER_TEMP}/gh-aw/actions/print_prompt_summary.sh"
+ 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
@@ -413,7 +362,7 @@ jobs:
steps:
- name: Setup Scripts
id: setup
- uses: github/gh-aw-actions/setup@2709137ea6c5b0e19aa621454dc643ea8dc526b1 # v0.85.4
+ uses: github/gh-aw-actions/setup@6aab9e5b5c91c615506061f09bedd81a23babe3c # v0.86.2
with:
destination: ${{ runner.temp }}/gh-aw/actions
job-name: ${{ github.job }}
@@ -422,7 +371,7 @@ jobs:
env:
GH_AW_SETUP_WORKFLOW_NAME: "Update aspire.dev support page for a new Aspire release"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/release-update-support-mdx.lock.yml@${{ github.ref }}
- GH_AW_INFO_VERSION: "1.0.78"
+ 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
@@ -497,11 +446,13 @@ jobs:
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.85.4
+ 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: Generate GitHub App token
@@ -552,7 +503,7 @@ jobs:
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.8@sha256:38bbea36cdb46a3c9d04d1db05e672966f5239b431a2022eb35881688e5721d8 ghcr.io/github/gh-aw-node@sha256:0d9f1fb5fd6610c0ac1f5194a38e45a8a1e81f8a390d5142d8e4e6f26a4b3196 ghcr.io/github/github-mcp-server:v1.8.0@sha256:d5a18c04b92714c309eb46a2305087e91a4dbd80420f6e462656699f95093520
+ 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 ghcr.io/github/github-mcp-server:v1.9.0@sha256:881b53d6f75f69bdbc1b5b10fc2f1361717c19054143b3a8529fb5c32061a50e
- name: Generate Safe Outputs Config
run: |
mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs"
@@ -606,6 +557,10 @@ jobs:
"type": "string",
"maxLength": 256
},
+ "temporary_id": {
+ "type": "string",
+ "pattern": "^#?aw_[A-Za-z0-9_]{3,12}$"
+ },
"title": {
"required": true,
"type": "string",
@@ -719,22 +674,23 @@ jobs:
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"
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 -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.8'
+ 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_4c54f505c38e359f_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs"
+ cat << GH_AW_MCP_CONFIG_f55df6cf4d1d307e_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs"
{
"mcpServers": {
"github": {
"type": "stdio",
- "container": "ghcr.io/github/github-mcp-server:v1.8.0",
+ "container": "ghcr.io/github/github-mcp-server:v1.9.0",
"env": {
"GITHUB_FEATURES": "fields_param",
"GITHUB_HOST": "${GITHUB_SERVER_URL}",
@@ -796,7 +752,7 @@ jobs:
"startupTimeout": 120
}
}
- GH_AW_MCP_CONFIG_4c54f505c38e359f_EOF
+ GH_AW_MCP_CONFIG_f55df6cf4d1d307e_EOF
- name: Mount MCP servers as CLIs
id: mount-mcp-clis
continue-on-error: true
@@ -830,6 +786,18 @@ jobs:
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
@@ -854,8 +822,8 @@ jobs:
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 GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_API_KEY --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 /usr/local/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 --allow-all-paths --add-dir "${GITHUB_WORKSPACE}" --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log
+ 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 GITHUB_MCP_SERVER_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-all-tools --allow-all-paths --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
@@ -869,7 +837,7 @@ jobs:
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: 15
- GH_AW_VERSION: v0.85.4
+ GH_AW_VERSION: v0.86.2
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
GITHUB_COPILOT_INTEGRATION_ID: agentic-workflows
@@ -1062,7 +1030,7 @@ jobs:
steps:
- name: Setup Scripts
id: setup
- uses: github/gh-aw-actions/setup@2709137ea6c5b0e19aa621454dc643ea8dc526b1 # v0.85.4
+ uses: github/gh-aw-actions/setup@6aab9e5b5c91c615506061f09bedd81a23babe3c # v0.86.2
with:
destination: ${{ runner.temp }}/gh-aw/actions
job-name: ${{ github.job }}
@@ -1071,7 +1039,7 @@ jobs:
env:
GH_AW_SETUP_WORKFLOW_NAME: "Update aspire.dev support page for a new Aspire release"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/release-update-support-mdx.lock.yml@${{ github.ref }}
- GH_AW_INFO_VERSION: "1.0.78"
+ GH_AW_INFO_VERSION: "1.0.79"
GH_AW_INFO_AWF_VERSION: "v0.27.44"
GH_AW_INFO_ENGINE_ID: "copilot"
- name: Generate GitHub App token
@@ -1286,7 +1254,7 @@ jobs:
steps:
- name: Setup Scripts
id: setup
- uses: github/gh-aw-actions/setup@2709137ea6c5b0e19aa621454dc643ea8dc526b1 # v0.85.4
+ uses: github/gh-aw-actions/setup@6aab9e5b5c91c615506061f09bedd81a23babe3c # v0.86.2
with:
destination: ${{ runner.temp }}/gh-aw/actions
job-name: ${{ github.job }}
@@ -1295,7 +1263,7 @@ jobs:
env:
GH_AW_SETUP_WORKFLOW_NAME: "Update aspire.dev support page for a new Aspire release"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/release-update-support-mdx.lock.yml@${{ github.ref }}
- GH_AW_INFO_VERSION: "1.0.78"
+ 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
@@ -1347,25 +1315,7 @@ jobs:
- name: Prepare threat detection files
if: always() && steps.detection_guard.outputs.run_detection == 'true'
run: |
- mkdir -p /tmp/gh-aw/threat-detection/aw-prompts
- rm -f /tmp/gh-aw/agent_usage.json
- cp /tmp/gh-aw/aw-prompts/prompt.txt /tmp/gh-aw/threat-detection/aw-prompts/prompt.txt 2>/dev/null || true
- if [ ! -s /tmp/gh-aw/threat-detection/aw-prompts/prompt.txt ]; then
- echo "::warning::ERR_VALIDATION: Missing or empty detection context prompt at /tmp/gh-aw/threat-detection/aw-prompts/prompt.txt. Ensure the agent artifact includes /tmp/gh-aw/aw-prompts/prompt.txt. Detection will continue with fallback workflow context."
- fi
- cp /tmp/gh-aw/agent_output.json /tmp/gh-aw/threat-detection/agent_output.json 2>/dev/null || true
- for f in /tmp/gh-aw/aw-*.patch; do
- if [ -f "$f" ]; then
- cp "$f" /tmp/gh-aw/threat-detection/ 2>/dev/null || true
- fi
- done
- for f in /tmp/gh-aw/aw-*.bundle; do
- if [ -f "$f" ]; then
- cp "$f" /tmp/gh-aw/threat-detection/ 2>/dev/null || true
- fi
- done
- echo "Prepared threat detection files:"
- ls -la /tmp/gh-aw/threat-detection/ 2>/dev/null || true
+ 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
@@ -1385,18 +1335,20 @@ jobs:
run: |
mkdir -p /tmp/gh-aw/threat-detection
touch /tmp/gh-aw/threat-detection/detection.log
- rm -f /tmp/gh-aw/threat-detection/step-summary.md
- touch /tmp/gh-aw/threat-detection/step-summary.md
+ 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.85.4
+ 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
@@ -1412,6 +1364,18 @@ jobs:
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
@@ -1438,9 +1402,10 @@ jobs:
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 --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 /usr/local/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 --add-dir "${GITHUB_WORKSPACE}" --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' 2>&1 | tee -a /tmp/gh-aw/threat-detection/detection.log
+ 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 --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
@@ -1452,14 +1417,13 @@ jobs:
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_TIMEOUT_MINUTES: 20
- GH_AW_VERSION: v0.85.4
+ 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]
@@ -1468,6 +1432,23 @@ jobs:
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()
@@ -1539,14 +1520,14 @@ jobs:
steps:
- name: Setup Scripts
id: setup
- uses: github/gh-aw-actions/setup@2709137ea6c5b0e19aa621454dc643ea8dc526b1 # v0.85.4
+ 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: "Update aspire.dev support page for a new Aspire release"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/release-update-support-mdx.lock.yml@${{ github.ref }}
- GH_AW_INFO_VERSION: "1.0.78"
+ GH_AW_INFO_VERSION: "1.0.79"
GH_AW_INFO_AWF_VERSION: "v0.27.44"
GH_AW_INFO_ENGINE_ID: "copilot"
- name: Check team membership for workflow
@@ -1598,15 +1579,20 @@ jobs:
create_discussion_errors: ${{ steps.process_safe_outputs.outputs.create_discussion_errors }}
created_pr_number: ${{ steps.process_safe_outputs.outputs.created_pr_number }}
created_pr_url: ${{ steps.process_safe_outputs.outputs.created_pr_url }}
+ 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@2709137ea6c5b0e19aa621454dc643ea8dc526b1 # v0.85.4
+ uses: github/gh-aw-actions/setup@6aab9e5b5c91c615506061f09bedd81a23babe3c # v0.86.2
with:
destination: ${{ runner.temp }}/gh-aw/actions
job-name: ${{ github.job }}
@@ -1615,7 +1601,7 @@ jobs:
env:
GH_AW_SETUP_WORKFLOW_NAME: "Update aspire.dev support page for a new Aspire release"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/release-update-support-mdx.lock.yml@${{ github.ref }}
- GH_AW_INFO_VERSION: "1.0.78"
+ 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
diff --git a/.github/workflows/repo-pulse.lock.yml b/.github/workflows/repo-pulse.lock.yml
index 042c276a261..cd7b1ad19df 100644
--- a/.github/workflows/repo-pulse.lock.yml
+++ b/.github/workflows/repo-pulse.lock.yml
@@ -1,6 +1,6 @@
-# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"8f20ffc2805d6661eb63b093ce5d47e9ebaad59646ed7dbc434fc7084e89bfee","body_hash":"dff652e509d2a0a9235f278c99bf3657a7495a9ecfc63ba41bf7adcf44b81cd4","compiler_version":"v0.85.4","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.78"}}
-# gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/checkout","sha":"3d3c42e5aac5ba805825da76410c181273ba90b1","version":"v7.0.1"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"373c709c69115d41ff229c7e5df9f8788daa9553","version":"v9"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"820762786026740c76f36085b0efc47a31fe5020","version":"v7.0.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"2709137ea6c5b0e19aa621454dc643ea8dc526b1","version":"v0.85.4"}],"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.8","digest":"sha256:38bbea36cdb46a3c9d04d1db05e672966f5239b431a2022eb35881688e5721d8","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.4.8@sha256:38bbea36cdb46a3c9d04d1db05e672966f5239b431a2022eb35881688e5721d8"},{"image":"ghcr.io/github/gh-aw-node","digest":"sha256:0d9f1fb5fd6610c0ac1f5194a38e45a8a1e81f8a390d5142d8e4e6f26a4b3196","pinned_image":"ghcr.io/github/gh-aw-node@sha256:0d9f1fb5fd6610c0ac1f5194a38e45a8a1e81f8a390d5142d8e4e6f26a4b3196"},{"image":"ghcr.io/github/github-mcp-server:v1.8.0","digest":"sha256:d5a18c04b92714c309eb46a2305087e91a4dbd80420f6e462656699f95093520","pinned_image":"ghcr.io/github/github-mcp-server:v1.8.0@sha256:d5a18c04b92714c309eb46a2305087e91a4dbd80420f6e462656699f95093520"}]}
-# This file was automatically generated by gh-aw (v0.85.4). DO NOT EDIT. To debug this workflow, load the skill at https://github.com/github/gh-aw/blob/main/debug.md
+# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"dc3c220f0ad09525ead1ec145c0dc0c88d7912df57e11cc4c47a903b65fea764","body_hash":"dff652e509d2a0a9235f278c99bf3657a7495a9ecfc63ba41bf7adcf44b81cd4","compiler_version":"v0.86.2","strict":true,"agent_id":"copilot","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/checkout","sha":"3d3c42e5aac5ba805825da76410c181273ba90b1","version":"v7.0.1"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"373c709c69115d41ff229c7e5df9f8788daa9553","version":"v9"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"820762786026740c76f36085b0efc47a31fe5020","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"},{"image":"ghcr.io/github/github-mcp-server:v1.9.0","digest":"sha256:881b53d6f75f69bdbc1b5b10fc2f1361717c19054143b3a8529fb5c32061a50e","pinned_image":"ghcr.io/github/github-mcp-server:v1.9.0@sha256:881b53d6f75f69bdbc1b5b10fc2f1361717c19054143b3a8529fb5c32061a50e"}]}
+# 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
#
# ___ _ _
# / _ \ | | (_)
@@ -34,7 +34,6 @@
# the resulting JSON files and renders the issue body.
#
# Secrets used:
-# - COPILOT_GITHUB_TOKEN
# - GH_AW_GITHUB_MCP_SERVER_TOKEN
# - GH_AW_GITHUB_TOKEN
# - GITHUB_TOKEN
@@ -46,15 +45,15 @@
# - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
# - actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
# - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
-# - github/gh-aw-actions/setup@2709137ea6c5b0e19aa621454dc643ea8dc526b1 # v0.85.4
+# - 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.8@sha256:38bbea36cdb46a3c9d04d1db05e672966f5239b431a2022eb35881688e5721d8
+# - ghcr.io/github/gh-aw-mcpg:v0.4.9@sha256:e5a1569aeaf41820fa7bdee3e94468cae448133cdbf00119ad24f5b74db1ab9f
# - ghcr.io/github/gh-aw-node@sha256:0d9f1fb5fd6610c0ac1f5194a38e45a8a1e81f8a390d5142d8e4e6f26a4b3196
-# - ghcr.io/github/github-mcp-server:v1.8.0@sha256:d5a18c04b92714c309eb46a2305087e91a4dbd80420f6e462656699f95093520
+# - ghcr.io/github/github-mcp-server:v1.9.0@sha256:881b53d6f75f69bdbc1b5b10fc2f1361717c19054143b3a8529fb5c32061a50e
name: "Repo Pulse — Daily Report"
on:
@@ -98,14 +97,14 @@ jobs:
steps:
- name: Setup Scripts
id: setup
- uses: github/gh-aw-actions/setup@2709137ea6c5b0e19aa621454dc643ea8dc526b1 # v0.85.4
+ 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: "Repo Pulse — Daily Report"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/repo-pulse.lock.yml@${{ github.ref }}
- GH_AW_INFO_VERSION: "1.0.78"
+ 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
@@ -114,9 +113,9 @@ jobs:
GH_AW_INFO_ENGINE_ID: "copilot"
GH_AW_INFO_ENGINE_NAME: "GitHub Copilot CLI"
GH_AW_INFO_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || vars.GH_AW_DEFAULT_MODEL_COPILOT || 'auto' }}
- GH_AW_INFO_VERSION: "1.0.78"
- GH_AW_INFO_AGENT_VERSION: "1.0.78"
- GH_AW_INFO_CLI_VERSION: "v0.85.4"
+ 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: "Repo Pulse — Daily Report"
GH_AW_INFO_EXPERIMENTAL: "false"
GH_AW_INFO_SUPPORTS_TOOLS_ALLOWLIST: "true"
@@ -126,6 +125,7 @@ jobs:
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_COMPILED_STRICT: "true"
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
@@ -138,7 +138,6 @@ jobs:
id: check-oauth-tokens
run: bash "${RUNNER_TEMP}/gh-aw/actions/check_oauth_tokens.sh"
env:
- COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
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
@@ -158,8 +157,8 @@ jobs:
env:
GH_AW_AGENT_FOLDERS: ".agents .github"
GH_AW_AGENT_FILES: "AGENTS.md"
- # poutine:ignore untrusted_checkout_exec
- run: bash "${RUNNER_TEMP}/gh-aw/actions/save_base_github_folders.sh"
+ 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
@@ -175,7 +174,7 @@ jobs:
- name: Check compile-agentic version
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
- GH_AW_COMPILED_VERSION: "v0.85.4"
+ GH_AW_COMPILED_VERSION: "v0.86.2"
with:
script: |
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
@@ -186,9 +185,12 @@ jobs:
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_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ 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\"},{\"file\":\"github_mcp_tools_with_safeoutputs_prompt.md\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0004\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0005\"}]}"
GH_AW_EXPR_1A3A194A: ${{ github.event.discussion.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'discussion' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }}
GH_AW_EXPR_463A214A: ${{ github.event.pull_request.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'pull_request' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }}
GH_AW_EXPR_802A9F6A: ${{ github.event.issue.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'issue' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }}
@@ -197,63 +199,22 @@ jobs:
GH_AW_GITHUB_REPOSITORY: ${{ github.repository }}
GH_AW_GITHUB_RUN_ID: ${{ github.run_id }}
GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }}
- # poutine:ignore untrusted_checkout_exec
- run: |
- bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh"
- {
- cat << 'GH_AW_PROMPT_9495a7868ee358fe_EOF'
-
- GH_AW_PROMPT_9495a7868ee358fe_EOF
- cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md"
- cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md"
- cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md"
- cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md"
- cat << 'GH_AW_PROMPT_9495a7868ee358fe_EOF'
-
- Tools: update_issue, missing_tool, missing_data, noop
-
- GH_AW_PROMPT_9495a7868ee358fe_EOF
- cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md"
- cat << 'GH_AW_PROMPT_9495a7868ee358fe_EOF'
-
- The following GitHub context information is available for this workflow:
- {{#if github.actor}}
- - **actor**: __GH_AW_GITHUB_ACTOR__
- {{/if}}
- {{#if github.repository}}
- - **repository**: __GH_AW_GITHUB_REPOSITORY__
- {{/if}}
- {{#if github.workspace}}
- - **workspace**: __GH_AW_GITHUB_WORKSPACE__
- {{/if}}
- {{#if github.event.issue.number || (github.aw.context.item_type == 'issue' && github.aw.context.item_number)}}
- - **issue-number**: #__GH_AW_EXPR_802A9F6A__
- {{/if}}
- {{#if github.event.discussion.number || (github.aw.context.item_type == 'discussion' && github.aw.context.item_number)}}
- - **discussion-number**: #__GH_AW_EXPR_1A3A194A__
- {{/if}}
- {{#if github.event.pull_request.number || (github.aw.context.item_type == 'pull_request' && github.aw.context.item_number)}}
- - **pull-request-number**: #__GH_AW_EXPR_463A214A__
- {{/if}}
- {{#if github.event.comment.id || github.aw.context.comment_id}}
- - **comment-id**: __GH_AW_EXPR_FF1D34CE__
- {{/if}}
- {{#if github.run_id}}
- - **workflow-run-id**: __GH_AW_GITHUB_RUN_ID__
- {{/if}}
-
-
- GH_AW_PROMPT_9495a7868ee358fe_EOF
- cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md"
- cat << 'GH_AW_PROMPT_9495a7868ee358fe_EOF'
-
- {{#runtime-import .github/workflows/repo-pulse.md}}
- GH_AW_PROMPT_9495a7868ee358fe_EOF
- } > "$GH_AW_PROMPT"
+ GH_AW_PROMPT_CONTENT_0000: "\n"
+ GH_AW_PROMPT_CONTENT_0001: "\nTools: update_issue, missing_tool, missing_data, noop\n"
+ GH_AW_PROMPT_CONTENT_0002: "\n"
+ GH_AW_PROMPT_CONTENT_0003: "\nThe following GitHub context information is available for this workflow:\n{{#if github.actor}}\n- **actor**: __GH_AW_GITHUB_ACTOR__\n{{/if}}\n{{#if github.repository}}\n- **repository**: __GH_AW_GITHUB_REPOSITORY__\n{{/if}}\n{{#if github.workspace}}\n- **workspace**: __GH_AW_GITHUB_WORKSPACE__\n{{/if}}\n{{#if github.event.issue.number || (github.aw.context.item_type == 'issue' && github.aw.context.item_number)}}\n- **issue-number**: #__GH_AW_EXPR_802A9F6A__\n{{/if}}\n{{#if github.event.discussion.number || (github.aw.context.item_type == 'discussion' && github.aw.context.item_number)}}\n- **discussion-number**: #__GH_AW_EXPR_1A3A194A__\n{{/if}}\n{{#if github.event.pull_request.number || (github.aw.context.item_type == 'pull_request' && github.aw.context.item_number)}}\n- **pull-request-number**: #__GH_AW_EXPR_463A214A__\n{{/if}}\n{{#if github.event.comment.id || github.aw.context.comment_id}}\n- **comment-id**: __GH_AW_EXPR_FF1D34CE__\n{{/if}}\n{{#if github.run_id}}\n- **workflow-run-id**: __GH_AW_GITHUB_RUN_ID__\n{{/if}}\n\n\n"
+ GH_AW_PROMPT_CONTENT_0004: "\n"
+ GH_AW_PROMPT_CONTENT_0005: "{{#runtime-import .github/workflows/repo-pulse.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: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_PROMPT: ${{ runner.temp }}/gh-aw/aw-prompts/prompt.txt
GH_AW_ENGINE_ID: "copilot"
with:
script: |
@@ -264,7 +225,7 @@ jobs:
- name: Substitute placeholders
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
- GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_PROMPT: ${{ runner.temp }}/gh-aw/aw-prompts/prompt.txt
GH_AW_EXPR_1A3A194A: ${{ github.event.discussion.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'discussion' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }}
GH_AW_EXPR_463A214A: ${{ github.event.pull_request.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'pull_request' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }}
GH_AW_EXPR_802A9F6A: ${{ github.event.issue.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'issue' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }}
@@ -298,14 +259,18 @@ jobs:
});
- name: Validate prompt placeholders
env:
- GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
- # poutine:ignore untrusted_checkout_exec
- run: bash "${RUNNER_TEMP}/gh-aw/actions/validate_prompt_placeholders.sh"
+ 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: /tmp/gh-aw/aw-prompts/prompt.txt
- # poutine:ignore untrusted_checkout_exec
- run: bash "${RUNNER_TEMP}/gh-aw/actions/print_prompt_summary.sh"
+ 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
@@ -370,7 +335,7 @@ jobs:
steps:
- name: Setup Scripts
id: setup
- uses: github/gh-aw-actions/setup@2709137ea6c5b0e19aa621454dc643ea8dc526b1 # v0.85.4
+ uses: github/gh-aw-actions/setup@6aab9e5b5c91c615506061f09bedd81a23babe3c # v0.86.2
with:
destination: ${{ runner.temp }}/gh-aw/actions
job-name: ${{ github.job }}
@@ -379,7 +344,7 @@ jobs:
env:
GH_AW_SETUP_WORKFLOW_NAME: "Repo Pulse — Daily Report"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/repo-pulse.lock.yml@${{ github.ref }}
- GH_AW_INFO_VERSION: "1.0.78"
+ 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
@@ -425,11 +390,13 @@ jobs:
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.85.4
+ 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: Determine automatic lockdown mode for GitHub MCP Server
@@ -473,7 +440,7 @@ jobs:
run: "set -euo pipefail\n\nmkdir -p .repo-pulse\n\n# Accumulates human-readable warnings about data collection issues\n# (fetch failures, partial results from the search API, etc.). Each\n# line becomes one entry in meta.data_quality_warnings, which the\n# agent renders as a banner at the top of the report so readers know\n# the dashboard may be incomplete.\nWARNINGS_FILE=\"$(mktemp)\"\n: > \"${WARNINGS_FILE}\"\n\n# Window: last 3 days (72 hours) in UTC.\nWINDOW_DAYS=3\nNOW_UTC=\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"\nCUTOFF_UTC=\"$(date -u -d \"${WINDOW_DAYS} days ago\" +%Y-%m-%dT%H:%M:%SZ)\"\nCUTOFF_DATE=\"$(date -u -d \"${WINDOW_DAYS} days ago\" +%Y-%m-%d)\"\nGENERATED_DISPLAY=\"$(date -u +'%Y-%m-%d %H:%M UTC')\"\n\necho \"Repo: $REPO\"\necho \"Now (UTC): $NOW_UTC\"\necho \"Cutoff (UTC): $CUTOFF_UTC ($WINDOW_DAYS days)\"\n\n# Shared jq helper: project each search-issues item down to just the\n# fields the report uses.\n#\n# Title normalization:\n# - Escape backticks (\\u0060 in jq string) — also avoids any chance\n# of bash interpreting a literal backtick during variable\n# expansion into the jq expression below.\n# - Strip HTML comments .\n# - Trim whitespace.\n# Labels are extracted as plain strings.\nread -r -d '' SAFE_FIELDS <<'JQ' || true\n{\n number: .number,\n title: (\n (.title // \"\")\n | gsub(\"\"; \"\")\n | gsub(\"\\u0060\"; \"'\")\n | sub(\"^\\\\s+\"; \"\") | sub(\"\\\\s+$\"; \"\")\n ),\n author: (.user.login // \"unknown\"),\n created_at: .created_at,\n updated_at: .updated_at,\n closed_at: .closed_at,\n merged_at: (.pull_request.merged_at // null),\n is_pr: (.pull_request != null),\n is_draft: (.draft // false),\n state: .state,\n comments: (.comments // 0),\n labels: [ .labels[]?.name // empty ],\n html_url: .html_url\n}\nJQ\n\n# URL-encode a raw search query for use in an https://github.com/.../issues?q=... link.\nurlencode() {\n jq -Rr @uri <<< \"$1\"\n}\n\n# Fetch all pages of a GitHub search-issues query, project each item\n# down to the fields the report uses, and write a JSON array to $2.\n#\n# Resilience:\n# - A single fetch failure must not abort the entire daily report.\n# On failure (non-zero gh exit), we write `[]` to the outfile,\n# record a warning, and return non-zero so the caller can\n# continue with `|| true`.\n# - If the search API sets `incomplete_results: true` on any page\n# (backend timeout), we record a warning so the report header\n# can tell readers this section may be partial.\nfetch_search() {\n local query=\"$1\"\n local outfile=\"$2\"\n local section=\"$3\"\n echo \"--> fetch [$section]: $query\"\n local tmp_pages\n tmp_pages=\"$(mktemp)\"\n # Run the paginated API call without -e propagation so we can\n # observe the exit code and respond in-script.\n set +e\n gh api --paginate -X GET \"search/issues\" -f \"q=${query}\" -f \"per_page=100\" > \"${tmp_pages}\"\n local api_rc=$?\n set -e\n if [ \"${api_rc}\" -ne 0 ]; then\n echo \" WARN: gh api failed (exit=${api_rc}) — writing empty array and continuing\"\n echo \"${section}: data collection failed (gh api exit=${api_rc}); this section is empty\" >> \"${WARNINGS_FILE}\"\n echo \"[]\" > \"${outfile}\"\n rm -f \"${tmp_pages}\"\n return 1\n fi\n # Check for incomplete_results across all pages. The search API\n # sets this to true when the backend times out; items[] is then\n # only a partial slice of the real match set.\n local incomplete\n incomplete=\"$(jq -s 'map(.incomplete_results // false) | any' \"${tmp_pages}\")\"\n if [ \"${incomplete}\" = \"true\" ]; then\n echo \" WARN: search reported incomplete_results=true — section may be partial\"\n echo \"${section}: GitHub search API reported incomplete_results (backend timeout); items shown may be a partial subset\" >> \"${WARNINGS_FILE}\"\n fi\n jq -s \"map(.items) | add | map(${SAFE_FIELDS})\" \"${tmp_pages}\" > \"${outfile}\"\n rm -f \"${tmp_pages}\"\n local count\n count=\"$(jq 'length' \"${outfile}\")\"\n echo \" wrote ${count} items -> ${outfile}\"\n return 0\n}\n\n# --- 1. Merged PRs in window ---\nQ_MERGED=\"repo:${REPO} is:pr is:merged merged:>=${CUTOFF_DATE}\"\nfetch_search \"$Q_MERGED\" .repo-pulse/merged-prs.raw.json \"merged_prs\" || true\njq 'sort_by(.merged_at) | reverse\n | map({number, title, author, merged_at, labels, html_url,\n age_hours: ((now - (.merged_at | fromdateiso8601)) / 3600 | floor)})' \\\n .repo-pulse/merged-prs.raw.json > .repo-pulse/merged-prs.json\n\n# --- 2. Opened PRs in window, still open ---\nQ_OPENED=\"repo:${REPO} is:pr is:open created:>=${CUTOFF_DATE}\"\nfetch_search \"$Q_OPENED\" .repo-pulse/opened-prs.raw.json \"opened_prs\" || true\njq 'sort_by(.created_at) | reverse\n | map({number, title, author, created_at, is_draft, labels, html_url,\n age_hours: ((now - (.created_at | fromdateiso8601)) / 3600 | floor)})' \\\n .repo-pulse/opened-prs.raw.json > .repo-pulse/opened-prs.json\n\n# --- 3. Filed issues in window ---\nQ_ISSUES=\"repo:${REPO} is:issue created:>=${CUTOFF_DATE}\"\nfetch_search \"$Q_ISSUES\" .repo-pulse/filed-issues.raw.json \"filed_issues\" || true\njq 'sort_by(.created_at) | reverse\n | map({number, title, author, created_at, labels, html_url,\n age_hours: ((now - (.created_at | fromdateiso8601)) / 3600 | floor)})' \\\n .repo-pulse/filed-issues.raw.json > .repo-pulse/filed-issues.json\n\n# --- 4. PRs awaiting review (any age) ---\n# `review:required` = review is requested but not yet given.\nQ_AWAITING=\"repo:${REPO} is:pr is:open review:required draft:false\"\nfetch_search \"$Q_AWAITING\" .repo-pulse/awaiting-review.raw.json \"awaiting_review\" || true\njq 'sort_by(.created_at)\n | map({number, title, author, created_at, labels, html_url,\n age_days: ((now - (.created_at | fromdateiso8601)) / 86400 | floor)})' \\\n .repo-pulse/awaiting-review.raw.json > .repo-pulse/awaiting-review.json\n\n# --- 5. Activity highlights (items updated in window with many comments) ---\n# Exclude items labeled quarantined-test or failing-test, per team request:\n# label churn on those surfaces is noise, not \"attention going somewhere new\".\nQ_ACTIVITY=\"repo:${REPO} updated:>=${CUTOFF_DATE} comments:>=3 -label:quarantined-test -label:failing-test\"\nfetch_search \"$Q_ACTIVITY\" .repo-pulse/activity-highlights.raw.json \"activity_highlights\" || true\njq 'sort_by(.updated_at) | reverse\n | map({number, title, author, is_pr, updated_at, comments, labels, html_url})' \\\n .repo-pulse/activity-highlights.raw.json > .repo-pulse/activity-highlights.json\n\n# --- Precompute \"See all\" search URLs (agent should not build these) ---\nALL_MERGED_URL=\"https://github.com/${REPO}/pulls?q=$(urlencode \"is:pr is:merged merged:>=${CUTOFF_DATE}\")\"\nALL_OPENED_URL=\"https://github.com/${REPO}/pulls?q=$(urlencode \"is:pr is:open created:>=${CUTOFF_DATE}\")\"\nALL_ISSUES_URL=\"https://github.com/${REPO}/issues?q=$(urlencode \"is:issue created:>=${CUTOFF_DATE}\")\"\nALL_AWAITING_URL=\"https://github.com/${REPO}/pulls?q=$(urlencode \"is:pr is:open review:required draft:false\")\"\nALL_ACTIVITY_URL=\"https://github.com/${REPO}/issues?q=$(urlencode \"updated:>=${CUTOFF_DATE} comments:>=3 -label:quarantined-test -label:failing-test sort:updated-desc\")\"\n\n# Fold any accumulated warnings into a JSON array for meta.json.\nif [ -s \"${WARNINGS_FILE}\" ]; then\n WARNINGS_JSON=\"$(jq -R -s 'split(\"\\n\") | map(select(length > 0))' \"${WARNINGS_FILE}\")\"\nelse\n WARNINGS_JSON=\"[]\"\nfi\nrm -f \"${WARNINGS_FILE}\"\n\njq -n \\\n --arg repo \"$REPO\" \\\n --arg now_utc \"$NOW_UTC\" \\\n --arg generated_display \"$GENERATED_DISPLAY\" \\\n --arg cutoff_utc \"$CUTOFF_UTC\" \\\n --arg cutoff_date \"$CUTOFF_DATE\" \\\n --arg window_days \"$WINDOW_DAYS\" \\\n --arg run_url \"$RUN_URL\" \\\n --arg all_merged_url \"$ALL_MERGED_URL\" \\\n --arg all_opened_url \"$ALL_OPENED_URL\" \\\n --arg all_issues_url \"$ALL_ISSUES_URL\" \\\n --arg all_awaiting_url \"$ALL_AWAITING_URL\" \\\n --arg all_activity_url \"$ALL_ACTIVITY_URL\" \\\n --argjson warnings \"$WARNINGS_JSON\" \\\n '{\n repo: $repo,\n generated_utc: $now_utc,\n generated_display: $generated_display,\n cutoff_utc: $cutoff_utc,\n cutoff_date: $cutoff_date,\n window_days: ($window_days | tonumber),\n run_url: $run_url,\n display_cap: 25,\n data_quality_warnings: $warnings,\n see_all_urls: {\n merged_prs: $all_merged_url,\n opened_prs: $all_opened_url,\n filed_issues: $all_issues_url,\n awaiting_review: $all_awaiting_url,\n activity_highlights: $all_activity_url\n }\n }' > .repo-pulse/meta.json\n\n# Remove intermediate raw bundles — only the cleaned ones are input to the agent.\nrm -f .repo-pulse/*.raw.json\n\necho \"--- Repo Pulse data bundle ---\"\nls -la .repo-pulse/\necho \"--- meta.json ---\"\ncat .repo-pulse/meta.json\necho \"--- counts ---\"\nfor f in merged-prs opened-prs filed-issues awaiting-review activity-highlights; do\n printf \"%-22s %s\\n\" \"$f.json\" \"$(jq 'length' \".repo-pulse/${f}.json\")\"\ndone"
- 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.8@sha256:38bbea36cdb46a3c9d04d1db05e672966f5239b431a2022eb35881688e5721d8 ghcr.io/github/gh-aw-node@sha256:0d9f1fb5fd6610c0ac1f5194a38e45a8a1e81f8a390d5142d8e4e6f26a4b3196 ghcr.io/github/github-mcp-server:v1.8.0@sha256:d5a18c04b92714c309eb46a2305087e91a4dbd80420f6e462656699f95093520
+ 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 ghcr.io/github/github-mcp-server:v1.9.0@sha256:881b53d6f75f69bdbc1b5b10fc2f1361717c19054143b3a8529fb5c32061a50e
- name: Generate Safe Outputs Config
run: |
mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs"
@@ -650,22 +617,23 @@ jobs:
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"
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 -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.8'
+ 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_32c95f97bcc4bf55_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs"
+ cat << GH_AW_MCP_CONFIG_3d76effbe9e274f4_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs"
{
"mcpServers": {
"github": {
"type": "stdio",
- "container": "ghcr.io/github/github-mcp-server:v1.8.0",
+ "container": "ghcr.io/github/github-mcp-server:v1.9.0",
"env": {
"GITHUB_FEATURES": "fields_param",
"GITHUB_HOST": "${GITHUB_SERVER_URL}",
@@ -725,7 +693,7 @@ jobs:
"startupTimeout": 120
}
}
- GH_AW_MCP_CONFIG_32c95f97bcc4bf55_EOF
+ GH_AW_MCP_CONFIG_3d76effbe9e274f4_EOF
- name: Mount MCP servers as CLIs
id: mount-mcp-clis
continue-on-error: true
@@ -750,6 +718,24 @@ jobs:
- name: Execute GitHub Copilot CLI
id: agentic_execution
# Copilot CLI tool arguments (sorted):
+ # --allow-tool github
+ # --allow-tool safeoutputs
+ # --allow-tool shell(cat)
+ # --allow-tool shell(date)
+ # --allow-tool shell(echo)
+ # --allow-tool shell(github:*)
+ # --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(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
@@ -759,6 +745,18 @@ jobs:
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
@@ -783,8 +781,8 @@ jobs:
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 GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_API_KEY --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 /usr/local/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 --allow-all-paths --add-dir "${GITHUB_WORKSPACE}" --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log
+ 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 GITHUB_MCP_SERVER_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 github --allow-tool safeoutputs --allow-tool '\''shell(cat)'\'' --allow-tool '\''shell(date)'\'' --allow-tool '\''shell(echo)'\'' --allow-tool '\''shell(github:*)'\'' --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(sort)'\'' --allow-tool '\''shell(tail)'\'' --allow-tool '\''shell(uniq)'\'' --allow-tool '\''shell(wc)'\'' --allow-tool '\''shell(yq)'\'' --allow-tool write --allow-all-paths --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
@@ -798,7 +796,7 @@ jobs:
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.85.4
+ GH_AW_VERSION: v0.86.2
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
GITHUB_COPILOT_INTEGRATION_ID: agentic-workflows
@@ -987,7 +985,7 @@ jobs:
steps:
- name: Setup Scripts
id: setup
- uses: github/gh-aw-actions/setup@2709137ea6c5b0e19aa621454dc643ea8dc526b1 # v0.85.4
+ uses: github/gh-aw-actions/setup@6aab9e5b5c91c615506061f09bedd81a23babe3c # v0.86.2
with:
destination: ${{ runner.temp }}/gh-aw/actions
job-name: ${{ github.job }}
@@ -996,7 +994,7 @@ jobs:
env:
GH_AW_SETUP_WORKFLOW_NAME: "Repo Pulse — Daily Report"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/repo-pulse.lock.yml@${{ github.ref }}
- GH_AW_INFO_VERSION: "1.0.78"
+ 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
@@ -1193,7 +1191,7 @@ jobs:
steps:
- name: Setup Scripts
id: setup
- uses: github/gh-aw-actions/setup@2709137ea6c5b0e19aa621454dc643ea8dc526b1 # v0.85.4
+ uses: github/gh-aw-actions/setup@6aab9e5b5c91c615506061f09bedd81a23babe3c # v0.86.2
with:
destination: ${{ runner.temp }}/gh-aw/actions
job-name: ${{ github.job }}
@@ -1202,7 +1200,7 @@ jobs:
env:
GH_AW_SETUP_WORKFLOW_NAME: "Repo Pulse — Daily Report"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/repo-pulse.lock.yml@${{ github.ref }}
- GH_AW_INFO_VERSION: "1.0.78"
+ 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
@@ -1254,25 +1252,7 @@ jobs:
- name: Prepare threat detection files
if: always() && steps.detection_guard.outputs.run_detection == 'true'
run: |
- mkdir -p /tmp/gh-aw/threat-detection/aw-prompts
- rm -f /tmp/gh-aw/agent_usage.json
- cp /tmp/gh-aw/aw-prompts/prompt.txt /tmp/gh-aw/threat-detection/aw-prompts/prompt.txt 2>/dev/null || true
- if [ ! -s /tmp/gh-aw/threat-detection/aw-prompts/prompt.txt ]; then
- echo "::warning::ERR_VALIDATION: Missing or empty detection context prompt at /tmp/gh-aw/threat-detection/aw-prompts/prompt.txt. Ensure the agent artifact includes /tmp/gh-aw/aw-prompts/prompt.txt. Detection will continue with fallback workflow context."
- fi
- cp /tmp/gh-aw/agent_output.json /tmp/gh-aw/threat-detection/agent_output.json 2>/dev/null || true
- for f in /tmp/gh-aw/aw-*.patch; do
- if [ -f "$f" ]; then
- cp "$f" /tmp/gh-aw/threat-detection/ 2>/dev/null || true
- fi
- done
- for f in /tmp/gh-aw/aw-*.bundle; do
- if [ -f "$f" ]; then
- cp "$f" /tmp/gh-aw/threat-detection/ 2>/dev/null || true
- fi
- done
- echo "Prepared threat detection files:"
- ls -la /tmp/gh-aw/threat-detection/ 2>/dev/null || true
+ 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
@@ -1292,18 +1272,20 @@ jobs:
run: |
mkdir -p /tmp/gh-aw/threat-detection
touch /tmp/gh-aw/threat-detection/detection.log
- rm -f /tmp/gh-aw/threat-detection/step-summary.md
- touch /tmp/gh-aw/threat-detection/step-summary.md
+ 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.85.4
+ 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
@@ -1319,6 +1301,18 @@ jobs:
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
@@ -1345,9 +1339,10 @@ jobs:
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 --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 /usr/local/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 --add-dir "${GITHUB_WORKSPACE}" --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' 2>&1 | tee -a /tmp/gh-aw/threat-detection/detection.log
+ 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 --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
@@ -1359,14 +1354,13 @@ jobs:
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_TIMEOUT_MINUTES: 20
- GH_AW_VERSION: v0.85.4
+ 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]
@@ -1375,6 +1369,23 @@ jobs:
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()
@@ -1458,15 +1469,20 @@ jobs:
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@2709137ea6c5b0e19aa621454dc643ea8dc526b1 # v0.85.4
+ uses: github/gh-aw-actions/setup@6aab9e5b5c91c615506061f09bedd81a23babe3c # v0.86.2
with:
destination: ${{ runner.temp }}/gh-aw/actions
job-name: ${{ github.job }}
@@ -1475,7 +1491,7 @@ jobs:
env:
GH_AW_SETUP_WORKFLOW_NAME: "Repo Pulse — Daily Report"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/repo-pulse.lock.yml@${{ github.ref }}
- GH_AW_INFO_VERSION: "1.0.78"
+ 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
diff --git a/.github/workflows/repo-pulse.md b/.github/workflows/repo-pulse.md
index 181cfd5f24b..04f884d985d 100644
--- a/.github/workflows/repo-pulse.md
+++ b/.github/workflows/repo-pulse.md
@@ -30,6 +30,9 @@ permissions:
network: defaults
tools:
+ # Shell access is explicit because the unfiltered GitHub integrity setting
+ # requires an intentional allowlist for reading the preloaded data bundle.
+ bash: ["cat", "ls", "grep", "head", "tail", "wc"]
github:
# Data collection runs in pre-agent-steps via `gh api`; the agent
# does not need to search GitHub itself.
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 858223935c4..3f546a5c47d 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -286,7 +286,8 @@ jobs:
uses: ./.github/workflows/build-cli-native-archives.yml
with:
versionOverrideArg: ${{ inputs.versionOverrideArg }}
- targets: '[{"os": "windows-latest", "runner": "windows-11-arm", "rids": "win-arm64"}]'
+ # Use the newer VS 2026 ARM linker; the VS 2022 image fails on Aspire.Dashboard.obj with LNK1322.
+ targets: '[{"os": "windows-latest", "runner": "windows-11-vs2026-arm", "rids": "win-arm64"}]'
build_cli_archive_macos:
name: Build native CLI archive (macOS)
@@ -569,8 +570,9 @@ jobs:
name: Run VS Code extension unit tests (Windows)
runs-on: windows-latest
needs: [setup_for_tests]
- # Also gated on run_extension_e2e (not just run_extension_unit): extension_e2e_tests `needs` this
- # job, so gating it off while e2e runs would skip e2e via need-propagation.
+ # Also gated on run_extension_e2e (not just run_extension_unit): this job packages and uploads
+ # the aspire-extension VSIX that extension_e2e_tests installs, so skipping it would leave the
+ # shards with nothing to install.
if: ${{ needs.setup_for_tests.outputs.run_extension_unit == 'true' || needs.setup_for_tests.outputs.run_extension_e2e == 'true' }}
env:
NPM_REGISTRY: https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/
@@ -639,14 +641,19 @@ jobs:
run: corepack yarn install --frozen-lockfile --non-interactive
- name: Run tests
run: corepack yarn test
+ # The VSIX steps from here down run even when 'Run tests' failed. extension_e2e_tests
+ # installs the artifact this job uploads but is deliberately not gated on the unit-test
+ # result, so the packaging has to happen regardless or that decoupling buys nothing.
- name: Override extension version for PR builds
- if: ${{ inputs.extensionVersionOverride != '' }}
+ if: ${{ !cancelled() && inputs.extensionVersionOverride != '' }}
run: corepack yarn version --new-version "${{ inputs.extensionVersionOverride }}" --no-git-tag-version
- name: Package VSIX
+ if: ${{ !cancelled() }}
env:
ASPIRE_EXTENSION_E2E_INCLUDE_BRIDGE: "true"
run: corepack yarn run vsce package --pre-release -o out/aspire-extension.vsix
- name: Assert E2E VSIX contains bridge
+ if: ${{ !cancelled() }}
run: ../.github/scripts/assert-extension-e2e-bridge-vsix.ps1 -VsixPath out/aspire-extension.vsix -Expected Present
# Packaged separately (not reusing out/aspire-extension.vsix) because the step above already
# proved that VSIX contains the bridge on purpose; asserting Absent against it would be
@@ -655,10 +662,13 @@ jobs:
# GitHub Actions step `env:` blocks don't leak into later steps, so this reproduces exactly
# what Extension.proj's shipping build packages, with no ability to inherit the opt-in above.
- name: Package production VSIX
+ if: ${{ !cancelled() }}
run: corepack yarn run vsce package --pre-release -o out/aspire-extension-production.vsix
- name: Assert production VSIX excludes bridge
+ if: ${{ !cancelled() }}
run: ../.github/scripts/assert-extension-e2e-bridge-vsix.ps1 -VsixPath out/aspire-extension-production.vsix -Expected Absent
- name: Upload VSIX
+ if: ${{ !cancelled() }}
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: aspire-extension
@@ -722,8 +732,21 @@ jobs:
extension_e2e_tests:
name: Run VS Code extension E2E tests
- if: ${{ needs.setup_for_tests.outputs.run_extension_e2e == 'true' }}
uses: ./.github/workflows/extension-e2e-tests.yml
+ # extension_tests_win stays in `needs` because it uploads the aspire-extension VSIX these shards
+ # install, but E2E is deliberately not gated on its unit-test *result*: !cancelled() keeps the
+ # shards running when those tests fail, and the VSIX packaging steps in that job carry the same
+ # condition so the artifact is published either way. Before this, one unit failure - or an npm
+ # blip on that single Windows runner - skipped all 30 shards and erased the E2E signal entirely.
+ # The remaining producers are still required by result, since a missing CLI archive or package
+ # feed makes every shard fail on a download rather than tell us anything.
+ if: >-
+ ${{ !cancelled() &&
+ needs.setup_for_tests.outputs.run_extension_e2e == 'true' &&
+ needs.build_packages.result == 'success' &&
+ needs.build_cli_archive_linux.result == 'success' &&
+ needs.build_cli_archive_windows.result == 'success' &&
+ needs.extension_bootstrap_linux.result == 'success' }}
needs: [setup_for_tests, build_packages, build_cli_archive_linux, build_cli_archive_windows, extension_tests_win, extension_bootstrap_linux]
typescript_sdk_tests:
diff --git a/.github/workflows/update-nix-cli-flake.yml b/.github/workflows/update-nix-cli-flake.yml
index fc080736e9a..bbb0d83c09c 100644
--- a/.github/workflows/update-nix-cli-flake.yml
+++ b/.github/workflows/update-nix-cli-flake.yml
@@ -1,9 +1,16 @@
# Update Nix CLI Flake Workflow
#
-# This workflow updates eng/nix/versions.json after the AzDO release pipeline
-# uploads the stable aspire-cli-* archives and their .sha512 sidecars to the
-# GitHub release. It is dispatched by release-publish-nuget.yml after
-# PublishReleaseAssetsJob, so the release asset URLs it pins are already live.
+# This workflow updates eng/nix/versions.json for a stable Aspire CLI release.
+# It is dispatched by release-publish-nuget.yml, which passes the aspire-cli-*
+# .sha512 digests it already downloaded and verified from the signed source
+# build's BlobArtifacts. Because the checksums come from the build (not the
+# GitHub release), the manifest can be produced while the release is still an
+# unpublished draft — required for immutable releases, where draft assets aren't
+# served from the public releases/download/... URL. The url values pinned in
+# versions.json are still the public release download URLs (what Nix consumers
+# fetch once the release is published); only the checksum source changed.
+# Manual runs against an already-published release may omit the sha512_* inputs,
+# in which case the updater reads the .sha512 assets from the release directly.
# The changes are committed to the update-baseline- branch created by
# release-github-tasks.yml, then the workflow creates or updates the PR from
# that branch so the post-release stable-version updates land together.
@@ -22,6 +29,31 @@ on:
required: false
type: boolean
default: false
+ # Optional build-provided SHA512 digests (hex), one per platform RID. When
+ # supplied (all four required), the manifest updater uses them directly and
+ # does NOT read the .sha512 assets from the GitHub release. The AzDO release
+ # pipeline passes the digests it already downloaded and verified from the
+ # signed source build's BlobArtifacts, so the Nix manifest can be built
+ # while the GitHub release is still an unpublished draft (draft assets are
+ # not served from the public releases/download/... URL). Manual runs against
+ # an already-published release can omit these and fall back to the release
+ # read. See eng/nix/update-versions.sh for the offline-mode contract.
+ sha512_osx_arm64:
+ description: 'SHA512 (hex) of aspire-cli-osx-arm64-.tar.gz. Optional; omit to read from the published release.'
+ required: false
+ type: string
+ sha512_osx_x64:
+ description: 'SHA512 (hex) of aspire-cli-osx-x64-.tar.gz. Optional; omit to read from the published release.'
+ required: false
+ type: string
+ sha512_linux_arm64:
+ description: 'SHA512 (hex) of aspire-cli-linux-arm64-.tar.gz. Optional; omit to read from the published release.'
+ required: false
+ type: string
+ sha512_linux_x64:
+ description: 'SHA512 (hex) of aspire-cli-linux-x64-.tar.gz. Optional; omit to read from the published release.'
+ required: false
+ type: string
concurrency:
group: update-nix-cli-flake-${{ inputs.release_version }}
@@ -131,8 +163,36 @@ jobs:
- name: Update Nix release manifest
if: inputs.dry_run != true
+ env:
+ # Passed through env (not string-interpolated into the run body) so the
+ # digest values can't break the shell quoting. Empty when the caller
+ # didn't supply build-provided checksums (manual/post-publish runs).
+ SHA512_OSX_ARM64: ${{ inputs.sha512_osx_arm64 }}
+ SHA512_OSX_X64: ${{ inputs.sha512_osx_x64 }}
+ SHA512_LINUX_ARM64: ${{ inputs.sha512_linux_arm64 }}
+ SHA512_LINUX_X64: ${{ inputs.sha512_linux_x64 }}
run: |
- eng/nix/update-versions.sh --version "${{ inputs.release_version }}"
+ set -euo pipefail
+ args=(--version "${{ inputs.release_version }}")
+
+ # If any build-provided digest is present, run the updater in offline
+ # mode (no GitHub release read). Require all four so the manifest is
+ # complete and reproducible — a partial set is a pipeline wiring bug.
+ if [[ -n "$SHA512_OSX_ARM64" || -n "$SHA512_OSX_X64" || -n "$SHA512_LINUX_ARM64" || -n "$SHA512_LINUX_X64" ]]; then
+ if [[ -z "$SHA512_OSX_ARM64" || -z "$SHA512_OSX_X64" || -z "$SHA512_LINUX_ARM64" || -z "$SHA512_LINUX_X64" ]]; then
+ echo "::error::Partial SHA512 inputs supplied. All four platform checksums (osx-arm64, osx-x64, linux-arm64, linux-x64) are required for offline mode."
+ exit 1
+ fi
+ echo "Using build-provided SHA512 checksums (offline mode); not reading the GitHub release."
+ args+=(--sha512 "osx-arm64=$SHA512_OSX_ARM64")
+ args+=(--sha512 "osx-x64=$SHA512_OSX_X64")
+ args+=(--sha512 "linux-arm64=$SHA512_LINUX_ARM64")
+ args+=(--sha512 "linux-x64=$SHA512_LINUX_X64")
+ else
+ echo "No SHA512 inputs supplied; reading checksums from the published GitHub release assets."
+ fi
+
+ eng/nix/update-versions.sh "${args[@]}"
- name: Show Nix manifest diff
if: inputs.dry_run != true
diff --git a/.gitignore b/.gitignore
index 7f2f2fa1532..d9600fc6b80 100644
--- a/.gitignore
+++ b/.gitignore
@@ -140,9 +140,14 @@ target/
dependency-reduced-pom.xml
# Java AppHost build artifacts
-playground/**/.java-build/
+#
+# .java-build is where the CLI compiles a single-file Java AppHost before launching it with
+# `java -cp .java-build AppHost`, so it appears next to any Java AppHost - the playgrounds, the
+# polyglot test fixtures, and the scratch workspace the extension E2E runner creates under
+# extension/. Scoping the rule to known directories left the others untracked-but-visible, which is
+# how build output ends up in a commit.
+.java-build/
playground/**/*.class
-tests/PolyglotAppHosts/**/.java-build/
tests/PolyglotAppHosts/**/Java/**/*.class
# Ignore cache created with the Angular CLI.
diff --git a/Aspire-Core.slnf b/Aspire-Core.slnf
index 17d1cb72d31..c8199adc2e8 100644
--- a/Aspire-Core.slnf
+++ b/Aspire-Core.slnf
@@ -29,6 +29,7 @@
"src\\Aspire.Hosting.EntityFrameworkCore\\Aspire.Hosting.EntityFrameworkCore.csproj",
"src\\Aspire.Hosting.Go\\Aspire.Hosting.Go.csproj",
"src\\Aspire.Hosting.Integration.Analyzers\\Aspire.Hosting.Integration.Analyzers.csproj",
+ "src\\Aspire.Hosting.Java\\Aspire.Hosting.Java.csproj",
"src\\Aspire.Hosting.JavaScript\\Aspire.Hosting.JavaScript.csproj",
"src\\Aspire.Hosting.PostgreSQL\\Aspire.Hosting.PostgreSQL.csproj",
"src\\Aspire.Hosting.Python\\Aspire.Hosting.Python.csproj",
@@ -57,6 +58,7 @@
"tests\\Aspire.Hosting.Analyzers.Tests\\Aspire.Hosting.Analyzers.Tests.csproj",
"tests\\Aspire.Hosting.Containers.Tests\\Aspire.Hosting.Containers.Tests.csproj",
"tests\\Aspire.Hosting.EntityFrameworkCore.Tests\\Aspire.Hosting.EntityFrameworkCore.Tests.csproj",
+ "tests\\Aspire.Hosting.Java.Tests\\Aspire.Hosting.Java.Tests.csproj",
"tests\\Aspire.Hosting.Rust.Tests\\Aspire.Hosting.Rust.Tests.csproj",
"tests\\Aspire.Hosting.Testing.Tests\\Aspire.Hosting.Testing.Tests.csproj",
"tests\\Aspire.Hosting.Tests\\Aspire.Hosting.Tests.csproj",
diff --git a/Aspire.slnx b/Aspire.slnx
index 343ef13d947..d157c96c6f4 100644
--- a/Aspire.slnx
+++ b/Aspire.slnx
@@ -59,6 +59,7 @@
+
@@ -368,6 +369,15 @@
+
+
+
+
+
+
+
+
+
@@ -538,6 +548,7 @@
+
diff --git a/Directory.Build.props b/Directory.Build.props
index c0af8b06bf8..98ccecb9c15 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -55,7 +55,7 @@
- $(MSBuildThisFileDirectory)/artifacts/bin/Aspire.Dashboard/$(Configuration)/net8.0/
+ $(MSBuildThisFileDirectory)/artifacts/bin/Aspire.Dashboard/$(Configuration)/net11.0/
$(MSBuildThisFileDirectory)/artifacts/bin/Aspire.TerminalHost/$(Configuration)/net8.0/
diff --git a/Directory.Packages.props b/Directory.Packages.props
index 8dfbb15494e..0540e8f712a 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -101,28 +101,28 @@
-
-
+
+
-
+
-
-
-
+
+
+
-
-
+
+
-
-
-
+
+
+
@@ -133,36 +133,36 @@
-
+
-
-
-
+
+
+
-
-
+
+
-
+
-
+
-
+
-
-
-
+
+
+
-
+
@@ -198,7 +198,7 @@
-
+
@@ -234,6 +234,9 @@
+
+
@@ -307,4 +310,11 @@
+
+
+
+
+
+
+
diff --git a/NuGet.config b/NuGet.config
index 68f1e3a83e4..f3bf72016af 100644
--- a/NuGet.config
+++ b/NuGet.config
@@ -19,6 +19,7 @@
+
@@ -38,6 +39,9 @@
+
+
+
diff --git a/THIRD-PARTY-NOTICES.TXT b/THIRD-PARTY-NOTICES.TXT
index 5c4ac631770..c993b722b84 100644
--- a/THIRD-PARTY-NOTICES.TXT
+++ b/THIRD-PARTY-NOTICES.TXT
@@ -13,7 +13,7 @@ License notice for plotly.js
The MIT License (MIT)
-Copyright (c) 2021 Plotly, Inc
+Copyright (c) 2016-2024 Plotly Technologies Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/benchmarks/Aspire.Dashboard.Benchmarks/Aspire.Dashboard.Benchmarks.csproj b/benchmarks/Aspire.Dashboard.Benchmarks/Aspire.Dashboard.Benchmarks.csproj
index d075e13ae28..49d1ddf9ea7 100644
--- a/benchmarks/Aspire.Dashboard.Benchmarks/Aspire.Dashboard.Benchmarks.csproj
+++ b/benchmarks/Aspire.Dashboard.Benchmarks/Aspire.Dashboard.Benchmarks.csproj
@@ -2,7 +2,7 @@
Exe
- net10.0
+ net11.0
Aspire.Dashboard.Benchmarks
Aspire.Dashboard.Benchmarks
enable
diff --git a/docs/ci/native-cli-packaging.md b/docs/ci/native-cli-packaging.md
index 70421b85337..56a7e43a5f1 100644
--- a/docs/ci/native-cli-packaging.md
+++ b/docs/ci/native-cli-packaging.md
@@ -41,12 +41,12 @@ Linux native jobs do not sign ELF binaries in `build_sign_native`. For Linux, ex
The root `flake.nix` packages the stable Aspire CLI from the versioned GitHub release archive URLs and hashes tracked in `eng/nix/versions.json`. It is a binary package, not a Nix source build of this repository. This keeps the Nix package aligned with the same canonical signed native archive consumed by the other installers.
-For stable releases, the GitHub release assets must exist before the Nix manifest is updated. `release-publish-nuget` dispatches `.github/workflows/update-nix-cli-flake.yml` after `PublishReleaseAssetsJob` uploads the `aspire-cli-*` archives and `.sha512` sidecars to the GitHub release. The workflow runs:
+For stable releases, `release-publish-nuget`'s `UpdateNixPackageJob` dispatches `.github/workflows/update-nix-cli-flake.yml`. The job reads the `aspire-cli-*.tar.gz.sha512` checksums from the signed source build's `BlobArtifacts` and passes them to the workflow as inputs, so the manifest is built from the build — not from the GitHub release. This lets it run while the release is still a **draft** (immutable releases don't serve draft assets from the public download URL). The workflow runs:
```sh
-eng/nix/update-versions.sh --version
+eng/nix/update-versions.sh --version --sha512 osx-arm64= --sha512 osx-x64= --sha512 linux-arm64= --sha512 linux-x64=
```
-The workflow commits the Nix manifest change to the `update-baseline-` branch created by `release-github-tasks.yml`, then creates or updates the baseline PR. Merging that PR is the in-repo Nix "ship" step: it publishes the flake metadata that points at the already-published release assets. The updater reads the official `.sha512` assets and writes Nix-compatible SRI hashes. Do not point the manifest at mutable `aka.ms` channel URLs; Nix fixed-output fetches require stable versioned URLs.
+The workflow commits the Nix manifest change to the `update-baseline-` branch created by `release-github-tasks.yml`, then creates or updates the baseline PR. Merging that PR is the in-repo Nix "ship" step: it publishes the flake metadata that points at the versioned release download URLs (which go live when the release manager publishes the draft). When the `--sha512` inputs are supplied the updater uses them directly; run manually without them (against an already-published release) it downloads the official `.sha512` assets instead. Either way it writes Nix-compatible SRI hashes. Do not point the manifest at mutable `aka.ms` channel URLs; Nix fixed-output fetches require stable versioned URLs.
The Nix derivation writes `{"source":"nix"}` to `.aspire-install.json` next to the packaged native binary. `BundleService` treats this route as read-only and extracts the embedded bundle payload into the user-owned Aspire home instead of the Nix store.
diff --git a/docs/release-process.md b/docs/release-process.md
index 5aa5bc34b99..15630f5f9df 100644
--- a/docs/release-process.md
+++ b/docs/release-process.md
@@ -13,29 +13,48 @@ The Aspire release process uses these main automation components:
- Publishes Aspire CLI npm packages through ESRP/MicroBuild.
- Promotes the build to the GA channel via darc.
- Submits WinGet manifest PRs.
- - Optionally validates the Homebrew cask against the live GitHub release when `SkipHomebrewValidation=false` (cask version bumps themselves are submitted by upstream autobump; see [Installer channels](#installer-channels)).
- Optionally publishes the signed VS Code extension to the Visual Studio Marketplace.
- Dispatches the GitHub Actions workflow below as the `aspire-repo-bot` GitHub App and waits for it to complete.
- - Uploads `aspire-cli-*` archives from the source build's `BlobArtifacts` onto the GitHub Release as the `aspire-repo-bot`.
- - Dispatches the Nix flake update workflow after stable release assets are live.
+ - Uploads `aspire-cli-*` archives from the source build's `BlobArtifacts` onto the **draft** GitHub Release as the `aspire-repo-bot`.
+ - Dispatches the Nix flake update workflow, passing the `aspire-cli-*.tar.gz.sha512` checksums read from the source build's `BlobArtifacts` (so the manifest is built from the build, not the draft release).
2. **GitHub Actions workflow** (`.github/workflows/release-github-tasks.yml`)
- Creates Git tags.
- - Creates GitHub Releases.
+ - Creates **draft** GitHub Releases (see [Draft-then-publish release flow](#draft-then-publish-release-flow)).
- Creates merge-back PRs.
- Creates baseline version update branches and, when not deferred, PRs.
- Normally dispatched automatically by the AzDO pipeline above; it can also be run manually as a fallback for partial-failure re-runs.
-3. **GitHub Actions workflow** (`.github/workflows/update-nix-cli-flake.yml`)
- - Reads the stable release's official `.sha512` assets after `release-publish-nuget` uploads them.
+3. **GitHub Actions workflow** (`.github/workflows/release-notes-generate.md`) — agentic
+ - Triggered when the draft release is created.
+ - Replaces the placeholder release notes body with auto-generated notes against the live draft (via the gh-aw `update-release` safe output).
+4. **GitHub Actions workflow** (`.github/workflows/update-nix-cli-flake.yml`)
+ - Receives the CLI `.sha512` checksums from the AzDO pipeline (sourced from the source build's `BlobArtifacts`), so it can run while the release is still a draft. Manual runs against a published release omit the inputs and read the release's `.sha512` assets instead.
- Updates `eng/nix/versions.json`.
- Commits the Nix manifest update to the `update-baseline-` branch created by `release-github-tasks.yml`, then creates or updates the PR.
- Normally dispatched automatically by the AzDO pipeline; it can also be run manually as a fallback after the GitHub release assets are live.
-4. **GitHub Actions workflow** (`.github/workflows/extension-release.yml`)
+5. **GitHub Actions workflow** (`.github/workflows/homebrew-validate-release.yml`)
+ - Triggered when the release manager publishes the draft (i.e. `release: [published]`).
+ - Generates the Homebrew cask file from the just-published `aspire-cli-osx-*` assets and runs `brew audit --cask --online --signing` + a real `brew install`/`brew uninstall` cycle to catch problems before Homebrew/homebrew-cask's autobump PR is opened.
+6. **GitHub Actions workflow** (`.github/workflows/extension-release.yml`)
- Prepares a VS Code extension release PR.
- Bumps `extension/package.json`.
- Generates or updates `extension/CHANGELOG.md`.
- Defaults its comparison baseline to the latest stable Marketplace VSIX's embedded `extension/.version` commit SHA.
- Can run with `dry_run: true` in forks to validate changelog generation without bot secrets.
+## Draft-then-publish release flow
+
+GitHub's [immutable releases](https://docs.github.com/en/code-security/concepts/supply-chain-security/immutable-releases) lock release assets and the underlying tag at publish time. Once a release is published, the assets attached to it (and the tag itself) cannot be changed. The body and title remain editable, but everything else is frozen.
+
+Aspire's release flow has historically depended on mutating the released artifact: the agentic release-notes-generate workflow rewrites the body, and the AzDO pipeline's `PublishReleaseAssetsJob` uploads `aspire-cli-*` archives onto the release *after* it was created. With immutable releases enabled, all of those mutations must happen **before** the release is published.
+
+To support this, the release flow now creates the GitHub release as a **draft**:
+
+1. `release-github-tasks.yml` runs `gh release create --draft`, which writes the tag and creates a draft release with a placeholder body.
+2. `release-github-tasks.yml` then explicitly dispatches `release-notes-generate` via `workflow_dispatch` (passing the tag name), which rewrites the body via the gh-aw `update-release` safe output. It uses an explicit dispatch because GitHub Actions does [not fire `release` events](https://docs.github.com/en/actions/reference/workflows-and-actions/events-that-trigger-workflows#release) (including `created`) for draft releases. (Draft releases support body edits via the Releases REST API.)
+3. The AzDO pipeline's `PublishReleaseAssetsJob` uploads `aspire-cli-*` archives onto the draft via `gh release upload`. (Draft releases support asset upload via the Releases REST API.)
+4. **The release manager publishes the draft manually as a final step** — see [Step 5: Publish the draft release](#step-5-publish-the-draft-release).
+5. Publishing the draft fires `release: [published]`, which kicks off downstream workflows that need the live release: `release-update-support-mdx` (opens a PR on `microsoft/aspire.dev`) and `homebrew-validate-release` (validates the cask against the live download URLs). Both subscribe to `published` rather than `released` because GitHub does not reliably fire `released` when a release is published from a draft.
+
## Installer channels
Aspire ships through several channels. The release pipeline either submits the bump itself or validates a bump submitted upstream; the per-channel docs describe manifest shape, validation modes, and dogfooding workflows in detail.
@@ -44,10 +63,10 @@ Aspire ships through several channels. The release pipeline either submits the b
|---------|------------------------------|------------------|
| **NuGet** (libraries, AppHost SDK, `Aspire.Cli` tool packages) | `release-publish-nuget` pushes to NuGet.org | This document |
| **WinGet** (`winget install Microsoft.Aspire`) | `release-publish-nuget` submits manifest PRs to `microsoft/winget-pkgs` via `wingetcreate` | [`eng/winget/README.md`](../eng/winget/README.md) |
-| **Homebrew cask** (`brew install --cask aspire`) | Upstream Homebrew/homebrew-cask's [autobump workflow](https://github.com/Homebrew/homebrew-cask/blob/master/.github/workflows/autobump.yml) opens the bump PR on a 3-hour schedule, detecting the new version via the cask's `livecheck` block. `release-publish-nuget` validates the cask against the live GitHub release after asset upload only when `SkipHomebrewValidation=false` (skipped by default). | [`eng/homebrew/README.md`](../eng/homebrew/README.md) |
+| **Homebrew cask** (`brew install --cask aspire`) | Upstream Homebrew/homebrew-cask's [autobump workflow](https://github.com/Homebrew/homebrew-cask/blob/master/.github/workflows/autobump.yml) opens the bump PR on a 3-hour schedule, detecting the new version via the cask's `livecheck` block. `homebrew-validate-release.yml` validates the cask against the live GitHub release after the release manager publishes it. | [`eng/homebrew/README.md`](../eng/homebrew/README.md) |
| **`dotnet tool install -g Aspire.Cli`** | `release-publish-nuget` pushes the per-RID `Aspire.Cli.*.nupkg` packages to NuGet.org alongside the libraries | [`docs/specs/install-routes.md`](specs/install-routes.md) |
| **Install script** (`get-aspire-cli.sh` / `.ps1`) | No separate publication — the script downloads directly from the GitHub release assets attached in Step 1 | [`docs/specs/install-routes.md`](specs/install-routes.md), `eng/scripts/get-aspire-cli.*` |
-| **Nix flake** (`nix run github:microsoft/aspire#aspire-cli`) | `release-publish-nuget` dispatches `.github/workflows/update-nix-cli-flake.yml` after stable GitHub release assets are uploaded; the workflow adds the manifest update to the baseline version branch and creates or updates the PR | [`eng/nix/README.md`](../eng/nix/README.md), [`docs/ci/native-cli-packaging.md`](ci/native-cli-packaging.md) |
+| **Nix flake** (`nix run github:microsoft/aspire#aspire-cli`) | `release-publish-nuget` dispatches `.github/workflows/update-nix-cli-flake.yml`, passing the CLI `.sha512` checksums from the source build; the workflow adds the manifest update to the baseline version branch and creates or updates the PR | [`eng/nix/README.md`](../eng/nix/README.md), [`docs/ci/native-cli-packaging.md`](ci/native-cli-packaging.md) |
The CLI identifies which channel installed it via a per-install sidecar so that self-update can route back through the same channel. See [`docs/specs/install-routes.md`](specs/install-routes.md).
@@ -104,8 +123,7 @@ Before starting a release:
| `SkipWinGetPublish` | Set `true` if re-running after WinGet success. | `true` |
| `SkipGitHubTasks` | Set `true` to skip dispatching the GH workflow. | `false` |
| `SkipReleaseAssets` | Set `true` to skip uploading `aspire-cli-*` assets to the GitHub release. | `false` |
- | `SkipHomebrewValidation` | Set `false` to run Homebrew cask validation against the live GitHub release. | `true` |
- | `SkipNixPackageUpdate` | Set `true` if the Nix flake update was already added to the baseline version PR. Stable releases dispatch the updater after the GitHub release assets are uploaded; prereleases skip it. | `false` |
+ | `SkipNixPackageUpdate` | Set `true` if the Nix flake update was already added to the baseline version PR. Stable releases dispatch the updater with checksums from the source build; prereleases skip it. | `false` |
| `SkipVSCodeExtensionPublish` | Set `false` to publish the signed `aspire-vscode-extension` artifact to the Visual Studio Marketplace. | `true` |
| `NpmPublishOwners` | Single ESRP owner alias or email. Overrides must be one of the required owner aliases in `eng/pipelines/release-publish-nuget.yml` (currently `joperezr` or `ankj`). | `joperezr` |
| `NpmPublishApprovers` | Single ESRP approver alias or email. The approver must be a Microsoft address and must not be the same alias as the owner. | `adamratzman` |
@@ -115,8 +133,8 @@ Before starting a release:
4. Select the **Resources** button in the bottom right, then select the source build from the `aspire-build` dropdown.
- The picker shows all recent builds from the `microsoft-aspire` pipeline regardless of branch. Pick the build that corresponds to the release branch and version you intend to ship.
- Each build's tags are shown alongside its number. Verify the `release-version - X.Y.Z` tag matches the version you intend to ship before clicking **Run**. If the tag is missing, either re-run the source build after the tag-emitting change in `azure-pipelines.yml` is on that release branch or pass an explicit `ReleaseVersion` override.
-5. Click **Run** and monitor the pipeline. The final stage (`GitHubTasks`) dispatches `release-github-tasks.yml`, waits for it to complete, uploads the `aspire-cli-*` archives from the source build's `BlobArtifacts` onto the newly-created GitHub release, and then dispatches `update-nix-cli-flake.yml` for stable releases so `eng/nix/versions.json` is bumped from the live `.sha512` assets on the `update-baseline-` branch before the baseline PR is created or updated. If `SkipHomebrewValidation=false`, it also validates the Homebrew cask against that live release. The AzDO pipeline only succeeds if the enabled GitHub tasks, asset upload, Nix update dispatch, and optional Homebrew validation succeed.
-6. Verify packages appear on NuGet.org and npm, verify that the `aspire-cli-*` archives are attached to the GitHub release, and review the generated baseline version PR including the Nix flake manifest update.
+5. Click **Run** and monitor the pipeline. The final stage (`GitHubTasks`) dispatches `release-github-tasks.yml`, waits for it to complete, uploads the `aspire-cli-*` archives from the source build's `BlobArtifacts` onto the newly-created **draft** GitHub release, and then dispatches `update-nix-cli-flake.yml` for stable releases so `eng/nix/versions.json` is bumped from the source build's `.sha512` checksums on the `update-baseline-` branch before the baseline PR is created or updated. The AzDO pipeline only succeeds if the enabled GitHub tasks, asset upload, and Nix update dispatch succeed.
+6. Verify packages appear on NuGet.org and npm, verify that the `aspire-cli-*` archives are attached to the draft GitHub release, and review the generated baseline version PR including the Nix flake manifest update. Then proceed to [Step 5: Publish the draft release](#step-5-publish-the-draft-release).
To publish only the VS Code extension after merging an extension release PR, run the same `release-publish-nuget` pipeline, select the signed source build from that merge, and set:
@@ -130,7 +148,6 @@ To publish only the VS Code extension after merging an extension release PR, run
| `SkipNpmPointerPublish` | `true` |
| `SkipChannelPromotion` | `true` |
| `SkipWinGetPublish` | `true` |
-| `SkipHomebrewValidation` | `true` |
| `SkipGitHubTasks` | `true` |
| `SkipReleaseAssets` | `true` |
| `SkipNixPackageUpdate` | `true` |
@@ -167,7 +184,7 @@ Run this step only when releasing the VS Code extension independently of the nor
The GitHub workflow is normally dispatched by the AzDO pipeline as the `aspire-repo-bot` GitHub App, with its `authorize` job bypassed for the bot. If a GitHub-side step fails partway through and you need to re-run only the GitHub work, you can:
-1. Re-run the AzDO pipeline with completed AzDO-side work skipped, such as `SkipNuGetPublish`, `SkipNpmRidPublish`, `SkipNpmPointerPublish`, `SkipChannelPromotion`, `SkipWinGetPublish`, `SkipNixPackageUpdate`, `SkipHomebrewValidation`, and `SkipReleaseAssets` set as appropriate, keeping `SkipGitHubTasks: false`. The `GitHubTasks` stage will dispatch the workflow again with the right inputs, and the workflow's own `skip_*` idempotency makes the completed steps no-ops.
+1. Re-run the AzDO pipeline with completed AzDO-side work skipped, such as `SkipNuGetPublish`, `SkipNpmRidPublish`, `SkipNpmPointerPublish`, `SkipChannelPromotion`, `SkipWinGetPublish`, `SkipNixPackageUpdate`, and `SkipReleaseAssets` set as appropriate, keeping `SkipGitHubTasks: false`. The `GitHubTasks` stage will dispatch the workflow again with the right inputs, and the workflow's own `skip_*` idempotency makes the completed steps no-ops.
2. Or, navigate to Actions → **Release GitHub Tasks**, click **Run workflow**, and fill in the parameters manually:
| Parameter | Description | Example |
@@ -178,26 +195,48 @@ The GitHub workflow is normally dispatched by the AzDO pipeline as the `aspire-r
| `is_prerelease` | `true` for preview releases. | `false` |
| `dry_run` | `true` to validate without making changes. | `false` |
| `skip_tagging` | Skip if tag already created. | `false` |
- | `skip_github_release` | Skip if release already exists. | `false` |
+ | `skip_github_release` | Skip if draft release already exists. | `false` |
| `skip_merge_pr` | Skip if PR already created. | `false` |
| `skip_baseline_pr` | Skip if PR already created. | `false` |
Manual runs go through the normal `authorize` check (admin/maintain permission required).
-### Step 4: Post-Release Tasks (Manual)
+### Step 4: Verify and prepare to publish
After automation completes:
-1. **Review and merge automatically created PRs**:
+1. **Review and merge the merge-back PR**:
- Merge-back PR: `$RELEASE_BRANCH` → `main`.
- - Baseline version PR: updates `PackageValidationBaselineVersion`.
- - Baseline version PR also includes `eng/nix/versions.json` for stable releases.
-2. **Verify the release**:
- - Check the [GitHub Releases page](https://github.com/microsoft/aspire/releases).
+ - **Do not merge the baseline version PR yet.** It updates `PackageValidationBaselineVersion` and, for stable releases, `eng/nix/versions.json`, which points at the release's public `releases/download/v/...` asset URLs. Those URLs return 404 until the draft is published, so merging this PR before Step 5 would break `nix run github:microsoft/aspire#aspire-cli` on `main`. You merge it after publishing — see [Step 5](#step-5-publish-the-draft-release).
+2. **Verify draft release contents**:
+ - Open the draft on the [GitHub Releases page](https://github.com/microsoft/aspire/releases) (drafts appear above published releases).
+ - Confirm the `aspire-cli-*` archives are attached.
+ - Confirm the release-notes-generate workflow has rewritten the body. If the body still contains the placeholder text after ~30 minutes, check the [`release-notes-generate` runs](https://github.com/microsoft/aspire/actions/workflows/release-notes-generate.lock.yml) for failures and rerun via `workflow_dispatch` if needed.
+3. **Verify upstream channels**:
- Verify packages on [NuGet.org](https://www.nuget.org/packages?q=Aspire).
- Verify npm packages on the Microsoft npm profile.
- - Test installation: `dotnet new install Aspire.ProjectTemplates::VERSION` and `aspire update --self`.
-3. **Communicate**:
+
+### Step 5: Publish the draft release
+
+This is a **manual** step performed by the release manager. The release is created as a draft so that all mutations (release notes rewrite, CLI asset upload) can complete before publish — once published, GitHub's [immutable releases](https://docs.github.com/en/code-security/concepts/supply-chain-security/immutable-releases) policy locks the assets and tag. Publishing must therefore happen *after* Step 4 verification, not before.
+
+1. Navigate to the draft release on the [GitHub Releases page](https://github.com/microsoft/aspire/releases).
+2. Click **Edit** to do a final review — confirm the title is `Aspire `, the body looks correct, the tag is `v` pointing at the release commit, and the `aspire-cli-*` archives are attached.
+3. Uncheck **Set as a pre-release** if it is checked but this is a stable release (or check it for a preview release).
+4. Click **Publish release**.
+5. **Now merge the baseline version PR.** With the release published, its `eng/nix/versions.json` asset URLs resolve, so merging it updates `PackageValidationBaselineVersion` and the Nix manifest on `main` without breaking the flake.
+
+Publishing the draft fires the `release: [published]` event, which triggers:
+
+- [`release-update-support-mdx`](https://github.com/microsoft/aspire/actions/workflows/release-update-support-mdx.lock.yml): opens a draft PR on `microsoft/aspire.dev` to update the support mdx with the new release info.
+- [`homebrew-validate-release`](https://github.com/microsoft/aspire/actions/workflows/homebrew-validate-release.yml): runs `brew audit --cask --online --signing` + a real `brew install`/`brew uninstall` cycle against the cask generated from the just-published `aspire-cli-osx-*` assets.
+
+If either downstream workflow fails, the release itself is fine — the release is published and immutable. Investigate the failure on the workflow run, fix the underlying issue, and rerun via `workflow_dispatch` against the published tag.
+
+### Step 6: Post-Release Communication
+
+1. **Test installation**: `dotnet new install Aspire.ProjectTemplates::VERSION` and `aspire update --self`.
+2. **Communicate**:
- Update any tracking issues.
- Notify stakeholders.
@@ -218,11 +257,11 @@ These automations are designed to be idempotent and safe to re-run.
| MicroBuild npm Publish | Check the ESRP release result. If RID packages published but the pointer package did not, re-run with `SkipNuGetPublish: true`, `SkipNpmRidPublish: true`, `SkipNpmPointerPublish: false`, and `SkipChannelPromotion: true`; do not set `SkipNpmPointerPublish` until the pointer package is published. |
| Validate Published npm Package from Registry | Confirm the pointer package is visible on npm and that `npm install -g @microsoft/aspire-cli@` works. If registry propagation is slow, re-run with completed publish steps skipped after the package is visible. |
| Promote Build to Channel | Re-run with completed publish steps skipped. |
-| WinGet publishing / Homebrew validation | Re-run with the corresponding skip flags for completed work. |
+| WinGet publishing | Re-run with the corresponding skip flag for completed work. |
| Publish VS Code Extension to Marketplace | Check that `aspire-vscode-extension` contains one `.vsix`, `.manifest`, and `.signature.p7s`; verify the `AspireSecurePublishPipelineMarketplaceConnectionWithManagedIdentity` service connection identity is a Contributor on the Visual Studio Marketplace `microsoft-aspire` publisher; re-run with the already-completed `Skip*` flags set to `true`. |
| GitHubTasks dispatch | Re-run with completed AzDO-side work skipped and `SkipGitHubTasks: false`; set `SkipReleaseAssets` according to whether release asset upload already completed. |
-| Release asset upload | Re-run with `SkipGitHubTasks: true` and `SkipReleaseAssets: false` after the GitHub release exists. |
-| Nix flake update dispatch | Re-run with `SkipGitHubTasks: true`, `SkipReleaseAssets: true`, and `SkipNixPackageUpdate: false` after the stable GitHub release assets and `update-baseline-` branch exist. If the Nix manifest was already committed to the baseline PR, set `SkipNixPackageUpdate: true` instead. For prereleases, leave it skipped because the Nix manifest only tracks stable `x.y.z` releases. |
+| Release asset upload | Re-run with `SkipGitHubTasks: true` and `SkipReleaseAssets: false` after the draft GitHub release exists. |
+| Nix flake update dispatch | Re-run with `SkipGitHubTasks: true`, `SkipReleaseAssets: true`, and `SkipNixPackageUpdate: false` after the `update-baseline-` branch exists. The job sources checksums from the source build's `BlobArtifacts`, so it does not require the GitHub release assets to be uploaded first. If the Nix manifest was already committed to the baseline PR, set `SkipNixPackageUpdate: true` instead. For prereleases, leave it skipped because the Nix manifest only tracks stable `x.y.z` releases. |
### GitHub Actions failures
@@ -235,7 +274,7 @@ Re-run with the corresponding `skip_*` input set to `true` to skip steps that ha
| Authorize | Caller lacks admin/maintain permission, or the AzDO bot identity check failed. |
| Validate Version Format / Commit SHA | Fix the input parameters and re-run. |
| Create Tag | If the tag exists with the wrong SHA, resolve it manually. |
-| Create GitHub Release | Re-run with `skip_tagging: true`. |
+| Create GitHub Release (draft) | Re-run with `skip_tagging: true`. |
| Create Merge PR | Re-run with `skip_tagging: true` and `skip_github_release: true`. |
| Create Baseline PR | Re-run with all prior skips set to `true`. |
@@ -350,8 +389,8 @@ Official source build
-> signed native archives / native CLI packages
-> npm tarballs verified against the native archive
-> PackageArtifacts: NuGet packages
- -> BlobArtifacts: microsoft-aspire-cli*.tgz and aspire-cli-* release assets
- -> eng/nix/versions.json can be updated from the published aspire-cli-* release assets
+ -> BlobArtifacts: microsoft-aspire-cli*.tgz and aspire-cli-* archives + .sha512 sidecars
+ -> eng/nix/versions.json is updated from the build's aspire-cli-*.tar.gz.sha512 checksums
Azure DevOps release-publish-nuget.yml
-> PrepareArtifacts
@@ -369,22 +408,39 @@ Azure DevOps release-publish-nuget.yml
-> WinGetJob
-> GitHubTasks
-> dispatch release-github-tasks.yml as aspire-repo-bot
- -> upload aspire-cli-* assets to the GitHub release
- -> dispatch update-nix-cli-flake.yml as aspire-repo-bot (stable releases)
- -> validate Homebrew cask against the live release (only when SkipHomebrewValidation=false)
+ -> upload aspire-cli-* assets to the draft GitHub release
+ -> dispatch update-nix-cli-flake.yml as aspire-repo-bot (stable releases),
+ passing the build's aspire-cli-*.tar.gz.sha512 checksums as inputs
GitHub release-github-tasks.yml
-> create tag
- -> create GitHub release
+ -> create DRAFT GitHub release (with placeholder body)
-> create merge-back PR
-> create baseline version branch
-> create baseline version PR immediately only when Nix update is skipped or the workflow is run manually without deferral
-GitHub update-nix-cli-flake.yml
- -> read .sha512 assets from the live GitHub release
- -> update eng/nix/versions.json
+GitHub update-nix-cli-flake.yml (dispatched by UpdateNixPackageJob, stable releases)
+ -> receive the build's aspire-cli-*.tar.gz.sha512 checksums as inputs
+ -> update eng/nix/versions.json (no draft-release read needed)
-> commit the Nix manifest update to update-baseline-
-> create or update the baseline version PR
+
+GitHub release-notes-generate.lock.yml (dispatched by release-github-tasks.yml
+ via workflow_dispatch — draft releases
+ do not fire `release: created`)
+ -> agent rewrites the draft release body with real notes
+ via the gh-aw `update-release` safe output
+
+[Release manager]
+ -> reviews the draft release on github.com
+ -> clicks "Publish release"
+
+GitHub release-update-support-mdx.lock.yml (triggered on `release: published`)
+ -> opens draft PR on microsoft/aspire.dev
+
+GitHub homebrew-validate-release.yml (triggered on `release: published`)
+ -> generates aspire.rb from the just-published aspire-cli-osx-* assets
+ -> runs `brew audit --cask --online --signing` + brew install/uninstall
```
## Related documentation
diff --git a/docs/specs/bundle.md b/docs/specs/bundle.md
index 290dfe128e7..629c52efec0 100644
--- a/docs/specs/bundle.md
+++ b/docs/specs/bundle.md
@@ -31,10 +31,11 @@ This document specifies the **Aspire Bundle**, a self-contained distribution pac
The Aspire Bundle is a platform-specific archive containing the Aspire CLI and all runtime components:
- **Aspire CLI** (native AOT executable, includes native certificate management)
-- **Aspire Managed** (unified self-contained binary: Dashboard + AppHost Server + NuGet Helper)
+- **Aspire Managed** (self-contained AppHost Server, NuGet Helper, and Terminal Host)
+- **Aspire Dashboard** (Native AOT executable)
- **Developer Control Plane (DCP)** (no longer distributed via NuGet)
-**Key change**: DCP and Dashboard are now bundled with the CLI installation, not downloaded as NuGet packages. Dashboard, AppHost Server, and NuGet Helper are consolidated into a single `aspire-managed` binary that dispatches via subcommands. Certificate management is handled natively in the CLI (no subprocess needed). This:
+**Key change**: DCP and Dashboard are bundled with the CLI installation, not downloaded on first run. The Dashboard ships as a Native AOT executable, while AppHost Server, NuGet Helper, and Terminal Host share `aspire-managed`. Certificate management is handled natively in the CLI.
- Eliminates large NuGet package downloads on first run
- Ensures version consistency between CLI and runtime components
@@ -142,7 +143,7 @@ When a user runs `aspire run` with a TypeScript app host:
4. **CLI generates `appsettings.json`** for the AppHost Server with integration list
5. **CLI starts AppHost Server** using aspire-managed's server subcommand
6. **CLI starts guest app host** (TypeScript) which connects via JSON-RPC
-7. **AppHost Server orchestrates** containers, Dashboard (via aspire-managed dashboard), and DCP
+7. **AppHost Server orchestrates** containers, the Native AOT Dashboard, and DCP
---
@@ -156,18 +157,21 @@ aspire-{version}-{platform}/
├── aspire[.exe] # Native AOT CLI (~25 MB)
│ # (includes native certificate management)
│
-├── managed/ # Unified managed binary (~65 MB)
-│ └── aspire-managed[.exe] # Self-contained single-file executable
-│ # Subcommands: dashboard | server | nuget
+├── managed/
+│ └── aspire-managed[.exe] # Self-contained server/NuGet/terminal executable
+│
+├── dashboard/
+│ ├── Aspire.Dashboard[.exe] # Native AOT Dashboard
+│ └── wwwroot/ # Dashboard static assets
│
├── dcp/ # Developer Control Plane (~127 MB)
│ ├── dcp[.exe] # Native executable
│ └── ...
│
-└── (no more runtime/, dashboard/, aspire-server/, tools/ directories)
+└── (no more runtime/, aspire-server/, tools/ directories)
```
-**Key change from previous layout**: The separate `.NET Runtime` (~106 MB), `dashboard/` (~42 MB), `aspire-server/` (~19 MB), `tools/aspire-nuget/` (~5 MB), and `tools/dev-certs/` directories have been consolidated into a single `managed/aspire-managed` self-contained binary. Certificate management has been moved natively into the CLI itself, eliminating the need for a separate dev-certs tool.
+The bundle keeps the Native AOT Dashboard and its static assets separate from the self-contained `aspire-managed` host used for server, NuGet, and terminal operations.
**Total Bundle Size:**
- **Unzipped:** ~220 MB (down from ~323 MB — eliminated separate runtime)
@@ -295,7 +299,7 @@ The parent directory check supports the installed layout where the CLI binary li
|----------|-------------|---------|
| `ASPIRE_LAYOUT_PATH` | Root of the bundle | `/opt/aspire` |
| `ASPIRE_DCP_PATH` | DCP binaries location | `/opt/aspire/dcp` |
-| `ASPIRE_DASHBOARD_PATH` | Path used by Aspire.Hosting to locate the dashboard binary (now points to `aspire-managed`) | `/opt/aspire/managed/aspire-managed` |
+| `ASPIRE_DASHBOARD_PATH` | Path used by Aspire.Hosting to locate the Native AOT Dashboard | `/opt/aspire/dashboard/Aspire.Dashboard` |
| `ASPIRE_MANAGED_PATH` | CLI-only path for the `aspire-managed` binary | `/opt/aspire/managed/aspire-managed` |
| `ASPIRE_HOME` | Default Aspire state root and fallback bundle extraction root when no install-route sidecar selects an install-owned location | `/home/user/.aspire` |
| `ASPIRE_INTEGRATION_LIBS_PATH` | Path to copied project-reference integration DLLs for aspire-server assembly resolution | `/home/user/myapp/.aspire/integrations/apphosts/app-hash/project-layouts/items/fingerprint/libs` |
@@ -720,8 +724,12 @@ The bundle installs components as siblings under `~/.aspire/`, with the CLI bina
│
├── .aspire-bundle-version # Version marker (hex FNV-1a hash, written after extraction)
│
-├── managed/ # Unified managed binary (self-contained)
-│ └── aspire-managed # Subcommands: dashboard | server | nuget
+├── managed/
+│ └── aspire-managed # Subcommands: server | nuget | terminalhost
+│
+├── dashboard/
+│ ├── Aspire.Dashboard # Native AOT Dashboard
+│ └── wwwroot/ # Dashboard static assets
│
├── dcp/ # Developer Control Plane
│ └── dcp
@@ -737,7 +745,7 @@ The bundle installs components as siblings under `~/.aspire/`, with the CLI bina
- The CLI lives at `~/.aspire/bin/aspire` regardless of install method
- With self-extracting binaries, the CLI in `bin/` contains the embedded payload; `aspire setup` extracts siblings
- `.aspire-bundle-version` tracks the extracted version — extraction is skipped when hash matches
-- `aspire-managed` is a single self-contained binary replacing separate runtime, dashboard, aspire-server, and tools directories
+- `aspire-managed` remains the self-contained server/NuGet/terminal binary; the Dashboard is a separate Native AOT executable
- Certificate management is native to the CLI (no external tool needed)
- NuGet hives and settings are preserved across installations and re-extractions
- `LayoutDiscovery` finds the bundle by checking the CLI's parent directory for components
@@ -825,7 +833,8 @@ AppHost integration restore artifacts are cached under `/.aspire/inte
| Component | On Disk | Zipped |
|-----------|---------|--------|
| DCP (platform-specific) | ~286 MB | ~100 MB |
-| Aspire Managed (self-contained: Dashboard + Server + NuGet + .NET Runtime) | ~65 MB | ~25 MB |
+| Aspire Managed (self-contained Server + NuGet + Terminal Host) | ~114 MB | varies |
+| Aspire Dashboard (Native AOT) | ~60 MB | varies |
| CLI (native AOT, includes certificate management) | ~22 MB | ~10 MB |
| **Total** | **~373 MB** | **~135 MB** |
@@ -1313,11 +1322,12 @@ This section tracks the implementation progress of the bundle feature.
- `ICertificateToolRunner` abstraction
- `NativeCertificateToolRunner` - calls `CertificateManager` directly (no subprocess)
- `CertificateGeneration/` - vendored from aspnetcore, EventSource replaced with ILogger
-- [x] **Aspire Managed unified binary** - `src/Aspire.Managed/`
- - Self-contained single binary: `aspire-managed dashboard|server|nuget`
- - Replaces separate runtime, dashboard, aspire-server, and tools directories
+- [x] **Aspire Managed binary** - `src/Aspire.Managed/`
+ - Self-contained binary: `aspire-managed server|nuget|terminalhost`
+- [x] **Native AOT Dashboard** - `src/Aspire.Dashboard/`
- [x] **Bundle build tooling** - `tools/CreateLayout/`
- - Builds aspire-managed as self-contained single-file binary
+ - Builds aspire-managed as a self-contained single-file binary
+ - Builds Aspire.Dashboard as a Native AOT executable
- Copies DCP
- `--embed-in-cli` option creates self-extracting binary
- [x] **Installation scripts** - `eng/scripts/get-aspire-cli-pr.sh`, `eng/scripts/get-aspire-cli-pr.ps1`
@@ -1381,13 +1391,11 @@ The bundle is built using the `tools/CreateLayout` tool, which assembles all com
### Aspire Managed Build
-The `aspire-managed` binary is published as a self-contained single-file executable, which includes the .NET runtime. This eliminates the need to separately download and bundle the .NET SDK/runtime.
+The `aspire-managed` binary is published as a self-contained single-file executable. The Dashboard is published separately with Native AOT so Blazor does not expand the reflection and dynamic-code requirements of the server, NuGet, and terminal tools.
```text
-aspire-managed (self-contained, ~65 MB)
+aspire-managed (self-contained)
├── .NET 10 Runtime (embedded)
-├── ASP.NET Core Framework (embedded)
-├── Aspire.Dashboard (embedded)
├── Aspire.Hosting.RemoteHost / aspire-server (embedded)
├── NuGet Commands (embedded)
└── All managed dependencies
@@ -1401,10 +1409,11 @@ aspire-managed (self-contained, ~65 MB)
### Build Steps
-1. **Build aspire-managed** as a self-contained single-file binary (includes .NET runtime, Dashboard, AppHost Server, NuGet operations)
-2. **Download and copy DCP** binaries
-3. **Create archive** (tar.gz for Unix, ZIP for Windows) with `COPYFILE_DISABLE=1` to suppress macOS xattr headers
-4. **Create self-extracting binary** — appends tar.gz payload + 32-byte trailer to native AOT CLI
+1. **Build aspire-managed** as a self-contained single-file binary
+2. **Build Aspire.Dashboard** as a Native AOT executable
+3. **Download and copy DCP** binaries
+4. **Create archive** with both executables and Dashboard static assets
+5. **Create self-extracting binary** — appends tar.gz payload + 32-byte trailer to native AOT CLI
### Self-Extracting Binary Build
diff --git a/docs/specs/cli-output-formats.md b/docs/specs/cli-output-formats.md
index 350f22e00e8..e184f364fe7 100644
--- a/docs/specs/cli-output-formats.md
+++ b/docs/specs/cli-output-formats.md
@@ -508,6 +508,8 @@ The `devtools` category surfaces development-tooling recommendations. The `vscod
}
```
+The `isolated-launch.v1` capability indicates that `aspire run` accepts the `--isolated` option.
+
## MCP tooling
### `aspire mcp tools`
diff --git a/eng/Build.props b/eng/Build.props
index ff9d3b3bd51..a6c621c3e36 100644
--- a/eng/Build.props
+++ b/eng/Build.props
@@ -60,10 +60,17 @@
Other projects in the AspireWithMaui playground can still be built.
The aspireify-eval projects are intentionally un-aspirified sample apps used
as eval inputs for the aspireify skill — they do not import the repo's
- Directory.Build.props/targets and are not meant to be built by CI. -->
+ Directory.Build.props/targets and are not meant to be built by CI.
+ `.aspire/` holds throwaway projects the CLI scaffolds while running a polyglot
+ AppHost (for example integration-restore/IntegrationRestore.csproj). They pin the
+ released Aspire.Hosting version, so building them against the repo's -dev version
+ fails with NU1605. They are gitignored, but that does not keep them out of an
+ MSBuild glob — so running any polyglot playground would otherwise break the next
+ `./build.sh` until the directory was deleted by hand. -->
diff --git a/eng/Bundle.proj b/eng/Bundle.proj
index 4f6c79f644a..8f77476ef64 100644
--- a/eng/Bundle.proj
+++ b/eng/Bundle.proj
@@ -5,10 +5,11 @@
Usage: dotnet msbuild eng/Bundle.proj /p:TargetRid=linux-x64 /p:Configuration=Release
This project:
- 1. Publishes the unified managed binary (Aspire.Managed) as self-contained
- 2. Publishes native CLI (unless SkipNativeBuild=true)
- 3. Restores DCP package
- 4. Runs CreateLayout to assemble the bundle
+ 1. Publishes Aspire.Managed as self-contained
+ 2. Publishes the Dashboard with Native AOT
+ 3. Publishes native CLI (unless SkipNativeBuild=true)
+ 4. Restores DCP package
+ 5. Runs CreateLayout to assemble the bundle
Options:
- SkipNativeBuild=true: Skip building native CLI (use pre-built from artifacts)
@@ -38,6 +39,7 @@
$(RepoRoot)src\Aspire.Cli\Aspire.Cli.csproj
$(RepoRoot)src\Aspire.Managed\Aspire.Managed.csproj
+ $(RepoRoot)src\Aspire.Dashboard\Aspire.Dashboard.csproj
$(RepoRoot)src\Aspire.Hosting.AppHost\Aspire.Hosting.AppHost.csproj
$(RepoRoot)tools\CreateLayout\CreateLayout.csproj
@@ -97,10 +99,13 @@
<_ManagedBinlog Condition="'$(ContinuousIntegrationBuild)' == 'true'">-bl:$(ArtifactsLogDir)PublishManaged.binlog
+ <_DashboardBinlog Condition="'$(ContinuousIntegrationBuild)' == 'true'">-bl:$(ArtifactsLogDir)PublishDashboard.binlog
+
+
diff --git a/eng/Signing.props b/eng/Signing.props
index f31dc899365..892689f3c84 100644
--- a/eng/Signing.props
+++ b/eng/Signing.props
@@ -68,10 +68,13 @@
+
+
+
@@ -107,6 +110,8 @@
+
+
$(DotNetRuntimeNet8VersionForTesting)
$(DotNetRuntimeNet9VersionForTesting)
@@ -55,27 +55,24 @@
10.8.0
10.8.0
- 1.15.2
- 1.15.1
- 1.15.3
- 1.15.1
- 1.15.3
- 1.8.0
+ 1.17.0
+ 1.17.0
+ 1.17.0
+ 1.17.0
+ 1.17.0
+ 1.8.3
2.23.32-alpha
1.0.0
-
-
- 10.0.8
- 11.0.0-preview.6.26359.118
-
- 11.0.0-preview.6.26359.118
+ 11.0.0-rc.1.26413.103
+ 11.0.0-rc.1.26413.103
+ 11.0.0-rc.1.26413.103
+ 11.0.0-rc.1.26413.103
+ 11.0.0-rc.1.26413.103
diff --git a/eng/clipack/Common.projitems b/eng/clipack/Common.projitems
index 9baf2383d61..9b855a33292 100644
--- a/eng/clipack/Common.projitems
+++ b/eng/clipack/Common.projitems
@@ -182,7 +182,7 @@
<_ExtractedNativeBinaryPath Condition="$(CliRuntime.StartsWith('win-'))">$(_ExtractedNativeBinaryPath).exe
<_CliToolPublishBaseDir>$([MSBuild]::NormalizeDirectory($(IntermediateOutputPath), 'tool-publish'))
<_CliToolPublishDir>$([MSBuild]::NormalizeDirectory($(_CliToolPublishBaseDir), '$(CliRuntime)'))
- <_CliToolPointerPublishDir>$([MSBuild]::NormalizeDirectory($(_CliToolPublishBaseDir), 'pointer'))
+ <_CliToolPointerPublishDir>$([MSBuild]::NormalizeDirectory($(_CliToolPublishBaseDir), 'pointer-$(CliRuntime)'))
<_CliNpmPackageStagingDir>$([MSBuild]::NormalizeDirectory($(IntermediateOutputPath), 'npm-packages', '$(CliRuntime)'))
<_CliNpmPackageStagingDirArg>$(_CliNpmPackageStagingDir.TrimEnd('\').TrimEnd('/'))
<_PackageOutputPathArg>$(PackageOutputPath.TrimEnd('\').TrimEnd('/'))
@@ -190,9 +190,7 @@
- <_SharedPackToolProperties Include="CreateRidSpecificToolPackages=true" />
<_SharedPackToolProperties Include="PreBuiltCliBinaryPath=$(_ExtractedNativeBinaryPath)" />
- <_SharedPackToolProperties Include="PublishAot=true" />
<_SharedPackToolProperties Include="BundlePayloadPath=" />
<_SharedPackToolProperties Include="Configuration=$(Configuration)" />
<_SharedPackToolProperties Include="ContinuousIntegrationBuild=$(ContinuousIntegrationBuild)" />
@@ -223,6 +221,8 @@
<_PackToolProperties Include="@(_SharedPackToolProperties)" />
+ <_PackToolProperties Include="CreateRidSpecificToolPackages=true" />
+ <_PackToolProperties Include="PublishAot=true" />
<_PackToolProperties Include="RuntimeIdentifier=$(CliRuntime)" />
<_PackToolProperties Include="PublishDir=$(_CliToolPublishDir)" />
@@ -244,6 +244,8 @@
<_PackPointerProperties Include="@(_SharedPackToolProperties)" />
+ <_PackPointerProperties Include="CreateRidSpecificToolPackages=false" />
+ <_PackPointerProperties Include="PublishAot=false" />
<_PackPointerProperties Include="PublishDir=$(_CliToolPointerPublishDir)" />
<_PackPointerProperties Include="NoBuild=true" />
diff --git a/eng/dashboardpack/Common.projitems b/eng/dashboardpack/Common.projitems
index 556d61fcfcf..0f3233125c6 100644
--- a/eng/dashboardpack/Common.projitems
+++ b/eng/dashboardpack/Common.projitems
@@ -4,12 +4,15 @@
- net8.0
- true
+ net11.0
+ true
+ true
+ true
+ $(CanPublishDashboardNativeAot)
true
- true
+ $(CanPublishDashboardNativeAot)
false
false
$(ArtifactsShippingPackagesDir)
@@ -33,20 +36,29 @@
-
+
+ Condition="'$(SkipDashboardPublish)' != 'true'"
+ Properties="Configuration=$(Configuration);Platform=$(Platform);TargetFramework=$(TargetFramework);RuntimeIdentifier=$(DashboardRuntime);PlatformName=$(DashboardRuntime);PublishAot=true;SelfContained=true" />
+
+ <_DashboardExecutableName>Aspire.Dashboard
+ <_DashboardExecutableName Condition="$(DashboardRuntime.StartsWith('win-'))">$(_DashboardExecutableName).exe
+ <_DashboardPublishDirectory>$(DotNetOutputPath)Aspire.Dashboard/$(DashboardRuntime)/$(Configuration)/$(TargetFramework)/$(DashboardRuntime)/publish
+
+
+
<_PublishItems
- Include="$(DotNetOutputPath)Aspire.Dashboard/$(DashboardRuntime)/$(Configuration)/$(TargetFramework)/$(DashboardRuntime)/publish/**/*" />
+ Include="$(_DashboardPublishDirectory)/**/*" />
diff --git a/eng/dashboardpack/Sdk.targets b/eng/dashboardpack/Sdk.targets
index f903ca475d9..53efbd5df8c 100644
--- a/eng/dashboardpack/Sdk.targets
+++ b/eng/dashboardpack/Sdk.targets
@@ -7,7 +7,6 @@
$([MSBuild]::EnsureTrailingSlash('$(AspireDashboardDir)'))
$([MSBuild]::NormalizePath($(AspireDashboardDir), 'Aspire.Dashboard'))
$(AspireDashboardPath).exe
- $(AspireDashboardPath).dll
diff --git a/eng/github-ci/test-trigger-map.yml b/eng/github-ci/test-trigger-map.yml
index fc720dcc42f..359f33930a6 100644
--- a/eng/github-ci/test-trigger-map.yml
+++ b/eng/github-ci/test-trigger-map.yml
@@ -343,6 +343,7 @@ affected_project_rules:
- Aspire.AppHost.Sdk
- Aspire.Hosting.CodeGeneration.*
- Aspire.Hosting.Go
+ - Aspire.Hosting.Java
- Aspire.Hosting.JavaScript
- Aspire.Hosting.Python
- Aspire.Hosting.Rust
diff --git a/eng/homebrew/README.md b/eng/homebrew/README.md
index 280d11d2a29..e1719ffc581 100644
--- a/eng/homebrew/README.md
+++ b/eng/homebrew/README.md
@@ -74,20 +74,34 @@ what `brew install` fetches from the GitHub release URL.
|---|---|---|---|
| `.github/workflows/tests.yml` | Prerelease casks (artifacts only) | — | — |
| `azure-pipelines.yml` (prepare stage) | Stable or prerelease casks (artifacts only) | — | — |
-| `release-publish-nuget.yml` (release) | — | Stable cask, LiveRelease mode (only when `SkipHomebrewValidation=false`) | — (autobump handles bumps; see below) |
-
-The release pipeline's `HomebrewValidateJob` runs `validate-cask-artifact.sh`
-in LiveRelease mode against the cask emitted by the source build, after the
-release-asset upload step has attached the `aspire-cli-osx-*.tar.gz`
-archives to the GitHub release. This is the first point at which the
-cask's `url` (a `v#{version}` GitHub release-asset URL) actually resolves;
-the source-build prepare stage can only validate offline because the
-GitHub release for the version being built does not exist yet. Failures
-in this job catch problems that would otherwise only surface to end
-users running `brew install aspire`, or block Homebrew/homebrew-cask's
-autobump PR a few hours later. Gated by `SkipHomebrewValidation`, which
-defaults to `true`; the job only runs when `SkipHomebrewValidation=false`
-(opt in per release, or when re-running after a partial failure).
+| `.github/workflows/homebrew-validate-release.yml` (post-publish) | — | Stable cask, LiveRelease mode | — (autobump handles bumps; see below) |
+
+`.github/workflows/homebrew-validate-release.yml` runs `validate-cask-artifact.sh`
+in LiveRelease mode after the release manager publishes the draft GitHub
+release (it triggers on `release: [published]`). This is the first point
+at which the cask's `url` (a `v#{version}` GitHub release-asset URL)
+actually resolves; the source-build prepare stage can only validate
+offline because the GitHub release for the version being built does not
+exist yet, and the AzDO release pipeline now creates the GitHub release
+as a draft (assets on a draft are not served from the public
+`releases/download/v/...` URL that `--online`/`brew install`
+need). Failures in this workflow catch problems that would otherwise
+only surface to end users running `brew install aspire`, or block
+Homebrew/homebrew-cask's autobump PR a few hours later. Manual re-runs
+go through `workflow_dispatch` with the release version as input.
+
+> **Note:** The workflow regenerates the cask via
+> `eng/homebrew/generate-cask.sh --version ` rather than consuming a
+> prebuilt cask artifact from the source build. That makes
+> `generate-cask.sh` the de-facto single source of truth for the cask
+> file shape — if the source build ever needs to customize the cask
+> beyond what `generate-cask.sh` produces (custom `test do` block,
+> per-build template tweaks, etc.), this workflow will silently validate
+> a cask that doesn't match what would ship. Keep the source-build cask
+> generation and `generate-cask.sh` in sync, or upload the source-build
+> cask as a release asset and have this workflow download+validate it
+> instead. See [aspire#18068](https://github.com/microsoft/aspire/pull/18068)
+> for the discussion that introduced this trade-off.
### Submission: upstream autobump
@@ -129,7 +143,7 @@ cask URL points at validation time:
| Mode | Cask URL resolves? | Audit args | Used by |
|---|---|---|---|
-| `LiveRelease` | Yes — points at a live GitHub release | `brew audit --cask --online --signing` + `brew install`/`brew uninstall` | `release-publish-nuget.yml` `HomebrewValidateJob`, after `PublishReleaseAssetsJob` uploads the archives |
+| `LiveRelease` | Yes — points at a live GitHub release | `brew audit --cask --online --signing` + `brew install`/`brew uninstall` | `.github/workflows/homebrew-validate-release.yml`, on `release: [published]` after the human publishes the draft |
| `LiveArchives` | Not yet — release for `v#{version}` hasn't been published | `brew audit --cask --no-signing` (no `--online`) | `azure-pipelines.yml` Homebrew Cask job; `.github/workflows/tests.yml`; `dogfood.sh` PR validation |
Common to both modes:
@@ -151,12 +165,14 @@ source-build archives are unsigned CI artifacts.
The price is that LiveArchives doesn't run the `--online`-only checks:
github/gitlab repo probes, homepage redirect/404 detection, livecheck
-strategy resolution. LiveRelease in `HomebrewValidateJob` runs all of
-them on every released version, so a regression in any surfaces there.
+strategy resolution. LiveRelease in `homebrew-validate-release.yml` runs
+all of them on every released version, so a regression in any surfaces
+there.
`LiveRelease` is the contract that matches what
`Homebrew/homebrew-cask`'s own CI runs on the autobump PR — a clean run
-in `HomebrewValidateJob` implies the autobump PR will audit cleanly too.
+in `homebrew-validate-release.yml` implies the autobump PR will audit
+cleanly too.
To dogfood a GitHub Actions artifact locally, download the
`homebrew-cask-prerelease` artifact and the `cli-native-archives-osx-*`
diff --git a/eng/homebrew/prepare-cask-artifact.sh b/eng/homebrew/prepare-cask-artifact.sh
index 94e17ee48e4..02097d3ea91 100755
--- a/eng/homebrew/prepare-cask-artifact.sh
+++ b/eng/homebrew/prepare-cask-artifact.sh
@@ -31,7 +31,8 @@ OUTPUT_DIR=""
# resolve yet — the GH release for v#{version} hasn't been published". Callers
# that want the full upstream-CI-equivalent audit + brew install/uninstall must
# do so against an already-published cask via validate-cask-artifact.sh
-# directly, as HomebrewValidateJob does in release-publish-nuget.yml.
+# directly, as the homebrew-validate-release.yml GitHub workflow does on
+# release: [published].
VALIDATION_MODE="LiveArchives"
while [[ $# -gt 0 ]]; do
diff --git a/eng/homebrew/validate-cask-artifact.sh b/eng/homebrew/validate-cask-artifact.sh
index 36bb0387157..46bb6768897 100755
--- a/eng/homebrew/validate-cask-artifact.sh
+++ b/eng/homebrew/validate-cask-artifact.sh
@@ -185,7 +185,7 @@ echo ""
# * github/gitlab repo probes (e.g. "is microsoft/aspire archived?")
# * homepage redirect / 404 detection against aspire.dev
# * livecheck strategy resolution
-# All of these run in LiveRelease in `HomebrewValidateJob` for every
+# All of these run in LiveRelease in `homebrew-validate-release.yml` for every
# released version, so a regression in any of them surfaces there.
echo "Auditing cask via local tap..."
audit_args=(--cask --online --signing)
diff --git a/eng/nix/README.md b/eng/nix/README.md
index 97eebf7e2ad..bb32cc8193f 100644
--- a/eng/nix/README.md
+++ b/eng/nix/README.md
@@ -86,17 +86,17 @@ Use the overlay the same way:
## Updating the packaged version
-The stable GitHub release assets must exist before this manifest is updated. The `release-publish-nuget` Azure DevOps pipeline dispatches `.github/workflows/update-nix-cli-flake.yml` after stable CLI archives and `.sha512` sidecars are uploaded to the GitHub release. That workflow runs the updater below, commits the Nix manifest change to the `update-baseline-` branch created by `release-github-tasks.yml`, and creates or updates the baseline PR so the post-release stable version updates stay together.
+The `release-publish-nuget` Azure DevOps pipeline dispatches `.github/workflows/update-nix-cli-flake.yml` as part of a stable release. The pipeline reads the `aspire-cli-*.tar.gz.sha512` checksums from the signed source build's `BlobArtifacts` (the same artifacts it verifies and uploads to the release) and passes them to the workflow as inputs, so the manifest is built from the build rather than the GitHub release. This lets the manifest be produced while the release is still an unpublished **draft** — required for GitHub's immutable releases, where a draft's assets are not served from the public `releases/download/...` URL. The workflow commits the Nix manifest change to the `update-baseline-` branch created by `release-github-tasks.yml`, and creates or updates the baseline PR so the post-release stable version updates stay together.
-Merging the baseline PR is the in-repo Nix "ship" step: it updates the flake metadata in `main` to point at the already-published GitHub release assets and hashes. There is no separate Nix registry publish step in this repository.
+Merging the baseline PR is the in-repo Nix "ship" step: it updates the flake metadata in `main` to point at the GitHub release assets and hashes (the `url` fields are always the public versioned release download URLs, which become live once the release manager publishes the draft). There is no separate Nix registry publish step in this repository.
-To update the manifest manually after a stable Aspire release publishes native CLI assets to GitHub, pass the same stable version used by the release baseline PR:
+To update the manifest manually against an **already-published** stable release, pass the same stable version used by the release baseline PR:
```sh
eng/nix/update-versions.sh --version
```
-The script downloads each official `.sha512` checksum asset and rewrites `versions.json` with Nix SRI hashes. The manifest must use versioned GitHub release URLs, not mutable `aka.ms` channel redirects, so Nix fixed-output fetches remain reproducible.
+Run manually like this, the script downloads each official `.sha512` checksum asset from the published release and rewrites `versions.json` with Nix SRI hashes. When the release pipeline runs it instead, it passes `--sha512 =` for all four platforms so no release read happens (see the script header for the offline-mode contract). Either way the manifest uses versioned GitHub release URLs, not mutable `aka.ms` channel redirects, so Nix fixed-output fetches remain reproducible.
## Relationship to nixpkgs
diff --git a/eng/nix/update-versions.sh b/eng/nix/update-versions.sh
index 530a7929075..a893fe093eb 100755
--- a/eng/nix/update-versions.sh
+++ b/eng/nix/update-versions.sh
@@ -2,21 +2,47 @@
set -euo pipefail
-# This updater intentionally runs after a stable GitHub release already exists.
# The Nix package is a fixed-output binary package, so the manifest must point
# at immutable release asset URLs plus their hashes instead of branch builds,
-# mutable channel redirects, or locally produced artifacts.
+# mutable channel redirects, or locally produced artifacts. The `url` fields
+# written below are always the public github.com/.../releases/download/v/...
+# URLs that Nix consumers fetch after the release is published.
+#
+# The per-platform SHA512 digests can come from one of two sources:
+# 1. Default: read each official `.sha512` asset from the published GitHub
+# release over the public download URL (`curl`). Used by manual/post-publish
+# runs where the release already exists.
+# 2. Offline (`--sha512 =`): the digests are supplied directly by the
+# caller. The AzDO release pipeline uses this to pass the `.sha512` values it
+# already downloaded and verified from the signed source build's
+# BlobArtifacts, so the Nix manifest can be built before the draft release is
+# published (GitHub's immutable releases require every mutation to happen
+# while the release is still a draft, and draft assets are not served from
+# the public download URL). The digests are identical either way — they are
+# the same `.sha512` files that get uploaded to the release verbatim.
repo="microsoft/aspire"
version=""
output_path="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/versions.json"
+# Collected `=` overrides from --sha512. When any are supplied
+# the script runs in offline mode and every platform must be provided (no curl).
+sha512_overrides=()
show_help() {
cat <<'EOF'
Usage: eng/nix/update-versions.sh --version VERSION [--repo OWNER/REPO] [--output-path PATH]
+ [--sha512 RID=HEX ...]
Updates eng/nix/versions.json from stable Aspire CLI GitHub release assets.
The script reads each official .sha512 checksum asset and converts it to the
Nix SRI hash format used by fetchurl.
+
+By default the .sha512 digests are read from the published GitHub release over
+the public download URL. Pass --sha512 RID=HEX (one per platform RID:
+osx-arm64, osx-x64, linux-arm64, linux-x64) to supply the digests directly and
+skip the network read entirely. When any --sha512 is passed, all four platforms
+must be supplied. This is how the release pipeline feeds the checksums it
+already verified from the source build so the manifest can be produced before
+the draft release is published.
EOF
}
@@ -46,6 +72,21 @@ while [[ $# -gt 0 ]]; do
output_path="$2"
shift 2
;;
+ --sha512)
+ # Format: =, e.g. osx-arm64=1a2b... The value is
+ # validated (128-char hex) later, in hex_sha512_to_sri, so a malformed
+ # digest fails the same way whether it came from --sha512 or from curl.
+ if [[ $# -lt 2 || -z "$2" ]]; then
+ echo "error: --sha512 requires a value of the form =" >&2
+ exit 1
+ fi
+ if [[ "$2" != *=* ]]; then
+ echo "error: --sha512 value '$2' must be of the form =" >&2
+ exit 1
+ fi
+ sha512_overrides+=("$2")
+ shift 2
+ ;;
-h|--help)
show_help
exit 0
@@ -63,6 +104,30 @@ if [[ -z "$version" ]]; then
exit 1
fi
+# Offline mode is engaged when the caller supplies any --sha512 override. In that
+# mode every platform must be provided so the manifest is complete and no curl
+# happens; mixing supplied and fetched digests is rejected to keep the result
+# reproducible.
+offline_mode="false"
+if [[ ${#sha512_overrides[@]} -gt 0 ]]; then
+ offline_mode="true"
+fi
+
+# Returns the supplied SHA512 hex for a RID from the --sha512 overrides, or a
+# non-zero exit if none was provided. Portable to bash 3.2 (no associative
+# arrays) so the script still runs on stock macOS bash used by local test runs.
+sha512_override_for() {
+ local rid="$1"
+ local pair
+ for pair in "${sha512_overrides[@]}"; do
+ if [[ "$pair" == "$rid="* ]]; then
+ printf '%s' "${pair#*=}"
+ return 0
+ fi
+ done
+ return 1
+}
+
# The in-repo flake tracks latest stable CLI acquisition assets. Preview/daily
# channels can move independently and are intentionally not written here because
# Nix fixed-output fetches must be reproducible after a consumer pins this repo.
@@ -117,15 +182,25 @@ temp_path="${output_path}.tmp"
archive_url="${asset_base_url}/${archive_name}"
checksum_url="${archive_url}.sha512"
- echo "Reading ${checksum_url}" >&2
- # curl must fail loudly here. A missing asset usually means the release
- # pipeline dispatched this workflow before PublishReleaseAssetsJob finished
- # or the release was re-run with CLI asset upload skipped.
- checksum_contents="$(curl -fsSL "$checksum_url")"
- # The release checksum sidecar can be either:
+ # The checksum sidecar can be either:
#
#
# Only the first token is the digest consumed by Nix's SRI hash format.
+ # This is true for both the release .sha512 asset and the build-provided
+ # override, so the same parse applies to whichever source is used.
+ if [[ "$offline_mode" == "true" ]]; then
+ if ! checksum_contents="$(sha512_override_for "$rid")"; then
+ echo "error: no --sha512 override supplied for rid '$rid'. Offline mode requires all four platforms (osx-arm64, osx-x64, linux-arm64, linux-x64)." >&2
+ exit 1
+ fi
+ echo "Using supplied SHA512 for ${archive_name} (offline mode; no release read)" >&2
+ else
+ echo "Reading ${checksum_url}" >&2
+ # curl must fail loudly here. A missing asset usually means the release
+ # pipeline dispatched this workflow before PublishReleaseAssetsJob finished
+ # or the release was re-run with CLI asset upload skipped.
+ checksum_contents="$(curl -fsSL "$checksum_url")"
+ fi
read -r checksum _ <<< "$checksum_contents"
hash="$(hex_sha512_to_sri "$checksum")"
diff --git a/eng/pipelines/azure-pipelines.yml b/eng/pipelines/azure-pipelines.yml
index c49dbe1a760..bddb62145ef 100644
--- a/eng/pipelines/azure-pipelines.yml
+++ b/eng/pipelines/azure-pipelines.yml
@@ -365,8 +365,9 @@ extends:
# IMPORTANT: This artifact is ALSO consumed by the `template_tests`
# stage. It must contain every Aspire.* nupkg the templates
# transitively reference — including per-RID arch-specific
- # Aspire.Hosting.Orchestration. and Aspire.Dashboard.Sdk.
- # packages produced by the managed build. If a future refactor
+ # Aspire.Hosting.Orchestration. packages produced by the
+ # managed build. Native Dashboard RID packages are produced by
+ # the matching native jobs. If a future refactor
# moves any of those out of Shipping/, template_tests will start
# failing with restore errors.
- task: 1ES.PublishPipelineArtifact@1
@@ -375,16 +376,6 @@ extends:
path: '$(Build.SourcesDirectory)/artifacts/packages/$(_BuildConfig)/Shipping'
artifactName: managed_packages_shipping
- # Dashboard runtime zips ship from artifacts/DashboardArtifacts///
- # (per eng/dashboardpack/Common.projitems) and are picked up by
- # Publishing.props _DashboardFilesToPublish. They sit outside packages/,
- # so they need their own pipeline-artifact handoff to assemble.
- - task: 1ES.PublishPipelineArtifact@1
- displayName: 🟣Publish dashboard artifacts for assemble
- inputs:
- path: '$(Build.SourcesDirectory)/artifacts/DashboardArtifacts/$(_BuildConfig)'
- artifactName: managed_dashboard_artifacts
-
- ${{ if and(notin(variables['Build.Reason'], 'PullRequest'), eq(variables['Build.SourceBranch'], 'refs/heads/main')) }}:
- template: /eng/common/templates-official/job/onelocbuild.yml@self
parameters:
@@ -565,7 +556,8 @@ extends:
-Project '$(System.TeamProject)' `
-BuildId '$(Build.BuildId)' `
-ArchivesTargetDir "$(Build.SourcesDirectory)/artifacts/signed-archives/$(_BuildConfig)" `
- -NupkgsTargetDir "$(Build.SourcesDirectory)/artifacts/native-cli-packages/$(_BuildConfig)"
+ -NupkgsTargetDir "$(Build.SourcesDirectory)/artifacts/native-cli-packages/$(_BuildConfig)" `
+ -DashboardArtifactsTargetDir "$(Build.SourcesDirectory)/artifacts/DashboardArtifacts/$(_BuildConfig)"
displayName: 🟣Download native archives (parallel)
env:
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
@@ -653,13 +645,26 @@ extends:
artifact: aspire-vscode-extension
targetPath: '$(Build.SourcesDirectory)/artifacts/packages/$(_BuildConfig)/vscode'
- # Dashboard runtime zips originate at artifacts/DashboardArtifacts//
- # and are scanned by _DashboardFilesToPublish at publish time.
- - task: DownloadPipelineArtifact@2
- displayName: 🟣Download dashboard artifacts
- inputs:
- artifact: managed_dashboard_artifacts
- targetPath: '$(Build.SourcesDirectory)/artifacts/DashboardArtifacts/$(_BuildConfig)'
+ # Native jobs package the signed Dashboard executable for their RID.
+ # Stage those nupkgs only after the npm signing pass so Arcade does
+ # not reopen and re-sign their already-signed nested executable.
+ - pwsh: |
+ $ErrorActionPreference = 'Stop'
+ $sourceRoot = "$(Build.SourcesDirectory)/artifacts/native-cli-packages/$(_BuildConfig)"
+ $shipping = "$(Build.SourcesDirectory)/artifacts/packages/$(_BuildConfig)/Shipping"
+ $packages = @(Get-ChildItem -Path $sourceRoot -Filter "Aspire.Dashboard.Sdk.*.nupkg" -File -Recurse)
+ if ($packages.Count -ne 7) {
+ throw "Expected 7 Native AOT Dashboard RID packages, found $($packages.Count): $($packages.FullName -join ', ')"
+ }
+ foreach ($package in $packages) {
+ Copy-Item -LiteralPath $package.FullName -Destination $shipping -Force
+ }
+
+ $dashboardArchives = @(Get-ChildItem -Path "$(Build.SourcesDirectory)/artifacts/DashboardArtifacts/$(_BuildConfig)" -Filter "aspire-dashboard-*.zip" -File -Recurse)
+ if ($dashboardArchives.Count -ne 7) {
+ throw "Expected 7 Native AOT Dashboard runtime archives, found $($dashboardArchives.Count): $($dashboardArchives.FullName -join ', ')"
+ }
+ displayName: 🟣Stage Native AOT Dashboard packages
- pwsh: |
Get-ChildItem -Path "$(Build.SourcesDirectory)/artifacts/packages" -File -Recurse |
diff --git a/eng/pipelines/release-publish-nuget.yml b/eng/pipelines/release-publish-nuget.yml
index 99a6395c819..6125911d0bb 100644
--- a/eng/pipelines/release-publish-nuget.yml
+++ b/eng/pipelines/release-publish-nuget.yml
@@ -4,17 +4,20 @@
# 1. Downloads signed packages from a specified build
# 2. Publishes packages to NuGet.org and npm
# 3. Promotes the build to the Aspire GA channel via darc
-# 4. Submits WinGet manifests and, when SkipHomebrewValidation=false,
-# validates the Homebrew cask
+# 4. Submits WinGet manifests
# 5. Optionally publishes the signed VS Code extension to the Marketplace
# 6. Dispatches the release-github-tasks GitHub Actions workflow as the
-# aspire-repo-bot GitHub App (tag, GitHub Release, merge-back PR,
+# aspire-repo-bot GitHub App (tag, DRAFT GitHub Release, merge-back PR,
# baseline PR) and waits for it to complete
# 7. Uploads aspire-cli-* archives from the source build's BlobArtifacts
-# onto the GitHub Release as the aspire-repo-bot
+# onto the draft GitHub Release as the aspire-repo-bot
# 8. Dispatches the Nix flake manifest update workflow after stable release
# assets are live
#
+# The release manager publishes the prepared draft release manually as the
+# final step. Homebrew cask validation runs post-publish in
+# .github/workflows/homebrew-validate-release.yml (on release: [published]).
+#
# For full documentation, see: docs/release-process.md
trigger: none # Manual trigger only
@@ -86,11 +89,6 @@ parameters:
type: boolean
default: false
- - name: SkipHomebrewValidation
- displayName: '[Advanced] Skip Homebrew cask validation against live GitHub release (default; set false to opt in)'
- type: boolean
- default: true
-
- name: SkipNixPackageUpdate
displayName: '[Advanced] Skip Nix flake update on baseline PR (re-run after success)'
type: boolean
@@ -2116,13 +2114,7 @@ extends:
} elseif ("${{ parameters.DryRun }}" -eq "true") {
Write-Host " (verify only; no upload in dry-run)"
} else {
- Write-Host " (uploaded after GitHub Tasks job)"
- }
- Write-Host "║ Homebrew Val: ${{ parameters.SkipHomebrewValidation }}" -NoNewline
- if ("${{ parameters.SkipHomebrewValidation }}" -eq "true") {
- Write-Host " (SKIPPED)"
- } else {
- Write-Host " (validates cask against live GH release after asset upload)"
+ Write-Host " (uploaded to draft release after GitHub Tasks job)"
}
Write-Host "║ Nix Flake: ${{ parameters.SkipNixPackageUpdate }}" -NoNewline
if ("${{ parameters.SkipNixPackageUpdate }}" -eq "true") {
@@ -2346,56 +2338,56 @@ extends:
dryRun: ${{ parameters.DryRun }}
# ===== STAGE 3: GITHUB TASKS =====
- # Four responsibilities, all running as (or against) the aspire-repo-bot
+ # Three responsibilities, all running as (or against) the aspire-repo-bot
# GitHub App:
#
# 1. DispatchGitHubTasksJob — dispatches the release-github-tasks
- # GitHub Actions workflow (tag, GitHub Release, merge-back PR,
+ # GitHub Actions workflow (tag, DRAFT GitHub Release, merge-back PR,
# baseline PR) and polls the run to completion. Fails the pipeline
# if the workflow doesn't succeed.
#
# 2. PublishReleaseAssetsJob — downloads aspire-cli-* archives from
# the signed source build's BlobArtifacts, verifies their SHA512s,
- # and uploads them as assets on the GitHub release that the
- # dispatch job just created.
+ # and uploads them as assets on the draft GitHub release that the
+ # dispatch job just created. Asset upload against drafts is
+ # supported by the Releases REST API.
#
# 3. UpdateNixPackageJob — dispatches the update-nix-cli-flake
- # GitHub Actions workflow after release asset upload. The workflow
- # reads the live .sha512 assets, commits eng/nix/versions.json to
- # the update-baseline- branch, and opens the PR from that
- # branch (release-github-tasks.yml created only the branch via
+ # GitHub Actions workflow. It reads the aspire-cli-*.tar.gz.sha512
+ # checksums from the signed source build's BlobArtifacts and passes
+ # them to the workflow as inputs, so the manifest is built from the
+ # build (not the draft release, whose assets aren't publicly
+ # downloadable). The workflow commits eng/nix/versions.json to the
+ # update-baseline- branch and opens the PR from that branch
+ # (release-github-tasks.yml created only the branch via
# defer_baseline_pr=true; PR creation is handled here).
#
- # 4. HomebrewValidateJob — runs the full upstream-equivalent cask
- # validation (`brew audit --cask --online --signing` + real
- # `brew install`/`brew uninstall`) against the cask generated by
- # the source build, with the live GitHub release URL it points
- # at. This is the moment when the URL is actually reachable —
- # the source-build prepare stage can only validate offline because
- # the GitHub release for the version being built does not exist
- # yet. Catches problems that would otherwise only surface to
- # end users (or block Homebrew/homebrew-cask's autobump PR).
+ # After these jobs succeed the release is a fully-prepared DRAFT — the
+ # release manager publishes it manually as a final step (see
+ # docs/release-process.md "Publish the draft release"). The draft-first
+ # flow is required for compatibility with GitHub's immutable releases
+ # (https://docs.github.com/en/code-security/concepts/supply-chain-security/immutable-releases):
+ # publishing the release locks assets + tag, so every mutation must
+ # happen before publish.
+ #
+ # Homebrew cask validation against the live GitHub release used to
+ # run as a fourth job in this stage. It now lives in
+ # .github/workflows/homebrew-validate-release.yml and runs on the
+ # `release: [published]` event, i.e. only once the release manager
+ # publishes the draft and the asset URLs become public. See that
+ # workflow for details.
#
# Each job has its own skip flag (SkipGitHubTasks / SkipReleaseAssets /
- # SkipNixPackageUpdate / SkipHomebrewValidation) so partial-failure
- # re-runs can recover any piece independently. Skipping all four skips
- # the stage entirely.
+ # SkipNixPackageUpdate) so partial-failure re-runs can recover any piece
+ # independently. Skipping all three skips the stage entirely.
#
# DryRun behavior: this stage still runs when DryRun=true. DryRun is
# propagated to the GH workflow as dry_run=true (keeps it from
# creating tags/releases/PRs) and to the asset script (downloads and
- # verifies SHA512s but skips the gh release upload). When
- # SkipHomebrewValidation=false, HomebrewValidateJob also runs under DryRun
- # — it does not publish anything, it only audits and `brew install`/
- # `brew uninstall` against a public URL. The Nix workflow is dispatched
- # with dry_run=true and intentionally does not read release assets in
- # that mode because the AzDO dry-run path does not create/upload a live
- # GitHub release. If the release for the version being validated does not
- # yet exist when Homebrew validation runs (DryRun, or a re-run after
- # assets were already uploaded), the job is expected to surface that as a
- # real failure rather than be silently skipped. This lets a release
- # manager validate the full AzDO → GitHub path end-to-end without
- # performing a real release.
+ # verifies SHA512s but skips the gh release upload). The Nix workflow is
+ # dispatched with dry_run=true and intentionally does not read release
+ # assets in that mode because the AzDO dry-run path does not create/upload
+ # a live GitHub release.
- stage: GitHubTasks
displayName: 'Dispatch GitHub Release Tasks'
# PrepareArtifacts is listed explicitly (in addition to Release) so the
@@ -2417,8 +2409,7 @@ extends:
and(
eq('${{ parameters.SkipNixPackageUpdate }}', 'false'),
eq('${{ parameters.IsPrerelease }}', 'false')
- ),
- eq('${{ parameters.SkipHomebrewValidation }}', 'false')
+ )
)
)
jobs:
@@ -2650,13 +2641,17 @@ extends:
ASPIRE_BOT_APP_ID: $(aspire-bot-app-id)
ASPIRE_BOT_PRIVATE_KEY: $(aspire-bot-private-key)
- # Dispatch the Nix manifest update workflow only after the GitHub
- # release assets are live. The updater reads the release .sha512
- # assets, commits eng/nix/versions.json to the update-baseline-
- # branch created by release-github-tasks.yml (which deferred PR creation
- # via defer_baseline_pr=true), and opens the PR from that branch.
- # Accepting 'Skipped' supports partial-failure re-runs where the
- # assets were already uploaded and SkipReleaseAssets=true is used.
+ # Dispatch the Nix manifest update workflow. The checksums come from
+ # the signed source build's BlobArtifacts (the .sha512 sidecars this
+ # job downloads below), NOT from the GitHub release, so the manifest
+ # can be produced while the release is still an unpublished draft —
+ # required for immutable releases. The updater commits
+ # eng/nix/versions.json to the update-baseline- branch created
+ # by release-github-tasks.yml (which deferred PR creation via
+ # defer_baseline_pr=true) and opens the PR from that branch. dependsOn
+ # PublishReleaseAssetsJob is kept for ordering (branch creation +
+ # single release upload), and accepting 'Skipped' supports
+ # partial-failure re-runs where SkipReleaseAssets=true is used.
- job: UpdateNixPackageJob
displayName: 'Update baseline PR with Nix flake manifest'
dependsOn: PublishReleaseAssetsJob
@@ -2687,10 +2682,56 @@ extends:
displayName: 'Checkout repo (for dispatch script)'
fetchDepth: 1
+ # Download the aspire-cli-* .sha512 sidecars from the source build.
+ # These are the checksums we forward to the Nix updater so it never
+ # has to read the (draft, non-public) GitHub release assets. Only
+ # the tiny .sha512 files are needed here — not the archives — so the
+ # glob is narrowed accordingly. See PublishReleaseAssetsJob for the
+ # broader '**/aspire-cli-*' download and the reason the '**/' prefix
+ # is required (the artifact name is a path prefix on each item).
+ - download: aspire-build
+ displayName: 'Download aspire-cli-*.sha512 from Source Build'
+ artifact: BlobArtifacts
+ patterns: '**/aspire-cli-*.sha512'
+
- pwsh: |
+ $ErrorActionPreference = 'Stop'
+ $version = "$(ReleaseVersionEffective)"
+ $assetsDir = Join-Path "$(Pipeline.Workspace)" 'aspire-build/BlobArtifacts'
+
+ # The Nix flake ships the .tar.gz (macOS/Linux) archives only, so
+ # read just those four RIDs' checksums. Map each to the workflow
+ # input name expected by update-nix-cli-flake.yml.
+ $ridToInput = [ordered]@{
+ 'osx-arm64' = 'sha512_osx_arm64'
+ 'osx-x64' = 'sha512_osx_x64'
+ 'linux-arm64' = 'sha512_linux_arm64'
+ 'linux-x64' = 'sha512_linux_x64'
+ }
+
$inputs = @{
- release_version = "$(ReleaseVersionEffective)"
- dry_run = ([System.Convert]::ToBoolean("${{ parameters.DryRun }}")).ToString().ToLowerInvariant()
+ release_version = $version
+ dry_run = ([System.Convert]::ToBoolean("${{ parameters.DryRun }}")).ToString().ToLowerInvariant()
+ }
+
+ foreach ($rid in $ridToInput.Keys) {
+ $shaPath = Join-Path $assetsDir "aspire-cli-$rid-$version.tar.gz.sha512"
+ if (-not (Test-Path $shaPath)) {
+ Write-Host "ERROR: No .sha512 companion found for aspire-cli-$rid-$version.tar.gz (expected at $shaPath). The source build must produce the CLI archives and their checksums before the Nix manifest can be built." -ForegroundColor Red
+ exit 1
+ }
+
+ # .sha512 files emitted by the build are a single line:
+ # [whitespace]. Take the first token and
+ # lowercase it, matching publish-release-cli-assets.ps1.
+ $hex = ((Get-Content $shaPath -Raw).Trim() -split '\s+')[0].ToLower()
+ if ($hex -notmatch '^[0-9a-f]{128}$') {
+ Write-Host "ERROR: '$shaPath' did not contain a 128-char hex SHA512 (got '$hex')." -ForegroundColor Red
+ exit 1
+ }
+
+ $inputs[$ridToInput[$rid]] = $hex
+ Write-Host " $($ridToInput[$rid]) = $hex"
}
& "$(Build.SourcesDirectory)/eng/pipelines/scripts/dispatch-release-github-tasks.ps1" `
@@ -2714,67 +2755,3 @@ extends:
condition: always()
env:
DISPATCHED_RUN_URL: $(DispatchedRunUrl)
-
- # Validate the generated Homebrew cask against the live GitHub
- # release. Runs `brew audit --cask --online --signing` and a real
- # `brew install`/`brew uninstall` against the cask file produced by
- # the source build. The cask URL points at
- # github.com/microsoft/aspire/releases/download/v#{version}/..., so
- # the release for the version being built must already exist for
- # this job to pass — normally that happens earlier in this stage
- # via PublishReleaseAssetsJob. The dependsOn below is purely
- # temporal; the cask artifact itself comes from the aspire-build
- # resource, not from PublishReleaseAssetsJob. Accepting 'Skipped'
- # alongside Succeeded lets you re-run with SkipReleaseAssets=true
- # against a previously uploaded release; if the release is missing
- # the job is expected to fail loudly rather than be silently
- # gated out.
- #
- # Modeled on PublishReleaseAssetsJob (regular buildJob with checkout
- # + a `download: aspire-build` step) rather than WingetJob's
- # releaseJob + templateContext.inputs pattern, because we need both
- # to check out the repo (for eng/homebrew/validate-cask-artifact.sh)
- # and to consume an artifact from the source build — and 1ES PT's
- # releaseJob enforces `checkout: none`.
- - job: HomebrewValidateJob
- displayName: 'Validate Homebrew Cask against live release'
- dependsOn: PublishReleaseAssetsJob
- condition: |
- and(
- eq('${{ parameters.SkipHomebrewValidation }}', 'false'),
- in(dependencies.PublishReleaseAssetsJob.result, 'Succeeded', 'SucceededWithIssues', 'Skipped')
- )
- timeoutInMinutes: 30
- pool:
- name: Azure Pipelines
- vmImage: macOS-latest-internal
- os: macOS
- templateContext:
- # No ESRP publish in this job (read-only brew audit / brew install of a public cask).
- # Skip the auto-injected publish auth task.
- mb:
- publish:
- enabled: false
- steps:
- - checkout: self
- displayName: 'Checkout repo (for validate-cask-artifact.sh)'
- fetchDepth: 1
-
- - download: aspire-build
- displayName: 'Download Homebrew Cask from Source Build'
- artifact: homebrew-cask-stable
-
- - bash: |
- set -euo pipefail
- cask_file="$(Pipeline.Workspace)/aspire-build/homebrew-cask-stable/aspire.rb"
- if [[ ! -f "$cask_file" ]]; then
- echo "##[error]Expected cask file not found: $cask_file"
- ls -la "$(Pipeline.Workspace)/aspire-build/homebrew-cask-stable" || true
- exit 1
- fi
-
- "$(Build.SourcesDirectory)/eng/homebrew/validate-cask-artifact.sh" \
- --cask-file "$cask_file" \
- --channel stable \
- --validation-mode LiveRelease
- displayName: '🟣Validate cask against live GitHub release'
diff --git a/eng/pipelines/templates/build_sign_native.yml b/eng/pipelines/templates/build_sign_native.yml
index 9dd1188f9dc..c34a9c0e2fa 100644
--- a/eng/pipelines/templates/build_sign_native.yml
+++ b/eng/pipelines/templates/build_sign_native.yml
@@ -202,6 +202,21 @@ jobs:
/bl:$(Build.Arcade.LogsPath)PublishManaged.binlog
displayName: 🟣Prepare aspire-managed
+ - script: >-
+ $(Build.SourcesDirectory)/$(dotnetScript)
+ publish
+ $(Build.SourcesDirectory)/src/Aspire.Dashboard/Aspire.Dashboard.csproj
+ -c $(_BuildConfig)
+ -r ${{ targetRid }}
+ --self-contained
+ /p:PublishAot=true
+ /p:PlatformName=${{ targetRid }}
+ /p:GenerateDocumentationFile=false
+ /p:EnforceCodeStyleInBuild=false
+ ${{ parameters.extraBuildArgs }}
+ /bl:$(Build.Arcade.LogsPath)PublishDashboard.binlog
+ displayName: 🟣Prepare Native AOT Dashboard
+
# On macOS, ad-hoc codesign aspire-managed with JIT entitlements BEFORE Arcade signing.
# MicroBuild (MacDeveloperHardenWithNotarization) preserves entitlements from the prior
# ad-hoc signature when re-signing with the real certificate. Without this step,
@@ -219,7 +234,7 @@ jobs:
$(Build.SourcesDirectory)/$(scriptName)
-restore -sign
${{ parameters.extraBuildArgs }}
- -projects $(Build.SourcesDirectory)/src/Aspire.Managed/Aspire.Managed.csproj
+ -projects "$(Build.SourcesDirectory)/src/Aspire.Managed/Aspire.Managed.csproj;$(Build.SourcesDirectory)/src/Aspire.Dashboard/Aspire.Dashboard.csproj"
/bl:$(Build.Arcade.LogsPath)SignManaged.binlog
displayName: 🟣Sign aspire-managed
env:
@@ -230,9 +245,33 @@ jobs:
# to the default umask (typically 644). The execute bit must be restored before
# CreateLayout packs the binary into the bundle archive.
- ${{ if and(eq(parameters.codeSign, true), ne(parameters.agentOs, 'windows')) }}:
- - script: >-
+ - script: |
chmod +x $(Build.SourcesDirectory)/artifacts/bin/Aspire.Managed/Release/net10.0/${{ targetRid }}/publish/aspire-managed
- displayName: 🟣Restore execute permission on aspire-managed
+ chmod +x $(Build.SourcesDirectory)/artifacts/bin/Aspire.Dashboard/${{ targetRid }}/Release/net11.0/${{ targetRid }}/publish/Aspire.Dashboard
+ displayName: 🟣Restore execute permissions on managed executables
+
+ # Package the already-published/signed Dashboard without republishing it,
+ # which would replace the signed executable.
+ - script: >-
+ $(Build.SourcesDirectory)/$(dotnetScript)
+ build
+ $(Build.SourcesDirectory)/eng/dashboardpack/Aspire.Dashboard.Sdk.${{ targetRid }}.csproj
+ -c $(_BuildConfig)
+ /p:SkipDashboardPublish=true
+ ${{ parameters.extraBuildArgs }}
+ /bl:$(Build.Arcade.LogsPath)PackDashboard.binlog
+ displayName: 🟣Pack Native AOT Dashboard
+
+ # The native_archives artifact publishes only artifacts/packages. Stage
+ # the Dashboard runtime zip there so Assemble can recover it alongside
+ # the RID-specific Dashboard nupkg.
+ - pwsh: |
+ $ErrorActionPreference = 'Stop'
+ $source = "$(Build.SourcesDirectory)/artifacts/DashboardArtifacts/$(_BuildConfig)/${{ targetRid }}/aspire-dashboard-${{ targetRid }}.zip"
+ $destination = "$(Build.SourcesDirectory)/artifacts/packages/$(_BuildConfig)/DashboardArtifacts/${{ targetRid }}"
+ New-Item -ItemType Directory -Force -Path $destination | Out-Null
+ Copy-Item -LiteralPath $source -Destination $destination -Force
+ displayName: 🟣Stage Native AOT Dashboard artifact
- task: NodeTool@0
displayName: 🟣Install node.js
diff --git a/eng/pipelines/templates/prepare-homebrew-cask.yml b/eng/pipelines/templates/prepare-homebrew-cask.yml
index a19124d33dd..639e0021b19 100644
--- a/eng/pipelines/templates/prepare-homebrew-cask.yml
+++ b/eng/pipelines/templates/prepare-homebrew-cask.yml
@@ -45,8 +45,9 @@ steps:
# prepare-cask-artifact.sh defaults to LiveArchives mode, which is what
# source-build prep needs — the cask URL points at a github.com release
# that doesn't exist yet at prep time. The full LiveRelease audit + real
- # brew install runs later in release-publish-nuget.yml's
- # HomebrewValidateJob, against the cask emitted by this prep stage.
+ # brew install runs later in the homebrew-validate-release.yml GitHub
+ # workflow, which fires on release: [published] after the release manager
+ # publishes the draft GitHub release.
args=(
--version "$(CliVersion)"
--channel "$(HomebrewChannel)"
diff --git a/eng/scripts/download-native-archives.ps1 b/eng/scripts/download-native-archives.ps1
index e08c03a5e4f..95bfa14351a 100644
--- a/eng/scripts/download-native-archives.ps1
+++ b/eng/scripts/download-native-archives.ps1
@@ -21,6 +21,8 @@
///aspire-cli-*.{zip,tar.gz}
///Aspire.Cli*.nupkg
///microsoft-aspire-cli*.tgz
+ ///Aspire.Dashboard.Sdk.*.nupkg
+ ///aspire-dashboard-*.zip
The path component is preserved so that
stage-native-cli-tool-packages.ps1 (which the assemble job runs next) sees
@@ -48,11 +50,15 @@
Created if it does not already exist.
.PARAMETER NupkgsTargetDir
- Destination directory for Aspire.Cli*.nupkg AND microsoft-aspire-cli*.tgz
+ Destination directory for Aspire.Cli*.nupkg, Aspire.Dashboard.Sdk.*.nupkg,
+ and microsoft-aspire-cli*.tgz
files. Created if it does not already exist. (Both land here because
stage-native-cli-tool-packages.ps1 then walks this directory for both
shapes when called with -RequireNpmPackages.)
+.PARAMETER DashboardArtifactsTargetDir
+ Destination directory for Native AOT Dashboard runtime zip files.
+
.PARAMETER ArtifactNamePattern
Wildcard for selecting artifacts. Defaults to `native_archives_*`.
@@ -83,7 +89,8 @@
-Project 'internal' `
-BuildId 2987730 `
-ArchivesTargetDir 'artifacts/signed-archives/Release' `
- -NupkgsTargetDir 'artifacts/native-cli-packages/Release'
+ -NupkgsTargetDir 'artifacts/native-cli-packages/Release' `
+ -DashboardArtifactsTargetDir 'artifacts/DashboardArtifacts/Release'
.NOTES
Only Build/Container artifacts (the type produced by
@@ -111,6 +118,9 @@ param(
[Parameter(Mandatory)]
[string]$NupkgsTargetDir,
+ [Parameter(Mandatory)]
+ [string]$DashboardArtifactsTargetDir,
+
[string]$ArtifactNamePattern = 'native_archives_*',
[ValidateRange(1, 64)]
@@ -206,6 +216,7 @@ $DownloadOneArtifact = {
[string]$DownloadUrl,
[string]$ArchivesTargetDir,
[string]$NupkgsTargetDir,
+ [string]$DashboardArtifactsTargetDir,
[int]$MaxDownloadAttempts,
[int]$RetryBaseDelaySeconds
)
@@ -284,16 +295,28 @@ $DownloadOneArtifact = {
$archivesCount = 0
$nupkgsCount = 0
+ $dashboardArchivesCount = 0
try {
foreach ($entry in $zip.Entries) {
# Skip directory entries (empty Name).
if (-not $entry.Name) { continue }
$isArchive = ($entry.Name -like 'aspire-cli-*.zip') -or ($entry.Name -like 'aspire-cli-*.tar.gz')
- $isNupkg = ($entry.Name -like 'Aspire.Cli*.nupkg') -or ($entry.Name -like 'microsoft-aspire-cli*.tgz')
- if (-not ($isArchive -or $isNupkg)) { continue }
-
- $target = if ($isArchive) { $ArchivesTargetDir } else { $NupkgsTargetDir }
+ $isNupkg = ($entry.Name -like 'Aspire.Cli*.nupkg') -or
+ ($entry.Name -like 'Aspire.Dashboard.Sdk.*.nupkg') -or
+ ($entry.Name -like 'microsoft-aspire-cli*.tgz')
+ $isDashboardArchive = $entry.Name -like 'aspire-dashboard-*.zip'
+ if (-not ($isArchive -or $isNupkg -or $isDashboardArchive)) { continue }
+
+ $target = if ($isArchive) {
+ $ArchivesTargetDir
+ }
+ elseif ($isDashboardArchive) {
+ $DashboardArtifactsTargetDir
+ }
+ else {
+ $NupkgsTargetDir
+ }
# Preserve the original layout: //.
# stage-native-cli-tool-packages.ps1 walks for `native_archives_*`
@@ -320,19 +343,27 @@ $DownloadOneArtifact = {
}
[System.IO.Compression.ZipFileExtensions]::ExtractToFile($entry, $dest, $true)
- if ($isArchive) { $archivesCount++ } else { $nupkgsCount++ }
+ if ($isArchive) {
+ $archivesCount++
+ }
+ elseif ($isDashboardArchive) {
+ $dashboardArchivesCount++
+ }
+ else {
+ $nupkgsCount++
+ }
}
}
finally {
$zip.Dispose()
}
- if (($archivesCount + $nupkgsCount) -eq 0) {
+ if (($archivesCount + $nupkgsCount + $dashboardArchivesCount) -eq 0) {
# Zero matches isn't necessarily an error (an artifact might be all
# symbols or sdl analysis files), but log so devs investigating an
# empty-asset-manifest failure can see exactly what each artifact
# contributed.
- Write-Warning "Artifact '$ArtifactName' had no entries matching aspire-cli-*, Aspire.Cli*.nupkg, or microsoft-aspire-cli*.tgz shapes. Inspect $tempZip if this was unexpected."
+ Write-Warning "Artifact '$ArtifactName' had no entries matching CLI or Dashboard shipping artifact shapes. Inspect $tempZip if this was unexpected."
}
else {
# Only remove the temp zip when at least something was extracted —
@@ -347,6 +378,7 @@ $DownloadOneArtifact = {
TotalMs = $sw.ElapsedMilliseconds
Archives = $archivesCount
Nupkgs = $nupkgsCount
+ DashboardArchives = $dashboardArchivesCount
}
}
@@ -363,6 +395,7 @@ function Invoke-ParallelDownloads {
[Parameter(Mandatory)] [string]$AccessToken,
[Parameter(Mandatory)] [string]$ArchivesTargetDir,
[Parameter(Mandatory)] [string]$NupkgsTargetDir,
+ [Parameter(Mandatory)] [string]$DashboardArtifactsTargetDir,
[Parameter(Mandatory)] [scriptblock]$Worker,
[Parameter(Mandatory)] [int]$ThrottleLimit,
[Parameter(Mandatory)] [int]$MaxDownloadAttempts,
@@ -401,7 +434,7 @@ function Invoke-ParallelDownloads {
$jobs = @(foreach ($a in $Artifacts) {
Start-ThreadJob `
-ScriptBlock $Worker `
- -ArgumentList @($AccessToken, $a.name, $a.resource.downloadUrl, $ArchivesTargetDir, $NupkgsTargetDir, $MaxDownloadAttempts, $RetryBaseDelaySeconds) `
+ -ArgumentList @($AccessToken, $a.name, $a.resource.downloadUrl, $ArchivesTargetDir, $NupkgsTargetDir, $DashboardArtifactsTargetDir, $MaxDownloadAttempts, $RetryBaseDelaySeconds) `
-ThrottleLimit $ThrottleLimit `
-Name $a.name
})
@@ -412,8 +445,8 @@ function Invoke-ParallelDownloads {
foreach ($job in $jobs) {
try {
$result = $job | Receive-Job -ErrorAction Stop
- Write-Host (" {0,-32} download={1,7:N0}ms total={2,7:N0}ms archives={3} nupkgs={4}" `
- -f $result.ArtifactName, $result.DownloadMs, $result.TotalMs, $result.Archives, $result.Nupkgs)
+ Write-Host (" {0,-32} download={1,7:N0}ms total={2,7:N0}ms archives={3} nupkgs={4} dashboardArchives={5}" `
+ -f $result.ArtifactName, $result.DownloadMs, $result.TotalMs, $result.Archives, $result.Nupkgs, $result.DashboardArchives)
}
catch {
$failures += [pscustomobject]@{ Name = $job.Name; Error = $_ }
@@ -433,7 +466,7 @@ function Invoke-ParallelDownloads {
# --- Main ---
-New-Item -ItemType Directory -Force -Path $ArchivesTargetDir, $NupkgsTargetDir | Out-Null
+New-Item -ItemType Directory -Force -Path $ArchivesTargetDir, $NupkgsTargetDir, $DashboardArtifactsTargetDir | Out-Null
$artifacts = Get-MatchingArtifacts `
-CollectionUri $CollectionUri `
@@ -448,6 +481,7 @@ Invoke-ParallelDownloads `
-AccessToken $AccessToken `
-ArchivesTargetDir $ArchivesTargetDir `
-NupkgsTargetDir $NupkgsTargetDir `
+ -DashboardArtifactsTargetDir $DashboardArtifactsTargetDir `
-Worker $DownloadOneArtifact `
-ThrottleLimit $ThrottleLimit `
-MaxDownloadAttempts $MaxDownloadAttempts `
diff --git a/eng/scripts/test-native-dashboard.ps1 b/eng/scripts/test-native-dashboard.ps1
new file mode 100644
index 00000000000..b53382e7d66
--- /dev/null
+++ b/eng/scripts/test-native-dashboard.ps1
@@ -0,0 +1,78 @@
+param(
+ [Parameter(Mandatory)]
+ [string]$DashboardPath
+)
+
+$ErrorActionPreference = 'Stop'
+
+if (-not (Test-Path -LiteralPath $DashboardPath -PathType Leaf)) {
+ throw "Native AOT Dashboard executable was not found at '$DashboardPath'."
+}
+
+$listener = [System.Net.Sockets.TcpListener]::new([System.Net.IPAddress]::Loopback, 0)
+$listener.Start()
+$port = ([System.Net.IPEndPoint]$listener.LocalEndpoint).Port
+$listener.Stop()
+
+$dashboardUrl = "http://127.0.0.1:$port"
+$testDirectory = Join-Path ([System.IO.Path]::GetTempPath()) "aspire-dashboard-smoke-$([guid]::NewGuid().ToString('N'))"
+$null = New-Item -ItemType Directory -Path $testDirectory
+$stdoutPath = Join-Path $testDirectory 'stdout.log'
+$stderrPath = Join-Path $testDirectory 'stderr.log'
+$dashboardProcess = $null
+
+try {
+ $dashboardProcess = Start-Process `
+ -FilePath $DashboardPath `
+ -ArgumentList @(
+ "--ASPNETCORE_URLS=$dashboardUrl",
+ '--ASPIRE_DASHBOARD_UNSECURED_ALLOW_ANONYMOUS=true'
+ ) `
+ -WorkingDirectory (Split-Path -Parent $DashboardPath) `
+ -RedirectStandardOutput $stdoutPath `
+ -RedirectStandardError $stderrPath `
+ -PassThru
+
+ $deadline = [DateTime]::UtcNow.AddMinutes(1)
+ while ([DateTime]::UtcNow -lt $deadline) {
+ if ($dashboardProcess.HasExited) {
+ throw "Native AOT Dashboard exited before becoming ready with exit code $($dashboardProcess.ExitCode)."
+ }
+
+ try {
+ $assetResponse = Invoke-WebRequest -Uri "$dashboardUrl/_framework/blazor.web.js" -TimeoutSec 5 -UseBasicParsing
+ if ($assetResponse.StatusCode -eq 200 -and
+ $assetResponse.RawContentLength -gt 0) {
+ Write-Host "Native AOT Dashboard smoke test passed at $dashboardUrl."
+ return
+ }
+ }
+ catch {
+ # The server can accept TCP connections before static assets are ready.
+ }
+
+ [System.Threading.Thread]::Sleep(500)
+ }
+
+ throw 'Timed out waiting for the Native AOT Dashboard HTTP endpoints.'
+}
+catch {
+ $failure = $_
+ [Console]::Error.WriteLine($failure)
+ if (Test-Path -LiteralPath $stdoutPath) {
+ Write-Host 'Dashboard stdout:'
+ Get-Content -LiteralPath $stdoutPath
+ }
+ if (Test-Path -LiteralPath $stderrPath) {
+ Write-Host 'Dashboard stderr:'
+ Get-Content -LiteralPath $stderrPath
+ }
+ throw $failure
+}
+finally {
+ if ($dashboardProcess -and -not $dashboardProcess.HasExited) {
+ Stop-Process -Id $dashboardProcess.Id -Force
+ $dashboardProcess.WaitForExit()
+ }
+ Remove-Item -LiteralPath $testDirectory -Recurse -Force -ErrorAction SilentlyContinue
+}
\ No newline at end of file
diff --git a/extension/CHANGELOG.md b/extension/CHANGELOG.md
index 5c266c5a85d..4008924df47 100644
--- a/extension/CHANGELOG.md
+++ b/extension/CHANGELOG.md
@@ -1,5 +1,21 @@
# Aspire VS Code Extension Changelog
+## v1.18.0
+
+
+
+### Features
+
+- Add a Java hosting integration, including Spring Boot and Quarkus app support, container publishing, and VS Code debugger wiring ([#18033](https://github.com/microsoft/aspire/pull/18033)).
+- Add a Rust hosting package with VS Code debugger wiring ([#18906](https://github.com/microsoft/aspire/pull/18906)).
+
+### Fixes
+
+- Remember the selected AppHost folder correctly in multi-root workspaces ([#19342](https://github.com/microsoft/aspire/issues/19342), [#19359](https://github.com/microsoft/aspire/pull/19359)).
+- Honor the AppHost launch profile selected in `launch.json` instead of falling back to the default profile's environment and URL ([#19387](https://github.com/microsoft/aspire/issues/19387), [#19400](https://github.com/microsoft/aspire/pull/19400)).
+- Scope AppHost start/stop to the current git worktree and fix AppHost launch arguments being dropped or flattened when forwarded through VS Code ([#19357](https://github.com/microsoft/aspire/issues/19357), [#19384](https://github.com/microsoft/aspire/pull/19384)).
+- Harden Aspire Skills bundle integrity checks by switching to SHA-512 and hide the remote-fetch preview toggle from user-facing settings ([#19303](https://github.com/microsoft/aspire/pull/19303)).
+
## v1.17.0
@@ -16,6 +32,7 @@
### Fixes
+- Remember the selected AppHost folder when debugging multi-root workspaces ([#19342](https://github.com/microsoft/aspire/issues/19342)).
- Make C# Dev Kit Hot Reload discoverable while debugging ([#19067](https://github.com/microsoft/aspire/pull/19067)).
- Keep launch-configuration AppHost targets out of the workspace default list ([#19126](https://github.com/microsoft/aspire/pull/19126)).
- Honor `ASPIRE_HOME` for deployment state ([#19244](https://github.com/microsoft/aspire/pull/19244)).
diff --git a/extension/CONTRIBUTING.md b/extension/CONTRIBUTING.md
index 1e25052b29e..9de36e50210 100644
--- a/extension/CONTRIBUTING.md
+++ b/extension/CONTRIBUTING.md
@@ -59,7 +59,15 @@ Run `build.ps1` (Windows) or `build.sh` (Mac/Linux) from the repository root to
### Optional: set the CLI path
-If you want to effectively debug the Aspire CLI together with the Aspire VS Code extension, set the `Aspire Cli Executable Path` setting to the Aspire CLI output path. The raw local build output path, relative to the Aspire repository root directory, is `artifacts/bin/Aspire.Cli/Debug/net10.0/aspire`. Pointing at the raw build output makes the extension invoke your dev CLI, but that raw path is intentionally not forwarded as `AspireCliPath` (see Dogfooding below). To also dogfood bundle metadata, use an installed/bundled CLI layout instead.
+To debug the Aspire CLI together with the extension, set `Aspire Cli Executable Path` to the CLI output path. You can use an absolute path or a workspace token. If you opened the `extension` folder, the local build is:
+
+```json
+"aspire.aspireCliExecutablePath": "${workspaceFolder}/../artifacts/bin/Aspire.Cli/Debug/net10.0/aspire"
+```
+
+`${workspaceFolder}` uses the folder that owns the current operation. In a multi-root workspace, `${workspaceFolder:name}` selects the uniquely named folder. Plain relative paths are not resolved; use a workspace token when the path should move with the checkout.
+
+Pointing at the raw build output makes the extension invoke your dev CLI, but that path is intentionally not forwarded as `AspireCliPath` (see Dogfooding below). To also dogfood bundle metadata, use an installed/bundled CLI layout instead.
You may also want to use the `Run Extension (cli stop on entry)` launch configuration, as `Run Extension` does not prevent the Aspire CLI from executing immediately.
@@ -67,9 +75,9 @@ You can use the `Aspire: Extension settings` command to open VS Code settings di
#### Dogfooding a CLI build alongside the extension
-When `Aspire Cli Executable Path` points at an existing **absolute** path that is not a raw framework-dependent local CLI build output, the extension forwards that value as the `AspireCliPath` MSBuild property/environment variable to every terminal, task, and debug process it creates. The Aspire SDK's `ResolveAspireCliBundle` task uses `AspireCliPath` (defined in [`src/Aspire.Hosting.Tasks/ResolveAspireCliBundle.cs`](/src/Aspire.Hosting.Tasks/ResolveAspireCliBundle.cs)) to locate the matching bundle layout — DCP, dashboard, and terminal-host binaries — and bakes those paths into the built AppHost as `[AssemblyMetadata]` attributes. Without this forwarding, MSBuild probes `PATH` and can stamp the *stable* CLI's bundle into the AppHost while the extension is launching it through the *dev* CLI, producing surprising runtime mismatches such as `` even though the new CLI is correctly invoked (tracked in [issue #18073](https://github.com/microsoft/aspire/issues/18073)).
+When `Aspire Cli Executable Path` resolves to an existing **absolute** path that is not a raw framework-dependent local CLI build output, the extension forwards that value as the `AspireCliPath` MSBuild property/environment variable to terminals, tasks, and debug processes in that workspace folder. The Aspire SDK's `ResolveAspireCliBundle` task uses `AspireCliPath` (defined in [`src/Aspire.Hosting.Tasks/ResolveAspireCliBundle.cs`](/src/Aspire.Hosting.Tasks/ResolveAspireCliBundle.cs)) to locate the matching bundle layout — DCP, dashboard, and terminal-host binaries — and bakes those paths into the built AppHost as `[AssemblyMetadata]` attributes. Without this forwarding, MSBuild probes `PATH` and can stamp the *stable* CLI's bundle into the AppHost while the extension is launching it through the *dev* CLI, producing surprising runtime mismatches such as `` even though the new CLI is correctly invoked (tracked in [issue #18073](https://github.com/microsoft/aspire/issues/18073)).
-A relative value (for example the bare `aspire` literal) or an absolute path that no longer exists is intentionally not forwarded because `ResolveAspireCliBundle` stops with a warning for invalid explicit `AspireCliPath` values instead of probing `PATH`. A raw framework-dependent local build output such as `artifacts/bin/Aspire.Cli/Debug/net10.0/aspire` is also not forwarded because it can make `ResolveAspireCliBundle` fall back to unrelated `ASPIRE_HOME` metadata. Symlinks to that raw local build output are filtered the same way. To dogfood bundle metadata end-to-end, point the setting at an installed/bundled CLI layout with a sidecar or adjacent bundle assets. Clear the setting to revert to default PATH/ASPIRE_HOME resolution.
+A tokenized setting is expanded to an absolute path before validation. A plain relative value (for example the bare `aspire` literal) or an absolute path that no longer exists is intentionally not forwarded because `ResolveAspireCliBundle` stops with a warning for invalid explicit `AspireCliPath` values instead of probing `PATH`. A raw framework-dependent local build output such as `artifacts/bin/Aspire.Cli/Debug/net10.0/aspire` is also not forwarded because it can make `ResolveAspireCliBundle` fall back to unrelated `ASPIRE_HOME` metadata. Symlinks to that raw local build output are filtered the same way. To dogfood bundle metadata end-to-end, point the setting at an installed/bundled CLI layout with a sidecar or adjacent bundle assets. Clear the setting to revert to default PATH/ASPIRE_HOME resolution.
## Running tests
@@ -115,6 +123,7 @@ The suite can be sharded by running separate VS Code windows/processes, which is
ASPIRE_EXTENSION_E2E_SHARD=command-palette ASPIRE_EXTENSION_E2E_SPEC=out/test-e2e/test-e2e/commandPalette.e2e.test.js ASPIRE_EXTENSION_E2E_CLI_PATH=/path/to/aspire corepack yarn test:e2e
ASPIRE_EXTENSION_E2E_SHARD=settings-files ASPIRE_EXTENSION_E2E_SPEC=out/test-e2e/test-e2e/settingsFiles.e2e.test.js ASPIRE_EXTENSION_E2E_CLI_PATH=/path/to/aspire corepack yarn test:e2e
ASPIRE_EXTENSION_E2E_SHARD=discovery-configuration ASPIRE_EXTENSION_E2E_SPEC=out/test-e2e/test-e2e/discoveryConfiguration.e2e.test.js ASPIRE_EXTENSION_E2E_CLI_PATH=/path/to/aspire corepack yarn test:e2e
+ASPIRE_EXTENSION_E2E_SHARD=dynamic-debug-configuration ASPIRE_EXTENSION_E2E_SPEC=out/test-e2e/test-e2e/dynamicDebugConfiguration.e2e.test.js ASPIRE_EXTENSION_E2E_CLI_PATH=/path/to/aspire corepack yarn test:e2e
ASPIRE_EXTENSION_E2E_SHARD=apphost-tree ASPIRE_EXTENSION_E2E_SPEC=out/test-e2e/test-e2e/appHostTree.e2e.test.js ASPIRE_EXTENSION_E2E_CLI_PATH=/path/to/aspire corepack yarn test:e2e
ASPIRE_EXTENSION_E2E_SHARD=tree-actions ASPIRE_EXTENSION_E2E_SPEC=out/test-e2e/test-e2e/treeActions.e2e.test.js ASPIRE_EXTENSION_E2E_CLI_PATH=/path/to/aspire corepack yarn test:e2e
ASPIRE_EXTENSION_E2E_SHARD=debug-dashboard ASPIRE_EXTENSION_E2E_SPEC=out/test-e2e/test-e2e/debugDashboard.e2e.test.js ASPIRE_EXTENSION_E2E_CLI_PATH=/path/to/aspire corepack yarn test:e2e
@@ -135,7 +144,7 @@ ASPIRE_EXTENSION_E2E_SHARD=fast-subset ASPIRE_EXTENSION_E2E_SPEC='out/test-e2e/t
ASPIRE_EXTENSION_E2E_SHARD=tree-subset ASPIRE_EXTENSION_E2E_SPEC='out/test-e2e/test-e2e/*Tree.e2e.test.js' ASPIRE_EXTENSION_E2E_CLI_PATH=/path/to/aspire corepack yarn test:e2e
```
-The current shards cover command palette and terminal routing, settings-file creation/opening with an isolated Aspire home, workspace AppHost discovery/configuration changes, AppHost run/stop/resource rendering, tree action commands for copy/open/log/resource operations, debug/dashboard lifecycle, Azure Functions HTTPS startup and termination through the real Functions extension, a zero-to-running flow that routes the Aspire new/add terminal commands, creates a C# AppHost through the CLI, adds an integration package, registers a source breakpoint, and debugs the generated AppHost, the `package.json` contribution surface including exact activation events, command registration, menu/view/settings inventory, JSON validation, walkthrough command registration, CodeLens routing, and debug launch command routing, plus negative-path edge cases for invalid control payloads, missing tree targets, CLI-independent settings commands, and launch-state cleanup.
+The current shards cover command palette and terminal routing, settings-file creation/opening with an isolated Aspire home, workspace AppHost discovery/configuration changes, remembered multi-root dynamic debug configuration selection, AppHost run/stop/resource rendering, tree action commands for copy/open/log/resource operations, debug/dashboard lifecycle, Azure Functions HTTPS startup and termination through the real Functions extension, a zero-to-running flow that routes the Aspire new/add terminal commands, creates a C# AppHost through the CLI, adds an integration package, registers a source breakpoint, and debugs the generated AppHost, the `package.json` contribution surface including exact activation events, command registration, menu/view/settings inventory, JSON validation, walkthrough command registration, CodeLens routing, and debug launch command routing, plus negative-path edge cases for invalid control payloads, missing tree targets, CLI-independent settings commands, and launch-state cleanup.
Diagnostics are left under `extension/.test-results`, `extension/.test-storage`, and `extension/.test-workspaces`, with shard-specific subdirectories when `ASPIRE_EXTENSION_E2E_SHARD` is set. The runner also sets `ASPIRE_HOME` to an isolated per-run directory and copies it into diagnostics before cleanup so settings-file failures do not touch or depend on the real user profile. These folders are ignored by git and are uploaded by CI when the E2E job runs.
diff --git a/extension/loc/xlf/aspire-vscode.xlf b/extension/loc/xlf/aspire-vscode.xlf
index 6cdfaed0474..d00aa1be9af 100644
--- a/extension/loc/xlf/aspire-vscode.xlf
+++ b/extension/loc/xlf/aspire-vscode.xlf
@@ -25,6 +25,9 @@
AppHosts
+
+ Arguments containing %NAME% cannot be forwarded through a Windows .cmd or .bat shim, because cmd.exe expands them before the Aspire CLI receives the value. Configure aspire.aspireCliExecutablePath to point at aspire.exe instead of the .cmd shim and try again.
+
Aspire
@@ -82,6 +85,9 @@
Aspire: Launch default AppHost
+
+ Aspire: Launch default AppHost ({0}: {1})
+
Attempted to start unsupported resource type: {0}.
@@ -391,6 +397,18 @@
Invalid token provided.
+
+ Java
+
+
+ Java AppHosts are launched through the Java debugger extension. Install {0} from the Extensions view, then start the AppHost again.
+
+
+ Java resources are started by the IDE rather than attached to, and the app host requested an attach session. Aspire cannot start one because no debug address is available.
+
+
+ Java: {0}
+
Latest build from main via the install script
@@ -511,6 +529,9 @@
Open Aspire terminal
+
+ Open Setting
+
Open Settings
@@ -566,7 +587,7 @@
Polling interval in milliseconds for fetching running AppHosts. Minimum: 1000.
- Prefer this tool over invoking Aspire AppHost lifecycle commands in a terminal whenever VS Code is active. Start an Aspire AppHost that Aspire has already discovered in the current workspace, using the editor's own debug lifecycle. Requires the workspace-relative path of one of the discovered AppHosts; absolute paths are rejected. Also requires whether to start it in 'run' mode (no debugger attached) or 'debug' mode (debugger attached). Does not create, pick, or guess an AppHost: if the path does not name a discovered AppHost, or names more than one, the call fails and the result lists the AppHosts you can pass. If the AppHost is already starting or already running, no second process is started.
+ Prefer this tool over invoking Aspire AppHost lifecycle commands in a terminal whenever VS Code is active. Start an Aspire AppHost that Aspire has already discovered in the current workspace, using the editor's own debug lifecycle. Requires the workspace-relative path of one of the discovered AppHosts; absolute paths are rejected. Also requires whether to start it in 'run' mode (no debugger attached) or 'debug' mode (debugger attached). Optional 'isolated' starts the AppHost with randomized ports and isolated user secrets; when omitted, linked git worktrees start isolated automatically so they do not collide with the primary checkout. Explicit true or false overrides that inference. Does not create, pick, or guess an AppHost: if the path does not name a discovered AppHost, or names more than one, the call fails and the result lists the AppHosts you can pass. If the AppHost is already starting or already running, no second process is started. A successful new launch includes the verified effective 'isolated' value; idempotent or uncertain results omit it.
Prefer this tool over invoking Aspire AppHost lifecycle commands in a terminal whenever VS Code is active. Stop a running Aspire AppHost that Aspire has already discovered in the current workspace. Requires the workspace-relative path of one of the discovered AppHosts; absolute paths are rejected. AppHosts started by this editor stop through the coordinated debug lifecycle. AppHosts started outside the editor stop through 'aspire stop --apphost' for the same discovered path. The extension never kills arbitrary processes. If it cannot determine whether the AppHost is running, the call fails rather than reporting that nothing is running.
@@ -673,6 +694,9 @@
Select the default AppHost to launch when starting an Aspire debug session
+
+ Select the workspace folder for the Aspire command
+
Select what should happen with the Aspire Dashboard when this launch configuration starts
@@ -712,6 +736,9 @@
Start an Aspire AppHost from this workspace in run or debug mode.
+
+ Start the Aspire AppHost {0} in {1} mode with isolation?
+
Start the Aspire AppHost {0} in {1} mode?
@@ -781,9 +808,15 @@
The Aspire panel workspace view requires Aspire CLI 13.2.0 or newer and an AppHost that references Aspire.Hosting 13.2.0 or newer. Install or update the Aspire CLI and update your AppHost package to get started.
[Update Aspire CLI](command:aspire-vscode.updateSelf)
[Refresh](command:aspire-vscode.globalRefreshAppHosts)
+
+ The Java AppHost launch command was not recognized and cannot be debugged.
+
The command completed, but its output could not be opened: {0}
+
+ The configured Aspire CLI path could not be used, so a different Aspire CLI is running instead: {0}. Check that aspire.aspireCliExecutablePath points to the aspire executable itself and that it runs.
+
The configured VS Code task shell is not supported for Azure Functions launch arguments. Configure terminal.integrated.automationProfile to use PowerShell, Command Prompt, bash, zsh, fish, or WSL.
@@ -797,11 +830,17 @@
The default launch profile '{0}' is an Executable profile, so dotnet run-api does not return the file-based app {1}; launching it with dotnet run without debugger attach. Breakpoints will not be hit for this resource.
- The path to the Aspire CLI executable. If not set, the extension will attempt to use 'aspire' from the system PATH.
+ The path to the Aspire CLI executable. Use '${workspaceFolder}' for the operation's workspace folder or '${workspaceFolder:name}' for a named folder. If not set, the extension will attempt to use 'aspire' from the system PATH.
The pipeline step name to execute when command is 'do'
+
+ The selected Aspire CLI does not support the requested isolation mode.
+
+
+ The selected Aspire CLI isolation capability could not be verified.
+
This Aspire AppHost is already starting or running. The new debug session was cancelled so only one AppHost runs.
@@ -847,6 +886,15 @@
Use "{0}"
+
+ Use Aspire Run or Debug instead. The Java extension runs this file directly, so the AppHost starts with no Aspire session: none of its resources are launched, and the dashboard never appears.
+
+
+ Use Aspire Run or Debug instead. The Spring Boot Dashboard starts the app on its own, so it receives none of the service discovery, connection string, or OpenTelemetry settings Aspire injects.
+
+
+ Use Aspire controls instead. The Java extension starts another java process outside the running Aspire session.
+
Use the configured dashboard browser behavior, falling back to VS Code's integrated browser for compatibility.
@@ -886,6 +934,9 @@
Welcome to Aspire
+
+ When true, start with randomized ports and isolated user secrets. When false, do not isolate. When omitted, linked git worktrees start isolated automatically.
+
Whether to register the Aspire MCP server when a workspace is open.
@@ -967,5 +1018,14 @@
{0}: {1}
+
+ ⚠️ Do not click the Java Run or Debug actions; they bypass Aspire
+
+
+ ⚠️ Do not click the Java Run or Debug actions; this AppHost is already running in Aspire
+
+
+ ⚠️ Do not start this app from the Spring Boot Dashboard; it bypasses Aspire
+