kevmando
kevmando

Reputation: 1137

How to send post build message in azure DevOps YAML pipeline?

I'm trying to send a post-build Slack message after the job is done/failed in a Azure DevOps YAML pipeline. But it seems I can't find a proper condition setting.

Basically, I have three stages: test, build, and notification.

I tried the following at last, but dependencies.UnitTest.result returns null, so not giving me Succeeded or Failed.

I also tried a bunch of different conditions but they didn't work. For example, a plain succeeded() and failed() without dependencies, or succeeded('Test') as stage level or succeeded('UnitTest') as job level.

In most cases, they send the success message even if they failed at the Test stage, or a syntax error for job names as argument in succeeded() or failed()

What is the proper condition to send a post-build message like 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)

--- EDIT ---
MS support confirmed jobs in multi stages can't support as yaml syntax itself.

Not same as the original flow as expected, but you can split succeed and fail into different stages as follow. (It may increase quite number of stages just for the notification if you want different message for each jobs..)

...

- 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)

Upvotes: 2

Views: 5842

Answers (2)

Krzysztof Madej
Krzysztof Madej

Reputation: 40533

It is possible but you have to use REST API. With below YAML you will get what you described:

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)

Let me explain what I did above:

  • I made a call to REST API to get result of step from previous stage (as the the moment is not possible to get task result)
  • I assign status of that step to output variable
  • I used this variable as condition to run specific job Succeed or Fail

Remark: before you run code, please change orgName to your.

EDIT

Below url return you details for your build. But you will not fine there information about specific tasks or stages. But you will get there url for a timeline.

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

This REST endpoint will return you a timeline which includes details for tasks and stages.

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

Upvotes: 3

Cece Dong - MSFT
Cece Dong - MSFT

Reputation: 31003

You can specify the conditions under which each stage runs. By default, a stage runs if it does not depend on any other stage, or if all of the stages that it depends on have completed and succeeded.

Example to run a stage based upon the status of running a previous stage:

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')

Example of using a custom condition:

stages:
- stage: A

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

Note: You cannot currently specify that a stage run based on the value of an output variable set in a previous stage.

Documentation:

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

Upvotes: 2

Related Questions