如何在Azure Pipeline单阶段中选择运行QA/DEV环境
Azure DevOps流水线:单阶段手动选择运行QA/DEV环境
我在Azure DevOps中维护一条流水线,当前会同时构建QA和DEV两个环境的镜像。需求是手动触发流水线时,能选择仅运行其中一个环境的构建,并且只通过单个阶段实现,不需要拆分出独立的QA、DEV阶段。之前尝试用条件判断配置,但没达到预期效果,当前阶段代码如下:
# BUILD ENVIRONMENTS - stage: build_envs dependsOn: quality_control displayName: Build Envs condition: | or ( and(eq(variables.isQa, true), ne(variables['Build.Reason'], 'PullRequest')), eq(variables['Build.Reason'], 'Manual'), and(eq(variables.isDev, true), ne(variables['Build.Reason'], 'PullRequest')), eq(variables['Build.Reason'], 'Manual') ) jobs: - job: Job_build displayName: Application Build steps: - ${{ if eq(variables.isQa, true) }}: - checkout: backend-qa path: enext-data-platform-backend - script: rm -rf enext-data-platform-backend/enext-data-platform-frontend - checkout: frontend-qa path: enext-data-platform-backend/enext-data-platform-frontend #submodules: true - script: | ls -la $(Pipeline.Workspace)/enext-data-platform-backend ls -la $(Pipeline.Workspace)/enext-data-platform-backend/enext-data-platform-frontend - powershell: | Write-Host "##vso[build.addbuildtag]qa" #displayName: Application Build DEV - ${{ elseif eq(variables.isDev, true) }}: - checkout: backend-dev submodules: true - script: git rev-parse HEAD - script: ls -la - powershell: | Write-Host "##vso[build.addbuildtag]dev" #displayName: 'Build Tag' - task: npmAuthenticate@0 displayName: npm Authenticate enext-data-platform-backend/.npmrc inputs: ${{ if eq(variables.isQa, true) }}: workingFile: $(Pipeline.Workspace)/enext-data-platform-backend/.npmrc ${{ elseif eq(variables.isDev, true) }}: workingFile: .npmrc - task: npmAuthenticate@0 displayName: npm Authenticate enext-data-platform-backend/enext-data-platform-frontend/.npmrc inputs: ${{ if eq(variables.isQa, true) }}: workingFile: $(Pipeline.Workspace)/enext-data-platform-backend/enext-data-platform-frontend/.npmrc ${{ elseif eq(variables.isDev, true) }}: workingFile: enext-data-platform-frontend/.npmrc - task: Docker@0 displayName: 'Build an image' inputs: command: 'buildAndPush' containerregistrytype: 'Container Registry' imageName: "$(Build.Repository.Name):$(Build.BuildId)" ${{ if eq(variables.isQa, true) }}: buildContext: $(Pipeline.Workspace)/enext-data-platform-backend/ Dockerfile: $(Pipeline.Workspace)/enext-data-platform-backend/Dockerfile ${{ elseif eq(variables.isDev, true) }}: buildContext: enext-data-platform-backend Dockerfile: 'Dockerfile' - script: | set -x env pwd echo "CONTAINER_APP=$(Build.Repository.Name):$(Build.BuildId)" > artifact.txt source ./artifact.txt docker save $CONTAINER_APP > container.tar ls -la displayName: 'Shell Script: APP' - task: PublishPipelineArtifact@1 displayName: 'Publish Pipeline Artifact - container id' inputs: targetPath: artifact.txt artifact: artifact - task: PublishPipelineArtifact@1 displayName: 'Publish Pipeline Artifact - container data' inputs: targetPath: container.tar artifact: container - task: Docker@0 displayName: 'Build an image' inputs: command: 'buildAndPush' containerregistrytype: 'Container Registry' imageName: "$(Build.Repository.Name):$(Build.BuildId)" ${{ if eq(variables.isQa, true) }}: buildContext: $(Pipeline.Workspace)/enext-data-platform-backend/ Dockerfile: $(Pipeline.Workspace)/enext-data-platform-backend/Dockerfile ${{ elseif eq(variables.isDev, true) }}: buildContext: enext-data-platform-backend Dockerfile: 'Dockerfile' - script: | echo "CONTAINER_KNEX=$(Build.Repository.Name):$(Build.BuildId)" > artifact-knex.txt source ./artifact-knex.txt docker save $CONTAINER_KNEX > container-knex.tar ls -la displayName: 'Shell Script: knex' - task: PublishPipelineArtifact@1 displayName: 'Publish Pipeline Artifact - container id: knex' inputs: targetPath: artifact-knex.txt artifact: artifact-knex - task: PublishPipelineArtifact@1 displayName: 'Publish Pipeline Artifact - container data: knex' inputs: targetPath: container-knex.tar artifact: container-knex - job: dbschema displayName: DB Schema steps: - checkout: dbschema submodules: true - script: ls -la - task: Docker@0 displayName: 'Build an image' inputs: command: 'buildAndPush' buildContext: enext-matflow-dbschema containerregistrytype: 'Container Registry' imageName: "$(Build.Repository.Name):$(Build.BuildId)" Dockerfile: 'Dockerfile' - script: | echo "CONTAINER_DB=$(Build.Repository.Name):$(Build.BuildId)" > sql_artifact.txt source ./sql_artifact.txt docker save $CONTAINER_DB > sql_container.tar ls -la displayName: 'Shell Script: DB' - task: PublishPipelineArtifact@1 displayName: 'Publish Pipeline Artifact - sql container id' inputs: targetPath: sql_artifact.txt artifact: sql_artifact - task: PublishPipelineArtifact@1 displayName: 'Publish Pipeline Artifact - sql container data' inputs: targetPath: sql_container.tar artifact: sql_container
当前问题:流水线运行时会同时触发QA和DEV环境的构建,希望实现手动触发时能通过下拉选择指定环境(界面效果为:触发流水线时弹出选项框,可选择QA或DEV)。
解决方案步骤
1. 添加运行时参数
在yaml最顶部添加参数,让用户手动选择目标环境:
parameters: - name: targetEnvironment type: string default: 'QA' values: - 'QA' - 'DEV' displayName: '选择要构建的环境'
2. 修正阶段条件
替换原有的condition,确保仅在手动触发时运行,且匹配选择的环境:
condition: and(eq(variables['Build.Reason'], 'Manual'), in('${{ parameters.targetEnvironment }}', 'QA', 'DEV'))
3. 替换变量判断逻辑
把所有eq(variables.isQa, true)和eq(variables.isDev, true)替换为参数判断:
- QA环境判断:
${{ eq(parameters.targetEnvironment, 'QA') }} - DEV环境判断:
${{ eq(parameters.targetEnvironment, 'DEV') }}
修改后的完整代码
parameters: - name: targetEnvironment type: string default: 'QA' values: - 'QA' - 'DEV' displayName: '选择要构建的环境' # BUILD ENVIRONMENTS - stage: build_envs dependsOn: quality_control displayName: Build Envs condition: and(eq(variables['Build.Reason'], 'Manual'), in('${{ parameters.targetEnvironment }}', 'QA', 'DEV')) jobs: - job: Job_build displayName: Application Build steps: - ${{ if eq(parameters.targetEnvironment, 'QA') }}: - checkout: backend-qa path: enext-data-platform-backend - script: rm -rf enext-data-platform-backend/enext-data-platform-frontend - checkout: frontend-qa path: enext-data-platform-backend/enext-data-platform-frontend #submodules: true - script: | ls -la $(Pipeline.Workspace)/enext-data-platform-backend ls -la $(Pipeline.Workspace)/enext-data-platform-backend/enext-data-platform-frontend - powershell: | Write-Host "##vso[build.addbuildtag]qa" - ${{ elseif eq(parameters.targetEnvironment, 'DEV') }}: - checkout: backend-dev submodules: true - script: git rev-parse HEAD - script: ls -la - powershell: | Write-Host "##vso[build.addbuildtag]dev" - task: npmAuthenticate@0 displayName: npm Authenticate enext-data-platform-backend/.npmrc inputs: ${{ if eq(parameters.targetEnvironment, 'QA') }}: workingFile: $(Pipeline.Workspace)/enext-data-platform-backend/.npmrc ${{ elseif eq(parameters.targetEnvironment, 'DEV') }}: workingFile: .npmrc - task: npmAuthenticate@0 displayName: npm Authenticate enext-data-platform-backend/enext-data-platform-frontend/.npmrc inputs: ${{ if eq(parameters.targetEnvironment, 'QA') }}: workingFile: $(Pipeline.Workspace)/enext-data-platform-backend/enext-data-platform-frontend/.npmrc ${{ elseif eq(parameters.targetEnvironment, 'DEV') }}: workingFile: enext-data-platform-frontend/.npmrc - task: Docker@0 displayName: 'Build an image' inputs: command: 'buildAndPush' containerregistrytype: 'Container Registry' imageName: "$(Build.Repository.Name):$(Build.BuildId)" ${{ if eq(parameters.targetEnvironment, 'QA') }}: buildContext: $(Pipeline.Workspace)/enext-data-platform-backend/ Dockerfile: $(Pipeline.Workspace)/enext-data-platform-backend/Dockerfile ${{ elseif eq(parameters.targetEnvironment, 'DEV') }}: buildContext: enext-data-platform-backend Dockerfile: 'Dockerfile' - script: | set -x env pwd echo "CONTAINER_APP=$(Build.Repository.Name):$(Build.BuildId)" > artifact.txt source ./artifact.txt docker save $CONTAINER_APP > container.tar ls -la displayName: 'Shell Script: APP' - task: PublishPipelineArtifact@1 displayName: 'Publish Pipeline Artifact - container id' inputs: targetPath: artifact.txt artifact: artifact - task: PublishPipelineArtifact@1 displayName: 'Publish Pipeline Artifact - container data' inputs: targetPath: container.tar artifact: container - task: Docker@0 displayName: 'Build an image' inputs: command: 'buildAndPush' containerregistrytype: 'Container Registry' imageName: "$(Build.Repository.Name):$(Build.BuildId)" ${{ if eq(parameters.targetEnvironment, 'QA') }}: buildContext: $(Pipeline.Workspace)/enext-data-platform-backend/ Dockerfile: $(Pipeline.Workspace)/enext-data-platform-backend/Dockerfile ${{ elseif eq(parameters.targetEnvironment, 'DEV') }}: buildContext: enext-data-platform-backend Dockerfile: 'Dockerfile' - script: | echo "CONTAINER_KNEX=$(Build.Repository.Name):$(Build.BuildId)" > artifact-knex.txt source ./artifact-knex.txt docker save $CONTAINER_KNEX > container-knex.tar ls -la displayName: 'Shell Script: knex' - task: PublishPipelineArtifact@1 displayName: 'Publish Pipeline Artifact - container id: knex' inputs: targetPath: artifact-knex.txt artifact: artifact-knex - task: PublishPipelineArtifact@1 displayName: 'Publish Pipeline Artifact - container data: knex' inputs: targetPath: container-knex.tar artifact: container-knex - job: dbschema displayName: DB Schema steps: - checkout: dbschema submodules: true - script: ls -la - task: Docker@0 displayName: 'Build an image' inputs: command: 'buildAndPush' buildContext: enext-matflow-dbschema containerregistrytype: 'Container Registry' imageName: "$(Build.Repository.Name):$(Build.BuildId)" Dockerfile: 'Dockerfile' - script: | echo "CONTAINER_DB=$(Build.Repository.Name):$(Build.BuildId)" > sql_artifact.txt source ./sql_artifact.txt docker save $CONTAINER_DB > sql_container.tar ls -la displayName: 'Shell Script: DB' - task: PublishPipelineArtifact@1 displayName: 'Publish Pipeline Artifact - sql container id' inputs: targetPath: sql_artifact.txt artifact: sql_artifact - task: PublishPipelineArtifact@1 displayName: 'Publish Pipeline Artifact - sql container data' inputs: targetPath: sql_container.tar artifact: sql_container
效果说明
手动触发流水线时,会出现下拉选项框,可选择QA或DEV,流水线会根据选择的环境执行对应分支的构建步骤,不会同时运行两个环境的任务。
内容的提问来源于stack exchange,提问作者AdanVRuiz
相关产品推荐
相关产品推荐

