I'm trying to pass the environment parameter to a template and then to another template (line webAppName: 'my-webapp-${{parameters.environment}}')
I get the error : A template expression is not allowed in this context. Is it not possible to do that ?
main pipeline (just the necessary code for clarity)
- stage: deploy
displayName: 'Deploy Dev Stage'
dependsOn: build
condition: succeeded()
jobs:
- deployment: deploymentjob
displayName: deployment job
environment: dev
variables:
- template: variables/dev.yml
strategy:
runOnce:
deploy:
steps:
- template: templates/pipeline-deploy/master.yml
parameters:
environment: 'dev'
master.yml
parameters:
environment: ''
steps:
- template: webapp.yml
parameters:
webAppName: 'my-webapp-${{parameters.environment}}'
then webapp.yml
parameters:
webAppName: ''
steps:
- task: AzureRmWebAppDeployment#4
displayName: 'Deploy my app'
inputs:
azureSubscription: '(#some id)'
WebAppName: ${{parameters.webAppName}}
packageForLinux: '$(workFolder)/my-package.zip'
I don't believe you're allowed to use variable substitution in ARM template parameters. But you ARE allowed to do so in variables.
So in master.yml, define a variables section, and compose your webAppName as a variable. Then pass that variable into webapp.yml instead of using a parameter.
The problem was the indentation in one of my YAML files, which was not correct. Adding an extra tab solved it.
Related
I'm currently trying to setup my complete build/release pipeline with yaml files.
First I tried with different stages (dev/staging/prod) and it worked.
Now I wanted to add an approval that the deploy doesn't not happen automatically on each system.
Therefore I added an environment in the TFS with an approval check.
But when I try to setup the yaml file I always get an error.
I don't know how to setup this properly.
This is my main yaml file called release-pipeline.yaml
trigger:
- master
pool:
name: POOL
stages:
- stage: BuildSolution
jobs:
- job: BuildSolutionJob
displayName: Build
workspace:
clean: all
steps:
- template: yaml/BuildSolution.yml
- template: yaml/CopyFiles.yml
- template: yaml/PublishArtifact.yml
- stage: DeployOn_STAGING_System
dependsOn: BuildSolution
jobs:
- job: Deploy_STAGING
- template: yaml/Deploy.yml
parameters:
Environment: 'SITE'
Staging: 1
- stage: Deploy_DEV_System
dependsOn: BuildSolution
jobs:
- deployment: Deploy_DEV
environment: ENVCHECK_DEV
strategy:
runOnce:
deploy:
steps:
- template: yaml/Deploy.yml
parameters:
Environment: 'SITE'
ViewDeploy: 1
This is my Deploy.yml file which i want to execute (only some snips):
parameters:
- name: Environment
type: string
- name: ProdSystem
type: number
default: 0
- name: Staging
type: number
default: 0
- name: ViewDeploy
type: number
default: 0
jobs:
- job:
variables:
artifactName: $[stageDependencies.BuildSolution.BuildSolutionJob.outputs['SetVariables.artifactName']]
version: $[stageDependencies.BuildSolution.BuildSolutionJob.outputs['SetVariables.version']]
steps:
- task: PowerShell#2
displayName: Display given parameters
inputs:
targetType: inline
script: >
Write-Host "ArtifaceName: " $(artifactName)
Write-Host "Environment for Deploy: " ${{ parameters.Environment }}
Write-Host "##vso[task.setvariable variable=isStaging]${{ parameters.Staging }}"
failOnStderr: true
When I try to execute I get the following error:
/release-pipeline.yml: Unexpected value 'parameters'.
How do I need to change this that it will work with the template in both cases, with and without the environment approval check?
I tried https://samlearnsazure.blog/2020/02/05/approvals-in-environments/
and of course different structure for the calling. But nothing helped.
In the tutorials they always have steps below the "deploy" but because I have different sites and environments I want/need the template file to save work.
I found another post which goes in the same direction.
I reworked my complete template so that I can use the approach of this: DevOps template with conditional manual approval job
It's not the same as I wanted, but it works.
My goal was that I don't want to create a environment if I have no checks on this site. Only for sites where I wanted the approval check.
With the above mentioned solution I need to create an environment for each site, independent if I have checks or not.
I want to customize environment attribute to choose programmatically environment for approval (dev, preprod, prod). When I try to launch pipeline, I see this error. Is there an alternative?
Job : Environment $(environment) could not be found. The environment does not exist or has not been authorized for use.
variables:
environment: dev
jobs:
- deployment: test
displayName: test
timeoutInMinutes: 0
# creates an environment if it doesn't exist
environment: $(environment)
strategy:
runOnce:
deploy:
steps:
- checkout: self
clean: true
displayName : Checkout repository
- task: NodeTool#0
inputs:
versionSpec: '16.x'
checkLatest: true
For this use case you should use parameters. This is because variables are not available during the initial parsing stage of the pipeline.
parameters:
- name: "environment"
type: string
default: "development"
And then environment: ${{ parameters.environment }}
Or if you want to get fancy, you could do something like this:
parameters:
- name: "environments"
type: object
default:
- name: development
param1: value
param2: value
- name: test
param1: value
param2: value
# This will look through the environment parameter and create a job for each environment.
- ${{ each environment in parameters.environments }} :
jobs:
- deployment: test
#read in vars from a file in variables/development.yml
variables: variables/${{ environment.name }}.yml
displayName: test
timeoutInMinutes: 0
# creates an environment if it doesn't exist
environment: ${{ environment.name }}
strategy:
runOnce:
deploy:
steps:
- checkout: self
clean: true
displayName : Checkout repository
- task: NodeTool#0
inputs:
versionSpec: '16.x'
checkLatest: true
Hi I am using agent pool in azure pipeline, so i have multiple agents so i want to parameterize the pool name like shown below but when i do this i get an error as (Line: 11, Col: 9): A template expression is not allowed in this context
parameters:
- name: pool_name
displayName: agent pool location
type: string
default: test-ashish
trigger:
- none
pool:
name: ${{parameters.pool_name}}
demands:
- Location -equals EASTUS2
steps:
- script: |
echo "This job is only for testing"
echo $()
name: Test_Job
displayName: Test Job
This issue can be solved by using the answer in this issue: Azure Devops: Is it possible to nest yaml templates inside another yaml template?.
Copyed from link:
refer code:
parameters:
buildArtifactName: "build"
solution: ""
jobs:
- job: 'BuildSolution'
pool:
vmImage: ${{parameters.vmImage}}
continueOnError: false
variables:
artifactName: ${{ parameters.buildArtifactName}}
steps:
- task: NuGetCommand#2
displayName: 'Restore NuGet packages'
inputs:
restoreSolution: ${{ parameters.solutionDir }}/${{ parameters.solution }}
configuration: ${{parameters.buildConfiguration}}
Please consider the following:
- job: Backend
steps:
- template: $(ClassLibraryTemplate)
parameters:
projectName: 'Core'
solutionPath: 'Source/Core.sln'
ClassLibraryTemplate is defined as a pipeline variable. But when I run the build, it fails because the variable is not replaced by its value and the template is not found.
Is it not possible to store the template name in a variable ?
For Azure DevOps YAML pipeline, the template get processed at compile time. However, the $(ClassLibraryTemplate) get processed at the runtime. That's why it fails.
More information: Understand variable syntax
You could define variable or parameter in your YAML pipeline, then use template expression. For parameter, you could specify value when queue/run pipeline in pop-up window.
For example:
parameters:
- name: temName
displayName: template name
type: string
default: steps/test.yml
trigger:
- none
variables:
- name: tem
value: steps/build.yml
jobs:
- job: Linux
pool:
vmImage: 'ubuntu-16.04'
steps:
- template: ${{ variables.tem }}
- template: ${{ parameters.temName }}
In a previous SO question, I was trying to get create an Azure DevOps template.
Now that I know how to do that, I'm trying to pass in a list of strings to the template and use them in the template, like so:
azure_pipelines.yml
extends:
template: AzurePipelines/job.yml
parameters:
projects:
- FirstProject.csproj
- SecondProject.csproj
and in this template...
job.yml
steps:
(for each projectFileName in projects)
- bash echo $(projectFileName)
- run code in the build.yml template using $(projectFileName)
- run code in the test.yml template using $(projectFileName)
- run code in the publish.yml template using $(projectFileName)
So for each project name handed into the template, run the template steps.
I'm not sure how to pass in an array of strings and how to test that it works?
It seems you are looking for each function:
# my-template.yml
parameters:
- name: 'projects'
type: projectList
default: []
steps:
- ${{ each project in parameters.projects }}:
- task: PublishBuildArtifacts#1
displayName: 'Publish ${{ project }}'
inputs:
PathtoPublish: '$(Build.ArtifactStagingDirectory)/${{ project }}.zip'
# ci.yml
steps:
- template: my-template.yml
parameters:
projects:
- test1
- test2
The easiest way I found to accomplish the use of templates is by using the templates from within the main yaml file pipeline. This way you will have access to all the variables and variable groups defined in the main template. Using this architecture you will be able to bundle several steps into a template then run it from the main yaml file. Eg:
azure_pipelines.yml
variables:
- name: projectFileName
value: "Variable 1 value"
- name: VAR2
value: "Variable 2 value"
trigger:
- master
pool:
vmImage: 'ubuntu-latest'
steps:
- template: templates/job.yml
- template: templates/test.yml
templates/job.yml
steps:
- task: Bash#3
displayName: 'Run Bash Command'
inputs:
targetType: 'inline'
script: |
print "Variable value: " $(projectFileName)
Hope it helps