从 GitLab 8.0 开始,GitLab 开始集成 CI(持续集成) 功能。只需要在服务器上添加一个 Runner,同时在项目中添加一个 .gitlab-ci.yml 文件,就可以进行 CI。在 GitLab 搭建与配置 中笔者记录了从零开始搭建 GitLab 服务的整个流程。在 GitLab CI 持续集成 中笔者交代了 GitLab CI 的一些基本概念,并给出了一个简单的 Demo。
本文主要讨论的是使用 Git 作为代码仓库时,多人开发的工作模式;在前端开发过程中,如何利用 GitLab-CI 工具,自动化编译 Webpack 项目。
1. 问题与需求
笔者从事 SaaS 开发,简单描述下目前团队项目开发的现状。
SaaS 基于 PaaS 提供的框架和 CI/CD 功能进行开发、预发布、发布,使用 SVN 进行代码的管理。PaaS 提供了 SaaS 开发人员快速开发应用的能力。
但是,在多人合作开发的项目中,SVN 提供的分支功能不便于管理分支、合并代码。
相比较于 SVN,Git 拉取代码速度快、允许上千个并行开发的分支、完全分布式,受到大量开发人员的喜爱。多人合作开发项目时,倾向于使用 Git 来管理代码,而在准备部署时才提交到 SVN。为了缩短流程,一方面,可以推动 PaaS 提供 Git 代码托管服务;另一方面,可以通过一定的工具来自动化整个流程(Git -> SVN),节省开发部署的时间。
另外一个问题是,前端团队使用的是 Webpack 模块打包管理工具,前端工程需要打包编译。针对一些复杂的项目,可能会有多人参与前端的开发工作。有时,前端人员在打包 Webpack 项目之前,没有拉取最新代码,导致其他前端人员开发的功能没有及时更新到最新的版本文件中。
幸运的是,GitLab 提供 CI 的功能,能解决上面的问题。GitLab CI 提供了在服务器上执行脚本、自动化流程的能力。
2. Git 工作流
通常 Git 的工作流程,采用的是功能驱动式开发。先有需求,再有功能分支或补丁分支。完成开发后,该分支就合并到主分支,然后删除分支。
广泛使用的工作流程有三种:
- Git flow
- Github flow
- Gitlab flow
Git flow 需要同时维护两个非常相似的分支 develop 和 master,比较适合具有较长版本发布周期的项目;Github flow 只需要维护一个分支,根据新需求从 master 拉取新分支,合并上线后,再删除新分支。Gitlab flow 在 master 分支以外,再建立不同的环境分支,通过不同环境的上下游关系合并新功能。
目前团队的SaaS 更新周期短,迭代频繁,新的功能和修复的 Bug 很快就能合并到 master ,个人认为使用 Github flow 工作流程会比较简单方便。
当有新需求或者 Bug 时,从最新的 master 拉出一个新的分支,在新的分支上进行开发。在新分支上开发完成之后,发起 Pull Request 合并到 master ,最后删掉新建的分支。
3. GitLab-CI 工作流
通过在项目中配置 CI 流程,GitLab 默认在代码提交之后触发 CI 过程。默认的 CI 配置文件路径是项目根目录下 .gitlab-ci.yml 文件,也可以在项目的【Settings】-【Pipelines】- 【Pipelines】中指定配置文件路径。
简单说,就是在项目下新增一个 .gitlab-ci.yml 文件,在文件中定义 CI 流程,提交代码之后,GitLab CI 就自动开始构建了。下面的一些讨论,主要是围绕 .gitlab-ci.yml 文件。
3.1 .gitlab-ci.yml 关键字及含义
- before_script
定义任何 Jobs 运行前都会执行的命令。 - after_script
定义任何 Jobs 运行完后都会执行的命令。(要求 GitLab 8.7+ 和 GitLab Runner 1.2+) - variables && Job.variables
定义环境变量。如果定义了 Job 级别的环境变量的话,该 Job 会优先使用 Job 级别的环境变量。(要求 GitLab Runner 0.5.0+) - cache && Job.cache
定义需要缓存的文件。每个 Job 开始的时候,Runner 都会删掉 .gitignore 里面的文件。如果有些文件 (如 node_modules/) 需要多个 Jobs 共用的话,我们只能让每个 Job 都先执行一遍 npm install。(要求 GitLab Runner 0.7.0+) - Job.script
定义 Job 要运行的命令,必填项 - Job.stage
定义 Job 的 stage,默认为 test - Job.artifacts
定义 Job 中生成的附件。当该 Job 运行成功后,生成的文件可以作为附件 (如生成的二进制文件) 保留下来,打包发送到 GitLab,之后我们可以在 GitLab 的项目页面下下载该附件。
3.2 工作流
本地开发功能、定义流程,提交代码后,GitLab 通过 Pipeline 完成 CI/CD 过程。
4. Webpack CI 实践
GitLab 服务器最低配置要求是 1 core CPU、1GB RAM、3GB swap,推荐配置是 2 cores CPU、4GB RAM。团队使用的 GitLab 服务器配置为:
- Intel(R) Xeon(R) CPU E5-2420 六核,1.90GHz,线程数 12
- 内存 64G
- 硬盘 300G,10000RPM,SAS
项目的文件结构:
|
|
4.1 .gitlab-ci.yaml 配置
需要注意的是 GitLab CI 提供了一些内置的环境变量,比如,$CI_PROJECT_PATH
表示项目的路径。使用这些内置变量,能够显著提高 yaml 配置的可移植性,减少拼写错误。下面是配置的 yaml 文件,具体每个步骤的功能,写在注释中。
|
|
上面的 yaml 配置实现了,提交代码之后,自动打包编译 Webpack 项目,并将编译生成的文件更新到 GitLab 仓库。如果需要更新到 SVN ,只需要执行 SVN 相应的提交命令即可,这个就当做是作业布置给看本篇文档的你了。
4.2 通过环境变量隐藏敏感信息
在项目页面依次选择 - 【Settings】- 【Pipelines】- 【Secret variables】
4.3 查看 CI 结果
向 GitLab 提交代码之后,CI 过程将被自动触发。等待执行的完成。
需要说明的另外一个关键点是:循环构建。在 script 里面,在每次构建时,会执行一次 git 的提交,这样会触发一次新的构建,如此反复,不停地执行构建。为了解决这个问题,在 script 里面提交代码时,需要在 commit 的 message 中加上 “[ci skip] 或者 [skip ci] 关键字”,跳过当次构建。在 Web 上查看 【Pipeline】 的执行状态时,可以看到一次提交会新增两条记录,其中一条为 【skipped】。
执行 job 时,除了 console 会输出构建信息。在 【Jobs】选项中还可以查看 job 的执行流和执行结果,为了更好的页面效果,下面是另外一个 Example 的执行结果(特意写了很多个 stage 和 job)。
4.4 一些小技巧
- job 中使用 when 关键字,可以控制 job 在满足一定条件时,才被执行
|
|
- 跳过 CI,在提交代码时,增加 ci skip或skip ci,可以跳过当次提交触发的 CI 过程
|
|
- 在 job 中可以设置 only ,限制仅指定分支才执行
|
|
5. 参考
- http://www.ruanyifeng.com/blog/2015/12/git-workflow.html
- https://guides.github.com/introduction/flow/index.html
- https://www.ibm.com/developerworks/cn/java/j-lo-git-mange/index.html
- https://docs.gitlab.com/ce/ci/variables/
- https://gitlab.com/gitlab-org/gitlab-ce/issues/18106
- https://hackernoon.com/setting-up-ci-cd-on-gitlab-step-by-step-guide-part-1-826385728223
- https://www.perforce.com/perforce/r16.3/manuals/gitswarm/ci/yaml/README.html
6. 附录
另外一份将 Git 仓库代码推送到 SVN 的配置
|
|