Adventures with Azure DevOps: Manual Validations

I wanted to test adding approvals to an Azure DevOps YAML pipeline, outside of Environment approvals.

I created a project that contains the following files:

  • deploy.bicepBicep template that will create a storage account in Azure.
  • validate.ps1 – PowerShell script that mocks a validation stage, could be a what-if or some other validation.
  • deploy.ps1 – PowerShell script to deploy the Bicep template to Azure.
  • deploy.yml – YAML pipeline file.

The repository is located at mattruma/MJR129 (github.com).

I have two branches: main and develop.

I have three environments: develop, staging and production.

The PowerShell scripts expect a -Prefix parameter, which will be different for each environment.

I created three variable groups, one for each environment.

I then added a Prefix variable to each variable group.

For develop the Prefix used dev as the suffix, e.g. mjr129dev, for staging used stg and for production used prd.

I next created three environments in Azure DevOps.

I added a gated approval to the Staging environment.

The Production environment did not need a gated approval as it would be triggered off of a commit to the main branch.

I wanted my workflow to work as such:

  1. Code changes are committed to the develop branch which would then trigger the pipeline at the Develop stage.
  2. The pipeline runs the validate.ps1 script.
  3. After the validation runs an email is sent requesting approval.
  4. The user approves the request which then runs the deploy.ps1 script, which in turn deploys the resources to the develop environment in Azure.
  5. Using the gated approval, a notification is sent for approval to Staging.
  6. User approves the request which then runs the validate.ps1 script.
  7. After the validation runs an email is sent requesting approval.
  8. The user approves the request which then runs the deploy.ps1 script, which in turn deploys the resources to staging environment Azure.
  9. If everything looks good, a pull request is created for the changes in develop.
  10. When the pull request is accepted the pipeline is triggered at the Production stage.
  11. The pipeline runs the validate.ps1 script.
  12. After the validation runs an email is sent requesting approval.
  13. The user approves the request which then runs the deploy.ps1 script, which in turn deploys the resources to the production environment in Azure.

The Develop and Staging stages would be triggered by the develop branch, while the Production stage would be triggered by the main branch.

I was able to accomplish this a combination of AzureCLI@2 and ManualValidation@0 tasks.

The complete Azure YAML Pipeline can be seen at MJR129/deploy.yml at develop ยท mattruma/MJR129 (github.com).

Some things to call out.

I used conditions on my stage to determine what branch would trigger what stage.

stages:

- stage: Develop
  condition: eq(variables['build.sourceBranch'], 'refs/heads/develop')

Variable groups were assigned to the appropriate stage.

  variables:
  - group: Production

Timeouts were required for the job and the ManualIntervention task.

  - job: StagingWaitingApproval
    dependsOn: StagingValidate
    pool: server
    timeoutInMinutes: 4320 # job times out in 3 days

    steps:

    - task: ManualValidation@0
      displayName: StagingWaitingApproval
      timeoutInMinutes: 1440 # task times out in 1 day
      inputs:
        notifyUsers: |
          $(Email)
        instructions: 'Please validate the build configuration and resume'
        onTimeout: 'resume'

Develop and Staging deployments happen within the same pipeline run.

The Production deployment, since it is triggered off the main branch, happens in a different pipeline run.

Seems to get the job done!

If there is a better way or different way, please share!

Leave a Reply

Your email address will not be published.