Skip to content

fix(auto_submit): pin release-branch direct merge to the validated head sha#5105

Open
mohammadmseet-hue wants to merge 1 commit into
flutter:mainfrom
mohammadmseet-hue:fix-autosubmit-toctou-head-pin
Open

fix(auto_submit): pin release-branch direct merge to the validated head sha#5105
mohammadmseet-hue wants to merge 1 commit into
flutter:mainfrom
mohammadmseet-hue:fix-autosubmit-toctou-head-pin

Conversation

@mohammadmseet-hue

Copy link
Copy Markdown

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.submitPullRequest routes main/master PRs to the GitHub merge queue (which re-runs required checks on the integrated head) but sends every other branch — including release/candidate branches — to a direct merge via _mergePullRequest:

  • routing: validation_service.dart if (pullRequest.isMergeQueueEnabled) { _enqueuePullRequest(...) } else { _mergePullRequest(...) }
  • isMergeQueueEnabled is false for any baseRef != 'main' && baseRef != 'master'

_mergePullRequest_processMergeInternalGithubService.mergePullRequestgithub.pullRequests.merge all accept a requestSha head-pin (GitHub merges only if the current head equals that SHA), but _mergePullRequest never supplied it, and the 5-attempt retry loop re-issues the merge against whatever the current head is.

Net effect: Cocoon validates pullRequest.head.sha but does not bind the merge to it on the direct-merge path. A push that lands a new commit during the single processMessage validate→merge window is merged by the in-flight run. On a release/candidate branch this lands a commit that was never reviewed or validated.

The fix

Supply the validated head sha as requestSha on 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 requestSha parameter was already plumbed end-to-end; this change just passes it.

Tests

  • New regression test Direct merge is pinned to the validated head sha asserts the direct-merge call carries the PR's validated head sha. FakeGithubService now records requestSha.
  • Verified the new test fails on the unpatched code (merge issued with 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 analyze on the changed files → no issues.

Pre-launch Checklist

  • I read the Contributor Guide and followed the process outlined there for submitting PRs.
  • I signed the CLA.
  • I updated/added relevant documentation (doc comments with ///).
  • All existing and new tests are passing.

…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.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

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.

Suggested change
pullRequest.head!.sha,
pullRequest.head?.sha,

@jtmcdole

Copy link
Copy Markdown
Member

There needs to be an issue filed for this before we can review it.

@mohammadmseet-hue

Copy link
Copy Markdown
Author

Dear @jtmcdole ,

I filed one under https://issuetracker.google.com/issues/529477828

Kindly check it

@jtmcdole

Copy link
Copy Markdown
Member

Dear @jtmcdole ,

I filed one under https://issuetracker.google.com/issues/529477828

Kindly check it

That's not the flutter/flutter issue tracker.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants