Azure Pipelines:解决仅部署未选依赖的包时作业无法运行的问题
Azure Pipelines 选择性部署带依赖库的问题解决
场景与现有配置
我们需要让Azure Pipelines支持运行时选择要部署的库,参数定义如下:
parameters: - name: librariesToBePublished default: - name: my-awesome-package-1 dependsOn: [] - name: my-awesome-package-2 dependsOn: - my-awesome-package-1 - name: my-awesome-package-3 dependsOn: - my-awesome-package-1 - my-awesome-package-2 type: object - name: my-awesome-package-1 default: false type: boolean - name: my-awesome-package-2 default: false type: boolean - name: my-awesome-package-3 default: false type: boolean
通过each循环生成带依赖的发布作业,配置如下:
jobs: - ${{ each package in parameters.librariesToBePublished }}: - job: Publish_package_${{ replace(package.name, '-', '_') }} displayName: "Publish ${{ package.name }}" dependsOn: - ${{ each dep in package.dependsOn }}: - Publish_package_${{ replace(dep, '-', '_') }} condition: | and( succeeded(), eq('${{parameters[package.name]}}', true) )
遇到的问题
当勾选所有三个包时,流水线正常运行;但如果仅选择部署my-awesome-package-2且不选中其依赖my-awesome-package-1,由于依赖作业被跳过(而非成功),结合succeeded()条件会导致my-awesome-package-2的作业无法运行。
尝试过的无效方案
方案1:条件添加依赖
试图仅在依赖被选中时才添加到dependsOn中,但未解决问题:
jobs: - ${{ each package in parameters.librariesToBePublished }}: - job: Publish_package_${{ replace(package.name, '-', '_') }} displayName: "Publish ${{ package.name }}" dependsOn: - ${{ each dep in package.dependsOn }}: - ${{ if eq('${{parameters[dep]}}', true) }}: - Publish_package_${{ replace(dep, '-', '_') }} condition: | and( succeeded(), eq('${{parameters[package.name]}}', true) )
方案2:扩展成功条件
尝试用or(succeeded(), skipped())处理跳过的依赖,但Azure Pipelines中不存在skipped()函数,且无法在condition中引用依赖参数:
jobs: - ${{ each package in parameters.librariesToBePublished }}: - job: Publish_package_${{ replace(package.name, '-', '_') }} displayName: "Publish ${{ package.name }}" dependsOn: - ${{ each dep in package.dependsOn }}: - Publish_package_${{ replace(dep, '-', '_') }} condition: | and( or(succeeded(), skipped()), eq('${{parameters[package.name]}}', true) )
可行解决方案
通过动态生成依赖条件,针对每个依赖判断:要么依赖作业成功(如果依赖被选中运行),要么依赖未被选中(参数为false)。将这些条件组合后,再结合当前包被选中的条件,即可解决问题。
最终配置如下:
jobs: - ${{ each package in parameters.librariesToBePublished }}: - job: Publish_package_${{ replace(package.name, '-', '_') }} displayName: "Publish ${{ package.name }}" dependsOn: - ${{ each dep in package.dependsOn }}: - Publish_package_${{ replace(dep, '-', '_') }} condition: | and( eq('${{ parameters[package.name] }}', true), ${{ if ne(length(package.dependsOn), 0) }} and( ${{ each dep in package.dependsOn }} or( succeeded('Publish_package_${{ replace(dep, '-', '_') }}'), eq('${{ parameters[dep] }}', false) ) ${{ if not(last()) }}, ) ) ${{ else }} true ${{ endif }} )
原理说明
- 编译时针对每个依赖动态生成条件:
or(succeeded('依赖作业名'), eq('依赖参数', false)) - 所有依赖的条件通过
and组合,确保每个依赖要么已成功发布,要么未被选择 - 最后结合当前包被选中的条件(
eq('${{ parameters[package.name] }}', true)),只有满足所有条件时作业才会运行
内容的提问来源于stack exchange,提问作者yenerunver
相关产品推荐
相关产品推荐

