Run only one instance of a build on VSTS

后端 未结 4 788
梦毁少年i
梦毁少年i 2020-12-20 07:29

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

相关标签:
4条回答
  • 2020-12-20 07:39

    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:

    1. Go do Agent Queues admin page
    2. Select the queue
    3. Uncheck agent to disable it

    On other hand, you can create a temp database with the name include build number, then they won't interfere with each other.

    0 讨论(0)
  • 2020-12-20 07:40

    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.

    0 讨论(0)
  • 2020-12-20 07:50

    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.

    file structure

    / Project-Folder
        - extension-icon.png
        - extension-manifest.json
        / Tasks
            / KeepBuildSynchronous
                - icon.png
                - task.json
                - task.ps1
    

    extension-manifest.json

    {
        "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"
                }
            }
        ]
    }
    

    task.json

    {
        "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"
            }
        }
    }
    

    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
    }
    

    create the .vsix file

    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

    0 讨论(0)
  • 2020-12-20 07:58

    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:

    • Enable continuous integration
    • Batch changes while a build is in progress
    0 讨论(0)
提交回复
热议问题