diff --git a/.github/workflows/api-consumption-report.lock.yml b/.github/workflows/api-consumption-report.lock.yml index c1be441a657..57de3b6a634 100644 --- a/.github/workflows/api-consumption-report.lock.yml +++ b/.github/workflows/api-consumption-report.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"20e2a4ce02670cc04cc74b5b70f31618d9a64ea05cd20663594648ec8e1df8e3","body_hash":"a6e27e1763264356252aeff4b7516ab7def7925fb72ae026ca5c3d29a658e057","strict":true,"agent_id":"claude","engine_versions":{"claude":"2.1.198"}} +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"ca9d1ddd0b6a5d40ffa8c20eb35f47d9ade662139798ba256f73c36098cb0edf","body_hash":"a6e27e1763264356252aeff4b7516ab7def7925fb72ae026ca5c3d29a658e057","strict":true,"agent_id":"claude","engine_versions":{"claude":"2.1.198"}} # gh-aw-manifest: {"version":1,"secrets":["ANTHROPIC_API_KEY","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_GRAFANA_AUTHORIZATION","GH_AW_OTEL_GRAFANA_ENDPOINT","GH_AW_OTEL_SENTRY_AUTHORIZATION","GH_AW_OTEL_SENTRY_ENDPOINT","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":"9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0","version":"v7.0.0"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-go","sha":"924ae3a1cded613372ab5595356fb5720e22ba16","version":"v6.5.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/setup-python","sha":"ece7cb06caefa5fff74198d8649806c4678c61a1","version":"v6.3.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"docker/build-push-action","sha":"f9f3042f7e2789586610d6e8b85c8f03e5195baf","version":"v7.2.0"},{"repo":"docker/setup-buildx-action","sha":"d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5","version":"v4.1.0"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.27.22","digest":"sha256:55f06588411008b7148eb64b8dfe28602a0cce3675b36c6b190b54aca138468e","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.27.22@sha256:55f06588411008b7148eb64b8dfe28602a0cce3675b36c6b190b54aca138468e"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.22","digest":"sha256:afb9ff9140b17d38871dfb9dbac5ff8689ea634c2f91c435da2825192d4881c1","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.22@sha256:afb9ff9140b17d38871dfb9dbac5ff8689ea634c2f91c435da2825192d4881c1"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.27.22","digest":"sha256:3cdcc1e2b4b4fe602ba69fd3e21aac7ac512d5c1fce24df4ce69dc4f98164b59","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.27.22@sha256:3cdcc1e2b4b4fe602ba69fd3e21aac7ac512d5c1fce24df4ce69dc4f98164b59"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.32","digest":"sha256:63e46b56dfd70895a701b6fc6dd0189e11e2d875f327f1781e81b31848735477","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.32@sha256:63e46b56dfd70895a701b6fc6dd0189e11e2d875f327f1781e81b31848735477"},{"image":"ghcr.io/github/gh-aw-node","digest":"sha256:529d02eb970b1161aa25c593a9c3df57fdfad5a8add328cb3b6eccef66f3183b","pinned_image":"ghcr.io/github/gh-aw-node@sha256:529d02eb970b1161aa25c593a9c3df57fdfad5a8add328cb3b6eccef66f3183b"},{"image":"ghcr.io/github/github-mcp-server:v1.5.0","digest":"sha256:e25564dccc9110a70a77b9df560cbde11aa392fcb5f08b9abe5c4ebc6d146ea4","pinned_image":"ghcr.io/github/github-mcp-server:v1.5.0@sha256:e25564dccc9110a70a77b9df560cbde11aa392fcb5f08b9abe5c4ebc6d146ea4"}]} # This file was automatically generated by gh-aw. DO NOT EDIT. To debug this workflow, load the skill at https://github.com/github/gh-aw/blob/main/debug.md # @@ -1079,7 +1079,7 @@ jobs: 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 --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 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 GITHUB_AW_OTEL_TRACE_ID -e GITHUB_AW_OTEL_PARENT_SPAN_ID -e OTEL_EXPORTER_OTLP_HEADERS -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.3.32' GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node) - cat << GH_AW_MCP_CONFIG_a91bf15279da34af_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + cat << GH_AW_MCP_CONFIG_ae1ba431374e0d2e_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" { "mcpServers": { "agenticworkflows": { @@ -1152,6 +1152,7 @@ jobs: "domain": "${MCP_GATEWAY_DOMAIN}", "apiKey": "${MCP_GATEWAY_API_KEY}", "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}", + "toolTimeout": 600, "opentelemetry": { "endpoint": "${OTEL_EXPORTER_OTLP_ENDPOINT}", "traceId": "${GITHUB_AW_OTEL_TRACE_ID}", @@ -1159,7 +1160,7 @@ jobs: } } } - GH_AW_MCP_CONFIG_a91bf15279da34af_EOF + GH_AW_MCP_CONFIG_ae1ba431374e0d2e_EOF - name: Mount MCP servers as CLIs id: mount-mcp-clis continue-on-error: true diff --git a/.github/workflows/api-consumption-report.md b/.github/workflows/api-consumption-report.md index 45e6cc247c0..e384a01dd8d 100644 --- a/.github/workflows/api-consumption-report.md +++ b/.github/workflows/api-consumption-report.md @@ -12,7 +12,10 @@ permissions: pull-requests: read discussions: read tracker-id: api-consumption-report-daily -engine: claude +engine: + id: claude + mcp: + tool-timeout: 10m sandbox: agent: sudo: false diff --git a/.github/workflows/audit-workflows.lock.yml b/.github/workflows/audit-workflows.lock.yml index edec263f019..cab62184cd5 100644 --- a/.github/workflows/audit-workflows.lock.yml +++ b/.github/workflows/audit-workflows.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"aa172014cae1ff8fa4a455dcf5573d5abdd3b85d193acb76dc0c3871199e9936","body_hash":"967c30e914d6532b466b00b27295735ed5f9471750c124d6e2abb1fc46a4f7e9","strict":true,"agent_id":"claude","engine_versions":{"claude":"2.1.198"}} +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"3635c39c5f2f6e1894da643f13d5c249e3a32a5407346937621961f1b124f44e","body_hash":"967c30e914d6532b466b00b27295735ed5f9471750c124d6e2abb1fc46a4f7e9","strict":true,"agent_id":"claude","engine_versions":{"claude":"2.1.198"}} # gh-aw-manifest: {"version":1,"secrets":["ANTHROPIC_API_KEY","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_GRAFANA_AUTHORIZATION","GH_AW_OTEL_GRAFANA_ENDPOINT","GH_AW_OTEL_SENTRY_AUTHORIZATION","GH_AW_OTEL_SENTRY_ENDPOINT","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":"9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0","version":"v7.0.0"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-go","sha":"924ae3a1cded613372ab5595356fb5720e22ba16","version":"v6.5.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/setup-python","sha":"ece7cb06caefa5fff74198d8649806c4678c61a1","version":"v6.3.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"docker/build-push-action","sha":"f9f3042f7e2789586610d6e8b85c8f03e5195baf","version":"v7.2.0"},{"repo":"docker/setup-buildx-action","sha":"d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5","version":"v4.1.0"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.27.22","digest":"sha256:55f06588411008b7148eb64b8dfe28602a0cce3675b36c6b190b54aca138468e","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.27.22@sha256:55f06588411008b7148eb64b8dfe28602a0cce3675b36c6b190b54aca138468e"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.22","digest":"sha256:afb9ff9140b17d38871dfb9dbac5ff8689ea634c2f91c435da2825192d4881c1","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.22@sha256:afb9ff9140b17d38871dfb9dbac5ff8689ea634c2f91c435da2825192d4881c1"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.27.22","digest":"sha256:3cdcc1e2b4b4fe602ba69fd3e21aac7ac512d5c1fce24df4ce69dc4f98164b59","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.27.22@sha256:3cdcc1e2b4b4fe602ba69fd3e21aac7ac512d5c1fce24df4ce69dc4f98164b59"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.32","digest":"sha256:63e46b56dfd70895a701b6fc6dd0189e11e2d875f327f1781e81b31848735477","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.32@sha256:63e46b56dfd70895a701b6fc6dd0189e11e2d875f327f1781e81b31848735477"},{"image":"ghcr.io/github/gh-aw-node","digest":"sha256:529d02eb970b1161aa25c593a9c3df57fdfad5a8add328cb3b6eccef66f3183b","pinned_image":"ghcr.io/github/gh-aw-node@sha256:529d02eb970b1161aa25c593a9c3df57fdfad5a8add328cb3b6eccef66f3183b"},{"image":"ghcr.io/github/github-mcp-server:v1.5.0","digest":"sha256:e25564dccc9110a70a77b9df560cbde11aa392fcb5f08b9abe5c4ebc6d146ea4","pinned_image":"ghcr.io/github/github-mcp-server:v1.5.0@sha256:e25564dccc9110a70a77b9df560cbde11aa392fcb5f08b9abe5c4ebc6d146ea4"}]} # This file was automatically generated by gh-aw. DO NOT EDIT. To debug this workflow, load the skill at https://github.com/github/gh-aw/blob/main/debug.md # @@ -861,7 +861,7 @@ jobs: 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 --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 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 GITHUB_AW_OTEL_TRACE_ID -e GITHUB_AW_OTEL_PARENT_SPAN_ID -e OTEL_EXPORTER_OTLP_HEADERS -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.3.32' GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node) - cat << GH_AW_MCP_CONFIG_a91bf15279da34af_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + cat << GH_AW_MCP_CONFIG_ae1ba431374e0d2e_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" { "mcpServers": { "agenticworkflows": { @@ -934,6 +934,7 @@ jobs: "domain": "${MCP_GATEWAY_DOMAIN}", "apiKey": "${MCP_GATEWAY_API_KEY}", "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}", + "toolTimeout": 600, "opentelemetry": { "endpoint": "${OTEL_EXPORTER_OTLP_ENDPOINT}", "traceId": "${GITHUB_AW_OTEL_TRACE_ID}", @@ -941,7 +942,7 @@ jobs: } } } - GH_AW_MCP_CONFIG_a91bf15279da34af_EOF + GH_AW_MCP_CONFIG_ae1ba431374e0d2e_EOF - name: Mount MCP servers as CLIs id: mount-mcp-clis continue-on-error: true diff --git a/.github/workflows/audit-workflows.md b/.github/workflows/audit-workflows.md index 705e3cfade1..043831f484d 100644 --- a/.github/workflows/audit-workflows.md +++ b/.github/workflows/audit-workflows.md @@ -12,7 +12,10 @@ permissions: issues: read pull-requests: read tracker-id: audit-workflows-daily -engine: claude +engine: + id: claude + mcp: + tool-timeout: 10m tools: cli-proxy: true agentic-workflows: diff --git a/.github/workflows/detection-analysis-report.lock.yml b/.github/workflows/detection-analysis-report.lock.yml index 5b64703c56a..7cbecefd5cd 100644 --- a/.github/workflows/detection-analysis-report.lock.yml +++ b/.github/workflows/detection-analysis-report.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"179078ab5cd745919117a67bbc9f30c8448c98b0e4187f2caff2175422ea4d7a","body_hash":"f76f3bc31cbb52b73129dd9c59de35a3d3e319bf3387b10794003672c3dbf0ec","strict":true,"agent_id":"claude","engine_versions":{"claude":"2.1.198"}} +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"48c71de42ae39f852ce6feee58fa3607929af5e18ce42b752dafe7f24b2e7399","body_hash":"f76f3bc31cbb52b73129dd9c59de35a3d3e319bf3387b10794003672c3dbf0ec","strict":true,"agent_id":"claude","engine_versions":{"claude":"2.1.198"}} # gh-aw-manifest: {"version":1,"secrets":["ANTHROPIC_API_KEY","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_GRAFANA_AUTHORIZATION","GH_AW_OTEL_GRAFANA_ENDPOINT","GH_AW_OTEL_SENTRY_AUTHORIZATION","GH_AW_OTEL_SENTRY_ENDPOINT","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":"9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0","version":"v7.0.0"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-go","sha":"924ae3a1cded613372ab5595356fb5720e22ba16","version":"v6.5.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/setup-python","sha":"ece7cb06caefa5fff74198d8649806c4678c61a1","version":"v6.3.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"docker/build-push-action","sha":"f9f3042f7e2789586610d6e8b85c8f03e5195baf","version":"v7.2.0"},{"repo":"docker/setup-buildx-action","sha":"d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5","version":"v4.1.0"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.27.22","digest":"sha256:55f06588411008b7148eb64b8dfe28602a0cce3675b36c6b190b54aca138468e","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.27.22@sha256:55f06588411008b7148eb64b8dfe28602a0cce3675b36c6b190b54aca138468e"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.22","digest":"sha256:afb9ff9140b17d38871dfb9dbac5ff8689ea634c2f91c435da2825192d4881c1","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.22@sha256:afb9ff9140b17d38871dfb9dbac5ff8689ea634c2f91c435da2825192d4881c1"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.27.22","digest":"sha256:3cdcc1e2b4b4fe602ba69fd3e21aac7ac512d5c1fce24df4ce69dc4f98164b59","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.27.22@sha256:3cdcc1e2b4b4fe602ba69fd3e21aac7ac512d5c1fce24df4ce69dc4f98164b59"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.32","digest":"sha256:63e46b56dfd70895a701b6fc6dd0189e11e2d875f327f1781e81b31848735477","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.32@sha256:63e46b56dfd70895a701b6fc6dd0189e11e2d875f327f1781e81b31848735477"},{"image":"ghcr.io/github/gh-aw-node","digest":"sha256:529d02eb970b1161aa25c593a9c3df57fdfad5a8add328cb3b6eccef66f3183b","pinned_image":"ghcr.io/github/gh-aw-node@sha256:529d02eb970b1161aa25c593a9c3df57fdfad5a8add328cb3b6eccef66f3183b"},{"image":"ghcr.io/github/github-mcp-server:v1.5.0","digest":"sha256:e25564dccc9110a70a77b9df560cbde11aa392fcb5f08b9abe5c4ebc6d146ea4","pinned_image":"ghcr.io/github/github-mcp-server:v1.5.0@sha256:e25564dccc9110a70a77b9df560cbde11aa392fcb5f08b9abe5c4ebc6d146ea4"}]} # This file was automatically generated by gh-aw. DO NOT EDIT. To debug this workflow, load the skill at https://github.com/github/gh-aw/blob/main/debug.md # @@ -837,7 +837,7 @@ jobs: 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 --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 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 GITHUB_AW_OTEL_TRACE_ID -e GITHUB_AW_OTEL_PARENT_SPAN_ID -e OTEL_EXPORTER_OTLP_HEADERS -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.3.32' GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node) - cat << GH_AW_MCP_CONFIG_a91bf15279da34af_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + cat << GH_AW_MCP_CONFIG_ae1ba431374e0d2e_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" { "mcpServers": { "agenticworkflows": { @@ -910,6 +910,7 @@ jobs: "domain": "${MCP_GATEWAY_DOMAIN}", "apiKey": "${MCP_GATEWAY_API_KEY}", "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}", + "toolTimeout": 600, "opentelemetry": { "endpoint": "${OTEL_EXPORTER_OTLP_ENDPOINT}", "traceId": "${GITHUB_AW_OTEL_TRACE_ID}", @@ -917,7 +918,7 @@ jobs: } } } - GH_AW_MCP_CONFIG_a91bf15279da34af_EOF + GH_AW_MCP_CONFIG_ae1ba431374e0d2e_EOF - name: Mount MCP servers as CLIs id: mount-mcp-clis continue-on-error: true diff --git a/.github/workflows/detection-analysis-report.md b/.github/workflows/detection-analysis-report.md index 6722e90539f..d35c2dd9c28 100644 --- a/.github/workflows/detection-analysis-report.md +++ b/.github/workflows/detection-analysis-report.md @@ -12,7 +12,10 @@ permissions: issues: read discussions: read tracker-id: detection-analysis-report-daily -engine: claude +engine: + id: claude + mcp: + tool-timeout: 10m tools: cli-proxy: true agentic-workflows: diff --git a/pkg/cli/logs_json_test.go b/pkg/cli/logs_json_test.go index e1368faa4be..7c026639004 100644 --- a/pkg/cli/logs_json_test.go +++ b/pkg/cli/logs_json_test.go @@ -719,6 +719,71 @@ func TestBuildLogsDataWithContinuation(t *testing.T) { } } +// TestBuildLogsDataWithCountLimitContinuation tests that count-limit continuation +// (issued when a date-range fetch fills the requested count) is correctly serialised. +// This mirrors the scenario fixed in issue #42994 where daily audits only received +// partial run sets because the count cap was hit mid-range with no pagination signal. +func TestBuildLogsDataWithCountLimitContinuation(t *testing.T) { + tmpDir := testutil.TempDir(t, "test-*") + + processedRuns := []ProcessedRun{ + { + Run: WorkflowRun{ + DatabaseID: 20000, + WorkflowName: "api-consumption-report", + LogsPath: filepath.Join(tmpDir, "run-20000"), + }, + }, + { + Run: WorkflowRun{ + DatabaseID: 19999, + WorkflowName: "api-consumption-report", + LogsPath: filepath.Join(tmpDir, "run-19999"), + }, + }, + } + + // Simulate what DownloadWorkflowLogs emits when fetchAllInRange is true and the + // count limit is reached before all runs in the date window are fetched. + // DownloadWorkflowLogs receives resolved absolute dates (the CLI resolves relative + // shorthands like "-1d" before calling it), so use a concrete date here. + continuation := &ContinuationData{ + Message: "Count limit reached. Use these parameters to continue fetching more logs from the same date range.", + StartDate: "2026-06-01", + Count: 100, + BeforeRunID: 19999, // oldest processed run + Timeout: 3, + } + + logsData := buildLogsData(processedRuns, tmpDir, continuation) + + if logsData.Continuation == nil { + t.Fatal("Expected continuation field, got nil") + } + if logsData.Continuation.BeforeRunID != 19999 { + t.Errorf("Expected BeforeRunID 19999, got %d", logsData.Continuation.BeforeRunID) + } + if logsData.Continuation.StartDate != "2026-06-01" { + t.Errorf("Expected StartDate '2026-06-01', got %q", logsData.Continuation.StartDate) + } + + // Verify round-trip JSON serialisation preserves continuation. + raw, err := json.Marshal(logsData) + if err != nil { + t.Fatalf("json.Marshal: %v", err) + } + var parsed LogsData + if err := json.Unmarshal(raw, &parsed); err != nil { + t.Fatalf("json.Unmarshal: %v", err) + } + if parsed.Continuation == nil { + t.Fatal("Expected continuation in round-tripped JSON, got nil") + } + if parsed.Continuation.BeforeRunID != 19999 { + t.Errorf("Round-trip BeforeRunID: got %d, want 19999", parsed.Continuation.BeforeRunID) + } +} + // TestBuildLogsDataWithoutContinuation tests that continuation is omitted when nil func TestBuildLogsDataWithoutContinuation(t *testing.T) { tmpDir := testutil.TempDir(t, "test-*") diff --git a/pkg/cli/logs_orchestrator.go b/pkg/cli/logs_orchestrator.go index a2a4a2b506c..697f2024137 100644 --- a/pkg/cli/logs_orchestrator.go +++ b/pkg/cli/logs_orchestrator.go @@ -139,6 +139,45 @@ func selectPaginationCursorDate(filteredRuns []WorkflowRun, oldestFetchedCreated return filteredRuns[len(filteredRuns)-1].CreatedAt.Format(time.RFC3339), true } +// buildContinuationIfNeeded returns a ContinuationData cursor when more runs may +// be available after this batch, or nil if the full result set was collected. +// +// A continuation is emitted in two cases: +// - timeoutReached: the caller's timeout expired mid-download; runs beyond the +// deadline were not fetched and may still exist. +// - countLimitReached: in fetchAllInRange mode the count cap was hit before the +// date window was exhausted; the next page starts just before the oldest run +// returned in this batch. +func buildContinuationIfNeeded( + processedRuns []ProcessedRun, + timeoutReached, countLimitReached bool, + workflowName, startDate, endDate, engine, branch string, + afterRunID int64, count, timeoutMinutes int, +) *ContinuationData { + if len(processedRuns) == 0 || (!timeoutReached && !countLimitReached) { + return nil + } + // Use the oldest processed run as the before_run_id cursor for the next page. + oldestRunID := processedRuns[len(processedRuns)-1].Run.DatabaseID + message := "Timeout reached. Use these parameters to continue fetching more logs." + if countLimitReached { + // In fetchAllInRange mode the date window may contain more runs than count. + message = "Count limit reached. Use these parameters to continue fetching more logs from the same date range." + } + return &ContinuationData{ + Message: message, + WorkflowName: workflowName, + Count: count, + StartDate: startDate, + EndDate: endDate, + Engine: engine, + Branch: branch, + AfterRunID: afterRunID, + BeforeRunID: oldestRunID, + Timeout: timeoutMinutes, + } +} + // DownloadWorkflowLogs downloads and analyzes workflow logs with metrics func DownloadWorkflowLogs(ctx context.Context, opts LogsDownloadOptions) error { workflowName := opts.WorkflowName @@ -246,11 +285,19 @@ func DownloadWorkflowLogs(ctx context.Context, opts LogsDownloadOptions) error { var beforeDate string iteration := 0 - // Determine if we should fetch all runs (when date filters are specified) or limit by count - // When date filters are specified, we fetch all runs within that range and apply count to final output - // When no date filters, we fetch up to 'count' runs with artifacts (old behavior for backward compatibility) + // Determine if we should fetch all runs in the date window or limit iteratively by count. + // In fetchAllInRange mode (when date filters are specified), count acts as a page size: + // the loop stops once count runs are collected and a continuation cursor is emitted so + // callers can page through the full date window. + // Without date filters, we fetch up to count runs with artifacts and stop (old behavior + // for backward compatibility). fetchAllInRange := startDate != "" || endDate != "" + // countLimitReached is set when the loop exits because len(processedRuns) >= count in + // fetchAllInRange mode. It signals that more runs may be available in the date window + // and drives continuation-data generation so callers can page through the full range. + var countLimitReached bool + // Iterative algorithm: keep fetching runs until we have enough or exhaust available runs outerLoop: for iteration < MaxIterations { @@ -285,8 +332,13 @@ outerLoop: } } - // Stop if we've collected enough processed runs + // Stop if we've collected enough processed runs. + // In fetchAllInRange mode, record that we hit the count limit so the caller + // can paginate to retrieve runs that fall outside this batch. if len(processedRuns) >= count { + if fetchAllInRange { + countLimitReached = true + } break } @@ -681,25 +733,10 @@ outerLoop: processedRuns = processedRuns[:count] } - // Build continuation data if timeout was reached and there are processed runs - var continuation *ContinuationData - if timeoutReached && len(processedRuns) > 0 { - // Get the oldest run ID from processed runs to use as before_run_id for continuation - oldestRunID := processedRuns[len(processedRuns)-1].Run.DatabaseID - - continuation = &ContinuationData{ - Message: "Timeout reached. Use these parameters to continue fetching more logs.", - WorkflowName: workflowName, - Count: count, - StartDate: startDate, - EndDate: endDate, - Engine: engine, - Branch: ref, - AfterRunID: afterRunID, - BeforeRunID: oldestRunID, // Continue from where we left off - Timeout: timeoutMinutes, - } - } + // Build continuation data if timeout was reached and there are processed runs, + // OR if a date-range fetch hit the count limit (more runs may exist in the window). + continuation := buildContinuationIfNeeded(processedRuns, timeoutReached, countLimitReached, + workflowName, startDate, endDate, engine, ref, afterRunID, count, timeoutMinutes) return renderLogsOutput(processedRuns, renderLogsOutputOptions{ outputDir: outputDir, diff --git a/pkg/cli/logs_orchestrator_unit_test.go b/pkg/cli/logs_orchestrator_unit_test.go index 3f055f564a5..93d65df62df 100644 --- a/pkg/cli/logs_orchestrator_unit_test.go +++ b/pkg/cli/logs_orchestrator_unit_test.go @@ -134,3 +134,49 @@ func TestParseFilterDate(t *testing.T) { }) } } + +// TestBuildContinuationIfNeeded exercises the helper that DownloadWorkflowLogs uses +// to emit a pagination cursor when a date-range fetch hits the count limit or times out. +func TestBuildContinuationIfNeeded(t *testing.T) { + runs := []ProcessedRun{ + {Run: WorkflowRun{DatabaseID: 3000}}, + {Run: WorkflowRun{DatabaseID: 2999}}, // oldest – used as BeforeRunID cursor + } + + t.Run("count limit reached emits cursor with correct message and BeforeRunID", func(t *testing.T) { + c := buildContinuationIfNeeded(runs, false, true, + "my-workflow", "2026-06-01", "2026-06-30", "claude", "main", + 0, 100, 3, + ) + require.NotNil(t, c, "expected continuation when countLimitReached=true") + assert.Equal(t, int64(2999), c.BeforeRunID, "BeforeRunID should be oldest processed run") + assert.Equal(t, "2026-06-01", c.StartDate) + assert.Equal(t, "2026-06-30", c.EndDate) + assert.Equal(t, 100, c.Count) + assert.Contains(t, c.Message, "Count limit reached") + }) + + t.Run("timeout reached emits cursor with timeout message", func(t *testing.T) { + c := buildContinuationIfNeeded(runs, true, false, + "my-workflow", "2026-06-01", "", "claude", "", + 0, 50, 10, + ) + require.NotNil(t, c, "expected continuation when timeoutReached=true") + assert.Equal(t, int64(2999), c.BeforeRunID) + assert.Contains(t, c.Message, "Timeout reached") + }) + + t.Run("neither flag set returns nil", func(t *testing.T) { + c := buildContinuationIfNeeded(runs, false, false, + "my-workflow", "2026-06-01", "", "claude", "", 0, 100, 3, + ) + assert.Nil(t, c, "expected nil when neither timeout nor count limit was reached") + }) + + t.Run("empty processedRuns returns nil even when count limit reached", func(t *testing.T) { + c := buildContinuationIfNeeded(nil, false, true, + "my-workflow", "2026-06-01", "", "claude", "", 0, 100, 3, + ) + assert.Nil(t, c, "expected nil when no runs were processed") + }) +}