Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 30 additions & 2 deletions .github/workflows/code-scanning-fixer.lock.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 9 additions & 6 deletions actions/setup/js/update_pull_request.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ function isNonFatalUpdateBranchError(error) {
if (status === 403 && (hasWorkflowsPermissionError || hasWorkflowsScopeRequired)) {
return true;
}
if (status !== 422) {
if (status !== 422 && !message.includes("head ref does not exist")) {
return false;
}
}
Expand All @@ -62,12 +62,15 @@ function isNonFatalUpdateBranchError(error) {
// - cannot auto-update due to conflict ("merge conflict between base and head")
// - stale merged targets where the head branch was deleted ("head ref does not exist")
// These should not fail safe output processing.
// Restrict to status === 422 to avoid silently swallowing the same phrases from proxy/network
// errors that lack a numeric status. hasWorkflowsPermissionError / hasWorkflowsScopeRequired
// are only checked for errors with no numeric status (status === undefined); the explicit 403
// case is already handled by the if-block above.
// A deleted head ref is a stale target regardless of which numeric status the API/proxy reports.
// Keep requiring some numeric status so transport/proxy failures with no HTTP response still fail.
// Restrict the other phrases to status === 422 to avoid silently swallowing proxy/network
// errors. hasWorkflowsPermissionError / hasWorkflowsScopeRequired are only checked for errors
// with no numeric status (status === undefined); the explicit 403 case is already handled by
// the if-block above.
return (
(status === 422 && (message.includes("there are no new commits on the base branch") || message.includes("merge conflict between base and head") || message.includes("head ref does not exist"))) ||
(status !== undefined && message.includes("head ref does not exist")) ||
(status === 422 && (message.includes("there are no new commits on the base branch") || message.includes("merge conflict between base and head"))) ||
((hasWorkflowsPermissionError || hasWorkflowsScopeRequired) && status === undefined)
);
}
Expand Down
18 changes: 16 additions & 2 deletions actions/setup/js/update_pull_request.test.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -960,17 +960,31 @@ describe("update_pull_request.cjs - update_branch behavior", () => {
expect(mockCore.warning).toHaveBeenCalledWith(expect.stringContaining("branch from base (non-fatal)"));
});

it("should treat head-ref-missing as fatal when updateBranch returns a non-422 status", async () => {
it("should treat head-ref-missing as non-fatal regardless of updateBranch status", async () => {
const unexpectedStatusError = new Error("head ref does not exist - https://docs.github.com/rest/pulls/pulls#update-a-pull-request-branch");
unexpectedStatusError.status = 404;
mockGithub.rest.pulls.updateBranch.mockRejectedValueOnce(unexpectedStatusError);

const handler = await updatePRModule.main({ update_branch: true });
const result = await handler({ pull_request_number: 100 });

expect(result.success).toBe(false);
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 keep head-ref-missing fatal when updateBranch has no numeric status", async () => {
const missingStatusError = new Error("head ref does not exist - https://docs.github.com/rest/pulls/pulls#update-a-pull-request-branch");
mockGithub.rest.pulls.updateBranch.mockRejectedValueOnce(missingStatusError);

const handler = await updatePRModule.main({ update_branch: true });
const result = await handler({ pull_request_number: 100 });

expect(result.success).toBe(false);
expect(result.error).toContain("update pull request #100 branch from base failed");
expect(mockGithub.rest.pulls.updateBranch).toHaveBeenCalledTimes(1);
expect(mockCore.warning).toHaveBeenCalledWith(expect.not.stringContaining("(non-fatal)"));
});

it("should continue title/body updates when updateBranch gets workflows-permission 403", async () => {
Expand Down
Loading