CI/CD 是 Continuous Intergration/Continuous Deploy 的简称,翻译过来就是持续集成/持续部署。CD 也会被解释为持续交付(Continuous Delivery),可是对于软件工程师而言,最直接接触的应该是持续部署。php
我刚开始工做时,就有接触过CI的概念,那个时候主要是团队 QA(质量保证)使用 hudson 对工程进行质量扫描,跑一些基础的自动化测试。当时印象最深的一幕就是 QA 对我说:”你的代码静态告警了,赶忙改一下...“。html
如今一想,我不由感到诧异,”咦?咱们当时没有用 ESLint 吗?记不清楚了...“因而我翻了下 ESLint 的更新记录,发现那时候 ESLint 的大版本号才刚到3,VSCode 的 ESLint 插件也仍是比较早期的版本,可能还没普及开吧。前端
后面我也慢慢地听到了 Jenkins, Travis CI 这样一些名词,可是因为太菜,我一个都不会用。node
并且我发现,我对 CI/CD 并无什么兴趣,为何呢?由于我尚未使用它的动机。linux
构建/部署那些事构建/部署说的简单点,就是先利用 webpack 或者 gulp 这类的工具把工程打包,而后把打包获得的文件放在服务器上某个托管静态资源的 Web 容器里,像 Java 就能够放在 Tomcat,不过如今流行用 Nginx 托管静态资源。有了 Web 容器,前端打包的那些文件(好比index.html, main.js等等)就能够被访问到了,这个相信你们都懂。webpack
16年~18年时,我还不负责打包部署这些事(另外一方面也是由于前端根本没权限碰服务器啊,emmm...),因此我压根没关注打包部署这些事情。nginx
18年到19年时,我开始负责打包部署了。当时彻底没这方面经验,Linux 命令都是靠着一边百度一边敲。不过我清楚地记得,以前在测试组那间办公室看他们用的是xshell和xftp,把这俩工具搞来用后,我以为部署真是简单,我只要跑个脚本,安静地等 webpack 和 gulp 的工做流结束后,把文件经过 xftp 传到服务器就行,只要注意不要操做出错就好了(显然,人为操做就容易出错,这也是个隐患)。因为构建部署的频率不高,项目数量也不是不少,这一年我基本应付得过来。git
直到去年,我手底下有差很少5个项目,接近10个前端工程。在这种平常部署节奏下,我以为 xshell+xftp 也救不了我,虽然这些项目不是每天都发版上线,可是测试环境仍是常常发的,天天光部署这事我就够烦躁,写代码常常被打断,并且也很是浪费时间。web
我想着要寻求些改变了,但我仍是没考虑 CI/CD 这事,由于我以为我好像仍是不太懂 CI/CD。因而我考虑先用 shell 脚本来作构建/部署的事情,因此后来就有了这么两篇探索性的文章:shell
靠着这一波脚本的探索,我基本上也是过渡到半自动化的阶段了,这种焦虑的情况基本上获得了一些缓解。可是,我发现个人电脑仍是扛不住,风扇急速旋转的声音能让我自闭。。。毕竟一边跑本地开发环境,一边还可能同时跑1~2个工程的构建/部署脚本,再加上电脑运行的其余软件,这发热量你懂的!
因此,构建/部署这活不该该由个人电脑来承担,它太累了。
并且,我也不想手动触发部署脚本了,太累了,是时候让代码学会本身部署了。也就是这个时候,我对 CI/CD 就有了诉求。
因为咱们的代码是托管在自建的 gitlab 服务器上,因此 CI/CD 这块我直接选择了用 gitlab 自带的 CI/CD 能力。工做之余,我差很少花了两天时间去熟悉gitlab CI/CD的文档[3]。
而后我按照文档先把环境搭建好,接着一遍遍地调试.gitlab-ci.yml
配置文件,我记得第一次成功跑完一个 Pipeline 前,我一共失败了大概11次,这个过程挺折磨人,有时候你就是不知道到底哪里配错了。
不过调通这个流程后,你就会以为这整个试错的过程都是值得的。Nice!
其实我前面也提到了,一个版本发布的过程,主要就是分为如下几个步骤:
package.json
的 scripts
中了,我这儿定义的命令是 build:prod
,因此只要运行 npm run build:prod
就好了。而 CI/CD 作的事情就是:用自动化技术接管流程。
监控Mutation个人诉求是:当代码合并到某个分支后,gitlab能自动帮我执行完打包和部署这两个步骤。
因此,首先就必须有代码变更的监控能力。这个确实有,若是你有关注过git hook[4],就知道这是能够实现的。
并且,绝大部分代码托管平台都提供了 webhooks,能监控很多事件,好比 push 和 merge。
这也就是说,即使不使用代码托管平台提供的 CI/CD 能力,开发者也有能力实现本身的 CI/CD 机制。
ps:固然,除了 CI/CD,作短信/邮件通知也是可行的,只要你敢去尝试,基于平台开放的能力,咱们能作不少事情。自研 CI/CD 的事情咱们就不去搞了,人家造的轮子已经6翻了,直接拿来用。
回归主题,只要我监控到代码变更了,服务器端自动执行构建/部署脚本便可。
Gitlab CI/CD是怎么工做的软件服务于生活,也源于生活。Gitlab CI/CD 设计了不少概念,其中我以为最有意思的是:Pipeline 和 Runner。
Pipeline是CI/CD的最上层组件,它翻译过来是管道,其实你能够将之理解为流水线,每个符合.gitlab-ci.yml
触发规则的 CI/CD 任务都会产生一个 Pipeline。这个概念就有点像工厂中的车间流水线了,咱们知道车间中有不少条流水线,不一样的流水线可能会处理同一类型的生产任务,也可能处理不一样类型的生产任务。当一条流水线空闲的时候,就有可能会被用来安排执行其余的生产任务。而 Gitlab 的 Pipeline 虽然没有空闲的概念,一个 Pipeline 执行结束后也不会被复用,可是会将资源让出来给其余的 Pipeline,因此和车间流水线也有殊途同归之妙。
有了流水线,还必须有辛勤的工人进行生产做业,Runner在 Gitlab Pipeline 中就扮演着工人角色,根据咱们下达的指令进行做业。
在 Gitlab 中,Runner 有不少种,分为Shared Runner, Group Runner, Specific Runner。
工人是要持证上岗的,一样地,Runner 有一个注册的过程,就至关于在工厂中入职登记的意思。具体见Registering runners[5]。只有合法注册的 Runner,才有资格执行 Pipeline。不过,Gitlab 好像没给 Runner 发工资啊!
流水线和工人都安排好以后,就必须制定车间生产规章制度了。一条流水线到底怎么干活,总要有个规矩吧,你说呢?
没错,.gitlab-ci.yml
文件就是来制定规则的!其实我要求的 CI/CD 流程并不复杂,只要帮我把构建和部署两步搞定就好了。下面以一个简化的生产环境构建部署流程为例说明:
workflow: rules: - if: '$CI_COMMIT_REF_NAME == "master"' stages: - build - deploy build_prod: stage: build cache: key: build_prod paths: - node_modules/ script: - yarn install - yarn build:prod artifacts: paths: - dist deploy_prod: stage: deploy script: - scp -r $CI_PROJECT_DIR username@host:/usr/share/nginx/html
首先,我但愿只在 master 分支进行构建/部署做业,这个能够经过workflow.rules
下的if
条件约束完成。
而后,我但愿把整个过程分为两个阶段执行,第一个阶段是build
,用于执行构建任务;第二个阶段是deploy
,用于执行部署任务。这能够经过stages
来完成定义。
接着,我定义了两个job
,第一个job
是build_prod
,属于build
阶段;第二个job
是deploy_prod
,属于deploy
阶段。
在buiild_prod
这个job
中,主要是运行了yarn install
和yarn build:prod
两个脚本,打包生成的文件资产会根据artifacts
的配置保存下来,供后面的job
使用。
在deploy_prod
这个job
中,主要是经过scp
命令向 linux 服务器上的 nginx 目录下传输文件。
这个简单的 Pipeline 配置示例其实应用的是 Basic Pipeline Architecture,只不过示例中每一个 stage 只定义了一个 job。
Gitlab 经过 Variables 为 CI/CD 提供了更多配置化的能力,方便咱们快速取得一些关键信息,用来作流程决策。上述示例中的$CI_COMMIT_REF_NAME
和$CI_PROJECT_DIR
就是 Gitlab 的预约义变量。
除了预约义变量,咱们也能够自行定义一些环境变量,好比服务器 ip,用户名等等,这样就免去了在配置文件中明文列出私密信息的风险;另外一方面也方便后期快速调整配置,避免直接修改.gitlab-ci.yml
。
在不一样主机间经过scp
传输文件须要创建信任关系,在 CI/CD 中最好选择免密方式,其基本原理就是把 ssh公钥 交给对方。而这一点我在自动化部署的一小步,前端搬砖的一大步[1]这篇文章中也提到了,这里就再也不赘述。
因为我是将 Runner 直接部署到了 Gitlab 代码服务器上,而我司配的这台代码服务器的配置自己就不高,用来跑高 CPU 占用的构建部署 Pipeline 仍是有点吃力的,有时候 Pipeline 跑起来甚至直接把 Gitlab 的 Web 服务搞崩了。
队友问我:”怎么 Gitlab 白屏打不开了?“
没过多久,领导那边给我发了一台 Linux 服务器,专门给前端搞平常工做用的。bingo,我就顺手把 Runner 独立部署到新机器上了,这样就不会影响队友了,并且每次发版时间直接从 8min 缩短到 2min 之内,简直 Nice!
直观来看,个人重复劳动被去除了大部分,多出来的这部分时间我能够用来干更多有意义的事情,或者摸鱼它不香吗?并且,天天不用手动发版,心情也是倍儿棒!
此外,因为 CI/CD 采用自动化做业方式,只要脚本写对了,几乎不会出错,出生产事故的概率也就大大下降了。
小结本文从笔者的一些亲身经历出发,回忆了笔者在构建/部署过程当中遇到的痛点,并围绕一个最基础的Gitlab CI/CD案例,讲述了笔者使用 CI/CD 来解决这些痛点的过程。虽然本文的主角是Gitlab CI/CD,但它和其余代码托管平台的CI/CD在思路上是相似的,掌握了一个,举一反三也就不难。而且,利用 Pipeline 这类工具,咱们还能够作更多事情,好比持续集成+自动化测试。这就考验你们的想象力了,剩下的就交给聪明的读者啦!