是否可以为管道模板中的阶段设置基于 System.PullRequest.TargetBranch 的条件?
Is it possible to set a condition based on System.PullRequest.TargetBranch for a stage in a pipeline template?
我有一个 git 分支与环境直接相关的解决方案(必须这样,所以请不要讨论这是好是坏,我知道这不是最佳实践).
我们可以选择 运行 对环境进行验证部署(包括自动测试),而无需实际将解决方案部署到环境中。因此,我想设置一个管道,每当向该环境的分支打开拉取请求时,该管道 运行 都会对环境进行此验证。此外,我正在为大部分管道使用模板。主存储库中的实际管道只是一个指向另一个存储库中模板管道的微小解决方案。反过来,该模板具有针对每个相应环境的阶段。
我已经在主管道中成功添加了一个标识当前分支的解决方案,对于拉取请求应该是目标分支:
variables:
- name: currentBranch
${{ if eq(variables['Build.Reason'], 'PullRequest') }}:
value: $(System.PullRequest.TargetBranch)
${{ if ne(variables['Build.Reason'], 'PullRequest') }}:
value: $(Build.SourceBranch)
我想通过参数将此变量 currentBranch
发送到模板,因为我的模板管道根据分支有不同的阶段。我的解决方案是像这样使用管道:
extends:
template: <template-reference>
parameters:
branch: $(currentBranch)
...然后在我的管道中的一个阶段执行此操作:
- stage: TestAndDeployBranchName
condition: eq('${{ parameters.branch }}', 'refs/heads/branchName')
jobs:
- job1... etc.
基本上,如果当前分支是“branchName”,或者(对于拉取请求)当目标分支是“branchName”时,阶段应该 运行发送到模板。
但是,我看到here that System.PullRequest.TargetBranch
is not available for templates and further here当模板展开时,参数不适用于模板(变量为空)。因此我的管道没有按预期工作(条件没有在应该触发的时候触发,即当分支名称匹配时)。
有什么方法可以在模板中的条件下使用 System.PullRequest.TargetBranch
,还是我应该寻找其他解决方案?
检查您的脚本后,我们发现无法使用
variables:
- name: currentBranch
${{ if eq(variables['Build.Reason'], 'PullRequest') }}:
value: $(System.PullRequest.TargetBranch)
${{ if ne(variables['Build.Reason'], 'PullRequest') }}:
value: $(Build.SourceBranch)
在变量中。
变量会将第二个值复制到第一个值。
这将导致您的问题。
因此,就我而言,我创建了一个变通方法,希望这对您有所帮助。这是我的主要 yaml:
parameters:
- name: custom_agent
displayName: Use Custom Agent
type: boolean
default: true
- name: image
type: string
default: default
resources:
repositories:
- repository: templates
type: git
name: Tech-Talk/template
trigger: none
pool:
vmImage: windows-latest
# vmImage: ubuntu-20.04
stages:
- stage: A
jobs:
- job: A1
steps:
- task: PowerShell@2
name: printvar
inputs:
targetType: 'inline'
script: |
If("$(Build.Reason)" -eq "PullRequest"){
Write-Host "##vso[task.setvariable variable=currentBranch;isOutput=true]$(System.PullRequest.TargetBranch)"
}
else{
Write-Host "##vso[task.setvariable variable=currentBranch;isOutput=true]$(Build.SourceBranch)"
}
- stage: B
condition: eq(dependencies.A.outputs['A1.printvar.currentBranch'], 'refs/heads/master')
dependsOn: A
jobs:
- job: B1
variables:
varFromA: $[ stageDependencies.A.A1.outputs['printvar.currentBranch'] ]
steps:
- task: PowerShell@2
inputs:
targetType: 'inline'
script: |
# Write your PowerShell commands here.
Write-Host "$(varFromA)"
- template: temp.yaml@templates
parameters:
branchName: $(varFromA)
agent_pool_name: ''
db_resource_path: $(System.DefaultWorkingDirectory)
请注意:
如果我们使用它,我们需要修改您的临时 yaml。
我们需要将条件移动到主 yaml 并使临时 yaml 只剩下步骤。
进一步调查后,我得出结论,我正在尝试做的事情是不可能的。
简而言之,System.PullRequest.TargetBranch
(我假设 System.PullRequest
中至少有一些其他变量在模板的编译时不可用,这是在评估条件时。因此,在模板中的条件不可能。
由于我的目标是根据拉取请求的目标分支仅对拉取请求执行某些步骤 运行,因此我通过创建重复管道解决了这个问题。每个管道都是相同的,引用相同的模板,只是模板的输入参数不同。然后,我将每个“PR 管道”添加到 运行 作为分支策略的一部分,每个分支都适用。
这很好用,但是如果我对另一个分支有相同的要求,它需要我创建一个新的管道。此外,我必须单独维护每个 PR 管道(这可能是好的也可能是坏的)。
这不是一个理想的解决方案,但它确实有效。
参考 PR 渠道:
trigger: none # no trigger as PR triggers are set by branch policies
#This references the template repository to reuse the basic pipeline
resources:
repositories:
- repository: <template repo>
type: git # "git" means azure devops repository
name: <template name> # Syntax: <project>/<repo>
ref: refs/heads/master # Grab latest pipeline template from the master branch
stages:
- stage: VerifyPullRequest
condition: |
and(
not(failed()),
not(canceled()),
eq(variables['Build.Reason'], 'PullRequest')
)
displayName: 'Verify Pull Request'
jobs:
- template: <template reference> # Template reference
parameters:
image: <image>
targetBranch: <targetBranch> # Adjust this to match each respective relevant branch
targetBranch
参数是模板中相关地方使用的运行PR验证
分支政策示例:
(为每个相关分支设置)
Picture of branch policy set up
我有一个 git 分支与环境直接相关的解决方案(必须这样,所以请不要讨论这是好是坏,我知道这不是最佳实践).
我们可以选择 运行 对环境进行验证部署(包括自动测试),而无需实际将解决方案部署到环境中。因此,我想设置一个管道,每当向该环境的分支打开拉取请求时,该管道 运行 都会对环境进行此验证。此外,我正在为大部分管道使用模板。主存储库中的实际管道只是一个指向另一个存储库中模板管道的微小解决方案。反过来,该模板具有针对每个相应环境的阶段。
我已经在主管道中成功添加了一个标识当前分支的解决方案,对于拉取请求应该是目标分支:
variables:
- name: currentBranch
${{ if eq(variables['Build.Reason'], 'PullRequest') }}:
value: $(System.PullRequest.TargetBranch)
${{ if ne(variables['Build.Reason'], 'PullRequest') }}:
value: $(Build.SourceBranch)
我想通过参数将此变量 currentBranch
发送到模板,因为我的模板管道根据分支有不同的阶段。我的解决方案是像这样使用管道:
extends:
template: <template-reference>
parameters:
branch: $(currentBranch)
...然后在我的管道中的一个阶段执行此操作:
- stage: TestAndDeployBranchName
condition: eq('${{ parameters.branch }}', 'refs/heads/branchName')
jobs:
- job1... etc.
基本上,如果当前分支是“branchName”,或者(对于拉取请求)当目标分支是“branchName”时,阶段应该 运行发送到模板。
但是,我看到here that System.PullRequest.TargetBranch
is not available for templates and further here当模板展开时,参数不适用于模板(变量为空)。因此我的管道没有按预期工作(条件没有在应该触发的时候触发,即当分支名称匹配时)。
有什么方法可以在模板中的条件下使用 System.PullRequest.TargetBranch
,还是我应该寻找其他解决方案?
检查您的脚本后,我们发现无法使用
variables:
- name: currentBranch
${{ if eq(variables['Build.Reason'], 'PullRequest') }}:
value: $(System.PullRequest.TargetBranch)
${{ if ne(variables['Build.Reason'], 'PullRequest') }}:
value: $(Build.SourceBranch)
在变量中。 变量会将第二个值复制到第一个值。 这将导致您的问题。 因此,就我而言,我创建了一个变通方法,希望这对您有所帮助。这是我的主要 yaml:
parameters:
- name: custom_agent
displayName: Use Custom Agent
type: boolean
default: true
- name: image
type: string
default: default
resources:
repositories:
- repository: templates
type: git
name: Tech-Talk/template
trigger: none
pool:
vmImage: windows-latest
# vmImage: ubuntu-20.04
stages:
- stage: A
jobs:
- job: A1
steps:
- task: PowerShell@2
name: printvar
inputs:
targetType: 'inline'
script: |
If("$(Build.Reason)" -eq "PullRequest"){
Write-Host "##vso[task.setvariable variable=currentBranch;isOutput=true]$(System.PullRequest.TargetBranch)"
}
else{
Write-Host "##vso[task.setvariable variable=currentBranch;isOutput=true]$(Build.SourceBranch)"
}
- stage: B
condition: eq(dependencies.A.outputs['A1.printvar.currentBranch'], 'refs/heads/master')
dependsOn: A
jobs:
- job: B1
variables:
varFromA: $[ stageDependencies.A.A1.outputs['printvar.currentBranch'] ]
steps:
- task: PowerShell@2
inputs:
targetType: 'inline'
script: |
# Write your PowerShell commands here.
Write-Host "$(varFromA)"
- template: temp.yaml@templates
parameters:
branchName: $(varFromA)
agent_pool_name: ''
db_resource_path: $(System.DefaultWorkingDirectory)
请注意: 如果我们使用它,我们需要修改您的临时 yaml。 我们需要将条件移动到主 yaml 并使临时 yaml 只剩下步骤。
进一步调查后,我得出结论,我正在尝试做的事情是不可能的。
简而言之,System.PullRequest.TargetBranch
(我假设 System.PullRequest
中至少有一些其他变量在模板的编译时不可用,这是在评估条件时。因此,在模板中的条件不可能。
由于我的目标是根据拉取请求的目标分支仅对拉取请求执行某些步骤 运行,因此我通过创建重复管道解决了这个问题。每个管道都是相同的,引用相同的模板,只是模板的输入参数不同。然后,我将每个“PR 管道”添加到 运行 作为分支策略的一部分,每个分支都适用。
这很好用,但是如果我对另一个分支有相同的要求,它需要我创建一个新的管道。此外,我必须单独维护每个 PR 管道(这可能是好的也可能是坏的)。
这不是一个理想的解决方案,但它确实有效。
参考 PR 渠道:
trigger: none # no trigger as PR triggers are set by branch policies
#This references the template repository to reuse the basic pipeline
resources:
repositories:
- repository: <template repo>
type: git # "git" means azure devops repository
name: <template name> # Syntax: <project>/<repo>
ref: refs/heads/master # Grab latest pipeline template from the master branch
stages:
- stage: VerifyPullRequest
condition: |
and(
not(failed()),
not(canceled()),
eq(variables['Build.Reason'], 'PullRequest')
)
displayName: 'Verify Pull Request'
jobs:
- template: <template reference> # Template reference
parameters:
image: <image>
targetBranch: <targetBranch> # Adjust this to match each respective relevant branch
targetBranch
参数是模板中相关地方使用的运行PR验证
分支政策示例: (为每个相关分支设置) Picture of branch policy set up