845614720
845614720

Reputation: 838

Conditionally Set Environment Azure DevOps

I am working with an Azure Pipeline in which I need to conditionally set the environment property. I am invoking the pipeline from a rest API call by passing Parameters in the body which is documented here.. When I try to access that parameter at compile time to set the environment conditionally though the variable is coming through as empty (assuming it is not accessible at compile time?)

enter image description here

enter image description here

Does anybody know a good way to solve for this via the pipeline or the API call?

Upvotes: 2

Views: 2559

Answers (3)

Thalles Noce
Thalles Noce

Reputation: 806

I would create a new stage that holds the deployment with an environment that needs approval and put a condition on it using a variable created in a previous stage or your case, through the API request.

Condition is evaluated before the beginning of the stage, before the environment approval.

The ${{}} expressions are evaluated at compile time and it isn't possible to grab the value of variables created/modified at runtime.

trigger: none

stages:
  - stage: setVariableStage
    dependsOn: []
    jobs:
      - job: setVariableJob
        steps:
          - task: PowerShell@2
            name: setVariableTask
            inputs:
              pwsh: true
              targetType: 'inline'
              script: |
                $enabledaux = [boolean]::Parse('True');
                Write-Host "variable $enabledaux";
                Write-Host "##vso[task.setvariable variable=shouldrun;isOutput=true]${enabledaux}"

  - stage: deploySomethingWithApproval
    dependsOn: setVariableStage
    variables:
        shouldrun: $[ stageDependencies.setVariableStage.setVariableJob.outputs['setVariableTask.shouldrun'] ]
    condition: eq(variables.shouldrun, 'True')
    jobs:
      - deployment:
        environment: environmentApproval # Contains the approval needed
        strategy:
          runOnce:
            deploy:
              steps:
                - task: PowerShell@2
                  inputs:
                    pwsh: true
                    targetType: 'inline'
                    script: 'Do something'

  - stage: afterStage
    dependsOn: 
      - deploySomethingWithApproval
    condition: in(dependencies.deploy.result, 'Succeeded', 'Skipped')
    jobs:
      - job:
        steps:
          - task: PowerShell@2
            inputs:
              pwsh: true
              targetType: 'inline'
              script: "Do something"

Upvotes: 0

845614720
845614720

Reputation: 838

After some digging I have found the answer to my question and I hope this helps someone else in the future.

As it turns out the Build REST API does support template parameters that can be used at compile time, the documentation just doesn't explicitly tell you. This is also supported in the Runs endpoint as well.

My payload for my request ended up looking like:

{
    "Parameters": "{\"Env\":\"QA\"}",
    "templateParameters": {"SkipApproval" : "Y"},
    "Definition": {
        "Id": 123
    },
    "SourceBranch": "main"
}

and my pipeline consumed those changes at compile time via the following (abbreviated version) of my pipeline

parameters:
  - name: SkipApproval
    default: ''
    type: string
...
        ${{if eq(parameters.SkipApproval, 'Y')}}: 
            environment: NoApproval-All
        ${{if ne(parameters.SkipApproval, 'Y')}}:
            environment: digitalCloud-qa

Upvotes: 2

Daniel Mann
Daniel Mann

Reputation: 58981

This is a common area of confusion for YAML pipelines. Run-time variables need to be accessed using a different syntax.

$[ variable ]

YAML pipelines go through several phases.

  1. Compilation - This is where all of the YAML documents (templates, etc) comprising the final pipelines are compiled into a single document. Final values for parameters and variables using ${{}} syntax are inserted into the document.
  2. Runtime - Run-time variables using the $[] syntax are plugged in.
  3. Execution - The final pipeline is run by the agents.

This is a simplification, another explanation from Microsoft is a bit better:

  1. First, expand templates and evaluate template expressions.
  2. Next, evaluate dependencies at the stage level to pick the first stage(s) to run.
  3. For each stage selected to run, two things happen:
    • All resources used in all jobs are gathered up and validated for authorization to run.
    • Evaluate dependencies at the job level to pick the first job(s) to run.
  4. For each job selected to run, expand multi-configs (strategy: matrix or strategy: parallel in YAML) into multiple runtime jobs.
  5. For each runtime job, evaluate conditions to decide whether that job is eligible to run.
  6. Request an agent for each eligible runtime job.

...

This ordering helps answer a common question: why can't I use certain variables in my template parameters? Step 1, template expansion, operates solely on the text of the YAML document. Runtime variables don't exist during that step. After step 1, template parameters have been resolved and no longer exist.

[ref: https://learn.microsoft.com/en-us/azure/devops/pipelines/process/runs?view=azure-devops]

Upvotes: 2

Related Questions