azure-devopsazure-pipelinesazure-pipelines-yaml

Azure Pipelines - Do something on deployment jobs failed or succeeded


What i want to achieve:

After all deployment jobs i want to run powershell script, but knowing which branch has triggered this pipeline run, and whether all deployment jobs succeeded or not.

My pipeline looks like this:

trigger:
  branches:
    include:
      - qa
      - main

variables:
  - name: targetEnv
    ${{ if in(variables['Build.SourceBranch'], 'refs/heads/qa') }}:
      value: $(QA)
    ${{ elseif eq(variables['Build.SourceBranch'], 'refs/heads/main') }}:
      value: $(PROD)
    ${{ else }}:
      value: "Unknown"

stages:
- stage: CI
  jobs:
  - job: Build
    pool:
      vmImage: windows-latest
    steps:
          (... some tasks)

- stage: CD
  jobs:
  - deployment: MyUi_deploy
    strategy:
      runOnce:
        deploy:
          steps:
          (... some tasks)
          
  - deployment: 'ServiceOne_deploy'
    strategy:
      runOnce:
        deploy:
          steps:
          (... some tasks)
          
  - job: StartMyPSscript
    displayName: 'Here i want to be after all deployments are completed'
    steps:
          (... some tasks)

I want job "StartMyPSscript" to be started after all "deployment" steps are completed, and in this "StartMyPSscript" step i need to know whether deployment steps failed, or succeeded

I have tried to do this part like:


  - job: StartMyPSscript_Failure
    displayName: 'Here i want to be after all deployments are completed but any of them failed'
    dependsOn:
      - MyUi_deploy
      - ServiceOne_deploy
    condition: and(eq(variables['targetEnv'], variables['QA']), failed())
          
  - job: StartMyPSscript_Success
    displayName: 'Here i want to be after all deployments are completed succesfully'
    dependsOn:
      - MyUi_deploy
      - ServiceOne_deploy
    condition: and(eq(variables['targetEnv'], variables['QA']), succeeded())

But it didn't work, none of these jobs were started - i assume that using failed() or succeeded() within job, not stage is not working as intended.

Then i tried doing it like:

   - job: StartMyPSscript
    displayName: 'Here i want to be after all above deployments are completed'
    dependsOn:
      - MyUi_deploy
      - ServiceOne_deploy
      
    steps:
    - task: PowerShell@2
      condition: and(eq(variables['targetEnv'], variables['QA']), succeeded())
      displayName: 'Success'
      inputs:
        targetType: 'inline'
        script: (some script)
        
    - task: PowerShell@2
      condition: and(eq(variables['targetEnv'], variables['QA']), failed())
      displayName: 'Failure'
      inputs:
        targetType: 'inline'
        script: (some script)

But it was also a fail, due to problem with variables (?):

Evaluating: eq(variables['targetEnv'], variables['QA'])
Expanded: eq('$(QA)', 'MyApp QA')
Result: False

Where QA is of course defined in Variables of this Pipeline to 'MyApp QA'

So question is - how to do it properly, with all standards and best practices


Solution

  • Test the same YAML sample and I can reproduce the same issue.

    enter image description here

    From your YAML sample, you are using the nested variable: targetEnv in condition.

    When you use the format $(varname) in Pipeline condition to get the actual value of nested variable, it is not passed correctly. This is because this format processes the variable at runtime before a task/job executes. At this point in time, the variable value has not been set correctly.

    To solve this issue, you can use the format: $[variables.var] to set the targetEnv variable value. This format will process the variable at runtime.

    YAML sample:

    variables:
      - name: targetEnv
        ${{ if in(variables['Build.SourceBranch'], 'refs/heads/qa') }}:
          value: $[variables.QA]
        ${{ elseif eq(variables['Build.SourceBranch'], 'refs/heads/main') }}:
          value: $[variables.PROD]
        ${{ else }}:
          value: "Unknown"
    
    
    stages:
    - stage: CI
      jobs:
      - job: Build
        pool:
          vmImage: windows-latest
        steps:
              (... some tasks)
    
    - stage: CD
      jobs:
      - deployment: MyUi_deploy
        strategy:
          runOnce:
            deploy:
              steps:
              (... some tasks)
              
      - deployment: 'ServiceOne_deploy'
        strategy:
          runOnce:
            deploy:
              steps:
              (... some tasks)
      - job: StartMyPSscript_Failure
        displayName: 'Here i want to be after all deployments are completed but any of them failed'
        dependsOn:
          - MyUi_deploy
          - ServiceOne_deploy
        condition: and(eq(variables['targetEnv'], variables['QA']), failed())
              
      - job: StartMyPSscript_Success
        displayName: 'Here i want to be after all deployments are completed succesfully'
        dependsOn:
          - MyUi_deploy
          - ServiceOne_deploy
        condition: and(eq(variables['targetEnv'], variables['QA']), succeeded())
    

    Result:

    enter image description here

    For more detailed info, you can refer to this doc: Runtime expression syntax