powershellazure-devopsazure-pipelines

Pass powershell output between tasks in Azure Devops


I have read multiple questions regarding this but I can't make it work.

I want to pass a powershell object (hashtable) between tasks.

I set the hashtable here:

$output += @{
  roleAssignments = $roleAssignments
  subscriptionName = "$workloadName-$omgevingKeyLower"
  subscriptionManagementGroupId = $workloadName
  subscriptionTags = $tags
  subscriptionWorkload = $subscriptionWorkload
  virtualNetworkAddressSpace = $virtualNetworkAddressSpace
}

# Output the entire object as JSON
# the json part is optional as far as I'm concerned. Rather have plain hashtable
$outputJson = $output | ConvertTo-Json -Compress
Write-Output $output

I see the hashtable is returned at conclusion of the task that reads the file and sets the hashtable.

This is my pipeline code:

  - task: PowerShell@2
    displayName: 'Read YAML file'
    name: ReadYaml
    inputs:
      targetType: filePath
      filePath: ./scripts/readYaml.ps1
      arguments: '-filePath ${{ parameters.yamlFilePath }}'

  - task: AzureCLI@2
    displayName: 'Create management group'
    inputs:
      azureSubscription: iaCS-ASE
      scriptType: 'pscore'
      scriptLocation: 'inlineScript'
      inlineScript: |
        echo "print the output"
        & az account management-group create --name $(output.subscriptionManagementGroupId) --parent Landingzones

I want to do $(output.subscriptionName) here. I've tried converting to and from json. accessing keys with and without []. I'm at a loss. Locally in PowerShell it works fine. But ado throws a wrench in the works.


Solution

  • The variables generated in one PowerShell session cannot be referenced in another session. This is true even for local PowerShell prompt not only specific to the task of Azure Pipelines.

    You need to set an output variable for use in the same job and according to the document, All variables are strings.

    Based on the possible data shapes you mentioned so far, here is a sample script and YAML definition to help understand how to safely output a one-line string across tasks in the same agent job.

    scripts/readYaml.ps1

    $roleAssignments = @(
        @{
            'principalName' = "123@abc.com"
            'roleDefinitionName' = "User Access Administrator"
            'scope' = "/"
        }
        @{
            'principalName' = "456@xyz.com"
            'roleDefinitionName' = "Owner"
            'scope' = "/providers/Microsoft.Management/managementGroups/00000000-0000-0000-0000-000000000000"
        }
    )
    
    $workloadName = "sample workload"
    $omgevingKeyLower = "lowerkey"
    $subscriptionWorkload = "some string"
    
    $tags = @{
        'Workload' = "workloadTagValue"
        'TestTag' = "testTagValue"
    }
    
    $virtualNetworkAddressSpace = @{
        addressPrefixes = @( 
            "10.0.0.0/16"
            "192.168.0.0/24"
        )
    }
    
    $output += @{
        roleAssignments = $roleAssignments
        subscriptionName = "$workloadName-$omgevingKeyLower"
        subscriptionManagementGroupId = $workloadName
        subscriptionTags = $tags
        subscriptionWorkload = $subscriptionWorkload
        virtualNetworkAddressSpace = $virtualNetworkAddressSpace
    }
    
    $output | ConvertTo-Json -Depth 10
    
    $outputJson = $output | ConvertTo-Json -Compress
    
    Write-Host "##vso[task.setvariable variable=outputJson]$outputJson"
    
    trigger: none
    
    pool:
      vmImage: ubuntu-latest
    
    steps:
    - task: PowerShell@2
      displayName: 'Read YAML file'
      name: ReadYaml
      inputs:
        targetType: filePath
        filePath: ./scripts/readYaml.ps1
        # arguments: '-filePath ${{ parameters.yamlFilePath }}'
    
    - pwsh: |
        # Using single quotes to safely handle JSON strings
        Write-Host outputJson is '$(outputJson)'
        $output = '$(outputJson)' | ConvertFrom-Json
        
        Write-Host "================ Check output from upstream step in the same job ================"
        Write-Host $output.roleAssignments[0].principalName
        $output | ConvertTo-Json -Depth 10
    

    outputvarialbes