Tom Padilla
Tom Padilla

Reputation: 944

How to pass environment specific values to Azure pipeline?

I am deploying Service Fabric Application packages and I have several (~15) devtest environments, any one of which can be used to test a code fix. I can pass in the Service Connection so deploying the final package is not the issue. What I can't figure out is how to set the other environment specific variables based on the target environment. I tried using the Service Connection name to pick one of several variable template files:

variables:
- name: envTemplateFileTest
  ${{ if eq( variables['DevConnection'], 'Environ01' ) }}:
    value: ../Templates/DEV01-Variables-Template.yml
  ${{ if eq( variables['DevConnection'], 'Environ02' ) }}:
    value: ../Templates/DEV02-Variables-Template.yml

... (snip) ...

variables:
  - template: ${{ variables.envTemplateFile }}

But UI variables are not set at compile time. So the template expressions see blank values and fail.

I could use a pipeline variable but then QA would have to make a file change and check it in each time they want to deploy to a different environment than last time.

What I currently have is an empty variable template and a powershell script that sets the values based on different script names.

        - task: PowerShell@2
          inputs:
            targetType: 'filePath'
            filePath: '$(Build.ArtifactStagingDirectory)\drop\Deployment\Code\Scripts\Set-$(DevConnection)Variables.ps1'
            #arguments: # Optional
          displayName: Set environment variables

There has got to be a better way than this. Please.

Upvotes: 1

Views: 1965

Answers (2)

Levi Lu-MSFT
Levi Lu-MSFT

Reputation: 30363

There is not a direct way to achieve this, as the template expression is parsed at compile time.

However I have workaround which no need to write additional ps script and avoid making a file change and check it in to your repo each time.

Since all your devtest environments has the same deployment steps. Then you can create steps template yaml to hold the deployment steps.

Then you can modify your azure-pipelines.yml like below example:

jobs:
- job: A
  pool:
    vmImage: 'windows-latest'

  steps:
  - powershell: |
      $con = "$(connection)" 
      if($con -eq "environ1"){echo "##vso[task.setvariable variable=variablegroup;isOutput=true]environ1"}
      if($con -eq "environ2"){echo "##vso[task.setvariable variable=variablegroup;isOutput=true]environ2"}
    name: setvarStep
  - script: echo '$(setvarStep.variablegroup)'
  

- job: environ1
  pool:
    vmImage: 'windows-latest'
  dependsOn: A
  condition: eq(dependencies.A.outputs['setvarStep.variablegroup'], 'environ1')
  variables: 
    - template: environ1.yaml
  steps:
  - template: deploy-jobs.yaml
  
  
- job: environ2
  pool:
    vmImage: 'windows-latest'
  dependsOn: A
  condition: eq(dependencies.A.outputs['setvarStep.variablegroup'], 'environ2')
  variables: 
    - template: environ2.yml
  steps:
  - template: deploy-jobs.yaml

Above yml pipeline use dependencies and condition. The first job A will output a variable according to the variable (eg.$(connection)) you specify when running the pipeline. In the following jobs, there are conditions to evaluate the output variable. If condition is satisfied then the job will be executed, the job will be skipped if failed on condition.

Upvotes: 1

Tom Padilla
Tom Padilla

Reputation: 944

What we decided to do was add a Powershell script step that sets the variables based on a string passed in.

    - task: PowerShell@2
      inputs:
        targetType: 'filePath'
        filePath: $(Build.ArtifactStagingDirectory)\drop\Deployment\Code\Scripts\Set-DefaultValues.ps1
      displayName: Set default pipeline variables

Then we load the appropriate file and loop through the variables, setting each in turn.

param(
  [string]
  $EnvironmentName
)

$environmentValues = @{}

switch ($EnvironmentName) {
  'DEV98' { . '.\Dev98-Values.ps1'}
  'DEV99' { . '.\Dev99-Values.ps1'}
}

foreach ($keyName in $environmentValues.Keys) {
  Write-Output "##vso[task.setvariable variable=$($keyName)]$($environmentValues[$keyName])"
}

This allows us to put the environment specific variables in a plain PSCustom object file and dot import it.

$environmentValues = @{
    currentYear = '2020';
    has_multiple_nodetypes = 'false';
    protocol = 'http';
    endpoint = 'vm-dev98.cloudapp.com';
    ... snip ...
}

So QA has an easier time maintaining the different environment files. Hope this helps others out there.

Upvotes: 0

Related Questions