I am trying to read a text file using bash in a AZDO pipeline template, but for some reason the variable containing the name of the file is empty:
##deploy-to-env.yml
parameters:
- name: env
type: string
default: ""
- name: envLong
type: string
default: ""
stages:
- stage: "deployTo${{ parameters.envLong }}"
displayName: "Deploy to ${{ parameters.env }}"
variables:
- name: releasesFile
value: ""
jobs:
- deployment:
environment: "${{ parameters.env }}"
displayName: "Deploy to ${{ parameters.env }}"
strategy:
runOnce:
deploy:
steps:
- task: Bash#3
name: FindReleaseFile
displayName: "Find the releases.txt file"
inputs:
targetType: 'inline'
script: |
echo "##vso[task.setvariable variable=releasesFile;isOutput=true]$(find $(Build.SourcesDirectory) -name releases.txt -maxdepth 1 -type f 2>/dev/null)"
- task: Bash#3
name: DownloadUsingArtifactTool
displayName: "Download Using Artifact Tool"
inputs:
targetType: 'inline'
script: |
echo "$(FindReleaseFile.releasesFile)"
The pipeline looks like this:
trigger:
branches:
include:
- azure-pipelines
paths:
include:
- "releases.txt"
stages:
- template: deploy-to-env.yml
parameters:
env: "tst"
envLong: "Test"
How can I pass the releasesFile variable to the 2nd task in deploy-to-env.yml template?
The problem was the the repository was not cloned, adding checkout: self in the steps fixed it
Related
I can't understand why dependencies don't work. I need to fix - task: cake#2 and other commented tasks. Now they looks like jobs, but I need to convert them into tasks.
Here that task:
- task: Cake#2
displayName: Restore FE and Sitecore modules
condition: Or(eq(dependencies.check.outputs['ChangedFiles.BE'], 'true'), ne(variables['Build.Reason'], 'PullRequest'))
inputs:
script: "$(Build.Repository.LocalPath)/src/build.cake"
target: "Server :: Restore"
verbosity: "Quiet"
Version: "1.3.0"
Here's the whole code
name: test-build$(Rev:.r)
trigger:
branches:
include:
- develop
- release/*
paths:
exclude:
- "environment/**/*"
schedules:
- cron: 0 19 * * 1-5
displayName: evening-deployment
branches:
include:
- develop
always: false # whether to always run the pipeline or only if there have been source code changes since the last successful scheduled run. The default is false.
pool:
vmImage: "windows-latest"
variables:
- group: shared-variables
- name: ArtifactsLocation
value: "$(Build.Repository.LocalPath)/output"
- name: NUGET_PACKAGES
value: "$(Pipeline.Workspace)/.nuget/packages"
stages:
- stage: build
displayName: Build solution
jobs:
- job: Init
steps:
- ${{ if eq(variables['Build.Reason'],'PullRequest') }}:
- template: /environment/azure/templates/steps/validate-pr-title.yml
- task: gitversion/setup#0
displayName: Installing GitVersion tool
inputs:
versionSpec: "5.8.1"
- task: ChangedFiles#1
displayName: check
condition: eq(variables['Build.Reason'], 'PullRequest')
inputs:
rules: |
[FE]
**/*.json
**/*.ts
**/*.js
**/*.tsx
**/*.scss
**/*.html
**/*.css
[BE]
**/*.csproj
**/*.cs
**/*.yml
**/*.yaml
[SCContent]
**/*.json
**/*.yml
**/*.yaml
- task: GitVersion#5
displayName: Generate GitVersion
inputs:
versionSpec: "5.8.1"
runtime: "full"
configFilePath: "$(Build.Repository.LocalPath)/GitVersion.yml"
- script: |
echo deployInt: $(deployInt)
echo deployQa: $(deployQa)
displayName: Show variables for debug
condition: eq(variables['system.debug'], 'true')
- job: SitecoreCode
dependsOn: Init
steps:
- task: UseNode#1
displayName: Install correct Node.Js version
inputs:
version: "16.x"
- task: Cache#2
displayName: Cache cake packages
inputs:
key: 'cake | "$(Agent.OS)"'
restoreKeys: |
cake
path: "$(Build.Repository.LocalPath)/src/tools"
- task: Cache#2
displayName: Cache nuget modules
inputs:
key: 'nuget | "$(Agent.OS)" | **/packages.lock.json,!**/bin/**,!**/obj/**'
restoreKeys: |
nuget | "$(Agent.OS)"
nuget
path: "$(Build.Repository.LocalPath)/src/packages"
- task: Cache#2
displayName: Cache nuget package reference modules
inputs:
key: 'nuget_pr | "$(Agent.OS)" | $(Build.SourcesDirectory)/**/packages.lock.json'
path: "$(NUGET_PACKAGES)"
restoreKeys: |
nuget_pr | "$(Agent.OS)"
nuget_pr
- task: Cache#2
displayName: Cache node modules
inputs:
key: 'npm | "$(Agent.OS)" | $(Build.Repository.LocalPath)/src/package-lock.json'
restoreKeys: |
npm | "$(Agent.OS)"
npm
path: "$(Build.Repository.LocalPath)/src/node_modules"
- task: Cache#2
displayName: Cache client node modules
inputs:
key: 'client_npm | "$(Agent.OS)" | $(Build.Repository.LocalPath)/src/rendering/package-lock.json'
restoreKeys: |
client_npm | "$(Agent.OS)"
client_npm
path: "$(Build.Repository.LocalPath)/src/rendering/node_modules"
- task: DownloadSecureFile#1
displayName: Download license
name: licenseFile
inputs:
secureFile: "license.xml"
- task: PowerShell#2
displayName: Place license file under /src folder
inputs:
targetType: "inline"
script: |
Move-Item $(licenseFile.secureFilePath) "$(Build.Repository.LocalPath)/src/" -Force
- template: /environment/azure/templates/steps/set-assembly-version.yml
- task: Cake#2
displayName: Restore FE and Sitecore modules
condition: Or(eq(dependencies.check.outputs['ChangedFiles.BE'], 'true'), ne(variables['Build.Reason'], 'PullRequest'))
inputs:
script: "$(Build.Repository.LocalPath)/src/build.cake"
target: "Server :: Restore"
verbosity: "Quiet"
Version: "1.3.0"
# - job: Restore_BE
# displayName: Restore BE
# dependsOn: Init
# condition: Or(eq(dependencies.check.outputs['CheckChanges.FE'], 'true'),ne(variables['Build.Reason'], 'PullRequest'))
# steps:
# - task: Cake#2
# displayName: Restore FE and Sitecore modules
# inputs:
# script: "$(Build.Repository.LocalPath)/src/build.cake"
# target: "Server :: Restore"
# verbosity: "Quiet"
# Version: "1.3.0"
# - job: Restore_FE
# displayName: Restore FE
# dependsOn: Init
# condition: Or(eq(dependencies.check.outputs['CheckChanges.FE'], 'true'),ne(variables['Build.Reason'], 'PullRequest'))
# steps:
# - task: Cake#2
# displayName: Restore FE and Sitecore modules
# inputs:
# script: "$(Build.Repository.LocalPath)/src/build.cake"
# target: "Client :: Restore"
# verbosity: "Quiet"
# Version: "1.3.0"
# drop empty config to make sure that JSS app picks settings from env vars
- powershell: |
$MyJsonHashTable = #{
'sitecore' = #{
'instancePath' = ''
'apiKey' = '$(JssApiKey)'
'deploySecret' = ''
'deployUrl' = ''
'layoutServiceHost' = ''
}
}
$MyJsonVariable = $MyJsonHashTable | ConvertTo-Json
Set-Content "$(Build.Repository.LocalPath)/src/rendering/scjssconfig.json" $MyJsonVariable
Write-Host ('{0}vso[task.logissue type={1}]{2}' -F '##', 'warning', "It would be nice to make app use SITECORE_API_KEY env var instead of API KEY in this file");
displayName: Generate scjssconfig.json with default API key
# TODO: Fix application to read SITECORE_API_KEY Variable
# - job: Build_BE
# displayName: Build BE
# dependsOn: Init
# condition: Or(eq(dependencies.check.outputs['CheckChanges.BE'], 'true'),ne(variables['Build.Reason'], 'PullRequest'))
# steps:
# - task: Cake#2
# displayName: Generate and Build FE and Sitecore
# inputs:
# script: "$(Build.Repository.LocalPath)/src/build.cake"
# target: "Server :: Build"
# verbosity: "Quiet"
# arguments: '--BuildConfiguration "Release" --ScSiteUrl "dummy"'
# Version: "1.3.0"
# - job: Build_FE
# displayName: Build FE
# dependsOn: Init
# condition: Or(eq(dependencies.check.outputs['CheckChanges.FE'], 'true'),ne(variables['Build.Reason'], 'PullRequest'))
# steps:
# - task: Cake#2
# displayName: Generate and Build FE and Sitecore
# inputs:
# script: "$(Build.Repository.LocalPath)/src/build.cake"
# target: "Client :: Build"
# verbosity: "Quiet"
# arguments: '--BuildConfiguration "Release" --ScSiteUrl "dummy"'
# Version: "1.3.0"
- ${{ if eq(variables['Build.Reason'],'PullRequest') }}:
- template: /environment/azure/templates/steps/npm-audit.yml
# - job: Unit_tests_BE
# displayName: Unit tests BE
# dependsOn: Init
# condition: Or(eq(dependencies.check.outputs['CheckChanges.BE'], 'true'),ne(variables['Build.Reason'], 'PullRequest'))
# steps:
# - task: Cake#2
# displayName: Run Unit tests
# inputs:
# script: "$(Build.Repository.LocalPath)/src/build.cake"
# target: "Server :: Tests"
# verbosity: "Quiet"
# Version: "1.3.0"
# - job: Unit_tests_FE
# displayName: Unit tests FE
# dependsOn: Init
# condition: Or(eq(dependencies.check.outputs['CheckChanges.FE'], 'true'),ne(variables['Build.Reason'], 'PullRequest'))
# steps:
# - task: Cake#2
# displayName: Run Unit tests
# inputs:
# script: "$(Build.Repository.LocalPath)/src/build.cake"
# target: "Client :: Tests"
# verbosity: "Quiet"
# Version: "1.3.0"
- task: PublishTestResults#2
displayName: Publish test results
inputs:
testResultsFormat: "XUnit"
testResultsFiles: "**/*.xml"
searchFolder: "$(ArtifactsLocation)/tests"
- task: PublishCodeCoverageResults#1
displayName: Publish code coverage
inputs:
codeCoverageTool: "Cobertura"
summaryFileLocation: "$(ArtifactsLocation)/tests/coverage/**/*.xml"
- ${{ if ne(variables['Build.Reason'],'PullRequest') }}:
- task: Cake#2
displayName: Publish Sitecore code
inputs:
script: "src/build.cake"
target: "004-Publish"
verbosity: "Quiet"
arguments: '--BuildConfiguration "Release" --PublishingTargetDir "$(ArtifactsLocation)/sitecore" --ClientConfigDir "$(Build.Repository.LocalPath)/src/rendering/sitecore/config"'
Version: "1.3.0"
- task: CopyFiles#2
displayName: Copy Sitecore root files
inputs:
SourceFolder: "$(Build.Repository.LocalPath)/src/configs/Sitecore"
TargetFolder: "$(ArtifactsLocation)/sitecore"
Contents: "**"
- task: CopyFiles#2
displayName: Copy transform files to separate artifact
inputs:
SourceFolder: $(ArtifactsLocation)/sitecore/ # string. Source Folder.
Contents: '**/*.transform' # string. Required. Contents. Default: '**'.
TargetFolder: $(ArtifactsLocation)/sitecore-transforms/ # string. Required. Target Folder.
- task: ArchiveFiles#2
displayName: "Archive config file transform artifacts"
inputs:
rootFolderOrFile: "$(ArtifactsLocation)/sitecore-transforms/"
archiveFile: "$(ArtifactsLocation)/sc/$(Build.BuildNumber)-transform.zip"
verbose: $(system.debug)
includeRootFolder: false
- task: DeleteFiles#1
displayName: Perform artifacts cleanup
inputs:
SourceFolder: "$(ArtifactsLocation)/sitecore"
RemoveDotFiles: true
Contents: |
**/obj/*
**/obj
**/*.wpp.targets
**/*.transform
# this hack is needed as our jss app have different roots now.
# hope in future it would be fixed
- powershell: |
$distFolder = $(Get-Item "$(ArtifactsLocation)/sitecore/dist/").FullName;
$files = Get-ChildItem "$distFolder" -Recurse -Force;
$TestFolder = New-Item $(Join-Path $distFolder "Test") -Type Directory -Force;
$optimaFolder = New-Item $(Join-Path $distFolder "optimahealth") -Type Directory -Force;
$files | % { Copy-Item $_.FullName -Destination $_.FullName.Replace($distFolder, "$($testFolder.FullName)/") -Force };
$files | % { Copy-Item $_.FullName -Destination $_.FullName.Replace($distFolder, "$($optimaFolder.FullName)/") -Force };
$files | % { if (Test-Path $_.FullName) { Remove-Item $_.FullName -Recurse -Force -Confirm:$false } }
displayName: Manually create folders for JSS app
- task: ArchiveFiles#2
displayName: "Archive Sitecore code artiffact"
inputs:
rootFolderOrFile: "$(ArtifactsLocation)/sitecore"
archiveFile: "$(ArtifactsLocation)/sc/$(Build.BuildNumber).zip"
verbose: $(system.debug)
includeRootFolder: false
- task: CopyFiles#2
displayName: Copy Id root files
inputs:
SourceFolder: "$(Build.Repository.LocalPath)/src/configs/Id"
TargetFolder: "$(ArtifactsLocation)/id"
Contents: "**"
- task: PublishPipelineArtifact#1
displayName: Publish Sitecore
inputs:
targetPath: "$(ArtifactsLocation)/sc"
artifactName: "SitecoreCode"
- task: PublishPipelineArtifact#1
displayName: Publish ID
inputs:
targetPath: "$(ArtifactsLocation)/id"
artifactName: "SitecoreID"
- job: SitecoreContent
dependsOn: Init
condition: eq(dependencies.check.outputs['ChangedFiles.SCContent'], 'true')
steps:
- template: /environment/azure/templates/steps/dotnet-cli.yml
parameters:
workingDir: "$(Build.Repository.LocalPath)/src"
- task: DotNetCoreCLI#2
displayName: Create Sitecore itempackage
inputs:
command: "custom"
custom: "sitecore"
arguments: "ser pkg create -o $(ArtifactsLocation)/w/test.itempackage"
workingDirectory: "$(Build.Repository.LocalPath)/src"
- ${{ if ne(variables['Build.Reason'],'PullRequest') }}:
- task: CopyFiles#2
displayName: Copy dotnet tools config
inputs:
SourceFolder: $(Build.Repository.LocalPath)/src/.config/ # string. Source Folder.
Contents: '**' # string. Required. Contents. Default: '**'.
TargetFolder: $(ArtifactsLocation)/w/.config/ # string. Required. Target Folder.
- task: CopyFiles#2
displayName: Copy sitecore dotnet config
inputs:
SourceFolder: $(Build.Repository.LocalPath)/src/ # string. Source Folder.
Contents: 'sitecore.json' # string. Required. Contents. Default: '**'.
TargetFolder: $(ArtifactsLocation)/w/ # string. Required. Target Folder.
- task: PublishPipelineArtifact#1
displayName: Publish Sitecore content
inputs:
targetPath: "$(ArtifactsLocation)/w/"
artifactName: "SitecoreContent"
## Deployment stage
- ${{ if ne(variables['Build.Reason'],'PullRequest') }}:
- template: /environment/azure/templates/deployment.yml
There is error:
Reproduce the same issue with the similar YAML sample:
The cause of the issue is that we are not able to directly use dependencies expression in condition field.
To solve this issue, you need to change the following two points.
To use the variable in previous job, you can define variable to get the output variable in previous job. Then you can use the new variable to set the condition.
The format you used to get the the output variable is incorrect.
Based on your situation, here is the correct sample:dependencies.Init.outputs['ChangedFiles.FE'].
Refer to the following example:
name: test-build$(Rev:.r)
trigger:
branches:
include:
- develop
- release/*
paths:
exclude:
- "environment/**/*"
schedules:
- cron: 0 19 * * 1-5
displayName: evening-deployment
branches:
include:
- develop
always: false # whether to always run the pipeline or only if there have been source code changes since the last successful scheduled run. The default is false.
pool:
vmImage: "windows-latest"
variables:
- group: shared-variables
- name: ArtifactsLocation
value: "$(Build.Repository.LocalPath)/output"
- name: NUGET_PACKAGES
value: "$(Pipeline.Workspace)/.nuget/packages"
stages:
- stage: build
displayName: Build solution
jobs:
- job: Init
steps:
- ${{ if eq(variables['Build.Reason'],'PullRequest') }}:
- template: /environment/azure/templates/steps/validate-pr-title.yml
- task: gitversion/setup#0
displayName: Installing GitVersion tool
inputs:
versionSpec: "5.8.1"
- task: ChangedFiles#1
displayName: check
condition: eq(variables['Build.Reason'], 'PullRequest')
inputs:
rules: |
[FE]
**/*.json
**/*.ts
**/*.js
**/*.tsx
**/*.scss
**/*.html
**/*.css
[BE]
**/*.csproj
**/*.cs
**/*.yml
**/*.yaml
[SCContent]
**/*.json
**/*.yml
**/*.yaml
- task: GitVersion#5
displayName: Generate GitVersion
inputs:
versionSpec: "5.8.1"
runtime: "full"
configFilePath: "$(Build.Repository.LocalPath)/GitVersion.yml"
- script: |
echo deployInt: $(deployInt)
echo deployQa: $(deployQa)
displayName: Show variables for debug
condition: eq(variables['system.debug'], 'true')
- job: SitecoreCode
dependsOn: Init
variables:
changes: $[dependencies.Init.outputs['ChangedFiles.FE'] ]
steps:
- task: UseNode#1
displayName: Install correct Node.Js version
inputs:
version: "16.x"
- task: Cache#2
displayName: Cache cake packages
inputs:
key: 'cake | "$(Agent.OS)"'
restoreKeys: |
cake
path: "$(Build.Repository.LocalPath)/src/tools"
- task: Cache#2
displayName: Cache nuget modules
inputs:
key: 'nuget | "$(Agent.OS)" | **/packages.lock.json,!**/bin/**,!**/obj/**'
restoreKeys: |
nuget | "$(Agent.OS)"
nuget
path: "$(Build.Repository.LocalPath)/src/packages"
- task: Cache#2
displayName: Cache nuget package reference modules
inputs:
key: 'nuget_pr | "$(Agent.OS)" | $(Build.SourcesDirectory)/**/packages.lock.json'
path: "$(NUGET_PACKAGES)"
restoreKeys: |
nuget_pr | "$(Agent.OS)"
nuget_pr
- task: Cache#2
displayName: Cache node modules
inputs:
key: 'npm | "$(Agent.OS)" | $(Build.Repository.LocalPath)/src/package-lock.json'
restoreKeys: |
npm | "$(Agent.OS)"
npm
path: "$(Build.Repository.LocalPath)/src/node_modules"
- task: Cache#2
displayName: Cache client node modules
inputs:
key: 'client_npm | "$(Agent.OS)" | $(Build.Repository.LocalPath)/src/rendering/package-lock.json'
restoreKeys: |
client_npm | "$(Agent.OS)"
client_npm
path: "$(Build.Repository.LocalPath)/src/rendering/node_modules"
- task: DownloadSecureFile#1
displayName: Download license
name: licenseFile
inputs:
secureFile: "license.xml"
- task: PowerShell#2
displayName: Place license file under /src folder
inputs:
targetType: "inline"
script: |
Move-Item $(licenseFile.secureFilePath) "$(Build.Repository.LocalPath)/src/" -Force
- template: /environment/azure/templates/steps/set-assembly-version.yml
- task: Cake#2
displayName: Restore FE and Sitecore modules
condition: Or(eq(variables['changes'], 'true'), ne(variables['Build.Reason'], 'PullRequest'))
inputs:
script: "$(Build.Repository.LocalPath)/src/build.cake"
target: "Server :: Restore"
verbosity: "Quiet"
Version: "1.3.0"
Refer to the doc about Use outputs in a different job
I have an Azure DevOps pipeline:
stages:
- stage: Stage1
jobs:
- job: RunScript
steps:
- task: PowerShell#2
inputs:
pwsh: true
targetType: 'filePath'
filePath: $(System.DefaultWorkingDirectory)/scripts/myscript1.ps1
- stage: Stage2
jobs:
- job: RunScript
steps:
- task: PowerShell#2
inputs:
pwsh: true
targetType: 'filePath'
filePath: $(System.DefaultWorkingDirectory)/scripts/myscript1.ps1
arguments: >
-Arg ??? # <======= HERE
Stage1 runs myscript1.ps1 which is (for simplicity):
$OutputValue = 'Hello'
$OutputValue
It is just a script which will eventually return something.
The problem
The issue is that the value produced by myscript1.ps1 in Stage1 must be consumed by myscript2.ps1 in Stage2.
How can I achieve this?
You need to use output variables as here
With the script myscript1.ps1 as this:
echo "##vso[task.setvariable variable=myOutputVar;isOutput=true]this is the value"
and pipeline:
stages:
- stage: A
jobs:
- job: A1
steps:
- task: PowerShell#2
inputs:
pwsh: true
targetType: 'filePath'
filePath: $(System.DefaultWorkingDirectory)/scripts/myscript1.ps1
name: setvarStep
- stage: B
dependsOn: A
variables:
myVarfromStageA: $[ stageDependencies.A.A1.outputs['setvarStep.myOutputVar'] ]
jobs:
- job: B1
steps:
- script: echo $(myVarfromStageA)
You can retrive value in the next stage.
It doesn't matter if you use it inside the script file. But important here is to have step named as later you will use it to reference output variable created by it.
I am trying to setup variable from predefined variable of pipeline resources and use it in condition for stage, but i could not succeeded. below is the my pipeline
resources:
pipelines:
- pipeline: pipeline1
project: appcom
source: pipeline-api
trigger:
branches:
- develop
- feat/*
- pipeline: pipeline2
project: appcom
source: pipeline2-api
trigger:
branches:
- develop
- feat/*
variables:
- name: alias
value: $(resources.triggeringAlias)
stages:
- stage: DEV
displayName: Deploying to DEV
jobs:
- deployment: Deployment
displayName: Deploying to Dev
environment: dev
pool:
name: 'CDaaSLinux'
strategy:
runOnce:
deploy:
steps:
- template: /variables/variable.yaml
- script: echo $(alias)
- task: Bash#3
inputs:
targetType: 'inline'
script: |
if [ "$(alias)" == "pipeline1" ]; then
echo "##vso[task.setvariable variable=apiname]$(resources.pipeline.pipeline1.pipelineName)"
echo "##vso[task.setvariable variable=branchName]$(resources.pipeline.pipeline1.sourceBranch)"
echo "##vso[task.setvariable variable=dockertag]$(resources.pipeline.pipeline1.sourceCommit) | cut -c -7"
echo "##vso[task.setvariable variable=helmpath]P02565Mallorca/pipeline1-api"
elif [ "$(alias)" = "pipeline2" ]; then
echo "##vso[task.setvariable variable=apiname]$(resources.pipeline.pipeline2.pipelineName)"
echo "##vso[task.setvariable variable=branchName]$(resources.pipeline.pipeline2.sourceBranch)"
echo "##vso[task.setvariable variable=dockertag]$(resources.pipeline.pipeline2.sourceCommit) | cut -c -7"
echo "##vso[task.setvariable variable=helmpath]P02565Mallorca/pipeline2-api"
fi
- script: echo $(dockertag)
- script: echo $(helmpath)
- script: echo $(apiname)
- script: echo $(branchName)
but I would like to execute above task on top of all stage and set them as global variables and use those variable in condition on following stages.
needed condition would be as below
stages:
- stage: DockerBuildtask
condition: and(succeeded(), or(eq(variables['$(branchName'], 'refs/heads/develop'), eq(variables['$(branchName'], 'refs/heads/release'), eq(variables['$(branchName'], 'refs/heads/feat*.'), eq(variables['$(branchName'], 'refs/heads/bugfix*.')))
below is the variable.yaml content
steps:
- task: Bash#3
inputs:
targetType: 'inline'
script: |
if [ "$(alias)" == "pipeline1" ]; then
echo "##vso[task.setvariable variable=apibuild]$(resources.pipeline.pipeline1.pipelineName)"
echo "##vso[task.setvariable variable=branchName;isOutput=true]$(resources.pipeline.pipeline1.sourceBranch)"
echo "##vso[task.setvariable variable=dockertag]$(echo '$(resources.pipeline.pipeline1.sourceCommit)' | cut -c -7)"
echo "##vso[task.setvariable variable=apiname]pipeline1-api"
could someone help me on this issue. thanks in advance
trying to use set variable from predefined variables and use it in condition for stage in azure devops pipeline
You could use Output variables from previous stages:
Dependencies.stageName.outputs['jobName.stepName.variableName']
Please check the document Jobs can access output variables from previous stages for some more details.
And we need also add a property ;isOutput=true and name to the previous stages:
echo "##vso[task.setvariable variable=branchName;isOutput=true]$(resources.pipeline.pipeline1.sourceBranch)"
- task: PowerShell#2
displayName: 'Inline Powershell'
inputs:
TargetType: inline
Script: |
if ("$(alias)" -eq "PipelineA")
{
...
}
pwsh: true
name: powershelltest
Then we could use the Dependencies.stageName.outputs['jobName.stepName.variableName'] as condition in next stage:
- stage: DockerBuildtask
and(succeeded(), or(eq(dependencies.ScanImage.outputs['ScanImage.powershelltest.branchName'], 'refs/heads/develop'), eq(dependencies.ScanImage.outputs['ScanImage.powershelltest.branchName'], 'refs/heads/release'), eq(dependencies.ScanImage.outputs['ScanImage.powershelltest.branchName'], 'refs/heads/feat*.'), eq(dependencies.ScanImage.outputs['ScanImage.powershelltest.branchName'], 'refs/heads/bugfix*.')))
Note: Since you need add the condition on top of all stage, we need update the stages refer from stageDependencies.stageName.jobName.outputs['stepName.variableName'] To Dependencies.stageName.outputs['jobName.stepName.variableName']
Update2:
here i am setting variable(variable.yaml) under deployment not job. so
how would i frame below one
Dependencies.stageNam.outputs['jobName.stepName.variableName'] should
i meniton Deployment as jobName ??
The answer is yes.
You could use the Dependencies.stageName.outputs['jobName.jobName.stepName.variableName'] as condition.
Note: There are two jobName in the conditions.
I have some templates and i'd like to check if variables are set or not.
So i tried this:
Template that gets included:
- ${{if not(variables.assemblyVersion)}}:
- task: PowerShell#2
inputs:
targetType: 'inline'
script: |
Write-Host $(assemblyVersion)
throw "assemblyVersion was not set"
But even if set assemblyVersion to something (e.g. 1.2.3.4) that task is being ran.
What am i doing wrong?
Edit: tried the answer from Krzysztof Madej, and i got false-positives:
Output:
2020-11-19T09:36:30.7383677Z ##[section]Starting: PowerShell
2020-11-19T09:36:30.7500976Z ==============================================================================
2020-11-19T09:36:30.7501272Z Task : PowerShell
2020-11-19T09:36:30.7501523Z Description : Run a PowerShell script on Linux, macOS, or Windows
2020-11-19T09:36:30.7501778Z Version : 2.170.1
2020-11-19T09:36:30.7501984Z Author : Microsoft Corporation
2020-11-19T09:36:30.7502296Z Help : https://learn.microsoft.com/azure/devops/pipelines/tasks/utility/powershell
2020-11-19T09:36:30.7502761Z ==============================================================================
2020-11-19T09:36:31.9944831Z Generating script.
2020-11-19T09:36:32.1228113Z ========================== Starting Command Output ===========================
2020-11-19T09:36:32.1504771Z ##[command]"C:\windows\System32\WindowsPowerShell\v1.0\powershell.exe" -NoLogo -NoProfile -NonInteractive -ExecutionPolicy Unrestricted -Command ". 'D:\a\_temp\2af656c2-be5b-4a73-8812-17185fff83cc.ps1'"
2020-11-19T09:36:32.4080866Z 1.2.3.4
2020-11-19T09:36:32.7066175Z assemblyVersion was not set
2020-11-19T09:36:32.7066649Z At D:\a\_temp\2af656c2-be5b-4a73-8812-17185fff83cc.ps1:4 char:1
2020-11-19T09:36:32.7067329Z + throw "assemblyVersion was not set"
2020-11-19T09:36:32.7068304Z + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2020-11-19T09:36:32.7069103Z + CategoryInfo : OperationStopped: (assemblyVersion was not set:String) [], RuntimeException
2020-11-19T09:36:32.7069840Z + FullyQualifiedErrorId : assemblyVersion was not set
2020-11-19T09:36:32.7070536Z
2020-11-19T09:36:32.8288504Z ##[error]PowerShell exited with code '1'.
2020-11-19T09:36:32.8929792Z ##[section]Finishing: PowerShell
Main pipeline where yaml is set:
trigger:
- master
- feature/*
pool:
vmImage: 'windows-latest'
variables:
- group: HmiSulis
- name: solution
value: AllProjects.sln
- name: buildPlatform
value: x86
- name: buildConfiguration
value: Debug
- name: assemblyVersion
value: 1.2.3.4
- name: fileVersion
value: 5.6.7.8
- name: informationalVersion
value: 9.10.11.12
resources:
repositories:
- repository: BuildTemplates
type: git
name: HMI/BuildTemplates
extends:
template: netFx/Jobs/netFx.Build.yml#BuildTemplates
The job used:
jobs:
- job: Build
steps:
- template: ../../NuGet/Steps/NuGet.Restore.yml
- template: ../Steps/netFx.Build.Version.yml
- template: ../Steps/netFx.Build.yml
The steps with the checks (netFx.Build.Version.yml):
steps:
- ${{if not(variables['assemblyVersion'])}}:
- task: PowerShell#2
inputs:
targetType: 'inline'
script: |
Write-Host $(assemblyVersion)
throw "assemblyVersion was not set"
- ${{if not(variables['fileVersion'])}}:
- task: PowerShell#2
inputs:
targetType: 'inline'
script: |
throw "fileVersion was not set"
- ${{if not(variables['informationalVersion'])}}:
- task: PowerShell#2
inputs:
targetType: 'inline'
script: |
throw "informationalVersion was not set"
- task: Assembly-Info-NetFramework#2
inputs:
Path: '$(Build.SourcesDirectory)'
FileNames: |
**\AssemblyInfo.cs
**\AssemblyInfo.vb
InsertAttributes: true
FileEncoding: 'auto'
WriteBOM: false
VersionNumber: '$(assemblyVersion)'
# File version in windows explorer
FileVersionNumber: '$(fileVersion)'
# Product version in windows explorer
InformationalVersion: '$(informationalVersion)'
LogLevel: 'verbose'
FailOnWarning: false
DisableTelemetry: false
Please use correct syntax as it is shown here:
variables:
${{ if eq(variables['Build.SourceBranchName'], 'master') }}: # only works if you have a master branch
stageName: prod
pool:
vmImage: 'ubuntu-latest'
steps:
- script: echo ${{variables.stageName}}
so in your case it would be
- ${{if not(variables['assemblyVersion'])}}:
- task: PowerShell#2
inputs:
targetType: 'inline'
script: |
Write-Host $(assemblyVersion)
throw "assemblyVersion was not set"
You can use an if clause to conditionally assign the value or a variable or set inputs for tasks. Conditionals only work when using template syntax.
I simplified your case and it works:
variables:
- name: solution
value: AllProjects.sln
- name: buildPlatform
value: x86
- name: buildConfiguration
value: Debug
- name: assemblyVersion
value: ''
# value: 1.2.3.4
- name: fileVersion
value: 5.6.7.8
- name: informationalVersion
value: 9.10.11.12
pool:
vmImage: 'ubuntu-latest'
jobs:
- job: Build
variables:
- name: test
value: $[not(variables['assemblyVersion'])]
steps:
- ${{if not(variables['assemblyVersion'])}}:
- task: PowerShell#2
continueOnError: true
inputs:
targetType: 'inline'
script: |
Write-Host $(assemblyVersion)
throw "assemblyVersion was not set"
- task: PowerShell#2
continueOnError: true
inputs:
targetType: 'inline'
script: |
Write-Host $(assemblyVersion)
Write-Host $(test)
So when assemblyVersion is given task is skipped. And when is not given task is ran and fail. Be aware $(assemblyVersion) it means that variable have to be available even if not set.
I made further tests moving logic to template. So this is my template:
jobs:
- job: BuildFromTemplate
dependsOn: []
variables:
- name: test
value: $[not(variables['assemblyVersion'])]
steps:
- ${{if not(variables['assemblyVersion'])}}:
- task: PowerShell#2
continueOnError: true
inputs:
targetType: 'inline'
script: |
Write-Host $(assemblyVersion)
throw "assemblyVersion was not set"
- task: PowerShell#2
continueOnError: true
inputs:
targetType: 'inline'
script: |
Write-Host $(assemblyVersion)
Write-Host $(test)
and here is the pipeline:
variables:
- name: assemblyVersion
# value: ''
value: 1.2.3.4
pool:
vmImage: 'ubuntu-latest'
stages:
- stage: A
jobs:
- job: Build
variables:
- name: test
value: $[not(variables['assemblyVersion'])]
steps:
- ${{if not(variables['assemblyVersion'])}}:
- task: PowerShell#2
continueOnError: true
inputs:
targetType: 'inline'
script: |
Write-Host $(assemblyVersion)
throw "assemblyVersion was not set"
- task: PowerShell#2
continueOnError: true
inputs:
targetType: 'inline'
script: |
Write-Host $(assemblyVersion)
Write-Host $(test)
- template: template.yaml
and yes job in template failed:
What seems strange, because:
The difference between runtime and compile time expression syntaxes is primarily what context is available. In a compile-time expression (${{ }}), you have access to parameters and statically defined variables. In a runtime expression ($[ ]), you have access to more variables but no parameters.
and assemblyVersion is statically defined variable.
It looks that we can use only paramaters in template expression in templates and not variables.
I created a bug on developer community for this.
IMHO if you want to use template you need to move this condition into task and just skip logic.
- task: PowerShell#2
continueOnError: true
inputs:
targetType: 'inline'
script: |
$ver = '$(assemblyVersion)'
Write-Host "Ver: $($ver)"
if (!$ver)
{
throw "assemblyVersion was not set"
}
Or use templates variable and reuse it in main file and template file:
parameters:
- name: 'variabaleTemplate'
default: 'variables.yaml'
type: string
jobs:
- job: BuildFromTemplate
dependsOn: []
variables:
- template: ${{parameters.variabaleTemplate}}
- name: test
value: $[not(variables['assemblyVersion'])]
steps:
- ${{if not(variables['assemblyVersion'])}}:
- task: PowerShell#2
continueOnError: true
inputs:
targetType: 'inline'
script: |
Write-Host $(assemblyVersion)
throw "assemblyVersion was not set"
with variables.yaml like
variables:
- name: assemblyVersion
# value: ''
value: 1.2.3.4
and main file like:
stages:
- stage: A
variables:
- template: variables.yaml
jobs:
- template: template2.yaml
So I got reply from MS
For security reasons, we only allow you to pass information into templated code via explicit parameters.
https://learn.microsoft.com/en-us/azure/devops/pipelines/process/templates?view=azure-devops
The means the author of the pipeline using your template needs to commit changes where they explicitly pass the needed info into your template code.
There are some exceptions to this, where the variable is statically defined in the same file or at pipeline compile time, but generally speaking, it’s probably better to use parameters for everything that does not involve system-defined read-only dynamic variable and custom-defined dynamic output variables.
So solution with separate variable template yaml is the best what is possible I think. Otherwise you need to pass all values via template parameters.
Let's say I have the following parameters in my pipeline:
parameters:
- name: environment
displayName: 'Environment'
default: 'SERVER_0562'
type: string
values:
- 'SERVER_0562'
- 'SERVER_5149'
- 'SERVER_1892'
But I don't want whoever is running the pipeline to see these names when selecting the Environment from the dropdown list. I want then to see the following names:
- QA Server
- DEV Server
- PROD Server
Is there any "easy" way to do so or the only way would be to deal with conditionals?
${{ if eq(parameters.environment, 'DEV Server') }}:
Please check this:
parameters:
- name: image
displayName: Pool Image
type: string
default: Ubuntu
values:
- Windows
- Ubuntu
- MacOS
trigger: none
jobs:
- job: build
displayName: build
pool:
${{ if eq(parameters.image, 'Ubuntu') }}:
vmImage: 'ubuntu-latest'
${{ if eq(parameters.image, 'Windows') }}:
vmImage: 'windows-latest'
${{ if eq(parameters.image, 'MacOS') }}:
vmImage: 'macOS-latest'
steps:
- script: echo building $(Build.BuildNumber) with ${{ parameters.image }}
After you changed a question I think this may help you
parameters:
- name: environment
displayName: 'Environment'
default: 'QA Server'
type: string
values:
- 'QA Server'
- 'DEV Server'
- 'PROD Server'
trigger: none
variables:
- name: QA
value: 'SERVER_0562'
- name: DEV
value: 'SERVER_5149'
- name: PROD
value: 'SERVER_1892'
jobs:
- job: build
displayName: build
pool:
vmImage: 'windows-latest'
steps:
- script: echo building $(Build.BuildNumber) with ${{ parameters.environment }}
- powershell: |
If('${{ parameters.environment }}' -eq 'QA Server') {
Write-Host '##vso[task.setvariable variable=folderName;isOutput=true]$(QA)'
} ElseIf('${{ parameters.environment }}' -eq 'DEV Server') {
Write-Host '##vso[task.setvariable variable=folderName;isOutput=true]$(DEV)'
} ElseIf('${{ parameters.environment }}' -eq 'PROD Server') {
Write-Host '##vso[task.setvariable variable=folderName;isOutput=true]$(PROD)'
} Else {
Write-Host 'I am here'
}
name: setFolderName
- powershell: |
Write-Host '$(setFolderName.folderName)'
Inspired by the contribution of #Krzysztof Madej, I ended up solving my own issue by conditionally assigning variables:
parameters:
- name: environment
displayName: 'Environment'
default: 'QA Server'
type: string
values:
- 'QA Server'
- 'DEV Server'
- 'PROD Server'
trigger: none
variables:
${{ if eq(parameters.environment, 'QA Server') }}:
bacon: SERVER_0562
${{ if eq(parameters.environment, 'DEV Server') }}:
bacon: SERVER_5149
${{ if eq(parameters.environment, 'PROD Server') }}:
bacon: SERVER_1892
jobs:
- job: build
displayName: build
steps:
- script: echo building $(Build.BuildNumber) with ${{ variables.bacon }}
I believe this is an easier implementation since I'm not dependent on a PowerShell script.