在VSTS上仅运行一个构建实例

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在VSTS上仅运行一个构建实例相关的知识,希望对你有一定的参考价值。

我在VSTS中有一个代理队列,有几个代理,我有一个分配给这个队列的构建。有没有办法告诉VSTS一次只能运行一个构建实例,其他实例(在其他代理上安排)应该等到上一个实例完成?

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

答案

我们实现了一个自定义VSTS任务来执行此操作。它运作良好。这是代码。

如果您不想创建自定义VSTS任务 - 您可以删除PowerShell。只需将值作为参数传递即可。

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

create the .vsix file

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

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

另一答案

你不能在Build级别(You can vote for this feature here)配置它,但也许你可以在阶段级别完成你想要的。

查看每个阶段下的Parallelism选项。看起来如果你看到行为相反,你会想要将其设置为“无”。 “无”是新构建的默认选项。

Parallelism Options

另一答案

不,没有这样的设置来控制它,它由管道控制:Concurrent build and release pipelines in VSTS

您可以禁用其他代理:

  1. 去代理队列管理页面
  2. 选择队列
  3. 取消选中代理以禁用它

另一方面,您可以创建名为include build number的临时数据库,然后它们不会相互干扰。

以上是关于在VSTS上仅运行一个构建实例的主要内容,如果未能解决你的问题,请参考以下文章

将 1 个 VSTS 实例链接到多个 Azure 订阅

VSTS 构建代理 - 一台计算机可以运行多个构建代理吗?

使用 Google Cloud 服务帐户是 VSTS 构建

使用 VSTS 构建/运行共享解决方案中定义的 Selenium 测试

服务结构升级在 VSTS 构建服务器上创建了一个错误

如何在VSTS托管构建代理上返回grunt错误