0
votes

We have just migrated our code from on-site TFS to Azure DevOps.

With TFS, I use a powershell script to build and deploy the application. The deployment part still works fine, but I don't know how to trigger the build. The command line I used with the old TFS is:

& "F:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\TFSBuild" start [repository URL] [project] "[build definition]" 

I know that DevOps has a REST API https://docs.microsoft.com/en-us/rest/api/azure/devops/build/builds/queue?view=azure-devops-rest-5.0 but there are many options and no examples there. I also saw this post: How to QUEUE a new build using VSTS REST API but the solution there does not wait for the build to finish and it uses API 4.1 - not sure if it's valid for DevOps? I already configured the build definitions in DevOps.

The URL to where the build is configured in DevOps is of this format: DevOps URL

All I need is to queue a build from a powershell script and wait for the build to complete, i.e. equivalent of my TFSBuild script above. Can someone help please?

2
@Matt: Yes I've seen this post and it is helpful, but it does not wait for the build to complete, it returns as soon as it's queued. I need to know when it has finished with success/error.PiotrS
There's no easy way to wait for build completion - you have to poll the devops server and query the build status. I've found this Gist which should get you started.Peter Schneider
So you want trigger build and wait to response?Amit Baranes

2 Answers

1
votes

You can use the following script which trigger new build and waiting till build completed.

$tfsUrl = "http://{tfsServer}:{Port}/{Organization}/{Collection}/{Project}"
$buildsURI = $tfsUrl + '/_apis/build/builds?api-version=2.0'
$BuildDefsUrl = $tfsUrl + '/_apis/build/definitions?api-version=2.0'
$buildLog =  "$tfsUrl/_apis/build/builds"

$allbuildDefs = (Invoke-RestMethod -Uri ($BuildDefsUrl) -Method GET -UseDefaultCredentials).value | Where-Object {$_.name -eq "BuildName"} | select id,name ## get all relevant builds

foreach ($build in $allbuildDefs)
{
   $body = '{ "definition": { "id": '+ $build.id + '}, reason: "Manual", priority: "Normal"}' # build body

   Write-Output "Queueing $($build.name)" # print build name

   $buildOutput = Invoke-RestMethod -Method Post -Uri $buildsURI -UseDefaultCredentials -ContentType 'application/json' -Body $body -Verbose # trigger new build 

   $allBuilds = (Invoke-RestMethod -Uri $buildsURI -Method get -UseDefaultCredentials).value # get all builds

   $buildID = ($allBuilds | where {$_.definition.name -eq $build.name })[0].id # get first build id 

   $buildInfo =  (Invoke-RestMethod -Uri "$buildLog/$buildID"  -UseDefaultCredentials -Method get)  # get build info by build ID
   while($buildInfo.status -eq "inProgress") # keep checking till build completed
   {
      Write-Output "Sleep for 5 seconds.."
      Start-Sleep -Seconds 5 # Start sleep for 5 seconds
      $buildInfo =  (Invoke-RestMethod -Uri "$buildLog/$buildID"  -UseDefaultCredentials -Method get) ## get status 
   }

   Write-Output "Build Status : $($buildInfo.result)" # print build result
}

Be aware that i'm working with TFS 2017 and not Azure DevOps Services REST API 5.0.So,there might be some small changes you need to implement .

1
votes

I ended up doing this and it works:

Function Queue-Build ($definitionName, $branchName)
{
    Write-Host "Building $definitionName - $branchName"
    $build = (vsts build queue --project [project_name] --instance [server_name] --definition-name $definitionName --branch $branchName) | Out-String | ConvertFrom-Json

    #wait for the build to complete
    while ($build.status -ne "completed") {
        Start-Sleep -s 5
        $build = (vsts build show --id $build.id --instance [server_name] --project [project_name]) | Out-String | ConvertFrom-Json
        #Write-Host $build.status
    }
}

vsts login --token PAT_created_in_DevOps

$sourceBranch = [branch_name]
Queue-Build [build_definition_name] $sourceBranch