I am trying to check if my stage-specific variable sourceCodeChanged is equal to true.
If it is true then the stage should be executed, else it should be skipped.
I can do this by using a condition and comparing sourceCodeChanged with true. this however is not working for me. what am I doing wrong?
This is a snippet out of my azure-pipelines.yml:
- stage: build
dependsOn: determineChanges
variables:
sourceCodeChanged: stageDependencies.determineChanges.checkChanges.outputs['check_changes.SOURCE_CODE_CHANGED']
condition: and(succeeded(), eq(variables.sourceCodeChanged, 'true'))
jobs:
- job: buildBinaries
displayName: Build Binaries
steps:
- bash: echo $(sourceCodechanged)
displayName: TestOutPutDeleteMe #debugging step
I implemented a debugging step called TestOutPutDeleteMe. when the step TestOutPutDeleteMe gets executed it prints out true, so that means the value gets correctly assigned to sourceCodeChanged.
If I try to use the variable sourceCodeChanged in the eq() function it always assigns false to the condition and skips all the steps in the stage.
azure pipeline condition always returns false
That because you are using the condition on the stage level. Please try to using following condition:
- stage: build
dependsOn: determineChanges
condition: eq(Dependencies.determineChanges.outputs['checkChanges.check_changes.SOURCE_CODE_CHANGED'], 'true')
Please note that we need update the stages refer from stageDependencies.stageName.jobName.outputs['stepName.variableName'] To Dependencies.stageName.outputs['jobName.stepName.variableName']
And not use the variable for the value Dependencies.determineChanges.outputs['checkChanges.check_changes.SOURCE_CODE_CHANGED']
My test result:
stages:
- stage: stageA
jobs:
- job: A
pool:
name: Default
steps:
- task: PowerShell#2
displayName: "create a variable"
inputs:
targetType: 'inline'
script: |
Write-Host "##vso[task.setvariable variable=CustomVar;isOutput=true]true"
name: CustomVariable
- stage: stageB
dependsOn: stageA
condition: eq(Dependencies.stageA.outputs['A.CustomVariable.CustomVar'], 'true')
jobs:
- job: A
pool:
name: Default
steps:
- task: PowerShell#2
displayName: "output the variable"
inputs:
targetType: 'inline'
script: |
Write-Host "hello world"
Related
How to make Delay task take value from variable instead of hardcoded value for delayForMinutes input?
When i do following, it works fine:
- job: WaitForDeploy
dependsOn: Main
pool: Server
steps:
- task: Delay#1
inputs:
delayForMinutes: '1'
but when i do it like this it does not:
- job: WaitForDeploy
dependsOn: Main
pool: Server
steps:
- task: Delay#1
inputs:
delayForMinutes: '$(SleepCount)'
$(SleepCount) is defined in variables as empty string and later on is passed from python script to pipeline via:
print(f'##vso[task.setvariable variable=SleepCount]{delay_seconds}')
I am printing this out in previos job and it shows intiger correctly:
- script: 'echo $(SleepCount)'
displayName: "print_sleep_count"
it looks like this variable value is not passed beyond job where i return it from python script, how to pass it?
This do not work:
variables:
SleepCount: ""
jobs:
- job: Main
pool:
name: 'CDaaSLinux'
[...]
- task: PythonScript#0
inputs:
scriptSource: 'filePath'
scriptPath: '$(Build.SourcesDirectory)/sleep_count.py'
env:
ACTUAL_START_DATE: $(ActualStartDate_value)
- script: 'echo $(SleepCount)'
name: setVariable
displayName: "print_sleep_count"
- script: 'echo "Waiting for Deploy for $(SleepCount) minutes"'
displayName: "Deploy_message_for_user"
- job: WaitForDeploy
dependsOn: Main
variables:
SleepCount: $[ dependencies.Main.outputs['setVariable.SleepCount']]
pool: Server
steps:
- task: Delay#1
inputs:
delayForMinutes: '$(SleepCount)'
In order to use a variable in a different stage/job you need to set the isoutput flag when setting the variable
print(f'##vso[task.setvariable variable=SleepCount;isoutput=true]{delay_seconds}')
Set an output variable for use in future jobs
I am trying to pass variables between stages. I was successfully able to pass values to immediate next stage, but after that the variables are blank. I tried all the ways to get this, but failing
stages:
- stage: InitialStage
jobs:
- job: StandAlone
displayName: Required Stand Alone Job
steps:
- bash: |
echo "##vso[task.setvariable variable=doThing;isOutput=true]Yes"
name: bash_test
- stage: SecondStage
jobs:
- job:
displayName: SecondStage
variables:
variable1: $[ stageDependencies.InitialStage.StandAlone.outputs['bash_test.doThing'] ]
steps:
- task: CmdLine#2
name: test
inputs:
script: |
echo "$(variable1)"
- stage: ThirdStage
jobs:
- job:
displayName: ThirdStage
variables:
variable1: $[ stageDependencies.InitialStage.StandAlone.outputs['bash_test.doThing'] ]
steps:
- task: CmdLine#2
name: test
inputs:
script: |
echo "$(variable1)"
The echo at stage SecondStage will give value, but ThirdStage it is blank, I am having a doubt either we can access a variable only in immediate stage or else I am doing something wrong, any help on this will be much appreciated.
Option 1:
In order to pass variable to the another stage you need to add isOutput=true
See the example as shown below;
- task: Bash#3
name: setprojectName
inputs:
targetType: 'inline'
script: |
echo "##vso[task.setvariable variable=projectNameGlobal;isOutput=true]$(echo $(Build.Repository.Name)| sed 's|.*/||')"
echo "##vso[task.setvariable variable=projectName]$(echo $(Build.Repository.Name)| sed 's|.*/||')"
projectName is only available the stage where variable populated but projectNameGlobal is available in next stage also.
Also see the documentation
Option 2:
## azure-pipelines.yml
stages:
- stage: one
jobs:
- job: A
steps:
- task: Bash#3
inputs:
filePath: 'script-a.sh'
name: setvar
- bash: |
echo "##vso[task.setvariable variable=skipsubsequent;isOutput=true]true"
name: skipstep
- stage: two
jobs:
- job: B
variables:
- name: StageSauce
value: $[ stageDependencies.one.A.outputs['setvar.sauce'] ]
- name: skipMe
value: $[ stageDependencies.one.A.outputs['skipstep.skipsubsequent'] ]
steps:
- task: Bash#3
inputs:
filePath: 'script-b.sh'
name: fileversion
env:
StageSauce: $(StageSauce) # predefined in variables section
skipMe: $(skipMe) # predefined in variables section
- task: Bash#3
inputs:
targetType: 'inline'
script: |
echo 'Hello inline version'
echo $(skipMe)
echo $(StageSauce)
In above option you can see how to use one variable where populated by any of the prior stages
i have something like this in my azure pipeline
pool:
name: name
vmImage: Image
stages:
stage: 1
jobs:
job: 1
job: 2
job: 3
stage: 2
condition: will run if stage 1 on job 2 is successful
stage: 3
condition: will run if job 1 or 3 in stage 1 is successful or stage
2 is successful
can I get the job 1 or 3 in stage 1? or can I do a
(dependencies.stage3.job1.result,"Succeeded")
like code?
How to get a job on a different stage in azure pipeline
You could add a task for job1,job2,job3 to set veriables for each job, like:
- task: InlinePowershell#1
displayName: 'SetVariableInJobA'
inputs:
Script: 'Write-Host "##vso[task.setvariable variable=JobA;isOutput=true]true"'
name: JobAResult
Then we could set the condition based on the variables from the job1 to job3 in the stage1 by the syntax stageDependencies.stageName.jobName.outputs['stepName.variableName'].
Please check the document Jobs can access output variables from previous stages for some more details.
So, my final test YAML file looks like:
stages:
- stage: A
jobs:
- job: jobA
steps:
- script: echo "This is JobA"
- task: InlinePowershell#1
displayName: 'SetVariableInJobA'
inputs:
Script: 'Write-Host "##vso[task.setvariable variable=JobA;isOutput=true]true"'
name: JobAResult
- job: jobB
steps:
- script: echo "This is JobB"
- task: InlinePowershell#1
displayName: 'SetVariableInJobB'
inputs:
Script: 'Write-Host "##vso[task.setvariable variable=JobB;isOutput=true]No"'
name: JobBResult
- job: jobC
steps:
- script: echo "This is JobC"
- task: InlinePowershell#1
displayName: 'SetVariableInJobC'
inputs:
Script: 'Write-Host "##vso[task.setvariable variable=JobC;isOutput=true]true"'
name: JobCResult
- stage: B
variables:
testB: $[ stageDependencies.A.jobB.outputs['JobBResult.JobB']]
jobs:
- job:
condition: and(succeeded(), eq(variables.testB, 'Yes'))
steps:
- task: InlinePowershell#1
inputs:
Script: 'Write-Output ''$(testB)'''
- stage: C
variables:
testA: $[ stageDependencies.A.jobA.outputs['JobAResult.JobA']]
testB: $[ stageDependencies.A.jobB.outputs['JobBResult.JobB']]
testC: $[ stageDependencies.A.jobC.outputs['JobCResult.JobC']]
jobs:
- job:
condition: and(succeeded(), or(eq(variables.testA, 'Yes'), or(eq(variables.testB, 'Yes'), eq(variables.testC, 'Yes'))))
steps:
- task: InlinePowershell#1
inputs:
Script: 'Write-Output ''hello world'''
Note:
We could not set the condotion on the stage level directly, that is because the variable $[ stageDependencies.A.jobA.outputs['JobAResult.JobA']] is compile variable, and the varibale we set by the task is runtime variable.
is it possible to declare a variable and then pass it downstream?
I have an image below StageA -> StageB -> StageC
where I obtain a url for my storage account on StageA, and I want to use it for both Stage B and StageC
But if I use the [stagedependencies.StageA.JobA.outputs['var'], it only works on StageB and not on StageC
- stage: 'StageC'
dependsOn: 'StageB'
pool:
vmImage: 'windows-latest'
variables:
blobUri: $[stageDependencies.StageA.JobA.outputs['createOutput.blobUri']]
jobs:
- job: 'JobC'
steps:
- checkout: none
- download: none
- powershell: |
echo JobBUri: $(blobUri)
Maybe I missed it somewhere but does this mean you can only obtain the variable from the immediate stage you depend?
Example:
trigger:
- master
pool:
vmImage: ubuntu-latest
stages:
- stage: 'StageA'
jobs:
- job: 'JobA'
steps:
- task: Powershell#2
name: 'createOutput'
inputs:
targetType: 'inline'
script: |
Write-Output "##vso[task.setvariable variable=blobUri;isOutput=true]www.google.com"
- stage: 'StageB'
dependsOn: 'StageA'
pool:
vmImage: 'windows-latest'
variables:
blobUri: $[stageDependencies.StageA.JobA.outputs['createOutput.blobUri']]
jobs:
- job: 'JobB'
steps:
- powershell: |
echo JobBUri: $(blobUri)
- stage: 'StageC'
dependsOn: 'StageB'
pool:
vmImage: 'windows-latest'
variables:
blobUri: $[stageDependencies.StageA.JobA.outputs['createOutput.blobUri']]
jobs:
- job: 'JobC'
steps:
- powershell: |
echo JobBUri: $(blobUri)
Try this and probably variable set in stage A will be available at stage C by stageDependencies.StageA
- stage: 'StageC'
dependsOn:
- StageA
- StageB
Other workaround is to set again this variable as output variable in stage B and access it from C by stageDependencies.StageB(...)
From release notes
https://learn.microsoft.com/en-us/azure/devops/release-notes/2020/sprint-168-update#jobs-can-access-output-variables-from-previous-stages
By default, each stage in a pipeline depends on the one just before it in the YAML file. Therefore, each stage can use output variables from the prior stage. You can alter the dependency graph, which will also alter which output variables are available. For instance, if stage 3 needs a variable from stage 1, it will need to declare an explicit dependency on stage 1.
The following illustrates that the answer from Kontekst is correct (I was going to edit the post to add this, but don't know if that's appropriate here?):
The following confirms and illustrates that this is the correct answer:
stages:
- stage: A
jobs:
- job: A1
steps:
- pwsh: Write-Host "##vso[task.setvariable variable=varFromA;isOutput=true]A"
name: writevar
- stage: B
dependsOn: A
jobs:
- job: B1
variables:
varA: $[ stageDependencies.A.A1.outputs['writevar.varFromA'] ]
steps:
- pwsh: |
Write-Host "##vso[task.setvariable variable=varFromB;isOutput=true]B"
Write-Host "accesses $(VarA) from A"
name: writevar
- stage: C
dependsOn:
- A
- B
jobs:
- job: C1
variables:
varA: $[ stageDependencies.A.A1.outputs['writevar.varFromA'] ]
varB: $[ stageDependencies.B.B1.outputs['writevar.varFromB'] ]
steps:
- pwsh: |
Write-Host "##vso[task.setvariable variable=varFromC;isOutput=true]C"
Write-Host "accesses $(varB) from B"
Write-Host "accesses $(varA) from A"
name: writevar
I have a yml pipeline with 2 stages:
- stage:
- stage:
My second stage needs to refer to the $(Build.BuildNumber) of the previous stage. How can this be achieved? My understanding is output variables are scoped to the same stage and can't be used across-stages.
Trying to pull from stageDependencies:
stages:
- stage: BuildPublish
displayName: "Build & Publish"
jobs:
- job: BuildPublishJob
displayName: "Build & Publish"
steps:
- script: |
echo "Recording MSI version"
echo "##vso[task.setvariable variable=msiVersion;isOutput=true]$(Build.BuildNumber)"
name: MsiVersion
- script: echo $(MsiVersion.msiVersion)
name: echovar
- stage: DeployInstallerTest
displayName: "Deploy Installer Test"
jobs:
- job:
displayName: "Deploy Installer Test"
steps:
- task: AzurePowerShell#5
inputs:
azureSubscription: 'Spektrix Non-Prod'
ScriptType: 'InlineScript'
Inline: |
$msiVersion = stageDependencies.BuildPublish.BuildPublishJob.outputs['MsiVersion.msiVersion']
azurePowerShellVersion: 'LatestVersion'
Fails with:
##[error]The term 'stageDependencies.BuildPublish.BuildPublishJob.outputs[MsiVersion.msiVersion]' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
It changed recently:
stages:
- stage: A
jobs:
- job: JA
steps:
- script: |
echo "This is job Foo."
echo "##vso[task.setvariable variable=doThing;isOutput=true]Yes" #The variable doThing is set to true
name: DetermineResult
- script: echo $(DetermineResult.doThing)
name: echovar
- job: JA_2
dependsOn: JA
condition: eq(dependencies.JA.outputs['DetermineResult.doThing'], 'Yes')
steps:
- script: |
echo "This is job Bar."
#stage B runs if DetermineResult task set doThing variable n stage A
- stage: B
dependsOn: A
jobs:
- job: JB
condition: eq(stageDependencies.A.JA.outputs['DetermineResult.doThing'], 'Yes') #map doThing and check if true
variables:
varFromStageA: $[ stageDependencies.A.JA.outputs['DetermineResult.doThing'] ]
steps:
- bash: echo "Hello world stage B first job"
- script: echo $(varFromStageA)
However, please be aware that stageDependencies is not available in condition at stage level. Of course you can use stageDependencies not only in condition.