女主宣言

本文的作者为奇舞团前端工程师怡红公子,他是基于ThinkJS 开发的高人气开源博客平台 Firekylin (over 1.2k Stars) 的作者,今天他分享的是使用 Drone.io 取代 travis-ci 做日常开发持续集成工作的经验。本文最先发布于怡红院落,转载已获取作者授权。

PS:丰富的一线技术、多元化的表现形式,尽在“HULK一线技术杂谈”,点关注哦!

前言

我在很多 Github 项目中都会使用 travis-ci 来做自动化构建任务,其中的一项主要内容就是代码提交后自动执行单元测试计算测试覆盖率。但是 travis-ci 对于其它平台(例如 Gitlab)以及公司内网仓库来说都是不支持的,所以萌生了想要找另外一款 CI 工具代替 travis-ci 的想法。

1

基于Docker的CI工具 - Drone

对比了几款 CI 产品之后,我最终选择了 Drone。它是一款使用 Go 开发的开源的 CI 自动构建平台,能够单独部署,支持常见的 Git 仓库,例如 Github, Gitlab, Bitbucket 以及 Gogs 等。Drone 主要有以下几个方面吸引我:


原生 Docker 支持

环境部署算是自动化构建比较复杂的一点了,目前最优解就是使用 docker 容器化技术打包我们的环境。原生 docker 的支持让我们不需要额外的在构建脚本中增加 docker 的命令,简单配置就可以为我们带来集成 docker 所引入的一系列的好处:环境隔离、标准化镜像。并且它的每一个插件都是一个镜像,让我们的自动构建环境模块化。

新版的 Drone 将其拆分成了 Server 端和 Agent 端,Server 用来处理任务分发,Agent 用来执行自动化构建任务。简单增加 Agent 容器实例,我们就可以非常方便的横向扩容 Drone。

PipeLine AS Code

在项目根目录有一个 .drone.yml 的文件,这个是 Drone 构建脚本的配置文件,它随项目一块进行版本管理,开发者不需要额外再去维护一个配置脚本。其实现代 CI 程序都是这么做了,这个主要是相对于 Jekins 来说的。虽然 Jekins 也有插件支持,但毕竟还是需要配置。

另外就是基于 yaml 的配置文件非常简单(当然也要视需求而定),例如一个简单的构建脚本如下:

pipeline:

build:

image: node:6.6.0

commands:

- npm install --silent

- npm test

比起 Jekins 纷繁复杂的配置,Drone 几行就搞定了构建的需求。

丰富的插件支持

http://plugins.drone.io/ 这个是 Drone 的插件商店,包含了常见的一些需求插件,例如:

  • 构建后发送消息:slack, telegram, line, facebook, discord, gitter, email...

  • 构建成功后发布:npm, docker, github release, google container...

  • 构建成功后部署:AWS, Kubernetes, rsync, scp, ftp...

pipeline 中简单的增加插件镜像配置就可以支持插件,例如:

pipeline:

build:

image: node:6.6.0

commands:

- npm install --silent

- npm test

publish:

image: plugins/npm

secret: [ npm_username, npm_pwd, npm_email ]

username: ${NPM_USERNAME}

password: ${NPM_PWD}

email: ${NPM_EMAIL}

when:

event: [ tag ]

notify:

image: appleboy/drone-telegram

secret: [ telegram_token, telegram_to ]

token: ${TELEGRAM_TOKEN}

to: ${TELEGRAM_TO}

由于 Drone 是基于 Docker 的,甚至是所有的插件也都是一个 docker 镜像。这代表着我们可以使用任何语言来开发 Drone 插件,最后只要打包成镜像就好了。

其它 CI 工具

Drone 相对于 Jekins 来说优势比较明显,复杂的配置以及需要插件支持的构建脚本 pipeline 化都是我没考虑它的原因。不过 Jekins 其丰富的插件扩展,针对于无项目的自动化构建来说还是非常不错的。Gitlab-CI 也是一款不错的工具,不过从名字上也能看出它的缺点,就是只支持 Gitlab,而且无法扩展配置文件,对于正好在使用 Gitlab 且需求不高的同学可以试试。

2

安装配置 Drone

下面我将来介绍下如何配置安装 Drone。官方推荐使用 docker-compose 来启动服务,所以首先我们要准备好 docker 和 docker-compose。

安装 docker

docker 服务提供了桌面版,服务器版和云服务版不同操作系统的多种支持,可以在官方文档中找到对应的安装方法。这里以 Debain 服务器安装为例。Docker 支持 Debian 7.7+ 以上的系统版本, 需要 3.10 版本以上的 Linux 内核环境。

首先我们添加 docker 源的密钥:

$ sudo apt-get update

$ sudo apt-get install \

apt-transport-https \

ca-certificates \

curl \

gnupg2 \

software-properties-common

$ curl -fsSL https://download.docker.com/linux/$(. /etc/os-release; echo "$ID")/gpg | sudo apt-key add -

然后我们添加 Docker 官方源并安装 Docker:

$ sudo add-apt-repository \

"deb [arch=amd64] https://download.docker.com/linux/$(. /etc/os-release; echo "$ID") \

$(lsb_release -cs) \

stable"

$ sudo apt-get update

$ sudo apt-get install docker-ce

执行以下命令确保我们已经安装正确:

$ sudo docker run hello-world

相比 docker 的安装,docker-compose 的安装就比较简单了。它是用 python 写的一个 docker 多镜像编排启动的工具,我们可以直接使用 pip 来安装它:

$ pip install docker-compose

Git仓库准备

CI 可持续构建的一个大前提是基于仓库的,所有的构建第一步都需要去仓库拉取代码。Drone 支持 Github,Gitlab,Bitbucket,Gogs, Gitea, coding 多个仓库类型,其中支持 OAuth 的仓库需要在网站申请密钥。这里以 Github 为例。在 New Oauth Application 页申请密钥,其中 callback URL 需要填写为<你的CI地址>/authorize。申请好后记录下你的 client id 和 client secret 以便后续使用。


创建 compose 配置文件

我们新建一个空目录防止我们的配置文件文件:

$ mkdir drone

$ cd drone

$ vim docker-compose.yml

在配置文件中,我们设置 docker-compose.yml 的格式为 2 号版本,定义两种服务。

  • drone-server :使用 drone/drone:0.8.2 版本镜像,将启动监听 3800 上的主 Drone 服务容器,9000 端口来开放给 Agent。我们将在容器内挂载 /etc/drone 目录,以便 drone 可以保留数据。配置服务自动重新启动,并添加一些环境变量。

  • drone-agent:使用 drone/agent:0.8.2 版本镜像,将 docker 启动句柄挂载到容器 /var/run/docker.sock 文件中,以便 drone 可以使用 docker 来执行镜像构建任务。环境变量中需要配置 drone server 的地址以及 server 的密钥,以便于 server 进行通信。

version: '2'

services:

drone-server:

image: drone/drone:0.8.2

ports:

- 3800:8000

- 9000

volumes:

- /etc/drone:/var/lib/drone/

restart: always

environment:

# 是否允许注册,false 后只有在 DRONE_ADMIN 变量中指定的账户才能登录

- DRONE_OPEN=true

# Drone可公开访问的地址

- DRONE_HOST=http://ci.eming.li

# 配置 Git 仓库,只能同时使用一种仓库

# Github 仓库需要配置上问申请到的 client id 和 client secret

- DRONE_GITHUB=true

- DRONE_GITHUB_CLIENT=xxxxx

- DRONE_GITHUB_SECRET=xxxxx

# Gogs 配置仓库地址即可

- DRONE_GOGS=false

- DRONE_GOGS_URL=http://git.eming.li

# Drone Server 和 Agent 的通信密钥

- DRONE_SECRET=xxxxx

drone-agent:

image: drone/agent:0.8.2

command: agent

restart: always

depends_on:

- drone-server

volumes:

- /var/run/docker.sock:/var/run/docker.sock

environment:

# 配置 SERVER 地址

- DRONE_SERVER=drone-server:9000

# 配置与 SERVER 通信的密钥,需要与 Server 配置的保持一致

- DRONE_SECRET=xxxxx

其中的通信密钥相当于 drone 的密码,最好为一个长串的随机字串防止被破解。可以在命令行中使用以下内容生成

$ LC_ALL=C </dev/urandom tr -dc A-Za-z0-9 | head -c 65 && echo

配置文件完成之后,我们就可以使用以下命令启动服务了:

$ docker-compose -f /etc/drone/docker-compose up

docker-compose 会自动帮我们去下载镜像并根据配置初始化容器。一切就绪之后,我们使用 http://<host>:3800   就可以访问到 drone 了。

配置 Nginx

带端口访问总是让人不爽,老方法我们配置下 Nginx 做下反向代理就可以了,以下是具体的 nginx 配置文件示例:

map $http_upgrade $connection_upgrade {

default upgrade;

''      close;

}

server {

listen 80;

server_name ci.eming.li;

set $drone_port 3800;

location / {

proxy_set_header X-Forwarded-For $remote_addr;

proxy_set_header X-Forwarded-Proto $scheme;

proxy_set_header Host $http_host;

proxy_pass http://127.0.0.1:$drone_port;

proxy_redirect off;

proxy_http_version 1.1;

proxy_buffering off;

chunked_transfer_encoding off;

}

location ~* /ws {

proxy_pass http://127.0.0.1:$drone_port;

proxy_http_version 1.1;

proxy_set_header Upgrade $http_upgrade;

proxy_set_header Connection "upgrade";

proxy_read_timeout 86400;

proxy_set_header X-Forwarded-For $remote_addr;

proxy_set_header X-Forwarded-Proto $scheme;

proxy_set_header Host $http_host;

}

}

修改 server_name 和 $drone_port 为正确的值即可,最后记得别忘了重启 Nginx 服务。这样我们就能直接使用 http://ci.eming.li 来访问 drone 了。

进程守护

刚才使用 docker-compose up 命令启动如果退出终端了之后服务就会停止,所以我们需要后台执行。我们可以直接使用 nohup 方法启动:

$ nohup docker-compose -f docker-compose.yml up &

除了使用 nohup 之外,我们还可以使用 systemctl 来启动进程。我们创建一个 drone.service 服务文件:

$ vim /etc/systemd/system/drone.service

复制以下内容:

[Unit]

Description=Drone server

After=docker.service nginx.service

[Service]

Restart=always

ExecStart=/usr/local/bin/docker-compose -f /etc/drone/docker-compose.yml up

ExecStop=/usr/local/bin/docker-compose -f /etc/drone/docker-compose.yml stop

[Install]

WantedBy=multi-user.target

第一部分告诉 systemd 在 Docker 和 Nginx 可用之后启动此服务。 第二部分告诉 init 系统在发生故障时自动重新启动服务。 然后,它使用 Docker Compose 和我们之前创建的配置文件定义启动和停止 Drone 服务的命令。 最后,最后一节定义了如何使服务在启动时启动。完成后保存文件并使用如下命令启动服务:

$ systemctl start drone

使用如下命令可以查看服务启动状态, 如状态显示为active (running)则服务运行正常。

$ systemctl status drone

这样我们的安装过程就结束了,访问 Drone,使用对应仓库的账户登录。如果是 Github 的话会使用 OAuth 连接到 Github 进行授权申请,如果是 Gogs 则需要输入 Gogs 的账号和密码。

3

User Guide

接下来我将来介绍重头戏——如何在项目中使用 Drone 完成自动化构建任务。首先我们要在 drone 中开启自动构建,实际上它会在对象的 Git 仓库中添加 webhooks 方便当开发者执行对应 git 操作后触发自动构建任务。


.drone.yml

在《基于DOCKER的CI工具—DRONE》一文中我们有说过它的每一个构建插件都是镜像,能够模块化的配置我们的构建任务。将构建任务理解成是一条管道,项目流经管道做各种具体的任务。以下是一个简单的管道流程,代码克隆下来后执行安装并执行测试,完成后使用使用 Telegram 通知用户。


通过编辑放置在项目的根目录下的 .drone.yml 文件,我们可以对构建流进行配置。下面就是上图构建流程的配置:

pipeline:

build:

image: node:6.6.0

commands:

- npm install --silent

- npm test

telegram:

image: appleboy/drone-telegram

token: XXX:XXXXX

to: 337635385

message: >

{{#success build.status}}

主人,{{repo.owner}}/{{repo.name}}第{{build.number}}次构建成功!

{{else}}

主人,{{repo.owner}}/{{repo.name}}第{{build.number}}次构建失败了,快来修理下吧。

{{/success}}

在配置文件中我们总共定义了两个管道任务:

  • build: 我们为 build 任务指定了 node:6.6.0 镜像,并在镜像中执行 npm install --silent 命令安装依赖。最后执行 npm test 来运行单元测试脚本。

  • telegram: 我们为 telegram 任务指定了 appleboy/brone-telegram 镜像,并定义了一些镜像需要的环境参数。包括 telegram 的机器人 token,指定了消息的发送对象 to 以及消息的模板。

将其保存提交后就能正常触发任务并使用 telegram 接收消息了。


telegram

telegram 插件需要设置 bot token,没有的需要先关注 @BotFather 并输入 /netbot 命令创建一个 bot,这样你就能获取到 token 了。

而 to 参数需要配置的是发送用户的 ID,这个比较坑爹了。最开始以为是 username,输入之后一直没有反应,后来才反应过来可能是唯一 ID。不过 telegram ID 的获取比较困难,有人为此特地做了一个机器人。关注 @userinfobot 后和它发个消息它就会告诉你你自己的 ID 啦。这里有个小技巧是把别人的消息转发给它,它会给出对象的 ID。

关于 telegram 插件更多的配置可以参考:http://plugins.drone.io/appleboy/drone-telegram/

Secrets

由于我们将 token 直接写在了 .drone.yml 的配置文件中,项目其它人也都可见,这会带来一些潜在的安全问题。为此我们可以使用 drone 的 secrets 功能。我们小改一下配置文件:

telegram:

image: appleboy/drone-telegram

secrets: [ telegram_token, telegram_to ]

token: ${TELEGRAM_TOKEN}

to: ${TELEGRAM_TO}

同时我们在网站后台添加两个名为 telegram_token 和 telegram_to 的密钥:


保存后重新执行构建任务即可,这样我们就做到了隐藏敏感信息的目的。当然其实这么做也有缺陷,因为在网站后台添加的密钥是对管道中所有的构建插件全局共享的,如果开发者在管道中增加其它插件并 echo 或者其它操作,一样也是能获取到密钥的。为此我们就需要使用 drone-cli 命令来添加密钥,它支持指定密钥的作用域镜像。

$ drone secrets add \

--repository=lizheming/qalarm \

--name=telegrame_to \

--value=337635385 \

--image=appleboy/telegram

4

Troubleshooting

构建任务无故退出

实际使用过程中我发现我的构建任务总是莫名其妙就失败,提示我被 killed 掉,并显示 exit code 137。最开始我一直在查 137 退出码,发现就是 kill -9 的退出,不明所以。后来偶然尝试以 docker killed 为关键词搜索,才发现原来是内存爆了 docker 执行 OOM 把容器杀掉了。后来按照作者建议给机器加到 2G 的内存就没问题了。


5

总结

基本上 Drone 的流程是我想要的 CI 模式了。不过人无完人,drone 也有一些不足,主要是:

  • 不同版本的文档太多,老文档的一些功能都不支持了。

  • 社区还不够发展,找个问题比较困难。不过好在有个官方论坛,作者回复倒是挺勤快的。

  • 前端界面比较简单,很多功能还是得依靠命令行。

不过这些问题都不影响我对它的看法,相信它会越来越好。

相关资料:

  1. https://aisensiy.github.io/2017/08/04/drone-best-ci/

  2. https://blog.wu-boy.com/2017/09/why-i-choose-drone-as-ci-cd-tool/

  3. http://docs.drone.io/installation/

  4. https://www.howtoing.com/how-to-install-and-configure-drone-on-ubuntu-16-04

  5. https://discourse.drone.io/t/http-request-in-drone-are-all-connect-timeout/1083/2

  6. https://github.com/drone/drone/issues/825

  7. https://github.com/drone/drone/issues/390

  8. http://docs.drone.io/getting-started/

  9. https://core.telegram.org/bots/api

  10. https://blog.wu-boy.com/2017/11/drone-secret-security/

扫描下方
二维码
了解更多内容

前端工程师的CI进阶之路相关推荐

  1. 运维工程师打怪升级进阶之路 V2.0

    很多读者伙伴们反应总结的很系统.很全面,无论是0基础初学者,还是有基础的入门者,或者是有经验的职场运维工程师们,都反馈此系列文章非常不错! 命名:<运维工程师打怪升级之路> 版本:V1.0 ...

  2. 前端工程师的技术进阶点在哪里?

    前端工程师的技术进阶点在哪里? 单纯讲技术进阶点意义不大,脱离场景都是耍流氓.我举个实际例子,今天的阿里大文娱优土,阿里接管2年,底层替换差不多了,由内容为王慢慢转变为产品技术驱动.这种情况下,前端如 ...

  3. Web前端工程师编程能力飞升之路

    今天看到这篇文章.写的非常有意思.发现自己才处于"入室"阶段.骚年,路还很长,继续前行. [背景] 如果你是刚进入web前端研发领域,想试试这潭水有多深,看这篇文章吧: 如果你是做 ...

  4. 如何成为web前端大神以及进阶之路

    前端大神 要想成为厉害的开发者,那么最不可缺少的就是知识技能的累计, 首先一些必要的基础还是要掌握的, 除此之外每天抽一点点时间学习一个新的技能点, 一年365天 ,你就能get到365个技能,那么你 ...

  5. 胡珈魁:00后工程师的AI进阶之路 | OneFlow U

    ‍ ‍ 胡珈魁,目前在西安电子科技大学读大三,电子科学与技术专业.暑期在OneFlow实习期间,主要参与了模型部署工作. 跟大多数大学生一样,他从大一开始学习编程,但却没有局限于课堂知识.他有着极强的 ...

  6. 《Java Web开发实战》Java工程师推荐的进阶之路

    <Java Web开发实战>一书更加趋于实战性.此教材由浅入深.循序渐进,在语法阐述时尽量避免术语和公式,使初学者能够快速入门,全面掌握实战技能.它既可以作为高等院校本.专科计算机相关专业 ...

  7. 前端工程师的进阶之路

    背景 如果你是刚进入WEB前端研发领域,想试试这潭水有多深,看这篇文章吧: 如果你是做了两三年WEB产品前端研发,迷茫找不着提高之路,看这篇文章吧: 如果你是四五年的前端开发高手,没有难题能难得住你的 ...

  8. 前端工程师做事的三重境界:我的进阶之路

    共 2835 字,读完需 5 分钟.写作本文的目的:构建自己关于前端工程师成长过程的认知模型,从自己的视角来分析 Programmer.Developer.Enginner 的能力结构与工程师成长过程 ...

  9. 前端网页广告无线翻滚_从小白到web前端工程师进阶之路 从0到1到更深

    互联网的发展,让web前端技术发生了翻天覆地的变化,前端开发工程师可以让网页内容变得更加生动,为用户带来更好的体验.那么,武汉web前端培训哪个好?web前端好学吗?作为一个合格的Web前端工程师,需 ...

最新文章

  1. UVA11054Gergovia的酒交易
  2. mysql flask-login_Flask web模板六–Flask-Login完成登录验证
  3. 八种常见的 SQL 错误用法
  4. 进程间通信线程间通信
  5. ​给前端开发者的 14 个 JavaScript 代码优化建议
  6. 成本预算的四个步骤_工业企业成本管理之成本控制体系的构建
  7. .net WPF是什么
  8. 几款免费PDF合并成一个PDF的软件推荐,快收藏起来吧
  9. linux查询文件md5sum,Linux下通过md5sum生成MD5文件校验MD5
  10. css文章排版代码,css文章排版
  11. 安装hustoj的一些心得及html的笔记
  12. 最小二乘法-线性拟合
  13. 程序员是不是青春饭?年纪大了何去何从
  14. Python数据爬虫学习笔记(19)Scrapy天善智能网课信息爬虫
  15. 怎样写好Flutter代码
  16. OSAL初始化流程分析
  17. Java线程状态及转换
  18. java常见面试题库大全
  19. 计算机网络:网络安全
  20. 深耕技术的同时,别忘了走出自己的舒适区

热门文章

  1. Memo History Tracking History in Access 2007
  2. Android之播放一首简单的音乐
  3. Spring之数据源整理
  4. [蓝桥杯]2019年第十届省赛真题C/C++ B组 填空+大题
  5. vue 组件 props配置
  6. java String类常用的方法
  7. SpringMVC面试
  8. container view_高级UI晋升之常用View(三)中篇
  9. ubuntu安装 rust nightly_一起学Rust编程「1」:开发环境
  10. 微信小程序周报(第十一期)-极乐商店出品