Concurrency Gate with dynamically injected block step

hi everyone :-)

I am successfully using a concurrency gate to ensure all my deployment steps are not run concurrently with another build.

So, i am needing to run a command inside of the gated steps, which checks the SHA currently deployed to production. If that SHA is later in the commit log than the builds SHA, I want to present a “this SHA is older, you sure you want to deploy it?” block step. Someone can then decide whether they want to proceed with the deploy, or leave it be.

So this occasional injection of the block into the concurrency gate is resulting is unpredictable behaviour. I was thinking it would be fine, as injecting the block step would disable the gate for the build which had the step injected (and the gating would continue to work as expected in other builds). But it doesn’t seem to work this way.

I have read of doco, and forum questions about concurrency gates, and my mental model of how they work is not clear. I don’t think what has been written so far gives a good indication of how they actually work. There are also many half answered forum posts on the topic, so getting a clear understanding of how gates work has been a struggle for me.

I know that concurrency gates do not work with a block inside the open/close of a gate, but I don’t fully grok why. I am also not sure what happens if you inject a block step after you open a gate, but before you close it.

Can someone ELIA5 why using buildkite-agent pipeline upload to inject a block step within a concurrency gate is NOT going to work?

Also, it would be really helpful someone please do write-up on how concurrency gates work behind the scenes, or better yet, implement a proper “concurrency grouped steps” feature.

Thanks!

Hey @jimmy :wave:

Welcome to the Buildkite Support Community!

The best explanation around the concurrency gates in general is on our blog, you’ve probably already seen it but I’ll drop the link here just incase.

Now to your question, whats happening when you use buildkite-agent pipeline upload to inject a block step within a concurrency gate!

Basically once you open a gate, that gate expects that nothing will change until it closes. It won’t recheck or adjust for any updates to the steps until that gate has closed. It won’t know how to handle a step being injected inside the running gate and that’s why it will give unpredictable results.

If you’d like further assistance just send us a email at support with your pipeline YAML, or a link to a build and we will be happy to take a look!

Thanks!

Thanks for the response. Yes, i did read that blogpost. It is good, but doesn’t really explain HOW the gates work.

Will the unpredictable results be limited to the current pipeline where the block was injected? Or will it produce unpredictable results in other pipelines?

If i inject a block into the current pipeline, inside the gate, what effect does it have on closing the gate? Does the close gate step get pulled off the queue?

Thanks for the offer to look at our pipeline yaml. It’s fairly elaborate, so I save taking you up on that offer for a bit later.

Hey @jimmy :wave:

The TL;DR is that concurrency only works on active jobs, not inactive ones. A block step falls in to the latter category.

We have information on active/inactive here.

Now, what will happen when you inject the block step? You pipeline will run as normal, but once it hits the block the concurrency group will be freed up for another build to use.

Thanks @benmc.

Now, what will happen when you inject the block step? You pipeline will run as normal, but once it hits the block the concurrency group will be freed up for another build to use.

In this scenario, would concurrency gates in other pipelines continue to function as expected? Say pipeline A was running the step in the gate, with two other pipelines (B & C)blocked and waiting, and in pipeline A the block step was injected. Would the pipeline B enter the gate, with pipeline C blocked and waiting until pipeline B completed it gated steps?

@jimmy that’s correct; the block in A would therefore free up the group for B, which would block C until it either finished with group use or it too injected a block

Thanks for your help all!