由于公司有两地研发团队,在统一CI/CD上难度不亚于两家公司合并后的新流程创建,并不是不可攻克,简单描述下心得。html
首先,代码管理使用gerrit -> 因其强大的 codereview 功能被选中为 codebase 的选型,并且,咱们依赖于 gerrit event 触发流程,取代沟通基本靠喊的简单粗暴的方式。前端
关于 gerrit event 介绍,请参考node
https://gerrit-review.googlesource.com/Documentation/cmd-stream-events.htmlpython
本来,CI/CD 流程是重度依赖 jenkins 及其插件。但因 jenkins 的排队处理,及其插件 gerrit-trigger 的 miss 率达到将近 10%(针对本公司 gerrit 提交状况),致使 CI/CD 流程没法得到指望中的推广效果,故抛弃 jenkins 插件,下降 jenkins 使用权重,下降替代 jenkins 的成本 json
使用 python 开发 gerrit client, 监听 gerrit event 事件(目前只处理 PatchSet Create & ChangeMerged ) app
监听 gerrit event:ssh
def run(self):
host = self.config.get("gerrit_host", "example.net")
user = self.config.get("gerrit_user", "engineer")
port = int(self.config.get("gerrit_ssh_port", "29418"))
fkey = self.config.get("gerrit_key_file", None)
etyp = self.config.get("gerrit_event_types", "").split(",")
events = queue.Queue()
listener = StreamEventListener(events, user, host, port, fkey)
listener.set_event_types(etyp)
listener.set_logger(self.logger)
listener.start()
while True:
e = events.get()
handler = GerritStreamEventHandler(e, self.logger, self.config)
handler.start() maven
eg:工具
if "patchset-created" == etype:
taskQueues[project][cs].put(self.event)
taskQueues[project][ut].put(self.event)
elif "change-merged" == etype:
#change-merged,启动ci构建jobpost
url = 'http://127.0.0.1:9091/citrigger'
param = {"event":event}
header = {"Content-Type": "application/json"}
response = requests.post("http://127.0.0.1:3200/", json=param, headers = header)
log_trigger_fmt = "Trigger ci job on [{}], ref: {}, event created {}, responses :{}"
self.logger.info(log_trigger_fmt(project, ref, etime, response))
此处,经过使用自行开发的EventListner 及 handler,替代 jenkins 中 gerrit trigger的功能,解决了 miss 的问题!
另外,发布系统做为前端展现及任务调度的部分,能够完成数据统计,针对某个提交进行重复构建,记录发布历史,统一公司项目结构进行的技术限制,保证高度统一。
经过 trigger 的转发及过滤,能够确保每一次开发的提交在通过submit后获得构建,构建使用的工具仍是采用了 jenkins (天坑jenkins,之后会丢掉的),经过参数化构建的方式,并依赖于公司内同一类型的项目的构建方式统一 (nodejs, maven, gradle),消息处理,更新模板,建立job, 更新job, 这个部分由一个独立的服务来维护, 服务与 jenkins 通讯,维护 jenkins 中 job的配置信息。
json:"app_id"
Project string json:"project"
TaskId string json:"task_id"
Ref string json:"ref"
}json:"Ref"
TaskId string json:"TaskId"
AppId string json:"AppId"
Project string json:"project"
Module string json:"Module"
}json:"app_id"
Project string json:"project"
Type string json:"type"
Module string json:"module"
SzOrSh string json:"SzOrSh"
}