是否有在本地验证 Azure DevOps Pipeline 的工具?

Posted

技术标签:

【中文标题】是否有在本地验证 Azure DevOps Pipeline 的工具?【英文标题】:Is there a tool to validate an Azure DevOps Pipeline locally? 【发布时间】:2019-04-02 03:49:26 【问题描述】:

在对 YAML 定义的 Azure DevOps Pipelines 进行更改时,将更改推送到分支只是为了看到构建失败并出现解析错误(有效的 YAML,但无效的管道定义)然后尝试尝试 - and-error 修复问题。

如果可以通过在本地分析和验证管道定义来缩短反馈循环,那就太好了;基本上是一个 linter,了解可以在 Azure 管道中定义的各种资源等。但是,我找不到任何可以执行此操作的工具。

哪里有这样的工具?

【问题讨论】:

【参考方案1】:

我可以告诉你我们是如何处理这种脱节的。

我们只使用管道即代码,yaml。

我们使用零 yaml 模板并严格执行 one-file-pr-pipeline。

我们对 vscode 使用 azure yaml 扩展,以在编辑器中获得类似 linter 的行为。

我们在管道中执行的大多数实际操作都是通过调用 PowerShell 来完成的,通过合理的默认设置也可以在 CLI 中调用,这意味着我们本质上可以在本地执行任何相关的操作。

代理的配置以及实际的仅管道内容(例如下载工件任务和发布任务等)除外。

让我举几个例子:

这里我们有构建前端组件的步骤:

我们在 CLI 中运行该步骤:

我不会发布实际管道运行的屏幕截图,因为清理它需要很长时间,但它基本上是相同的,加上更多的跟踪信息,由 run.ps1 调用包装器提供。

【讨论】:

如何管理依赖行Node、.NET SDK、Maven等? 当我们 f.ex "build-frontend" 时,该函数将断言,这意味着如果不满足条件它将失败,该节点和 npm 在预定义的版本中。在管道中我们使用 install-node 任务在 cli 中我们只是断言它,开发人员将在本地 nvm 安装 正确的做法,在2021年,ofc是把它全部包在一个容器里,但是如果你还没有跳起来,那就是这样【参考方案2】:

使用 YAML 描述的管道,如果您有一个包含有关如何组成 YAML 文件的规则的架构,则可以验证 YAML。它将作为您描述的情况的简短反馈,特别是对于语法解析错误。 YAML 模式验证可能适用于几乎任何 IDE。所以,我们需要:

    YAML 架构 - 我们将根据我们将验证管道的内容 一个 IDE(以 VS Code 为例) - 将执行验证 在飞行中 配置以上两项以共同创造更大的利益

架构可能在很多地方都可以找到,对于这种情况,我建议使用https://www.schemastore.org/json/ 它有Azure Pipelines schema(此架构包含一些问题,例如与 Microsoft 文档相比的不同类型的值,但仍涵盖无效语法的情况)

VS Code 需要一个额外的插件来执行 YAML 文本验证,还有一堆插件可以验证模式。我会建议尝试YAML from RedHat(我知道,插件的评级不是最好的,但它适用于验证并且也是可配置的)

在该 VS Code 插件的设置中,您将看到有关验证的部分(如屏幕截图所示)

现在您可以将所需架构添加到设置中,即使无需将其下载到您的机器上:

    "yaml.schemas": 
    
    "https://raw.githubusercontent.com/microsoft/azure-pipelines-vscode/v1.174.2/service-schema.json" : "/*"

只需保存设置并重新启动 VS Code。 你会注意到有关 YAML Azure DevOps Pipeline 文件中问题的警告(如果有的话)。下面的屏幕截图中的目的验证失败:

也见more details with examples here

【讨论】:

【参考方案3】:

这种工具目前不存在 - 他们的反馈渠道中存在一些问题:

Github Issues - How to test YAML locally before commit Developer Community - How to test YAML locally before commit

作为一种解决方法 - 您可以在自己的机器上安装 azure devops 构建代理,注册为自己的构建池,并使用它来构建和验证 yaml 文件的正确性。见Jamie's answer in this thread

当然,这意味着您需要在官方构建代理和您自己的构建池之间不断切换,这并不好。此外,如果有人不小心通过您自己的机器推送了一些更改 - 您可能会遇到各种问题,这可能发生在正常的构建机器中。 (如 ui 提示、在您自己的机器上运行恶意代码等 - 由于第三方可执行文件执行,恶意代码甚至可能是意外病毒感染)。

作为解决此问题的一种方法 - 可以使用 powershell 语法来最大化在构建端完成的功能并最小化在 azure devops 上完成的功能。

parameters:
  - name: publish
    type: boolean
    default: true

parameters:
  - name: noincremental
    type: boolean
    default: false

...

      - task: PowerShell@2
        displayName: invoke build
        inputs:
          targetType: 'inline'
          script: |
            # Mimic build machine
            #$env:USERNAME = 'builder'

            # Backup this script if need to troubleshoot it later on
            $scriptDir = "$(Split-Path -parent $MyInvocation.MyCommand.Definition)"
            $scriptPath = [System.IO.Path]::Combine($scriptDir, $MyInvocation.MyCommand.Name)
            $tempFile = [System.IO.Path]::Combine([System.Environment]::CurrentDirectory, 'lastRun.ps1')
            if($scriptPath -ne $tempFile)
            
                Copy-Item $scriptPath -Destination $tempFile
            

            ./build.ps1 'build;pack' -nuget_servers @
                'servername' = @
                    'url' = "https://..."
                    'pat' = '$(System.AccessToken)'
                

                'servername2' = @
                    'url' = 'https://...'
                    'publish_key' = '$(ServerSecretPublishKey)'
                
             `
            -b $(Build.SourceBranchName) `
            -addoperations publish=$parameters.publish;noincremental=$parameters.noincremental

然后在 build.ps1 上处理所有必要的参数。

param ( 

    # Can add operations using simple command line like this: 
    #   build a -add_operations c=true,d=true,e=false -v
    # => 
    #   a c d
    #
    [string] $addoperations = ''
)

...

foreach ($operationToAdd in $addoperations.Split(";,"))

    if($operationToAdd.Length -eq 0)
    
        continue
    

    $keyValue = $operationToAdd.Split("=")

    if($keyValue.Length -ne 2)
    
        "Ignoring command line parameter '$operationToAdd'"
        continue
    

    if([System.Convert]::ToBoolean($keyValue[1]))
    
        $operationsToPerform = $operationsToPerform + $keyValue[0];
    

这将允许在您自己的机器上本地运行所有相同的操作并最大限度地减少 yaml 文件内容的数量。

请注意,我还添加了最后执行 .ps1 脚本复制为 lastRun.ps1 文件。

如果您发现一些不可重现的问题,您可以在构建后使用它 - 但您想在自己的机器上运行相同的命令来测试它。

您可以使用 ` 字符在下一行继续执行 ps1,或者如果它已经是复杂的结构(例如@) - 它可以继续执行。

但即使这样 yaml 语法被最小化,它仍然需要测试 - 如果你想要不同的构建阶段和使用多个构建机器。一种方法是使用特殊类型的参数-noop,它不执行任何操作 - 但只会打印打算执行的内容。通过这种方式,您可以立即运行您的管道并检查计划执行的所有内容 - 将被执行。

【讨论】:

【参考方案4】:

仅供参考 - 此功能已在 Issue #2479 中删除 - 删除对“本地运行”功能的引用

考虑到 Github Actions 有 the ability to run actions locally,希望他们稍后能把它带回来

【讨论】:

【参考方案5】:

更新:此功能是 2019 年 10 月的 removed in Issue #2479


您可以使用其 YAML 测试功能在本地运行 Azure DevOps 代理。

    从microsoft/azure-pipelines-agent 项目,在您的本地计算机上安装代理。 然后使用Run local (internal only) 上的文档页面访问代理中可用的功能。

这应该会让您非常接近您所期望的反馈类型。

【讨论】:

谢谢!这对我来说有点矫枉过正(因为它似乎需要在本地安装代理;我没有设法仅通过存储库中的东西来使其工作......)。然而,这个咒语,我能不能让它发挥作用,似乎它会完全符合我的要求:./run.sh --yaml <my-yaml-file> --what-if。我会向他们提出问题,看看他们是否可以开始将该功能发布为全局 dotnet 工具或其他东西。 这是 GA 了吗? linked page 表明它只是内部的。 latest version 已被注释掉 - raw document 表明它在更改时仍在不断变化 (2018-06-24)【参考方案6】:

尝试在标准文本编辑器中手动编写整个 YAML 文件可能会很麻烦。取而代之的是,Azure DevOps 操作的开源扩展可以让你的生活变得更轻松。例如,我的一个朋友最近在我尝试向我的 YAML 管道添加构建任务时建议WhiteSource Bolt,您可以轻松免费安装并配置您的管道,我觉得使用 Azure DevOps 更容易白源螺栓。 现在,要将构建任务添加到 YAML 管道,请执行以下步骤:

    在管道编辑页面中,从右侧单击显示助手。将显示“任务”侧边栏。 在搜索栏中,输入 WhiteSource。显示 WhiteSource 任务。

    单击 WhiteSource Bolt 任务。 单击右下角的添加。 WhiteSource Bolt 任务已添加到管道中。
任务:WhiteSource@21 输入:cwd: '$(System.DefaultWorkingDirectory)'
    要指定要在 WhiteSource Essentials 中创建的 WhiteSource 项目的名称,请将以下内容添加到 WhiteSource 任务中。在以下示例中,将 New_Project_Name 替换为您要为 WhiteSource 项目指定的名称: 注意:第一次构建运行后,您无法更改项目名称。
任务:WhiteSource@21 输入:cwd: '$(System.DefaultWorkingDirectory)' 项目名称:New_Project_Name

如果 YAML 中有错误,则扩展程序本身会为您验证它并提供错误详细信息。有关如何将构建任务添加到 YAML 管道的更多信息,请查看上面的链接。

【讨论】:

您是不是忘记在答案末尾添加链接,还是您指的是上面的链接? 我指的是上面的链接【参考方案7】:

Azure DevOps 提供了一个 run preview api endpoint,它接受 yaml 覆盖并返回扩展的 yaml。我将此支持添加到AzurePipelinePS powershell 模块。下面的命令将执行 id 为 01 但我的 yaml 覆盖并返回扩展的 yaml 管道的管道。

预览 - 预览 服务: 管道 API版本: 6.1-preview.1 将管道的空运行排队并返回一个包含最终 yaml 的对象。

# AzurePipelinesPS session
$session = 'myAPSessionName'

# Path to my local yaml
$path = ".\extension.yml"    

# The id of an existing pipeline in my project
$id = 01        
        
# The master branch of my repository
$resources = @              
   repositories = @
       self = @
           refName = 'refs/heads/master'
        
   


Test-APPipelineYaml -Session $session -FullName $path -PipelineId $id -Resources 
$resources

【讨论】:

以上是关于是否有在本地验证 Azure DevOps Pipeline 的工具?的主要内容,如果未能解决你的问题,请参考以下文章

在不使用 PAT 的情况下验证 Azure Devops Api 调用?

Azure Devops 管道通过生成验证触发两次

将 Nuget 包从本地 TFS2017 发布到 azure DevOps

使用本地 TFS 发布管理器实施 Azure DevOps 服务

如何将本地 VS 项目添加到现有的非空 Azure DevOps Repo

SSL 证书问题:无法获取本地颁发者证书 AZURE DEVOPS