Gitlab

最近离职,一张机票跨越小半个中国,来魔都找了一份喜欢的工作。稳定了就开始继续写东西啦 👯‍

毕业实习的时候在公司里面积极推 Git,考虑到同事的学习成本,在 GogsGitlab 之间,我选了 Gogs,不为别的,只为原生中文 😂。然后一大段时间,我都是在 Github 和 Gogs 这两个平台进行协作的,Gitlab 的大名也不时的在耳边响起。

现在的公司版本控制用的是 Gitlab,所以借此机会我也简单适应了一下,其实和 Github 差不太多,更多的是 Gitlab 提供了一整套的解决方案,其中就包含了 CI/CD。

我还是比较崇尚那句话的:一切能自动化的工作都应该被自动化掉!

.gitlab-ci.yml

在 Gitlab 官网上有很多关于 gitlab CI 如何搭建的介绍,在此我就不多做介绍了,就是照着代码敲到命令行执行即可,现在要讲的是如何配置一个简单的 Gitlab CI 配置文件。

.gitlab-ci.yml 这个文件即是 Gitlab CI 的配置文件,你需要将这个文件放到你 repo 的根目录即可,然后你每次提交, Gitlab 都会自动地去读取执行该文件的内容,如果你提交了一个新的 .gitlab-ci.yml,那 gitlab CI 会使用你刚提交的那份配置文件进行 CI

下面就贴一份简单的用于部署前端项目的 .gitlab-ci.yml 文件:

1
# 这个是我现在项目初期使用的一个配置文件
2
# 下面我就开始简单的讲一下各个配置的作用
3
# yml 文件支持注释,像当前文字这样,左侧以 # 号开头即为注释
4
5
# 下面这个是表示,我们运行 CI 用的镜像是 kkarczmarczyk/node-yarn:latest
6
# 因为我司的 CI 任务是选的在 Docker 上运行,所以每次执行 CI 任务的时候,都会新启动一个 Docker 容器
7
# 然后在容器中依次执行下面的命令
8
# 注意:不同的 stage 执行前,都会将该容器环境设置为初始化时的状态
9
image: kkarczmarczyk/node-yarn:latest
10
11
# 定义全局的缓存策略,如上所说,每个不同的 stage,CI 都会重新启动一个新的容器,所以我们之前 stage 中的文件都会消失
12
# 那在前端开发中,就意味着每个 stage 都要重新完整装一次 node_modules,这样的时间和网络成本都不低
13
# 所以我们选择将这些文件缓存下来
14
# 但是,缓存也要讲究实效性,例如我在第二次的提交中增加了一个库,那第二次的 CI 就不能再重复使用上一次的 node_modules 缓存了
15
# 在 .gitlab-ci.yml 中,我们通过设置 cache 的 key 来区分不同的缓存
16
cache:
17
  # 该 Key 的值为一个系统变量,gitlab 在运行的时候内置了不少的系统变量供使用,下面的配置表示
18
  # 以每次提交的 ref 号为 key 来区分不同缓存,效果就是同一次提交中的所有 stage 用同一份 cache
19
  key: ${CI_COMMIT_REF_SLUG}
20
21
# 定义 stage,stage 可以简单的理解为“步骤”,会顺序执行,如果上一步错了,那不会继续执行下一步
22
# 比如像下面我定义的,第一步先初始化,第二步检查代码规范,第三步进行单元测试,第四步构建,第五步就直接将项目部署到服务器
23
stages:
24
  - init
25
  - lint
26
  - unit_test
27
  - build
28
  - deploy
29
30
# 这个是某个任务的名称,你可以随意起名
31
install_packages:
32
  # 指定该任务所属的步骤,每到一个步骤,该步骤所对应的所有任务都会并行执行
33
  stage: init
34
  # 指定要缓存的文件以及文件夹
35
  cache:
36
    # 这个属性是 gitlab 比较新版本里面加的特性,意思是在这一步,我只上传这个缓存,我不会拉取该缓存
37
    policy: push
38
    # 指定缓存的内容,在下面我缓存了 node_modules 这个文件夹,你还可以在下面继续添加文件或者文件夹
39
    paths:
40
      - node_modules/
41
  # 该任务要运行的脚本,顺序执行
42
  # 都是 bash 命令
43
  # 默认当前目录就是 repo 的根目录
44
  script:
45
    # 我先列出所有文件的列表,便于 script 出错后进行调试
46
    - "ls -la"
47
    # 设置 yarn 的源,会快一些
48
    - 'yarn config set registry "https://registry.npm.taobao.org"'
49
    # 安装所有依赖,也就是 node_modules
50
    - "yarn"
51
52
# 执行完 init 这个 stage(步骤)后,我们的 node_modules 目录就缓存下来了
53
# 然后我们就开始执行代码检查
54
lint_code:
55
  # 对应的步骤是代码检查,可以多个任务指向同一个 stage,这些任务将会被并行执行
56
  stage: lint
57
  # 定义缓存
58
  cache:
59
    # 下面的配置指示,我们当前只拉取缓存,不上传,这样会节省不少时间
60
    policy: pull
61
    # 指定要缓存的文件/文件夹
62
    paths:
63
      - node_modules/
64
  # 该任务要运行的 bash 脚本
65
  script:
66
    - "ls -la"
67
    - "yarn lint"
68
69
# 单元测试
70
unit_test:
71
  # 隶属于 单元测试 这个步骤
72
  stage: unit_test
73
  # 同 lint_code 任务,拉取缓存,我们就不用再重新下载 node_modules 了
74
  cache:
75
    policy: pull
76
    paths:
77
      - node_modules/
78
  # 执行 bash 命令
79
  script:
80
    - "ls -la"
81
    - "yarn test:unit"
82
83
build:
84
  stage: build
85
  cache:
86
    policy: pull
87
    paths:
88
      - node_modules/
89
  # artifacets 是打包你指定的文件或者文件夹,然后你可以通过 gitlab 的页面进行下载的
90
  artifacts:
91
    # artifacets 的名字
92
    name: "dist"
93
    # artifacets 的过期时间,因为这些数据都是直接保存在 Gitlab 机器上的,过于久远的资源就可以删除掉了
94
    expire_in: 60 mins
95
    # 制定需要打包的目录,这里我把 dist 目录给打包了,准备发布到服务器
96
    paths:
97
      - dist/
98
  script:
99
    - "ls -la"
100
    - "yarn build"
101
102
# 部署任务
103
deploy:
104
  stage: deploy
105
  # 该命令指定只有 master 分支才能够执行当前任务
106
  only:
107
    - master
108
  # 部署脚本,在下面的代码中,我用到了很多类似 ${AMAZON_PEM} 的变量,由于我们的私钥、Ip 都算是不宜公开显示的信息,
109
  # 所以我用到了 Gitlab 的变量工具,在 repo 的 CI/CD > Environments 中,这些变量值只有项目管理员才有权限访问
110
  script:
111
    - "ls -la"
112
    - "ls -Rl dist"
113
    - 'echo "${AMAZON_PEM}" > amazon.pem'
114
    - "chmod 600 amazon.pem"
115
    - "scp -o StrictHostKeyChecking=no -i amazon.pem -r dist/* ${AMAZON_NAME_IP}:/usr/share/nginx/html/"

坑 s

在使用的过程中,还是经历了一些坑的,也记录下来

  • 公司的 Gitlab 估计是版本问题,cache 基本是失效的,所以无奈,我直接添加了一个 before_script 来在每个 jobs 执行前都完整安装一次 node_modules
  • 将服务器私钥保存到 Gitlab 的 CI 变量中后,本想通过 echo ${AMAZON_PEM} > amazon.pem,把私钥存储为文件使用,结果发现 echo 出来的文本没有了换行,最终解决办法是 echo "${AMAZON_PEM}" > amazon.pem(就只需要加两个引号)