Search code examples
azuredeploymentazure-pipelines-yaml

Azure YAML pipeline - How to selectively deploy to 1 or more resources


I'm working on a YAML pipeline to build a deploy a project and could not figure out how to selectively deploy to 1 or more Dev/Test/Prods servers.

Resources: There are 3 Test resources and multiple Prod resources.

Requirement: A given build can be independently deployed any or all of the Test resources. Similarly, it can be independently deployed to any or all of the Prod resources.

Can this be done? If so, please point me to the right direction. All the examples and documentations I have found so far only showed the deployment sequence to 1 Dev resource, 1 Test resource, and 1 Prod resource.

Thank you in advance for your help.

Snippet of my pipeline. Deploying to Test1, Test2 and Test3 stages are in sequence, and that's not what I need.

stages:
- stage: Build
  jobs:
  - job: BuildProject
  # steps to build and publish

- stage: Test1
  # deploy to Test1 resource
- stage: Test2
  # deploy to Test2 resource
- stage: Test3
  # deploy to Test3 resource

Solution

  • It sounds like you are asking how to deploy to your different environments in parallel.

    If not specified, a stage will depend on the previously defined stage in the yaml. If you want stages to run in parallel, you can add dependsOn: [] onto each of your stages to set it so the stages do not depend on each other, and will run in parallel.

    Since you have your build and deployment in the same pipeline, then your deploy stages will need to depend on your Build stage.

    Example snippet:

    stages:
    - stage: Build
      jobs:
      - job: BuildProject
      # steps to build and publish
    
    - stage: Test1
      dependsOn: Build
      # deploy to Test1 resource
    
    - stage: Test2
      dependsOn: Build
      # deploy to Test2 resource
    
    - stage: Test3
      dependsOn: Build
      # deploy to Test3 resource
    

    Keep in mind that you will need an available agent for each stage/job in your pipeline.

    Recommended reading:


    Edit to respond to question from comments.

    When I do build #1, I just wanted to deploy to Test2. So, I would need to skip Test1 and Test3 stages. There is no way for me to deploy build #1 to Test1 or Test3 later on. How would I go about doing that?

    There are quite a few ways to go about designing a solution based on your requirements, each with there own quirks. I am not going to elaborate too much any one of these, do some experimentation and come back to ask a new question that details a specific problem.

    I'll suggest three options that may meet your use case.

    Use the Environments feature

    The Environments feature in Azure DevOps lets you define target environments, and then add approval gates that will stop a stage from progressing until it has been approved. If used for your deployment stages, your build stage will start and finish automatically, then each of your deploy environment stages will be on a waiting for approval state. Unfortunately, if any of the stages are 'denied', that pipeline stage will be marked as failed which looks ugly in my opinion.

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

    Your yaml will need to be tweaked slightly for environments like so:

    stages:
    - stage: Build
      jobs:
      - job: BuildProject
        steps:
        - checkout: self
    
    - stage: Test1
      dependsOn: Build
      jobs:
      - deployment: DeployEnvironmentA
        environment: EnvironmentA
        strategy:
          runOnce:
            deploy:
              steps:
              - checkout: self
    
    - stage: Test2
      dependsOn: Build
      jobs:
      - deployment: DeployEnvironmentB
        environment: EnvironmentB
        strategy:
          runOnce:
            deploy:
              steps:
              - checkout: self
    
    - stage: Test3
      dependsOn: Build
      jobs:
      - deployment: DeployEnvironmentC
        environment: EnvironmentC
        strategy:
          runOnce:
            deploy:
              steps:
              - checkout: self
    

    Split your pipeline into pieces

    If you cannot determine at trigger time of a pipeline which environments will be deployed, you can split your pipeline into multiple pieces.

    Create a seperate pipeline that builds your application and publishes artifacts that will be used to publish.

    Edit your existing pipeline so that it only deploys one environment, and you parse in a parameter to determine which environment will be deployed. You can link to the build pipeline using the resources yaml keyword to easily download the artifacts from your build pipeline. Then each of your pipeline runs will target a single environment, and you trigger the pipeline whenever that environment needs to be deployed too.

    Docs: https://learn.microsoft.com/en-us/azure/devops/pipelines/yaml-schema/resources-pipelines-pipeline?view=azure-pipelines

    Use the built in stage selector

    When manually triggering a multi-stage pipeline, you can select the advanced option Stages to run to toggle which stages will run. Using this, you can disable which environments you want to deploy too.

    Stages-to-run

    It is possible to create similar behaviour with parameters/variables using yaml expressions.

    Docs: https://learn.microsoft.com/en-us/azure/devops/pipelines/process/expressions?view=azure-devops