5

We had set up my TFS CI Build, and we're managing one variable for our purposes to maintaining versioning, We want to update after every success build, any idea how to do so?

I had written PowerShell script

param([Int32]$currentPatchVersion)
Write-Host "Current patch version "$currentPatchVersion
$NewVersion=$currentPatchVersion + 1
Write-Host "New patch version "$NewVersion
Write-Host ("##vso[task.setvariable variable=PackageVersion.Patch;]$NewVersion")

but it just applies on the fly.

I want's to apply it on setting permanently.

Community
  • 1
  • 1
Nilesh Moradiya
  • 691
  • 1
  • 10
  • 19

1 Answers1

8

"##vso[task.setvariable variable=PackageVersion.Patch;]$NewVersion" just set the variable value in the build process, it doesn't set the value in the build definition level. If you want to update the variable value in the build definition permanently, you can call the Rest API to set the value of the variables in the definition. Refer to following section for details:

Create a "testvariable" as example: enter image description here

Create a Power Shell script with following code and upload it into source control:

[String]$buildID = "$env:BUILD_BUILDID"
[String]$project = "$env:SYSTEM_TEAMPROJECT"
[String]$projecturi = "$env:SYSTEM_TEAMFOUNDATIONCOLLECTIONURI"

$username="alternativeusername"
$password="alternativepassword"

$basicAuth= ("{0}:{1}"-f $username,$password)
$basicAuth=[System.Text.Encoding]::UTF8.GetBytes($basicAuth)
$basicAuth=[System.Convert]::ToBase64String($basicAuth)
$headers= @{Authorization=("Basic {0}"-f $basicAuth)}

$buildurl= $projecturi + $project + "/_apis/build/builds/" + $buildID + "?api-version=2.0"

$getbuild = Invoke-RestMethod -Uri $buildurl -headers $headers -Method Get |select definition

$definitionid = $getbuild.definition.id

$defurl = $projecturi + $project + "/_apis/build/definitions/" + $definitionid + "?api-version=2.0"

$definition = Invoke-RestMethod -Uri $defurl -headers $headers -Method Get

$definition.variables.testvariable.value = "1.0.0.1"

$json = @($definition) | ConvertTo-Json  -Depth 999

$updatedef = Invoke-RestMethod  -Uri $defurl -headers $headers -Method Put -Body $json -ContentType "application/json; charset=utf-8"

This script will get the current build definition and update the value of "testvariable" to "1.0.0.1". You need to enable alternative credential.

And then you can add a "PowerShell Script" task in your build definition to run this script.

Per Salmi
  • 1,398
  • 1
  • 14
  • 28
Eddie Chen - MSFT
  • 29,708
  • 2
  • 46
  • 60
  • I had search through, Could you show me the example? – Nilesh Moradiya Jun 20 '16 at 06:52
  • I'm not able to enable alternative credentials in TFS on on premises, is there any way for it to enable? – Nilesh Moradiya Jun 20 '16 at 09:01
  • @Nilesh_Moradiya For On-premise TFS, you can enable "Basic" authentication for the server. – Eddie Chen - MSFT Jun 20 '16 at 09:04
  • Yes it helped and achieved it. Thankyou #happy_deving – Nilesh Moradiya Jun 20 '16 at 13:04
  • @Nilesh_Moradiya Can you mark it as answer if it works? :) – Eddie Chen - MSFT Jun 20 '16 at 23:31
  • Thanks for your answer. Moreover, in my situation, I met other issues. Somehow I solve them one by one via some articles: 1.[ConvertTo-Json throws error](https://stackoverflow.com/questions/23552000/convertto-json-throws-error-when-using-a-string-terminating-in-backslash) 2.[Use Invoke-WebRequest with a username and password](https://stackoverflow.com/questions/27951561/use-invoke-webrequest-with-a-username-and-password-for-basic-authentication-on-t) 3.[Error Handling for Invoke-RestMethod](https://stackoverflow.com/questions/29613572/error-handling-for-invoke-restmethod-powershell) – Mystic Lin Jul 26 '17 at 07:25
  • Moreover, if there is any symbol character (ex: © ) in building definitions or somewhere, the latest 'Invoke-RestMethod' would occur errors. – Mystic Lin Oct 27 '17 at 02:26
  • To make this work with characters outside the ordinary ASCII set in the $definition content body like @MysticLin mentions above the content type should be set to include an encoding like this: -ContentType "application/json; charset=utf-8" – Per Salmi Sep 28 '18 at 16:52
  • Is there a way to loop through all of the variables and update when a string matches? This is pretty hard coded in the sense the you are tied to: $definition.variables.testvariable.value = "1.0.0.1" but I want to pass in an object, look to see if the name of the object matches the name of the variable and if it does then I update the variable with the value from the object. I can do this in C# using the client libraries, I guess i'll have to load the json into some object? – gperrego Apr 30 '19 at 00:14
  • Something like: # Call the rest-API to get the definition details $BuildDefinition = Invoke-RestMethod -Uri $BuildDefUrl -Method Get -Headers @{Authorization=("Basic {0}" -f $base64AuthInfo)} foreach ($BuildVariable in $BuildVariables) { foreach ($defVar in $BuildDefiniton.variables) { if ($defvar.name = $BuildVariable.name) { Write-Host $BuildVariable.name " found" $defvar.value = $BuildVariable.value break } } } – gperrego Apr 30 '19 at 00:21