Conditions not evaluating as expected

We’re having a problem preventing multiple builds of the same configuration from executing at the same time.

We have conditions set that should prevent it, but I think there is a bug.

We expect “LastBuild.State = BuildCompleted” to happen after the entire build has finished, but it is setting that flag after a STAGE successfully completes. Our CI builds have 3 stages, we need a new queued build to wait until all 3 are completed. So when Build 1 Stage 1 completes and starts Stage 2, Build 2 starts Stage 1.

We’ll have to investigate what is going on here, however a better option for controlling the number of concurrent builds is to use a Shared Resource Lock - condition. Shared resources are acquired at the start of the build and released at the end.

BTW, shared resources were introduced in 1.8 - this blog post has some more useful info on them.

Right, we’ve used Shared Resource locks in the past to prevent multiple configurations that use the same file from building at the same time. But we now want to allow multiple configurations to build at once in the same project, but we don’t want multiple builds of the same configuration. We currently have 89 total configurations and will likely be adding 20+ more in a couple of months, I really don’t want to have to maintain 110 shared resources to have one for each config.

Hi Andy,

The BuildCompleted state is only set at the end of the build. It is not set after a stage completes.

Looking at your screenshot, I can see that one condition you have used is $Configuration.LastFinishedBuild.State$ Equals 'BuildCompleted'. This cannot be used to test whether any builds are running, as the last finished build is always finished and its state will either be BuildCompleted, BuildFailed, BuildError, BuildStoppedByUser, BuildDiscarded or StagePendingPromotion.

The expression $Configuration.LastBuild.State$ is also not useful as this refers to the last build started in the configuration and this can point to the current build. We don’t have an expression which refers to the previous build.

The only fail-safe way to limit the number of builds that run concurrently per configuration is to use a shared resource lock. If this is too much to maintain, maybe you can use a Quota List shared resource with a label for each configuration?

Why do you need to prevent multiple builds running for all of your configurations?

I don’t think that’s entirely how it’s behaving…in this configuration, I have that flag set and when I queue two builds up, one waits:

But as soon as the first stage completes…

The reason we want to prevent the same config from running at the same time is we have it set to 3 stages - build, unit tests, deploy. The first step of the build process deletes the build folder from the previous run, so if build 2 deletes that while build 1 is trying to deploy from that location, it fails mid-deploy.

Oh, and to go ahead and explain, we aren’t using the temporary workspace for the build/deploy parts because of some Angular dependencies that require pre-build setups to be done in the build path, that’s time consuming and not feasible to replicate every single build.

Hi Andy,

When the first stage of the first build completes, the build is then put on the queue waiting for a agent for the second stage. The condition $Configuration.QueuedBuildCount$ Equals 0 is then false, so that second build starts. This is nothing to do with the state of the last finished build.

But there are three conditions set, with And as the operator. Shouldn’t the build wait until all conditions are met?

Apologies, my last post was incorrect.

The reason the second build starts is because both $Configuration.QueuedBuildCount$ and $Configuration.RunningBuildCount$ become zero. I was concentrating on the condition $Configuration.LastFinishedBuild.State$ Equals 'BuildCompleted' which is always true as the last finished build for your configuration has completed sucessfully.

When the first build reaches the StageCompleted status it is neither Running or Queued. While the second build is in the state BuildAwaitingQueueConditions it is also neither Running or Queued. Therefore the condition is met.

We have now decided that builds with a StageCompleted state should in fact be counted as Running and have now updated the code as such for the next version. We have tested your scenario with this update and it works, although it doesn’t proved the same concurrency guarantees as a shared resource lock.

In the future we plan to add an option to the configuration to automatically set up a single hidden shared resource linked to the configuration for this purpose.

Please see version 1.9.1.422. This updates the StageCompleted state so that it is included in the running build count.

You should now get the required behaviour using the first two expressions only in your condition. e.g.

'$Configuration.RunningBuildCount$' Equals '0'
and '$Configuration.QueuedBuildCount$' Equals '0'