You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
blogcontent/blog/content/posts/automatic-merging.md

4.9 KiB

title date tags
Automatic Merging 2024-02-14T22:46:08-08:00 [CI/CD homelab productivity SDLC]

When working on my personal projects, I typically just push straight to main - opening a PR just to approve it seems entirely pointless, as if I had been able to find any issues in my own work, I wouldn't wait to do it in a PR! However, this does mean that, if I forget to run any quality checkers (linters, tests, etc.), I won't find out about it until on: push GitHub Action runs, and even then I might not see the failure until several commits later.

This problem can be addressed with pre-commit hooks1, but I've never been a fan of them:

  • As the documentation states, "client-side hooks are not copied when you clone a repository", meaning that any new collaborators (or even "me after blowing away the repo") will silently miss out on them.
  • On-commit seems like the wrong cadence to run quality checks - local commits should be fast and frequent checkpoints that you can return to (or juggle around) as needed, and adding friction to them makes development more precarious. Ideally, quality checks would run immediately prior to pushing, but the pre-push hook runs "after the remote refs have been updated", meaning2 that even if they fail, the remote will still have been changed.

The other day I hit on a cool idea that would seem to address both problems - since GitHub allows PRs to be set to be automatically merged when all checks pass, perhaps I could set up a workflow whereby:

  • I push commits to a dev branch
  • An auto-merging PR is automatically opened from that branch to main
    • If the checks pass, the PR is automatically merged
    • If it fails...well, I'd have to set up some non-email channel to notify myself about that, but that shouldn't be too hard

I did make some progress on it, but ran into some issues:

  • PRs cannot be created in an AutoMerge state - they have to be set into that state after creation. Although this SO answer did describe how to do so, some quirk of GHA meant that that failed when executed in a GHA context (claiming the PAT did not have permissions)
  • All is well and good if the PR immediately passes - but if it fails and I make correcting commits onto dev (which update the PR), then when the PR passes and is squashed into a single commit to then be merged into main3, then dev and main will have diverged, and the next PR that's submitted from dev to main will appear to be contributing the preceding commits as well. Not ideal!

After a couple of hours of fiddling around, I returned to investigating pre-commit hooks, and found the pre-commit tool, which provides a management interface for hooks. It unfortunately still requires manual installation (so a new contributor might not benefit from it - though, in fairness, that can be double-checked with CI checks), but the experience is smoother than writing hooks myself. I'll keep experimenting with it and see how I like it.


  1. And - spoiler alert - after running into frustrations with my first approach, this was exactly what I ended up doing, using the pre-commit tool.

  2. I do admit I haven't actually tested this understanding. It does seem surprising, as it would make the pre-push hook basically useless. This also seems to contradict the documentation here which states that ""git push" will stop without doing anything if the new "pre-push" hook exists and exits with a failure.". So, maybe pre-push hooks aren't useless? I've asked for more information on this here. But, the first counter-argument - and the convenience of the pre-commit tool - have me still using pre-commit hooks, even if pre-push would have worked.

  3. I will die on the hill that "Squash And Merge" is the only sensible PR merge strategy. A Merge Commit means that you have non-linear history, and Rebase means that one conceptual change is represented as however-many different commits were generated during development. There is no value whatsoever in preserving the frantic, scrabbling, experimental commits that were generated during development - they are scaffolding that should be tidied away before presenting the finished product as a single commit4

  4. Ironic, then, that in fact this tangled automation approach is one of the only cases where a Merge Commit would actually be...I can't believe I'm actually going to say this...better 🤮