1.0 前言
上节,我们介绍了 Koa 项目的部署,大家可以发现我们是手动执行各种命令来控制整个流程的,在实际开发过程中,每次都要去各种服务器上操作这些是很麻烦的,而且还容易出错,所以就有了持续集成,把这个流程工程化,这个流程就叫 CI/CD
CI(Continuous Integration) 简称持续交付,意思是新增代码后自动校验代码格式,打包,构建,跑单测,单测覆盖率,对应我们前端常见的就是 ESLint,Webpack 打包,各种脚本。
CD(Continuous Delivery)简称 持续部署,意思是 经过 CI 后,代码自动部署,对应前端的常见的是 打包后,自动发布到 oss,刷新cdn。
常用的 有 Jenkins,Gitlab CI/CD,Github Action,一般公司中都会用用到 Gitlab CI/CD,然后结合它提供的持续集成功能,接下来我们就讲讲 基于 Gitlab 的持续集成。
2.0 Gitlab CI/CD 简介
2.0.1 简单介绍
GitLab 中默认开启了 CI/CD 的支持,且使用 YAML ,通过根目录的 .gitlab-ci.yml 来描述管理项目构建配置,我们只需要在 .gitlab-ci.yml 配置文件中定义流水线的各个阶段,以及各个阶段中的若干任务就可以了。
比如下面这个最简单的配置:
image: node:latest
stages:
- test
test
stage: test
script:
- echo 'hello,world!'
这样 代码 push 到 Gitlab 后,会自动执行这个任务,我把这个 Demo 放到 Gitlab 公网上了,大家可以看下实际效果。
打开 gitlab 项目的地址,点击 左侧的 CI/CD下就能看到构建信息。
点击详情可以看到:
这里面就有我们刚才 echo ‘hello,world!’ ,那我们 echo 换成 npm install, npm run build,就换成了我们执行的执行的 npm 命令,这样不把我们的项目串联起来了么。
2.0.2 .gitlab-ci.yml 一些常用属性
.gitlab-ci.yml 包含了很多配置文件,接下来我们讲讲一些常用的配置,我们根据一个常用的配置来介绍。
# image 标记 使用的 docker 镜像,这里我们使用 nodejs 镜像
image: node:latest
# variables 是定义环境变量,可以在直接获取
variables:
HCNAME: "hucheng"
cache:
paths:
- node_modules/
# stages 定义 执行步骤,包含了需要执行的job,类似第一步干嘛,第二步干嘛,接着干嘛
stages:
- install_deps
- build
- deploy
# install_deps 就是job,job下面的 stage 字段和上面一一对应起来
install_deps:
stage: install_deps
only: # 这里的 only 标记 在下面3个分支下面,push代码后,执行当前job,,only 支持 branch,tag,change,正则
- develop
- preview
- master
script: # script 就是你要执行的脚本了
- echo $HCNAME && npm install
build:
stage: build
only:
- develop
- preview
- master
artifacts: # artifacts 标记,当前job 执行完成后,在 gitalb 网页可以下载的文件,会出现个下载按钮,可以下载这个目录
paths:
- ./dist
script:
- npm run build
deploy:
stage: deploy
only:
- develop
- preview
- master
script:
- npm run publish
stages
例子中 stages 值为一个数组(p.s. 用 - 代表数组和 markdown 类似)。包含了三个 job,test, build, deployr 分别实现自动测试,打包项目和部署。下方的 stage 必须在全局定义的 stages 内。
variables
值为键值对象,为了后续的流程,此处定义了开发项目和部署项目的 namespace 和 repo_name。同 shell 类似,后续使用其值需要加上 $ 符号。定义的变量也有对应的作用域,定义在顶层就可以作为全局变量供所有 job 使用,如果是一些 job 特有的变量,就定义在 job 内部。gitlab 默认提供了很多全局变量给我们使用,常用有:
name: CI_PROJECT_NAME,
namespace: CI_PROJECT_NAMESPACE,
path: CI_PROJECT_PATH,
url: CI_PROJECT_URL,
repo: CI_REPOSITORY_URL,
tag: CI_COMMIT_TAG,
before_script
值为数组,每一个元素其实就是一个 linux 命令,写的时候装作自己在写 shell 就好。该部分主要生成了后续构建需要的镜像标签,切换当前目录等。为了 debug 方便,这些变量最好打印。类似的,如果在 job 完成后有一些时候操作,可以定义 after_script。需要注意的是如果定义在顶层,内部的命令会在每个 job 运行之前执行,如果某些 job 需要特别的预操作,可以在 job 内部再配置一个 before_script 对象,它会复写外部的全局预操作。
test_stage
stage
job
对应的 stage
,如果有多个 job
对应同一个 stage
,在执行时会并行执行这些 job
。
script
这个 job 执行的命令,此处是进入的项目仓库目录,并且执行了一个 shell 脚本,这个脚本定义了执行项目的所有单元测试。一般建议如果要执行的命令过多,就把这些命令写成脚本放在项目内。CICD 流程直接执行这个脚本。
only
only
指明了 job
的执行场景,可以是分支名。
3.0 Koa 结合 .gitlab-ci.yml
.gitlab-ci.yml 配置文件如下:
image: node:latest
cache:
paths:
- node_modules/
stages:
- install_deps
- deploy
install_deps:
stage: install_deps
script:
- npm install
deploy:
stage: deploy
only:
- tags
script:
- sh ./deploy
这里我们分为 2 个步骤,当在 Gitlab 上 打完 tag 后 触发构建,先执行 npm install 获取依赖,接着执行 deploy 的 shell 脚本,我们看看 shell 脚本里面具体内容。
domain_name=koa-test
app_dir=/data/app
app_name=koa-test
ip=xxx.xxx.xxx.xxx
ssh work@$ip "mkdir -p ${app_dir}/${domain_name}/releases/${CI_COMMIT_TAG}"
rsync -az ./ --exclude .git --exclude .gitignore work@$ip:${app_dir}/${domain_name}/releases/${CI_COMMIT_TAG}
ssh work@$ip "ln -snf ${app_dir}/${domain_name}/releases/${CI_COMMIT_TAG} ${app_dir}/${domain_name}/current"
ssh work@$ip "cd ${app_dir}/${domain_name}/current && npm run start:prd"
npm run start:prd 对应 package.json 是:
"scripts": {
"dev": "cross-env NODE_ENV=dev nodemon bin/www",
"start:prod": "cross-env NODE_ENV=dev && pm2 delete koa-test || true && pm2 start ./bin/www --watch --name koa-test",
"lint": "lint-staged"
},
上面的 ip 表示我们的 ECS 服务器的IP,根据 tag ,把构建好的文件通过 ssh 把文件放到对应的目录下,然后 通过 pm2 启动这个项目。
这样通过 Gitlab CI/CD 我就完成了,当前项目的构建,部署。整个流程打完 tag 后自动触发,不需要人为参与,完成了整个流程。
4.0 小结
这节我们学习了 Gitlab CI/CD 的介绍,结合 Koa 项目的基本使用,大家可能本地没有这些环境,但是可以理解下,在实际工作中用的非常频繁,可以参照 Demo 看看,Demo 链接。