You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Azure DevOps构建流水线:新运行等待已有运行完成的方案咨询

Azure DevOps流水线串行执行方案指引

针对你提出的「单条流水线存在运行中实例时,新触发运行需等待其完成」的需求,结合你调研的三个方案,最适合的是方案3:在YAML流水线中新增阶段,通过脚本循环检查运行状态,以下是具体分析和实现指引:

方案优劣对比

  • 方案1:环境独占锁:配置简单,但粒度太粗——它会锁定整个环境下的所有流水线,无法精准控制单条流水线的串行执行,灵活性不足,不符合你的需求。
  • 方案2:环境检查项调用REST API:理论上可实现,但Azure官方文档支持少,配置和维护成本高,排查问题难度大,不推荐。
  • 方案3:YAML新增阶段+脚本检查:完全自定义逻辑,能精准针对当前流水线的运行实例做判断,灵活性和可扩展性最高,是最优选择。

方案3具体实现

核心思路

在流水线最前端新增一个前置检查阶段,通过脚本调用Azure DevOps API/CLI,循环查询当前流水线的所有运行实例:

  1. 过滤出状态为inProgress且不是当前运行的实例
  2. 如果存在这类实例,等待固定间隔后再次检查
  3. 直到所有运行中实例完成(状态变为succeeded/failed/canceled),再继续执行后续阶段

实现方式1:Bash脚本+Azure DevOps CLI

适用于使用Linux代理的流水线,步骤如下:

  1. 在YAML中新增前置阶段:
stages:
- stage: Check_Running_Instances
  displayName: Check for running pipeline instances
  jobs:
  - job: Check
    displayName: Wait for existing runs to complete
    steps:
    - script: |
        # 登录Azure DevOps CLI(使用系统自动注入的访问令牌)
        az devops login --organization $(System.CollectionUri) --token $(System.AccessToken)
        
        # 获取当前流水线ID
        PIPELINE_ID=$(az pipelines show --name "$(Build.DefinitionName)" --organization "$(System.CollectionUri)" --project "$(System.TeamProject)" --query id -o tsv)
        CURRENT_RUN_ID=$(Build.BuildId)
        
        # 设置最大等待时长(可选,避免无限等待)
        MAX_WAIT_MINUTES=60
        ELAPSED_MINUTES=0
        
        while true; do
            # 查询所有运行中的实例(排除当前运行)
            RUNNING_INSTANCES=$(az pipelines runs list --pipeline-id $PIPELINE_ID --organization "$(System.CollectionUri)" --project "$(System.TeamProject)" --query "[?status=='inProgress' && id!='$CURRENT_RUN_ID'].id" -o tsv)
            
            if [ -z "$RUNNING_INSTANCES" ]; then
                echo "No running instances found, proceeding with pipeline execution."
                break
            else
                if [ $ELAPSED_MINUTES -ge $MAX_WAIT_MINUTES ]; then
                    echo "Max wait time reached, exiting with failure."
                    exit 1
                fi
                echo "Found running instances: $RUNNING_INSTANCES. Waiting 30 seconds..."
                sleep 30
                ELAPSED_MINUTES=$((ELAPSED_MINUTES + 0.5))
            fi
        done
      displayName: Check running pipeline instances
      env:
        SYSTEM_ACCESSTOKEN: $(System.AccessToken)
  1. 确保流水线的服务账号拥有读取流水线运行的权限(在项目设置→权限→构建服务账号中配置)

实现方式2:Python脚本+Azure DevOps SDK

适用于更复杂的逻辑判断,步骤如下:

  1. 在YAML中新增前置阶段:
stages:
- stage: Check_Running_Instances
  displayName: Check for running pipeline instances
  jobs:
  - job: Check
    displayName: Wait for existing runs to complete
    steps:
    - script: pip install azure-devops
      displayName: Install Azure DevOps SDK
    - script: |
        python check_running_instances.py
      displayName: Check running instances
      env:
        ORG_URL: $(System.CollectionUri)
        PROJECT_NAME: $(System.TeamProject)
        PIPELINE_NAME: $(Build.DefinitionName)
        CURRENT_RUN_ID: $(Build.BuildId)
        PAT_TOKEN: $(System.AccessToken)
  1. 创建check_running_instances.py脚本:
import os
import time
from azure.devops.connection import Connection
from msrest.authentication import BasicAuthentication

# 读取环境变量
org_url = os.getenv("ORG_URL")
project_name = os.getenv("PROJECT_NAME")
pipeline_name = os.getenv("PIPELINE_NAME")
current_run_id = int(os.getenv("CURRENT_RUN_ID"))
pat_token = os.getenv("PAT_TOKEN")

# 建立API连接
credentials = BasicAuthentication("", pat_token)
connection = Connection(base_url=org_url, creds=credentials)
build_client = connection.clients.get_build_client()

# 获取目标流水线ID
pipelines = build_client.get_definitions(project=project_name, name=pipeline_name)
if not pipelines:
    raise ValueError(f"Pipeline '{pipeline_name}' not found")
pipeline_id = pipelines[0].id

# 设置最大等待时长(分钟)
MAX_WAIT_MINUTES = 60
elapsed_minutes = 0

while True:
    # 查询所有运行中的实例
    runs = build_client.get_runs(project=project_name, definition_id=pipeline_id, status="inProgress")
    running_runs = [run for run in runs if run.id != current_run_id]
    
    if not running_runs:
        print("No running instances detected. Proceeding with pipeline.")
        break
    
    if elapsed_minutes >= MAX_WAIT_MINUTES:
        print(f"Exceeded maximum wait time of {MAX_WAIT_MINUTES} minutes. Aborting.")
        exit(1)
    
    print(f"Found {len(running_runs)} running instance(s). Waiting 30 seconds...")
    time.sleep(30)
    elapsed_minutes += 0.5

注意事项

  • 权限配置:确保流水线的服务账号(Project Build Service)拥有读取构建运行的权限,避免API调用失败
  • 等待间隔:可根据实际场景调整等待时间(比如从30秒改为10秒)
  • 超时机制:建议添加最大等待时长,避免流水线无限等待
  • 代理兼容性:如果使用私有代理,需确保代理能正常访问Azure DevOps API

内容的提问来源于stack exchange,提问作者Avneet Singh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 01:04:56