create multiple projects error Azure DevOps rest api - powershell

I am using a rest API powershell to create multiple projects in azure devops. Writing my script in below way but it fails.
Any guidance on how I can construct my script to pick up multiple names?
'
$connectionToken="token"
$base64AuthInfo= [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($connectionToken)"))
$ProjectUrl = "url
$Body = #{
name = #{'TestProjectCreation1','test1','test2'
}
description = 'Frabrikam travel app for Windows Phone'
capabilities = #{
versioncontrol = #{
sourceControlType = 'Git'
}
processTemplate = #{
templateTypeId = 'template id'
}
}
} | ConvertTo-Json
$projectscreated = Invoke-RestMethod -Uri $ProjectUrl -Method Post -ContentType "application/json" -Headers #{
Authorization=("Basic {0}" -f $base64AuthInfo)} -Body $Body
'

According to your description, you could create a new array for projects and foreach the project to create: scrpit like:
$url='https://dev.azure.com/{org}/_apis/projects?api-version=6.0'
$connectionToken="{PAT}"
$base64AuthInfo = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($connectionToken)"))
$projects= #('TestProjectCreation1','test1','test2')
Foreach($prject in $projects){
$body="
{
`"name`": `"$prject`",
`"capabilities`": {
`"versioncontrol`": {
`"sourceControlType`": `"Git`"
},
`"processTemplate`": {
`"templateTypeId`": `"6b724908-ef14-45cf-84f8-768b5384da45`"
}
}
}
"
$response= Invoke-RestMethod -Uri $url -ContentType "application/json" -Body $body -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)} -Method POST
}

Related

Is it possible to execute Azure Test Plans using Rest api Powershell Script

I am new to Rest api and Powershell Scripting. I wanted to know if we can execute the Azure Test plans using Powershell script.
My plan is to write a powershell script to execute set of existing Test plans in my project. Then use that powershell script in Pipeline and schedule the pipeline to run at specific time.
Please help me.
I know that we can get list of Test Plans using Rets api , is it possible to execute them as well?
Test Plan does not support being run, only test point can be executed.
If you want to use Rest API to execute automatic test in test plan, you could refer to the following steps:
Here are the following steps:
Step1: You could define a variable in Release Pipeline.
Step2: Add this variable in VSTest Task:
Note: The test run id needs to correspond to the release one-to-one, and then the status of the test run will be updated.
Here is an example:
param (
[string]$token="",
[string]$collection="",
[string]$projectName ="",
[int] $planIdStatic =947 ,
[int] $suiteIdStatic =1086 ,
[int] $testcaseID =79,
[int] $releasedefinitionid =96,
[int] $buildid =62903
)
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user, $token)))
$response = Invoke-RestMethod "https://dev.azure.com/$collection/$projectName/_apis/test/plans?api-version=5.0" -Method 'GET' -Headers #{Authorization = ("Basic {0}" -f $base64AuthInfo)}
foreach( $val in $response.value)
{
#PLAN ID
Write-Host $val.id
# $planId = [convert]::ToInt32($val.id)
[int] $planId = $planIdStatic
$suites = "https://dev.azure.com/$collection/$projectName/_apis/test/plans/$planId/suites?api-version=5.0"
$listofSuites = Invoke-RestMethod $suites -Method 'GET' -Headers #{Authorization = ("Basic {0}" -f $base64AuthInfo)}
#define Suite ID
[int] $suiteId = $suiteIdStatic
$suitename = "https://dev.azure.com/$collection/$projectName/_apis/test/plans/$planId/suites/$suiteId/points?api-version=5.0"
$listofSuites = Invoke-RestMethod $suitename -Method 'GET' -Headers #{Authorization = ("Basic {0}" -f $base64AuthInfo)}
#Define TestCaseID
[int] $tcID = $testcaseID
$tc = "https://dev.azure.com/$collection/$projectName/_apis/test/plans/$planId/suites/$suiteId/points?testCaseId=$tcID&api-version=5.0"
$testcaseapi = Invoke-RestMethod $tc -Method 'GET' -Headers #{Authorization = ("Basic {0}" -f $base64AuthInfo)}
#Define PointID
[int] $pointID = $testcaseapi.value[0].id
$runName = "Test RUN Setup"
#PayLoad
$payload = #"
{
"name":"test",
"automated":true,
"pointIds":[$pointID],
"state":"NotStarted",
"dtlTestEnvironment":{"id":"vstfs://dummy"},
"plan":{"id":"$planId"},
"filter":{"sourceFilter":"*.dll","testCaseFilter":""}
}
"#;
#Initiate the RUN
$tcRun = "https://dev.azure.com/$collection/$projectName/_apis/test/runs?api-version=5.0"
$testRun = Invoke-RestMethod $tcRun -Method 'POST' -ContentType "application/json" -Body $payload -Headers #{Authorization = ("Basic {0}" -f $base64AuthInfo)}
Write-Host "Test Run Status is ...."
$testrunid = $testRun.id
echo $testrunid
$url = "https://vsrm.dev.azure.com/$collection/$projectName/_apis/Release/definitions/$($releasedefinitionid)?api-version=5.0-preview.3"
Write-Host "URL: $url"
$pipeline = Invoke-RestMethod -Uri $url -Method Get -Headers #{Authorization = ("Basic {0}" -f $base64AuthInfo)}
Write-Host "Pipeline = $($pipeline | ConvertTo-Json -Depth 100)"
$pipeline.variables.testrunid.value = "$testrunid"
####****************** update the modified object **************************
$json = #($pipeline) | ConvertTo-Json -Depth 99
$updatedef = Invoke-RestMethod -Uri $url -Method Put -Body $json -ContentType "application/json" -Headers #{Authorization = ("Basic {0}" -f $base64AuthInfo)}
$releaseRunurl ="https://vsrm.dev.azure.com/$collection/$projectName/_apis/Release/releases?api-version=6.1-preview.8"
$releasebody = #"
{
"definitionId": $releasedefinitionid
}
"#;
$ReleaseRun = Invoke-RestMethod $releaseRunurl -Method 'POST' -ContentType "application/json" -Body $releasebody -Headers #{Authorization = ("Basic {0}" -f $base64AuthInfo)}
$Releaseid=$ReleaseRun.id
echo $Releaseid
$ReleaseEnvID=$ReleaseRun.environments.id
echo $ReleaseEnvID
$updateTestrun="https://dev.azure.com/$collection/$projectName/_apis/test/Runs/$($testrunid)?api-version=6.1-preview.3"
$updatebody = #"
{
"build":
{
"id":"$buildid"
},
"releaseEnvironmentUri":"vstfs:///ReleaseManagement/Environment/$ReleaseEnvID","releaseUri":"vstfs:///ReleaseManagement/Release/$Releaseid"
}
"#;
$UpdateRun = Invoke-RestMethod $updateTestrun -Method 'PATCH' -ContentType "application/json" -Body $updatebody -Headers #{Authorization = ("Basic {0}" -f $base64AuthInfo)}
}
Result:
When the release is completed, the status of the test run will be updated

Get all users under all projects from Azure DevOps

I am trying to get all users under couple of project. The case is that under users there are many and I need to to use continuationToken. The result is messy because my logic is bad. I cannot figure out how to use the second foreach..
$outputItems = #()
foreach ($project in $projects) {
$uriProjectDescriptor = "https://vssps.dev.azure.com/$OrganizationName/_apis/graph/descriptors/$($project.id)?api-version=5.0-preview.1"
$projectDescriptor = Invoke-RestMethod -Uri $uriProjectDescriptor -Method Get -Headers $AzureDevOpsAuthenicationHeader
$descriptors = $projectDescriptor.value
foreach ($descriptor in $descriptors) {
do
{
$uriUsers="https://vssps.dev.azure.com/$OrganizationName/_apis/graph/users?continuationToken=$continuationToken&scopeDescriptor=$($descriptor)&api-version=6.0-preview.1"
$responseUsers=Invoke-WebRequest -Uri $uriUser -Method Get -ContentType "application/json" -Headers $AzureDevOpsAuthenicationHeader -UseBasicParsing -MaximumRedirection 0
$continuationToken = $responseUsers.Headers.'x-ms-continuationtoken'
$userSet = $responseUsers.content | ConvertFrom-Json
$users += $userSet.value.Count
$arealList = New-Object -TypeName PSObject -Property #{
CountUsers = $users.Count
} | Select-Object "CountUsers"
$outputItems += $arealList
$arealList = $null
}
while (($continuationToken))
$ProgressPreference = 'Continue'
}
} $outputItems
You could try the following Powershell Script:
$token = "PAT"
$url="https://dev.azure.com/{Organizationname}/_apis/projects?api-version=6.0"
$token = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($token)"))
$responses = Invoke-RestMethod -Uri $url -Headers #{Authorization = "Basic $token"} -Method Get -ContentType application/json
ForEach ($response in $responses.value.id)
{
$url1="https://vssps.dev.azure.com/{Organizationname}/_apis/graph/descriptors/$($response)?api-version=6.0-preview.1"
$Descriptor = Invoke-RestMethod -Uri $url1 -Headers #{Authorization = "Basic $token"} -Method Get -ContentType application/json
ForEach ($Descriptor1 in $Descriptor.value)
{
do
{
$url2="https://vssps.dev.azure.com/{Organizationname}/_apis/graph/users?scopeDescriptor=$($Descriptor1)&api-version=6.0-preview.1"
$UserLists = Invoke-RestMethod -Uri $url2 -Headers #{Authorization = "Basic $token"} -Method Get -ContentType application/json
$continuationToken = $UserLists.Headers.'x-ms-continuationtoken'
}
while ($continuationToken -ne $null)
Write-Host "result = $($UserLists | ConvertTo-Json -Depth 100)"
}
}
Explaination:
The first Rest API is used to get the Project name.
Then the second Rest API is used to get the descriptors.
The third Rest api is used to get the userlist.
I use foreach nesting to realize the loop of response to Rest API.
Update:
Test with the continuationToken and the maximum value of objects returned by a project is 500.
I found another Rest Api User Entitlements - List to get the users.
https://vsaex.dev.azure.com/Organization Name/_apis/userentitlements?top=10000&select=project&api-version=4.1-preview.1
This Rest APi could directly return the users under the organization(Project Scope). The max value is 10000.

Run an Azure Pipeline through API

I have done something to queue/build my pipelines in Azure through API. Now I am in need to run my pipelines through API. Hereby I attached my code for building/queuing pipeline.
$body = '
{
"definition": {
"id": 1
}
}
'
write-host "`n"
$bodyJson=$body
write-host $bodyJson -ForegroundColor Cyan
Write-Output $bodyJson | ConvertFrom-JSON
write-output $bodyJson
$bodyString=$bodyJson | ConvertTo-Json
write-host $bodyString -foregroundcolor green
$user="name"
$personalToken = "token"
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":$($personaltoken)"))
$Uri = "https://dev.azure.com/demoworldDemoworld/talentstogether/_apis/build/builds?api-version=5.1"
$buildresponse = Invoke-RestMethod -Method Post -UseDefaultCredentials -ContentType application/json -Uri $Uri -Body $bodyJson -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)}
write-host $buildresponse
Kindly help me to run my pipelines through API in a similar way.
Please try the following script:
Param(
[string]$orgurl = "https://dev.azure.com/{organization}",
[string]$projectName = "0508-t",
[string]$BuildDefinitionId = "166",
[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)))
function CreateJsonBody
{
$value = #"
{
"definition": {
"id": $BuildDefinitionId
}
}
"#
return $value
}
$json = CreateJsonBody
$uri = "$($orgurl)/$($projectName)/_apis/build/builds?api-version=5.1"
$buildresponse = Invoke-RestMethod -Uri $uri -Method Post -Body $json -ContentType "application/json" -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)}
Write-Host $buildresponse

What does the Body of the Invoke-RestMethod for queuing a build need to contain? [duplicate]

I have the following script
Param(
[string]$vstsAccount = "abc,
[string]$projectName = "abc",
[string]$user = "",
[string]$token = "xyz"
)
# Base64-encodes the Personal Access Token (PAT) appropriately
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user,$token)))
$verb = "POST"
$body = #"
{
"definition": {
"id": 20
}
}
"#
$uri = "https://$($vstsAccount).visualstudio.com/DefaultCollection/$($projectName)/_apis/build/builds?api-version=4.1"
$result = Invoke-RestMethod -Uri $uri -Method $verb -ContentType "application/json" -Body (ConvertTo-Json $body) -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)}
However I get this error
Invoke-RestMethod : {"$id":"1","innerException":null,"message":"This request expects an object in the request body, but the supplied data could not be
deserialized.","typeName":"Microsoft.TeamFoundation.Build.WebApi.RequestContentException,
So I tried to queue a build from the browser and see the payload using developer tools:
{"queue":{"id":70},"definition":{"id":20},"project":{"id":"b0e8476e-660a-4254-a100-92ef0ec255e5"},"sourceBranch":"refs/heads/master","sourceVersion":"","reason":1,"demands":[],"parameters":"{\"system.debug\":\"false\"}"}
So, I replaced that into my script:
$body = #"
{"queue":{"id":70},"definition":{"id":20},"project":{"id":"b0e8476e-660a-4254-a100-92ef0ec255e5"},"sourceBranch":"refs/heads/master","sourceVersion":"","reason":1,"demands":[],"parameters":"{\"system.debug\":\"false\"}"}
"#
However I keep getting the same error.
The official documentation for this endpoint is here, but its not clear
https://learn.microsoft.com/en-us/rest/api/vsts/build/builds/queue?view=vsts-rest-4.1#request-body
To queue a build with REST API, you can use below powershell script:
$body = '
{
"definition": {
"id": number
}
}
'
$bodyJson=$body | ConvertFrom-Json
Write-Output $bodyJson
$bodyString=$bodyJson | ConvertTo-Json -Depth 100
Write-Output $bodyString
$user="name"
$token="PAT"
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user,$token)))
$Uri = "https://account.visualstudio.com/project/_apis/build/builds?api-version=4.1"
$buildresponse = Invoke-RestMethod -Method Post -UseDefaultCredentials -ContentType application/json -Uri $Uri -Body $bodyString -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)}
write-host $buildresponse
This variant of Marina's answer worked for me against an on-prem TFS 2017 server:
$b= '{"buildNumber":<build id>,"definition":{"id":<build id>}}'
$user="DOMAIN\username"
$token="<PAT token>"
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes("${user}:${token}"))
$Uri = "https://tfs.mycompany.local/<team-name>/<project-name>/_apis/build/builds?api-version=4.1"
$buildresponse = Invoke-RestMethod -Method Post -UseDefaultCredentials -ContentType application/json -Uri $Uri -Body $b -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)}
write-host $buildresponse
If you're running your PowerShell script on an Azure Devops Server, you can take advantage of several environment variables to automatically authenticate:
# From https://learn.microsoft.com/en-us/rest/api/azure/devops/build/builds/queue?view=azure-devops-server-rest-6.0
$url = "$($env:SYSTEM_TEAMFOUNDATIONCOLLECTIONURI)$env:SYSTEM_TEAMPROJECTID/_apis/build/builds?api-version=6.0&definitionId=<definition_id_here>"
Write-Host "URL: $url"
# From https://learn.microsoft.com/en-us/azure/devops/pipelines/scripts/powershell?view=azure-devops-2020&tabs=yaml#example-powershell-script-access-rest-api
$pipeline = Invoke-RestMethod -Method 'Post' -Uri $url -ContentType "application/json" -Headers #{
Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"
}
Write-Host "Pipeline = $($pipeline | ConvertTo-Json -Depth 100)"

Getting Unauthorised error while triggering TFS build from release definition

I need to trigger a build after successful deployment of a release. I have tried using below code in Powershell in the release definition.
After executing, I get this error - Access is denied due to invalid credentials
$url = "http://abc:8080/tfs/GlobalCollection/Project/_apis/build/builds?
api-version=2.0"
$body = "{ 'definition' : { 'id' : 1} }"
$type = "application/json"
$headers = #{
Authorization = "Basic d3JlblxzcsampleTIzNA=="
}
Write-Host "URL: $url"
$definition = Invoke-RestMethod -Uri $url -Body $body -ContentType $type -
Method Post -Headers $headers
Write-Host "Definition = $($definition | ConvertTo-Json -Depth 1000)"`
Based on my test, you can use -UseDefaultCredentials :
$type = "application/json"
$url = "http://abc:8080/tfs/GlobalCollection/Project/_apis/build/builds?api-version=2.0"
$body = "{ 'definition' : { 'id' : 56} }"
Write-Host "URL: $url"
$definition = Invoke-RestMethod -Uri $url -Body $body -ContentType $type -Method Post -UseDefaultCredentials
Write-Host "Definition = $($definition | ConvertTo-Json -Depth 1000)"
Alternatively provide the specific Credential:
$user = "username"
$password = "password"
# Base64-encodes the Personal Access Token (PAT) appropriately
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user,$password)))
$headers = #{Authorization=("Basic {0}" -f $base64AuthInfo)}
$type = "application/json"
$url = "http://abc:8080/tfs/GlobalCollection/Project/_apis/build/builds?api-version=2.0"
$body = "{ 'definition' : { 'id' : 56} }"
Write-Host "URL: $url"
$definition = Invoke-RestMethod -Uri $url -Body $body -ContentType $type -Method Post -Headers $headers
Write-Host "Definition = $($definition | ConvertTo-Json -Depth 1000)"