Ask HN: How are pull requests integrated in a repo with high commit frequency?
So let's assume we open a pull request, merged current main into our feature branch and are running tests. The full acceptance test suite takes 5 minutes to complete.
Meanwhile, in those 5 minutes, 10 other commits have been made. If we merge now, we can't be sure that we won't break stuff right?
So after merging the pull request, are you supposed to perform another set of regression tests? Hard to find info about that
70 comments
[ 3.8 ms ] story [ 141 ms ] thread[0]: https://about.gitlab.com/blog/2020/01/30/all-aboard-merge-tr...
E.g. when merging A, B and C. C might have no conflict with master or A but it has a conflict with B. Now for the queuing to work A -> B -> C it will have to know somehow how to patch C to fit on top of B.
Maybe B breaks if it is not working after merged into A, and then the queue becomes A -> C -> B (modified), now B probably needs a patch to merge cleanly on C?
But that's exactly my point. The first PR to merge cleanly will determine whether the next PR causes a merge conflict or not. At the time of merging, none of these PRs had a merge conflict.
We often have 10 conflicts between PR admission and approval.
I don't think a devops solution can remove those conflicts. At least not all of them.
If you have devs in the same hot-spots of the code, you're going to get conflicts. Maybe refactoring can address some of this core issue.
And yeah, management won't do it. Fred Brooks wrote an entire book about this in 1975 that no one reads today and everyone would certainly ignore if they did read it. Because it tells you the unvarnished truth about the nature of communication and information flow within an organization. Such is the state of things in our industry. Sweet little lies.
Our library implementing this: https://gitlab.kitware.com/utils/rust-git-topic-stage
However, given your later metric of 10+ conflicts per topic…I suspect your project is still in the "getting off the ground" phase where a stage is awfully heavy process because there aren't "bright line" distinct sections of the code yet. Or your topics are too big. Hard to say.
(Homepage: https://bors.tech/)
Even if you don't have a supper high commit frequency it is still nice to enable certain rebase/stacked PR workflows. Which can remove a lot of friction even for teams which "just" have idk. 6 PRs merged per day (but other PRs which are based on top of this PRs in review and progress maybe stacked multiple layers deep).
OP’s numbers are 120 commits per hour and 5 minute test run, I’m wondering if adopting bors would necessarily reduce that to 12 commits per hour.
https://github.com/bors-ng/bors-ng/blob/master/README.md#how...
Definitely recommended. We run ours on a Heroku instance it’s cheap and almost entirely maintenance free.
If your change does break after merging, it can usually either be quickly fixed with a minor code change or simply reverted immediately.
Rather than look for a technical solution I would explore process and culture changes, such as having the various devs making all the different commits start pairing.
We run the acceptance tests for all PRs and also the main branch after each change. So a given PR needs to be 'green', and if we merge the PR then we run the tests on the integration branch too. If the integration branchs gets broken somehow, then all merges stop -- we don't merge any further PRs into a 'broken' branch.
We have tried the option of always rebasing PRs on the most recent integration branch and re-running the tests, but that results in exponential number of builds.
Of course you need a meaningful build farm -- we have around 1000 CPU cores for ~30 developers that are fully utilised during work hours.
1000 CPU cores, not CPUs. :)
This is where merge queues come into play which have a variety of names (merge queue, submit queue, merge train, etc)
I have a write up on merge queues [0] that goes into other benefits (e.g. speeding up PR builds), design considerations and their trade offs, and a comparison of various implementations.
[0] https://epage.github.io/dev/submit-queue/
Like others said, "merge queue" is the solution. GitHub's one has been in beta for many months now.
There are also dedicated companies doing this like https://mergify.com/
But there's several tricky aspects like "what if I want some commit to jump in front of queue?", compliance etc.
Due to the multitude of requirements and off-the-shelf solutions being somehow limited, infra folks in my place are considering building a custom solution :)
(disclaimer: I'm from the Mergify team )
Question: You list Uber (my employer) as a user in your homepage, but searching internally, the only search result for mergify is a mergify.yml in some random debian module for lua, so it doesn't seem like we actually use it for anything (and we built an in-house solution for the repos w/ serious commit traffic). I'm curious how you determine who your corporate users are?
Comment: we ended up building a merge queue in house because frankly build/test pipelines can look very different,(e.g. at one point we had jenkins pipelines and buildkite pipelines, some using bazel, some not, talking to phabricator instead of github, etc). At the end of day plugging in a merge queue technology requires a bunch of work integrating with a myriad of things anyways. Since the engineering effort is relatively high regardless, doing it in house lets us experiment with more aggressive optimization heuristics than just waiting on a 3rd party.
I definitely agree with your view on how pipelines can be different. I think none of our customers has something that is exactly the same. However, many of them don't have the workforce to build in house or even to optimize as far as you would do in a (very) large company.
https://github.blog/changelog/2021-10-27-pull-request-merge-...
Two things had to work or we would have lost all our sanity points (reference to Call of Chthulhu): automated checks of style, building, testing; and small PRs subscribing to the 'do one thing and do it well' approach.
As for the second, it's more doable than you might think - if you decomposed your work well. We decomposed our work at these levels on one project: product, demo capability, epic, task; the other project used feature, epic, task. Typically PRs were at the task level, though sometimes at PR level.
For us this had the added benefit that the developer velocity on these two projects exceeded the velocity of any of the other projects I've been on.
Some other tricks we used were to make sure we rebased our task branches from develop every morning (and if needed after lunch); each task branch had 1 person only working on it; where complexity warranted we created an Epic-### branch for that epic and treated it as a mini-develop for tasks on that epic.
Our test suite takes about 30m to finish.
In a nutshell, the idea is to keep track of currently running jobs, then any time a new commit enters the queue, you merge all the running commits into that and test that as a bundle. If merging fails, bail out. If that bundle job fails, bail out. If one of the previously running commits fail, you bail out of the bundle job and run another speculative bundle job without the failed commit. When a bundle succeeds, land all of its commits and abort any remaining redundant jobs.
Such systems will sometimes have heuristics to bundle commits together in some smarter way than a naive queue (e.g. preferring to bundle of commits without overlapping changes, or not bundling small commits with huge ones to prevent infecting speculative builds with the slowness of the big commit, using AI to come up with heuristics to detect "likely to fail" commits and preemptively starting speculative builds without them, etc)
I just felt that merging into main without having 100% confidence that acceptance tests would pass means that true continuous delivery isn't achieved. But with these tools, we can make sure that our software is always in a releasable state (according to our test suite). I learned a lot today.
It automatically tests the changes with a simulated merge on master together. So it orders PR1 -> PR2 -> PR3 -> .... -> PR-100 by order of approval. If PR1 -> PR2 (Fails) -> PR3 -> .... -> PR-100
It restarts -> PR3 -> .... -> PR-100 and Up after removing PR2. This behavior is even customizable.
Video of it in action: https://zuul-ci.org/media/simulation.webm
Links: [0]:https://zuul-ci.org/
So all commits are made sequentially, but most of the time developers don't need to rebase them themselves before pushing. The time distribution of commits sent to the queue is non-uniform, so you may have a long queue during the day, but by late evening it's pretty much empty. It has the greatest number of commits on Fridays.