21

I am have 2 build agents and 8 pipelines in azure devops. If a run starts for pipeline A, and another run is triggered for the same pipeline Azure Devops will start a second run on the other agent without waiting for the first to finish.

How do I make Azure Devops wait until the first run is finished before starting the second one?

Edit: using yaml pipelines rather than old build/release pipelines.

cfbd
  • 980
  • 2
  • 9
  • 21
  • 1
    Why does it matter to you? Builds should be stateless. – Daniel Mann Jun 27 '19 at 22:26
  • 3
    It's common in other CI such as jenkins to run end to end tests against a test environment before deploying to the next environment in the pipeline. So you want to prevent another version being deployed over this one until the pipeline as finished. – cfbd Jun 27 '19 at 22:37
  • 1
    That would happen in a release pipeline, not a build. Releases have mechanisms to control the degree of parallelism. – Daniel Mann Jun 27 '19 at 22:40
  • 3
    I'm using the new yaml pipelines rather than old build/release pipelines – cfbd Jun 27 '19 at 22:41
  • @DanielMann surely you would want to run all tests in the build pipeline before creating releases to deploy to manual test / staging enviornment? – Andy McWilliams Jan 17 '20 at 11:28
  • 4
    There is a community request for this feature that you can vote on: https://developercommunity.visualstudio.com/idea/365730/prevent-parallel-execution-of-the-same-build-defin.html. – Matt Thalman Aug 17 '20 at 13:12
  • Consider terraform with backend storage in Azure Storage Container (very common). The Container is Lease Locked, so concurrent pipelines will result in failure when second+ pipeline `terraform init` cannot lock the state file. – Beans Feb 09 '23 at 20:09

5 Answers5

5

Looks like you can do this by using the trigger options in the yaml file:

trigger:  
    batch: true

Do note that this value is false by default (so when left empty), but it might only be when a trigger has been defined?

Docs here: https://learn.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=azure-devops&tabs=schema#triggers

Rob Bos
  • 1,320
  • 1
  • 10
  • 25
  • According to docs that is not the default behavior. – Monsignor Jul 24 '20 at 09:36
  • You are correct @Monsignor: the default recently changed. Updated the answer – Rob Bos Aug 16 '20 at 18:46
  • This doc more clearly describes "batch: true" behavior.
    https://learn.microsoft.com/en-us/azure/devops/pipelines/repos/azure-repos-git?view=azure-devops&tabs=yaml#batching-ci-runs
    – Stas S Mar 30 '21 at 13:36
  • 3
    This doesn't actually disable concurrent build runs, just staggers builds. This answer helped for the OP's use-case. It doesn't address the titled question or doesn't seem to work anymore. – kayleeFrye_onDeck Mar 31 '22 at 13:46
3

Preventing concurrent runs may be done by setting up an environment with an Exclusive Lock check. That allows working with Microsoft-hosted agents, not just self-hosted agents. It also does not require pipelines to be assigned to specific agents the way Demands do.

  1. In Pipelines/Environments define an environment, say "my_environment". ADO nav bar image

  2. To the environment add a check of type "Exclusive Lock".

  3. In your YAML, reference environment "my_environment" using this form:

    lockBehavior: sequential
    stages:
    - stage: Stage
      jobs:
      - deployment: Job
        environment: my_environment
        strategy:
          runOnce:
            deploy:
              steps:
                ...

This will force multiple queues of the same pipeline to run sequentially in queue order. Different pipelines must use different environments, otherwise they will block each other.

More information here: https://learn.microsoft.com/en-us/azure/devops/release-notes/2021/sprint-190-update#azure-pipelines-1

2

I think you can use adding demands to the pool on the agent job of pipelines, so that it will run with one same agent because of the same specified condition.

First, add one Capability in the agent.

enter image description here

And then, in your YAML, add demands to the pool.

pool:
  name: {agent pool name}
  demands: Limit -equals DisAbleParallel 

The format of it is demands:{CapabilityName} -equals {CapabilityValue}.

While you specified the agent demands, the pipeline will just run with this agent. While A is running, the second one will not run at same time because the previous is running, the agent is being using. So that, the second one will run until previous ends.

Mengdi Liang
  • 17,577
  • 2
  • 28
  • 35
  • This will limit one job at a time. But I need to queue the whole Run. Only have one Run at a time. – cfbd Aug 14 '19 at 04:00
  • "Demands are only applicable when your pipeline runs on self-hosted agents." – Adrian Baker May 02 '20 at 22:41
  • This will not limit the parallel job execution on an agent having "Limit=DisableParallel" , only help to select a specific agent from a pool of agents. – Abdul Mohsin Jul 01 '21 at 12:32
2

I was able to do this (prevent a stage from being executed by multiple builds at the same time) by doing the following:

  1. Create a protected resource in Azure. I chose a variable group named build_concurrency_lock. You can add it via Pipelines -> Library -> Variable Groups. Be sure to add an "Exclusive Lock" to the resource.

adding an Exclusive Lock

  1. Then add this to the stage to run serially within azure-pipelines.yml.
stages:
  # Code Pipeline
  - stage: BuildStage
    displayName: "Build"

    # These next three lines make builds run in serial. We need to do this since we use a shared "builds" environment in azure - see https://stackoverflow.com/a/73694320/1072030, https://learn.microsoft.com/en-us/azure/devops/pipelines/library/variable-groups?view=azure-devops&tabs=yaml, and https://learn.microsoft.com/en-us/azure/devops/release-notes/2021/sprint-190-update#support-for-sequential-deployments-rather-than-latest-only-when-using-exclusive-lock-checks
    lockBehavior: sequential
    variables:
      - group: build_concurrency_lock # relies on a "build_concurrency_lock" Library variable group existing and having an "Exclusive Lock" "Approvals and checks" setup.

Chase Miller
  • 226
  • 1
  • 8
0

The linked-to PowerShell Task works well. I personally set the sleep polling to 60 seconds but other than that this works with one main exception. It won't work if they're queued simultaneously or within a similar starting time. If more than one build is queued before this task completes when no jobs are actually building yet, it will just get stuck until cancelled or times out.

That means if you can wait for a minute or two before building, this will work.

  • I don't recommend it for large teams all working on the same repository.
  • I also don't recommend it for incredibly long builds. I'm not sure, but I think the max timeout for builds is 360 minutes. So if they're long and queued up in numbers you'll risk chain-failures.

https://developercommunity.visualstudio.com/t/prevent-parallel-execution-of-the-same-build-defin/365730#T-N859271

kayleeFrye_onDeck
  • 6,648
  • 5
  • 69
  • 80