fix(auto_submit): pin release-branch direct merge to the validated head sha#5105
fix(auto_submit): pin release-branch direct merge to the validated head sha#5105mohammadmseet-hue wants to merge 1 commit into
Conversation
…ad sha The auto-submit direct-merge path (used for non-merge-queue repos and for release/candidate branches) validated a pull request's head commit and then merged the PR by number without pinning the commit it had just validated. A push that landed a new head in the gap between validation and merge would be merged unvalidated, because the GitHub merge call resolves the current head rather than the validated SHA and the retry loop re-issues against it. The requestSha head-pin was already plumbed through _processMergeInternal and GithubService.mergePullRequest down to github.pullRequests.merge; it was simply never supplied on this path. Pass the validated head sha so GitHub rejects the merge (HTTP 405) if the head has since moved. The merge-queue path is unchanged because it re-runs required checks on the integrated head. Adds a regression test asserting the direct-merge call carries the validated head sha, and records requestSha in FakeGithubService to enable it.
There was a problem hiding this comment.
Code Review
This pull request updates the auto-submit service to pin direct merges to the exact validated head SHA, preventing unvalidated commits from being merged if the head changes between validation and merging. This is achieved by passing the head SHA as requestSha to the merge request, with corresponding tests and mock service updates added to verify this behavior. The feedback suggests using the conditional access operator ?. instead of the null assertion operator ! on pullRequest.head to avoid potential runtime exceptions, as the target parameter is nullable.
| number, | ||
| commitMessage, | ||
| slug, | ||
| pullRequest.head!.sha, |
There was a problem hiding this comment.
Using the null assertion operator ! on pullRequest.head can cause a runtime exception if head is null. Since _mergePullRequest accepts a nullable String? requestSha, it is safer and more idiomatic to use the conditional access operator ?. instead.
| pullRequest.head!.sha, | |
| pullRequest.head?.sha, |
|
There needs to be an issue filed for this before we can review it. |
|
Dear @jtmcdole , I filed one under https://issuetracker.google.com/issues/529477828 Kindly check it |
That's not the flutter/flutter issue tracker. |
What this fixes
The auto-submit direct-merge path merges a validated pull request by number without pinning the commit it just validated, so a head that changes between validation and merge is merged unvalidated.
ValidationService.submitPullRequestroutesmain/masterPRs to the GitHub merge queue (which re-runs required checks on the integrated head) but sends every other branch — includingrelease/candidatebranches — to a direct merge via_mergePullRequest:validation_service.dartif (pullRequest.isMergeQueueEnabled) { _enqueuePullRequest(...) } else { _mergePullRequest(...) }isMergeQueueEnabledisfalsefor anybaseRef != 'main' && baseRef != 'master'_mergePullRequest→_processMergeInternal→GithubService.mergePullRequest→github.pullRequests.mergeall accept arequestShahead-pin (GitHub merges only if the current head equals that SHA), but_mergePullRequestnever supplied it, and the 5-attempt retry loop re-issues the merge against whatever the current head is.Net effect: Cocoon validates
pullRequest.head.shabut does not bind the merge to it on the direct-merge path. A push that lands a new commit during the singleprocessMessagevalidate→merge window is merged by the in-flight run. On arelease/candidatebranch this lands a commit that was never reviewed or validated.The fix
Supply the validated head sha as
requestShaon the direct-merge path. When the head has moved, GitHub rejects the merge (HTTP 405, "Head branch was modified") and the PR is left for re-validation. The merge-queue path is unchanged because it already re-runs required checks on the integrated head.The
requestShaparameter was already plumbed end-to-end; this change just passes it.Tests
Direct merge is pinned to the validated head shaasserts the direct-merge call carries the PR's validated head sha.FakeGithubServicenow recordsrequestSha.requestSha == null) and passes with the fix.dart test test/service/pull_request_validation_service_test.dart→ all pass.dart test test/service/github_service_test.dart→ all pass.dart analyzeon the changed files → no issues.Pre-launch Checklist
///).