-
-
Notifications
You must be signed in to change notification settings - Fork 254
ci: Check if any PRs in the merge queue affect a release #7114
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
| needs: check-workflows | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - name: Check if the commit or pull request is a release |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I considered reusing the is-release job below, but it adds a little bit of complexity around the conditionals, and we don't need the extra options below for merged commits.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: We could maybe skip this for push events? Just because it wouldn't be relevant anymore for push, and this might make it a bit more clear why we have to similarly-named jobs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could skip the individual steps on push, but not the job itself, since that would cause all-jobs-complete to be skipped.
| uses: MetaMask/action-is-release@d063725cd15ee145d7e795a2e77db31a3e3f2c92 | ||
| with: | ||
| commit-starts-with: 'Release [version],Release v[version],Release/[version],Release/v[version],Release `[version]`' | ||
| commit-message: ${{ github.event.pull_request.title }} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is used so we can determine if an unmerged pull request is a release pull request. github.event.pull_request.title is not defined for other events (push and merge_group), so doesn't affect those.
.github/workflows/main.yml
Outdated
| with: | ||
| commit-starts-with: 'Release [version],Release v[version],Release/[version],Release/v[version],Release `[version]`' | ||
| commit-message: ${{ github.event.pull_request.title }} | ||
| before: ${{ github.event.pull_request.base.sha || github.event.merge_group.base_sha || github.event.before }} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
github.event.before is only defined on push, not on pull_request or merge_group, so I had to add this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
base.sha doesn't seem correct here.
In the action-is-release action, we used github.event.before to get the diff of what changed in a given commit, to check whether the version number had changed. For the push event, the diff betweeen github.event.before and the current commit would only include changes from that push event.
Whereas base.sha refers to the commit on the base branch that the PR was originally branched from. It does not get updated when the branch is updated with a merge commit. That means if a core release goes out while a PR is open, github.event.pull_request.base.sha..HEAD will include a version bump from the unrelated core release on main.
Instead I think we need the merge-base here, between the base branch and the current commit
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Either that, or get the merge-base in action-is-release instead
| needs: check-workflows | ||
| uses: ./.github/workflows/lint-build-test.yml | ||
|
|
||
| check-release: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't add a conditional here, but only to the step below. This way we can add check-release as dependency to all-jobs-complete. Otherwise, if check-release (the job) is skipped, all-jobs-complete would be skipped too.
| done | ||
| # Get all files changed ahead of this PR. | ||
| git diff --name-only "$BEFORE..$(git merge-base HEAD refs/remotes/origin/main)" > changed-files.txt |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From my understanding, git merge-base HEAD refs/remotes/origin/main finds the common ancestor between HEAD (i.e., the current commit), and origin/main. We can then diff $BEFORE with that to find any differences on main not included in the current branch.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is an action rather than a workflow to support the uses syntax in a step, rather than as a job. It's related to this comment.
d677951 to
56f08cb
Compare
| # Get all packages being released in this PR | ||
| for package in "${PACKAGES[@]}"; do | ||
| MAIN_VERSION=$(git show "refs/remotes/origin/main:$package" | jq -r .version) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comparison doesn't seem quite right. We're using origin/main as the "before the current commit" comparison point, but there might be more changes in-between origin/main and the current commit. e.g. if there is a release PR queued before the current one
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| if: github.event_name != 'push' && steps.is-release.outputs.IS_RELEASE == 'true' | ||
| uses: ./.github/actions/check-release | ||
| with: | ||
| before: ${{ github.event.pull_request.base.sha || github.event.merge_group.base_sha }} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bug: Merge Queue Conflict Blind Spot
Using github.event.pull_request.base.sha or github.event.merge_group.base_sha as the before parameter doesn't capture changes from other PRs in the merge queue. These values represent the base branch commit when the PR was created, not the current state including queued changes. This means the release conflict check won't detect conflicts with other PRs ahead in the merge queue, defeating the purpose of checking merge queue conflicts.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cursor didn't explain this super well, but, I think this comment is at least partially accurate.
If you didn't use any merge commits, base.sha is exactly what we want here I think (at least for the pull_request event, not 100% sure on merge_group), but merges break that assumption.
Essentially what we want to compare in check-release is the previous merge base with the current merge base. We want to compare a merge base for both sides of the comparison.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the merge_group event, would base.sha refer to the previous commit in the queue itself? Even the merge-base of base.sha might not refer to the correct commit if that's the case.
We might need to consider something like.... grab the PR number from the merge-queue branch name, fetch the branch for that PR, then get the merge-base of that branch.
I found a discussion where someone talked about how to get the PR number from the merge queue branch name: https://github.com/orgs/community/discussions/120203
(in service of a different goal, of skipping the queue for PRs that were already up-to-date, which also would be pretty neat)
Explanation
This adds the
merge_grouptarget and adds a check for releases, so we can safely enable the merge queue.The release check will check for any differences on
mainor in the merge queue compared to the release branch. If any conflicts are detected, the release will be rejected from the merge queue, and will need to be updated with the latest changes first.References
Checklist
Note
Adds a composite action and workflow job to block release PRs (including merge queue) when releasing packages that conflict with upstream changes.
merge_grouptrigger in.github/workflows/main.yml.check-releasejob for PRs/merge groups usingMetaMask/action-is-releaseto detect releases and invoking./.github/actions/check-release; included inall-jobs-completeneeds../.github/actions/check-release/action.ymlcompares package versions atMERGE_BASEvsHEADto find released packages, checks files changed betweenbefore..MERGE_BASE, and fails with an error if changes touch those package directories.Written by Cursor Bugbot for commit 2f0340c. This will update automatically on new commits. Configure here.