From 42eba58a16c597fe9ac17603347dde4afb919a05 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 15 May 2026 03:36:11 +0000 Subject: [PATCH 01/22] Initial plan From 82101fe945abdc3ec1a25eceaf5226e3773380e5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 15 May 2026 03:46:36 +0000 Subject: [PATCH 02/22] fix: allow unsigned PR branch pushes when configured Co-authored-by: mrjf <180956+mrjf@users.noreply.github.com> --- .../patch-push-signed-commits-opt-out.md | 5 +++ actions/setup/js/push_signed_commits.cjs | 14 +++++- actions/setup/js/push_signed_commits.test.cjs | 33 ++++++++++++++ .../setup/js/push_to_pull_request_branch.cjs | 3 ++ .../js/push_to_pull_request_branch.test.cjs | 7 +++ actions/setup/js/types/handler-factory.d.ts | 2 + .../reference/safe-outputs-pull-requests.md | 3 ++ .../content/docs/reference/safe-outputs.md | 1 + pkg/parser/schemas/main_workflow_schema.json | 5 +++ .../compiler_safe_outputs_handlers.go | 1 + pkg/workflow/push_to_pull_request_branch.go | 8 ++++ .../push_to_pull_request_branch_test.go | 45 +++++++++++++++++++ 12 files changed, 126 insertions(+), 1 deletion(-) create mode 100644 .changeset/patch-push-signed-commits-opt-out.md diff --git a/.changeset/patch-push-signed-commits-opt-out.md b/.changeset/patch-push-signed-commits-opt-out.md new file mode 100644 index 00000000000..68761f09a27 --- /dev/null +++ b/.changeset/patch-push-signed-commits-opt-out.md @@ -0,0 +1,5 @@ +--- +"gh-aw": patch +--- + +Allow `push-to-pull-request-branch` to set `push-signed-commits: false` so repositories that do not require signed commits can push merge commits with direct `git push`. diff --git a/actions/setup/js/push_signed_commits.cjs b/actions/setup/js/push_signed_commits.cjs index 4df9fffc332..8739a386189 100644 --- a/actions/setup/js/push_signed_commits.cjs +++ b/actions/setup/js/push_signed_commits.cjs @@ -144,9 +144,10 @@ async function readBlobAsBase64(blobHash, cwd) { * @param {string} opts.baseRef - Git ref of the remote head before commits were applied (used for rev-list) * @param {string} opts.cwd - Working directory of the local git checkout * @param {object} [opts.gitAuthEnv] - Environment variables for git push fallback auth + * @param {boolean} [opts.signedCommits=true] - When false, skip GraphQL signed commits and use git push directly * @returns {Promise} SHA of the commit that landed on the target branch */ -async function pushSignedCommits({ githubClient, owner, repo, branch, baseRef, cwd, gitAuthEnv }) { +async function pushSignedCommits({ githubClient, owner, repo, branch, baseRef, cwd, gitAuthEnv, signedCommits = true }) { // Orphan branch first push: baseRef is "" when push_experiment_state creates a brand-new // branch for the first time (checkoutOrCreateBranch returns "" for new branches). // The GraphQL createCommitOnBranch path cannot handle root commits (no parent to resolve), @@ -176,6 +177,17 @@ async function pushSignedCommits({ githubClient, owner, repo, branch, baseRef, c return undefined; } + if (signedCommits === false) { + core.info(`pushSignedCommits: push-signed-commits disabled, using git push directly for branch ${branch}`); + await exec.exec("git", ["push", "origin", branch], { + cwd, + env: { ...process.env, ...(gitAuthEnv || {}) }, + }); + const pushedSha = shas[shas.length - 1]; + core.info(`pushSignedCommits: git push completed with signed commits disabled, using pushed SHA ${pushedSha}`); + return pushedSha; + } + core.info(`pushSignedCommits: replaying ${shas.length} commit(s) via GraphQL createCommitOnBranch (branch: ${branch}, repo: ${owner}/${repo})`); try { diff --git a/actions/setup/js/push_signed_commits.test.cjs b/actions/setup/js/push_signed_commits.test.cjs index 36c686707a1..385d4a1359a 100644 --- a/actions/setup/js/push_signed_commits.test.cjs +++ b/actions/setup/js/push_signed_commits.test.cjs @@ -1126,6 +1126,39 @@ describe("push_signed_commits integration tests", () => { expect(mockCore.warning).toHaveBeenCalledWith(expect.stringMatching(/merge commit [0-9a-f]{7,40} detected/)); }); + it("should use direct git push for merge commits when signed commits are disabled", async () => { + execGit(["checkout", "-b", "unsigned-side-branch"], { cwd: workDir }); + fs.writeFileSync(path.join(workDir, "unsigned-side.txt"), "side branch content\n"); + execGit(["add", "unsigned-side.txt"], { cwd: workDir }); + execGit(["commit", "-m", "Unsigned side branch commit"], { cwd: workDir }); + + execGit(["checkout", "main"], { cwd: workDir }); + execGit(["checkout", "-b", "unsigned-merge-test-branch"], { cwd: workDir }); + fs.writeFileSync(path.join(workDir, "unsigned-feature.txt"), "feature content\n"); + execGit(["add", "unsigned-feature.txt"], { cwd: workDir }); + execGit(["commit", "-m", "Unsigned feature commit"], { cwd: workDir }); + execGit(["merge", "--no-ff", "unsigned-side-branch", "-m", "Merge unsigned-side-branch into unsigned-merge-test-branch"], { cwd: workDir }); + const expectedHead = execGit(["rev-parse", "HEAD"], { cwd: workDir }).stdout.trim(); + + global.exec = makeRealExec(workDir); + const githubClient = makeMockGithubClient(); + + const pushedSha = await pushSignedCommits({ + githubClient, + owner: "test-owner", + repo: "test-repo", + branch: "unsigned-merge-test-branch", + baseRef: "origin/main", + cwd: workDir, + signedCommits: false, + }); + + expect(pushedSha).toBe(expectedHead); + expect(githubClient.graphql).not.toHaveBeenCalled(); + expect(execGit(["rev-parse", "refs/heads/unsigned-merge-test-branch"], { cwd: bareDir }).stdout.trim()).toBe(expectedHead); + expect(mockCore.info).toHaveBeenCalledWith("pushSignedCommits: push-signed-commits disabled, using git push directly for branch unsigned-merge-test-branch"); + }); + it("should not trigger merge-commit fallback for a commit message that starts with 'parent '", async () => { // Regression test: a commit whose message body starts with "parent " must not be misidentified // as a merge commit. The old cat-file approach would have counted this as an extra parent. diff --git a/actions/setup/js/push_to_pull_request_branch.cjs b/actions/setup/js/push_to_pull_request_branch.cjs index 80f4e6a9c9b..51d36550702 100644 --- a/actions/setup/js/push_to_pull_request_branch.cjs +++ b/actions/setup/js/push_to_pull_request_branch.cjs @@ -113,6 +113,7 @@ async function main(config = {}) { const ignoreMissingBranchFailure = config.ignore_missing_branch_failure === true; const fallbackAsPullRequest = config.fallback_as_pull_request !== false; const checkBranchProtection = config.check_branch_protection !== false; + const signedCommits = config.push_signed_commits !== false; const commitTitleSuffix = config.commit_title_suffix || ""; const maxSizeKb = config.max_patch_size ? parseInt(String(config.max_patch_size), 10) : 1024; const maxCount = config.max || 0; // 0 means no limit @@ -150,6 +151,7 @@ async function main(config = {}) { core.info(`Ignore missing branch failure: ${ignoreMissingBranchFailure}`); core.info(`Fallback as pull request: ${fallbackAsPullRequest}`); core.info(`Check branch protection: ${checkBranchProtection}`); + core.info(`Push signed commits: ${signedCommits}`); if (commitTitleSuffix) { core.info(`Commit title suffix: ${commitTitleSuffix}`); } @@ -891,6 +893,7 @@ async function main(config = {}) { baseRef: remoteHeadBeforePatch || `origin/${branchName}`, cwd: repoCwd || process.cwd(), gitAuthEnv, + signedCommits, }); if (pushedSha) { pushedCommitSha = pushedSha; diff --git a/actions/setup/js/push_to_pull_request_branch.test.cjs b/actions/setup/js/push_to_pull_request_branch.test.cjs index 7d26526bb3b..150110ae0e8 100644 --- a/actions/setup/js/push_to_pull_request_branch.test.cjs +++ b/actions/setup/js/push_to_pull_request_branch.test.cjs @@ -257,6 +257,13 @@ index 0000000..abc1234 expect(mockCore.info).toHaveBeenCalledWith("Target: 456"); }); + it("should accept disabling signed commits", async () => { + const module = await loadModule(); + await module.main({ push_signed_commits: false }); + + expect(mockCore.info).toHaveBeenCalledWith("Push signed commits: false"); + }); + it('should default if_no_changes to "warn"', async () => { const module = await loadModule(); const handler = await module.main({}); diff --git a/actions/setup/js/types/handler-factory.d.ts b/actions/setup/js/types/handler-factory.d.ts index 6ae98df8c2c..06f6ec965f5 100644 --- a/actions/setup/js/types/handler-factory.d.ts +++ b/actions/setup/js/types/handler-factory.d.ts @@ -24,6 +24,8 @@ interface HandlerConfig { protected_files_policy?: string; /** When true (default), create a fallback pull request if direct push to PR branch fails with non-fast-forward/diverged branch. */ fallback_as_pull_request?: boolean; + /** When false, skip GraphQL signed commits and push the local git history directly. */ + push_signed_commits?: boolean; /** Additional handler-specific configuration properties */ [key: string]: any; } diff --git a/docs/src/content/docs/reference/safe-outputs-pull-requests.md b/docs/src/content/docs/reference/safe-outputs-pull-requests.md index f07fcaee013..2ef0161b311 100644 --- a/docs/src/content/docs/reference/safe-outputs-pull-requests.md +++ b/docs/src/content/docs/reference/safe-outputs-pull-requests.md @@ -264,6 +264,7 @@ safe-outputs: github-token: ${{ secrets.SOME_CUSTOM_TOKEN }} # optional custom token for permissions github-token-for-extra-empty-commit: ${{ secrets.CI_TOKEN }} # optional token to push empty commit triggering CI fallback-as-pull-request: true # on non-fast-forward failure, create fallback PR to original PR branch (default: true) + push-signed-commits: true # set false to use git push directly, allowing merge commits when signed commits are not required ignore-missing-branch-failure: false # treat deleted/missing branch errors as skipped instead of failed (default: false) check-branch-protection: true # set to false to skip the branch protection pre-flight check (default: true) protected-files: fallback-to-issue # create review issue if protected files modified @@ -273,6 +274,8 @@ safe-outputs: When `push-to-pull-request-branch` is configured, git commands (`checkout`, `branch`, `switch`, `add`, `rm`, `commit`, `merge`) are automatically enabled. +By default, pushes are replayed through GitHub's signed commit API. Set `push-signed-commits: false` only for repositories that do not require signed commits; this uses direct `git push` and can preserve merge commits that the signed commit API cannot represent. + ### Cross-repo usage `push-to-pull-request-branch` supports pushing to pull requests in a different repository via `target-repo` (and optionally `allowed-repos`). When `target-repo` is set, **the target repository must be checked out into the workflow workspace** using the `checkout:` frontmatter field with a `path:` specified. diff --git a/docs/src/content/docs/reference/safe-outputs.md b/docs/src/content/docs/reference/safe-outputs.md index 9346881519d..6fbb980092d 100644 --- a/docs/src/content/docs/reference/safe-outputs.md +++ b/docs/src/content/docs/reference/safe-outputs.md @@ -890,6 +890,7 @@ safe-outputs: target: "*" # "triggering" (default), "*", or number title-prefix: "[bot] " # require title prefix labels: [automated] # require all labels + push-signed-commits: false # optional: use git push directly when signed commits are not required protected-files: fallback-to-issue # create review issue if protected files modified ``` diff --git a/pkg/parser/schemas/main_workflow_schema.json b/pkg/parser/schemas/main_workflow_schema.json index 3aa21bcb570..38d23c2caac 100644 --- a/pkg/parser/schemas/main_workflow_schema.json +++ b/pkg/parser/schemas/main_workflow_schema.json @@ -7616,6 +7616,11 @@ "description": "When true (default), if pushing to the PR branch fails due to a non-fast-forward/diverged branch, create a fallback pull request that targets the original PR branch. Set to false to disable this behavior and avoid requiring pull-requests: write permission.", "default": true }, + "push-signed-commits": { + "type": "boolean", + "description": "When true (default), pushes regular commits through GitHub's createCommitOnBranch GraphQL mutation so GitHub signs them. Set to false to use git push directly for repositories that do not require signed commits; this also allows pushing merge commits that GraphQL cannot represent.", + "default": true + }, "target-repo": { "type": "string", "description": "Target repository in format 'owner/repo' for cross-repository push to pull request branch. Takes precedence over trial target repo settings." diff --git a/pkg/workflow/compiler_safe_outputs_handlers.go b/pkg/workflow/compiler_safe_outputs_handlers.go index 443617bf080..4a7683e5be6 100644 --- a/pkg/workflow/compiler_safe_outputs_handlers.go +++ b/pkg/workflow/compiler_safe_outputs_handlers.go @@ -455,6 +455,7 @@ var handlerRegistry = map[string]handlerBuilder{ AddStringSlice("excluded_files", c.ExcludedFiles). AddIfNotEmpty("patch_format", c.PatchFormat). AddBoolPtr("fallback_as_pull_request", c.FallbackAsPullRequest). + AddBoolPtr("push_signed_commits", c.PushSignedCommits). AddBoolPtr("check_branch_protection", c.CheckBranchProtection). Build() }, diff --git a/pkg/workflow/push_to_pull_request_branch.go b/pkg/workflow/push_to_pull_request_branch.go index 0afa15f450f..1c140705164 100644 --- a/pkg/workflow/push_to_pull_request_branch.go +++ b/pkg/workflow/push_to_pull_request_branch.go @@ -27,6 +27,7 @@ type PushToPullRequestBranchConfig struct { ExcludedFiles []string `yaml:"excluded-files,omitempty"` // List of glob patterns for files to exclude from the patch using git :(exclude) pathspecs. Matching files are stripped by git at generation time and will not appear in the commit or be subject to allowed-files or protected-files checks. PatchFormat string `yaml:"patch-format,omitempty"` // Transport format for packaging changes: "bundle" (default, uses git bundle and preserves merge topology/per-commit metadata) or "am" (uses git format-patch). FallbackAsPullRequest *bool `yaml:"fallback-as-pull-request,omitempty"` // When true (default), creates a fallback pull request if direct push fails due to diverged/non-fast-forward branch. When false, fallback is disabled and pull-requests: write is not requested. + PushSignedCommits *bool `yaml:"push-signed-commits,omitempty"` // When false, skips GitHub GraphQL signed commits and pushes the local git history directly. Default is true. AllowWorkflows bool `yaml:"allow-workflows,omitempty"` // When true, adds workflows: write to the GitHub App token. Requires safe-outputs.github-app to be configured. CheckBranchProtection *bool `yaml:"check-branch-protection,omitempty"` // When false, skips the branch protection API pre-flight check. Default is true (check enabled). Set to false to avoid needing administration: read permission. } @@ -182,6 +183,13 @@ func (c *Compiler) parsePushToPullRequestBranchConfig(outputMap map[string]any) } } + // Parse push-signed-commits (optional, defaults to true) + if pushSignedCommits, exists := configMap["push-signed-commits"]; exists { + if pushSignedCommitsBool, ok := pushSignedCommits.(bool); ok { + pushToBranchConfig.PushSignedCommits = &pushSignedCommitsBool + } + } + // Parse allow-workflows: when true, adds workflows: write to the GitHub App token if allowWorkflows, exists := configMap["allow-workflows"]; exists { if allowWorkflowsBool, ok := allowWorkflows.(bool); ok { diff --git a/pkg/workflow/push_to_pull_request_branch_test.go b/pkg/workflow/push_to_pull_request_branch_test.go index 3b0a8e6c2d3..1053f1f031c 100644 --- a/pkg/workflow/push_to_pull_request_branch_test.go +++ b/pkg/workflow/push_to_pull_request_branch_test.go @@ -241,6 +241,51 @@ safe-outputs: } } +func TestPushToPullRequestBranchPushSignedCommitsDisabled(t *testing.T) { + tmpDir := testutil.TempDir(t, "test-*") + + testMarkdown := `--- +on: + pull_request: + types: [opened, synchronize] +safe-outputs: + push-to-pull-request-branch: + push-signed-commits: false +--- + +# Test Push to PR Branch Signed Commits Disabled +` + + mdFile := filepath.Join(tmpDir, "test-push-to-pull-request-branch-signed-commits-disabled.md") + if err := os.WriteFile(mdFile, []byte(testMarkdown), 0644); err != nil { + t.Fatalf("Failed to write test markdown file: %v", err) + } + + compiler := NewCompiler() + if err := compiler.CompileWorkflow(mdFile); err != nil { + t.Fatalf("Failed to compile workflow: %v", err) + } + + lockFile := stringutil.MarkdownToLockFile(mdFile) + lockContent, err := os.ReadFile(lockFile) + if err != nil { + t.Fatalf("Failed to read lock file: %v", err) + } + + pushConfig := extractPushToPullRequestBranchHandlerConfig(t, lockContent) + pushSignedCommits, exists := pushConfig["push_signed_commits"] + if !exists { + t.Errorf("Generated workflow should contain push_signed_commits in handler config JSON") + } + pushSignedCommitsBool, isBool := pushSignedCommits.(bool) + if !isBool { + t.Errorf("Expected push_signed_commits to be a bool, got %#v", pushSignedCommits) + } + if pushSignedCommitsBool { + t.Errorf("Expected push_signed_commits=false, got %#v", pushSignedCommitsBool) + } +} + func TestPushToPullRequestBranchFallbackAsPullRequestEnabled(t *testing.T) { tmpDir := testutil.TempDir(t, "test-*") From 115dd07f2286573bcd4b8d9a2aa6bfa0f7950974 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 15 May 2026 04:46:30 +0000 Subject: [PATCH 03/22] Plan signed commits feedback Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .github/workflows/linter-miner.lock.yml | 240 ++++++++++++++++-------- 1 file changed, 157 insertions(+), 83 deletions(-) diff --git a/.github/workflows/linter-miner.lock.yml b/.github/workflows/linter-miner.lock.yml index cd7ce15a6e8..f06725d2736 100644 --- a/.github/workflows/linter-miner.lock.yml +++ b/.github/workflows/linter-miner.lock.yml @@ -1,5 +1,5 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"efd1dc86fd08ae68de1ce40a9b2d5c7bf6481734599a94e6bf4b1f9de27769ee","compiler_version":"v0.72.1","strict":true,"agent_id":"copilot"} -# gh-aw-manifest: {"version":1,"secrets":["GH_AW_CI_TRIGGER_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_GRAFANA_ENDPOINT","GH_AW_OTEL_GRAFANA_HEADERS","GH_AW_OTEL_SENTRY_ENDPOINT","GH_AW_OTEL_SENTRY_HEADERS","GITHUB_TOKEN"],"actions":[{"repo":"actions/cache/restore","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/cache/save","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"v0.72.1","version":"v0.72.1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.41","digest":"sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.25.41@sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.41","digest":"sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.41@sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0"},{"image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.25.41","digest":"sha256:62171f2fa508667b8b0a9e096f826983f312e3da0ce894f80c0f83a875af60fe","pinned_image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.25.41@sha256:62171f2fa508667b8b0a9e096f826983f312e3da0ce894f80c0f83a875af60fe"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.41","digest":"sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.25.41@sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.6","digest":"sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.6@sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c"},{"image":"ghcr.io/github/github-mcp-server:v1.0.3","digest":"sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959","pinned_image":"ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959"},{"image":"ghcr.io/github/serena-mcp-server:latest","digest":"sha256:bf343399e3725c45528f531a230f3a04521d4cdef29f9a5af6282ff0d3c393c5","pinned_image":"ghcr.io/github/serena-mcp-server:latest@sha256:bf343399e3725c45528f531a230f3a04521d4cdef29f9a5af6282ff0d3c393c5"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"efd1dc86fd08ae68de1ce40a9b2d5c7bf6481734599a94e6bf4b1f9de27769ee","strict":true,"agent_id":"copilot"} +# gh-aw-manifest: {"version":1,"secrets":["GH_AW_CI_TRIGGER_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_GRAFANA_ENDPOINT","GH_AW_OTEL_GRAFANA_HEADERS","GH_AW_OTEL_SENTRY_ENDPOINT","GH_AW_OTEL_SENTRY_HEADERS","GITHUB_TOKEN"],"actions":[{"repo":"actions/cache/restore","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/cache/save","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"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":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.46"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.46"},{"image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.25.46"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.46"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.9","digest":"sha256:64828b42a4482f58fab16509d7f8f495a6d97c972a98a68aff20543531ac0388","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.9@sha256:64828b42a4482f58fab16509d7f8f495a6d97c972a98a68aff20543531ac0388"},{"image":"ghcr.io/github/github-mcp-server:v1.0.3","digest":"sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959","pinned_image":"ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959"},{"image":"ghcr.io/github/serena-mcp-server:latest","digest":"sha256:bf343399e3725c45528f531a230f3a04521d4cdef29f9a5af6282ff0d3c393c5","pinned_image":"ghcr.io/github/serena-mcp-server:latest@sha256:bf343399e3725c45528f531a230f3a04521d4cdef29f9a5af6282ff0d3c393c5"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]} # ___ _ _ # / _ \ | | (_) # | |_| | __ _ ___ _ __ | |_ _ ___ @@ -14,7 +14,7 @@ # \ /\ / (_) | | | | ( | | | | (_) \ V V /\__ \ # \/ \/ \___/|_| |_|\_\|_| |_|\___/ \_/\_/ |___/ # -# This file was automatically generated by gh-aw (v0.72.1). DO NOT EDIT. +# This file was automatically generated by gh-aw. DO NOT EDIT. # # To update this file, edit the corresponding .md file and run: # gh aw compile @@ -45,18 +45,17 @@ # - actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 # - actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 # - actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 -# - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 # - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 +# - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 (source v9) # - actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 # - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 -# - github/gh-aw-actions/setup@v0.72.1 # # Container images used: -# - ghcr.io/github/gh-aw-firewall/agent:0.25.41@sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770 -# - ghcr.io/github/gh-aw-firewall/api-proxy:0.25.41@sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0 -# - ghcr.io/github/gh-aw-firewall/cli-proxy:0.25.41@sha256:62171f2fa508667b8b0a9e096f826983f312e3da0ce894f80c0f83a875af60fe -# - ghcr.io/github/gh-aw-firewall/squid:0.25.41@sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4 -# - ghcr.io/github/gh-aw-mcpg:v0.3.6@sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c +# - ghcr.io/github/gh-aw-firewall/agent:0.25.46 +# - ghcr.io/github/gh-aw-firewall/api-proxy:0.25.46 +# - ghcr.io/github/gh-aw-firewall/cli-proxy:0.25.46 +# - ghcr.io/github/gh-aw-firewall/squid:0.25.46 +# - ghcr.io/github/gh-aw-mcpg:v0.3.9@sha256:64828b42a4482f58fab16509d7f8f495a6d97c972a98a68aff20543531ac0388 # - ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959 # - ghcr.io/github/serena-mcp-server:latest@sha256:bf343399e3725c45528f531a230f3a04521d4cdef29f9a5af6282ff0d3c393c5 # - node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f @@ -64,7 +63,7 @@ name: "Linter Miner" "on": schedule: - - cron: "19 8 * * *" + - cron: "21 17 * * *" # Friendly format: daily (scattered) workflow_dispatch: inputs: @@ -101,19 +100,28 @@ jobs: engine_id: ${{ steps.generate_aw_info.outputs.engine_id }} lockdown_check_failed: ${{ steps.generate_aw_info.outputs.lockdown_check_failed == 'true' }} model: ${{ steps.generate_aw_info.outputs.model }} + setup-parent-span-id: ${{ steps.setup.outputs.parent-span-id || steps.setup.outputs.span-id }} + setup-span-id: ${{ steps.setup.outputs.span-id }} setup-trace-id: ${{ steps.setup.outputs.trace-id }} stale_lock_file_failed: ${{ steps.check-lock-file.outputs.stale_lock_file_failed == 'true' }} steps: + - name: Checkout actions folder + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + repository: github/gh-aw + sparse-checkout: | + actions + persist-credentials: false - name: Setup Scripts id: setup - uses: github/gh-aw-actions/setup@v0.72.1 + uses: ./actions/setup with: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} env: GH_AW_SETUP_WORKFLOW_NAME: "Linter Miner" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/linter-miner.lock.yml@${{ github.ref }} - GH_AW_INFO_VERSION: "1.0.40" + GH_AW_INFO_VERSION: "1.0.43" - name: Mask OTLP telemetry headers run: bash "${RUNNER_TEMP}/gh-aw/actions/mask_otlp_headers.sh" - name: Generate agentic run info @@ -122,16 +130,15 @@ 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 || 'claude-sonnet-4.6' }} - GH_AW_INFO_VERSION: "1.0.40" - GH_AW_INFO_AGENT_VERSION: "1.0.40" - GH_AW_INFO_CLI_VERSION: "v0.72.1" + GH_AW_INFO_VERSION: "1.0.43" + GH_AW_INFO_AGENT_VERSION: "1.0.43" GH_AW_INFO_WORKFLOW_NAME: "Linter Miner" GH_AW_INFO_EXPERIMENTAL: "false" GH_AW_INFO_SUPPORTS_TOOLS_ALLOWLIST: "true" GH_AW_INFO_STAGED: "false" GH_AW_INFO_ALLOWED_DOMAINS: '["defaults"]' GH_AW_INFO_FIREWALL_ENABLED: "true" - GH_AW_INFO_AWF_VERSION: "v0.25.41" + GH_AW_INFO_AWF_VERSION: "v0.25.46" GH_AW_INFO_AWMG_VERSION: "" GH_AW_INFO_FIREWALL_TYPE: "squid" GH_AW_COMPILED_STRICT: "true" @@ -149,6 +156,7 @@ jobs: sparse-checkout: | .github .agents + actions/setup .claude .codex .crush @@ -175,25 +183,15 @@ jobs: setupGlobals(core, github, context, exec, io, getOctokit); const { main } = require('${{ runner.temp }}/gh-aw/actions/check_workflow_timestamp_api.cjs'); await main(); - - name: Check compile-agentic version - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 - env: - GH_AW_COMPILED_VERSION: "v0.72.1" - 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/check_version_updates.cjs'); - await main(); - name: Create prompt with built-in context env: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ runner.temp }}/gh-aw/safeoutputs/outputs.jsonl + 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) }} + 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_COMMENT_ID: ${{ github.event.comment.id }} - GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} - GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} - GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} GH_AW_GITHUB_RUN_NUMBER: ${{ github.run_number }} @@ -222,28 +220,28 @@ jobs: cat << 'GH_AW_PROMPT_563dae7ad56cbf7e_EOF' The following GitHub context information is available for this workflow: - {{#if __GH_AW_GITHUB_ACTOR__ }} + {{#if github.actor}} - **actor**: __GH_AW_GITHUB_ACTOR__ {{/if}} - {{#if __GH_AW_GITHUB_REPOSITORY__ }} + {{#if github.repository}} - **repository**: __GH_AW_GITHUB_REPOSITORY__ {{/if}} - {{#if __GH_AW_GITHUB_WORKSPACE__ }} + {{#if github.workspace}} - **workspace**: __GH_AW_GITHUB_WORKSPACE__ {{/if}} - {{#if __GH_AW_GITHUB_EVENT_ISSUE_NUMBER__ }} - - **issue-number**: #__GH_AW_GITHUB_EVENT_ISSUE_NUMBER__ + {{#if github.event.issue.number || (github.aw.context.item_type == 'issue' && github.aw.context.item_number)}} + - **issue-number**: #__GH_AW_EXPR_802A9F6A__ {{/if}} - {{#if __GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__ }} - - **discussion-number**: #__GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__ + {{#if github.event.discussion.number || (github.aw.context.item_type == 'discussion' && github.aw.context.item_number)}} + - **discussion-number**: #__GH_AW_EXPR_1A3A194A__ {{/if}} - {{#if __GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__ }} - - **pull-request-number**: #__GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__ + {{#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 __GH_AW_GITHUB_EVENT_COMMENT_ID__ }} - - **comment-id**: __GH_AW_GITHUB_EVENT_COMMENT_ID__ + {{#if github.event.comment.id || github.aw.context.comment_id}} + - **comment-id**: __GH_AW_EXPR_FF1D34CE__ {{/if}} - {{#if __GH_AW_GITHUB_RUN_ID__ }} + {{#if github.run_id}} - **workflow-run-id**: __GH_AW_GITHUB_RUN_ID__ {{/if}} @@ -310,11 +308,11 @@ jobs: GH_AW_ALLOWED_EXTENSIONS: '' GH_AW_CACHE_DESCRIPTION: '' GH_AW_CACHE_DIR: '/tmp/gh-aw/cache-memory/' + 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) }} + 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_COMMENT_ID: ${{ github.event.comment.id }} - GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} - GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} - GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} GH_AW_GITHUB_RUN_NUMBER: ${{ github.run_number }} @@ -334,11 +332,11 @@ jobs: GH_AW_ALLOWED_EXTENSIONS: process.env.GH_AW_ALLOWED_EXTENSIONS, GH_AW_CACHE_DESCRIPTION: process.env.GH_AW_CACHE_DESCRIPTION, GH_AW_CACHE_DIR: process.env.GH_AW_CACHE_DIR, + GH_AW_EXPR_1A3A194A: process.env.GH_AW_EXPR_1A3A194A, + GH_AW_EXPR_463A214A: process.env.GH_AW_EXPR_463A214A, + 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_COMMENT_ID: process.env.GH_AW_GITHUB_EVENT_COMMENT_ID, - GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: process.env.GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER, - GH_AW_GITHUB_EVENT_ISSUE_NUMBER: process.env.GH_AW_GITHUB_EVENT_ISSUE_NUMBER, - GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: process.env.GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER, 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_RUN_NUMBER: process.env.GH_AW_GITHUB_RUN_NUMBER, @@ -396,6 +394,7 @@ jobs: agentic_engine_timeout: ${{ steps.detect-copilot-errors.outputs.agentic_engine_timeout || 'false' }} checkout_pr_success: ${{ steps.checkout-pr.outputs.checkout_pr_success || 'true' }} effective_tokens: ${{ steps.parse-mcp-gateway.outputs.effective_tokens }} + effective_tokens_rate_limit_error: ${{ steps.parse-mcp-gateway.outputs.effective_tokens_rate_limit_error || 'false' }} has_patch: ${{ steps.collect_output.outputs.has_patch }} inference_access_error: ${{ steps.detect-copilot-errors.outputs.inference_access_error || 'false' }} mcp_policy_error: ${{ steps.detect-copilot-errors.outputs.mcp_policy_error || 'false' }} @@ -403,19 +402,29 @@ jobs: model_not_supported_error: ${{ steps.detect-copilot-errors.outputs.model_not_supported_error || 'false' }} output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} + setup-parent-span-id: ${{ steps.setup.outputs.parent-span-id || steps.setup.outputs.span-id }} + setup-span-id: ${{ steps.setup.outputs.span-id }} setup-trace-id: ${{ steps.setup.outputs.trace-id }} steps: + - name: Checkout actions folder + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + repository: github/gh-aw + sparse-checkout: | + actions + persist-credentials: false - name: Setup Scripts id: setup - uses: github/gh-aw-actions/setup@v0.72.1 + uses: ./actions/setup with: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} trace-id: ${{ needs.activation.outputs.setup-trace-id }} + parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }} env: GH_AW_SETUP_WORKFLOW_NAME: "Linter Miner" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/linter-miner.lock.yml@${{ github.ref }} - GH_AW_INFO_VERSION: "1.0.40" + GH_AW_INFO_VERSION: "1.0.43" - name: Set runtime paths id: set-runtime-paths run: | @@ -479,14 +488,14 @@ jobs: const { main } = require('${{ runner.temp }}/gh-aw/actions/checkout_pr_branch.cjs'); await main(); - name: Install GitHub Copilot CLI - run: bash "${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh" 1.0.40 + run: bash "${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh" 1.0.43 env: GH_HOST: github.com - name: Install AWF binary - run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.25.41 + run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.25.46 - name: Determine automatic lockdown mode for GitHub MCP Server id: determine-automatic-lockdown - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 (source v9) env: GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} @@ -511,7 +520,7 @@ jobs: GH_AW_SUB_AGENT_EXT: ".agent.md" run: bash "${RUNNER_TEMP}/gh-aw/actions/restore_inline_sub_agents.sh" - name: Download container images - run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.25.41@sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770 ghcr.io/github/gh-aw-firewall/api-proxy:0.25.41@sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0 ghcr.io/github/gh-aw-firewall/cli-proxy:0.25.41@sha256:62171f2fa508667b8b0a9e096f826983f312e3da0ce894f80c0f83a875af60fe ghcr.io/github/gh-aw-firewall/squid:0.25.41@sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4 ghcr.io/github/gh-aw-mcpg:v0.3.6@sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959 ghcr.io/github/serena-mcp-server:latest@sha256:bf343399e3725c45528f531a230f3a04521d4cdef29f9a5af6282ff0d3c393c5 node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f + run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.25.46 ghcr.io/github/gh-aw-firewall/api-proxy:0.25.46 ghcr.io/github/gh-aw-firewall/cli-proxy:0.25.46 ghcr.io/github/gh-aw-firewall/squid:0.25.46 ghcr.io/github/gh-aw-mcpg:v0.3.9@sha256:64828b42a4482f58fab16509d7f8f495a6d97c972a98a68aff20543531ac0388 ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959 ghcr.io/github/serena-mcp-server:latest@sha256:bf343399e3725c45528f531a230f3a04521d4cdef29f9a5af6282ff0d3c393c5 node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f - name: Generate Safe Outputs Config run: | mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs" @@ -718,11 +727,16 @@ jobs: export GH_AW_ENGINE="copilot" export GH_AW_MCP_CLI_SERVERS='["safeoutputs","serena"]' - echo 'GH_AW_MCP_CLI_SERVERS=["safeoutputs","serena"]' >> "$GITHUB_ENV" + echo GH_AW_MCP_CLI_SERVERS='["safeoutputs","serena"]' >> "$GITHUB_ENV" MCP_GATEWAY_UID=$(id -u 2>/dev/null || echo '0') MCP_GATEWAY_GID=$(id -g 2>/dev/null || echo '0') - DOCKER_SOCK_GID=$(stat -c '%g' /var/run/docker.sock 2>/dev/null || echo '0') - export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host --add-host host.docker.internal:127.0.0.1 --user '"${MCP_GATEWAY_UID}"':'"${MCP_GATEWAY_GID}"' --group-add '"${DOCKER_SOCK_GID}"' -v /var/run/docker.sock:/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_API_KEY -e MCP_GATEWAY_PAYLOAD_DIR -e MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -e DEBUG -e MCP_GATEWAY_LOG_DIR -e GH_AW_MCP_LOG_DIR -e GH_AW_SAFE_OUTPUTS -e GH_AW_SAFE_OUTPUTS_CONFIG_PATH -e GH_AW_SAFE_OUTPUTS_TOOLS_PATH -e GH_AW_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_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 GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -e GITHUB_AW_OTEL_TRACE_ID -e GITHUB_AW_OTEL_PARENT_SPAN_ID -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.3.6' + case "${DOCKER_HOST:-}" in + unix://* ) DOCKER_SOCK_PATH="${DOCKER_HOST#unix://}" ;; + /* ) DOCKER_SOCK_PATH="$DOCKER_HOST" ;; + * ) DOCKER_SOCK_PATH=/var/run/docker.sock ;; + esac + DOCKER_SOCK_GID=$(stat -c '%g' "$DOCKER_SOCK_PATH" 2>/dev/null || echo '0') + export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host --add-host host.docker.internal:127.0.0.1 --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_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 GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -e GITHUB_AW_OTEL_TRACE_ID -e GITHUB_AW_OTEL_PARENT_SPAN_ID -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.3.9' mkdir -p /home/runner/.copilot GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node) @@ -813,7 +827,7 @@ jobs: GH_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GITHUB_SERVER_URL: ${{ github.server_url }} CLI_PROXY_POLICY: '{"allow-only":{"repos":"all","min-integrity":"none"}}' - CLI_PROXY_IMAGE: 'ghcr.io/github/gh-aw-mcpg:v0.3.6' + CLI_PROXY_IMAGE: 'ghcr.io/github/gh-aw-mcpg:v0.3.9' run: | bash "${RUNNER_TEMP}/gh-aw/actions/start_cli_proxy.sh" - name: Execute GitHub Copilot CLI @@ -831,6 +845,7 @@ jobs: # --allow-tool shell(echo) # --allow-tool shell(find pkg/linters -type d) # --allow-tool shell(find pkg/linters -type f -name *.go) + # --allow-tool shell(gh:*) # --allow-tool shell(git add:*) # --allow-tool shell(git branch:*) # --allow-tool shell(git checkout:*) @@ -843,6 +858,7 @@ jobs: # --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(serena:*) @@ -855,14 +871,19 @@ jobs: timeout-minutes: 45 run: | set -o pipefail + printf '%s' "$(date +%s%3N)" > /tmp/gh-aw/agent_cli_start_ms.txt touch /tmp/gh-aw/agent-step-summary.md GH_AW_NODE_BIN=$(command -v node 2>/dev/null || true) export GH_AW_NODE_BIN (umask 177 && touch /tmp/gh-aw/agent-stdio.log) - printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.25.41/awf-config.schema.json","network":{"allowDomains":["api.business.githubcopilot.com","api.enterprise.githubcopilot.com","api.github.com","api.githubcopilot.com","api.individual.githubcopilot.com","api.snapcraft.io","archive.ubuntu.com","azure.archive.ubuntu.com","crl.geotrust.com","crl.globalsign.com","crl.identrust.com","crl.sectigo.com","crl.thawte.com","crl.usertrust.com","crl.verisign.com","crl3.digicert.com","crl4.digicert.com","crls.ssl.com","github.com","host.docker.internal","json-schema.org","json.schemastore.org","keyserver.ubuntu.com","ocsp.digicert.com","ocsp.geotrust.com","ocsp.globalsign.com","ocsp.identrust.com","ocsp.sectigo.com","ocsp.ssl.com","ocsp.thawte.com","ocsp.usertrust.com","ocsp.verisign.com","packagecloud.io","packages.cloud.google.com","packages.microsoft.com","ppa.launchpad.net","raw.githubusercontent.com","registry.npmjs.org","s.symcb.com","s.symcd.com","security.ubuntu.com","telemetry.enterprise.githubcopilot.com","ts-crl.ws.symantec.com","ts-ocsp.ws.symantec.com","www.googleapis.com"]},"apiProxy":{"enabled":true,"models":{"auto":["large"],"deep-research":["copilot/deep-research*","copilot/o3-deep-research*","copilot/o4-mini-deep-research*","google/deep-research*","openai/o3-deep-research*","openai/o4-mini-deep-research*"],"gemini-flash":["copilot/gemini-*flash*","google/gemini-*flash*"],"gemini-pro":["copilot/gemini-*pro*","google/gemini-*pro*"],"gpt-4.1":["copilot/gpt-4.1*","openai/gpt-4.1*"],"gpt-5":["copilot/gpt-5*","openai/gpt-5*"],"gpt-5-codex":["copilot/gpt-5*codex*","openai/gpt-5*codex*"],"gpt-5-mini":["copilot/gpt-5*mini*","openai/gpt-5*mini*"],"gpt-5-nano":["copilot/gpt-5*nano*","openai/gpt-5*nano*"],"gpt-5-pro":["copilot/gpt-5*pro*","openai/gpt-5*pro*"],"haiku":["copilot/*haiku*","anthropic/*haiku*"],"large":["sonnet","gpt-5-pro","gpt-5","gemini-pro"],"mini":["haiku","gpt-5-mini","gpt-5-nano","gemini-flash"],"opus":["copilot/*opus*","anthropic/*opus*"],"reasoning":["copilot/o1*","copilot/o3*","copilot/o4*","openai/o1*","openai/o3*","openai/o4*"],"small":["mini"],"sonnet":["copilot/*sonnet*","anthropic/*sonnet*"]}},"container":{"imageTag":"0.25.41,squid=sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4,agent=sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770,api-proxy=sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0,cli-proxy=sha256:62171f2fa508667b8b0a9e096f826983f312e3da0ce894f80c0f83a875af60fe"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json" && cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json + printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.25.46/awf-config.schema.json","network":{"allowDomains":["api.business.githubcopilot.com","api.enterprise.githubcopilot.com","api.github.com","api.githubcopilot.com","api.individual.githubcopilot.com","api.snapcraft.io","archive.ubuntu.com","azure.archive.ubuntu.com","crl.geotrust.com","crl.globalsign.com","crl.identrust.com","crl.sectigo.com","crl.thawte.com","crl.usertrust.com","crl.verisign.com","crl3.digicert.com","crl4.digicert.com","crls.ssl.com","github.com","host.docker.internal","json-schema.org","json.schemastore.org","keyserver.ubuntu.com","ocsp.digicert.com","ocsp.geotrust.com","ocsp.globalsign.com","ocsp.identrust.com","ocsp.sectigo.com","ocsp.ssl.com","ocsp.thawte.com","ocsp.usertrust.com","ocsp.verisign.com","packagecloud.io","packages.cloud.google.com","packages.microsoft.com","ppa.launchpad.net","raw.githubusercontent.com","registry.npmjs.org","s.symcb.com","s.symcd.com","security.ubuntu.com","telemetry.enterprise.githubcopilot.com","ts-crl.ws.symantec.com","ts-ocsp.ws.symantec.com","www.googleapis.com"]},"apiProxy":{"enabled":true,"enableTokenSteering":true,"maxRuns":500,"maxEffectiveTokens":25000000,"models":{"auto":["large"],"deep-research":["copilot/deep-research*","copilot/o3-deep-research*","copilot/o4-mini-deep-research*","google/deep-research*","gemini/deep-research*","openai/o3-deep-research*","openai/o4-mini-deep-research*"],"gemini-flash":["copilot/gemini-*flash*","google/gemini-*flash*","gemini/gemini-*flash*"],"gemini-flash-lite":["copilot/gemini-*flash*lite*","google/gemini-*flash*lite*","gemini/gemini-*flash*lite*"],"gemini-pro":["copilot/gemini-*pro*","google/gemini-*pro*","gemini/gemini-*pro*"],"gemma":["copilot/gemma*","google/gemma*","gemini/gemma*"],"gpt-4.1":["copilot/gpt-4.1*","openai/gpt-4.1*"],"gpt-5":["copilot/gpt-5*","openai/gpt-5*"],"gpt-5-codex":["copilot/gpt-5*codex*","openai/gpt-5*codex*"],"gpt-5-mini":["copilot/gpt-5*mini*","openai/gpt-5*mini*"],"gpt-5-nano":["copilot/gpt-5*nano*","openai/gpt-5*nano*"],"gpt-5-pro":["copilot/gpt-5*pro*","openai/gpt-5*pro*"],"haiku":["copilot/*haiku*","anthropic/*haiku*"],"large":["sonnet","gpt-5-pro","gpt-5","gemini-pro"],"mini":["haiku","gpt-5-mini","gpt-5-nano","gemini-flash-lite"],"opus":["copilot/*opus*","anthropic/*opus*"],"reasoning":["copilot/o1*","copilot/o3*","copilot/o4*","openai/o1*","openai/o3*","openai/o4*"],"small":["mini"],"sonnet":["copilot/*sonnet*","anthropic/*sonnet*"]}},"container":{"imageTag":"0.25.46"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json" && cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json + GH_AW_DOCKER_HOST_PATH_PREFIX_ARGS="" + if [[ "${DOCKER_HOST:-}" =~ ^tcp:// ]]; then + GH_AW_DOCKER_HOST_PATH_PREFIX_ARGS="--docker-host-path-prefix /tmp/gh-aw" + fi # shellcheck disable=SC1003 - sudo -E 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" --env-all --exclude-env COPILOT_GITHUB_TOKEN --exclude-env GH_TOKEN --exclude-env GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_API_KEY --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --allow-host-ports 80,443,8080 --skip-pull --difc-proxy-host host.docker.internal:18443 --difc-proxy-ca-cert /tmp/gh-aw/difc-proxy-tls/ca.crt \ - -- /bin/bash -c 'export PATH="${RUNNER_TEMP}/gh-aw/mcp-cli/bin:$PATH" && export PATH="$(find /opt/hostedtoolcache /home/runner/work/_tool -maxdepth 4 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/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 || echo node)"; 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 serena --allow-tool '\''shell(cat .github/skills/go-linters/SKILL.md)'\'' --allow-tool '\''shell(cat cmd/linters/main.go)'\'' --allow-tool '\''shell(cat pkg/linters/**/*.go)'\'' --allow-tool '\''shell(cat pkg/linters/largefunc/largefunc.go)'\'' --allow-tool '\''shell(cat)'\'' --allow-tool '\''shell(date)'\'' --allow-tool '\''shell(echo)'\'' --allow-tool '\''shell(find pkg/linters -type d)'\'' --allow-tool '\''shell(find pkg/linters -type f -name *.go)'\'' --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(grep -r * pkg/linters --include=*.go)'\'' --allow-tool '\''shell(grep)'\'' --allow-tool '\''shell(head)'\'' --allow-tool '\''shell(ls)'\'' --allow-tool '\''shell(pwd)'\'' --allow-tool '\''shell(safeoutputs:*)'\'' --allow-tool '\''shell(serena:*)'\'' --allow-tool '\''shell(sort)'\'' --allow-tool '\''shell(tail)'\'' --allow-tool '\''shell(uniq)'\'' --allow-tool '\''shell(wc)'\'' --allow-tool '\''shell(yq)'\'' --allow-tool write --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 + sudo -E 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_DOCKER_HOST_PATH_PREFIX_ARGS} --env-all --exclude-env COPILOT_GITHUB_TOKEN --exclude-env GH_TOKEN --exclude-env GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_API_KEY --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --allow-host-ports 80,443,8080 --skip-pull --difc-proxy-host host.docker.internal:18443 --difc-proxy-ca-cert /tmp/gh-aw/difc-proxy-tls/ca.crt \ + -- /bin/bash -c 'export PATH="${RUNNER_TEMP}/gh-aw/mcp-cli/bin:$PATH" && export PATH="$(find /opt/hostedtoolcache /home/runner/work/_tool -maxdepth 5 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/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_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 serena --allow-tool '\''shell(cat .github/skills/go-linters/SKILL.md)'\'' --allow-tool '\''shell(cat cmd/linters/main.go)'\'' --allow-tool '\''shell(cat pkg/linters/**/*.go)'\'' --allow-tool '\''shell(cat pkg/linters/largefunc/largefunc.go)'\'' --allow-tool '\''shell(cat)'\'' --allow-tool '\''shell(date)'\'' --allow-tool '\''shell(echo)'\'' --allow-tool '\''shell(find pkg/linters -type d)'\'' --allow-tool '\''shell(find pkg/linters -type f -name *.go)'\'' --allow-tool '\''shell(gh:*)'\'' --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(grep -r * pkg/linters --include=*.go)'\'' --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(serena:*)'\'' --allow-tool '\''shell(sort)'\'' --allow-tool '\''shell(tail)'\'' --allow-tool '\''shell(uniq)'\'' --allow-tool '\''shell(wc)'\'' --allow-tool '\''shell(yq)'\'' --allow-tool write --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 @@ -873,7 +894,7 @@ jobs: GH_AW_PHASE: agent 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_VERSION: v0.72.1 + GH_AW_VERSION: dev GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }} GITHUB_API_URL: ${{ github.api_url }} GITHUB_AW: true @@ -1092,23 +1113,32 @@ jobs: concurrency: group: "gh-aw-conclusion-linter-miner" cancel-in-progress: false + queue: max outputs: incomplete_count: ${{ steps.report_incomplete.outputs.incomplete_count }} noop_message: ${{ steps.noop.outputs.noop_message }} tools_reported: ${{ steps.missing_tool.outputs.tools_reported }} total_count: ${{ steps.missing_tool.outputs.total_count }} steps: + - name: Checkout actions folder + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + repository: github/gh-aw + sparse-checkout: | + actions + persist-credentials: false - name: Setup Scripts id: setup - uses: github/gh-aw-actions/setup@v0.72.1 + uses: ./actions/setup with: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} trace-id: ${{ needs.activation.outputs.setup-trace-id }} + parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }} env: GH_AW_SETUP_WORKFLOW_NAME: "Linter Miner" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/linter-miner.lock.yml@${{ github.ref }} - GH_AW_INFO_VERSION: "1.0.40" + GH_AW_INFO_VERSION: "1.0.43" - name: Download agent output artifact id: download-agent-output continue-on-error: true @@ -1202,6 +1232,8 @@ jobs: GH_AW_ACTION_FAILURE_ISSUE_EXPIRES_HOURS: "12" GH_AW_ENGINE_ID: "copilot" GH_AW_CHECKOUT_PR_SUCCESS: ${{ needs.agent.outputs.checkout_pr_success }} + GH_AW_EFFECTIVE_TOKENS: ${{ needs.agent.outputs.effective_tokens || '' }} + GH_AW_EFFECTIVE_TOKENS_RATE_LIMIT_ERROR: ${{ needs.agent.outputs.effective_tokens_rate_limit_error || 'false' }} GH_AW_INFERENCE_ACCESS_ERROR: ${{ needs.agent.outputs.inference_access_error }} GH_AW_MCP_POLICY_ERROR: ${{ needs.agent.outputs.mcp_policy_error }} GH_AW_AGENTIC_ENGINE_TIMEOUT: ${{ needs.agent.outputs.agentic_engine_timeout }} @@ -1216,6 +1248,7 @@ jobs: GH_AW_MISSING_TOOL_REPORT_AS_FAILURE: "true" GH_AW_MISSING_DATA_REPORT_AS_FAILURE: "true" GH_AW_TIMEOUT_MINUTES: "45" + GH_AW_MAX_EFFECTIVE_TOKENS: "25000000" GH_AW_CACHE_MEMORY_ENABLED: "true" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} @@ -1240,17 +1273,25 @@ jobs: detection_reason: ${{ steps.detection_conclusion.outputs.reason }} detection_success: ${{ steps.detection_conclusion.outputs.success }} steps: + - name: Checkout actions folder + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + repository: github/gh-aw + sparse-checkout: | + actions + persist-credentials: false - name: Setup Scripts id: setup - uses: github/gh-aw-actions/setup@v0.72.1 + uses: ./actions/setup with: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} trace-id: ${{ needs.activation.outputs.setup-trace-id }} + parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }} env: GH_AW_SETUP_WORKFLOW_NAME: "Linter Miner" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/linter-miner.lock.yml@${{ github.ref }} - GH_AW_INFO_VERSION: "1.0.40" + GH_AW_INFO_VERSION: "1.0.43" - name: Download agent output artifact id: download-agent-output continue-on-error: true @@ -1276,7 +1317,7 @@ jobs: rm -rf /tmp/gh-aw/sandbox/firewall/logs rm -rf /tmp/gh-aw/sandbox/firewall/audit - name: Download container images - run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.25.41@sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770 ghcr.io/github/gh-aw-firewall/api-proxy:0.25.41@sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0 ghcr.io/github/gh-aw-firewall/squid:0.25.41@sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4 + run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.25.46 ghcr.io/github/gh-aw-firewall/api-proxy:0.25.46 ghcr.io/github/gh-aw-firewall/squid:0.25.46 - name: Check if detection needed id: detection_guard if: always() @@ -1335,11 +1376,11 @@ jobs: node-version: '24' package-manager-cache: false - name: Install GitHub Copilot CLI - run: bash "${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh" 1.0.40 + run: bash "${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh" 1.0.43 env: GH_HOST: github.com - name: Install AWF binary - run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.25.41 + run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.25.46 - name: Execute GitHub Copilot CLI if: always() && steps.detection_guard.outputs.run_detection == 'true' continue-on-error: true @@ -1348,14 +1389,19 @@ jobs: timeout-minutes: 20 run: | set -o pipefail + printf '%s' "$(date +%s%3N)" > /tmp/gh-aw/agent_cli_start_ms.txt touch /tmp/gh-aw/agent-step-summary.md GH_AW_NODE_BIN=$(command -v node 2>/dev/null || true) export GH_AW_NODE_BIN (umask 177 && touch /tmp/gh-aw/threat-detection/detection.log) - printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.25.41/awf-config.schema.json","network":{"allowDomains":["api.business.githubcopilot.com","api.enterprise.githubcopilot.com","api.github.com","api.githubcopilot.com","api.individual.githubcopilot.com","github.com","host.docker.internal","telemetry.enterprise.githubcopilot.com"]},"apiProxy":{"enabled":true},"container":{"imageTag":"0.25.41"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json" && cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json + printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.25.46/awf-config.schema.json","network":{"allowDomains":["api.business.githubcopilot.com","api.enterprise.githubcopilot.com","api.github.com","api.githubcopilot.com","api.individual.githubcopilot.com","github.com","host.docker.internal","telemetry.enterprise.githubcopilot.com"]},"apiProxy":{"enabled":true,"enableTokenSteering":true,"maxRuns":500,"maxEffectiveTokens":25000000},"container":{"imageTag":"0.25.46"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json" && cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json + GH_AW_DOCKER_HOST_PATH_PREFIX_ARGS="" + if [[ "${DOCKER_HOST:-}" =~ ^tcp:// ]]; then + GH_AW_DOCKER_HOST_PATH_PREFIX_ARGS="--docker-host-path-prefix /tmp/gh-aw" + fi # shellcheck disable=SC1003 - sudo -E 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" --env-all --exclude-env COPILOT_GITHUB_TOKEN --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --allow-host-ports 80,443,8080 --skip-pull \ - -- /bin/bash -c 'export PATH="$(find /opt/hostedtoolcache /home/runner/work/_tool -maxdepth 4 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/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 || echo node)"; 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 + sudo -E 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_DOCKER_HOST_PATH_PREFIX_ARGS} --env-all --exclude-env COPILOT_GITHUB_TOKEN --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --allow-host-ports 80,443,8080 --skip-pull \ + -- /bin/bash -c 'export PATH="$(find /opt/hostedtoolcache /home/runner/work/_tool -maxdepth 5 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/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_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 env: AWF_REFLECT_ENABLED: 1 COPILOT_AGENT_RUNNER_TYPE: STANDALONE @@ -1364,7 +1410,7 @@ jobs: COPILOT_MODEL: ${{ vars.GH_AW_MODEL_DETECTION_COPILOT || 'claude-sonnet-4.6' }} GH_AW_PHASE: detection GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - GH_AW_VERSION: v0.72.1 + GH_AW_VERSION: dev GITHUB_API_URL: ${{ github.api_url }} GITHUB_AW: true GITHUB_COPILOT_INTEGRATION_ID: agentic-workflows @@ -1393,6 +1439,7 @@ jobs: uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: RUN_DETECTION: ${{ steps.detection_guard.outputs.run_detection }} + DETECTION_AGENTIC_EXECUTION_OUTCOME: ${{ steps.detection_agentic_execution.outcome }} GH_AW_DETECTION_CONTINUE_ON_ERROR: "true" with: script: | @@ -1403,10 +1450,11 @@ jobs: await main(); } catch (loadErr) { const continueOnError = process.env.GH_AW_DETECTION_CONTINUE_ON_ERROR !== 'false'; + const detectionExecutionFailed = process.env.DETECTION_AGENTIC_EXECUTION_OUTCOME === 'failure'; const msg = 'ERR_SYSTEM: \u274C Unexpected error loading threat detection module: ' + (loadErr && loadErr.message ? loadErr.message : String(loadErr)); core.error(msg); core.setOutput('reason', 'parse_error'); - if (continueOnError) { + if (continueOnError && !detectionExecutionFailed) { core.warning('\u26A0\uFE0F ' + msg); core.setOutput('conclusion', 'warning'); core.setOutput('success', 'false'); @@ -1436,7 +1484,7 @@ jobs: GH_AW_EFFECTIVE_TOKENS: ${{ needs.agent.outputs.effective_tokens }} GH_AW_ENGINE_ID: "copilot" GH_AW_ENGINE_MODEL: ${{ needs.agent.outputs.model }} - GH_AW_ENGINE_VERSION: "1.0.40" + GH_AW_ENGINE_VERSION: "1.0.43" GH_AW_TRACKER_ID: "linter-miner" GH_AW_WORKFLOW_ID: "linter-miner" GH_AW_WORKFLOW_NAME: "Linter Miner" @@ -1450,17 +1498,25 @@ jobs: process_safe_outputs_processed_count: ${{ steps.process_safe_outputs.outputs.processed_count }} process_safe_outputs_temporary_id_map: ${{ steps.process_safe_outputs.outputs.temporary_id_map }} steps: + - name: Checkout actions folder + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + repository: github/gh-aw + sparse-checkout: | + actions + persist-credentials: false - name: Setup Scripts id: setup - uses: github/gh-aw-actions/setup@v0.72.1 + uses: ./actions/setup with: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} trace-id: ${{ needs.activation.outputs.setup-trace-id }} + parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }} env: GH_AW_SETUP_WORKFLOW_NAME: "Linter Miner" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/linter-miner.lock.yml@${{ github.ref }} - GH_AW_INFO_VERSION: "1.0.40" + GH_AW_INFO_VERSION: "1.0.43" - name: Mask OTLP telemetry headers run: bash "${RUNNER_TEMP}/gh-aw/actions/mask_otlp_headers.sh" - name: Download agent output artifact @@ -1563,6 +1619,15 @@ jobs: /tmp/gh-aw/safe-output-items.jsonl /tmp/gh-aw/temporary-id-map.json if-no-files-found: ignore + - name: Restore actions folder + if: always() + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + repository: github/gh-aw + sparse-checkout: | + actions/setup + sparse-checkout-cone-mode: true + persist-credentials: false update_cache_memory: needs: @@ -1573,21 +1638,30 @@ jobs: always() && (needs.detection.result == 'success' || needs.detection.result == 'skipped') && needs.agent.result == 'success' runs-on: ubuntu-slim - permissions: {} + permissions: + contents: read env: GH_AW_WORKFLOW_ID_SANITIZED: linterminer steps: + - name: Checkout actions folder + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + repository: github/gh-aw + sparse-checkout: | + actions + persist-credentials: false - name: Setup Scripts id: setup - uses: github/gh-aw-actions/setup@v0.72.1 + uses: ./actions/setup with: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} trace-id: ${{ needs.activation.outputs.setup-trace-id }} + parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }} env: GH_AW_SETUP_WORKFLOW_NAME: "Linter Miner" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/linter-miner.lock.yml@${{ github.ref }} - GH_AW_INFO_VERSION: "1.0.40" + GH_AW_INFO_VERSION: "1.0.43" - name: Download cache-memory artifact (default) id: download_cache_default uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 From 056d58c3c4065455c7a008cda05efadcb872ee71 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 15 May 2026 04:46:59 +0000 Subject: [PATCH 04/22] Restore linter miner lockfile Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .github/workflows/linter-miner.lock.yml | 240 ++++++++---------------- 1 file changed, 83 insertions(+), 157 deletions(-) diff --git a/.github/workflows/linter-miner.lock.yml b/.github/workflows/linter-miner.lock.yml index f06725d2736..cd7ce15a6e8 100644 --- a/.github/workflows/linter-miner.lock.yml +++ b/.github/workflows/linter-miner.lock.yml @@ -1,5 +1,5 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"efd1dc86fd08ae68de1ce40a9b2d5c7bf6481734599a94e6bf4b1f9de27769ee","strict":true,"agent_id":"copilot"} -# gh-aw-manifest: {"version":1,"secrets":["GH_AW_CI_TRIGGER_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_GRAFANA_ENDPOINT","GH_AW_OTEL_GRAFANA_HEADERS","GH_AW_OTEL_SENTRY_ENDPOINT","GH_AW_OTEL_SENTRY_HEADERS","GITHUB_TOKEN"],"actions":[{"repo":"actions/cache/restore","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/cache/save","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"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":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.46"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.46"},{"image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.25.46"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.46"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.9","digest":"sha256:64828b42a4482f58fab16509d7f8f495a6d97c972a98a68aff20543531ac0388","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.9@sha256:64828b42a4482f58fab16509d7f8f495a6d97c972a98a68aff20543531ac0388"},{"image":"ghcr.io/github/github-mcp-server:v1.0.3","digest":"sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959","pinned_image":"ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959"},{"image":"ghcr.io/github/serena-mcp-server:latest","digest":"sha256:bf343399e3725c45528f531a230f3a04521d4cdef29f9a5af6282ff0d3c393c5","pinned_image":"ghcr.io/github/serena-mcp-server:latest@sha256:bf343399e3725c45528f531a230f3a04521d4cdef29f9a5af6282ff0d3c393c5"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"efd1dc86fd08ae68de1ce40a9b2d5c7bf6481734599a94e6bf4b1f9de27769ee","compiler_version":"v0.72.1","strict":true,"agent_id":"copilot"} +# gh-aw-manifest: {"version":1,"secrets":["GH_AW_CI_TRIGGER_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_GRAFANA_ENDPOINT","GH_AW_OTEL_GRAFANA_HEADERS","GH_AW_OTEL_SENTRY_ENDPOINT","GH_AW_OTEL_SENTRY_HEADERS","GITHUB_TOKEN"],"actions":[{"repo":"actions/cache/restore","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/cache/save","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"v0.72.1","version":"v0.72.1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.41","digest":"sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.25.41@sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.41","digest":"sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.41@sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0"},{"image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.25.41","digest":"sha256:62171f2fa508667b8b0a9e096f826983f312e3da0ce894f80c0f83a875af60fe","pinned_image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.25.41@sha256:62171f2fa508667b8b0a9e096f826983f312e3da0ce894f80c0f83a875af60fe"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.41","digest":"sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.25.41@sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.6","digest":"sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.6@sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c"},{"image":"ghcr.io/github/github-mcp-server:v1.0.3","digest":"sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959","pinned_image":"ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959"},{"image":"ghcr.io/github/serena-mcp-server:latest","digest":"sha256:bf343399e3725c45528f531a230f3a04521d4cdef29f9a5af6282ff0d3c393c5","pinned_image":"ghcr.io/github/serena-mcp-server:latest@sha256:bf343399e3725c45528f531a230f3a04521d4cdef29f9a5af6282ff0d3c393c5"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]} # ___ _ _ # / _ \ | | (_) # | |_| | __ _ ___ _ __ | |_ _ ___ @@ -14,7 +14,7 @@ # \ /\ / (_) | | | | ( | | | | (_) \ V V /\__ \ # \/ \/ \___/|_| |_|\_\|_| |_|\___/ \_/\_/ |___/ # -# This file was automatically generated by gh-aw. DO NOT EDIT. +# This file was automatically generated by gh-aw (v0.72.1). DO NOT EDIT. # # To update this file, edit the corresponding .md file and run: # gh aw compile @@ -45,17 +45,18 @@ # - actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 # - actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 # - actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 +# - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 # - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 -# - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 (source v9) # - actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 # - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 +# - github/gh-aw-actions/setup@v0.72.1 # # Container images used: -# - ghcr.io/github/gh-aw-firewall/agent:0.25.46 -# - ghcr.io/github/gh-aw-firewall/api-proxy:0.25.46 -# - ghcr.io/github/gh-aw-firewall/cli-proxy:0.25.46 -# - ghcr.io/github/gh-aw-firewall/squid:0.25.46 -# - ghcr.io/github/gh-aw-mcpg:v0.3.9@sha256:64828b42a4482f58fab16509d7f8f495a6d97c972a98a68aff20543531ac0388 +# - ghcr.io/github/gh-aw-firewall/agent:0.25.41@sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770 +# - ghcr.io/github/gh-aw-firewall/api-proxy:0.25.41@sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0 +# - ghcr.io/github/gh-aw-firewall/cli-proxy:0.25.41@sha256:62171f2fa508667b8b0a9e096f826983f312e3da0ce894f80c0f83a875af60fe +# - ghcr.io/github/gh-aw-firewall/squid:0.25.41@sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4 +# - ghcr.io/github/gh-aw-mcpg:v0.3.6@sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c # - ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959 # - ghcr.io/github/serena-mcp-server:latest@sha256:bf343399e3725c45528f531a230f3a04521d4cdef29f9a5af6282ff0d3c393c5 # - node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f @@ -63,7 +64,7 @@ name: "Linter Miner" "on": schedule: - - cron: "21 17 * * *" + - cron: "19 8 * * *" # Friendly format: daily (scattered) workflow_dispatch: inputs: @@ -100,28 +101,19 @@ jobs: engine_id: ${{ steps.generate_aw_info.outputs.engine_id }} lockdown_check_failed: ${{ steps.generate_aw_info.outputs.lockdown_check_failed == 'true' }} model: ${{ steps.generate_aw_info.outputs.model }} - setup-parent-span-id: ${{ steps.setup.outputs.parent-span-id || steps.setup.outputs.span-id }} - setup-span-id: ${{ steps.setup.outputs.span-id }} setup-trace-id: ${{ steps.setup.outputs.trace-id }} stale_lock_file_failed: ${{ steps.check-lock-file.outputs.stale_lock_file_failed == 'true' }} steps: - - name: Checkout actions folder - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - repository: github/gh-aw - sparse-checkout: | - actions - persist-credentials: false - name: Setup Scripts id: setup - uses: ./actions/setup + uses: github/gh-aw-actions/setup@v0.72.1 with: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} env: GH_AW_SETUP_WORKFLOW_NAME: "Linter Miner" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/linter-miner.lock.yml@${{ github.ref }} - GH_AW_INFO_VERSION: "1.0.43" + GH_AW_INFO_VERSION: "1.0.40" - name: Mask OTLP telemetry headers run: bash "${RUNNER_TEMP}/gh-aw/actions/mask_otlp_headers.sh" - name: Generate agentic run info @@ -130,15 +122,16 @@ 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 || 'claude-sonnet-4.6' }} - GH_AW_INFO_VERSION: "1.0.43" - GH_AW_INFO_AGENT_VERSION: "1.0.43" + GH_AW_INFO_VERSION: "1.0.40" + GH_AW_INFO_AGENT_VERSION: "1.0.40" + GH_AW_INFO_CLI_VERSION: "v0.72.1" GH_AW_INFO_WORKFLOW_NAME: "Linter Miner" GH_AW_INFO_EXPERIMENTAL: "false" GH_AW_INFO_SUPPORTS_TOOLS_ALLOWLIST: "true" GH_AW_INFO_STAGED: "false" GH_AW_INFO_ALLOWED_DOMAINS: '["defaults"]' GH_AW_INFO_FIREWALL_ENABLED: "true" - GH_AW_INFO_AWF_VERSION: "v0.25.46" + GH_AW_INFO_AWF_VERSION: "v0.25.41" GH_AW_INFO_AWMG_VERSION: "" GH_AW_INFO_FIREWALL_TYPE: "squid" GH_AW_COMPILED_STRICT: "true" @@ -156,7 +149,6 @@ jobs: sparse-checkout: | .github .agents - actions/setup .claude .codex .crush @@ -183,15 +175,25 @@ jobs: setupGlobals(core, github, context, exec, io, getOctokit); const { main } = require('${{ runner.temp }}/gh-aw/actions/check_workflow_timestamp_api.cjs'); await main(); + - name: Check compile-agentic version + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_COMPILED_VERSION: "v0.72.1" + 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/check_version_updates.cjs'); + await main(); - name: Create prompt with built-in context env: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ runner.temp }}/gh-aw/safeoutputs/outputs.jsonl - 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) }} - 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_COMMENT_ID: ${{ github.event.comment.id }} + GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} + GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} GH_AW_GITHUB_RUN_NUMBER: ${{ github.run_number }} @@ -220,28 +222,28 @@ jobs: cat << 'GH_AW_PROMPT_563dae7ad56cbf7e_EOF' The following GitHub context information is available for this workflow: - {{#if github.actor}} + {{#if __GH_AW_GITHUB_ACTOR__ }} - **actor**: __GH_AW_GITHUB_ACTOR__ {{/if}} - {{#if github.repository}} + {{#if __GH_AW_GITHUB_REPOSITORY__ }} - **repository**: __GH_AW_GITHUB_REPOSITORY__ {{/if}} - {{#if github.workspace}} + {{#if __GH_AW_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 __GH_AW_GITHUB_EVENT_ISSUE_NUMBER__ }} + - **issue-number**: #__GH_AW_GITHUB_EVENT_ISSUE_NUMBER__ {{/if}} - {{#if github.event.discussion.number || (github.aw.context.item_type == 'discussion' && github.aw.context.item_number)}} - - **discussion-number**: #__GH_AW_EXPR_1A3A194A__ + {{#if __GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__ }} + - **discussion-number**: #__GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__ {{/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 __GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__ }} + - **pull-request-number**: #__GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__ {{/if}} - {{#if github.event.comment.id || github.aw.context.comment_id}} - - **comment-id**: __GH_AW_EXPR_FF1D34CE__ + {{#if __GH_AW_GITHUB_EVENT_COMMENT_ID__ }} + - **comment-id**: __GH_AW_GITHUB_EVENT_COMMENT_ID__ {{/if}} - {{#if github.run_id}} + {{#if __GH_AW_GITHUB_RUN_ID__ }} - **workflow-run-id**: __GH_AW_GITHUB_RUN_ID__ {{/if}} @@ -308,11 +310,11 @@ jobs: GH_AW_ALLOWED_EXTENSIONS: '' GH_AW_CACHE_DESCRIPTION: '' GH_AW_CACHE_DIR: '/tmp/gh-aw/cache-memory/' - 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) }} - 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_COMMENT_ID: ${{ github.event.comment.id }} + GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} + GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} GH_AW_GITHUB_RUN_NUMBER: ${{ github.run_number }} @@ -332,11 +334,11 @@ jobs: GH_AW_ALLOWED_EXTENSIONS: process.env.GH_AW_ALLOWED_EXTENSIONS, GH_AW_CACHE_DESCRIPTION: process.env.GH_AW_CACHE_DESCRIPTION, GH_AW_CACHE_DIR: process.env.GH_AW_CACHE_DIR, - GH_AW_EXPR_1A3A194A: process.env.GH_AW_EXPR_1A3A194A, - GH_AW_EXPR_463A214A: process.env.GH_AW_EXPR_463A214A, - 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_COMMENT_ID: process.env.GH_AW_GITHUB_EVENT_COMMENT_ID, + GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: process.env.GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER, + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: process.env.GH_AW_GITHUB_EVENT_ISSUE_NUMBER, + GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: process.env.GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER, 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_RUN_NUMBER: process.env.GH_AW_GITHUB_RUN_NUMBER, @@ -394,7 +396,6 @@ jobs: agentic_engine_timeout: ${{ steps.detect-copilot-errors.outputs.agentic_engine_timeout || 'false' }} checkout_pr_success: ${{ steps.checkout-pr.outputs.checkout_pr_success || 'true' }} effective_tokens: ${{ steps.parse-mcp-gateway.outputs.effective_tokens }} - effective_tokens_rate_limit_error: ${{ steps.parse-mcp-gateway.outputs.effective_tokens_rate_limit_error || 'false' }} has_patch: ${{ steps.collect_output.outputs.has_patch }} inference_access_error: ${{ steps.detect-copilot-errors.outputs.inference_access_error || 'false' }} mcp_policy_error: ${{ steps.detect-copilot-errors.outputs.mcp_policy_error || 'false' }} @@ -402,29 +403,19 @@ jobs: model_not_supported_error: ${{ steps.detect-copilot-errors.outputs.model_not_supported_error || 'false' }} output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} - setup-parent-span-id: ${{ steps.setup.outputs.parent-span-id || steps.setup.outputs.span-id }} - setup-span-id: ${{ steps.setup.outputs.span-id }} setup-trace-id: ${{ steps.setup.outputs.trace-id }} steps: - - name: Checkout actions folder - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - repository: github/gh-aw - sparse-checkout: | - actions - persist-credentials: false - name: Setup Scripts id: setup - uses: ./actions/setup + uses: github/gh-aw-actions/setup@v0.72.1 with: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} trace-id: ${{ needs.activation.outputs.setup-trace-id }} - parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }} env: GH_AW_SETUP_WORKFLOW_NAME: "Linter Miner" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/linter-miner.lock.yml@${{ github.ref }} - GH_AW_INFO_VERSION: "1.0.43" + GH_AW_INFO_VERSION: "1.0.40" - name: Set runtime paths id: set-runtime-paths run: | @@ -488,14 +479,14 @@ jobs: const { main } = require('${{ runner.temp }}/gh-aw/actions/checkout_pr_branch.cjs'); await main(); - name: Install GitHub Copilot CLI - run: bash "${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh" 1.0.43 + run: bash "${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh" 1.0.40 env: GH_HOST: github.com - name: Install AWF binary - run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.25.46 + run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.25.41 - name: Determine automatic lockdown mode for GitHub MCP Server id: determine-automatic-lockdown - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 (source v9) + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 env: GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} @@ -520,7 +511,7 @@ jobs: GH_AW_SUB_AGENT_EXT: ".agent.md" run: bash "${RUNNER_TEMP}/gh-aw/actions/restore_inline_sub_agents.sh" - name: Download container images - run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.25.46 ghcr.io/github/gh-aw-firewall/api-proxy:0.25.46 ghcr.io/github/gh-aw-firewall/cli-proxy:0.25.46 ghcr.io/github/gh-aw-firewall/squid:0.25.46 ghcr.io/github/gh-aw-mcpg:v0.3.9@sha256:64828b42a4482f58fab16509d7f8f495a6d97c972a98a68aff20543531ac0388 ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959 ghcr.io/github/serena-mcp-server:latest@sha256:bf343399e3725c45528f531a230f3a04521d4cdef29f9a5af6282ff0d3c393c5 node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f + run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.25.41@sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770 ghcr.io/github/gh-aw-firewall/api-proxy:0.25.41@sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0 ghcr.io/github/gh-aw-firewall/cli-proxy:0.25.41@sha256:62171f2fa508667b8b0a9e096f826983f312e3da0ce894f80c0f83a875af60fe ghcr.io/github/gh-aw-firewall/squid:0.25.41@sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4 ghcr.io/github/gh-aw-mcpg:v0.3.6@sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959 ghcr.io/github/serena-mcp-server:latest@sha256:bf343399e3725c45528f531a230f3a04521d4cdef29f9a5af6282ff0d3c393c5 node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f - name: Generate Safe Outputs Config run: | mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs" @@ -727,16 +718,11 @@ jobs: export GH_AW_ENGINE="copilot" export GH_AW_MCP_CLI_SERVERS='["safeoutputs","serena"]' - echo GH_AW_MCP_CLI_SERVERS='["safeoutputs","serena"]' >> "$GITHUB_ENV" + echo 'GH_AW_MCP_CLI_SERVERS=["safeoutputs","serena"]' >> "$GITHUB_ENV" MCP_GATEWAY_UID=$(id -u 2>/dev/null || echo '0') MCP_GATEWAY_GID=$(id -g 2>/dev/null || echo '0') - case "${DOCKER_HOST:-}" in - unix://* ) DOCKER_SOCK_PATH="${DOCKER_HOST#unix://}" ;; - /* ) DOCKER_SOCK_PATH="$DOCKER_HOST" ;; - * ) DOCKER_SOCK_PATH=/var/run/docker.sock ;; - esac - DOCKER_SOCK_GID=$(stat -c '%g' "$DOCKER_SOCK_PATH" 2>/dev/null || echo '0') - export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host --add-host host.docker.internal:127.0.0.1 --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_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 GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -e GITHUB_AW_OTEL_TRACE_ID -e GITHUB_AW_OTEL_PARENT_SPAN_ID -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.3.9' + DOCKER_SOCK_GID=$(stat -c '%g' /var/run/docker.sock 2>/dev/null || echo '0') + export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host --add-host host.docker.internal:127.0.0.1 --user '"${MCP_GATEWAY_UID}"':'"${MCP_GATEWAY_GID}"' --group-add '"${DOCKER_SOCK_GID}"' -v /var/run/docker.sock:/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_API_KEY -e MCP_GATEWAY_PAYLOAD_DIR -e MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -e DEBUG -e MCP_GATEWAY_LOG_DIR -e GH_AW_MCP_LOG_DIR -e GH_AW_SAFE_OUTPUTS -e GH_AW_SAFE_OUTPUTS_CONFIG_PATH -e GH_AW_SAFE_OUTPUTS_TOOLS_PATH -e GH_AW_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_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 GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -e GITHUB_AW_OTEL_TRACE_ID -e GITHUB_AW_OTEL_PARENT_SPAN_ID -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.3.6' mkdir -p /home/runner/.copilot GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node) @@ -827,7 +813,7 @@ jobs: GH_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GITHUB_SERVER_URL: ${{ github.server_url }} CLI_PROXY_POLICY: '{"allow-only":{"repos":"all","min-integrity":"none"}}' - CLI_PROXY_IMAGE: 'ghcr.io/github/gh-aw-mcpg:v0.3.9' + CLI_PROXY_IMAGE: 'ghcr.io/github/gh-aw-mcpg:v0.3.6' run: | bash "${RUNNER_TEMP}/gh-aw/actions/start_cli_proxy.sh" - name: Execute GitHub Copilot CLI @@ -845,7 +831,6 @@ jobs: # --allow-tool shell(echo) # --allow-tool shell(find pkg/linters -type d) # --allow-tool shell(find pkg/linters -type f -name *.go) - # --allow-tool shell(gh:*) # --allow-tool shell(git add:*) # --allow-tool shell(git branch:*) # --allow-tool shell(git checkout:*) @@ -858,7 +843,6 @@ jobs: # --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(serena:*) @@ -871,19 +855,14 @@ jobs: timeout-minutes: 45 run: | set -o pipefail - printf '%s' "$(date +%s%3N)" > /tmp/gh-aw/agent_cli_start_ms.txt touch /tmp/gh-aw/agent-step-summary.md GH_AW_NODE_BIN=$(command -v node 2>/dev/null || true) export GH_AW_NODE_BIN (umask 177 && touch /tmp/gh-aw/agent-stdio.log) - printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.25.46/awf-config.schema.json","network":{"allowDomains":["api.business.githubcopilot.com","api.enterprise.githubcopilot.com","api.github.com","api.githubcopilot.com","api.individual.githubcopilot.com","api.snapcraft.io","archive.ubuntu.com","azure.archive.ubuntu.com","crl.geotrust.com","crl.globalsign.com","crl.identrust.com","crl.sectigo.com","crl.thawte.com","crl.usertrust.com","crl.verisign.com","crl3.digicert.com","crl4.digicert.com","crls.ssl.com","github.com","host.docker.internal","json-schema.org","json.schemastore.org","keyserver.ubuntu.com","ocsp.digicert.com","ocsp.geotrust.com","ocsp.globalsign.com","ocsp.identrust.com","ocsp.sectigo.com","ocsp.ssl.com","ocsp.thawte.com","ocsp.usertrust.com","ocsp.verisign.com","packagecloud.io","packages.cloud.google.com","packages.microsoft.com","ppa.launchpad.net","raw.githubusercontent.com","registry.npmjs.org","s.symcb.com","s.symcd.com","security.ubuntu.com","telemetry.enterprise.githubcopilot.com","ts-crl.ws.symantec.com","ts-ocsp.ws.symantec.com","www.googleapis.com"]},"apiProxy":{"enabled":true,"enableTokenSteering":true,"maxRuns":500,"maxEffectiveTokens":25000000,"models":{"auto":["large"],"deep-research":["copilot/deep-research*","copilot/o3-deep-research*","copilot/o4-mini-deep-research*","google/deep-research*","gemini/deep-research*","openai/o3-deep-research*","openai/o4-mini-deep-research*"],"gemini-flash":["copilot/gemini-*flash*","google/gemini-*flash*","gemini/gemini-*flash*"],"gemini-flash-lite":["copilot/gemini-*flash*lite*","google/gemini-*flash*lite*","gemini/gemini-*flash*lite*"],"gemini-pro":["copilot/gemini-*pro*","google/gemini-*pro*","gemini/gemini-*pro*"],"gemma":["copilot/gemma*","google/gemma*","gemini/gemma*"],"gpt-4.1":["copilot/gpt-4.1*","openai/gpt-4.1*"],"gpt-5":["copilot/gpt-5*","openai/gpt-5*"],"gpt-5-codex":["copilot/gpt-5*codex*","openai/gpt-5*codex*"],"gpt-5-mini":["copilot/gpt-5*mini*","openai/gpt-5*mini*"],"gpt-5-nano":["copilot/gpt-5*nano*","openai/gpt-5*nano*"],"gpt-5-pro":["copilot/gpt-5*pro*","openai/gpt-5*pro*"],"haiku":["copilot/*haiku*","anthropic/*haiku*"],"large":["sonnet","gpt-5-pro","gpt-5","gemini-pro"],"mini":["haiku","gpt-5-mini","gpt-5-nano","gemini-flash-lite"],"opus":["copilot/*opus*","anthropic/*opus*"],"reasoning":["copilot/o1*","copilot/o3*","copilot/o4*","openai/o1*","openai/o3*","openai/o4*"],"small":["mini"],"sonnet":["copilot/*sonnet*","anthropic/*sonnet*"]}},"container":{"imageTag":"0.25.46"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json" && cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json - GH_AW_DOCKER_HOST_PATH_PREFIX_ARGS="" - if [[ "${DOCKER_HOST:-}" =~ ^tcp:// ]]; then - GH_AW_DOCKER_HOST_PATH_PREFIX_ARGS="--docker-host-path-prefix /tmp/gh-aw" - fi + printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.25.41/awf-config.schema.json","network":{"allowDomains":["api.business.githubcopilot.com","api.enterprise.githubcopilot.com","api.github.com","api.githubcopilot.com","api.individual.githubcopilot.com","api.snapcraft.io","archive.ubuntu.com","azure.archive.ubuntu.com","crl.geotrust.com","crl.globalsign.com","crl.identrust.com","crl.sectigo.com","crl.thawte.com","crl.usertrust.com","crl.verisign.com","crl3.digicert.com","crl4.digicert.com","crls.ssl.com","github.com","host.docker.internal","json-schema.org","json.schemastore.org","keyserver.ubuntu.com","ocsp.digicert.com","ocsp.geotrust.com","ocsp.globalsign.com","ocsp.identrust.com","ocsp.sectigo.com","ocsp.ssl.com","ocsp.thawte.com","ocsp.usertrust.com","ocsp.verisign.com","packagecloud.io","packages.cloud.google.com","packages.microsoft.com","ppa.launchpad.net","raw.githubusercontent.com","registry.npmjs.org","s.symcb.com","s.symcd.com","security.ubuntu.com","telemetry.enterprise.githubcopilot.com","ts-crl.ws.symantec.com","ts-ocsp.ws.symantec.com","www.googleapis.com"]},"apiProxy":{"enabled":true,"models":{"auto":["large"],"deep-research":["copilot/deep-research*","copilot/o3-deep-research*","copilot/o4-mini-deep-research*","google/deep-research*","openai/o3-deep-research*","openai/o4-mini-deep-research*"],"gemini-flash":["copilot/gemini-*flash*","google/gemini-*flash*"],"gemini-pro":["copilot/gemini-*pro*","google/gemini-*pro*"],"gpt-4.1":["copilot/gpt-4.1*","openai/gpt-4.1*"],"gpt-5":["copilot/gpt-5*","openai/gpt-5*"],"gpt-5-codex":["copilot/gpt-5*codex*","openai/gpt-5*codex*"],"gpt-5-mini":["copilot/gpt-5*mini*","openai/gpt-5*mini*"],"gpt-5-nano":["copilot/gpt-5*nano*","openai/gpt-5*nano*"],"gpt-5-pro":["copilot/gpt-5*pro*","openai/gpt-5*pro*"],"haiku":["copilot/*haiku*","anthropic/*haiku*"],"large":["sonnet","gpt-5-pro","gpt-5","gemini-pro"],"mini":["haiku","gpt-5-mini","gpt-5-nano","gemini-flash"],"opus":["copilot/*opus*","anthropic/*opus*"],"reasoning":["copilot/o1*","copilot/o3*","copilot/o4*","openai/o1*","openai/o3*","openai/o4*"],"small":["mini"],"sonnet":["copilot/*sonnet*","anthropic/*sonnet*"]}},"container":{"imageTag":"0.25.41,squid=sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4,agent=sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770,api-proxy=sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0,cli-proxy=sha256:62171f2fa508667b8b0a9e096f826983f312e3da0ce894f80c0f83a875af60fe"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json" && cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json # shellcheck disable=SC1003 - sudo -E 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_DOCKER_HOST_PATH_PREFIX_ARGS} --env-all --exclude-env COPILOT_GITHUB_TOKEN --exclude-env GH_TOKEN --exclude-env GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_API_KEY --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --allow-host-ports 80,443,8080 --skip-pull --difc-proxy-host host.docker.internal:18443 --difc-proxy-ca-cert /tmp/gh-aw/difc-proxy-tls/ca.crt \ - -- /bin/bash -c 'export PATH="${RUNNER_TEMP}/gh-aw/mcp-cli/bin:$PATH" && export PATH="$(find /opt/hostedtoolcache /home/runner/work/_tool -maxdepth 5 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/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_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 serena --allow-tool '\''shell(cat .github/skills/go-linters/SKILL.md)'\'' --allow-tool '\''shell(cat cmd/linters/main.go)'\'' --allow-tool '\''shell(cat pkg/linters/**/*.go)'\'' --allow-tool '\''shell(cat pkg/linters/largefunc/largefunc.go)'\'' --allow-tool '\''shell(cat)'\'' --allow-tool '\''shell(date)'\'' --allow-tool '\''shell(echo)'\'' --allow-tool '\''shell(find pkg/linters -type d)'\'' --allow-tool '\''shell(find pkg/linters -type f -name *.go)'\'' --allow-tool '\''shell(gh:*)'\'' --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(grep -r * pkg/linters --include=*.go)'\'' --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(serena:*)'\'' --allow-tool '\''shell(sort)'\'' --allow-tool '\''shell(tail)'\'' --allow-tool '\''shell(uniq)'\'' --allow-tool '\''shell(wc)'\'' --allow-tool '\''shell(yq)'\'' --allow-tool write --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 + sudo -E 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" --env-all --exclude-env COPILOT_GITHUB_TOKEN --exclude-env GH_TOKEN --exclude-env GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_API_KEY --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --allow-host-ports 80,443,8080 --skip-pull --difc-proxy-host host.docker.internal:18443 --difc-proxy-ca-cert /tmp/gh-aw/difc-proxy-tls/ca.crt \ + -- /bin/bash -c 'export PATH="${RUNNER_TEMP}/gh-aw/mcp-cli/bin:$PATH" && export PATH="$(find /opt/hostedtoolcache /home/runner/work/_tool -maxdepth 4 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/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 || echo node)"; 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 serena --allow-tool '\''shell(cat .github/skills/go-linters/SKILL.md)'\'' --allow-tool '\''shell(cat cmd/linters/main.go)'\'' --allow-tool '\''shell(cat pkg/linters/**/*.go)'\'' --allow-tool '\''shell(cat pkg/linters/largefunc/largefunc.go)'\'' --allow-tool '\''shell(cat)'\'' --allow-tool '\''shell(date)'\'' --allow-tool '\''shell(echo)'\'' --allow-tool '\''shell(find pkg/linters -type d)'\'' --allow-tool '\''shell(find pkg/linters -type f -name *.go)'\'' --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(grep -r * pkg/linters --include=*.go)'\'' --allow-tool '\''shell(grep)'\'' --allow-tool '\''shell(head)'\'' --allow-tool '\''shell(ls)'\'' --allow-tool '\''shell(pwd)'\'' --allow-tool '\''shell(safeoutputs:*)'\'' --allow-tool '\''shell(serena:*)'\'' --allow-tool '\''shell(sort)'\'' --allow-tool '\''shell(tail)'\'' --allow-tool '\''shell(uniq)'\'' --allow-tool '\''shell(wc)'\'' --allow-tool '\''shell(yq)'\'' --allow-tool write --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 @@ -894,7 +873,7 @@ jobs: GH_AW_PHASE: agent 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_VERSION: dev + GH_AW_VERSION: v0.72.1 GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }} GITHUB_API_URL: ${{ github.api_url }} GITHUB_AW: true @@ -1113,32 +1092,23 @@ jobs: concurrency: group: "gh-aw-conclusion-linter-miner" cancel-in-progress: false - queue: max outputs: incomplete_count: ${{ steps.report_incomplete.outputs.incomplete_count }} noop_message: ${{ steps.noop.outputs.noop_message }} tools_reported: ${{ steps.missing_tool.outputs.tools_reported }} total_count: ${{ steps.missing_tool.outputs.total_count }} steps: - - name: Checkout actions folder - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - repository: github/gh-aw - sparse-checkout: | - actions - persist-credentials: false - name: Setup Scripts id: setup - uses: ./actions/setup + uses: github/gh-aw-actions/setup@v0.72.1 with: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} trace-id: ${{ needs.activation.outputs.setup-trace-id }} - parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }} env: GH_AW_SETUP_WORKFLOW_NAME: "Linter Miner" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/linter-miner.lock.yml@${{ github.ref }} - GH_AW_INFO_VERSION: "1.0.43" + GH_AW_INFO_VERSION: "1.0.40" - name: Download agent output artifact id: download-agent-output continue-on-error: true @@ -1232,8 +1202,6 @@ jobs: GH_AW_ACTION_FAILURE_ISSUE_EXPIRES_HOURS: "12" GH_AW_ENGINE_ID: "copilot" GH_AW_CHECKOUT_PR_SUCCESS: ${{ needs.agent.outputs.checkout_pr_success }} - GH_AW_EFFECTIVE_TOKENS: ${{ needs.agent.outputs.effective_tokens || '' }} - GH_AW_EFFECTIVE_TOKENS_RATE_LIMIT_ERROR: ${{ needs.agent.outputs.effective_tokens_rate_limit_error || 'false' }} GH_AW_INFERENCE_ACCESS_ERROR: ${{ needs.agent.outputs.inference_access_error }} GH_AW_MCP_POLICY_ERROR: ${{ needs.agent.outputs.mcp_policy_error }} GH_AW_AGENTIC_ENGINE_TIMEOUT: ${{ needs.agent.outputs.agentic_engine_timeout }} @@ -1248,7 +1216,6 @@ jobs: GH_AW_MISSING_TOOL_REPORT_AS_FAILURE: "true" GH_AW_MISSING_DATA_REPORT_AS_FAILURE: "true" GH_AW_TIMEOUT_MINUTES: "45" - GH_AW_MAX_EFFECTIVE_TOKENS: "25000000" GH_AW_CACHE_MEMORY_ENABLED: "true" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} @@ -1273,25 +1240,17 @@ jobs: detection_reason: ${{ steps.detection_conclusion.outputs.reason }} detection_success: ${{ steps.detection_conclusion.outputs.success }} steps: - - name: Checkout actions folder - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - repository: github/gh-aw - sparse-checkout: | - actions - persist-credentials: false - name: Setup Scripts id: setup - uses: ./actions/setup + uses: github/gh-aw-actions/setup@v0.72.1 with: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} trace-id: ${{ needs.activation.outputs.setup-trace-id }} - parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }} env: GH_AW_SETUP_WORKFLOW_NAME: "Linter Miner" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/linter-miner.lock.yml@${{ github.ref }} - GH_AW_INFO_VERSION: "1.0.43" + GH_AW_INFO_VERSION: "1.0.40" - name: Download agent output artifact id: download-agent-output continue-on-error: true @@ -1317,7 +1276,7 @@ jobs: rm -rf /tmp/gh-aw/sandbox/firewall/logs rm -rf /tmp/gh-aw/sandbox/firewall/audit - name: Download container images - run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.25.46 ghcr.io/github/gh-aw-firewall/api-proxy:0.25.46 ghcr.io/github/gh-aw-firewall/squid:0.25.46 + run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.25.41@sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770 ghcr.io/github/gh-aw-firewall/api-proxy:0.25.41@sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0 ghcr.io/github/gh-aw-firewall/squid:0.25.41@sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4 - name: Check if detection needed id: detection_guard if: always() @@ -1376,11 +1335,11 @@ jobs: node-version: '24' package-manager-cache: false - name: Install GitHub Copilot CLI - run: bash "${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh" 1.0.43 + run: bash "${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh" 1.0.40 env: GH_HOST: github.com - name: Install AWF binary - run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.25.46 + run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.25.41 - name: Execute GitHub Copilot CLI if: always() && steps.detection_guard.outputs.run_detection == 'true' continue-on-error: true @@ -1389,19 +1348,14 @@ jobs: timeout-minutes: 20 run: | set -o pipefail - printf '%s' "$(date +%s%3N)" > /tmp/gh-aw/agent_cli_start_ms.txt touch /tmp/gh-aw/agent-step-summary.md GH_AW_NODE_BIN=$(command -v node 2>/dev/null || true) export GH_AW_NODE_BIN (umask 177 && touch /tmp/gh-aw/threat-detection/detection.log) - printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.25.46/awf-config.schema.json","network":{"allowDomains":["api.business.githubcopilot.com","api.enterprise.githubcopilot.com","api.github.com","api.githubcopilot.com","api.individual.githubcopilot.com","github.com","host.docker.internal","telemetry.enterprise.githubcopilot.com"]},"apiProxy":{"enabled":true,"enableTokenSteering":true,"maxRuns":500,"maxEffectiveTokens":25000000},"container":{"imageTag":"0.25.46"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json" && cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json - GH_AW_DOCKER_HOST_PATH_PREFIX_ARGS="" - if [[ "${DOCKER_HOST:-}" =~ ^tcp:// ]]; then - GH_AW_DOCKER_HOST_PATH_PREFIX_ARGS="--docker-host-path-prefix /tmp/gh-aw" - fi + printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.25.41/awf-config.schema.json","network":{"allowDomains":["api.business.githubcopilot.com","api.enterprise.githubcopilot.com","api.github.com","api.githubcopilot.com","api.individual.githubcopilot.com","github.com","host.docker.internal","telemetry.enterprise.githubcopilot.com"]},"apiProxy":{"enabled":true},"container":{"imageTag":"0.25.41"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json" && cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json # shellcheck disable=SC1003 - sudo -E 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_DOCKER_HOST_PATH_PREFIX_ARGS} --env-all --exclude-env COPILOT_GITHUB_TOKEN --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --allow-host-ports 80,443,8080 --skip-pull \ - -- /bin/bash -c 'export PATH="$(find /opt/hostedtoolcache /home/runner/work/_tool -maxdepth 5 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/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_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 + sudo -E 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" --env-all --exclude-env COPILOT_GITHUB_TOKEN --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --allow-host-ports 80,443,8080 --skip-pull \ + -- /bin/bash -c 'export PATH="$(find /opt/hostedtoolcache /home/runner/work/_tool -maxdepth 4 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/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 || echo node)"; 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 env: AWF_REFLECT_ENABLED: 1 COPILOT_AGENT_RUNNER_TYPE: STANDALONE @@ -1410,7 +1364,7 @@ jobs: COPILOT_MODEL: ${{ vars.GH_AW_MODEL_DETECTION_COPILOT || 'claude-sonnet-4.6' }} GH_AW_PHASE: detection GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - GH_AW_VERSION: dev + GH_AW_VERSION: v0.72.1 GITHUB_API_URL: ${{ github.api_url }} GITHUB_AW: true GITHUB_COPILOT_INTEGRATION_ID: agentic-workflows @@ -1439,7 +1393,6 @@ jobs: uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: RUN_DETECTION: ${{ steps.detection_guard.outputs.run_detection }} - DETECTION_AGENTIC_EXECUTION_OUTCOME: ${{ steps.detection_agentic_execution.outcome }} GH_AW_DETECTION_CONTINUE_ON_ERROR: "true" with: script: | @@ -1450,11 +1403,10 @@ jobs: await main(); } catch (loadErr) { const continueOnError = process.env.GH_AW_DETECTION_CONTINUE_ON_ERROR !== 'false'; - const detectionExecutionFailed = process.env.DETECTION_AGENTIC_EXECUTION_OUTCOME === 'failure'; const msg = 'ERR_SYSTEM: \u274C Unexpected error loading threat detection module: ' + (loadErr && loadErr.message ? loadErr.message : String(loadErr)); core.error(msg); core.setOutput('reason', 'parse_error'); - if (continueOnError && !detectionExecutionFailed) { + if (continueOnError) { core.warning('\u26A0\uFE0F ' + msg); core.setOutput('conclusion', 'warning'); core.setOutput('success', 'false'); @@ -1484,7 +1436,7 @@ jobs: GH_AW_EFFECTIVE_TOKENS: ${{ needs.agent.outputs.effective_tokens }} GH_AW_ENGINE_ID: "copilot" GH_AW_ENGINE_MODEL: ${{ needs.agent.outputs.model }} - GH_AW_ENGINE_VERSION: "1.0.43" + GH_AW_ENGINE_VERSION: "1.0.40" GH_AW_TRACKER_ID: "linter-miner" GH_AW_WORKFLOW_ID: "linter-miner" GH_AW_WORKFLOW_NAME: "Linter Miner" @@ -1498,25 +1450,17 @@ jobs: process_safe_outputs_processed_count: ${{ steps.process_safe_outputs.outputs.processed_count }} process_safe_outputs_temporary_id_map: ${{ steps.process_safe_outputs.outputs.temporary_id_map }} steps: - - name: Checkout actions folder - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - repository: github/gh-aw - sparse-checkout: | - actions - persist-credentials: false - name: Setup Scripts id: setup - uses: ./actions/setup + uses: github/gh-aw-actions/setup@v0.72.1 with: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} trace-id: ${{ needs.activation.outputs.setup-trace-id }} - parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }} env: GH_AW_SETUP_WORKFLOW_NAME: "Linter Miner" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/linter-miner.lock.yml@${{ github.ref }} - GH_AW_INFO_VERSION: "1.0.43" + GH_AW_INFO_VERSION: "1.0.40" - name: Mask OTLP telemetry headers run: bash "${RUNNER_TEMP}/gh-aw/actions/mask_otlp_headers.sh" - name: Download agent output artifact @@ -1619,15 +1563,6 @@ jobs: /tmp/gh-aw/safe-output-items.jsonl /tmp/gh-aw/temporary-id-map.json if-no-files-found: ignore - - name: Restore actions folder - if: always() - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - repository: github/gh-aw - sparse-checkout: | - actions/setup - sparse-checkout-cone-mode: true - persist-credentials: false update_cache_memory: needs: @@ -1638,30 +1573,21 @@ jobs: always() && (needs.detection.result == 'success' || needs.detection.result == 'skipped') && needs.agent.result == 'success' runs-on: ubuntu-slim - permissions: - contents: read + permissions: {} env: GH_AW_WORKFLOW_ID_SANITIZED: linterminer steps: - - name: Checkout actions folder - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - repository: github/gh-aw - sparse-checkout: | - actions - persist-credentials: false - name: Setup Scripts id: setup - uses: ./actions/setup + uses: github/gh-aw-actions/setup@v0.72.1 with: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} trace-id: ${{ needs.activation.outputs.setup-trace-id }} - parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }} env: GH_AW_SETUP_WORKFLOW_NAME: "Linter Miner" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/linter-miner.lock.yml@${{ github.ref }} - GH_AW_INFO_VERSION: "1.0.43" + GH_AW_INFO_VERSION: "1.0.40" - name: Download cache-memory artifact (default) id: download_cache_default uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 From 125630209ae002dba154c3bb7f263d641c237085 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 15 May 2026 04:52:14 +0000 Subject: [PATCH 05/22] Apply signed commits option feedback Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .../patch-push-signed-commits-opt-out.md | 2 +- actions/setup/js/create_pull_request.cjs | 9 ++- actions/setup/js/create_pull_request.test.cjs | 31 +++++++++++ actions/setup/js/push_signed_commits.cjs | 4 +- actions/setup/js/push_signed_commits.test.cjs | 2 +- .../setup/js/push_to_pull_request_branch.cjs | 2 +- .../js/push_to_pull_request_branch.test.cjs | 2 +- actions/setup/js/types/handler-factory.d.ts | 2 +- .../reference/safe-outputs-pull-requests.md | 5 +- .../content/docs/reference/safe-outputs.md | 2 +- pkg/parser/schemas/main_workflow_schema.json | 9 ++- pkg/workflow/compile_outputs_pr_test.go | 55 +++++++++++++++++++ .../compiler_safe_outputs_handlers.go | 3 +- pkg/workflow/create_pull_request.go | 1 + pkg/workflow/push_to_pull_request_branch.go | 10 ++-- .../push_to_pull_request_branch_test.go | 16 +++--- 16 files changed, 126 insertions(+), 29 deletions(-) diff --git a/.changeset/patch-push-signed-commits-opt-out.md b/.changeset/patch-push-signed-commits-opt-out.md index 68761f09a27..a0692368ab7 100644 --- a/.changeset/patch-push-signed-commits-opt-out.md +++ b/.changeset/patch-push-signed-commits-opt-out.md @@ -2,4 +2,4 @@ "gh-aw": patch --- -Allow `push-to-pull-request-branch` to set `push-signed-commits: false` so repositories that do not require signed commits can push merge commits with direct `git push`. +Allow `create-pull-request` and `push-to-pull-request-branch` to set `signed-commits: false` so repositories that do not require signed commits can push merge commits with direct `git push`. diff --git a/actions/setup/js/create_pull_request.cjs b/actions/setup/js/create_pull_request.cjs index ad17e541cbe..2671567276e 100644 --- a/actions/setup/js/create_pull_request.cjs +++ b/actions/setup/js/create_pull_request.cjs @@ -671,9 +671,7 @@ async function main(config = {}) { const normalizedBranchPrefix = normalizeBranchName(rawBranchPrefix); if (rawBranchPrefix && normalizedBranchPrefix !== rawBranchPrefix) { core.warning( - `Branch prefix "${rawBranchPrefix}" contains characters that are invalid in a git ref. ` + - `Using normalized prefix: "${normalizedBranchPrefix}". ` + - `Update branch-prefix in the workflow configuration to avoid this warning.` + `Branch prefix "${rawBranchPrefix}" contains characters that are invalid in a git ref. ` + `Using normalized prefix: "${normalizedBranchPrefix}". ` + `Update branch-prefix in the workflow configuration to avoid this warning.` ); } const branchPrefix = normalizedBranchPrefix; @@ -691,6 +689,7 @@ async function main(config = {}) { const autoMerge = parseBoolTemplatable(config.auto_merge, false); const preserveBranchName = config.preserve_branch_name === true; const recreateRef = config.recreate_ref === true; + const signedCommits = config.signed_commits !== false; const expiresHours = config.expires ? parseInt(String(config.expires), 10) : 0; const maxCount = config.max || 1; // PRs are typically limited to 1 const maxSizeKb = config.max_patch_size ? parseInt(String(config.max_patch_size), 10) : 1024; @@ -822,6 +821,7 @@ async function main(config = {}) { core.info(`If no changes: ${ifNoChanges}`); core.info(`Allow empty: ${allowEmpty}`); core.info(`Auto-merge: ${autoMerge}`); + core.info(`Signed commits: ${signedCommits}`); if (expiresHours > 0) { core.info(`Pull requests expire after: ${expiresHours} hours`); } @@ -1422,6 +1422,7 @@ async function main(config = {}) { branch: branchName, baseRef: `origin/${baseBranch}`, cwd: process.cwd(), + signedCommits, }); core.info("Changes pushed to branch (from bundle)"); @@ -1638,6 +1639,7 @@ gh pr create --title '${title}' --base ${baseBranch} --head ${branchName} --repo branch: branchName, baseRef: `origin/${baseBranch}`, cwd: process.cwd(), + signedCommits, }); core.info("Changes pushed to branch"); @@ -1782,6 +1784,7 @@ ${patchPreview}`; branch: branchName, baseRef: `origin/${baseBranch}`, cwd: process.cwd(), + signedCommits, }); core.info("Empty branch pushed successfully"); diff --git a/actions/setup/js/create_pull_request.test.cjs b/actions/setup/js/create_pull_request.test.cjs index d4ba252452a..a425e536bde 100644 --- a/actions/setup/js/create_pull_request.test.cjs +++ b/actions/setup/js/create_pull_request.test.cjs @@ -266,6 +266,37 @@ index 0000000..abc1234 expect(bundleFetchCallIndex).toBeGreaterThan(unshallowCallIndex); }); + it("should pass signed_commits false to bundle pushes", async () => { + const patchPath = path.join(tempDir, "test.patch"); + fs.writeFileSync( + patchPath, + `From abc123 Mon Sep 17 00:00:00 2001 +From: Test Author +Date: Mon, 1 Jan 2024 00:00:00 +0000 +Subject: [PATCH] Test commit + +diff --git a/test.txt b/test.txt +new file mode 100644 +index 0000000..abc1234 +--- /dev/null ++++ b/test.txt +@@ -0,0 +1 @@ ++Hello World +-- +2.34.1 +` + ); + const bundlePath = path.join(tempDir, "test.bundle"); + fs.writeFileSync(bundlePath, "bundle content"); + + const { main } = require("./create_pull_request.cjs"); + const handler = await main({ base_branch: "main", preserve_branch_name: true, signed_commits: false }); + const result = await handler({ title: "Test PR", body: "Test body", branch: "feature/test", patch_path: patchPath, bundle_path: bundlePath }, {}); + + expect(result.success).toBe(true); + expect(pushSignedSpy).toHaveBeenCalledWith(expect.objectContaining({ signedCommits: false })); + }); + it("should resolve bundle source ref from list-heads when JSONL branch ref is missing in bundle", async () => { const patchPath = path.join(tempDir, "test.patch"); fs.writeFileSync( diff --git a/actions/setup/js/push_signed_commits.cjs b/actions/setup/js/push_signed_commits.cjs index 8739a386189..3a1c7a9b1fa 100644 --- a/actions/setup/js/push_signed_commits.cjs +++ b/actions/setup/js/push_signed_commits.cjs @@ -178,7 +178,7 @@ async function pushSignedCommits({ githubClient, owner, repo, branch, baseRef, c } if (signedCommits === false) { - core.info(`pushSignedCommits: push-signed-commits disabled, using git push directly for branch ${branch}`); + core.info(`pushSignedCommits: signed-commits disabled, using git push directly for branch ${branch}`); await exec.exec("git", ["push", "origin", branch], { cwd, env: { ...process.env, ...(gitAuthEnv || {}) }, @@ -414,7 +414,7 @@ async function pushSignedCommits({ githubClient, owner, repo, branch, baseRef, c `GitHub's createCommitOnBranch GraphQL mutation cannot represent merge commits, symlinks (mode 120000), ` + `submodule entries (mode 160000), or executable bits (mode 100755). ` + `Rewrite the commits to use only regular files (mode 100644) with no merge commits, ` + - `or set push-signed-commits: false if the repository does not require signed commits.`, + `or set signed-commits: false if the repository does not require signed commits.`, { cause: err } ); } diff --git a/actions/setup/js/push_signed_commits.test.cjs b/actions/setup/js/push_signed_commits.test.cjs index 385d4a1359a..e7dc36c4c59 100644 --- a/actions/setup/js/push_signed_commits.test.cjs +++ b/actions/setup/js/push_signed_commits.test.cjs @@ -1156,7 +1156,7 @@ describe("push_signed_commits integration tests", () => { expect(pushedSha).toBe(expectedHead); expect(githubClient.graphql).not.toHaveBeenCalled(); expect(execGit(["rev-parse", "refs/heads/unsigned-merge-test-branch"], { cwd: bareDir }).stdout.trim()).toBe(expectedHead); - expect(mockCore.info).toHaveBeenCalledWith("pushSignedCommits: push-signed-commits disabled, using git push directly for branch unsigned-merge-test-branch"); + expect(mockCore.info).toHaveBeenCalledWith("pushSignedCommits: signed-commits disabled, using git push directly for branch unsigned-merge-test-branch"); }); it("should not trigger merge-commit fallback for a commit message that starts with 'parent '", async () => { diff --git a/actions/setup/js/push_to_pull_request_branch.cjs b/actions/setup/js/push_to_pull_request_branch.cjs index 51d36550702..e5cb08ff87c 100644 --- a/actions/setup/js/push_to_pull_request_branch.cjs +++ b/actions/setup/js/push_to_pull_request_branch.cjs @@ -113,7 +113,7 @@ async function main(config = {}) { const ignoreMissingBranchFailure = config.ignore_missing_branch_failure === true; const fallbackAsPullRequest = config.fallback_as_pull_request !== false; const checkBranchProtection = config.check_branch_protection !== false; - const signedCommits = config.push_signed_commits !== false; + const signedCommits = config.signed_commits !== false; const commitTitleSuffix = config.commit_title_suffix || ""; const maxSizeKb = config.max_patch_size ? parseInt(String(config.max_patch_size), 10) : 1024; const maxCount = config.max || 0; // 0 means no limit diff --git a/actions/setup/js/push_to_pull_request_branch.test.cjs b/actions/setup/js/push_to_pull_request_branch.test.cjs index 150110ae0e8..ec507d09a1a 100644 --- a/actions/setup/js/push_to_pull_request_branch.test.cjs +++ b/actions/setup/js/push_to_pull_request_branch.test.cjs @@ -259,7 +259,7 @@ index 0000000..abc1234 it("should accept disabling signed commits", async () => { const module = await loadModule(); - await module.main({ push_signed_commits: false }); + await module.main({ signed_commits: false }); expect(mockCore.info).toHaveBeenCalledWith("Push signed commits: false"); }); diff --git a/actions/setup/js/types/handler-factory.d.ts b/actions/setup/js/types/handler-factory.d.ts index 06f6ec965f5..b98e602bb8c 100644 --- a/actions/setup/js/types/handler-factory.d.ts +++ b/actions/setup/js/types/handler-factory.d.ts @@ -25,7 +25,7 @@ interface HandlerConfig { /** When true (default), create a fallback pull request if direct push to PR branch fails with non-fast-forward/diverged branch. */ fallback_as_pull_request?: boolean; /** When false, skip GraphQL signed commits and push the local git history directly. */ - push_signed_commits?: boolean; + signed_commits?: boolean; /** Additional handler-specific configuration properties */ [key: string]: any; } diff --git a/docs/src/content/docs/reference/safe-outputs-pull-requests.md b/docs/src/content/docs/reference/safe-outputs-pull-requests.md index 2ef0161b311..c2456c79568 100644 --- a/docs/src/content/docs/reference/safe-outputs-pull-requests.md +++ b/docs/src/content/docs/reference/safe-outputs-pull-requests.md @@ -54,6 +54,7 @@ safe-outputs: - "dist/**" github-token: ${{ secrets.SOME_CUSTOM_TOKEN }} # optional custom token for permissions github-token-for-extra-empty-commit: ${{ secrets.CI_TOKEN }} # optional token to push empty commit triggering CI + signed-commits: true # signed commits are required (default); set false to use git push directly protected-files: fallback-to-issue # push branch, create review issue if protected files modified ``` @@ -264,7 +265,7 @@ safe-outputs: github-token: ${{ secrets.SOME_CUSTOM_TOKEN }} # optional custom token for permissions github-token-for-extra-empty-commit: ${{ secrets.CI_TOKEN }} # optional token to push empty commit triggering CI fallback-as-pull-request: true # on non-fast-forward failure, create fallback PR to original PR branch (default: true) - push-signed-commits: true # set false to use git push directly, allowing merge commits when signed commits are not required + signed-commits: true # signed commits are required (default); set false to use git push directly ignore-missing-branch-failure: false # treat deleted/missing branch errors as skipped instead of failed (default: false) check-branch-protection: true # set to false to skip the branch protection pre-flight check (default: true) protected-files: fallback-to-issue # create review issue if protected files modified @@ -274,7 +275,7 @@ safe-outputs: When `push-to-pull-request-branch` is configured, git commands (`checkout`, `branch`, `switch`, `add`, `rm`, `commit`, `merge`) are automatically enabled. -By default, pushes are replayed through GitHub's signed commit API. Set `push-signed-commits: false` only for repositories that do not require signed commits; this uses direct `git push` and can preserve merge commits that the signed commit API cannot represent. +By default, pushes are replayed through GitHub's signed commit API because `signed-commits: true` means signed commits are required. Set `signed-commits: false` only for repositories that do not require signed commits; this uses direct `git push` and can preserve merge commits that the signed commit API cannot represent. This field is supported by both `create-pull-request` and `push-to-pull-request-branch`. ### Cross-repo usage diff --git a/docs/src/content/docs/reference/safe-outputs.md b/docs/src/content/docs/reference/safe-outputs.md index 6fbb980092d..78429101d83 100644 --- a/docs/src/content/docs/reference/safe-outputs.md +++ b/docs/src/content/docs/reference/safe-outputs.md @@ -890,7 +890,7 @@ safe-outputs: target: "*" # "triggering" (default), "*", or number title-prefix: "[bot] " # require title prefix labels: [automated] # require all labels - push-signed-commits: false # optional: use git push directly when signed commits are not required + signed-commits: false # optional: use git push directly when signed commits are not required protected-files: fallback-to-issue # create review issue if protected files modified ``` diff --git a/pkg/parser/schemas/main_workflow_schema.json b/pkg/parser/schemas/main_workflow_schema.json index 38d23c2caac..a1c1c607e4d 100644 --- a/pkg/parser/schemas/main_workflow_schema.json +++ b/pkg/parser/schemas/main_workflow_schema.json @@ -6382,6 +6382,11 @@ ], "description": "Transport format for packaging changes. \"bundle\" (default) uses git bundle. \"am\" uses git format-patch/git am. Accepts a GitHub Actions expression for reusable workflows." }, + "signed-commits": { + "type": "boolean", + "description": "When true (default), signed commits are required and pushes use GitHub's createCommitOnBranch GraphQL mutation so GitHub signs them. Set to false to use git push directly for repositories that do not require signed commits; this also allows pushing merge commits that GraphQL cannot represent.", + "default": true + }, "staged": { "type": "boolean", "description": "If true, emit step summary messages instead of making GitHub API calls for this specific output type (preview mode)", @@ -7616,9 +7621,9 @@ "description": "When true (default), if pushing to the PR branch fails due to a non-fast-forward/diverged branch, create a fallback pull request that targets the original PR branch. Set to false to disable this behavior and avoid requiring pull-requests: write permission.", "default": true }, - "push-signed-commits": { + "signed-commits": { "type": "boolean", - "description": "When true (default), pushes regular commits through GitHub's createCommitOnBranch GraphQL mutation so GitHub signs them. Set to false to use git push directly for repositories that do not require signed commits; this also allows pushing merge commits that GraphQL cannot represent.", + "description": "When true (default), signed commits are required and pushes use GitHub's createCommitOnBranch GraphQL mutation so GitHub signs them. Set to false to use git push directly for repositories that do not require signed commits; this also allows pushing merge commits that GraphQL cannot represent.", "default": true }, "target-repo": { diff --git a/pkg/workflow/compile_outputs_pr_test.go b/pkg/workflow/compile_outputs_pr_test.go index 5927990bae9..2830200b822 100644 --- a/pkg/workflow/compile_outputs_pr_test.go +++ b/pkg/workflow/compile_outputs_pr_test.go @@ -757,6 +757,61 @@ This workflow tests the create-pull-request with fallback-as-issue disabled. } } +func TestOutputPullRequestSignedCommitsDisabled(t *testing.T) { + tmpDir := testutil.TempDir(t, "output-pr-signed-commits-test") + + testContent := `--- +on: push +permissions: + contents: read + pull-requests: read +engine: claude +strict: false +safe-outputs: + create-pull-request: + title-prefix: "[test] " + signed-commits: false + noop: + report-as-issue: false +--- + +# Test Output Pull Request Signed Commits Disabled +` + + testFile := filepath.Join(tmpDir, "test-output-pr-signed-commits.md") + if err := os.WriteFile(testFile, []byte(testContent), 0644); err != nil { + t.Fatal(err) + } + + compiler := NewCompiler() + workflowData, err := compiler.ParseWorkflowFile(testFile) + if err != nil { + t.Fatalf("Unexpected error parsing workflow with signed-commits: false: %v", err) + } + if workflowData.SafeOutputs == nil || workflowData.SafeOutputs.CreatePullRequests == nil { + t.Fatal("Expected create-pull-request configuration to be parsed") + } + if workflowData.SafeOutputs.CreatePullRequests.SignedCommits == nil { + t.Fatal("Expected signed-commits to be set") + } + if *workflowData.SafeOutputs.CreatePullRequests.SignedCommits { + t.Error("Expected signed-commits to be false") + } + + if err := compiler.CompileWorkflow(testFile); err != nil { + t.Fatalf("Unexpected error compiling workflow with signed-commits: false: %v", err) + } + + lockFile := stringutil.MarkdownToLockFile(testFile) + lockContent, err := os.ReadFile(lockFile) + if err != nil { + t.Fatalf("Failed to read generated lock file: %v", err) + } + if !strings.Contains(string(lockContent), `"signed_commits":false`) { + t.Error("Expected signed_commits:false in handler config JSON") + } +} + func TestOutputPullRequestFallbackAsIssueDefault(t *testing.T) { // Create temporary directory for test files tmpDir := testutil.TempDir(t, "output-pr-fallback-default-test") diff --git a/pkg/workflow/compiler_safe_outputs_handlers.go b/pkg/workflow/compiler_safe_outputs_handlers.go index 4a7683e5be6..58b714bc297 100644 --- a/pkg/workflow/compiler_safe_outputs_handlers.go +++ b/pkg/workflow/compiler_safe_outputs_handlers.go @@ -421,6 +421,7 @@ var handlerRegistry = map[string]handlerBuilder{ AddIfTrue("preserve_branch_name", c.PreserveBranchName). AddIfTrue("recreate_ref", c.RecreateRef). AddIfNotEmpty("patch_format", c.PatchFormat). + AddBoolPtr("signed_commits", c.SignedCommits). AddIfTrue("staged", c.Staged) return builder.Build() }, @@ -455,7 +456,7 @@ var handlerRegistry = map[string]handlerBuilder{ AddStringSlice("excluded_files", c.ExcludedFiles). AddIfNotEmpty("patch_format", c.PatchFormat). AddBoolPtr("fallback_as_pull_request", c.FallbackAsPullRequest). - AddBoolPtr("push_signed_commits", c.PushSignedCommits). + AddBoolPtr("signed_commits", c.SignedCommits). AddBoolPtr("check_branch_protection", c.CheckBranchProtection). Build() }, diff --git a/pkg/workflow/create_pull_request.go b/pkg/workflow/create_pull_request.go index c5901af8834..c4be15299bc 100644 --- a/pkg/workflow/create_pull_request.go +++ b/pkg/workflow/create_pull_request.go @@ -45,6 +45,7 @@ type CreatePullRequestsConfig struct { PreserveBranchName bool `yaml:"preserve-branch-name,omitempty"` // When true, skips the random salt suffix on agent-specified branch names. Invalid characters are still replaced for security; casing is always preserved. Useful when CI enforces branch naming conventions (e.g. Jira keys in uppercase). RecreateRef bool `yaml:"recreate-ref,omitempty"` // When true (and preserve-branch-name is true), allows the handler to force-delete an existing remote branch ref and recreate it from the agent's local HEAD. When false (default), an existing remote branch causes a fallback to issue (or push_failed). Useful for long-lived reusable branches whose previous PR was merged. PatchFormat string `yaml:"patch-format,omitempty"` // Transport format for packaging changes: "bundle" (default, uses git bundle and preserves merge topology/per-commit metadata) or "am" (uses git format-patch). + SignedCommits *bool `yaml:"signed-commits,omitempty"` // When false, skips GitHub GraphQL signed commits and pushes the local git history directly. Default is true. AllowWorkflows bool `yaml:"allow-workflows,omitempty"` // When true, adds workflows: write to the GitHub App token. Requires safe-outputs.github-app to be configured. } diff --git a/pkg/workflow/push_to_pull_request_branch.go b/pkg/workflow/push_to_pull_request_branch.go index 1c140705164..046a8030bb1 100644 --- a/pkg/workflow/push_to_pull_request_branch.go +++ b/pkg/workflow/push_to_pull_request_branch.go @@ -27,7 +27,7 @@ type PushToPullRequestBranchConfig struct { ExcludedFiles []string `yaml:"excluded-files,omitempty"` // List of glob patterns for files to exclude from the patch using git :(exclude) pathspecs. Matching files are stripped by git at generation time and will not appear in the commit or be subject to allowed-files or protected-files checks. PatchFormat string `yaml:"patch-format,omitempty"` // Transport format for packaging changes: "bundle" (default, uses git bundle and preserves merge topology/per-commit metadata) or "am" (uses git format-patch). FallbackAsPullRequest *bool `yaml:"fallback-as-pull-request,omitempty"` // When true (default), creates a fallback pull request if direct push fails due to diverged/non-fast-forward branch. When false, fallback is disabled and pull-requests: write is not requested. - PushSignedCommits *bool `yaml:"push-signed-commits,omitempty"` // When false, skips GitHub GraphQL signed commits and pushes the local git history directly. Default is true. + SignedCommits *bool `yaml:"signed-commits,omitempty"` // When false, skips GitHub GraphQL signed commits and pushes the local git history directly. Default is true. AllowWorkflows bool `yaml:"allow-workflows,omitempty"` // When true, adds workflows: write to the GitHub App token. Requires safe-outputs.github-app to be configured. CheckBranchProtection *bool `yaml:"check-branch-protection,omitempty"` // When false, skips the branch protection API pre-flight check. Default is true (check enabled). Set to false to avoid needing administration: read permission. } @@ -183,10 +183,10 @@ func (c *Compiler) parsePushToPullRequestBranchConfig(outputMap map[string]any) } } - // Parse push-signed-commits (optional, defaults to true) - if pushSignedCommits, exists := configMap["push-signed-commits"]; exists { - if pushSignedCommitsBool, ok := pushSignedCommits.(bool); ok { - pushToBranchConfig.PushSignedCommits = &pushSignedCommitsBool + // Parse signed-commits (optional, defaults to true) + if signedCommits, exists := configMap["signed-commits"]; exists { + if signedCommitsBool, ok := signedCommits.(bool); ok { + pushToBranchConfig.SignedCommits = &signedCommitsBool } } diff --git a/pkg/workflow/push_to_pull_request_branch_test.go b/pkg/workflow/push_to_pull_request_branch_test.go index 1053f1f031c..d26ddf45d50 100644 --- a/pkg/workflow/push_to_pull_request_branch_test.go +++ b/pkg/workflow/push_to_pull_request_branch_test.go @@ -241,7 +241,7 @@ safe-outputs: } } -func TestPushToPullRequestBranchPushSignedCommitsDisabled(t *testing.T) { +func TestPushToPullRequestBranchSignedCommitsDisabled(t *testing.T) { tmpDir := testutil.TempDir(t, "test-*") testMarkdown := `--- @@ -250,7 +250,7 @@ on: types: [opened, synchronize] safe-outputs: push-to-pull-request-branch: - push-signed-commits: false + signed-commits: false --- # Test Push to PR Branch Signed Commits Disabled @@ -273,16 +273,16 @@ safe-outputs: } pushConfig := extractPushToPullRequestBranchHandlerConfig(t, lockContent) - pushSignedCommits, exists := pushConfig["push_signed_commits"] + signedCommits, exists := pushConfig["signed_commits"] if !exists { - t.Errorf("Generated workflow should contain push_signed_commits in handler config JSON") + t.Errorf("Generated workflow should contain signed_commits in handler config JSON") } - pushSignedCommitsBool, isBool := pushSignedCommits.(bool) + signedCommitsBool, isBool := signedCommits.(bool) if !isBool { - t.Errorf("Expected push_signed_commits to be a bool, got %#v", pushSignedCommits) + t.Errorf("Expected signed_commits to be a bool, got %#v", signedCommits) } - if pushSignedCommitsBool { - t.Errorf("Expected push_signed_commits=false, got %#v", pushSignedCommitsBool) + if signedCommitsBool { + t.Errorf("Expected signed_commits=false, got %#v", signedCommitsBool) } } From b40bd5d69298af77ab074b3ff3902d12d6d9b0af Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 15 May 2026 04:53:57 +0000 Subject: [PATCH 06/22] Keep branch prefix warning readable Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- actions/setup/js/create_pull_request.cjs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/actions/setup/js/create_pull_request.cjs b/actions/setup/js/create_pull_request.cjs index 2671567276e..51e8fe8f88a 100644 --- a/actions/setup/js/create_pull_request.cjs +++ b/actions/setup/js/create_pull_request.cjs @@ -670,9 +670,12 @@ async function main(config = {}) { const rawBranchPrefix = config.branch_prefix || ""; const normalizedBranchPrefix = normalizeBranchName(rawBranchPrefix); if (rawBranchPrefix && normalizedBranchPrefix !== rawBranchPrefix) { - core.warning( - `Branch prefix "${rawBranchPrefix}" contains characters that are invalid in a git ref. ` + `Using normalized prefix: "${normalizedBranchPrefix}". ` + `Update branch-prefix in the workflow configuration to avoid this warning.` - ); + const branchPrefixWarning = [ + `Branch prefix "${rawBranchPrefix}" contains characters that are invalid in a git ref.`, + `Using normalized prefix: "${normalizedBranchPrefix}".`, + "Update branch-prefix in the workflow configuration to avoid this warning.", + ].join(" "); + core.warning(branchPrefixWarning); } const branchPrefix = normalizedBranchPrefix; const titlePrefix = config.title_prefix || ""; From 584be0133efce079e6d4c6039bd22ca668744d93 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 15 May 2026 05:06:54 +0000 Subject: [PATCH 07/22] Recompile workflows after main merge Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .github/workflows/daily-geo-optimizer.lock.yml | 4 +++- actions/setup/js/update_pull_request.cjs | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/daily-geo-optimizer.lock.yml b/.github/workflows/daily-geo-optimizer.lock.yml index 09b72484da6..7468b42b2f8 100644 --- a/.github/workflows/daily-geo-optimizer.lock.yml +++ b/.github/workflows/daily-geo-optimizer.lock.yml @@ -1383,8 +1383,10 @@ jobs: > /tmp/gh-aw/geo-optimizer/docs-sitemap-audit.json 2>&1 || true - name: Audit README via GitHub repository page run: | - geo audit --url https://github.com/${{ github.repository }} --format json \ + geo audit --url https://github.com/$GH_AW_GITHUB_REPOSITORY --format json \ > /tmp/gh-aw/geo-optimizer/readme-audit.json 2>&1 || true + env: + GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} - name: Write audit metadata run: | python3 - <<'EOF' diff --git a/actions/setup/js/update_pull_request.cjs b/actions/setup/js/update_pull_request.cjs index d3153b42bd4..3da5866e153 100644 --- a/actions/setup/js/update_pull_request.cjs +++ b/actions/setup/js/update_pull_request.cjs @@ -26,7 +26,7 @@ function isNonFatalUpdateBranchError(error) { /** @type {number | undefined} */ let status; if (typeof error === "object" && error !== null && "status" in error) { - status = /** @type {{status?: number}} */ error.status; + status = /** @type {{status?: number}} */ (error).status; } if (status !== undefined && status !== 422) { return false; From d9799de725941c12d8e791fca7056fa79978585a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 15 May 2026 05:26:59 +0000 Subject: [PATCH 08/22] Apply SOLID cleanup to unsigned push path Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- actions/setup/js/push_signed_commits.cjs | 59 +++++++++++++++--------- 1 file changed, 38 insertions(+), 21 deletions(-) diff --git a/actions/setup/js/push_signed_commits.cjs b/actions/setup/js/push_signed_commits.cjs index 3a1c7a9b1fa..891c27b4e30 100644 --- a/actions/setup/js/push_signed_commits.cjs +++ b/actions/setup/js/push_signed_commits.cjs @@ -118,6 +118,33 @@ async function readBlobAsBase64(blobHash, cwd) { return Buffer.concat(chunks).toString("base64"); } +/** + * Push the local branch to origin using git directly. + * + * @param {object} opts + * @param {string} opts.branch + * @param {string} opts.cwd + * @param {object} [opts.gitAuthEnv] + * @returns {Promise} + */ +async function pushBranchWithGit({ branch, cwd, gitAuthEnv }) { + await exec.exec("git", ["push", "origin", branch], { + cwd, + env: { ...process.env, ...(gitAuthEnv || {}) }, + }); +} + +/** + * Resolve the local HEAD SHA. + * + * @param {string} cwd + * @returns {Promise} + */ +async function resolveLocalHeadSha(cwd) { + const { stdout } = await exec.getExecOutput("git", ["rev-parse", "HEAD"], { cwd }); + return stdout.trim(); +} + /** * @fileoverview Signed Commit Push Helper * @@ -154,16 +181,20 @@ async function pushSignedCommits({ githubClient, owner, repo, branch, baseRef, c // so skip it entirely and fall directly through to git push. if (!baseRef) { core.info(`pushSignedCommits: empty baseRef detected (orphan branch first push), using git push directly for branch ${branch}`); - await exec.exec("git", ["push", "origin", branch], { - cwd, - env: { ...process.env, ...(gitAuthEnv || {}) }, - }); - const { stdout: headOut } = await exec.getExecOutput("git", ["rev-parse", "HEAD"], { cwd }); - const headSha = headOut.trim(); + await pushBranchWithGit({ branch, cwd, gitAuthEnv }); + const headSha = await resolveLocalHeadSha(cwd); core.info(`pushSignedCommits: git push completed for orphan branch, HEAD=${headSha}`); return headSha; } + if (signedCommits === false) { + core.info(`pushSignedCommits: signed-commits disabled, using git push directly for branch ${branch}`); + await pushBranchWithGit({ branch, cwd, gitAuthEnv }); + const pushedSha = await resolveLocalHeadSha(cwd); + core.info(`pushSignedCommits: git push completed with signed commits disabled, using pushed SHA ${pushedSha}`); + return pushedSha; + } + // Collect the commits introduced (oldest-first) using topological order to ensure // correct sequencing even when commit dates are out of sync (e.g. after rebase --committer-date-is-author-date). // Using --parents emits each line as " [ ...]", which lets us detect merge commits @@ -177,17 +208,6 @@ async function pushSignedCommits({ githubClient, owner, repo, branch, baseRef, c return undefined; } - if (signedCommits === false) { - core.info(`pushSignedCommits: signed-commits disabled, using git push directly for branch ${branch}`); - await exec.exec("git", ["push", "origin", branch], { - cwd, - env: { ...process.env, ...(gitAuthEnv || {}) }, - }); - const pushedSha = shas[shas.length - 1]; - core.info(`pushSignedCommits: git push completed with signed commits disabled, using pushed SHA ${pushedSha}`); - return pushedSha; - } - core.info(`pushSignedCommits: replaying ${shas.length} commit(s) via GraphQL createCommitOnBranch (branch: ${branch}, repo: ${owner}/${repo})`); try { @@ -419,10 +439,7 @@ async function pushSignedCommits({ githubClient, owner, repo, branch, baseRef, c ); } core.warning(`pushSignedCommits: GraphQL signed push failed, falling back to git push: ${err instanceof Error ? err.message : String(err)}`); - await exec.exec("git", ["push", "origin", branch], { - cwd, - env: { ...process.env, ...(gitAuthEnv || {}) }, - }); + await pushBranchWithGit({ branch, cwd, gitAuthEnv }); const fallbackSha = shas[shas.length - 1]; core.info(`pushSignedCommits: git push fallback completed, using pushed SHA ${fallbackSha}`); return fallbackSha; From 23e041f9707a3945fd988fe754b767542ba1961b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 15 May 2026 05:27:55 +0000 Subject: [PATCH 09/22] Address SOLID validation feedback Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- actions/setup/js/push_signed_commits.cjs | 30 ++++++++++++++++-------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/actions/setup/js/push_signed_commits.cjs b/actions/setup/js/push_signed_commits.cjs index 891c27b4e30..f0cf1209de0 100644 --- a/actions/setup/js/push_signed_commits.cjs +++ b/actions/setup/js/push_signed_commits.cjs @@ -1,6 +1,19 @@ // @ts-check /// +/** + * @fileoverview Signed Commit Push Helper + * + * Pushes local git commits to a remote branch using the GitHub GraphQL + * `createCommitOnBranch` mutation, so commits are cryptographically signed + * (verified) by GitHub. Falls back to a plain `git push` when the GraphQL + * approach is unavailable (e.g. GitHub Enterprise Server instances that do + * not support the mutation, or when branch-protection policies reject it). + * + * Both `create_pull_request.cjs` and `push_to_pull_request_branch.cjs` use + * this helper so the signed-commit logic lives in exactly one place. + */ + const { ERR_API } = require("./error_codes.cjs"); /** Sentinel error class used to signal that the commit range contains a shape @@ -146,17 +159,14 @@ async function resolveLocalHeadSha(cwd) { } /** - * @fileoverview Signed Commit Push Helper + * Returns true only when signed commit replay was explicitly disabled. * - * Pushes local git commits to a remote branch using the GitHub GraphQL - * `createCommitOnBranch` mutation, so commits are cryptographically signed - * (verified) by GitHub. Falls back to a plain `git push` when the GraphQL - * approach is unavailable (e.g. GitHub Enterprise Server instances that do - * not support the mutation, or when branch-protection policies reject it). - * - * Both `create_pull_request.cjs` and `push_to_pull_request_branch.cjs` use - * this helper so the signed-commit logic lives in exactly one place. + * @param {boolean} signedCommits + * @returns {boolean} */ +function shouldUseDirectGitPush(signedCommits) { + return signedCommits === false; +} /** * Pushes local commits to a remote branch using the GitHub GraphQL @@ -187,7 +197,7 @@ async function pushSignedCommits({ githubClient, owner, repo, branch, baseRef, c return headSha; } - if (signedCommits === false) { + if (shouldUseDirectGitPush(signedCommits)) { core.info(`pushSignedCommits: signed-commits disabled, using git push directly for branch ${branch}`); await pushBranchWithGit({ branch, cwd, gitAuthEnv }); const pushedSha = await resolveLocalHeadSha(cwd); From 947aa41eaa399862a36bb8588fd4489533dea8dd Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 15 May 2026 05:28:41 +0000 Subject: [PATCH 10/22] Clarify signed commit opt-out naming Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- actions/setup/js/push_signed_commits.cjs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/actions/setup/js/push_signed_commits.cjs b/actions/setup/js/push_signed_commits.cjs index f0cf1209de0..6fd06be8631 100644 --- a/actions/setup/js/push_signed_commits.cjs +++ b/actions/setup/js/push_signed_commits.cjs @@ -164,7 +164,7 @@ async function resolveLocalHeadSha(cwd) { * @param {boolean} signedCommits * @returns {boolean} */ -function shouldUseDirectGitPush(signedCommits) { +function isSignedCommitsExplicitlyDisabled(signedCommits) { return signedCommits === false; } @@ -197,12 +197,12 @@ async function pushSignedCommits({ githubClient, owner, repo, branch, baseRef, c return headSha; } - if (shouldUseDirectGitPush(signedCommits)) { + if (isSignedCommitsExplicitlyDisabled(signedCommits)) { core.info(`pushSignedCommits: signed-commits disabled, using git push directly for branch ${branch}`); await pushBranchWithGit({ branch, cwd, gitAuthEnv }); - const pushedSha = await resolveLocalHeadSha(cwd); - core.info(`pushSignedCommits: git push completed with signed commits disabled, using pushed SHA ${pushedSha}`); - return pushedSha; + const headSha = await resolveLocalHeadSha(cwd); + core.info(`pushSignedCommits: git push completed with signed commits disabled, using pushed SHA ${headSha}`); + return headSha; } // Collect the commits introduced (oldest-first) using topological order to ensure From 6569dc13b008b4ed707012a0b2fcd41127f532a8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 15 May 2026 05:29:24 +0000 Subject: [PATCH 11/22] Shorten signed commits predicate name Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- actions/setup/js/push_signed_commits.cjs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/actions/setup/js/push_signed_commits.cjs b/actions/setup/js/push_signed_commits.cjs index 6fd06be8631..570931cb3ce 100644 --- a/actions/setup/js/push_signed_commits.cjs +++ b/actions/setup/js/push_signed_commits.cjs @@ -164,7 +164,7 @@ async function resolveLocalHeadSha(cwd) { * @param {boolean} signedCommits * @returns {boolean} */ -function isSignedCommitsExplicitlyDisabled(signedCommits) { +function isSignedCommitsDisabled(signedCommits) { return signedCommits === false; } @@ -197,7 +197,7 @@ async function pushSignedCommits({ githubClient, owner, repo, branch, baseRef, c return headSha; } - if (isSignedCommitsExplicitlyDisabled(signedCommits)) { + if (isSignedCommitsDisabled(signedCommits)) { core.info(`pushSignedCommits: signed-commits disabled, using git push directly for branch ${branch}`); await pushBranchWithGit({ branch, cwd, gitAuthEnv }); const headSha = await resolveLocalHeadSha(cwd); From 72c1ae8fa5465bdb272d49e031acadac68e3152c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 15 May 2026 05:30:13 +0000 Subject: [PATCH 12/22] Clarify signed commit opt-out log Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- actions/setup/js/push_signed_commits.cjs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/actions/setup/js/push_signed_commits.cjs b/actions/setup/js/push_signed_commits.cjs index 570931cb3ce..f1d4c069fea 100644 --- a/actions/setup/js/push_signed_commits.cjs +++ b/actions/setup/js/push_signed_commits.cjs @@ -164,7 +164,7 @@ async function resolveLocalHeadSha(cwd) { * @param {boolean} signedCommits * @returns {boolean} */ -function isSignedCommitsDisabled(signedCommits) { +function isSignedCommitReplayOptedOut(signedCommits) { return signedCommits === false; } @@ -197,11 +197,11 @@ async function pushSignedCommits({ githubClient, owner, repo, branch, baseRef, c return headSha; } - if (isSignedCommitsDisabled(signedCommits)) { + if (isSignedCommitReplayOptedOut(signedCommits)) { core.info(`pushSignedCommits: signed-commits disabled, using git push directly for branch ${branch}`); await pushBranchWithGit({ branch, cwd, gitAuthEnv }); const headSha = await resolveLocalHeadSha(cwd); - core.info(`pushSignedCommits: git push completed with signed commits disabled, using pushed SHA ${headSha}`); + core.info(`pushSignedCommits: git push completed with signed commits disabled, using local HEAD SHA ${headSha}`); return headSha; } From 70ffc73168392a5a6940928f91666dcc4850ec01 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 15 May 2026 05:31:02 +0000 Subject: [PATCH 13/22] Document unsigned push HEAD resolution Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- actions/setup/js/push_signed_commits.cjs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/actions/setup/js/push_signed_commits.cjs b/actions/setup/js/push_signed_commits.cjs index f1d4c069fea..f185d4649c6 100644 --- a/actions/setup/js/push_signed_commits.cjs +++ b/actions/setup/js/push_signed_commits.cjs @@ -164,7 +164,7 @@ async function resolveLocalHeadSha(cwd) { * @param {boolean} signedCommits * @returns {boolean} */ -function isSignedCommitReplayOptedOut(signedCommits) { +function shouldSkipSignedCommitReplay(signedCommits) { return signedCommits === false; } @@ -197,9 +197,11 @@ async function pushSignedCommits({ githubClient, owner, repo, branch, baseRef, c return headSha; } - if (isSignedCommitReplayOptedOut(signedCommits)) { + if (shouldSkipSignedCommitReplay(signedCommits)) { core.info(`pushSignedCommits: signed-commits disabled, using git push directly for branch ${branch}`); await pushBranchWithGit({ branch, cwd, gitAuthEnv }); + // git push sends the currently checked-out branch tip; after it succeeds, + // local HEAD is the SHA that landed on the remote branch. const headSha = await resolveLocalHeadSha(cwd); core.info(`pushSignedCommits: git push completed with signed commits disabled, using local HEAD SHA ${headSha}`); return headSha; From cf4309faed5cd4dd6898a201631af90f8a345914 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 15 May 2026 05:31:48 +0000 Subject: [PATCH 14/22] Simplify unsigned push logging Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- actions/setup/js/push_signed_commits.cjs | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/actions/setup/js/push_signed_commits.cjs b/actions/setup/js/push_signed_commits.cjs index f185d4649c6..a02a01c7ecd 100644 --- a/actions/setup/js/push_signed_commits.cjs +++ b/actions/setup/js/push_signed_commits.cjs @@ -158,16 +158,6 @@ async function resolveLocalHeadSha(cwd) { return stdout.trim(); } -/** - * Returns true only when signed commit replay was explicitly disabled. - * - * @param {boolean} signedCommits - * @returns {boolean} - */ -function shouldSkipSignedCommitReplay(signedCommits) { - return signedCommits === false; -} - /** * Pushes local commits to a remote branch using the GitHub GraphQL * `createCommitOnBranch` mutation so commits are cryptographically signed. @@ -197,13 +187,13 @@ async function pushSignedCommits({ githubClient, owner, repo, branch, baseRef, c return headSha; } - if (shouldSkipSignedCommitReplay(signedCommits)) { + if (signedCommits === false) { core.info(`pushSignedCommits: signed-commits disabled, using git push directly for branch ${branch}`); await pushBranchWithGit({ branch, cwd, gitAuthEnv }); // git push sends the currently checked-out branch tip; after it succeeds, // local HEAD is the SHA that landed on the remote branch. const headSha = await resolveLocalHeadSha(cwd); - core.info(`pushSignedCommits: git push completed with signed commits disabled, using local HEAD SHA ${headSha}`); + core.info(`pushSignedCommits: git push completed, HEAD=${headSha}`); return headSha; } From 885fa6f4596996b058e8e15448022726947634fb Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 15 May 2026 05:32:43 +0000 Subject: [PATCH 15/22] Consolidate unsigned push documentation Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- actions/setup/js/push_signed_commits.cjs | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/actions/setup/js/push_signed_commits.cjs b/actions/setup/js/push_signed_commits.cjs index a02a01c7ecd..06654351249 100644 --- a/actions/setup/js/push_signed_commits.cjs +++ b/actions/setup/js/push_signed_commits.cjs @@ -1,19 +1,6 @@ // @ts-check /// -/** - * @fileoverview Signed Commit Push Helper - * - * Pushes local git commits to a remote branch using the GitHub GraphQL - * `createCommitOnBranch` mutation, so commits are cryptographically signed - * (verified) by GitHub. Falls back to a plain `git push` when the GraphQL - * approach is unavailable (e.g. GitHub Enterprise Server instances that do - * not support the mutation, or when branch-protection policies reject it). - * - * Both `create_pull_request.cjs` and `push_to_pull_request_branch.cjs` use - * this helper so the signed-commit logic lives in exactly one place. - */ - const { ERR_API } = require("./error_codes.cjs"); /** Sentinel error class used to signal that the commit range contains a shape @@ -133,6 +120,8 @@ async function readBlobAsBase64(blobHash, cwd) { /** * Push the local branch to origin using git directly. + * git push sends the currently checked-out branch tip; after it succeeds, + * local HEAD is the SHA that landed on the remote branch. * * @param {object} opts * @param {string} opts.branch @@ -190,8 +179,6 @@ async function pushSignedCommits({ githubClient, owner, repo, branch, baseRef, c if (signedCommits === false) { core.info(`pushSignedCommits: signed-commits disabled, using git push directly for branch ${branch}`); await pushBranchWithGit({ branch, cwd, gitAuthEnv }); - // git push sends the currently checked-out branch tip; after it succeeds, - // local HEAD is the SHA that landed on the remote branch. const headSha = await resolveLocalHeadSha(cwd); core.info(`pushSignedCommits: git push completed, HEAD=${headSha}`); return headSha; From a5b4bf970997123dddcbc4600d0355aecc05ec1d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 15 May 2026 05:33:37 +0000 Subject: [PATCH 16/22] Clarify direct push helper docs Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- actions/setup/js/push_signed_commits.cjs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/actions/setup/js/push_signed_commits.cjs b/actions/setup/js/push_signed_commits.cjs index 06654351249..13217fb88d8 100644 --- a/actions/setup/js/push_signed_commits.cjs +++ b/actions/setup/js/push_signed_commits.cjs @@ -120,8 +120,8 @@ async function readBlobAsBase64(blobHash, cwd) { /** * Push the local branch to origin using git directly. - * git push sends the currently checked-out branch tip; after it succeeds, - * local HEAD is the SHA that landed on the remote branch. + * This only performs the push; callers resolve HEAD separately when they need + * the resulting branch tip SHA. * * @param {object} opts * @param {string} opts.branch @@ -176,6 +176,7 @@ async function pushSignedCommits({ githubClient, owner, repo, branch, baseRef, c return headSha; } + // Only an explicit false opts out of signed commit replay; unset/default values keep it enabled. if (signedCommits === false) { core.info(`pushSignedCommits: signed-commits disabled, using git push directly for branch ${branch}`); await pushBranchWithGit({ branch, cwd, gitAuthEnv }); From f006c79a5d67f22a6f0c52831d09463272a01303 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 15 May 2026 05:34:32 +0000 Subject: [PATCH 17/22] Combine direct push head resolution Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- actions/setup/js/push_signed_commits.cjs | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/actions/setup/js/push_signed_commits.cjs b/actions/setup/js/push_signed_commits.cjs index 13217fb88d8..a96911c9c36 100644 --- a/actions/setup/js/push_signed_commits.cjs +++ b/actions/setup/js/push_signed_commits.cjs @@ -119,21 +119,21 @@ async function readBlobAsBase64(blobHash, cwd) { } /** - * Push the local branch to origin using git directly. - * This only performs the push; callers resolve HEAD separately when they need - * the resulting branch tip SHA. + * Push the local branch to origin using git directly and return the local HEAD + * SHA that landed on the remote branch. * * @param {object} opts * @param {string} opts.branch * @param {string} opts.cwd * @param {object} [opts.gitAuthEnv] - * @returns {Promise} + * @returns {Promise} */ -async function pushBranchWithGit({ branch, cwd, gitAuthEnv }) { +async function pushBranchAndResolveHead({ branch, cwd, gitAuthEnv }) { await exec.exec("git", ["push", "origin", branch], { cwd, env: { ...process.env, ...(gitAuthEnv || {}) }, }); + return resolveLocalHeadSha(cwd); } /** @@ -170,8 +170,7 @@ async function pushSignedCommits({ githubClient, owner, repo, branch, baseRef, c // so skip it entirely and fall directly through to git push. if (!baseRef) { core.info(`pushSignedCommits: empty baseRef detected (orphan branch first push), using git push directly for branch ${branch}`); - await pushBranchWithGit({ branch, cwd, gitAuthEnv }); - const headSha = await resolveLocalHeadSha(cwd); + const headSha = await pushBranchAndResolveHead({ branch, cwd, gitAuthEnv }); core.info(`pushSignedCommits: git push completed for orphan branch, HEAD=${headSha}`); return headSha; } @@ -179,8 +178,7 @@ async function pushSignedCommits({ githubClient, owner, repo, branch, baseRef, c // Only an explicit false opts out of signed commit replay; unset/default values keep it enabled. if (signedCommits === false) { core.info(`pushSignedCommits: signed-commits disabled, using git push directly for branch ${branch}`); - await pushBranchWithGit({ branch, cwd, gitAuthEnv }); - const headSha = await resolveLocalHeadSha(cwd); + const headSha = await pushBranchAndResolveHead({ branch, cwd, gitAuthEnv }); core.info(`pushSignedCommits: git push completed, HEAD=${headSha}`); return headSha; } @@ -429,8 +427,7 @@ async function pushSignedCommits({ githubClient, owner, repo, branch, baseRef, c ); } core.warning(`pushSignedCommits: GraphQL signed push failed, falling back to git push: ${err instanceof Error ? err.message : String(err)}`); - await pushBranchWithGit({ branch, cwd, gitAuthEnv }); - const fallbackSha = shas[shas.length - 1]; + const fallbackSha = await pushBranchAndResolveHead({ branch, cwd, gitAuthEnv }); core.info(`pushSignedCommits: git push fallback completed, using pushed SHA ${fallbackSha}`); return fallbackSha; } From dfdd57538edb3d7461ae2ae1ffda7006bc4db94f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 15 May 2026 05:35:22 +0000 Subject: [PATCH 18/22] Prioritize unsigned push opt-out Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- actions/setup/js/push_signed_commits.cjs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/actions/setup/js/push_signed_commits.cjs b/actions/setup/js/push_signed_commits.cjs index a96911c9c36..58c24fd1568 100644 --- a/actions/setup/js/push_signed_commits.cjs +++ b/actions/setup/js/push_signed_commits.cjs @@ -120,7 +120,7 @@ async function readBlobAsBase64(blobHash, cwd) { /** * Push the local branch to origin using git directly and return the local HEAD - * SHA that landed on the remote branch. + * SHA after the push succeeds. * * @param {object} opts * @param {string} opts.branch @@ -164,6 +164,14 @@ async function resolveLocalHeadSha(cwd) { * @returns {Promise} SHA of the commit that landed on the target branch */ async function pushSignedCommits({ githubClient, owner, repo, branch, baseRef, cwd, gitAuthEnv, signedCommits = true }) { + // Only an explicit false opts out of signed commit replay; unset/default values keep it enabled. + if (signedCommits === false) { + core.info(`pushSignedCommits: signed-commits disabled, using git push directly for branch ${branch}`); + const headSha = await pushBranchAndResolveHead({ branch, cwd, gitAuthEnv }); + core.info(`pushSignedCommits: git push completed, HEAD=${headSha}`); + return headSha; + } + // Orphan branch first push: baseRef is "" when push_experiment_state creates a brand-new // branch for the first time (checkoutOrCreateBranch returns "" for new branches). // The GraphQL createCommitOnBranch path cannot handle root commits (no parent to resolve), @@ -175,14 +183,6 @@ async function pushSignedCommits({ githubClient, owner, repo, branch, baseRef, c return headSha; } - // Only an explicit false opts out of signed commit replay; unset/default values keep it enabled. - if (signedCommits === false) { - core.info(`pushSignedCommits: signed-commits disabled, using git push directly for branch ${branch}`); - const headSha = await pushBranchAndResolveHead({ branch, cwd, gitAuthEnv }); - core.info(`pushSignedCommits: git push completed, HEAD=${headSha}`); - return headSha; - } - // Collect the commits introduced (oldest-first) using topological order to ensure // correct sequencing even when commit dates are out of sync (e.g. after rebase --committer-date-is-author-date). // Using --parents emits each line as " [ ...]", which lets us detect merge commits From eb58f064cf0374647adc482b6cabc26839783f26 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 15 May 2026 05:36:10 +0000 Subject: [PATCH 19/22] Clarify signed push helper docs Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- actions/setup/js/push_signed_commits.cjs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/actions/setup/js/push_signed_commits.cjs b/actions/setup/js/push_signed_commits.cjs index 58c24fd1568..f7d1dea5903 100644 --- a/actions/setup/js/push_signed_commits.cjs +++ b/actions/setup/js/push_signed_commits.cjs @@ -1,6 +1,12 @@ // @ts-check /// +/** + * @fileoverview Shared helper for pushing local commits either through + * GitHub's signed-commit GraphQL API or, when explicitly configured, direct + * `git push`. + */ + const { ERR_API } = require("./error_codes.cjs"); /** Sentinel error class used to signal that the commit range contains a shape @@ -164,7 +170,7 @@ async function resolveLocalHeadSha(cwd) { * @returns {Promise} SHA of the commit that landed on the target branch */ async function pushSignedCommits({ githubClient, owner, repo, branch, baseRef, cwd, gitAuthEnv, signedCommits = true }) { - // Only an explicit false opts out of signed commit replay; unset/default values keep it enabled. + // The default parameter converts missing/undefined values to true; only explicit false disables signed commit replay. if (signedCommits === false) { core.info(`pushSignedCommits: signed-commits disabled, using git push directly for branch ${branch}`); const headSha = await pushBranchAndResolveHead({ branch, cwd, gitAuthEnv }); From ee10dbb8145ede88a252104fd1e684cd3e2b1ce1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 15 May 2026 05:37:04 +0000 Subject: [PATCH 20/22] Tighten unsigned push wording Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- actions/setup/js/push_signed_commits.cjs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/actions/setup/js/push_signed_commits.cjs b/actions/setup/js/push_signed_commits.cjs index f7d1dea5903..67b70fbb97e 100644 --- a/actions/setup/js/push_signed_commits.cjs +++ b/actions/setup/js/push_signed_commits.cjs @@ -170,11 +170,11 @@ async function resolveLocalHeadSha(cwd) { * @returns {Promise} SHA of the commit that landed on the target branch */ async function pushSignedCommits({ githubClient, owner, repo, branch, baseRef, cwd, gitAuthEnv, signedCommits = true }) { - // The default parameter converts missing/undefined values to true; only explicit false disables signed commit replay. + // The default parameter converts undefined to true; only explicit false disables signed commit replay. if (signedCommits === false) { core.info(`pushSignedCommits: signed-commits disabled, using git push directly for branch ${branch}`); const headSha = await pushBranchAndResolveHead({ branch, cwd, gitAuthEnv }); - core.info(`pushSignedCommits: git push completed, HEAD=${headSha}`); + core.info(`pushSignedCommits: git push and HEAD resolution completed, HEAD=${headSha}`); return headSha; } From 73b13b021cf3675a1bf323fc4f64f64d21982368 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 15 May 2026 05:38:15 +0000 Subject: [PATCH 21/22] Align unsigned push test logging Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- actions/setup/js/push_signed_commits.cjs | 4 ++-- actions/setup/js/push_signed_commits.test.cjs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/actions/setup/js/push_signed_commits.cjs b/actions/setup/js/push_signed_commits.cjs index 67b70fbb97e..b87caa43b5b 100644 --- a/actions/setup/js/push_signed_commits.cjs +++ b/actions/setup/js/push_signed_commits.cjs @@ -170,9 +170,9 @@ async function resolveLocalHeadSha(cwd) { * @returns {Promise} SHA of the commit that landed on the target branch */ async function pushSignedCommits({ githubClient, owner, repo, branch, baseRef, cwd, gitAuthEnv, signedCommits = true }) { - // The default parameter converts undefined to true; only explicit false disables signed commit replay. + // The default parameter value converts undefined to true; this check tests only the explicit false value. if (signedCommits === false) { - core.info(`pushSignedCommits: signed-commits disabled, using git push directly for branch ${branch}`); + core.info(`pushSignedCommits: signed-commits disabled (using direct git push) for branch ${branch}`); const headSha = await pushBranchAndResolveHead({ branch, cwd, gitAuthEnv }); core.info(`pushSignedCommits: git push and HEAD resolution completed, HEAD=${headSha}`); return headSha; diff --git a/actions/setup/js/push_signed_commits.test.cjs b/actions/setup/js/push_signed_commits.test.cjs index e7dc36c4c59..3faf33a376b 100644 --- a/actions/setup/js/push_signed_commits.test.cjs +++ b/actions/setup/js/push_signed_commits.test.cjs @@ -1156,7 +1156,7 @@ describe("push_signed_commits integration tests", () => { expect(pushedSha).toBe(expectedHead); expect(githubClient.graphql).not.toHaveBeenCalled(); expect(execGit(["rev-parse", "refs/heads/unsigned-merge-test-branch"], { cwd: bareDir }).stdout.trim()).toBe(expectedHead); - expect(mockCore.info).toHaveBeenCalledWith("pushSignedCommits: signed-commits disabled, using git push directly for branch unsigned-merge-test-branch"); + expect(mockCore.info).toHaveBeenCalledWith("pushSignedCommits: signed-commits disabled (using direct git push) for branch unsigned-merge-test-branch"); }); it("should not trigger merge-commit fallback for a commit message that starts with 'parent '", async () => { From a39a17c8777cc4667b5bb00ead7f89f35ad3c42b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 15 May 2026 05:53:15 +0000 Subject: [PATCH 22/22] Fix JS lint formatting Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- actions/setup/js/update_pull_request.cjs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/actions/setup/js/update_pull_request.cjs b/actions/setup/js/update_pull_request.cjs index 3da5866e153..adac21ada2c 100644 --- a/actions/setup/js/update_pull_request.cjs +++ b/actions/setup/js/update_pull_request.cjs @@ -26,7 +26,10 @@ function isNonFatalUpdateBranchError(error) { /** @type {number | undefined} */ let status; if (typeof error === "object" && error !== null && "status" in error) { - status = /** @type {{status?: number}} */ (error).status; + const candidateStatus = error.status; + if (typeof candidateStatus === "number") { + status = candidateStatus; + } } if (status !== undefined && status !== 422) { return false;