Issue
In my YAML pipeline I have following sequence
- Check the packages that are changed through a powershell function where I pass a path to the folder as parameter and run git diff to find exit code 0 or 1
- I then want to receive the output 0 or 1 in a Bash@3 in my yaml pipeline and run an "if condition" to either skip or build a package
Here is my powershell function
function packageChangeChecker {
param(
[Parameter(Mandatory = $true)]
[string] $pathToPackage
)
git diff HEAD~:src/$pathToPackage HEAD:src/$pathToPackage --exit-code --quiet
if($LastExitCode -eq 1) {
variable=filesChanged;isOutput=False]$false"
return $false
}
elseif($LastExitCode -eq 0) {
return $true
}
}
Here is my Bash@3
- task: Bash@3
displayName: 'detectChanges'
inputs:
targetType: 'inline'
script: |
pathToPackage="docker-dotnet-app-aks2/"
export filesChanged = "powershell.exe "& { . .\package-change-checker.ps1; packageChangeChecker $pathToPackage}""
i then want to use output of files changed in an If condition in my YAML pipeline before calling a template to build the package
- ${{ if eq(stageDependencies.Deploy.preBuildChecks.outputs['detectChanges.filesChanged'], true) }}
I have tried passing on the output of powershell functions as below
filesChanged = "powershell.exe "& { . .\package-change-checker.ps1; packageChangeChecker $pathToPackage}""
I get error in my pipeline with above approach
What's the best way to pass output of powershell function back to the Bash to be used under If condition in YAML file further down
Solution
As a supplement based on the other answers under this topic, please be advised that you should not use conditional insertion (${{if}}
) to evaluate an output variable filesChanged
that is generated at runtime, because conditional insertion as template expression is processed at compile time before runtime starts (see Understand variable syntax).
Instead, you should use condition
property for a stage
, job
, deployment
job, or step
to control whether to skip the downstream stage
/job
/deployment
/step
. Kindly note the syntax depends on how the output variable is generated and how you would use it (across jobs/stages). Check Levels of output variables and dependency syntax overview for more samples.
Assuming your pipeline outputs the variable in an upstream job
(not a deployment
job, as it uses a different syntax in downstream evaluation) and the value of filesChanged
is passed to downstream stage to control whether the downstream stage is to run. Here is a sample for your reference.
stages:
- stage: Deploy
jobs:
- job: preBuildChecks
steps:
- checkout: self
fetchDepth: 0
- task: PowerShell@2
inputs:
targetType: 'inline'
script: |
$pathToPackage="docker-dotnet-app-aks2/"
git diff HEAD~:src/$pathToPackage HEAD:src/$pathToPackage --exit-code --quiet
if($LastExitCode -eq 1) {
Write-Output "##vso[task.setvariable variable=filesChanged;isOutput=true]$true"
}
else {
Write-Output "##vso[task.setvariable variable=filesChanged;isOutput=true]$false"
}
name: detectChanges
continueOnError: true
- task: PowerShell@2
inputs:
targetType: 'inline'
script: |
Write-Host $(detectChanges.filesChanged)
- stage: DownstreamStage
dependsOn: Deploy
condition: eq(dependencies.Deploy.outputs['preBuildChecks.detectChanges.filesChanged'], 'True')
jobs:
- job:
variables:
fileChangedDown: $[stageDependencies.Deploy.preBuildChecks.outputs['detectChanges.filesChanged']]
steps:
- powershell: |
Write-Host $(fileChangedDown)
Answered By - Alvin Zhao Answer Checked By - Senaida (WPSolving Volunteer)