GitLab CI 示例:构建 & 测试 Node.js 应用

通过解释说明一个简单的 Node.js 应用的 Pipeline 示例来介绍 GitLab CI 的工作方式和使用。

其中会重点介绍 GitLab CI 的执行过程,Stage Job 等基础概念,以及缓存策略。

示例定义

下面是一个简单的 Node.js 应用的 pipeline 定义:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# .gitlab-ci.yml
stages:
- build
- test

cache:
paths:
- node_modules/

build_job:
image: node:10
stage: build
script:
- npm version
- npm install

test_job:
image: node:10
stage: test
script:
- npm run test

解释说明

逐一介绍一下这几个字段:

stages

1
2
3
stages:
- build
- test

stage 定义了 pipeline 的执行步骤,也就是说 stages 是有序执行的。每个 stages 可包括多个 Job,Job 才是 CI Runner 要执行的任务。

上面的 pipeline 包括 build 和 test 两个步骤,先执行完所有 build 阶段的 Job,才会执行 test 阶段的 Job。

如果 build 阶段的 Job 执行失败了,则整个 pipeline 失败并中断执行,不会继续执行 test stage 了。

下面就来介绍什么是 Job.

build_job

1
2
3
4
5
6
build_job:
image: node:10
stage: build
script:
- npm version
- npm install

build_job 是 Job 的名称,可以自由定义;

stage 字段指定该 Job 属于 build 阶段的;

script 就是自定义的构建脚本了,这里就是简单的 npm install

image 这个是指定 script 脚本的执行环境,它的值应该是一个 Docker 镜像。

Runner 开始执行这个 Job 时,首先会 pull 项目的最新代码,然后基于这个镜像启动一个容器并把代码挂载到容器里,最后在这个容器里面执行 script 定义的脚本。因为我们这里使用的是 node:10 作为作业的镜像,所以在 script 里才可以直接用 npm。

test_job

1
2
3
4
5
test_job:
image: node:10
stage: test
script:
- npm run test

test_job 同样是一个 Job,它属于 test stage,在上面的 stages 定义中 test 是在 build 之后的,所以它会等所有 build 阶段的 Job 执行完之后才会被执行。

重点来了:每个 Job 是独立执行的,互相隔离的。 Runner 在执行 test_job 的时候,会重新 pull 应用的最新代码,然后启动一个新容器并挂载代码,再在里面执行 script 脚本。

这就会导致一个问题: 在 test_job 中我们并没有执行 npm install 就直接执行了 npm run test,理论上会是报错的!

这就要介绍最后一个未介绍的字段 cache.

cache

1
2
3
cache:
paths:
- node_modules/

cache 是 pipeline 中定义 Job 之间的缓存的;

我们这里定义的 cache 是全局的,即作用于所有 Job 的;

paths 定义需要缓存的目录,若需要,你可以指定多个;

缓存的逻辑是这样的:

- 执行 build_job 时会检查之前无有缓存
- 如果有缓存就下载到 `paths` 指定的缓存目录,无则忽略
- build_job 执行结束之前,会重新把缓存目录缓存起来
- test_job 执行之前,同样检查有无缓存,有则下载

所以,test_job 的 script 中没有执行 npm install 是因为我们将 node_modules 目录缓存了。

缓存是提高 Job 执行效率的策略,不仅仅是多个 Job 之间;

同一个 Job 在多次 pipeline 中也会共用缓存,意思是:

- build_job 第一次运行时并没有缓存
- 下次 pipeline 执行时,npm install 就会基于缓存的 node_modules 更新,而不是全量下载了

总结

通过这个示例,基本就了解 GitLab CI 的工作过程和定义方式了;

其中缓存策略是非常常用的,这里使用的是全局缓存,还可以指定某个 Job 特有有缓存策略。

想进一步了解缓存,请查看官方文档关于缓存的详细说明:
https://docs.gitlab.com/ee/ci/yaml/README.html#cache

这个简单的示例,只是展示了 Node.js 应用的构建和测试,一个更完整的 CI 流程通常还会包括 部署(deploy),接下来会继续通过示例讲解使用 GitLab CI 的更多使用。