How can I efficiently list all work item type states via ADO REST API? - azure-devops-rest-api

I am trying to list all work item type states for an organisation (visible to the authenticated user) via REST API. It seemed more efficient to list all processes (https://learn.microsoft.com/en-us/rest/api/azure/devops/core/processes/list?view=azure-devops-rest-4.1) and then use the endpoint to list all work item types of those processes together with the states (https://learn.microsoft.com/en-us/rest/api/azure/devops/processes/work-item-types/list?view=azure-devops-rest-4.1&tabs=HTTP). However, I am missing some custom states in the response.
When I list all projects (https://learn.microsoft.com/en-us/rest/api/azure/devops/core/projects/list?view=azure-devops-rest-4.1&tabs=HTTP), then all work item types of those projects (https://learn.microsoft.com/en-us/rest/api/azure/devops/wit/work-item-types/list?view=azure-devops-rest-4.1&tabs=HTTP) and then all states of those types (https://learn.microsoft.com/en-us/rest/api/azure/devops/wit/work-item-type-states/list?view=azure-devops-rest-4.1&tabs=HTTP), there is everything. But that is sooo many requests.
Can someone explain, why is the first approach not working? Every projet should be associated with a process. Or not? Do you know a better way to get all those states as efficiently as possible?
Thanks in advance. :)

As we can see from the official documentation : Work Item Type States - List, it's in project level not the organization level. So, we need to get the states by project scope.
GET https://dev.azure.com/{organization}/{project}/_apis/wit/workitemtypes/{type}/states?api-version=4.1-preview.1
We can write a script to retrieve the projects and work item types in a loop, then get the states of each work item type.
UPDATE:
We can use States - List REST API to return a list of all state definitions in a work item type of the process.
Below PowerShell script for your reference to return the states from a specific process:
Param(
[string]$orgurl = "https://dev.azure.com/{org}",
[string]$processname = "Your-Process-Name",
[string]$user = "",
[string]$token = "PAT"
)
# Base64-encodes the Personal Access Token (PAT) appropriately
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user,$token)))
#Get Process ID
$processesurl = "$orgurl/_apis/process/processes?api-version=6.0"
$processes = (Invoke-RestMethod -Uri $processesurl -Method Get -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)}).value | where {$_.name -eq $processname }
$processesid = $processes.id
#List Work item types and witRefName
$witsurl = "$orgurl/_apis/work/processes/$processesid/workitemtypes?api-version=6.0"
$witRefNames = (Invoke-RestMethod -Uri $witsurl -Method Get -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)}).value.referenceName #| where {$_.name -eq $processname }
#List WIT states
foreach ($witRefName in $witRefNames){
$statesurl = "$orgurl/_apis/work/processes/$processesid/workItemTypes/$witRefName/states?api-version=6.0"
$states = (Invoke-RestMethod -Uri $statesurl -Method Get -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)}).value.name
Write-Host "==================================================================================="
Write-Host "$witRefName - States:" $states
Write-Host "==================================================================================="
echo `n
}
If you want to retrieve all states from all processes, then you can get the processes and loop them in the script.

Related

How to get Package ID given a package name via AzureDevOps REST API

If I have just the package name, is it possible to get the package ID using a single API call. Looks like Package ID is required for any further API calls - to get versions of a package etc.,
Or is the only way to get all the packages from the feed, match with the name and then get the ID from that?
Reference API: https://learn.microsoft.com/en-us/rest/api/azure/devops/artifacts/artifact%20%20details/get%20package?view=azure-devops-rest-6.0
You can specify a packageNameQuery query parameter in the Get Packages rest api to retrieve the package's information with a given name.
GET https://feeds.dev.azure.com/{organization}/{project}/_apis/packaging/Feeds/{feedId}/packages?protocolType={protocolType}&packageNameQuery={packageNameQuery}&normalizedPackageName={normalizedPackageName}&includeUrls={includeUrls}&includeAllVersions={includeAllVersions}&isListed={isListed}&getTopPackageVersions={getTopPackageVersions}&isRelease={isRelease}&includeDescription={includeDescription}&$top={$top}&$skip={$skip}&includeDeleted={includeDeleted}&isCached={isCached}&directUpstreamId={directUpstreamId}&api-version=6.0-preview.1
For Organization scoped feeds:
$url= "https://feeds.dev.azure.com/{organization}/_apis/packaging/Feeds/{feedid or feedName}/packages?packageNameQuery={package Name}&api-version=6.0-preview.1"
For Project scoped feeds:
$url= "https://feeds.dev.azure.com/{organization}/{project}/_apis/packaging/Feeds/{feedid or feedName}/packages?packageNameQuery={package Name}&api-version=6.0-preview.1"
See below example:
#Organization scoped feed
$url= "https://feeds.dev.azure.com/{organization}/_apis/packaging/Feeds/{feedid or feedName}/packages?packageNameQuery={package Name}&api-version=6.0-preview.1"
$PAT="Personal Access Token"
$base64AuthInfo= [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($PAT)"))
$ArtInfo = Invoke-RestMethod -Uri $url -Headers #{Authorization = ("Basic {0}" -f $base64AuthInfo)} -Method get

Is there a way to find all item (Product Backlog Item, Bugs, Task) without any Tags included? (With Query)

I'm am querying across my project and want to find all item that don't have any Tags. is there a way to do it?
Is not possible to query all the work items without tags.
There is a feature request about it here.
As workaround, you can add to all non-tagged work items a specific tag to mark them and then query this tag.
You can use Rest API to get the work items, then filter the results to get the non-tagged work items.
Small script in PowerShell:
$user = ""
$token = "YOUR-PAT-HERE"
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user, $token)))
$url = "https://dev.azure.com/{organization}/{project}/{team}/_apis/wit/wiql/{queryGuid}?api-version=5.0"
$workItems = Invoke-RestMethod -Uri $url -Method Get -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)}
Write-Host "Work Items without Tags:"
$workItems.workItems.ForEach({
$url = "https://dev.azure.com/{organization}/{project}/_apis/wit/workitems/$($_.id)?api-version=5.0"
$workItemDetails = Invoke-RestMethod -Uri $url -Method Get -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)}
if($workItemDetails.fields.'System.Tags' -eq $null
{ Write-Host $_.id }
})

TFS 2017 Change Release summary description during build

We're using Team Foundation Server 2017. After lots of releasedefinition-making, I'm stucking on a problem.
During the release, I receive a message which I would write directly into the release description summary. I checked for an such an activity in the Marketstore, but I haven't found one.
Am I not able to search for the right activity or is there another way for updating this?
Currently, you can only update release name with Logging command, which requires agent version 2.132+. So the only way to update the release description is adding a powershell script in your release definition. The script is as below:
param (
[Parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string] $token
)
## Construct a basic auth head using PAT
function BasicAuthHeader()
{
param([string]$authtoken)
$ba = (":{0}" -f $authtoken)
$ba = [System.Text.Encoding]::UTF8.GetBytes($ba)
$ba = [System.Convert]::ToBase64String($ba)
$h = #{Authorization=("Basic{0}" -f $ba);ContentType="application/json"}
return $h
}
$getReleaseUri = "http://TFS2017:8080/tfs/DefaultCollection/TeamProject/_apis/release/releases/$($env:RELEASE_RELEASEID)?api-version=3.2-preview"
$h = BasicAuthHeader $token
$release = Invoke-RestMethod -Uri $getReleaseUri -Headers $h -Method Get
# Update an existing variable named d1 to its new value d5
$release.description = "this is a test";
####****************** update the modified object **************************
$release2 = $release | ConvertTo-Json -Depth 100
$release2 = [Text.Encoding]::UTF8.GetBytes($release2)
$updateReleaseUri = "http://TFS2017:8080/tfs/DefaultCollection/TeamProject/_apis/release/releases/$($env:Release_ReleaseId)?api-version=3.2-preview"
$content2 = Invoke-RestMethod -Uri $updateReleaseUri -Method Put -Headers $h -ContentType “application/json” -Body $release2 -Verbose -Debug
write-host "=========================================================="
And with argument -token {PAT}. Check my screenshot below:
I've tested on my side, it can update release description successfully.

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 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