diff --git a/.github/workflows/README.md b/.github/workflows/README.md index 7e4634ceb2..8b03b8429d 100644 --- a/.github/workflows/README.md +++ b/.github/workflows/README.md @@ -66,6 +66,7 @@ Agentic workflows authenticate through repository secrets: | --- | --- | --- | | `COPILOT_GITHUB_TOKEN` | GitHub Copilot CLI (model inference) | Fine-grained PAT. **Preferably replaced** by the `copilot-requests: write` permission — see below. | | `GH_AW_GITHUB_TOKEN` | GitHub MCP reads / safe-output writes that need more than the default `GITHUB_TOKEN` | Fine-grained PAT and the token that used to be forced by lockdown mode. **Preferably replaced** by a GitHub App — see below. **Currently unset**: the compiler's token chain (`GH_AW_GITHUB_MCP_SERVER_TOKEN` \|\| `GH_AW_GITHUB_TOKEN` \|\| `GITHUB_TOKEN`) falls back to the per-run `GITHUB_TOKEN` when this secret is absent, so leave it unset unless a workflow needs elevated access. | +| `BACKPORT_MACHINE_USER_PAT` | ResourceLock safe-output PR creation and existing deterministic automation PRs | Existing machine-user PAT that pushes automation branches to `nohwnd-bot/testfx` and opens PRs against `microsoft/testfx`, avoiding the repository policy that prevents the default `GITHUB_TOKEN` from creating PRs. Its scopes and rotation are managed outside this repository; replace it with the GitHub App below when that App is provisioned for both repositories. | > [!IMPORTANT] > **Fine-grained PATs expire, and the `Microsoft Open Source` enterprise now hard-rejects any @@ -73,14 +74,17 @@ Agentic workflows authenticate through repository secrets: > at the token's settings page). A PAT-based setup therefore breaks on a short cycle: when the > token lapses — or simply outlives the 8-day window — every workflow that depends on it fails at > once (e.g. the `Checkout PR branch` step 403s on the collaborator-permission and PR lookups) and -> files a burst of `[aw] … failed` issues. Prefer the two PAT-free options below — together they -> let this repo run agentic workflows with **no long-lived PAT at all**. +> files a burst of `[aw] … failed` issues. Prefer the two PAT-free options below for normal gh-aw +> authentication. `resource-lock-refactoring` is currently an explicit exception: repository policy +> prevents its run-scoped `GITHUB_TOKEN` from creating pull requests, so it reuses +> `BACKPORT_MACHINE_USER_PAT` until the GitHub App is provisioned for both the upstream repository +> and the automation fork. > > **Fast unblock:** delete the `GH_AW_GITHUB_TOKEN` secret (run `gh secret delete GH_AW_GITHUB_TOKEN --repo microsoft/testfx`). -> Because no source workflow forces a custom PAT anymore (`lockdown` was -> removed repo-wide and all declare `min-integrity: none`), every workflow then degrades gracefully -> to the built-in `GITHUB_TOKEN`. The only case that still needs elevated auth is a write-back on a -> **fork** PR (where `GITHUB_TOKEN` is read-only) — use the GitHub App below for those. +> Because no source workflow forces `GH_AW_GITHUB_TOKEN` anymore (`lockdown` was removed repo-wide +> and all declare `min-integrity: none`), general GitHub reads and writes then degrade gracefully to +> the built-in `GITHUB_TOKEN`. Workflows that explicitly name another credential, including +> `resource-lock-refactoring`, are unaffected by deleting `GH_AW_GITHUB_TOKEN`. ### Preferred: eliminate the expiring PATs diff --git a/.github/workflows/resource-lock-refactoring.lock.yml b/.github/workflows/resource-lock-refactoring.lock.yml index 7dd8a66da6..613f7249fd 100644 --- a/.github/workflows/resource-lock-refactoring.lock.yml +++ b/.github/workflows/resource-lock-refactoring.lock.yml @@ -1,5 +1,5 @@ -# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"b7e51dcaf22f774902178cd327bff150f47516da29abebf0abc41f0630749452","body_hash":"9c0969164e218ecf2b16747acb70133f8604fd005f6461b70e387bceb6d4ac08","compiler_version":"v0.86.2","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.79"}} -# gh-aw-manifest: {"version":1,"secrets":["GH_AW_CI_TRIGGER_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":"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/cli-proxy:0.27.44","digest":"sha256:c064d15974f7c933ec7d3f7b4038f4fd203547b3154bdc821afd379144887eff","pinned_image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.27.44@sha256:c064d15974f7c933ec7d3f7b4038f4fd203547b3154bdc821afd379144887eff"},{"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"}]} +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"95bcf2dc35b991b23e303d61ff90c7c2b80570ebf783731bcb65072dd4e467cc","body_hash":"6c9317f7c34d81aeb6e82d0c62afd2a181874a437b9e23dafbe72fa8e1bd8910","compiler_version":"v0.86.2","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.79"}} +# gh-aw-manifest: {"version":1,"secrets":["BACKPORT_MACHINE_USER_PAT","GH_AW_CI_TRIGGER_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":"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/cli-proxy:0.27.44","digest":"sha256:c064d15974f7c933ec7d3f7b4038f4fd203547b3154bdc821afd379144887eff","pinned_image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.27.44@sha256:c064d15974f7c933ec7d3f7b4038f4fd203547b3154bdc821afd379144887eff"},{"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,6 +29,7 @@ # - DOTNET_CLI_TELEMETRY_SESSIONID: (main workflow) # # Secrets used: +# - BACKPORT_MACHINE_USER_PAT # - GH_AW_CI_TRIGGER_TOKEN # - GH_AW_GITHUB_MCP_SERVER_TOKEN # - GH_AW_GITHUB_TOKEN @@ -501,13 +502,15 @@ jobs: - 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/cli-proxy:0.27.44@sha256:c064d15974f7c933ec7d3f7b4038f4fd203547b3154bdc821afd379144887eff 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 + env: + GH_AW_SECRET_BACKPORT_MACHINE_USER_PAT: ${{ secrets.BACKPORT_MACHINE_USER_PAT }} run: | mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs" mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs - cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_4bc276bbc9601950_EOF' - {"create_pull_request":{"allowed_branches":["resource-lock/*"],"allowed_files":["test/UnitTests/**/*.cs","test/IntegrationTests/**/*.cs"],"base_branch":"main","draft":true,"excluded_files":["test/IntegrationTests/TestAssets/**","test/Performance/**","test/UnitTests/TestFramework.UnitTests/Assertions/AssertInterpolatedStringHandlerGeneratedOverloadsTests.cs","test/**/*.Designer.cs","test/**/*.generated.cs","test/**/*.g.cs"],"fallback_as_issue":false,"if_no_changes":"ignore","labels":["type/automation","type/tech-debt"],"max":1,"max_patch_files":8,"max_patch_size":256,"protect_top_level_dot_folders":true,"protected_files":["package.json","bun.lockb","bunfig.toml","deno.json","deno.jsonc","deno.lock","global.json","NuGet.Config","Directory.Packages.props","mix.exs","mix.lock","go.mod","go.sum","stack.yaml","stack.yaml.lock","pom.xml","build.gradle","build.gradle.kts","settings.gradle","settings.gradle.kts","gradle.properties","package-lock.json","yarn.lock","pnpm-lock.yaml","npm-shrinkwrap.json","requirements.txt","Pipfile","Pipfile.lock","pyproject.toml","setup.py","setup.cfg","Gemfile","Gemfile.lock","uv.lock","CODEOWNERS","DESIGN.md","README.md","CONTRIBUTING.md","CHANGELOG.md","SECURITY.md","CODE_OF_CONDUCT.md","AGENTS.md"],"protected_files_policy":"blocked","title_prefix":"[ResourceLock] "},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"false"},"report_incomplete":{}} - GH_AW_SAFE_OUTPUTS_CONFIG_4bc276bbc9601950_EOF + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_95a0639b557a72f4_EOF' + {"create_pull_request":{"allowed_branches":["resource-lock/*"],"allowed_files":["test/UnitTests/**/*.cs","test/IntegrationTests/**/*.cs"],"allowed_repos":["microsoft/testfx","nohwnd-bot/testfx"],"base_branch":"main","draft":true,"excluded_files":["test/IntegrationTests/TestAssets/**","test/Performance/**","test/UnitTests/TestFramework.UnitTests/Assertions/AssertInterpolatedStringHandlerGeneratedOverloadsTests.cs","test/**/*.Designer.cs","test/**/*.generated.cs","test/**/*.g.cs"],"fallback_as_issue":false,"github-token":"${GH_AW_SECRET_BACKPORT_MACHINE_USER_PAT}","head-github-token":"${GH_AW_SECRET_BACKPORT_MACHINE_USER_PAT}","head-repo":"nohwnd-bot/testfx","if_no_changes":"ignore","labels":["type/automation","type/tech-debt"],"max":1,"max_patch_files":8,"max_patch_size":256,"protect_top_level_dot_folders":true,"protected_files":["package.json","bun.lockb","bunfig.toml","deno.json","deno.jsonc","deno.lock","global.json","NuGet.Config","Directory.Packages.props","mix.exs","mix.lock","go.mod","go.sum","stack.yaml","stack.yaml.lock","pom.xml","build.gradle","build.gradle.kts","settings.gradle","settings.gradle.kts","gradle.properties","package-lock.json","yarn.lock","pnpm-lock.yaml","npm-shrinkwrap.json","requirements.txt","Pipfile","Pipfile.lock","pyproject.toml","setup.py","setup.cfg","Gemfile","Gemfile.lock","uv.lock","CODEOWNERS","DESIGN.md","README.md","CONTRIBUTING.md","CHANGELOG.md","SECURITY.md","CODE_OF_CONDUCT.md","AGENTS.md"],"protected_files_policy":"blocked","target-repo":"microsoft/testfx","title_prefix":"[ResourceLock] "},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"false"},"report_incomplete":{}} + GH_AW_SAFE_OUTPUTS_CONFIG_95a0639b557a72f4_EOF - name: Generate Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | @@ -515,7 +518,12 @@ jobs: "description_suffixes": { "create_pull_request": " CONSTRAINTS: Maximum 1 pull request(s) can be created. Title will be prefixed with \"[ResourceLock] \". Labels [\"type/automation\" \"type/tech-debt\"] will be automatically added. PRs will be created as drafts." }, - "repo_params": {}, + "repo_params": { + "create_pull_request": { + "description": "Target repository for this operation in 'owner/repo' format. Default is \"microsoft/testfx\". Must be the target-repo or in the allowed-repos list.", + "type": "string" + } + }, "dynamic_tools": [] } GH_AW_VALIDATION_JSON: | @@ -915,7 +923,8 @@ jobs: const { main } = require('${{ runner.temp }}/gh-aw/actions/redact_secrets.cjs'); await main(); env: - GH_AW_SECRET_NAMES: 'GH_AW_GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,GITHUB_TOKEN' + GH_AW_SECRET_NAMES: 'BACKPORT_MACHINE_USER_PAT,GH_AW_GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,GITHUB_TOKEN' + SECRET_BACKPORT_MACHINE_USER_PAT: ${{ secrets.BACKPORT_MACHINE_USER_PAT }} SECRET_GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} SECRET_GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} SECRET_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -1683,13 +1692,13 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: true - token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + token: ${{ secrets.BACKPORT_MACHINE_USER_PAT }} - name: Configure Git credentials if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') env: GITHUB_REPOSITORY: ${{ github.repository }} GITHUB_SERVER_URL: ${{ github.server_url }} - GIT_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + GIT_TOKEN: ${{ secrets.BACKPORT_MACHINE_USER_PAT }} run: bash "${RUNNER_TEMP}/gh-aw/actions/configure_git_credentials.sh" - name: Configure GH_HOST for enterprise compatibility id: ghes-host-config @@ -1709,8 +1718,9 @@ jobs: GH_AW_ALLOWED_DOMAINS: "*.vsblob.vsassets.io,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.nuget.org,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,azuresearch-usnc.nuget.org,azuresearch-ussc.nuget.org,builds.dotnet.microsoft.com,ci.dot.net,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,data.nuget.org,dc.services.visualstudio.com,dist.nuget.org,dot.net,dotnet.microsoft.com,dotnetcli.blob.core.windows.net,github.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,nuget.org,nuget.pkg.github.com,nugetregistryv2prod.blob.core.windows.net,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,oneocsp.microsoft.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,pkgs.dev.azure.com,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com,www.microsoft.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_pull_request\":{\"allowed_branches\":[\"resource-lock/*\"],\"allowed_files\":[\"test/UnitTests/**/*.cs\",\"test/IntegrationTests/**/*.cs\"],\"base_branch\":\"main\",\"draft\":true,\"excluded_files\":[\"test/IntegrationTests/TestAssets/**\",\"test/Performance/**\",\"test/UnitTests/TestFramework.UnitTests/Assertions/AssertInterpolatedStringHandlerGeneratedOverloadsTests.cs\",\"test/**/*.Designer.cs\",\"test/**/*.generated.cs\",\"test/**/*.g.cs\"],\"fallback_as_issue\":false,\"if_no_changes\":\"ignore\",\"labels\":[\"type/automation\",\"type/tech-debt\"],\"max\":1,\"max_patch_files\":8,\"max_patch_size\":256,\"protect_top_level_dot_folders\":true,\"protected_files\":[\"package.json\",\"bun.lockb\",\"bunfig.toml\",\"deno.json\",\"deno.jsonc\",\"deno.lock\",\"global.json\",\"NuGet.Config\",\"Directory.Packages.props\",\"mix.exs\",\"mix.lock\",\"go.mod\",\"go.sum\",\"stack.yaml\",\"stack.yaml.lock\",\"pom.xml\",\"build.gradle\",\"build.gradle.kts\",\"settings.gradle\",\"settings.gradle.kts\",\"gradle.properties\",\"package-lock.json\",\"yarn.lock\",\"pnpm-lock.yaml\",\"npm-shrinkwrap.json\",\"requirements.txt\",\"Pipfile\",\"Pipfile.lock\",\"pyproject.toml\",\"setup.py\",\"setup.cfg\",\"Gemfile\",\"Gemfile.lock\",\"uv.lock\",\"CODEOWNERS\",\"DESIGN.md\",\"README.md\",\"CONTRIBUTING.md\",\"CHANGELOG.md\",\"SECURITY.md\",\"CODE_OF_CONDUCT.md\",\"AGENTS.md\"],\"protected_files_policy\":\"blocked\",\"title_prefix\":\"[ResourceLock] \"},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"false\"},\"report_incomplete\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_pull_request\":{\"allowed_branches\":[\"resource-lock/*\"],\"allowed_files\":[\"test/UnitTests/**/*.cs\",\"test/IntegrationTests/**/*.cs\"],\"allowed_repos\":[\"microsoft/testfx\",\"nohwnd-bot/testfx\"],\"base_branch\":\"main\",\"draft\":true,\"excluded_files\":[\"test/IntegrationTests/TestAssets/**\",\"test/Performance/**\",\"test/UnitTests/TestFramework.UnitTests/Assertions/AssertInterpolatedStringHandlerGeneratedOverloadsTests.cs\",\"test/**/*.Designer.cs\",\"test/**/*.generated.cs\",\"test/**/*.g.cs\"],\"fallback_as_issue\":false,\"github-token\":\"${{ secrets.BACKPORT_MACHINE_USER_PAT }}\",\"head-github-token\":\"${{ secrets.BACKPORT_MACHINE_USER_PAT }}\",\"head-repo\":\"nohwnd-bot/testfx\",\"if_no_changes\":\"ignore\",\"labels\":[\"type/automation\",\"type/tech-debt\"],\"max\":1,\"max_patch_files\":8,\"max_patch_size\":256,\"protect_top_level_dot_folders\":true,\"protected_files\":[\"package.json\",\"bun.lockb\",\"bunfig.toml\",\"deno.json\",\"deno.jsonc\",\"deno.lock\",\"global.json\",\"NuGet.Config\",\"Directory.Packages.props\",\"mix.exs\",\"mix.lock\",\"go.mod\",\"go.sum\",\"stack.yaml\",\"stack.yaml.lock\",\"pom.xml\",\"build.gradle\",\"build.gradle.kts\",\"settings.gradle\",\"settings.gradle.kts\",\"gradle.properties\",\"package-lock.json\",\"yarn.lock\",\"pnpm-lock.yaml\",\"npm-shrinkwrap.json\",\"requirements.txt\",\"Pipfile\",\"Pipfile.lock\",\"pyproject.toml\",\"setup.py\",\"setup.cfg\",\"Gemfile\",\"Gemfile.lock\",\"uv.lock\",\"CODEOWNERS\",\"DESIGN.md\",\"README.md\",\"CONTRIBUTING.md\",\"CHANGELOG.md\",\"SECURITY.md\",\"CODE_OF_CONDUCT.md\",\"AGENTS.md\"],\"protected_files_policy\":\"blocked\",\"target-repo\":\"microsoft/testfx\",\"title_prefix\":\"[ResourceLock] \"},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"false\"},\"report_incomplete\":{}}" GH_AW_CI_TRIGGER_TOKEN: ${{ secrets.GH_AW_CI_TRIGGER_TOKEN }} + GITHUB_TOKEN: ${{ secrets.BACKPORT_MACHINE_USER_PAT }} with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/resource-lock-refactoring.md b/.github/workflows/resource-lock-refactoring.md index a397d9dac1..c355f91896 100644 --- a/.github/workflows/resource-lock-refactoring.md +++ b/.github/workflows/resource-lock-refactoring.md @@ -72,6 +72,11 @@ safe-outputs: draft: true title-prefix: "[ResourceLock] " labels: [type/automation, type/tech-debt] + target-repo: "microsoft/testfx" + head-repo: "nohwnd-bot/testfx" + allowed-repos: ["microsoft/testfx", "nohwnd-bot/testfx"] + github-token: ${{ secrets.BACKPORT_MACHINE_USER_PAT }} + head-github-token: ${{ secrets.BACKPORT_MACHINE_USER_PAT }} base-branch: main allowed-branches: - resource-lock/* @@ -243,5 +248,9 @@ changes, then call `create_pull_request` exactly once with: - an explicit note when the project remains sequential that this is preparation for a later parallelization opt-in, not an opt-in itself +Pass the complete Markdown body as the safe-output tool's `body` value. Never +pass `--body -` or otherwise use `-` as a stdin placeholder; the safe-output CLI +treats it as the literal pull request body. + If no high-confidence bounded candidate exists, make no changes, call `noop` with a concise explanation, and stop. diff --git a/.github/workflows/test-improver.lock.yml b/.github/workflows/test-improver.lock.yml index 82f821ccfc..735b543a41 100644 --- a/.github/workflows/test-improver.lock.yml +++ b/.github/workflows/test-improver.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"f943b7e0c7415297860a2076f0d07b05308c6d2595ee79522d87bb57df4787f9","body_hash":"6056cf60279a64362ca789d07cd3bbc65344f7a62b4dc85f5f185025e2c15d56","compiler_version":"v0.86.2","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.79"}} +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"35c75e8a5c21eb0528b44ef17c541624cef3f2134d8d6785a01e1c4394531dc3","body_hash":"6056cf60279a64362ca789d07cd3bbc65344f7a62b4dc85f5f185025e2c15d56","compiler_version":"v0.86.2","strict":true,"agent_id":"copilot","detection_agent_id":"copilot","detection_agent_model":"gpt-5-mini","engine_versions":{"copilot":"1.0.79"}} # gh-aw-manifest: {"version":1,"secrets":["GH_AW_CI_TRIGGER_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":"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 # @@ -1647,6 +1647,7 @@ jobs: WORKFLOW_DESCRIPTION: "A testing-focused repository assistant that runs regularly (daily by default) to improve test quality and coverage.\nCan also be triggered on-demand via '/test-assist ' to perform specific tasks.\n- Discovers and validates build, test, and coverage commands for the repository\n- Identifies testing gaps and high-value test opportunities\n- Implements new tests with measured coverage impact\n- Maintains testing-related PRs when CI fails or conflicts arise\n- Records testing techniques and learnings in persistent memory\n- Updates a monthly activity summary for maintainer visibility\nAlways thoughtful, quality-focused, and mindful of test maintainability." HAS_PATCH: ${{ needs.agent.outputs.has_patch }} GH_AW_DETECTION_CONTINUE_ON_ERROR: "true" + CUSTOM_PROMPT: "End the response with exactly one complete THREAT_DETECTION_RESULT JSON object on a single line. Do not wrap that line in Markdown, a code fence, emphasis markers, or any other text formatting.\n" with: script: | const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); @@ -1733,7 +1734,7 @@ jobs: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_DUMMY_BYOK: dummy-byok-key-for-offline-mode COPILOT_GITHUB_TOKEN: ${{ github.token }} - COPILOT_MODEL: detection + COPILOT_MODEL: gpt-5-mini GH_AW_LLM_PROVIDER: github GH_AW_MAX_AI_CREDITS: ${{ vars.GH_AW_DEFAULT_DETECTION_MAX_AI_CREDITS || '400' }} GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }} diff --git a/.github/workflows/test-improver.md b/.github/workflows/test-improver.md index 287b508a5f..1032336458 100644 --- a/.github/workflows/test-improver.md +++ b/.github/workflows/test-improver.md @@ -73,6 +73,18 @@ network: safe-outputs: report-failure-as-issue: false + # Pin and constrain the detector because run 32787262866 wrapped its otherwise + # valid structured result in Markdown, which made it unparsable (#10711). + threat-detection: + prompt: > + End the response with exactly one complete THREAT_DETECTION_RESULT JSON + object on a single line. Do not wrap that line in Markdown, a code fence, + emphasis markers, or any other text formatting. + engine: + id: copilot + # gh-aw v0.86.2 requires the detection model under engine despite its + # generic engine.model deprecation warning. + model: gpt-5-mini messages: footer: "> 🤖 **Automated content by GitHub Copilot.** Generated by the [{workflow_name}]({agentic_workflow_url}) workflow.{ai_credits_suffix} · [◷]({history_link})" noop: