Github Stack [Merge as Stack] only triggering build against top-of-stack PR

I have a repository that is configured to only support “Squash and Rebase” for merges from Github PR’s into the trunk branch.

The new GH Stacks feature, [Merge as Stack], AFAICT only emits 1 webhook when using merge has stack, as I assume the github backend is pushing the entire stack of PR’s, with each PR branch squashed down to a single commit, as a single push (of multiple commits) into the trunk branch (based on this documentation[1]).

The result of this is now my CI is only running a build against the top PR of the stack after merging to trunk. This is not ideal for my CI system as we already perform change impulse calculations for the diff of each commit to trunk to isolate d only running CI jobs related to the changes of the commit (as opposed to the whole corpus of tests, its a monoreop).

Is there any known way that I configure the Github webhook / buildkite pipeline such that it will create a build for EVERY commit pushed into trunk?

OR Do I need to now perform this calculation on trigger backfill builds for the intermediate PR’s of the stack myself.

[1] Merging stacked pull requests - GitHub Docs

Also asking in github community discussions Github Stacks [Merge as Stack] Webhooks · community · Discussion #206370 · GitHub

Hello :waving_hand: ,

Welcome to the Buildkite Community! Thank you for the detailed context. Unfortunately, at the moment there is no setting as such that will make Buildkite create a build for every commit in a push.

And your read of what’s happening is correct. GitHub sends a single push webhook for the stack merge, and buildkite create a build for that push’s head commit only and the other commits in the push aren’t considered for build creation at all. This isn’t specific to merge as Stack either.

And to your second question, you’d need to backfill the intermediate commits yourself. I think it is the ideal way to do it. A step at the front of your trunk pipeline works out which commits came in with the push and triggers a build via our REST API for each one below the tip, setting an env var on those builds so they skip the backfill step and don’t recurse.

And few things I wanted to make a note of is usually I suppose the approach is to ask the API for the previous build on the branch, but your backfilled builds sit on that same branch, so that lookup will eventually pick one of them as the starting point. When it does, the commit
range comes out empty and the step quietly backfills nothing. Filtering to webhook-sourced builds only, and excluding the current commit so a rebuild at the tip isn’t mistaken for the previous one would sort it. And some backfilled builds will probably fail as intermediate commits in a stack aren’t always successful, if the stack wasn’t written so each PR stands alone.

Please let me know if you have any questions!

Cheers,
Meghana
Senior Support Engineer

Thank you for the response.

Your assumptions are correct.

My thinking was to have the step just try to start the parent if the pipeline didn’t have a build for that commit already launched. This works for us because we already require PR’s to only merge has squashed commits, so we have a linear history on our trunk already enforced.

So each build can just check if its parent commit has an associated build and stop there. If it launches a build, then that newly launched build will also check for its own parent; that should chain all the way back to a commit with a build already associated and stop.

That’s a neat approach and I think it’s better. Since the stopping condition is just “does this commit
already have a build”, your backfilled builds become the markers that stop future chains, so it’s self-terminating and avoids the previous-build lookup problem I mentioned entirely. With linear history enforced on trunk it should work well.

One thing I noticed while testing and wanted to flag is that our build lookup by commit is an exact string match, so an abbreviated SHA and a full SHA are treated as two different commits. I created a build using a short SHA, then queried for that same commit using its full SHA, and got nothing back. Builds created from push webhooks store the full SHA, so as long as your backfill step passes full SHAs too it should be fine. But if a short one ever slips in, the chain won’t see that build and will read the parent as unbuilt, and might keep walking back. Since that lookup is your only stopping condition, it’s worth putting a hard cap on how far the chain can walk, just so a bad lookup fails visibly instead of turning into a long run of builds.

Please let me know if you have any questions!