shravya
shravya

Reputation: 21

How to use output variable of one task under a job as a condition to next job's task in azure-yml

I have written a powershell script task under a job in same stage to find the $initialFile from my below script and perfrom few operations.I would like to set a output variable of my powershell script. so that I can use it as a condition in my following copy & publish task. In summary I would like to perform ProcessTestResults only when powershell task finds $initialFile Here is my yaml file:

Stage: Azure 
-jobs:
 -job: A

- task: PowerShell@2
              displayName: 'find failed tests and copy them'
              name: passOutput
              inputs:
                workingDirectory: $(Pipeline.Workspace)/$(Build.BuildId)/Tests/E2EAutomationTests/Logs
                targetType: 'inline'
                script: |
                  Write-Host "Current Working Directory:"
                  Write-Host (Get-Location)
 
                  Write-Host "Contents of the Current Directory:"
                  Get-ChildItem
 
                  $currentDirectory = Get-Location
                  $initialFileName = "failedTests.txt"
                  $targetFolder = ".\FailedTestCopy" 
                  $folders = Get-ChildItem -Path $currentDirectory -Directory
                 $script= foreach ($folder in $folders) {
                      $folderPath = $folder.FullName
                      $aTxtFile = Get-ChildItem -Path $folderPath -Filter $initialFileName -File | Select-Object -First 1
                      if (-not $aTxtFile) {
                          throw "No '$initialFileName' found in the folder '$($folder.Name)'."
                  } else {
                      $destination = Join-Path -Path $targetFolder -ChildPath            Write-Host "Destination directory created: $destination"
                  
                  }
                  }

- job:  ProcessTestResults
          displayName: 'Process Test Results'
          dependsOn: A
          condition: and(succeeded(), eq(dependencies.E2E_test.outputs['passOutput.script'], 'true'))
          steps:
            - task: CopyFiles@2           
              displayName: 'Copy Files to: $(Build.ArtifactStagingDirectory)/${{ parameters.targetfolder }}/TestArtifacts'

              inputs:
                sourceFolder: '$(Pipeline.Workspace)\$(Build.BuildId)\Tests\E2EAutomationTests\Logs\FailedTestCopy'
                contents: |
                 **/failedTests.txt
                  **/*.txt
                  **/*.etl
                
                TargetFolder: '$(Build.ArtifactStagingDirectory)/${{ parameters.targetfolder }}/TestResults'
                OverWrite: true
              continueOnError: true

I have tried using the following conditions in copy task condition: failed() condition: and(succeeded(), eq(dependencies.E2E_test.outputs['passOutput.script'], 'true')) But the evaluation is coming as null

Output of ProcessTestResults Job : Expanded: and(True, eq(Null, 'true')) Result: False

Upvotes: 0

Views: 1357

Answers (1)

wade zhou - MSFT
wade zhou - MSFT

Reputation: 8082

I would like to set a output variable of my powershell script. so that I can use it as a condition in my following copy & publish task.

Step1:

You need to using logging command to set variable (with isOutput=true) in your powershell script in your first job. For example, use $initialFileFound value to indicate if the file is found or not.

Write-Host "##vso[task.setvariable variable=initialFileFound;isoutput=true]yes"

You can use it in if else in your powershell task(for example)

  - task: PowerShell@2
    displayName: 'find failed tests and copy them'
    name: passOutput
    inputs:
      workingDirectory: $(Pipeline.Workspace)/$(Build.BuildId)/Tests/E2EAutomationTests/Logs
      targetType: 'inline'
      script: |
      ......
        if (-not $aTxtFile) {
          Write-Host "No '$initialFileName' found in the folder '$($folder.Name)'."
          Write-Host "##vso[task.setvariable variable=initialFileFound;isoutput=true]no"
        } else {
            $destination = Join-Path -Path $targetFolder -ChildPath
            Write-Host "Destination directory created: $destination"
            Write-Host "##vso[task.setvariable variable=initialFileFound;isoutput=true]yes"
          }
        }

Step2:

In next job, invoke the output variable in condition expression.

  - job:  ProcessTestResults
    displayName: 'Process Test Results'
    dependsOn: A
    condition: eq(dependencies.A.outputs['passOutput.initialFileFound'], 'yes') #map initialFileFound and check the value
    steps:
    .....

If file is NOT found, the next job is skipped:

enter image description here

You can find more details in official doc Use the output variable from a job in a condition in a subsequent job.

Edit:

  1. Fix the stage, job syntax error.

  2. The default working directory is $(Pipeline.Workspace)/s(with s), also $(Build.BuildId) points to build id which will be changed for every build. Do you generate the directory dynamically in the build? If not, please double confirm if the working directory on your yaml is expected. For test, I have folder structure as below in repo:

enter image description here

  1. You use foreach to check the file in every folder, it will override the variable value if you define variable in if&else expression. I add break to jump out once the file is found. Please consider your real situation about this.

  2. I add a step to check the variable value, to confirm it has value.

The full yaml:

trigger: none

pool:
  vmImage: Windows-latest
stages:
  - stage: Azure
    jobs:
      - job: A
        steps:
        - task: PowerShell@2
          displayName: 'find failed tests and copy them'
          name: passOutput
          inputs:
            workingDirectory: '$(Pipeline.Workspace)/s/TestFolder1'
            targetType: 'inline'
            script: |
                Write-Host "Current Working Directory:"
                Write-Host (Get-Location)
 
                Write-Host "Contents of the Current Directory:"
                Get-ChildItem
 
                $currentDirectory = Get-Location
                $initialFileName = "failedTests.txt"
                $targetFolder = ".\FailedTestCopy" 
                $folders = Get-ChildItem -Path $currentDirectory -Directory
                foreach ($folder in $folders) {
                    $folderPath = $folder.FullName
                    $aTxtFile = Get-ChildItem -Path $folderPath -Filter $initialFileName -File -Recurse
                      
                    if (-not $aTxtFile) {
                        Write-Host "No '$initialFileName' found in the folder '$($folder.Name)'."
                        Write-Host "##vso[task.setvariable variable=initialFileFound;isoutput=true]no"

                  } else {
                      $destination = Join-Path -Path $targetFolder -ChildPath $folder.Name
                      New-Item -ItemType Directory -Path $destination | Out-Null
                      Write-Host "Destination directory created: $destination"
                      Write-Host "##vso[task.setvariable variable=initialFileFound;isoutput=true]yes"
                      break       # add break here if the file is found, otherwise it will check for all folders if the file exists, and overwrite the variable.
                  }
                  }

        - script: |
            echo $(passOutput.initialFileFound)
          displayName: Checkthevalue

      - job:  ProcessTestResults
        displayName: 'Process Test Results'
        dependsOn: A
        condition: eq(dependencies.A.outputs['passOutput.initialFileFound'], 'yes')
        steps:
          - script: echo test

File found:

enter image description here

File Not found:

enter image description here

Upvotes: 0

Related Questions