Scripts/Set-AzDevOpsArmOutputs.ps1

param(
   [string][parameter(Mandatory = $false)] $VariableGroupName,
   [string][parameter(Mandatory = $false)] $ArmOutputsEnvironmentVariableName = "ArmOutputs",
   [switch][parameter(Mandatory = $false)] $UpdateVariableGroup = $false,
   [switch][parameter(Mandatory = $false)] $UpdateVariablesForCurrentJob = $false
)

function Add-VariableGroupVariable()
{
    [CmdletBinding()]
    param
    (
        [string][parameter(Mandatory = $true)]$VariableGroupName,
        [string][parameter(Mandatory = $true)]$variableName,
        [string][parameter(Mandatory = $true)]$variableValue
    )
    BEGIN
    {
        Write-Verbose "Retrieving Azure DevOps project details for variable group '$VariableGroupName'..."
        [String]$project = "$env:SYSTEM_TEAMPROJECT"
        [String]$projectUri = "$env:SYSTEM_TEAMFOUNDATIONCOLLECTIONURI"
        [String]$apiVersion = "4.1-preview.1"
        Write-Debug "Using Azure DevOps project: $project, project URI: $projectUri"
        

        Write-Verbose "Setting authorization headers to retrieve potential existing Azure DevOps variable group '$VariableGroupName'..."
        if ([string]::IsNullOrEmpty($env:SYSTEM_ACCESSTOKEN))
        {
            Write-Error "The SYSTEM_ACCESSTOKEN environment variable is empty. Remember to explicitly allow the build job to access the OAuth Token!"
        }
        $headers = @{ Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN" }


        Write-Verbose "Getting Azure DevOps variable group '$VariableGroupName'..."
        $getVariableGroupUrl= $projectUri + $project + "/_apis/distributedtask/variablegroups?api-version=" + $apiVersion + "&groupName=" + $VariableGroupName
        $variableGroup = (Invoke-RestMethod -Uri $getVariableGroupUrl -Headers $headers -Verbose)

        $releaseName = $env:RELEASE_RELEASENAME
        if ([string]::IsNullOrEmpty($releaseName))
        {
            $releaseName = $env:BUILD_DEFINITIONNAME + " " + $env:BUILD_BUILDNUMBER
        }
        
        if($variableGroup.value)
        {
            Write-Host "Set properties for update of existing Azure DevOps variable group '$variableGroupName'"
            $variableGroup = $variableGroup.value[0]
            $variableGroup | Add-Member -Name "description" -MemberType NoteProperty -Value "Variable group that got auto-updated by release '$releaseName'." -Force
            $method = "Put"
            $upsertVariableGroupUrl = $projectUri + $project + "/_apis/distributedtask/variablegroups/" + $variableGroup.id + "?api-version=" + $apiVersion    
        }
        else
        {
            Write-Host "Set properties for creation of new Azure DevOps variable group '$VariableGroupName'"
            $variableGroup = @{name=$VariableGroupName;type="Vsts";description="Variable group that got auto-updated by release '$releaseName'.";variables=New-Object PSObject;}
            $method = "Post"
            $upsertVariableGroupUrl = $projectUri + $project + "/_apis/distributedtask/variablegroups?api-version=" + $apiVersion
        }

        $variableGroup.variables | Add-Member -Name $variableName -MemberType NoteProperty -Value @{value=$variableValue} -Force

        Write-Verbose "Upserting Azure DevOps variable group '$variableGroupName'..."
        $body = $variableGroup | ConvertTo-Json -Depth 10 -Compress
        Write-Debug $body
        Invoke-RestMethod $upsertVariableGroupUrl -Method $method -Body $body -Headers $headers -ContentType 'application/json; charset=utf-8' -Verbose
    }
}

Write-Verbose "Geting ARM outputs from '$ArmOutputsEnvironmentVariableName' environment variable..."
$json = [System.Environment]::GetEnvironmentVariable($ArmOutputsEnvironmentVariableName)
$armOutputs = ConvertFrom-Json $json

foreach ($output in $armOutputs.PSObject.Properties) {
  $variableName = ($output.Name.Substring(0,1).ToUpper() + $output.Name.Substring(1)).Trim()
  $variableValue = $output.Value.value
  
  if ($UpdateVariableGroup) {
    Write-Host Adding variable $output.Name with value $variableValue to variable group $VariableGroupName
    Add-VariableGroupVariable -VariableGroupName $VariableGroupName -variableName $variableName -variableValue $variableValue
  }

  if ($UpdateVariablesForCurrentJob) {
    Write-Host "The pipeline variable $variableName will be updated to value $variableValue, so it can be used in subsequent tasks of the current job"
    Write-Host "##vso[task.setvariable variable=$variableName]$variableValue"
  }
}