Azure DevOps dependency between different runs of a build pipeline

I have a requirement where I want a build pipeline run to wait if a previous run for the pipeline is still “inProgress”.

For example, in below image a run is already in progress, now a new run should wait or depend on this run to complete (either fail, cancel, or succeed).

I have explored below options:

  1. “exclusive lock” as a check in Environment. (not very flexible)
  2. invoke rest api as a check in Environment. (could not find much in Azure documentation on how to use result to handle check )
  3. or have a stage in yaml pipeline for checking previous runs status may be in a loop as a bash or python step. (this seems to be a flexible approach which can be customized.)

Any pointers on the right approach to address this requirement will really help.

As per Define approvals and checks – Exclusive Lock:

In the YAML file for the pipeline, specify a property called lockBehavior. This can be specified for the whole pipeline or for a given stage.

Example:

trigger: none

pool:
  vmImage: 'ubuntu-latest'

lockBehavior: sequential

stages:
- stage: A
  jobs:
  - job: Job
    steps:
    - script: sleep 20
      displayName: 'Sleep for 20 seconds'

Running 2 builds one right after another, this is displayed in the second build:

Clicking on View button:

EDIT

I ran more tests. It seems that the lockBehavior works only at the stage level, not the whole pipeline.

Consider the following pipeline with 2 stages:

trigger: none

pool:
  vmImage: 'ubuntu-latest'

lockBehavior: sequential

stages:
  - stage: A
    jobs:
    - job: Job
      steps:
      - script: sleep 20
        displayName: 'Sleep for 20 seconds'

  - stage: B
    dependsOn: A
    jobs:
    - job: Job
      steps:
      - script: sleep 20
        displayName: 'Sleep for 20 seconds'

Running 2 builds one right after another, we can see that stage A in the second build is run before stage B in the first build:

1

a new run should wait or depend on this run to complete

Currently, Azure DevOps doesn’t support it if your pipeline has multiple stages. Azure pipeline allocates agents based on jobs instead of builds. And the dependency is job/stage level instead of build level. If you want such feature, you can submit a feature request on Azure DevOps Developer Community and share the link here. Then others who want the same feature can follow it and add comments to increase the priority.

For your case, there is a workaround you can refer to, although it’s not perfect.

  1. In the first stage of your pipeline, run REST API Definitions – Update to update the value of queueStatus to paused. When it is paused, builds in the queue will not be started by the system.

    • Run REST API Definitions – Get to check the current queueStatus, if it is paused, which means that there is already a running build, exit and fail the current build.
    • If the value is enabled, change it to paused.
  2. In the last stage of your pipeline, run REST API Definitions – Update to update the value of queueStatus to enabled.

  3. You must use stage dependency to ensure the order of the step1 and step2.

  4. Example YAML:

lockBehavior: sequential

pool:
  vmImage: windows-latest

stages:
- stage: First
  jobs:
  - job: first_job
    displayName: 'Pause new runs'
    steps:
      - task: PowerShell@2
        inputs:
          targetType: 'inline'
          script: |
            $token = "{PAT}"
            $token = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($token)"))
            $head = @{ Authorization =" Basic $token" }
            $url="https://dev.azure.com/{OrgName}/{ProjectName}/_apis/build/definitions/{BuildDefinitionID}?api-version=7.1"
            $response = Invoke-RestMethod -Uri $url -Method Get -Headers $head
            if ($response.queueStatus -eq "enabled") {
              $response.queueStatus = "paused"
              Invoke-RestMethod -Uri $url -Method PUT -Headers $head -Body ($response | ConvertTo-Json -Depth 10) -ContentType application/json
            } else {
                exit 1
            }


- stage: A
  dependsOn: First
  condition: succeeded()
  jobs:
  - job: A1
    displayName: A1
    steps:
      - script: echo "This is A1"

- stage: B
  dependsOn: A
  condition: succeeded()
  jobs:
  - job: B1
    displayName: B1
    steps:
      - script: echo "This is B1"

- stage: Last
  jobs:
  - job: last_job
    displayName: 'Enable new runs'
    steps:
      - task: PowerShell@2
        inputs:
          targetType: 'inline'
          script: |
            $token = "{PAT}"
            $token = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($token)"))
            $head = @{ Authorization =" Basic $token" }
            $url="https://dev.azure.com/{OrgName}/{ProjectName}/_apis/build/definitions/{BuildDefinitionID}?api-version=7.1"
            $response = Invoke-RestMethod -Uri $url -Method Get -Headers $head
            $response.queueStatus = "enabled"
            Invoke-RestMethod -Uri $url -Method PUT -Headers $head -Body ($response | ConvertTo-Json -Depth 10) -ContentType application/json
  1. Result:

    • build1 gets the agent.
    • build2 comes before build1 finishes the first stage. When build2 gets the agent, it will fail in the first stage. Build1 gets the agent back and keeps running until completing the last stage.
    • build3 comes after Build1-Firststage finished, it will wait for the agent until build1 is completed.

4

Here is what worked for me.

stages:
- stage: ExistingBuildCheck
displayName: Checking if there is an existing build inProgress

jobs:
  - job: GetInProgressBuilds
    steps:
    - checkout: none
    - script: |        
        set -e  

        json_response=$(curl --location --request GET 'https://dev.azure.com/{Org}/{Project}/_apis/build/builds?definitions=$(System.DefinitionId)&branchName=$(Build.SourceBranch)&statusFilter=inProgress&api-version=7.1' --header 'Authorization: Bearer $(System.AccessToken)')

        # escape character can create parsing issues
        refined_json=$(echo $json_response| sed 's/\/\\/g')

        ## get count of all Runs retrieved where status is inProgress. 
        read -r count_inProgress_runs <<< $(python -c "import json; data = '''$refined_json'''; parsed = json.loads(data); 
                                                    count_inProgress_runs = parsed['count']; 
                                                    print(count_inProgress_runs )" 
                                          )
         # exiting run counts as 1 so count > 1 confirms existing inProgress run other than the current run
        if [ "$count_inProgress_runs " -gt 1 ]; then
          echo -e "33[1;31m Another run is currently in progress. Wait for it to finish or cancel it before starting a new one."
          exit 1 # exit with error to fail stage
        else
          echo -e "33[1;32m There is no other run inProgress except this one!"
          exit 0 # success.
        fi            

The above stage is injected between build stage and deploy stage.
I allowed artifact build stage to complete, then a Rest API validation stage to check if any previous run status is inProgress and fail the validation stage. User can first take decision on the already inProgress run and after it completes then re-run the validation stage in current pipeline.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật