SOLVED

Passing a here-string as adhoc Output Variable

Copper Contributor

I would like to send a multiple line here-string as an output variable in my release pipeline. For whatever reason when I try to do this, it only returns the first line of text. 


For example (PowerShell):

$output = @'
This is some text that I want to send
to another task in my pipeline.
'@

Write-Host "##vso[task.setvariable variable=scriptOutputMsg;]$output"

This only returns as "This is some text that I want to send" in a downstream task. How do I get it to return text on additional lines?

9 Replies

@brandonmc909 

 

Can confirm the return message? 

best response confirmed by brandonmc909 (Copper Contributor)
Solution

@brandonmc909 

In Azure DevOps pipelines, when you set a variable using the `Write-Host` command as you've shown in your example, the variable is set to the value until the first newline character. To set a multi-line variable, you can use a different approach. You can use the `Write-Host` command with multiple `##vso[task.setvariable]` commands to set the variable line by line.

 

Here's an example of how you can set a multi-line variable in PowerShell:

$lines = @(
    "This is some text that I want to send",
    "to another task in my pipeline.",
    "This is another line of text."
)

foreach ($line in $lines) {
    Write-Host "##vso[task.setvariable variable=scriptOutputMsg;isOutput=true]$line"
}

 

This PowerShell script creates an array of lines and then iterates through the lines, setting the `scriptOutputMsg` variable one line at a time. The `isOutput=true` parameter is used to indicate that this is an output variable.

In your downstream tasks, you can access this multi-line variable as `$(scriptOutputMsg)` and it will retain all the lines you've set in the loop.

Makes sense. Thank you.

this solution is not working, what happen is the values get replaced by whatever is the last line in the lines! so in example above $(scriptOutputMsg) contains "This is another line of text." only. I tried all the solution I could find online, none of them are working, so I believe there is no way to pass a string with newline in it.

If you find that there is no direct way to pass a string with newline characters in Azure DevOps variables, you might need to adjust your pipeline scripting or consider alternative approaches based on the specific requirements of your use case.
I have a docker build template (build_docker.yaml file with content below) that accept tags as parameter, it all works if we tag the docker image with one version but does not work if the image needs to be tagged with multiple tags:

parameters:
...
- name: azureServiceConnection
displayName: The service connection that has access to azure container registry in development environment
type: string

- name: dockerfilePath
displayName: The path to docker file
type: string

- name: image
displayName: The name of image
type: string

- name: containerRegistry
displayName: The name of container registry in development environment
type: string

- name: dockerBuildArgs
displayName: Any arguments as --build-arg, by deafult is empty (passing no argumnets to docker build command )
type: string
default: ' '

- name: versions
displayName: The versions of the image (list of tags that new generated image must be tagged with, coma separatd)
type: string

jobs:
- job: docker build
....
steps:
- task: AzureCLI@2
displayName: Acr login
inputs:
azureSubscription: ${{ parameters.azureServiceConnection }}
scriptType: "bash"
scriptLocation: "inlineScript"
failOnStandardError: false
inlineScript: |
az acr login --name ${{ parameters.containerRegistry }}

- powershell: |
$versions = "${{ parameters.versions }}"
$versionlist = $versions.Split(",") | foreach {$_.Trim() }
foreach ($version in $versionlist){
Write-Host "##vso[task.setvariable variable=TAGS;isOutput=true]$version"
}
displayName: 'Set versions for docker tasks'
name: SetVersions

- bash: |
echo $(SetVersions.TAGS)

- task: Docker@2
displayName: Build ${{ parameters.image }} image
inputs:
command: build
dockerfile: ${{ parameters.dockerfilePath }}
repository: ${{ parameters.containerRegistry }}/images/${{ parameters.image }}
arguments: --target ${{ parameters.image }} ${{ parameters.dockerBuildArgs }}
tags: |
$(SetVersions.TAGS)

@Robina This solution does not work. Calling set variable multiple times will overwrite the previous value. However, you can use percent encoding to convert new lines into "%0A". Once processed it will be converted back into a new line when the variable is set.


This is briefly mentioned under this section: Set variables in scripts - Azure Pipelines | Microsoft Learn

Thanks, I can confirm using "%0A" as "new line" char works. I've finally managed to update my docker build template to accept the list of versions for tagging.

@Preston2330 

As @Robina mentioned you need to replace the carriage return character with encoded new line character.

 
$MultilineString=@"
This is test
for showing multi lines
in Azure Devops pipeline
"@
$output=$MultilineString -replace "`n", "%0D%0A"

You can pass the $output variable to the rest of pipeline

1 best response

Accepted Solutions
best response confirmed by brandonmc909 (Copper Contributor)
Solution

@brandonmc909 

In Azure DevOps pipelines, when you set a variable using the `Write-Host` command as you've shown in your example, the variable is set to the value until the first newline character. To set a multi-line variable, you can use a different approach. You can use the `Write-Host` command with multiple `##vso[task.setvariable]` commands to set the variable line by line.

 

Here's an example of how you can set a multi-line variable in PowerShell:

$lines = @(
    "This is some text that I want to send",
    "to another task in my pipeline.",
    "This is another line of text."
)

foreach ($line in $lines) {
    Write-Host "##vso[task.setvariable variable=scriptOutputMsg;isOutput=true]$line"
}

 

This PowerShell script creates an array of lines and then iterates through the lines, setting the `scriptOutputMsg` variable one line at a time. The `isOutput=true` parameter is used to indicate that this is an output variable.

In your downstream tasks, you can access this multi-line variable as `$(scriptOutputMsg)` and it will retain all the lines you've set in the loop.

View solution in original post