Drone CI 源代码走读

开篇

使用开源工具的好处是,可以通过阅读源代码,深入了解工具的运行原理,可以更好的使用和掌握工具,遇到问题能更好的定位。阅读源代码,往往比阅读文档更加高效,尤其在遇到复杂的问题,代码才是最好的文档。

drone是用golang开发的,golang本身入门简单,方便掌握,golang本身更强调工程实用性,golang写出的代码相对更直接,好理解。
Drone代码量不是很多,结构很清晰,如果对Drone基本流程比较熟悉的话,很容易能把源代码顺下来。

drone 代码扩展性很好,作为开发人员可以很容易的定制自己的功能,如扩展yaml pipleline的语法,扩展权限管理系统等,从而更高效率的使用drone CI。我后边会写一系列的文章来由浅入深的介绍drone源码。

本篇为基础篇将从主体核心逻辑来讲解,从代码角度过一下drone的触发和build流程,不会深入太多细节。

建议对drone本身有一定使用经验,并且阅读过我前两篇文章,再来阅读这篇文章。

正文

为了便于理解,我会结合drone 的web UI 的操作,分布讲解UI中的操作背后触发的代码逻辑,给读者更好的直观感受,更好的理解代码。本文只会涉及核心的代码逻辑流程,不会过多深入代码细节。

名词解释:
scm 源代码管理工具 如github gitlab

同步repos列表:

以gitlab为例,首先通过gilab的oauth2 authorization flow授权进入主页,点击syncer按钮, 实现repo list的同步,这个过程实际是调用后端service/syncer/syncer.go 文件Sync 方法实现本地数据库repos 数据和scm remote的数据的同步,通过RepositoryService获取scm列表信息,然后将数据更新到repos数据库表中。

激活repo

在同步完的Repositories列表中,选择想要的repo,点击active按钮,进入repo的详细页面,点击Activate repository实现repo的激活。实际上通过API执行了handler/api/repos/enable.go中HandleEnable方法,该方法主要是:

  • 更新repos数据库表对应的repo的数据状态
  • 调用scm api将drone的webhook api注册到scm中,当scm接收到对应事件(用户commit并push代码)会给注册进来的所有webhook API发送消息,调用注册的web API方法。
   // 调用api的方式激活scm对应repo的webhook功能
  err = hooks.Create(r.Context(), user, repo) 

实际是调用 RepositoryService 中DeleteHook和CreateHook

Drone中所有和scm交互的代码都在go-scm这个包中,go-scm为多种scm提供了统一的操作接口, 目前支持 gogs bitbucket gitea github gitlab 等scm系统
https://github.com/drone/go-scm

buid执行流程:

当用户commit并push代码到scm中,scm就会触发第二步注册的drone API,该API实际上是执行handler/web/hook.go HandleHook方法,HandleHook方法是所有drone build流程的起点。HandleHook功能主要是,根据scm触发的webhook类型不同(如PushHook TagHook)构建出对应的core.Hook core.Repository数据结构,再用这个core.Repository 对象找到对应的数据库对象

repo, err := repos.FindName(r.Context(), remote.Namespace, remote.Name)

。然后将这两者当做参数传递给tiggerer.

builds, err := triggerer.Trigger(ctx, repo, hook)

Trigger(trigger/trigger.go)方法利用ConfigService找到drone config文件也就是drone.yaml

raw, err := t.config.Find(ctx, req)

,然后对done.yaml文件进行解析,对pipeline类型的Resource进行处理,根据skip条件过滤掉相关的pipeline,利用pipeline数据构造stage对象,构造build对象,然后将build对象和对应生成的stage对象,以及他们之间的依赖关系,分别存入数据库。然后stages列表循环调用schedule方法,来schedule stage。

  err = t.sched.Schedule(ctx, stage)

schedule依据三种runtime环境 docker k8s nomad,目前有三种实现,这里介绍常用的两种。

  1. 基于docker的默认运行方式
    启动多个runner进程(默认值是2,可以配置),每个进程不停的从server(db )中轮询、获取待执行的build然后执行
    operator/runner/runner.go
func (r *Runner) Start(ctx context.Context, n int) error {
    var g errgroup.Group
    for i := 0; i < n; i++ {
        g.Go(func() error {
            return r.start(ctx)
        })
    }
    return g.Wait()
}
  1. 基于k8s运行时的方式
    以scheduler\queue\kube为例,程序在Trigger 中执行 Schedule 方法,实际就是调用k8s API,构建一个k8s job,用drone-controller作为镜像,将stage id通过环境变量传过去,然后启动container,在这个drone-controller节点执行整个stage的build流程。drone-controller (cmd/drone-controller)主要功能是调用runner.Runner(operator/runner.go)控制执行stage build流程。

build实际执行主要流程

Run(operator/runner.go )是核心运行函数,Runner对象是核心对象,负责获取,解析和执行实际的build,并且实时更新build状态到数据库。

Drone yaml解析、运行基本流程

将drone yaml 转成drone-runtime使用的数据结构spec(drone-runtime包 engine/spec.go),再转换为go-docker api 使用的数据结构(container.Config container.HostConfig network.NetworkingConfig container.DeviceMapping),调用 docker go api 利用解析后的参数运行相关step。

drone build 实际执行核心代码在包drone-runtime包中,

Engine

Engine定义用于pipeline step的运行时引擎,是drone pipeline 定义的step的实际执行者。对应有docker 和k8s两种运行时。

Docker运行时环境(engine/docker)

对于docker api进行封装,实现container的构建的过程(共享临时volumes创建,网络环境的创建,container的文件拷贝,container创建并执行,container wait ,container销毁,日志获取等功能)

Runtime

Runtime 负责执行整个drone config pipline,解析配置文件,如果各个step之间没有依赖关系,就按照顺序执行的方式执行,否则根据config 定义的 depdon关系创建一个,有向非循环图,按照并行拓扑顺序运行对应step。理解有向非循环图,可以更好的理解step并行执行如何定义和实现,怎们通过不同的depdon来实行step并行,这种有向非循环图方式从学术上更专业了,但是比之前通过配置group的方式要难理解一点,但是如果从理伦方面了解了相关概念其实还是很好掌握的。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,902评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,037评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,978评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,867评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,763评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,104评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,565评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,236评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,379评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,313评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,363评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,034评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,637评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,719评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,952评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,371评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,948评论 2 341

推荐阅读更多精彩内容