Azure-devops-docs: Use of environment-scoped variables

Created on 9 Jul 2019  Â·  6Comments  Â·  Source: MicrosoftDocs/azure-devops-docs

Do you have guidance on how we should use variables and environments together? For example, let’s say one of my deployment steps is to run some database scripts, and in order to do that I need to pass a connection string into the YAML pipeline. Different environments will have different connection strings. What’s the recommended way to do this? As far as I can see, we can’t scope variables to environments currently.


Document Details

⚠ Do not edit this section. It is required for docs.microsoft.com ➟ GitHub issue linking.

Pri2 devops-cictech devopprod doc-bug

Most helpful comment

@clancy (and anyone else who is interested) - I did a little more investigation into this and have found an approach that hopefully is workable. It doesn't use environments at all.

  • Non-secret variables - you can define non-secret variables within the YAML files themselves. This can be done both at the level of the whole pipeline (which is equivalent to setting a release-wide variable in the classic model), and/or on individual stages (which is equivalent to setting a variable at the scope of a single release stage in the classic model).
  • Secret variables - the best option right now seems to be to use variable groups. You create and configure these in the Azure Pipelines UI. Secrets can be added into the group directly, or variable groups can also link to a Key Vault for storing secrets. Once the variable group is created, you can refer to it inside the YAML template. (Note that once you refer to a variable group you need to switch the syntax of all of your variable definitions to the key/value model of defining variables.)
  • Task groups - in the classic release model you may have used a task group to define the sequence of steps to follow to run a release, and then added that task group into each of the release stages. In YAML there is a nicer option, which is to use a YAML template, which essentially embeds that file inline. This means you could have a file that defines all of your release steps, and then instantiate it for each of your environments by including it as a stage.

Here's an example that shows all of the above:

Parent template:

trigger:
- master
pr: none

pool:
  vmImage: 'ubuntu-latest'

variables:
  MySharedVariable: xyz

stages:

- stage: build
  jobs:
  - job: run_build
    pool:
      vmImage: 'Ubuntu 16.04'
    steps:
    - checkout: self
    - script: echo Build

- stage: deploy_dev
  dependsOn: build
  jobs:
  - job: deploy_dev
    variables:
      - group: MySecrets-Dev
      - name: EnvironmentName
        value: Dev
    steps:
      - template: pipeline-deploy.yml

- stage: deploy_test
  dependsOn: deploy_dev
  jobs:
  - job: deploy_test
    variables:
      - group: MySecrets-Test
      - name: EnvironmentName
        value: Test
    steps:
      - template: pipeline-deploy.yml

Child template (pipeline-deploy.yml):

steps:
- script: echo Deploying to $(EnvironmentName) with secret $(ExternalApiKey)

And I have two variable groups set up:

  • MySecrets-Dev

    • ExternalApiKey = xxx (and configured as a secret)

  • MySecrets-Test

    • ExternalApiKey = yyy (and configured as a secret)

All 6 comments

Thanks for your question. It looks like you're working through an issue with your scenario or implementation, rather than an issue with the documentation. Here are a couple of options where you might consider asking your question:

Hi @WilliamAntonRohm, I would argue that this is an issue with the documentation. Having environment-specific variables in releases is an extremely common thing to do, and there's nothing in the documentation to advise how to do this. It's also possible that this feature is coming soon and isn't there yet, but I think it's a reasonable question to ask about the documentation.

@johndowns -- thank you for replying; you make a good point. I've re-opened this issue and notified the article's author.

Agreed. It would be quite helpful to have documentation on how to achieve this. Or guidance as to what the recommended approach should be.

variables are set at pipeline scope or at stage, job scope. In the case of environment, they are scoped to a specific deployment job. Hence variables at job scope will be equivalent to setting variables at environment scope.

We do have plans to support linking variables/key vaults to an environment (no time lines). This would be an alternate option to handle environment scoped variables.

@clancy (and anyone else who is interested) - I did a little more investigation into this and have found an approach that hopefully is workable. It doesn't use environments at all.

  • Non-secret variables - you can define non-secret variables within the YAML files themselves. This can be done both at the level of the whole pipeline (which is equivalent to setting a release-wide variable in the classic model), and/or on individual stages (which is equivalent to setting a variable at the scope of a single release stage in the classic model).
  • Secret variables - the best option right now seems to be to use variable groups. You create and configure these in the Azure Pipelines UI. Secrets can be added into the group directly, or variable groups can also link to a Key Vault for storing secrets. Once the variable group is created, you can refer to it inside the YAML template. (Note that once you refer to a variable group you need to switch the syntax of all of your variable definitions to the key/value model of defining variables.)
  • Task groups - in the classic release model you may have used a task group to define the sequence of steps to follow to run a release, and then added that task group into each of the release stages. In YAML there is a nicer option, which is to use a YAML template, which essentially embeds that file inline. This means you could have a file that defines all of your release steps, and then instantiate it for each of your environments by including it as a stage.

Here's an example that shows all of the above:

Parent template:

trigger:
- master
pr: none

pool:
  vmImage: 'ubuntu-latest'

variables:
  MySharedVariable: xyz

stages:

- stage: build
  jobs:
  - job: run_build
    pool:
      vmImage: 'Ubuntu 16.04'
    steps:
    - checkout: self
    - script: echo Build

- stage: deploy_dev
  dependsOn: build
  jobs:
  - job: deploy_dev
    variables:
      - group: MySecrets-Dev
      - name: EnvironmentName
        value: Dev
    steps:
      - template: pipeline-deploy.yml

- stage: deploy_test
  dependsOn: deploy_dev
  jobs:
  - job: deploy_test
    variables:
      - group: MySecrets-Test
      - name: EnvironmentName
        value: Test
    steps:
      - template: pipeline-deploy.yml

Child template (pipeline-deploy.yml):

steps:
- script: echo Deploying to $(EnvironmentName) with secret $(ExternalApiKey)

And I have two variable groups set up:

  • MySecrets-Dev

    • ExternalApiKey = xxx (and configured as a secret)

  • MySecrets-Test

    • ExternalApiKey = yyy (and configured as a secret)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

csutorasr picture csutorasr  Â·  3Comments

adnanebrahimi picture adnanebrahimi  Â·  3Comments

o-o00o-o picture o-o00o-o  Â·  3Comments

dannyvv picture dannyvv  Â·  3Comments

KacperMucha picture KacperMucha  Â·  3Comments