Skip to content

Commit

Permalink
Merge pull request #1266 from product-os/kyle/enforce-linear-history
Browse files Browse the repository at this point in the history
Improve enforcement of linear commit history
  • Loading branch information
klutchell authored Dec 9, 2024
2 parents 41d15f7 + fdb8e1a commit 3d65526
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 20 deletions.
46 changes: 37 additions & 9 deletions .github/workflows/flowzone.yml

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

69 changes: 58 additions & 11 deletions flowzone.yml
Original file line number Diff line number Diff line change
Expand Up @@ -571,6 +571,56 @@
Please consult the documentation for more information."
exit 1
- &rejectNonLinearHead
# This can happen when a PR is updated with a merge commit from main, rather than rebased on main.
# In the GitHub UI this is represented by the "Update with merge commit" option vs "Update with rebase".
# https://github.com/actions/github-script
# https://octokit.github.io/rest.js/v21/#pulls-list-commits
name: Reject HEAD branches containing merge commits
if: github.event.pull_request.state == 'open'
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7
with:
github-token: ${{ github.token }}
result-encoding: json
script: |
const { data: commits } = await github.rest.pulls.listCommits({
...context.repo,
pull_number: context.payload.pull_request.number
});
if (commits.some(({ parents }) => parents.length > 1)) {
throw new Error('Non-linear history detected - merge commit(s) identified in HEAD branch');
}
- &rejectNonLinearMerge
# This can happen if multiple PRs are merged at the same time, typically because
# one PR is rebased on another PR before merging, where the merge commit in the BASE
# branch does not include the tip of the HEAD branch as a parent.
# https://github.com/actions/github-script
# https://octokit.github.io/rest.js/v21/#repos-get-commit
name: Reject merge commits that do not include the HEAD commit as a parent
# This check passes when the PR is open too, but only on pull_request events and not pull_request_target.
# So only check on merged PRs where the HEAD sha should always be a parent of the merge commit.
if: github.event.pull_request.merged
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7
with:
github-token: ${{ github.token }}
result-encoding: json
script: |
console.debug(`Merge commit SHA: ${context.sha}`)
console.debug(`HEAD commit SHA: ${context.payload.pull_request.head.sha}`)
const { data: commit } = await github.rest.repos.getCommit({
...context.repo,
ref: context.sha
});
console.debug('Commit parents: %s', JSON.stringify(commit.parents, null, 2))
if (!commit.parents.some(({ sha }) => sha === context.payload.pull_request.head.sha)) {
throw new Error('Non-linear history detected - HEAD branch commit is not a parent of the merge commit');
}
- &setupBuildx # https://github.com/docker/setup-buildx-action
name: Setup buildx
id: setup_buildx
Expand Down Expand Up @@ -1078,6 +1128,7 @@ jobs:
- *rejectExternalPullRequest
- *rejectInternalPullRequestTarget
- *rejectMissingSecrets

- <<: *getGitHubAppToken
with:
<<: *getGitHubAppTokenWith
Expand Down Expand Up @@ -1116,7 +1167,9 @@ jobs:
<<: *rootWorkingDirectory

permissions: {}
permissions:
# Required to inspect commits in branches for linear history
contents: read

outputs:
tag: ${{ steps.versionist.outputs.tag || steps.git_describe.outputs.tag }}
Expand All @@ -1137,6 +1190,10 @@ jobs:
<<: *gitHubCliEnvironment

steps:

- *rejectNonLinearHead
- *rejectNonLinearMerge

- <<: *getGitHubAppToken
with:
<<: *getGitHubAppTokenWith
Expand All @@ -1163,16 +1220,6 @@ jobs:
- <<: *checkoutEventSha
if: github.event.pull_request.state != 'open'

# fail on merge commits (ones with more than one parent)
- name: Reject merge commits
if: github.event.pull_request.state == 'open'
run: |
if [ "$(git cat-file -p ${{ github.event.pull_request.head.sha || github.event.head_commit.id }} | grep -c '^parent ')" -gt 1 ]
then
echo "::error::Latest commit appears to be a merge, which is currently unsupported. Try a rebase instead."
exit 1
fi
# The current commit sha is needed as the parent sha for the versioned commit
# and/or as default tag & semver if versioning is disabled.
- *describeGitState
Expand Down

0 comments on commit 3d65526

Please sign in to comment.