【问题标题】:How to CI build branches in VSTS如何在 VSTS 中 CI 构建分支
【发布时间】:2016-10-05 14:33:43
【问题描述】:

我们在 VSTS 中使用带有分支和 Pull Requests 模型的 Git 存储库来允许代码审查。

我们有一个 CI Build 定义并遵循它Release 定义,用于推送到 master 的所有提交。

如果我们也可以为所有分支进行CI,那将是一个巨大的好处。 但是 Git repos 的构建定义只允许设置单个分支来跟踪。

并且为每个分支创建一个构建是不可行的,因为我们的分支是短暂的又名特性分支,我们在 PR 合并到主分支后将它们删除。

是的,可以在 Branch Policies 页面中指定运行 CI build for PRs 以掌握。但这有两个问题:

  • 这将只构建 PR,而我们希望在将所有单独的提交推送到分支后立即构建它们

  • PR 的 CI 构建也会触发我们的发布,但我们显然希望它仅在主构建时触发。是的,我可以在 Release 定义中分析 $(Build.SourceBranch)$(Build.SourceBranchName),如果它不是“master”则失败,但无论如何它都会创建一个失败的 Release,我只想避免这种情况

那么...我们如何在 VSTS 中为任意分支构建 CI?


更新

另一个只为主构建运行发布的想法 - 是从构建端触发发布,例如by using API 如果 $(Build.SourceBranch) 等于 'master',例如自定义 PowerShell 脚本。

我可以看到VSTS Trigger build step 甚至还有一个扩展名,但即使是非主版本也会触发,尽管微软正在开发a feature to run steps conditionally

【问题讨论】:

    标签: git continuous-integration azure-devops pull-request


    【解决方案1】:

    您可以在构建定义的末尾添加一个 powershell 脚本任务以通过 Rest API 触发发布,我创建了一个简单的代码示例供您参考:

    if ($env:BUILD_SOURCEBRANCHNAME -eq "master")
    {
    $collectionuri = $env:SYSTEM_TEAMFOUNDATIONCOLLECTIONURI
    $buildid = $env:BUILD_BUILDID
    $project = $env:SYSTEM_TEAMPROJECT
    $token = $env:SYSTEM_ACCESSTOKEN
    $builddef = $env:BUILD_DEFINITIONNAME
    $buildnum = $env:BUILD_BUILDID
    $releaseid = 2;
    
    #Generate API URL
    $account = "";
    $reg = "https://+(?<acc>\w+?).visualstudio+"
    if ($collectionuri -match $reg)
    {
        $account = $Matches.acc;
    }
    else
    {
        Write-Host "Fail to get the account name from collection url";
    }
    $url= "https://" + $account + ".vsrm.visualstudio.com/"+ $project + "/_apis/release/releases?api-version=3.0-preview.2"
    
    #Generate Auth info
    $basicAuth= ("{0}:{1}"-f "anys",$token)
    $basicAuth=[System.Text.Encoding]::UTF8.GetBytes($basicAuth)
    $basicAuth=[System.Convert]::ToBase64String($basicAuth)
    $headers= @{Authorization=("Basic {0}"-f $basicAuth)}
    
    #Generate body content
    $instanceRef = @{id = $buildID};
    $artif = @{alias = $builddef; instanceReference = @{id = $buildnum}}
    $content = @{
        definitionId = $releaseid
        description = "Triggered from CI Build"
        artifacts = @($artif)
        }
    $json = $content | ConvertTo-Json -Depth 100
    
    #Call Rest API to start the release
    $responseBuild = Invoke-RestMethod -Uri $url -headers $headers -Method Post -Body $json -ContentType "application/json"
    }
    else
    {
        Write-Host "Not master branch, no release triggered"
    }
    

    您需要将“releaseid”更新为您要触发的发布定义的 ID,并在该定义的安全配置中,将“项目集合构建服务”的“创建发布”权限设置为“允许” " 帐户。

    【讨论】:

    • 出色的脚本和环境变量的使用 - 完成了工作!只是一个小评论 - 在正则表达式中,我已将 \w 替换为 [\w-] 因为我们的帐户名称包含连字符。
    • 另外,为了能够使用 SYSTEM_ACCESSTOKEN,我必须为构建定义启用选项“允许脚本访问 OAuth 令牌”。没什么大不了的,但仍然需要为所有构建配置它。所以想知道是否有办法为 Invoke-RestMethod 使用 -UsedefaultCredential 选项而不是使用访问令牌?尝试但失败 - 它返回一些 HTML 抱怨 Internet Explorer 增强的安全配置,而不是 JSON
    【解决方案2】:

    但是 Git repos 的构建定义只允许设置单个分支来跟踪。

    这实际上不是真的。 (Repository 选项卡有一个 Default branch 设置,您可能会感到困惑,它只接受一个分支。)

    在构建定义上,转到Triggers 选项卡。如果还没有,请选中 Continuous Integration 框。

    Branch filters 下单击Add new filter 并将值设置为*。 (它会提示您选择一个现有的分支,但您可以忽略它并按 Enter 键。)

    您的构建定义现在将在您的存储库中的任何分支上构建提交。

    【讨论】:

    • 嗨斯科特...是的,在我发布问题后意识到这一点。然而它对我们没有帮助 - a)我们需要不断更新每个新分支的构建定义(一天几次); b) 这些非主版本仍将触发发布。
    • @Ivan 你说的(a)是什么意思?对于 (b),我所做的是创建一个触发发布的构建定义,并为所有其他分支创建一个(不触发发布)。
    • 哈,对不起,错过了你关于星号 (*) 的观点,现在测试它,是的,它有效!谢谢。
    • 关于 (b) 每个存储库有 2 个构建定义是可行的,我们想到了这一点,但它仍然增加了一些复杂性 - 维护一个额外的定义,例如当我们修改它时,我们需要做两次,而且 VSTS 项目中的构建定义量也会增加一倍。
    • 顺便说一句,请参阅上面的更新我提出的问题 - 关于从构建端触发发布的想法。
    【解决方案3】:

    非常非常容易。

    1. 转到 Marketplace 并将 GitVersion 安装到 VSTS/Azure DevOps https://marketplace.visualstudio.com/items?itemName=gittools.gitversion

    2. 如前所述,更改 CI 触发器以监控所有分支:

      我还将第 2 行添加到监控标签的原因是,当我准备发布我的产品时,我利用 GitVersion 和 git 标签对构建工件进行版本控制。当我应用并推送一个 git 标签时,除非我明确告诉它注意它,否则构建不会检测到它。我的 git 标签格式是“v1.2.3”,以小写“v”开头。以防万一我想应用任何其他标签而不开始构建。

    3. 最后更改内部版本号格式。您需要辨别正在构建的分支。 GitVersion 使用语义版本控制,因此这描述了正在构建的内容。

    1. 现在从任意数量的分支启动尽可能多的构建,并查看它们都从单个构建定义启动。设置一次,从现在开始忘记!

    好处:

    • 没有要维护的脚本
    • 遵循语义版本控制
    • 创建一个构建管道/定义一次,再也不用担心功能分支。
    • 仍适用于拉取请求。
    • https://gitversion.readthedocs.io 上阅读有关 GitVersion 的更多信息

    秘诀:GitVersion 会读取 Git 历史记录,因此每次 git commit 标记后,数字都会递增。它从它正在使用的 CI 系统创建构建变量并使其可用。它派生这些变量并根据您正在使用 GitVersion 的 mode 为其正在构建的分支创建一个 tag 或别名。在上面的示例中,我有一些提交(未显示),当它是版本 0.1.0然后我将其标记为版本1.0.0 并发布。下一次提交预测下一个版本将是 1.1.0 并且有很多提交(其中 11 个)进入 develop 分支。构建名称使用别名 alpha,因为构建工件是 alpha 候选。还有 4 次提交。在从提交 #15 分支之后,有一个功能分支构建,进行了第 16 次提交并推送,然后构建。我想你明白了。这一切都来自一个构建管道,并使用 GitVersion 来描述正在构建的分支和正在构建的提交。语义版本控制描述了构建。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-10-13
      • 2016-12-28
      • 2018-08-30
      • 1970-01-01
      • 1970-01-01
      • 2018-05-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多