[Azure Devops] 使用 Azure Pipelines 实现 CI

1. 什么是 Azure Pipelines

Azure Pipelines 会自动构建和测试代码项目,以将其提供给其他人。它适用于任何语言或项目类型。Azure Pipelines 结合了持续集成 (CI) 和持续交付 (CD),以持续不断地测试和构建您的代码,并将代码运送到任何目标。

在网上关于 Azure Pipelines 的教程很多,通常都是从 CI 到 CD 一条龙。但对于 WPF 来说也 CD 部分就有些尴尬,毕竟桌面应用通常不需要“部署”,所以这篇文章将只简单介绍如何创建编译 WPF 代码的 Pipeline。

2. 创建 Pipeline

在 Azure Devops 左边菜单中选中 Pipelines,进入 Pipelines 页面,点击 Create Pipeline 按钮进入下图中的创建 Pipeline 页面,然后按以下步骤操作:

  1. Where is your code?:选择代码所在的位置,选择 Azure Repos Git

  2. Select a repository:选中代码的存储库,这里我选择了之前创建的 wpf 存储库。

  3. Configure your pipeline:选择 Pipeline 的配置方式,因为是 WPF 项目,所以选择 .NET Desktop

  4. Review:检查生成的 YAML,可以重命名 YAML 文件,也可以点击右边的 Show assistant 打开 Tasks 列表查找并添加其它任务到 YAML 中。然后点击右上角的 Save and run 按钮。

  1. 在弹出的面板中,选择 Create a new branch for this commitStart a pull request,然后点击 Save and run 按钮。

现在创建了一个 Pull request,并且将刚刚创建的 Pipeline 的 YAML 加入到文件里了。这个 Pull Request 和 YAML 的内容如下:

trigger:
- master
pool:
  vmImage: 'windows-latest'
variables:
  solution: '**/*.sln'
  buildPlatform: 'Any CPU'
  buildConfiguration: 'Release'
steps:
- task: NuGetToolInstaller@1
- task: NuGetCommand@2
  inputs:
    restoreSolution: '$(solution)'
- task: VSBuild@1
  inputs:
    solution: '$(solution)'
    platform: '$(buildPlatform)'
    configuration: '$(buildConfiguration)'
- task: VSTest@2
  inputs:
    platform: '$(buildPlatform)'
    configuration: '$(buildConfiguration)'
  • trigger:触发器,当 master 更改时执行这个 Pipeline。
  • pool:要使用 Azure Pipelines 构建代码,至少需要一个代理。默认使用 Microsoft 托管的代理。
  • varibles:各种参数。
  • steps:步骤,可以看到这个 Pipeline 有四个Task:安装 Nuget,还原 Nuget,编译,测试。

VSBuild@1VSTest@2 等名称后面带 @ 和数字的,代表这个任务的第几版,例如 VSBuild@1 代表 VSBuild 的第一版。

回到 Pipelines 页面,找到新创建的 Pipeline(名称为 wpf),点击进入详细,可以看到 Runs、Branches、Analytics 三个页面,点击 Runs 列表中最上面一条,进入最近一个运行的详细结果。

点击 Job 进入运行的详细结果。可以看到每一个 task 的运行状况、持续时间,点击 task 还可以看到具体日志。

3. 下载软件

刚刚那个 Pipeline 还只是第一步,因为 Build 完就完事了,软件编译到哪里了?我怎么下载?接下来就要编辑 这个 Pipeline,加入 PublishBuildArtifacts 任务。

回到 Pipeline 的详细页面,点击右上角的 Edit 按钮,进入编辑页面。

编辑页面左边是 YAML 编辑器,右边是可用的 Task 列表。

在右上角的搜索框里输入 copy 找到 Copy files 这个 Task,点击进入配置页面。在 Source Folder 输入 WPF 项目的 Release 位置,Target Folder 输入 $(build.artifactstagingdirectory)。Build.ArtifactStagingDirectory 是个预定义变量,代表代理服务器上一个路径,artifact 发布前通常把要发布的内容复制到这个目录。

点击 Add 按钮把这个任务添加到 YAML。

接着搜索 publish 找到 Publish build artifacts 任务,可以直接保留默认值,也可以在 publish location 选项中选择 A file share,直接复制到指定位置点击,这里不作修改。Add 添加任务。

完成后可以看到下面这段内容被添加到 YAML 中。最后点击右上角的 Save,这个 YAML 将保存到 master 的文件中,由于要修改 master 分支,所以会自动创建一个 Pull request 并运行这个 Pipeline。

- task: CopyFiles@2
  inputs:
    SourceFolder: 'wpf/bin/release'
    Contents: '**'
    TargetFolder: '$(build.artifactstagingdirectory)'
- task: PublishBuildArtifacts@1
  inputs:
    PathtoPublish: '$(Build.ArtifactStagingDirectory)'
    ArtifactName: 'drop'
    publishLocation: 'Container'

上面是一般做法。也可以在新建 Pipeline 选择 Use the classic editor to create a pipeline without YAML,之后选择:

  • Select a source:Azure Repos Git
  • Team project:wpf
  • Repository:wpf
  • Default branch…:master
  • Featured:.NET Desktop

然后就一切都安排得妥妥当当,再在 Triggers 页面选中 Enable continuous integration,然后直接点击 Save & queue 完成创建。

最后,Pipeline 运行完成后,在 Run 的详细页面点击这个按钮(因为只创建了一个 Publish build artifacts 的 Task,所以结果是 1 published),进入 Artifacts 页面,即可将发布的内容以 Zip 的形式下载。

4.创建用于验证提交的 Pipeline

测试是持续集成的一个重要组成部分,我们可以通过配置分支策略,让每次代码合并到 master 分支之前都先通过测试。那么整个代码修改的流程就变成这样:

  1. 提交 Pull request
  2. 触发验证的 Pipeline
  3. 验证通过后代码合并到 master 分支
  4. 触发构建 artifact 的 Pipeline。

现在我们已经有一个 Pipeline了,完全可以用这个 Pipeline 满足上面的要求。但如果项目很大,编译测试耗时很长,最好还是将它拆分成两个分别用来完成第 2 步和第 4 步的 Pipeline。

具体来说,就是从已经创建的 Pipeline 中删除 VSTest 这个 Task,再重新建一个 Pipeline(只包含 NuGetToolInstaller、NuGetCommand、VSBuild、VSTest 等 4 个 Task,并且删除 trigger,即不再从 master 分支触发),将它 Rename 为 wpf-verify。

打开 master 的 Branch Policies 页面,在 Build Validation 中添加一个编译策略,Build pipeline 选择 wpf-verify,点击保存。

现在,当代码编译不通过,或者单元测试有不通过的测试,Pull request 检查不通过,不能合并。

点击错误信息,可以看到具体出错的单元测试。

修改代码后再提交,所有验证通过的结果如下:

之后代码合并到 master 分支并触发自动构建,整个流程就基本完成了。

5. 最后

对于 wpf 应用来说,Azure Pipelines 的使用还有其它一些问题,将在之后的文章里介绍。

更多的内容可以参考官方文档:

Azure Pipelines 文档

posted @ 2021-04-07 11:45  dino.c  阅读(515)  评论(1编辑  收藏