Setting TFS 2017 builds to Partially succeeded - tfs

We have an orchestration build that we would like to set status to partially succeeded if it didn't do certain things. With Xaml builds, we could do it by setting the CompilationStatus and TestStatus of the build.
For Tfs Builds, I can am trying to it by setting calling the TFS Rest API to update the build result.
$query = [uri]::EscapeUriString("$tfsCollection$tfsProject/_apis/build/builds/$buildId`?api-version=2.0")
$request = "{""result"":""$result""}"
try {
$result = Invoke-RestMethod -Method PATCH -UseDefaultCredentials -ContentType "application/json" -Uri $query -Body $request
}
catch{
Write-Output "StatusCode:" + $_.Exception.Response.StatusCode.value__ +
"`r`nStatusDescription:" + $_.Exception.Response.StatusDescription
}
After the call, I can see that the ribbon of the build changes to orange indicating that is partially succeeded. However, it gets changed to succeeded when the Finalize Build step of build is run.
What should I do that the end build finishes with a status partially succeeded.

You can add a task with its control options set to "Continue on Error". Whenever this tasks fails, your build will be partially succeeded.

Related

Get default Testers for Test Suite with powershell script

trying to get the default testers that are assigned to a test suite in azure devops with a powershell script
$coreAreaId = "3b95fb80-fdda-4218-b60e-1052d070ae6b"
$tfsBaseUrl = GetUrl -orgUrl $orgUrl -header $header -AreaId $coreAreaId
$testerUrl = "$($tfsBaseUrl)$projectname/_apis/test/Plans/$testplanid/suites/$testsuiteid" +"?" + "`$expand" + "=1&api-version=5.0"
$tester = Invoke-RestMethod -Uri $testerUrl -Method Get -ContentType "application/json" -Headers $header
Url is like this:
"https://example.com/xxx/_apis/test/Plans/12572/suites/12583?$expand=1&api-version=5.0"
In the data I get back from devops there is no item
"defaultTesters ShallowReference[] Test suite default testers"
as described here:
https://learn.microsoft.com/en-us/rest/api/azure/devops/test/test%20%20suites/get%20test%20suite%20by%20id?view=azure-devops-server-rest-5.0
I tried and got the same result with powershell script calling test suite by id,
BTW,I found there was not an option allowing me to set a default tester for a test suite. Do not know how you assign a default tester to a test suite?
But for specific test case, assigned tester can be retrieved by rest API.
I have submitted an issue to Microsoft document team to track this issue.

Is it possible to use a variable in the Agent.Name demand for tfs?

I am trying to force the run of a specific agent phase on a specific agent. My variable however does not seems to be picked up. I get the error:
No agent found in pool TEST which satisfies the specified demands:
Agent.Name -equals $(Release.ReleaseName)
vstest
Agent.Version -gtVersion 2.103.0
Is this possible?
I wanted to do something similar. I had 2 "environments" in the TFS release definition. The first one ("MyEnvironment-Setup") did setup like big file copies and database script generation. The second ("MyEnvironment") did the actual deployment. I needed them both to run on the same agent.
What I ended up doing is using the TFS API during "MyEnvironment-Setup" to modify the currently running release instance and set the agent demand for "MyEnvironment".
Several things were necessary to make this happen.
In "MyEnvironment-Setup" > Run on Agent > Additional Options, I enabled "Allow scripts to access the OAuth token"
In the left pane of the release definition screen where it lists all release definitions, I clicked the ellipsis next to "All release definitions" and selected "Security". Then for the "Project Collection Build Service (TEAM FOUNDATION)" user, I set "Edit release definition" and "Manage releases" to "Allow".
I called the following Powershell method in "MyEnvironment-Setup"
function Set-FinalAgent()
{
# Force the "MyEnvironment" step to run on the same agent as the "MyEnvironment-Setup" step
$baseApiUrl = "$($env:SYSTEM_TEAMFOUNDATIONCOLLECTIONURI)$env:SYSTEM_TEAMPROJECTID/_apis"
$apiVersion = "3.1-preview"
$header = #{ Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN" }
$environmentToModify = $($env:Release_EnvironmentName).Replace("-Setup", "")
$releaseID = $env:Release_ReleaseID
$release = Invoke-RestMethod -Uri "$baseApiUrl/release/releases/$($releaseID)?api-version=$apiVersion" -Method GET -Header $header
($release.environments | where name -eq $environmentToModify).deployPhasesSnapshot[0].deploymentInput.demands += "Agent.Name -equals $($env:Agent_Name)"
# Compression is needed for the body to contain all of the info for larger release definitions when running on older servers
$body = $release | ConvertTo-Json -Depth 100 -Compress
Invoke-RestMethod -Uri "$baseApiUrl/release/releases/$($releaseID)?api-version=$apiVersion" -Method PUT -Header $header -ContentType application/json -Body $body
}
If you want to test and tweak this in Powershell ISE or something where you don't have access to the OAuth token, you can use a personal access token instead. In the top-right of your TFS Web UI, click your profile picture and select "Security" to generate a PAT. Then you can replace the header in the script above with the following:
$header = #{Authorization = 'Basic ' + [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":$($personalAccessToken)"))}

TFS 2015 Queue new build using REST Api - Set Demands

Im trying to queue a new build using the TFS 2015.3 REST API, i have followed many articles but cannot get it to work.
I am executing this in PowerShell, a standard queue new build call works when passing only the Definition ID, but passing anything else in addition to the id doesn't seem to work.
my code:
$buildDef = Invoke-RestMethod -Method Get -UseDefaultCredentials -Uri "$($tfsRoot)/_apis/build/definitions?api-version=2.0&name=$buildDefintionName"
$detailedResults = Invoke-RestMethod -Uri $buildDef.Value[0].Url -Method Get -ContentType "application/json" -UseDefaultCredentials
if ($buildDef.Value[0].Id)
{
$agentDemandString = "Agent.Name -equals $agent"
$demands = $detailedResults.Demands
$json = "definition: { id:$($buildDef.Value[0].Id) }, demands: $demands"
$bodyjson = $json | ConvertTo-Json
Write-Host "Queuing build $buildDefintionName on agent $agent with parameters $json"
$build = Invoke-RestMethod -Method Post -UseDefaultCredentials -ContentType application/json -Uri "$($tfsRoot)/_apis/build/builds?api-version=2.0" -Body $bodyjson
}
I have tried many different variations of passing the demands, but it looks like it is not even getting to that point as its complaining about the "build" parameter.
Invoke-RestMethod : {"$id":"1","innerException":null,"message":"Value cannot be null.\r\nParameter name: build","typeName":"System.ArgumentNullException, mscorlib, Version=4.0.0.0, Culture=neutral
If im right the build parameter contains the build steps to execute. Which makes me think that the queued build is dropping all existing configuration and tries to rely only on what has been passed in the JsonBody, this is ofcourse not what i want.
What and how should i pass in order to queue a new build but with updated/additional demands.
I finaly got it working with some help. The Demands property is accepted.
Looks like it was not working because of the powerShell code with Json conversion. If i use below and dont convert it to Json, it works !
Function queuebuild{
$uri="$($tfsRoot)/_apis/build/builds?api-version=2.0"
$body='{
"definition": {
"id": 1061
},
"sourceBranch": "$/Project/Branch",
"demands":["Demand1", "Agent.Name -equals Computer2-E-A2"]
}';
$result=Invoke-RestMethod -Uri $uri -Method Post -ContentType "application/json" -UseDefaultCredentials -Body $body
}
Try to set the depth:
$bodyjson = $json | ConvertTo-Json -Depth 3
$json = "definition: { id:$($buildDef.Value[0].Id) }, demands: $demands" is not going to be valid JSON -- it wouldn't be wrapped in curly braces, for example.
I recommend creating an associative array that will properly convert to valid JSON. The example JSON provided in the documentation is:
{
"definition": {
"id": 25
},
"sourceBranch": "refs/heads/master",
"parameters": "{\"system.debug\":\"true\",\"BuildConfiguration\":\"debug\",\"BuildPlatform\":\"x64\"}"
}
So this would generate an appropriate JSON object:
$body = #{
definition = #{ id=25 }
sourceBranch = 'refs/heads/master'
parameters = '{\"system.debug\":\"true\",\"BuildConfiguration\":\"debug\",\"BuildPlatform\":\"x64\"}'
}
$body | convertto-json
Or if you wanted to be extra fancy and eliminate the inner JSON-as-a-string bit:
$body = #{
definition = #{ id=25 }
sourceBranch = 'refs/heads/master'
parameters = (#{'system.debug' = $true; BuildConfiguration='debug'; BuildPlatform='x64'}) | convertto-json -Compress
}
$body | convertto-json
Based on my test, we cannot Set Demands directly with the Queue build REST Api.
The build will still use the agent which was set in definition even though we specified other agents with the "Demands" set when queue the build. You can check this with the REST API, below screenshot for your reference.
And with the REST API to get a build eg:
GET http://SERVER:8080/tfs/CollectionLC/6debd6ea-fa97-4ea2-b0c0-3cbbc4afa802/_apis/build/Builds/1071/
You can see that, the "Demands" is not included in the response. It only appears in build definition response.
Actually, the "Demands" is set in build definition,it's against the build definition only. When queue a build with REST API, it just trigger the build definition. So, if you want to trigger build with the specific agent using REST API, you need to update the definition (set demands )first, then trigger the build definition.
To update the definition use the REST API : See Update a build definition
PUT https://{instance}/DefaultCollection/{project}/_apis/build/definitions/{definitionId}?api-version={version}
So, you can write the script to update build definition fist, then trigger the build with build definition ID.

How to tell if TFS vNext build failed via variable?

I am trying to perform different actions (such as copying to a different directory on publish) if a build failed or not. I am unable to find any documentation about any variables that let me know if it failed or not. Can anyone let me know how to tell if the build failed or not?
You can create a PowerShell script to call Rest API to get the build information (You need to enable the alternative credential):
[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)}
$url= $projecturi + $project + "/_apis/build/builds/" + $buildID + "/timeline?api-version=2.0"
Write-Host $url
$responseBuild = Invoke-RestMethod -Uri $url -headers $headers -Method Get | select records
And then you can check the result in the information to see if there is any failed steps and then perform the actions you want:
foreach ($record in $responseBuild.records)
{
$result = $record.result
##xxxxxxxxxxxxxxxxxxxx
}

How to post build result to team room in TFS 2015?

Is there a way to post build results from the build system (vNext?) in the Team Rooms?
I noticed there is an option to post build results in the team rooms, but the available list to choose from are only XAML build definitions and not the new build system (vNext?) definitions.
No there is not.
I have logged the issue here : https://connect.microsoft.com/VisualStudio/Feedback/Details/1874524
I have try it on my environment(TFS2015&VS2015) .
Sorry about that, this function seems only support XAML build by now.
You can raise your requirements to Microsoft.
The following Powershell code is a first attempt at getting something working for us:
Param($teamroom,$message)
# Example: Write-MessageToTeamRoom.ps1 -teamroom "Team Room Name" -message "Notify #User name about work item #54142"
# https://jaspergilhuis.nl/2014/02/18/utilize-the-tfs-team-room-rest-api/
# https://jaspergilhuis.nl/2014/02/23/encapsulate-team-room-api-calls-with-a-powershell-commandlet/
$rooms = Invoke-RestMethod -Method GET http://tfsapp02:8080/tfs/defaultcollection/_apis/chat/rooms?api-version=1.0 -UseDefaultCredentials
$room = $rooms.value | Where-Object {$_.Name -eq $teamroom}
$relevantRoomID = $room.id
$jsonbody = #{ content="$message"} | ConvertTo-Json
$response = Invoke-RestMethod -Method POST "http://{TfsDefaultCollectionPath}/_apis/chat/rooms/$relevantRoomID/messages?api-version=1.0" -Body $jsonbody -ContentType "application/json" -UseDefaultCredentials
My ambition is to expand this code to run whenever a build completes and then write the build result into the team room

Resources