I have an agent queue in VSTS with several agents and I have a build assigned to this queue. Is there any way of telling VSTS that only one instance of the build should be r
No, there isn’t such setting to control it, it is controlled by pipelines: Concurrent build and release pipelines in VSTS.
You can disable other agents:
On other hand, you can create a temp database with the name include build number, then they won't interfere with each other.
You can't configure this at the Build level (You can vote for this feature here), but perhaps you can accomplish what you want at the phase level.
Look at the Parallelism options under each Phase. Looks like you'll want to set this to "None" if you are seeing behavior contrary. "None" is the default option for new builds.
We implemented a custom VSTS task to do this. It works swimmingly. Here is the code.
If creating a custom VSTS task isn't your thing - you can strip out the PowerShell. Just have to pass the values as parameters instead.
/ Project-Folder
- extension-icon.png
- extension-manifest.json
/ Tasks
/ KeepBuildSynchronous
- icon.png
- task.json
- task.ps1
{
"manifestVersion": 1,
"id": "your-task-name",
"name": "your-package-name",
"version": "0.0.1",
"publisher": "your-publisher-account",
"targets": [
{
"id": "Microsoft.VisualStudio.Services"
}
],
"description": "your-description",
"categories": [
"Build and release"
],
"icons": {
"default": "extension-icon.png"
},
"files": [
{
"path": "Tasks/KeepBuildSynchronous"
}
],
"contributions": [
{
"id": "12345678-0000-0000-0000-000000000000", <-- must match task.json id
"type": "ms.vss-distributed-task.task",
"targets": [
"ms.vss-distributed-task.tasks"
],
"properties": {
"name": "Tasks/KeepBuildSynchronous"
}
}
]
}
{
"id": "12345678-0000-0000-0000-000000000000",
"name": "keepBuildSynchronous",
"friendlyName": "Keep Build Synchronous",
"description": "Only allow one build with the same build definition to run at a time",
"helpMarkDown": "",
"category": "Utility",
"visibility": [
"Build"
],
"runsOn": [
"Agent",
"DeploymentGroup"
],
"author": "-your team-",
"version": {
"Major": 1,
"Minor": 1,
"Patch": 1
},
"releaseNotes": "Initial release",
"minimumAgentVersion": "1.91.0",
"inputs": [
{
"name": "waitTimeinMinutes",
"type": "int",
"label": "How many minutes do you want to wait before cancelling the build",
"defaultValue": "15",
"required": true,
"helpMarkDown": ""
}
],
"instanceNameFormat": "Keep Build Synchronous",
"execution": {
"PowerShell3": {
"target": "task.ps1"
}
}
}
[CmdletBinding()]
Param ()
Trace-VstsEnteringInvocation $MyInvocation
try {
Import-VstsLocStrings "$PSScriptRoot\Task.json"
# Get agent/build variables
[string]$teamFoundationCollectionUri = Get-VstsTaskVariable -Name "system.teamFoundationCollectionUri"
[string]$teamProjectId = Get-VstsTaskVariable -Name "system.teamProjectId"
[string]$buildId = Get-VstsTaskVariable -Name "build.buildId"
[int]$definitionId = Get-VstsTaskVariable -Name "system.definitionId" -AsInt
[string]$accessToken = Get-VstsTaskVariable -Name "system.accessToken"
# Get task inputs
[int]$waitTimeinMinutes = Get-VstsInput -Name waitTimeinMinutes -AsInt
[Object[]]$global:buildsByDefinition = $null
[Object[]]$global:runningBuilds = $null
function Get-Builds-By-Definition([int]$definitionId) {
$url = "$teamFoundationCollectionUri/$teamProjectId/_apis/build/builds?api-version=2.0&definitions=$definitionId"
$type = "application/json"
$headers = @{
Authorization = "Bearer $accessToken"
}
$global:buildsByDefinition = (Invoke-RestMethod -Uri $url -ContentType $type -Method Get -Headers $headers).value
$global:runningBuilds = $buildsByDefinition | Where-Object -Property "status" -Value "inProgress" -EQ
}
[datetime]$startedAt = Get-Date
[datetime]$waitUntil = $startedAt.AddMinutes($waitTimeinMinutes)
Get-Builds-By-Definition -definitionId $definitionId
[string]$buildDefinitionName = $buildsByDefinition[0].definition.name
Write-Host ""
Write-Host "Build definition ..... $buildDefinitionName"
Write-Host "Current build ........ $buildId"
Write-Host ""
Write-Host "Started at ........... $startedAt"
Write-Host "Willing to wait until $waitUntil"
Write-Host ""
while (1 -eq 1) {
if ((Get-Date) -gt $waitUntil) {
Write-Host "Waited too long (cancelling)"
throw "Waited longer than $waitTime minutes to start. Cancelling."
}
if ($global:runningBuilds -eq $null) {
Write-Host "No build running (weird, but ok...)"
break
}
[int]$firstToGo = ($global:runningBuilds | Sort-Object -Property "Id")[0].Id
if ($global:runningBuilds.Count -le 1 -or $buildId -le $firstToGo) {
Write-Host "Your turn to shine"
break
} else {
Write-Host "$($global:runningBuilds.Count) builds running. $firstToGo is next. (checking again)"
Start-Sleep -Seconds 15
}
Get-Builds-By-Definition -definitionId $definitionId
}
}
finally {
Trace-VstsLeavingInvocation $MyInvocation
}
tfx extension create --manifest-globs extension-manifest.json --rev-version
I'll leave a little mystery and let you find out how to publish this to the marketplace and get it installed on your build agents
I appears this is not possible for manually triggered builds (arghh). However, for CI builds, DevOps can be configured to bunch changes while a build is running. Got to the "Triggers" tab of the build definition. Check: