How to get Package ID given a package name via AzureDevOps REST API - azure-devops-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

Related

How can I efficiently list all work item type states via ADO 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.

How to get only the latest version of a package via AzureDevOps REST API

Below API returns all the versions of a specific package. In order to get the latest version of that package, I can use the isLatest:true data from the returned response.
https://learn.microsoft.com/en-us/rest/api/azure/devops/artifacts/artifact%20%20details/get%20package%20versions?view=azure-devops-rest-6.0
But I was wondering if there is way to only get the latest version in the response rather than all the version? Is it possible?
If there is no possibility of that, then a second question - Will latest version be always the first item in the response? (I assume there is a limit to the return item count (1000?) so I was wondering if one API call would always be sufficient if I need to get the latest version.
If there is no possibility of that, then a second question - Will latest version be always the first item in the response?
The answer is yes. The latest version be always the first item in the response.
As test, I published a test package to my feed with versions 1.0.0, 2.0.0, then published the version 1.0.1-preview1.2, 1.0.1. But Azure devops will be sorted in order of package version:
So, we could use REST API with powershell parameter Select-Object -first 1 to get the latest package version:
$connectionToken="Your PAT"
$base64AuthInfo= [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($connectionToken)"))
$url = 'GET https://feeds.dev.azure.com/{organization}/{project}/_apis/packaging/Feeds/{feedId}/Packages/{packageId}/versions?api-version=6.0-preview.1
'
$PackageInfo = (Invoke-RestMethod -Uri $url -Method Get -UseDefaultCredential -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)})
$LatestVersion= $PackageInfo.value.version | Select-Object -first 1
Write-Host "Latest package Version = $LatestVersion"
The test result:
For the first question, I am afraid that there is no out-of-the-box parameter to return the latest version of a package directly through the rest api, because the isLatest parameter is not provided in rest api url to return the latest version. In addition, the $top parameter is not provided in the url parameteres to specify the returned count.
Will latest version be always the first item in the response?
For the second question, the answer is Yes, the latest version will be always the first item in the response.
So as workaround, we can simply filter response through powershell script to return the latest package version.
$url = 'https://feeds.dev.azure.com/{org}/_apis/packaging/Feeds/{feedId}/Packages/{packageId}/versions?api-version=6.0-preview.1';
$token = "{PAT}"
$token = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($token)"))
$response = Invoke-RestMethod -Uri $url -Headers #{Authorization = "Basic $token"} -Method Get
$result = $response.value | Where {$_.isLatest -eq "true"} #|
Write-Host "results = $($result | ConvertTo-Json -Depth 100)"

How to specify git author/committer for PullRequest merge in Azure DevOps?

I have defined a release pipeline to synchronize code between two git repositories in Azure DevOps. The process requires a PullRequest in the destination repo which is created and completed using the WebAPI.
The pipeline is executed by the build agent running using a Windows domain service account. So, the PullRequest is created and completed on behalf of the service account, which is also mentioned as author, committer, etc. in the git history after merge is completed. (According to our rules the PR must be merged using squash commit.)
I would like see a different user in the git history after (squash) merge.
Can I specify the user (e.g. the user triggering the release pipeline) using WebAPI?
I did not find such option in the API documentation.
Any other recommendation? Maybe convention like adding "co-authored-by" to commit message like github?
When you use Pull Requests-Create rest api to create a pull request, the pull request creator is determined by the creator of the PAT you used for authentication (e.g. I used the PAT of hughl01 user as the authentication to create the pull request, then the creator of the pull request is hughl01).
Test in Postman:
Sample test script in powershell task:
$token = "{User-created PAT}"
$url = "https://dev.azure.com/{org}/{pro}/_apis/git/repositories/{repoId}/pullrequests?api-version=6.0"
$token = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($token)"))
$JSON = #'
{
"sourceRefName": "refs/heads/dev2",
"targetRefName": "refs/heads/master",
"title": "ForTest",
"description": "Adding a new feature"
}
'#
$response = Invoke-RestMethod -Uri $url -Headers #{Authorization = "Basic $token"} -Method Post -ContentType application/json -body $JSON
You can create a variable group, with the release trigger as the variable name, and the PAT corresponding to the user as the variable value and set the value of the variable to secret. Then get the name of the triggerer through the predefined variable $(Release.RequestedFor) in the script, then obtain the corresponding PAT according to the trigger name to create pull request.

How to Login to VSTS programmatically

I have an automatic branching utility that does various operations.
We have upgraded to VSTS and I am having trouble using the Tfs calls with the new server:
//login
NetworkCredential netCred = new NetworkCredential("emailAddress", password");
BasicAuthCredential basicCred = new BasicAuthCredential(netCred);
TfsClientCredentials tfsCred = new TfsClientCredentials(basicCred);
tfsCred.AllowInteractive = false;
TfsTeamProjectCollection tfsServer = new TfsTeamProjectCollection(new Uri("https://myco.visualstudio.com/mycoll"), tfsCred);
// get a local workspace
VersionControlServer sc = server.GetService(typeof(VersionControlServer)) as VersionControlServer;
... other code
and then boom!
"You are not authorized to access https://myco.visualstudio.com/mycoll"
Is there some setting somewhere?
Should I try and use the REST API?
Am I calling something I shouldn't?
I've tried all sorts of formats for the URI, with :8080, with /tfs in the path to no avail!
You can use PAT (Personal Access Token) to access VSTS. Click on your profile in VSTS and go to security menu item. You can define a PAT in there. Keep the PAT saved as it will only be shown once.
Define the scope as per your needs
You can use the PAT to access TFS REST API as shown in following PowerShell sample. Using https://yourAccount.visualstudio.com or https://yourAccount.visualstudio.com/DefaultCollection for ColletionUri parameter is OK.
param(
[Parameter(Mandatory=$true)]
[string] $token,
[Parameter(Mandatory=$true)]
[string] $collectionUri
)
$User=""
# Base64-encodes the Personal Access Token (PAT) appropriately
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $User,$token)));
$header = #{Authorization=("Basic {0}" -f $base64AuthInfo)};
$Uri = $collectionUri + '/_apis/projects?api-version=1.0'
$projects = Invoke-RestMethod -Method Get -ContentType application/json -Uri $Uri -Headers $header
You can find C# code samples here https://www.domstamand.com/accessing-tfs-2017-programmatically/

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.

Resources