diff --git a/.github/workflows/advisory-uk-ai-operational-resilience.lock.yml b/.github/workflows/advisory-uk-ai-operational-resilience.lock.yml index 59406781..951e4ce9 100644 --- a/.github/workflows/advisory-uk-ai-operational-resilience.lock.yml +++ b/.github/workflows/advisory-uk-ai-operational-resilience.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"c417562927e4f81e9e32068650cb19f02a90842872d1aa99c3ffc7ec921f5067","body_hash":"5d8407114d649b50d22021708afa35ef8dda3965e83b4eee52cd482201a009df","compiler_version":"v0.87.9","strict":true,"agent_id":"pi","agent_model":"copilot/gpt-5.4","engine_versions":{"pi":"0.84.3"}} +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"78f2551069955c0b3772720fcbcf79b76ebd8010a3cc5c0f06dd6b171ed18d20","body_hash":"5d8407114d649b50d22021708afa35ef8dda3965e83b4eee52cd482201a009df","compiler_version":"v0.87.9","strict":true,"agent_id":"pi","agent_model":"copilot/gpt-5.4","engine_versions":{"pi":"0.84.3"}} # gh-aw-manifest: {"version":1,"secrets":["GH_AW_DEFAULT_OTLP_HEADERS","GH_AW_GITHUB_APP_ID","GH_AW_GITHUB_APP_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":"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":"49dc896ccb7d6d975514cfe232bcbd68cc12e2c1","version":"v0.87.9"},{"repo":"github/gh-aw-actions/setup-cli","sha":"49dc896ccb7d6d975514cfe232bcbd68cc12e2c1","version":"v0.87.9"},{"repo":"ruby/setup-ruby","sha":"95ef2b042f9d7a56d8268cba8559e2842e2ad01b","version":"v1.321.0"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.28.9","digest":"sha256:54b2fb3068efc15a4cc1bd4033f8fa056a9b1779baeba0cb80ae95ea55e7e343","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.28.9@sha256:54b2fb3068efc15a4cc1bd4033f8fa056a9b1779baeba0cb80ae95ea55e7e343"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.28.9","digest":"sha256:a0ffb1dc926c6e5a500b336893e032a8f167d3db43c869be886874ef14280bb8","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.28.9@sha256:a0ffb1dc926c6e5a500b336893e032a8f167d3db43c869be886874ef14280bb8"},{"image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.28.9","digest":"sha256:38d7ac0585ee5aa6a06eb71e087d514b059db36005c7783c6485e0dfd36fea35","pinned_image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.28.9@sha256:38d7ac0585ee5aa6a06eb71e087d514b059db36005c7783c6485e0dfd36fea35"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.28.9","digest":"sha256:3d5dba0b0a139bbb11b5d5b8b44f277d2b18f69cf43090e3c283d750cf864baa","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.28.9@sha256:3d5dba0b0a139bbb11b5d5b8b44f277d2b18f69cf43090e3c283d750cf864baa"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.4.13","digest":"sha256:ec4008521c610e1113ed557ecec0ff64a2c2111e4cfa817bab54d9b7da24c7cc","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.4.13@sha256:ec4008521c610e1113ed557ecec0ff64a2c2111e4cfa817bab54d9b7da24c7cc"},{"image":"ghcr.io/github/gh-aw-node","digest":"sha256:bac2192f6374d6262116399b34fc5e143d576f82719e90a18261cae7480f4d4e","pinned_image":"ghcr.io/github/gh-aw-node@sha256:bac2192f6374d6262116399b34fc5e143d576f82719e90a18261cae7480f4d4e"},{"image":"ghcr.io/github/github-mcp-server:v1.11.0","digest":"sha256:fbec75de11c255213fa08d80fb166abe73d851fff631c51c0079872967720699","pinned_image":"ghcr.io/github/github-mcp-server:v1.11.0@sha256:fbec75de11c255213fa08d80fb166abe73d851fff631c51c0079872967720699"}],"mcp_servers":[{"name":"safeoutputs","tools":["create_issue","missing_data","missing_tool","noop"]}]} # This file was automatically generated by gh-aw (v0.87.9). DO NOT EDIT. To debug this workflow, load the skill at https://github.com/github/gh-aw/blob/main/debug.md # @@ -387,7 +387,7 @@ jobs: security-events: read vulnerability-alerts: read concurrency: - group: "gh-aw-pi-${{ github.workflow }}" + group: "gh-aw-pi-${{ github.workflow }}-${{ github.run_id }}" queue: max timeout-minutes: 60 env: @@ -604,6 +604,7 @@ jobs: permission-contents: read permission-issues: read permission-pull-requests: read + permission-secret-scanning-alerts: read permission-security-events: read permission-vulnerability-alerts: read - name: Determine automatic lockdown mode for GitHub MCP Server @@ -1179,7 +1180,7 @@ jobs: actions: read issues: write concurrency: - group: "gh-aw-conclusion-advisory-uk-ai-operational-resilience" + group: "gh-aw-conclusion-advisory-uk-ai-operational-resilience-${{ github.run_id }}" cancel-in-progress: false queue: max env: diff --git a/.github/workflows/advisory-uk-ai-operational-resilience.md b/.github/workflows/advisory-uk-ai-operational-resilience.md index 7e8bd598..5002899e 100644 --- a/.github/workflows/advisory-uk-ai-operational-resilience.md +++ b/.github/workflows/advisory-uk-ai-operational-resilience.md @@ -57,6 +57,7 @@ permissions: issues: read pull-requests: read security-events: read + secret-scanning-alerts: read vulnerability-alerts: read engine: @@ -75,6 +76,7 @@ run-name: "UK AI operational resilience advisory · ${{ inputs.target_repo }} · concurrency: group: "${{ github.workflow }}-${{ inputs.target_repo }}" + job-discriminator: ${{ github.run_id }} cancel-in-progress: true tracker-id: advisory-uk-ai-operational-resilience diff --git a/tests/unit/workflow-contract.test.mjs b/tests/unit/workflow-contract.test.mjs index 6cea6259..0f4162b6 100644 --- a/tests/unit/workflow-contract.test.mjs +++ b/tests/unit/workflow-contract.test.mjs @@ -321,7 +321,7 @@ test("enterprise defaults, budgets, timeouts, and concurrency are finite", () => const source = workflow(name); assert.match(source, new RegExp(`max-ai-credits: ${limits.credits}`), name); assert.match(source, new RegExp(`timeout-minutes: ${limits.timeout}`), name); - assert.match(source, /concurrency:\n\s+group:.*\n\s+cancel-in-progress: true/, name); + assert.match(source, /concurrency:\n\s+group:.*\n(?:\s+job-discriminator:.*\n)?\s+cancel-in-progress: true/, name); assert.doesNotMatch(source, /^\s+(contents|actions|issues|pull-requests): write$/m, name); if (limits.dispatchMax) { assert.match(source, new RegExp(`dispatch_max: "${limits.dispatchMax}"`), name); @@ -904,6 +904,8 @@ test("Advisory preserves UK AI guidance and human-review boundaries", () => { assert.match(worker, /repository_metadata/); assert.match(worker, /visibility: repositoryData\.visibility/); assert.match(worker, /open_dependabot_alerts/); + assert.match(worker, /secret-scanning-alerts: read/); + assert.match(worker, /job-discriminator: \$\{\{ github\.run_id \}\}/); assert.match(worker, /dependency_automation/); assert.match(worker, /security_policy/); assert.match(worker, /age_days: ageDays\(alert\.created_at\)/);