Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Azure Pipelines using YAML for multiple environments (stages) with different variable values but no YAML duplication

Let's suppose I have 3 environments on Azure: Dev, Test and Prod. I have the same pipeline for building and deploying the resources and the code for each one of the environments except for two differences:

  • different trigger branch
  • different variable values

What is the correct approach for this scenario? Because at least 3 come to my mind, none of which is perfect:

Option 1: I guess I could create a single pipeline on Azure DevOps (triggered by any of 3 branches) with 3 stages for each environment and for each stage add a condition to run depending on the source branch, like this:

condition: eq(variables['Build.SourceBranch'], 'refs/heads/a-branch-name')

and in each stage reference different variables. But this would introduce code duplication in each stage - when adding or modifying a step I would have to remember to edit 3 stages - not desirable.

Option 2: Create 3 separate YAML files in my repository, each one of them with specified trigger branch and referencing the same variable names, then create 3 different pipeline on Azure DevOps, each one of them with different variable values. But this would also introduce code duplication.

Option 3: Create 1 build-and-deploy.yaml file as a template with the steps defined in it and then create another 3 YAML files referring to that template, each with different trigger branch and with different variable values in each Azure Pipeline, like this:

trigger:
  branches:
    include:
    - a-branch-name

steps:
- template: build-and-deploy.yaml
  parameters:
      parameterName1: $(parameterValue1)
      parameterName2: $(parameterValue2)

This seems to be the best option but I haven't seen it used anywhere in the examples so maybe I'm just unaware of downsides of it, if there are any.

like image 269
Mariusz Ignatowicz Avatar asked Nov 10 '20 22:11

Mariusz Ignatowicz


People also ask

How do you use multiple variable groups in Azure pipeline?

Sign in to your organization ( https://dev.azure.com/{yourorganization} ) and select your project. Select Pipelines > Library > + Variable group. Enter a name and description for the group. Optional: Move the toggle to link secrets from an Azure key vault as variables.

How do you pass variables in Azure pipelines yml tasks?

Passing variables between tasks in the same job Set the value with the command echo "##vso[task. setvariable variable=FOO]some value" In subsequent tasks, you can use the $(FOO) syntax to have Azure Pipelines replace the variable with some value.

How do I set environment variables in Azure DevOps pipeline YAML?

There are 3 ways to get an environment variable value on your build server: Set the value on the build machine. Set the value in the YAML build script. Set the value in Azure DevOps for the build pipeline definition.

How to create multi stage pipelines with YAML in Azure DevOps?

Create Multi Stage Pipelines with YAML in Azure DevOps 1 Enable Multi Stage Pipeline feature 2 Write a Multi Stage Pipeline. Azure DevOps pipelines consists of multiple stages. ... 3 Create Multi Stage Pipeline. ... 4 Run the Azure Pipeline and Viewing Details. ... 5 Summary and Notes. ...

What is a YAML pipeline?

Conceptually, a YAML pipeline is structured in the same way. The reason why the above YAML definition is missing the definition of stages and jobs is because it is only required if you want to run multiple jobs or stages.

Does Azure DevOps Server TFS support YAML?

Support for stages was added in Azure DevOps Server 2019.1. This version of TFS doesn't support YAML. You can organize the deployment jobs in your release pipeline into stages. Stages are the major divisions in your release pipeline: "run functional tests", "deploy to pre-production", and "deploy to production" are good examples of release stages.

Is Azure-pipelines yml supported?

It is supported. azure-pipelines.yml is being auto-picked up by VSTS, you can create as many yaml files and create builds manually for those. that's the only difference. so you need to manually create builds for different envs using different yaml files. Show activity on this post. The process has changed. As of June 2020, the steps are:


Video Answer


2 Answers

According to your description, if you want different stages to share the same repo resource, but their trigger branch and variable values are different.

Regarding trigger branch, you can use expression {{if ......}} to determine the trigger branch condition.

Regarding variable values, you can define templates and variable groups to specify them through parameters.

Here is an example, you can refer to it:

  1. First go to Library under Pipelines, click on the Variable group to add a variable group. You can add multiple variables to this variable group. enter image description here enter image description here

  2. Repo structure: enter image description here

  3. azure-pipelines.yml:

    sample:

     stages:
     - template: stage/test.yml
       parameters:
        ${{if contains(variables['Build.SourceBranch'], 'master')}}:
          variableGroup: devGroup
          stageName: Dev
          test: a
        ${{if contains(variables['Build.SourceBranch'], 'test')}}:
          stageName: test
          test: b
    

stage/test. yml:

parameters:
- name: stageName
  displayName: Test
  type: string
  default: test
  
- name: test
  displayName: Test
  type: string
  default: test

- name: variableGroup
  displayName: Test
  type: string
  default: test

stages:
- stage: Test_${{ parameters.stageName }}
  variables: 
    - group: ${{parameters.variableGroup}}
  jobs:
  - job: Test1
    pool:
      vmImage: vs2017-win2016
    steps:
    - script: echo "Hello Test1"
    - script: echo  ${{ parameters.test }}
    - script: echo $(dev1)

Of course, if you want to use a single variable, you can define the variable directly in yaml without adding a variable group.

like image 63
Alina Wang-MSFT Avatar answered Oct 24 '22 09:10

Alina Wang-MSFT


Here's how to do it with a shared pipeline config that gets included into env-specific pipelines.

To support 2 environments (dev and prod) you'd need:

  • 1 shared pipeline yaml
  • 2 env-specific yamls, one for each env
  • 2 pipelines created in Azure DevOps, one for each env; each pipeline referencing corresponding yaml

pipeline-shared.yml:

variables:
  ARTIFACT_NAME: ApiBuild
  NPM_CACHE_FOLDER: $(Pipeline.Workspace)/.npm

stages:
  - stage: Build
    displayName: Build
    pool:
      vmImage: 'ubuntu-latest'
      demands: npm
    jobs:
      ...

  - stage: Release
    displayName: Release
    dependsOn: Build
    pool:
      vmImage: 'ubuntu-latest'
    jobs:
      ...

pipeline-dev.yml:

# Trigger builds on commits to branches
trigger:
  - dev

# Do not trigger builds on PRs
pr: none

extends:
  template: pipeline-shared.yml

pipeline-prod.yml

trigger:
  - master

pr: none

extends:
  template: pipeline-shared.yml
like image 40
Max Ivanov Avatar answered Oct 24 '22 07:10

Max Ivanov