'How to use the Manual Validation task in Azure DevOps pipeline?

I've have read the official document for the Manual Validation task.

This is one of my stages in my YAML Pipeline:

  - stage: Prod
    dependsOn: QA
    condition: and(succeeded('QA'), eq(variables['Build.SourceBranch'], 'refs/heads/release'))
    jobs:
      - job: WaitForValidation
        pool: server
        displayName: Wait for approval
        timeoutInMinutes: 4320
        steps:
          - task: ManualValidation@0
            timeoutInMinutes: 1440 # task times out in 1 day
            inputs:
              notifyUsers: |
                [email protected]
                [email protected]
              instructions: 'Approve the deployment to Prod'
      - template: build-and-deploy-stage.yml
        parameters:
          targetEnv: 'Prod'
          dataset: 'prod'
          token: $(deploymentTokenProd)

And this is build-and-deploy-stage.yml:

parameters:
  - name: targetEnv
    type: string
  - name: dataset
    type: string
  - name: token
    type: string

jobs:
  - job: Deploy
    displayName: Build and deploy to ${{ parameters.targetEnv }}
    steps:
      - task: NodeTool@0
        displayName: 'Install Node LTS'
        inputs:
          versionSpec: '14.18.x'
      # … not relevant but using parameters.dataset and parameters.token

Unfortunately, the Deploy job is run even though no one has manually approved/resumed the pipeline.

Can it only be used at the end of a stage to move to the next one?



Solution 1:[1]

I've ended up using dependsOn on the job.

Solution 2:[2]

I think your problem is that you actually have to jobs in your pipeline, as the yaml template has a job specified in it. Haven't actually tested it, but I would think that the manual validation step in first job only applies in that job, and the another job starts regardless.

There are probably multiple ways to solve the problem (by adding DependsOn-clause and/or changing the template to only have steps), but I would actually suggest adding an environment in Azure DevOps (under Pipelines -> Environments, let's call it 'Production' for now), adding manual approval to that environment, and changing the Prod-stage and jobs to be a deployment job that targets the 'Production'-enviroment.

So something like:

  - stage: Prod
    displayName: "Deployment: Production"
    dependsOn: QA
    jobs:
      - deployment: deploy_prod
        displayName: Deploy Production        
        pool: server
        condition: and(succeeded('QA'), eq(variables['Build.SourceBranch'], 'refs/heads/release'))
        environment: Production
        strategy:
          runOnce:
            deploy:
              steps:
                - template: build-and-deploy-stage.yml
                  parameters: 
                    targetEnv: 'Prod'
                    dataset: 'prod'
                    token: $(deploymentTokenProd)

And template with just steps:

parameters:
  - name: targetEnv
    type: string
  - name: dataset
    type: string
  - name: token
    type: string

steps:
  - task: NodeTool@0
    displayName: 'Install Node LTS'
    inputs:
      versionSpec: '14.18.x'
  # … not relevant but using parameters.dataset and parameters.token

https://docs.microsoft.com/en-us/azure/devops/pipelines/process/environments?view=azure-devops

https://docs.microsoft.com/en-us/azure/devops/pipelines/process/deployment-jobs?view=azure-devops

Solution 3:[3]

The other way to deal with this is to move the manual validation job to the previous stage. Make that job as the last job in the previous stage. If it fails, the next stage doesn't run

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Thomas
Solution 2 JukkaK
Solution 3 user1