powershellazure-pipelinesazure-pipelines-release-pipelineazure-pipelines-release-task

Cannot update variable in Azure Pipelines Library group from Release definition


I have an Azure Pipelines variable group with tree variables defined in "Library". I want to update one of the values from my pipelines.

I have written this Powershell script to do so.

$variableName = "Version_old"
$url = "$($env:SYSTEM_TEAMFOUNDATIONCOLLECTIONURI)$env:SYSTEM_TEAMPROJECTID/_apis/distributedtask/variablegroups/4?api-version=5.1-preview.1"

$authHeader = @{Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"}
$definition = Invoke-RestMethod -Uri $url -Headers $authHeader

$oldValue = $definition.variables.$variableName.Value
Write-Host "Using old value:" $oldValue

$array = $oldValue.Split(".")
$newValue = $array[0] + "." + $array[1]+"." +  ([int] $array[2] + 1) 
Write-Host "Updating new value:" $newValue

$definition.variables.$variableName.Value = "$($newValue)"
$definitionJson = $definition | ConvertTo-Json -Depth 100 -Compress
Invoke-RestMethod -Method Put -Uri $url -Headers $authHeader -ContentType "application/json" -Body ([System.Text.Encoding]::UTF8.GetBytes($definitionJson)) | Out-Null

When I run this from a build pipeline, everything works as intended - the variable is updated.

When I extract the JSON from the URI created above, I get this:

{
    "createdBy": {
        "displayName": "<redacted>",
        "id": "guid",
        "uniqueName": "<redacted>"
    },
    "createdOn": "2020-12-16T02:21:48.65Z",
    "id": 4,
    "isShared": false,
    "modifiedBy": {
        "displayName": "MyTeam Build Service (myorg)",
        "id": "<redacted>",
        "uniqueName": "Build\\<redacted>"
    },
    "modifiedOn": "2021-03-14T19:55:34.1466667Z",
    "name": "MyTeam",
    "type": "Vsts",
    "variableGroupProjectReferences": [
        {
            "name": "MyTeam",
            "projectReference": {
                "id": "<redacted>",
                "name": "MyTeam"
            }
        }
    ],
    "variables": {
        "API": {
            "value": "0.8.8"
        },
        "UI": {
            "value": "0.7.13"
        },
        "Version_old": {
            "value": "10.0.19"
        }
    }
}

However - when I do a verbatim copy of the script and add it as a Task in a Release pipeline, it fails.

When I add these lines to the script

Write-Host "JSON content from REST API:"
Write-Host $definition.variables.API.value
Write-Host $definition.variables.UI.value
Write-Host $definition.variables.Version_old.value

The result is this in the build pipeline:

2021-03-14T21:15:35.8686524Z JSON content from REST API:
2021-03-14T21:15:35.8769811Z 0.8.9
2021-03-14T21:15:35.8828202Z 0.7.13
2021-03-14T21:15:35.8863094Z 10.0.22
2021-03-14T21:15:35.8912583Z Using old value: 10.0.22
2021-03-14T21:15:35.9233459Z Updating new value: 10.0.23

But this in the release pipeline:

2021-03-14T21:17:42.7708488Z JSON content from REST API:
2021-03-14T21:17:42.7833228Z 
2021-03-14T21:17:42.7863873Z 
2021-03-14T21:17:42.7890923Z 
2021-03-14T21:17:42.7954203Z Using old value: 
2021-03-14T21:17:42.9884159Z You cannot call a method on a null-valued expression.
2021-03-14T21:17:42.9885985Z At C:\agent\_work\_temp\869a5459-3622-464a-9f6e-f20fb6ac1020.ps1:20 char:1
2021-03-14T21:17:42.9886600Z + $array = $oldValue.Split(".")

(I have not added the three more-or-less blank lines)

More debug information:

When I modify the script to pipe the $definition variable to the output like this:

$definition = Invoke-RestMethod -Uri $url -Headers $authHeader
Write-Host "JSON content from REST API:"
Write-Host $definition

This is the result from my build pipeline:

2021-03-14T21:28:25.5046100Z JSON content from REST API:
2021-03-14T21:28:25.5109539Z @{variables=; id=4; type=Vsts; name=MyTeam; createdBy=; createdOn=2020-12-16T02:21:48.65Z; modifiedBy=; modifiedOn=2021-03-14T21:15:35.96Z; isShared=False; variableGroupProjectReferences=System.Object[]}

And this is the result from my release pipeline:

2021-03-14T21:31:50.5474731Z JSON content from REST API:
2021-03-14T21:31:50.5478033Z @{id=4; name=MyTeam; isShared=False; variableGroupProjectReferences=}

Configuration of the release job:

My configuration is this. The "Allow scripts to access the OAuth token" was already ticked off.

enter image description here

So something is clearly different. The exact same lines produce different output depending on whether it is run from the build pipeline or the release pipeline.

What I am doing wrong?

I have configured the build pipeline and the release stage exactly the same. I have linked the variable group in the same way. In the "Release pipeline" I have configured the scope of the variable group link to "Stages --> my stage". Everything seems to be set up correctly ... but it does not work.

Thank you :-)


Solution

  • I test your ps file and I reproduce this issue and solve it in the Release. Please check your release job and make sure your have checked the 'Allow scripts to access the OAuth token'. Attach my test result: enter image description here enter image description here

    Update:

    You can try to check your release security, please make sure you have add the Project Collection Build Service user into your release: enter image description here

    And in your variable group security, you can check if you have set the Project Collection Build Service user Admin access: enter image description here

    You issue seems about the OAuth Token using issue in the release, so we can also try to create a new PAT token and use it in the PS script:

    $token = "xxxxxxx"
    
    $token = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($token)"))
    
    $response2 = Invoke-RestMethod -Uri $urlIds -Headers @{Authorization = "Basic $token"} -Method Post -Body $JSON -ContentType application/json