CI
全称为Continuous Integration
,意为持续集成
,是在源代码变更后自动检测、拉取、构建和进行自动化测试的过程,属于开发人员的自动化流程。该解决方案可以解决在一次开发中有太多应用分支,从而导致相互冲突的问题。其基本思路是,自动化监测代码仓库的变化并拉取最新代码、编译构建和自动化测试。CI
的触发方式可分为以下三种:
webhook
)通知CI
进行任务,这需要CI
环境被代码仓库访问到,因此需要一个外网可达地址CD
指的是持续交付(Continuous Delivery)
或持续部署(Continuous Deployment)
。持续交付
通常是指开发人员对应用的更改会自动进行错误测试并上传到存储库(如 GitHub 或容器注册表),然后由运维团队将其部署到实时生产环境中。持续部署
指的是自动将开发人员的更改从存储库发布到生产环境,它以持续交付为基础,实现了管道后续阶段的自动化。
CI/CD
既可能仅指持续集成和持续交付构成的关联环节,也可以指持续集成、持续交付和持续部署这三项构成的关联环节。
请参考:redhat:什么是CI/CD
Drone CI官网说:
Drone is a self-service Continuous Delivery platform for busy development teams.
相对于常见的Jenkins
,选中 Drone
的原因在于它非常简洁,不像Jenkins
那样复杂,同时它拥有可以满足基本需求的能力,并且提供了许多实用的插件,如GitHub
,Email
,helm
,微信
,钉钉
等
需要注意的是,drone 0.8版本和0.1版本差别较大,本文使用1.0版本
drone文档给出了相对于不同git仓库和部署方式的方案,支持的git仓库有:
拿github来说,drone提供了以下部署方式:
本节给出对于GitHub的单机部署方案,对官方部署方案做了docker-compose
方案的补充
Setting
,选择Developer settings
,选择OAuth Application
,选择新建一个application,如下图:http://127.0.0.1
{{HomePage}}/login
,如http://127.0.0.1/login
Client ID
和Client Secret
Docker安装文档
docker pull drone/drone:1.0.0-rc.6
docker 启动:
docker run \
--volume=/var/run/docker.sock:/var/run/docker.sock \
--volume=/var/lib/drone:/data \
--env=DRONE_GITHUB_SERVER=https://github.com \
--env=DRONE_GITHUB_CLIENT_ID={% your-github-client-id %} \
--env=DRONE_GITHUB_CLIENT_SECRET={% your-github-client-secret %} \
--env=DRONE_RUNNER_CAPACITY=2 \
--env=DRONE_SERVER_HOST={% your-drone-server-host %} \
--env=DRONE_SERVER_PROTO={% your-drone-server-protocol %} \
--env=DRONE_TLS_AUTOCERT=true \
--publish=80:80 \
--publish=443:443 \
--restart=always \
--detach=true \
--name=drone \
drone/drone:1.0.0-rc.6
docker-compse 启动
上面的启动命令是drone
官方文档的方案,下面给出我使用的docker compose
的方法
.env
文件,这是docker-compose启动时默认读取的文件,用来设置环境变量
DRONE_SERVER_HOST=127.0.0.1
DRONE_GITHUB_CLIENT_ID=XXXXXXXXXXXXXX
DRONE_GITHUB_CLIENT_SECRET=XXXXXXXXXX
DRONE_SERVER_PROTO=http
DRONE_SECRET_SECRET=ci-drone
docker-compose.yml
文件# drone server 部署
version: "2"
services:
drone-server:
image: drone/drone:1.0.0-rc.6
ports:
- 80:80
- 443:443
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /var/lib/drone:/data
restart: always
environment:
- DRONE_GITHUB_CLIENT_ID=${DRONE_GITHUB_CLIENT_ID}
- DRONE_GITHUB_CLIENT_SECRET=${DRONE_GITHUB_CLIENT_SECRET}
- DRONE_SERVER_PROTO=${DRONE_SERVER_PROTO}
- DRONE_SERVER_HOST=${DRONE_SERVER_HOST}
- DRONE_TLS_AUTOCERT=false
- DRONE_RUNNER_CAPACITY=8
- DRONE_DEBUG=false
- DRONE_LOGS_DEBUG=false
- DRONE_GIT_ALWAYS_AUTH=false
- DRONE_SECRET_SECRET=${DRONE_SECRET_SECRET}
DRONE_GITHUB_CLIENT_ID
: 在Github中创建OAuth Application
时生成的Client ID
DRONE_GITHUB_CLIENT_SECRET
: 在Github中创建OAuth Application
时生成的Client Secret
DRONE_SERVER_PROTO
: Drone提供服务的prototype,可选为http
或https
DRONE_SERVER_HOST
: Drone的server地址,设置为127.0.0.1
作为本地地址,也可以设置为外部可访问的域名或IP地址DRONE_TLS_AUTOCERT
: 设置是否自动开启安全传输层协议,若设置为true
,那么drone server proto会设置为使用https
,DRONE_SERVER_PROTO
设置为http
也是无效DRONE_RUNNER_CAPACITY
: drone提供服务的最大并行度DRONE_SECRET_SECRET
: 可自由设置 docker-compose up
或者通过后台的方式运行:
docker-compose up -d
使用github账户登陆之后,浏览器被重定向回drone,并被授权访问你的github仓库
选中你要配置的仓库,点击ACTIVATE
按钮,进入SETTINGS
卡片,点击ACTIVATE
按钮开启这个仓库.开启之后可以设置CI
任务的基本配置。用过jenkins
的人会发现,这个页面显然简洁一点。
此时,github仓库中会添加一条webhook地址,当github仓库发生改变时会通过webhook通知drone server。
不过,问题是这个webhook地址是DRONE_SERVER_HOST
,如果配置为127.0.0.1
或外网不可达时,这个webhook
地址github是访问不到的。不过这不影响Cron Job
的触发。
配置里面有四个主要选项
Main: 主要配置
Secrets:
如Drone Secret文档中所说,不方便明文存储到代码仓库里的密码值,可以通过Repository Secrets
,Encrypted Secrets
和External Secrets
来存储
这里的Secrets设置可以指定Repository Secrets
,在Secret Name
中指定密码名称,Secret Value
中设置该值。Allow Pull Requests
是指,当是pull_request
请求时这个密钥是否可被使用,因为其他人可能会通过pull request
来触发CI,造成安全隐患。
在.drone.yaml
中可以通过from_secret
引用,如下面的username
和password
kind: pipeline
name: default
steps:
- name: build
image: alpine
environment:
USERNAME:
from_secret: username
PASSWORD:
from_secret: password
Cron Jobs:定时任务
这里可以通过任务名称,分支名称和时间指定定期的CI任务。前文提到,CI触发有三种规则轮询
,定期
和推送
。
注:但这里的定期任务稍微有点怪,cron job的执行逻辑是定期触发一次检查,事件是指定分支的最后一次事件,执行的pipline会验证trigger
规则,不像是通常说的定期任务,也不能说是轮询,因为轮询是监测是否有新事件。
Badges:编译状态图标
这里提供了CI运行的状态图标,可以放到Git仓库里作为编译状态。不过Drone server的地址就不能简单的设置为127.0.0.1
了,因为Github访问不到,需要一个外网IP或域名
Drone通过Pipline的方式来声明CI的执行过程,如文档所示。
kind: pipeline
name: api
steps:
# api unit test
- name: api-test
image: node:11
depends_on: [clone]
commands:
- cd ./api/
- npm install --registry https://registry.npm.taobao.org
- cd ./dgc_sdk && npm install --production
- cd .. && npm run test
# web lint
- name: web-lint
image: node:10.15.1
depends_on: [clone]
commands:
- cd ./web
- npm install --registry https://registry.npm.taobao.org
- npm run lint
trigger:
branch:
- master
event:
- pull_request
- push
---
# stream test
kind: pipeline
name: stream
steps:
- name: stream test
image: ccr.ccs.tencentyun.com/star/stream-test-base
commands:
- echo 'Hello!'
trigger:
branch:
- stream
event:
- pull_request
steps指定CI执行的步骤,默认pipline或创建一个叫做clone
的步骤,它是从git仓库克隆代码大步骤
多个step之间可以通过depends_on
来指定执行顺序,比如先clone
,后build
,然后deploy
同一个pipline
下的多steps之间默认是串行的,实现方式应该是下面的stepdepends_on
紧邻的上一个step
多pipline
之间是并行的,同一个yaml
文件里使用---
分割多个pipline
的定义
triggers是指在什么情况下才会执行ICI任务,比如只对master
分支的pull request
和push
事件触发
在每一个step
中,可以通过Conditions
来指定在CI过程中是否执行该step,通过when
关键字指定。trriger
是指定pipline
何时被执行,condition
指定pipline
中的step
是否被执行,如:
kind: pipeline
name: default
steps:
- name: build
image: golang
commands:
- go build
- go test
when:
branch:
- master
- feature/*
Cron Job
,那到到该时间点时,会触发CI的任务,此时pipline
中的trigger
规则会失效event
都会监控CI的状态trigger
中指定event
为pull_request
时,使用的分支为target branch
;当trigger
中指定event
为tag
时,指定的branch
规则是无效的Project settings
设置为Protected
后,每次CI任务都要手动确定