2
votes

I have an Azure pipeline which starts by declaring some variables, including some pulled from template YAML files. Here's a summary of the pipeline focusing on key parts only:

variables:
- template: "variables/my-variables.yml"

The first stage is coded directly into the pipeline YAML and results in an artifact being published:

artifact: ${{ variables.artifactName }}-provisioning

Where artifactName is a variable defined in variables/my-variables.yml.

The next stage uses jobs from a template in an external file:

- stage: Next
  displayName: "Stage using template yml"
  jobs:
  - template: templates/jobs/external.yml

In that external file there are a couple of jobs that themselves are referenced from external files:

jobs:
- deployment: PublishArmTemplate
  strategy:
    runOnce:
      deploy:
        steps:
        - template: "../job.yml"
          parameters:
            ArtifactName: ${{ variables.artifactName }}

Notice that variables.artifactName is passed as an argument to the job's ArtifactName parameter.

That job YAML file itself has a step which depends on the artifact I published above:

parameters:
- name: 'ArtifactName'
  type: string

steps:
  - download: current
    artifact: ${{ parameters.ArtifactName }}-provisioning

However, when the pipeline runs I get this error:

##[error]Artifact -provisioning was not found for build 322650.

In other words, the variable I have defined and scoped to the pipeline itself has not been passed down to that job step (parameters.ArtifactName is empty).

My understanding based on the Microsoft docs was that variables scoped to the pipeline should be available to all stages and jobs. Does this not apply when using templates? Or is there something else I need to do to get this working??

1

1 Answers

3
votes

The variables are not available to nested components of your pipeline. According to the documentation (and I have experienced this behavior):

Within a template expression, you have access to the parameters context that contains the values of parameters passed in. Additionally, you have access to the variables context that contains all the variables specified in the YAML file plus many of the predefined variables (noted on each variable in that topic).

by "YAML file", they really mean the current file in which the reference is made.

Within your nested template(s) you need to either

  1. Include the same variables templates at the right scope, or
  2. Pass the variable value from your pipeline, where declared, all the way through each nested template as a parameter.

So, you could do something like this:

- stage: Next
  displayName: "Stage using template yml"
  jobs:
  - template: templates/jobs/external.yml
    parameters:
      artifactName: ${{ variables.artifactName }}

and then

parameters:
- name: artifactName
  type: string

jobs:
- deployment: PublishArmTemplate
  strategy:
    runOnce:
      deploy:
        steps:
        - template: "../job.yml"
          parameters:
            ArtifactName: ${{ parameters.artifactName }}