CI: add check to prevent merge commits in PRs - #21741
Conversation
|
Hi @david-allison can you have a look in this PR? |
|
Hi, no need to ping until it's been a few days 😅, it's almost midnight here |
Sorry!!, Will take care about that from now onwards. |
Could you elaborate? What did you run this against [and what did you run]? Can you confirm that nothing here was AI-generated? It feels a bit too 'clean' |
I tested this against my existing PR for issue #21671 and ran the script against it locally in my terminal. gh api --paginate /repos/ankidroid/Anki-Android/pulls/21671/commits --jq '[.[] | select(.parents | length > 1)] | length'This command asks the github API for all the commits in PR #21671, and then counts how many of those commits have more than 1 parent.
Yeah I can confirm that nothing here was AI generated. |
Did you test this on a PR with conflicts, and on one which goes past the paginate boundary? |
I haven't manually run the test against a PR with conflicts or one that goes past the pagination boundary but the script handles those cases. The github API endpoint that I am using simply lists the commits on the head branch and I have included the gh api --paginate flag, which automatically follows all link headers to fetch paginated results. |
gh api --paginate /repos/ankitects/anki/pulls/4289/commits --jq '[.[] | select(.parents | length > 1)] | length' | cat
4
1
4which I believe would break the check edge case: the check also seems broken over 250 commits gh api --paginate /repos/ankitects/anki/pulls/4289/commits --jq 'length' | cat
100
100
50 |
|
Hm yes the gh tools when combines with --paginate and --jq it does not combine all the pages together first. It applies filter to each page individually as it arrives and yes also there is limitation of 250 commits. To make this completely robust against edge cases, would you prefer I just switch the workflow to use a deep git checkout and pure git instead of the API? Something like this - name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Check for merge commits
run: |
MERGE_COMMITS=$(git log --merges --oneline origin/${{ github.base_ref }}..HEAD)
if [ -n "$MERGE_COMMITS" ]; then
# fail check
fiThis approach handles infinite commits and ignores API pagination entirely, let me know what do you think about this approach.. |
Purpose / Description
Adds a new GitHub Actions workflow that automatically prevents Pull Requests from being merged if they contain merge commits. This enforces a linear, rebased commit history and reduces manual checks by maintainers.
Fixes
Approach
Created a new workflow (check_merge_commits.yml) that runs on the pull_request event. It uses the pre-installed GitHub CLI (gh api) to query the GitHub REST API for all commits in the current PR and counts them. If any commit has more than 1 parent (parents | length > 1), it fails the workflow and prompts the contributor to rebase. Using the GitHub API avoids the need to do a slow, deep Git checkout of the repository.
How Has This Been Tested?
This was tested by verifying that the GitHub Action triggers correctly when this Pull Request is opened. The logic was verified using gh api against existing PRs to ensure it correctly identifies commits with multiple parents.
Checklist
Please, go through these checks before submitting the PR.