1

I want to update the value of a release (not the release definition) scoped variable while the stage is running but every time I try I receive following error message.

How can I do this please?

##[error]Invoke-RestMethod : {"$id":"1","innerException":null,"message":"VS402898: Stage 'dev' cannot be modified as it is 
in-progress or completed. Changes were detected in the following properties: 
'Variables'","typeName":"Microsoft.VisualStudio.Services.ReleaseManagement.Data.Exceptions.InvalidRequestException, Mic
rosoft.VisualStudio.Services.ReleaseManagement2.Data","typeKey":"InvalidRequestException","errorCode":0,"eventId":3000}
At line:263 char:5

+     Invoke-RestMethod -Uri $url -Method Put -ContentType "application ...

+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebExc 

   eption

    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
2020-11-03T06:45:48.2096034Z ##[error]PowerShell exited with code '1'.

Example script:

$url = "{0}{1}/_apis/Release/releases/{2}?api-version=5.0" -f $env:SYSTEM_TEAMFOUNDATIONCOLLECTIONURI, $env:SYSTEM_TEAMPROJECTID, $env:RELEASE_RELEASEID

$pipeline = Invoke-RestMethod -Uri $url -Method Get -Headers @{
    Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"
}

# Update an existing scoped variable named TestVar
# Just for StackOverflow we assume that the currently running stage in Azure DevOps Server
# matches this environment[0] below
$pipeline.environments[0].variables.TestVar.value = "NewValue"

$body = $pipeline | ConvertTo-Json -Depth 99

Invoke-RestMethod -Uri $url -Method Put -Body $body-ContentType "application/json" -Headers @{Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"}

Just in case there is another solution out there... What I'm trying to achieve is to have the variable output of a PowerShell script later be used in a separate 'Substitute Files' JSON transformation step to populate the value within an appsettings.json file for a web application. The problem is that the variable is being created in one job, and isn't being used by the Substitute Files step as I assume it needs to be a release variable, not just task variable.

Benjamin
  • 353
  • 1
  • 4
  • 17

1 Answers1

1

It seems that you are using this REST API, according to the error message VS402898: Stage 'dev' cannot be modified as it is in-progress or completed and doc description. We could only use it to update a complete release.

As a workaround, we could change the variable value when we create release.

My test steps: Create a release variable->name it test and set value to 55->Enable the option Settable at release time->add task power shell to print variable test value

Then call the rest API to create release and update runtime release variable.

Note: It will not change the release definition variable.

API:

POST https://{instance}/{collection}/{project}/_apis/release/releases?api-version=5.0

Request Body:

{
  "definitionId": {Release definition ID},
  "artifacts": [
  ],
  "variables": {
    "test": {
      "value": "99"
    }
  }
}

Result:

enter image description here

Update1

It seems that you want to pass variable between agent jobs, we cannot do this in the classic mode, we could use output variables in the YAML mode, please refer to this doc and blog for more details.

Sample code.

jobs:
- job: A
  steps:
  - task: MyTask@1  # this step generates the output variable
    name: ProduceVar  # because we're going to depend on it, we need to name the step
- job: B
  dependsOn: A
  variables:
    # map the output variable from A into this job
    varFromA: $[ dependencies.A.outputs['ProduceVar.MyVar'] ]
  steps:
  - script: echo $(varFromA) # this step uses the mapped-in variable
Vito Liu
  • 7,525
  • 1
  • 8
  • 17
  • Unfortunately setting the value of the variable and triggering the release through the REST API isn't an option here. The value is generated as part of one of the release steps and then must be used in a later job. Through additional testing I have found that if I add or update a Release-scoped variable instead of a scoped variable it does actually let me update the release. I'm wondering now why you can't modify the currently running stage variables... A possible workaround could be to just add the variable as a Release one and use that instead... – Benjamin Nov 04 '20 at 01:40
  • Hi @Benjamin, Do you mean that you change the release variable scope to release instead of stage, then you could update the release variable at the release runtime and use it in this release? Have you changed the script? I tried it but could not get the same result with you. – Vito Liu Nov 04 '20 at 01:53
  • Yes. If I add a new variable to the release with the scope of Release it lets me add it. The problem now is that even though I can see the new variable in the release it is not being used by later steps in the job. I assume this is because the stage takes a snapshot of the state of the release stage when it starts and used whatever values are present. If you modify it in any way it does not use those changes until the next stage/release. This is a problem for my use case. – Benjamin Nov 04 '20 at 02:40
  • Maybe I might need to ask a different question to solve the underlying problem in a different way... My real problem is that the Substitute Variables step is not updating the value in my appsettings.json file using a dynamically created variable from a previous job. – Benjamin Nov 04 '20 at 02:42
  • Oof. I just realised I've been calling it "Substitute Variables" when it's officially called the "File transform" step... I'm going to post another question that might better describe what I'm trying to achieve. – Benjamin Nov 04 '20 at 03:01
  • Hi @Benjamin, As a Idea, I am try to get the new variable value and set it to env variable via Write-Host "##vso[task.setvariable variable={new variable name};]$(test)" . Note" test is variable configure in the release variable. Then we can use it in next jobs. – Vito Liu Nov 04 '20 at 03:09
  • This I would love to do. I've already added the variable using that exact syntax. How would I get the File transforms task in the next job to use the variable to substitute within an appsettings.json file? – Benjamin Nov 04 '20 at 03:11
  • https://i.stack.imgur.com/xNaID.png contains an image of a sample of what I'm effectively trying to do. – Benjamin Nov 04 '20 at 03:13
  • Hi @Benjamin, I have update the answer, please check it. – Vito Liu Nov 04 '20 at 06:16
  • Do you expect that by adding a variable in the deployment group job named Authentication.MyVariable with the value of the stagedependency from the previous job, the File tranforms step will actually use that value to update the appsettings.json file? It sounds highly plausible to me, I'm just aware that Azure DevOps Server 2019.1 doesn't support YAML release pipelines just yet (although I'm aware 2020 does and we're upgrading to that shortly) – Benjamin Nov 04 '20 at 06:21
  • 1
    Hi @Benjamin, Yes, we could create release definition with YAML mode, just define the stage as release and then define the release definition in the yaml file. You could refer to this [blog](https://devblogs.microsoft.com/devops/whats-new-with-azure-pipelines/) for more details. – Vito Liu Nov 04 '20 at 06:55
  • Cool, thank you! I won't be able to try this until my organisation upgrades to Azure DevOps Server 2020 but then I'll absolutely be trying this :) – Benjamin Nov 05 '20 at 04:50