最近给一个小团队项目做了持续集成和持续部署,实现很快,成本也很低,把过程分享出来供大家参考。

需求

  1. 基本要求:实现持续集成和持续部署,从提交代码开始,自动构建、部署到测试环境。
  2. 系统生态:尽量 .Net 友好。
  3. 代码管理:对接已经存在的私有代码库,国内的,如开源中国Coding.NetCSDN 等。
  4. 成本控制:仅一台测试/演示服务器,尽量使用更少的服务器资源,尽量不增加额外资金投入。

方案

列了几个方案,见下表:

Solution Type Private Project Concurrent Job Code Service Fee Maint Fee .Net Support
AppVeyor Cloud 1 1 External Git $29+ / Month Low First Class
Travis CI Pro Cloud Unlimited 1 External Git $69+ / Month Low  
Jenkins On Premise Unlimited Unlimited Any N / A Middle  
TFS Express On Premise Unlimited Unlimited Any N / A High First Class
VS Team Service Cloud Unlimited 1 + 1 Any N / A Low First Class

P.S. Visual Studio Team Service 的 Free Hosted Pipeline 每月限时 240 分钟。

首先排除掉很贵的那两个,然后考虑一下要不要自建。
自建的话,如果团队内部有对 Jenkins 熟悉的可以选它;TFS Express 同理但是对服务器的配置要求会更高一点。
这次的项目是一个小团队,一个并行构建完全够用,一个 TFS 或者 Jenkins 对测试服务器的负担还是有些大,最后选用了 VS Team Service

实施

创建服务账号

填好账号名、项目名,Agile、Scrum、CMMI 按需选一个,决定不了就 Agile。
位置目前有 巴西南部、澳大利亚东部、印度南部、欧洲西部、美国中部 五个区域可选,可以在 Azure Latency Test 测试一下这几个相关的区域,按我的经验美国中部稍好一些,延迟大概在100毫秒到200毫秒之间。位置速度的敏感性取决于你的需求,按照本文的项目,不托管代码,不上传下载构建产物,这个延迟已经够用了。
注意,项目创建完成之后,如果你不打算托管代码,就不要初始化默认代码库

Create Visual Studio Team Services Accounts

配置构建代理(Agent)

打开管理面板中的 Agent queues,选择 Default,按说明下载 agent 并在测试服务器上配置好。
Agent queues

配置过程中需要注意的是,如果以服务方式运行(推荐),建议修改登陆为特定用户,而不是默认的本地网络服务账号
完成后应该能在此处看到 agent 的名字,以及 Online / Idle 的状态。

Agent service
Agent queues

配置 Remote Git Repo

这一步非常关键,为了使用我们已有的私有代码库,要把代码库的信息添加进来。
打开管理面板中的 Services,在 Endpoints 选项卡下,点击 New Service Endpoint - External Git,添加一个远程代码库。

Services Endpoints
Add new external Git repository connection

如果已有的私有库支持分配只读权限的 Access Token 最好,如果不支持,就只能添加一个只读权限的账号,通过用户名和密码认证。这里的 External Git 只支持 HTTPS 方式访问代码库仅主库,submodule 是支持 SSH 的,详情见后文)。

配置构建(Build)和发行(Release)

构建(Build)就是编译,而发行(Release)代表部署到某个环境。
参考文档:

1. 创建 Build definition,选择合适的模板。

Build definition template

2. 在 Process 页,选择 Default 为 Defualt agent queue。

Build definition template

3. 在 Get Sources 页,选择 From Remote repo,再选择之前创建的 External Git 库。

Build definition template

这一步需要注意的是,如果你的代码库包含 submodule,依据访问协议的不同,需要做如下处理:

  • SSH 协议:Agent 登陆的用户主目录下须有用于 SSH 登陆的证书(.ssh 目录),且该证书所属的 Git 用户至少应有读权限。
  • HTTPS 协议:1) 如果 submodule 所在库可以被公开读取(内网公开可读、或者内部 Git 服务器依据 IP 允许此服务器匿名读取均可),则不需要任何处理;2) 如果 submodule 所在库需要登陆,则需要在 Git Credential Manager 中存储相关登录凭据,最简单的办法,以 Agent 用户身份打开命令行,执行一次基于 HTTPS 协议的 git clone,相关窗口会自动弹出询问凭据。

Git Credential Manager

4. 参考第 2 步的图示,根据实际情况配置构建、本地拷贝构建产物等步骤。

需要注意的是 Agent 登陆用户需要对相关的本地路径、网络共享有写权限。

5. 在 Triggers 选项卡,启用 Continuous Integration 的触发器,并配置轮询间隔。

如果需要也可以配置分支过滤。

Triggers

6. 在 Options 选项卡,配置 Build number format,按需启用 Badge。

Badge 的 URL 会在保存后显示。

Options

7. 在 Publish Build Artifacts 页,选择将 $(Build.SourcesDirectory)\README.md(按实际情况配置一个标志文件)发布到 Server。

Publish Build Artifacts
这一步将一个标志文件作为构建产物上传到服务器,是触发自动发行(Release)的必要条件。如果不进行这一步,在配置发行的时候系统就会尝试自动构建内置代码库的内容来作为发行源。

至此构建部分配置完成。Push 一下,自动构建应该就开始了!

Build Summary
Email Notification

8. 创建 Release definition,选择 Empty

Create release definition

9. 在 Artifacts 页,选择 Choose Later

如果你已经进行过了编译,也可以从 Build 中选择。效果和等下进行了第 11 步一样。

Artifacts

10. 给 Environment 起个名字。

11. 在 Triggers 选项卡,启用 Continuous Integration 的触发器,并配置 Artifacts Source。

Triggers

点击 Link to an artifact source,如无意外所有的条目都会自动填好,直接 Link:

Link to an artifact source
Triggers

12. 在 General 选项卡,填好 Release name format

General

12. 回到 Environments 选项卡,添加一些 Tasks。

通常来说部署到环境的流程不外乎以下三个步骤:

  1. 停止服务
  2. 拷贝新版本
  3. 启动服务

一般会采用脚本停止、启动多个服务。需要注意的是,为了避免意外,如果任意一个服务的停止出错(exit code 不为 0),就应该让整个部署失败(可以在脚本中用类似 if not "%errorlevel%"=="0" exit 1 的语句放在每一个停止服务之后);相对的,启动服务的脚本无论何种情况都应该执行,这样如果某些服务停止失败,可以将其他服务再启动起来以恢复环境(虽然部署会失败,但是大部分情况下不影响环境正常工作),因而如图所示,勾选 Start Services 这个 Task 的 Always run。

Environments - Tasks

13. 切到 管理面板的 Notifications 选项卡,配置通知选项。

默认 VS Team Service 的通知是基于服务账号的,也就是说通知只会发送给注册到这个服务账号内的用户。需要做一些修改,才能让我们的团队成员收到自动构建和自动发行(部署)的结果。
推荐禁用内置的 Build Completes、Deployment to an owned environment failed、Deployment to an approved environment failed、Deployment completion failures 这几个通知;然后建立两个通知:Build - A build fails 和 Release - A deployment is completed,注意将 Deliver to 设置为 Team email address,然后填写对应的收件人。

Build - A build fails
Release - A deployment is completed

至此发行(部署)部分配置完成。Push 一下,自动的 构建 - 发行 应该就开始了!

Release lummary
Release list
Email Notification

如果有什么问题,欢迎在微博或者上和我交流。╮( ̄▽ ̄”)╭