在 VSTS 上仅运行一个构建实例 [英] Run only one instance of a build on VSTS

查看:12
本文介绍了在 VSTS 上仅运行一个构建实例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 VSTS 中有一个代理队列,其中包含多个代理,并且我有一个分配给该队列的构建.有什么方法可以告诉 VSTS 一次只运行一个构建实例,其他实例(安排在其他代理上)应该等到前一个实例完成?

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 run at a time, and the other instances (scheduled on other agents) should wait until the previous one finishes?

我需要这个,因为测试会创建一个临时数据库,在该数据库上运行集成测试,如果多个实例针对同一个数据库运行,那么它们会相互干扰.

I need this because the tests create a temp database on which integration tests are run and if multiple instances are running against the same database then they interfere with each other.

推荐答案

我们实施了自定义 VSTS 任务来执行此操作.它工作得很好.这是代码.

We implemented a custom VSTS task to do this. It works swimmingly. Here is the code.

如果创建自定义 VSTS 任务不是您的事 - 您可以去掉 PowerShell.只需将值作为参数传递即可.

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

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 "$PSScriptRootTask.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
}

创建 .vsix 文件

tfx extension create --manifest-globs extension-manifest.json --rev-version

我会留下一点神秘感,让您了解如何将其发布到市场并将其安装在您的构建代理上

这篇关于在 VSTS 上仅运行一个构建实例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆