Search code examples
azure-devopsazure-pipelinesazure-pipelines-yaml

Azure pipelines: deployment template with optional confirmation parameter does not succeed when reused


I'm in the process of creating a pipeline template to deploy our microservices. Simplified, the setup as follows:

parameters:
  - name: environment
    type: string
  - name: requireConfirmation
    type: boolean

jobs:
  - job: confirmDeployment
    displayName: Confirm deployment
    pool: server
    condition: ${{ parameters.requireConfirmation }}
    steps:
      - task: ManualValidation@0
        continueOnError: false
        inputs:
          instructions: 'Continue deployment to ${{ parameters.environment }} environment?'

  - job: deploy
    condition: or(eq('${{ parameters.requireConfirmation }}', false), succeeded('confirmDeployment'))
    timeoutInMinutes: 10
    steps:
      - script: echo "Fake deploying to $(environment)"
        displayName: 'Fake deployment'

And invoked using:


  # - build stage here

  - stage: deployTest
    displayName: Deploy to Test
    condition: succeeded()
    dependsOn:
      - build
    jobs:
    - template: pipeline/deploy.yml
      parameters:
        environment: 'test'
        requireConfirmation: false

  - stage: deployAcc
    displayName: Deploy to Acceptance
    condition: succeeded()
    dependsOn:
      - deployTest
    jobs:
      - template: pipeline/deploy.yml
        parameters:
          environment: 'acceptance'
          requireConfirmation: true

When using the script, the deployment successfully deploys to test without confirming the deployment on beforehand. The confirmation message is successfully displayed when deploying to the acceptance environment. Nothing happens however when I proceed the deployment to the acceptance environment.

My guess is that the acceptance deployment checks the result of the confirmDeployment job invoked in the deployTest stage instead of the deployAcc stage. As deployTest does not require a confirmation it was skipped instead of "succeeding".

I tried to suffix the jobs with the environment name:

- job: confirmDeployment_$(environment)
...
condition: or(eq('${{ parameters.requireConfirmation }}', false), succeeded('confirmDeployment_$(environment)'))

But apparently job names may only contain alfanumeric characters and underscores. Would anyone know how this can be resolved? I would rather not duplicate the stages for dev/acc/prod as that would make the template rather useless.


Solution

  • The following won't work because $(...) is the syntax to reference a pipeline variable:

    - job: confirmDeployment_$(environment)
    

    Use ${{ parameter.xxxx }} instead:

    - job: confirmDeployment_${{ parameters.environment }}
    

    Also, you can simplify your template by replacing conditions with template expressions ${{ if ... }}:

    parameters:
      - name: environment
        type: string
    
      - name: requireConfirmation
        type: boolean
    
    jobs:
      - ${{ if parameters.requireConfirmation }}:
        - job: confirmDeployment_${{ parameters.environment }}
          displayName: Confirm deployment
          pool: server
          steps:
            - task: ManualValidation@0
              continueOnError: false
              inputs:
                instructions: 'Continue deployment to ${{ parameters.environment }} environment?'
    
      - job: deploy_${{ parameters.environment }}
        ${{ if parameters.requireConfirmation }}:
          dependsOn: confirmDeployment_${{ parameters.environment }}
        timeoutInMinutes: 10
        steps:
          - script: echo "Fake deploying to $(environment)"
            displayName: 'Fake deployment'