【问题标题】:Multiple separate triggers in azure-pipelines.ymlazure-pipelines.yml 中的多个单独触发器
【发布时间】:2020-01-03 20:06:53
【问题描述】:

我目前在子目录中有一个带有服务的 monorepo,我倾向于将其变成带有 metarepo 的 multirepo。

我决定尝试 Azure DevOps 的原因之一是有人告诉我,您可以在子目录中设置触发器,例如:

trigger:
  branches:
    include:
    - master
  paths:
    include:
    - client

经过测试,它可以工作。

但是,我想知道是否可以有多个独立的触发器,或者这是否需要一个 polyrepo 或多个 .yml?原因是如果 client 服务中只有更改,它只会触发该组测试、构建和部署,而不触发 api 服务来运行测试、构建和部署。

例如:

trigger:
  branches:
    include:
    - master
  paths:
    include:
    - client

  stages:
    ...
    Run tests
    If tests pass, build and push to ACR
    Deploy to AKS
    ...

trigger:
  branches:
    include:
    - master
  paths:
    include:
    - api

  stages:
    ...
    Run tests
    If tests pass, build and push to ACR
    Deploy to AKS
    ...

这样,一个变化不会导致整个应用程序被重建,只是改变了什么。

但是,这是否需要多个 .yml 文件(甚至不确定是否可以识别除 azure-pipelines.yml 以外的任何文件),这是否需要一个 polyrepo,或者这在单个 azure-pipelines.yml 中是否可行,我只是不看到了吗?

【问题讨论】:

  • 检查一下docs.microsoft.com/en-us/azure/devops/pipelines/test/… 是的,您可以拥有多个具有任何名称的 .yml 文件。创建构建管道时,您选择并引用现有的 yaml。没有简单的方法可以根据某个 git 目录中的更改来触发测试。您引用的是构建任务条件。但是没有可以用作条件的内置变量。可能有一些复杂的 API 操作可以通过点击 GIT api 组合在一起。

标签: azure azure-devops azure-pipelines


【解决方案1】:

如果我正确理解您的要求。您可以在单个 azure-pipeline.yml 中实现此目的。请检查下面的示例 yml。

trigger:
  branches:
    include:
    - master
  paths:
    include:
    - client/*
    - api/*

jobs:
- job: getchangepath
  pool:
    vmImage: 'windows-latest'
  steps: 
  - powershell: |
      $url="$(System.CollectionUri)/$(System.TeamProject)/_apis/git/repositories/$(Build.Repository.ID)/commits/$(Build.SourceVersion)/changes?api-version=5.1"
      $result = Invoke-RestMethod -Uri $url -Headers @{Authorization = "Bearer $(System.AccessToken)"} -Method GET
                       
      $changesFolder = $result.changes | Where-Object{$_.item.gitObjectType -match "tree"} | Select-Object -Property {$_.item.path}
     
      foreach($path in $changesFolder){
        if($path -match '/client'){
          echo "##vso[task.setvariable variable=Client;isOutput=true]$True"
          break
        }
      }

      foreach($path in $changesFolder){
        if($path -match '/api'){
          echo "##vso[task.setvariable variable=Api;isOutput=true]$True"
          break
        }
      }
    name: MyVariable

- job: client
  pool :
    vmImage: 'windows-latest'
  dependsOn: getchangepath
  condition: eq(dependencies.getchangepath.outputs['Myvariable.Client'], 'true')
  steps:
  - powershell: echo 'client job start'
  
- job: api
  pool :
    vmImage: 'windows-latest'
  dependsOn: getchangepath
  condition: eq(dependencies.getchangepath.outputs['Myvariable.Api'], 'true')
  steps:
  - powershell: echo 'api job start'

在上面的 yml.我有三份工作。在第一份工作getchangepath 中,我在powershell 任务中调用git get changes rest api 以获取触发构建的更改路径。如果路径包含路径/client/api,则为output the variables

Job client 和job api 依赖于job getchangepath 并且会在job 中输出变量的条件下执行获取更改路径

假设我更改了文件夹客户端中的文件并将更改提交到 azure repo。然后在工作getchangepath 完成后。 MyVariable.Client 将设置为 true。然后 Job 客户端将评估其状况并开始。 Job Api 将失败并被跳过。

【讨论】:

  • 嗨@eox.dev 你检查了上面的脚本,怎么样?如果有任何问题,请告诉我?
  • 终于有机会回到这个话题了。像冠军一样工作!
  • 路径中需要通配符吗?
【解决方案2】:

我最近遇到了这个问题。您无需在上述解决方案中硬编码和访问 DevOps API 和 PowerShell 代码。

根据 Azure DevOps 官方文档,这是一个使用开箱即用 YAMLworkingDirectory property 的更简单的解决方案。

像这样设置项目结构,每个存储库都有自己的 YAML 文件:

.
├── README.md
├── azure-pipelines.yml
├── service-a
|── azure-pipelines-a.yml
│   └── …
└── service-b
        |── azure-pipelines-b.yml
        └── …

您可能不需要根管道,但如果需要,您将需要忽略子项目:

# Excerpt from /azure-pipeline.yml 

trigger:
  paths:
    exclude: # Exclude!
      - 'service-a/*'
      - 'service-b/*'

而在子项目中,你希望他们关注自己:

# Excerpt from /service-a/azure-pipeline-a.yml

trigger:
  paths:
    include: # Include!
      - 'service-a/*' # or 'service-b/*'

警告 - 工作目录!

您的子项目管道仍在以根目录作为您的工作目录运行。例如,您可以使用 workingDirectory 键更改此设置(使用变量来避免重复):

variables:
  - name: working-dir
    value: 'service-b/'

steps:
- script: npm install
  workingDirectory: $(working-dir)

- script: npm run task
  workingDirectory: $(working-dir)

如果您的项目共享步骤,则应改用Pipeline Templates (in another repository) per official docs

【讨论】:

  • 但是你还需要创建多个管道并指定每个yml文件吗?使用 PS 脚本,您可以在一个 yml 管道中管理所有这些。我说的对吗?
  • 是的,每个目录都需要单独的管道。哪个更好将取决于您的项目的规模和复杂性。我个人认为这样的脚本使调试变得困难。我会与多个管道解耦,并根据需要将管道模板用于重复性任务。
  • @julie-ng 我已经尝试过这种方法并且效果很好,感谢这个很好的例子。但是,当在这些文件夹中进行一些更改时,我在 service-a 和 service-b 中设置的管道不会被触发,只有根管道会被触发。有没有办法让 service-a、service-b 管道自动触发?有什么建议吗?
【解决方案3】:

如果你用上述方法得到203响应你可以试试这个方法

$userName = "whatever"
$AuthInfo = [Conver]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $userName,$(PAT)))
$result = Invoke-RestMethod -Uri $url -Headers @{Authorization = "Basic {0} $AuthInfo" } -Method GET

我在 powershell 上运行它,它工作正常。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-12-18
    • 1970-01-01
    • 2022-11-11
    • 2020-10-19
    • 1970-01-01
    • 2018-08-20
    • 2018-06-25
    • 1970-01-01
    相关资源
    最近更新 更多