From efcfa27bafb88d4bbf1d99bcea3659d056ad6581 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 25 Jul 2026 08:53:44 +0000 Subject: [PATCH 1/2] Initial plan From 7ae5abdf2055004aaf33023b0b986d5106771435 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 25 Jul 2026 09:03:51 +0000 Subject: [PATCH 2/2] Soft-fail verified-signatures PR branch updates Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- actions/setup/js/update_pull_request.cjs | 5 ++- actions/setup/js/update_pull_request.test.cjs | 36 +++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/actions/setup/js/update_pull_request.cjs b/actions/setup/js/update_pull_request.cjs index a80344b526d..dcdca3b020e 100644 --- a/actions/setup/js/update_pull_request.cjs +++ b/actions/setup/js/update_pull_request.cjs @@ -38,6 +38,7 @@ function isNonFatalUpdateBranchError(error) { // Require both permission wording and update-branch context to avoid treating unrelated // "workflows permission" errors as non-fatal for pull request branch updates. const hasWorkflowsPermissionError = hasWorkflowsPermissionPhrase && (hasWorkflowMutationRefusal || message.includes("update pull request")); + const hasVerifiedSignaturesRuleViolation = message.includes("repository rule violations found") && /commits?\s+must\s+have\s+verified\s+signatures\b/i.test(message); if (status !== undefined) { if (status === 403 && hasWorkflowsPermissionError) { @@ -51,8 +52,10 @@ function isNonFatalUpdateBranchError(error) { // GitHub update-branch API can return these 422 messages for benign conditions: // - already up to date ("There are no new commits on the base branch") // - cannot auto-update due to conflict ("merge conflict between base and head") + // - branch protection/ruleset refusal when the synthetic merge commit would be unsigned + // ("Repository rule violations found" + "Commits must have verified signatures") // These should not fail safe output processing. - return message.includes("there are no new commits on the base branch") || message.includes("merge conflict between base and head") || hasWorkflowsPermissionError; + return message.includes("there are no new commits on the base branch") || message.includes("merge conflict between base and head") || hasWorkflowsPermissionError || hasVerifiedSignaturesRuleViolation; } /** diff --git a/actions/setup/js/update_pull_request.test.cjs b/actions/setup/js/update_pull_request.test.cjs index 6fb5e16ae11..7f2ad8f7cd8 100644 --- a/actions/setup/js/update_pull_request.test.cjs +++ b/actions/setup/js/update_pull_request.test.cjs @@ -941,4 +941,40 @@ describe("update_pull_request.cjs - update_branch behavior", () => { }); expect(mockCore.warning).toHaveBeenCalledWith(expect.stringContaining("branch from base (non-fatal)")); }); + + it("should treat verified-signatures ruleset rejection as non-fatal for update-branch-only requests", async () => { + const ruleViolationError = new Error("Repository rule violations found\n\nCommits must have verified signatures."); + ruleViolationError.status = 422; + mockGithub.rest.pulls.updateBranch.mockRejectedValueOnce(ruleViolationError); + + const handler = await updatePRModule.main({ update_branch: true }); + const result = await handler({ pull_request_number: 100 }); + + expect(result.success).toBe(true); + expect(mockGithub.rest.pulls.updateBranch).toHaveBeenCalledTimes(1); + expect(mockGithub.rest.pulls.update).not.toHaveBeenCalled(); + expect(mockCore.warning).toHaveBeenCalledWith(expect.stringContaining("branch from base (non-fatal)")); + }); + + it("should continue title/body updates when updateBranch hits verified-signatures ruleset rejection", async () => { + const ruleViolationError = new Error("Repository rule violations found\n\nCommits must have verified signatures."); + ruleViolationError.status = 422; + mockGithub.rest.pulls.updateBranch.mockRejectedValueOnce(ruleViolationError); + + const handler = await updatePRModule.main({ update_branch: true }); + const result = await handler({ + pull_request_number: 100, + title: "Updated PR", + }); + + expect(result.success).toBe(true); + expect(mockGithub.rest.pulls.updateBranch).toHaveBeenCalledTimes(1); + expect(mockGithub.rest.pulls.update).toHaveBeenCalledWith({ + owner: "testowner", + repo: "testrepo", + pull_number: 100, + title: "Updated PR", + }); + expect(mockCore.warning).toHaveBeenCalledWith(expect.stringContaining("branch from base (non-fatal)")); + }); });