【问题标题】:How to send post build message in azure DevOps YAML pipeline?如何在 azure DevOps YAML 管道中发送构建后消息?
【发布时间】:2020-05-10 04:40:16
【问题描述】:

我正在尝试在 Azure DevOps YAML 管道中完成/失败后发送构建后 Slack 消息。但似乎我找不到合适的条件设置。

基本上,我分为三个阶段:测试、构建和通知。

我最后尝试了以下方法,但 dependencies.UnitTest.result 返回 null,所以没有给我 SucceededFailed

我也尝试了很多不同的条件,但都没有奏效。例如,没有依赖关系的普通 succeeded()failed(),或 succeeded('Test') 作为阶段级别或 succeeded('UnitTest') 作为作业级别。

在大多数情况下,即使在测试阶段失败,它们也会发送成功消息,或者将作业名称作为 succeeded()failed() 中的参数的语法错误

像 Jenkins 这样发送构建后消息的合适条件是什么?

stages:
- stage: Test
  jobs:
  - job: UnitTest
    steps:
    - script: echo UnitTest
    - script: exit 1

- stage: Build
  jobs:
  - job: Build
    steps:
    - script: echo Build

- stage: Notify
  dependsOn:
  - Test
  - Build

  condition: succeededOrFailed()
  jobs:
  - job: Succeed
    condition: eq(dependencies.UnitTest.result, 'Succeeded')
    steps:
    - script: echo Succeed #(slack)

  - job: Fail
    condition: eq(dependencies.UnitTest.result, 'Failed')
    steps:
    - script: echo Fail #(slack)

--- 编辑 ---
MS 支持多阶段确认的作业,不能作为 yaml 语法本身支持。

与预期的原始流程不同,但您可以将成功和失败分为不同的阶段,如下所示。 (如果你想为每个作业提供不同的消息,它可能会增加相当多的阶段,只是为了通知..)

...

- stage: Notify_Succeeded
  condition: succeeded()

  jobs:
  - job: Succeed
    steps:
    - script: echo Succeed #(slack)

- stage: Notify_Fail
  condition: failed()
  jobs:
  - job: Fail
    steps:
    - script: echo Fail #(slack)

【问题讨论】:

  • 您可以使用 WebHooks 来完成此操作:docs.microsoft.com/en-us/azure/devops/service-hooks/services/…
  • 谢谢@derekbaker783 我可以看到服务挂钩有松弛和一般的网络挂钩支持,但它似乎只发送预定义的消息。有什么方法可以发送阻止套件消息吗?
  • 另外,有些人可能会想知道条件本身,以防他们想发布工作,而不仅仅是通知。 Azure devops doc 可能会错过阶段到阶段条件的某些内容。我从他们的文档中复制了这个 dependencies.result 东西,但这个例子处于同一阶段并且有效。但就我而言,它们处于不同的阶段。我想知道是否会有像 jenkins 那样的简单构建状态变量。
  • @CeceDong-MSFT 不幸的是,他的样本还不适合我。一旦我可以让它在我的身上工作,我会确认。

标签: azure-devops azure-pipelines


【解决方案1】:

这是可能的,但您必须使用 REST API。使用以下 YAML,您将获得您所描述的内容:

variables:
  orgName: 'thecodemanual'

stages:
- stage: Test
  jobs:
  - job: UnitTest
    steps:
    - script: echo UnitTest
    - script: exit 1

- stage: Build
  jobs:
  - job: Build
    steps:
    - script: echo Build

- stage: Notify
  dependsOn:
  - Test
  - Build

  condition: succeededOrFailed()
  jobs:
  - job: InitialJob
    condition: always()
    steps:
    - pwsh: |
        $url = "https://dev.azure.com/$(orgName)/$(System.TeamProject)/_apis/build/builds/$(Build.BuildId)/timeline?api-version=5.1"
        $timeline = Invoke-RestMethod -Uri $url -Headers @{Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"}
        Write-Host "Pipeline = $($timeline | ConvertTo-Json -Depth 100)"

        $test = $timeline.records | where { $_.identifier -eq "Test.UnitTest" }

        $result = $test.result

        Write-Host "##vso[task.setvariable variable=testResult;isOutput=true]$result"
      name: initial
      env:
        SYSTEM_ACCESSTOKEN: $(system.accesstoken)

  - job: Succeed
    dependsOn: InitialJob
    condition: eq(dependencies.InitialJob.outputs['initial.testResult'], 'succeeded')
    steps:
    - script: echo Succeed #(slack)

  - job: Fail
    dependsOn: InitialJob
    condition: eq(dependencies.InitialJob.outputs['initial.testResult'], 'failed')
    steps:
    - script: echo Fail #(slack)

让我解释一下我在上面做了什么:

  • 我调用了 REST API 以获取上一阶段的步骤结果(因为目前无法获取任务结果)
  • 我将该步骤的状态分配给输出变量
  • 我使用这个变量作为条件来运行特定的作业SucceedFail

备注:在运行代码之前,请将orgName更改为您的。

编辑

下面的 url 返回您构建的详细信息。但是您不会在那里获得有关特定任务或阶段的信息。但是你会得到一个时间轴的 url。

https://dev.azure.com/$(orgName)/$(System.TeamProject)/_apis/build/builds/$(Build.BuildId)?api-version=5.1

此 REST 端点将为您返回一个时间表,其中包括任务和阶段的详细信息。

https://dev.azure.com/$(orgName)/$(System.TeamProject)/_apis/build/builds/$(Build.BuildId)/timeline?api-version=5.1

【讨论】:

  • 嗨,谢谢。看起来很复杂,但我会尝试更新。
  • 我有第 7 行错误说 Uri 为空或为空。但是,如果我单击 $url 值,它似乎会返回 json 响应。也许一些转换错误?时间线 = Invoke-RestMethod -Uri $build._links.timeline.href -Header ... 无法验证参数“Uri”上的参数。参数为 null 或为空。
  • 我简化了一点。现在您只需拨打一个电话 - 直接拨打时间线。你能试一试吗?顺便说一句,您对原始版本有疑问很奇怪。它适用于我的 Azure DevOps :)
  • 嗯不确定你和我的有什么区别:),但这次它没有给出错误,但似乎没有从 initial.testResult 返回结果 - 扩展:eq('', '失败') 结果:错误
  • 在第一个版本中,您首先调用了 build 并从该响应中获取了时间线 href。这里直接调用timeline。您可以尝试拨打邮递员的电话并检查您收到的内容吗?
【解决方案2】:

您可以指定每个阶段运行的条件。默认情况下,如果一个阶段不依赖于任何其他阶段,或者它所依赖的所有阶段都已完成并成功,则该阶段会运行。

根据运行前一个阶段的状态运行阶段的示例:

stages:
- stage: A

# stage B runs if A fails
- stage: B
  condition: failed()

# stage C runs if B succeeds
- stage: C
  dependsOn:
  - A
  - B
  condition: succeeded('B')

使用自定义条件的示例:

stages:
- stage: A

- stage: B
  condition: and(succeeded(), eq(variables['build.sourceBranch'], 'refs/heads/master'))

注意:您目前无法指定基于前一阶段中设置的输出变量的值运行阶段。

文档:

https://docs.microsoft.com/en-us/azure/devops/pipelines/process/stages?view=azure-devops&tabs=yaml#conditions

【讨论】:

  • 嗨,谢谢。这是我在报告问题后从 MS 那里听到的。似乎条件适用于同一阶段或阶段到阶段的工作,但不适用于多个阶段的工作。他们还建议在需要时请求功能。
  • 我们一直在改进产品,任何想法您都可以在这里提交建议:developercommunity.visualstudio.com/content/idea/…。目前,您可以按照@Krzysztof Madej 的建议尝试使用 api 的解决方法。
猜你喜欢
  • 2020-04-23
  • 2019-05-14
  • 2019-04-06
  • 2019-06-01
  • 2020-12-08
  • 2020-06-08
  • 2019-02-18
  • 2022-11-03
  • 2020-09-27
相关资源
最近更新 更多