CODE/2022-10-17

Gitlab-CI 使用教程

Gitlab CI/CD 介绍

Gitlab CI/CD 是一款用于持续集成(CI),持续交付(CD)的工具,相似的工具有 Jenkins、Travis CI、GoCD 等。
持续集成,即 Continuous Integration, 即在源代码变更后(git push)后自动检测(code lint)、构建和进行单元测试的过程,持续集成的目标是快速确保开发人员新提交的代码是好的(少 bug),并且适合在代码库中进一步使用。
持续交付,即 Continuous Delivery, 通常是指整个流程链(管道),它自动监测源代码变更并通过构建、测试、打包和相关操作运行它们以生成可部署的版本(可以是 apk 打包,也可以是网站部署),基本上没有任何人为干预。它包括持续集成,持续测试(保证代码质量),持续部署(自动发布版本,供用户使用)。
Gitlab 的 CI/CD 算是比较简单的了,只需要依靠一份".gitlab-ci.yml",将该文件随代码上传,Gitlab 就会自动执行相应的任务,从而实现 CI/CD。

Gitlab 安装

要使用 Gitlab 的 CI/CD 功能,一般有以下几种选择:
  • 第一,自己搭一套 Gitlab,再加上部署自己的 Runner(即实际执行代码的机器),推荐 docker 部署
  • 第二,使用公司 / 官方的 Gitlab,且使用自带的 Runner,即 shared Runner, 见下图。

Gitlab-ci 编写

.gitlab-ci.yml遵循 YAML 文件的语法,这份文件记录了你想要执行的各种指令,这些指令可以用来对你的代码进行规范检查(例如 PEP8)、自动打包(例如 Android 自动打包)、自动部署等。
对于新手,如果不知道自己写的.gitlab-ci.yml是否有错误,可以通过 Gitlab 自带的CI Lint进行检查。
本文使用版本:GitLab Community Edition 12.5.6-ee

官方文档

image

该关键字指定一个任务(job)所使用的 docker 镜像,例如image: python:latest使用 Python 的最新镜像。
镜像下载的策略:
  • never: 当使用这个策略,会禁止 Gitlab Runner 从 Docker hub 或者其他地方下拉镜像,只能使用自己手动下拉的镜像
  • if-not-present: 当使用这个策略,Runner 会先检测本地是否有镜像,有的话使用该镜像,如果没有再去下拉。这个策略如果再配合定期删除镜像,就能达到比较好的效果。
  • always: 这个是 gitlab-ci 默认使用的策略,即每一次都是重新下拉镜像,导致的结果就是比较耗时间

services

该关键字指向其他 Docker 镜像,这些镜像会与 image 关键字指定的镜像绑定(link)。比如可以绑定一个 mysql 服务,存储单元测试所需要的假数据。
plain text_snippet
Plain Text · 8 lines|
default_job:
image: python:3.6
services:
- mysql:5.7
before_script:
- apt-get install mysql-client

before_script 和 after_script

before_script 关键字定义了一组在每个任务开始之前需要执行的命令,after_script 则相反。例如可以在 before_script 做好 ssh 连接的准备,见下文。
注:before_script 可以针对全部任务,也可以针对单个任务。

Gitlab-CI 实现 SSH 连接

1.生成 SSH 需要的公私钥 2.Gitlab-CI 文件编写如下:
plain text_snippet
Plain Text · 22 lines|
image: python:3.6
before_script:
# which ssh-agent 用于寻找ssh-agent是否存在,
- 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
# 启动ssh-agent
- eval $(ssh-agent -s)
# 设置环境变量SSH_PRIVATE_KEY,并将私钥添加到agent store
- echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
# 修改权限
- mkdir -p ~/.ssh && chmod 700 ~/.ssh
# 跳过SSH询问
- '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config'
# 上文添加的是项目私钥,如果SSH连接成功则能够下拉项目代码
ssh-test:
script:
- git clone git@git.xx
# 远程到其他机器并执行命令
- ssh root@172.17.0.3 "cd /root && mkdir your_dir"
# 如果使用非默认端口
- ssh -p 5555 root@172.17.0.3 "cd /root && mkdir your_dir"

stages

前面提到,我们可以定义一系列任务(job)去执行我们想要的指令,但怎样指定先后顺序呢,这就需要用到 stages 关键字了。
stages 关键字有两个特性:1.如果两个任务对应的 stage 名相同,则这两个任务会并行运行 2.下一个 stage 关联的任务会等待上一个 stage 执行成功后才继续运行,失败则不运行
plain text_snippet
Plain Text · 29 lines|
image: python:3.6
stages:
- build
- test
- deploy
# build-job1和build-job2会并行执行
build-job1:
stage: build
script:
- echo $PWD
build-job2:
stage: build
script:
- echo $PWD
# 这个任务会在build-job1和build-job2执行成功后再运行
test-job:
stage: test
script:
- echo $PWD
# 注意定义的stage都需要用到
deploy-job:
stage: deploy
script:
- echo $PWD
效果图如下:
注:如果想要控制某一个 stage 在最开始,或者最后执行,可以使用.pre 和 .post 关键字

only / except

这两个是让我又爱有恨的字段, 没有之一。
为了更好地说明,我们还需引入一个Pipelines的概念,Pipelines 就是我们在 Gitlab 的 UI 界面看到一行行记录:
如上图,一共有三个 Pipelines,每个 Pipelines 内部就是我们定义的任务的执行情况,就是这么简单。
前面提到,通过 stages 关键字可以控制任务执行的先后顺序,而通过only/except关键字控制的是任务的触发条件。
only/except 关键字包含了一些子关键字(或者你可以理解为策略),当符合定义的策略时才会触发 Pipelines 的执行,except 则相反。
only 关键字的默认策略是['branches', 'tags'],即你提交了一个分支或者打了标签,就会触发,
除此之外,only/except 关键字还有基础特性和高级特性之分,所包含的子关键字也各不相同,建议还是仔细阅读官方文档。
only/except(basic):
  • branches: 当你的 Git Refs 对应的是一个分支时触发
  • tags: 当你的 Git Refs 对应的是一个标签时触发
  • pushes: 当你使用git push时触发
  • web: 当你使用 Web 界面的Run Pipeline时触发
  • merge_requests: 当你创建或者更新一个 merge_requests 时触发
  • ...
only/except(advanced):
  • refs: 注意异或关系
  • variables
  • changes
  • kubernetes
下面是一些示例,希望能给你带来帮助
1.当提交的分支为 master 才会触发 Pipelines
plain text_snippet
Plain Text · 24 lines|
image: python:3.6
# 第一种方式
job1:
only:
- master
script:
- echo $PWD
# 第二种方式
job2:
only:
refs:
- master
script:
- echo $PWD
# 第三种方式
job3:
only:
variables:
- $CI_COMMIT_REF_NAME == "master"
script:
- echo $PWD
2.当打了 tag 才会触发 Pipelines(正常的提交不会)
plain text_snippet
Plain Text · 16 lines|
image: python:3.6
# 第一种方式
job1:
only:
- tags
script:
- echo $PWD
# 第二种方式
job2:
only:
refs:
- tags
script:
- echo $PWD
3.当提交的分支为 master 或者打了 tags 触发 Pipelines
plain text_snippet
Plain Text · 9 lines|
image: python:3.6
# 举这个例子是想说明only关键字之间的关系是”或“关系
job1:
only:
- master
- tags
script:
- echo $PWD
4.当提交的分支为 master 且打了 tags 触发 Pipelines 目前没找到办法,应该可以配合rules关键字实现
5.当使用 Web 界面的Run Pipelines时触发(个人感觉这种方式挺有用的)
plain text_snippet
Plain Text · 8 lines|
image: python:3.6
# 举这个例子是想说明only关键字之间的关系是”或“关系
job1:
only:
- web
script:
- echo $PWD

tags

该关键字指定了使用哪个 Runner(哪个机器)去执行我们的任务,注意与上文 only 关键字的 tags 进行区分。
plain text_snippet
Plain Text · 10 lines|
image: python:3.6
# 举这个例子是想说明only关键字之间的关系是”或“关系
job1:
only:
- dev
tags:
- machine1
script:
- echo $PWD

when

前面说过,stages 关键字可以控制每个任务的执行顺序,且后一个 stage 会等待前一个 stage 执行成功后才会执行,那如果我们想要达到前一个 stage 失败了,后面的 stage 仍然能够执行的效果呢?
这时候 when 关键字就可以发挥作用了,它一共有五个值:
  • on_success:只有前面 stages 的所有工作成功时才执行,这是默认值。
  • on_failure:当前面 stages 中任意一个 jobs 失败后执行
  • always:无论前面 stages 中 jobs 状态如何都执行
  • manual:手动执行
  • delayed:延迟执行
plain text_snippet
Plain Text · 37 lines|
# 官方示例
stages:
- build
- cleanup_build
- test
- deploy
- cleanup
build_job:
stage: build
script:
- make build
# 如果build_job任务失败,则会触发该任务执行
cleanup_build_job:
stage: cleanup_build
script:
- cleanup build when failed
when: on_failure
test_job:
stage: test
script:
- make test
deploy_job:
stage: deploy
script:
- make deploy
when: manual
# 总是执行
cleanup_job:
stage: cleanup
script:
- cleanup after jobs
when: always

cache

该关键字指定了需要缓存的文件夹或者文件,目的是为了加快执行速度。
值得注意的是,cache 不能缓存工作路径以外的文件。比如你的用户是 yangan,项目是 helloworld,默认的工作路径就是 /build/yangan/helloworld, 如果你想缓存 /root 下的某个文件,就会出现“找不到文件”的错误。
另外,cache 并不能保证每次都能命中,而且如果缓存的文件较大,有时候反而会适得其反,导致速度变慢。
plain text_snippet
Plain Text · 14 lines|
image: python:3.6
cache:
# 注意是相对路径
paths:
- cache_dir/
job1:
script: echo $PWD
# 针对单个任务
cache:
- binaries/

artifacts

类似 cache 关键字,也可以缓存文件或者文件夹,不同的是,这些文件可以在 Gitlab 的 UI 界面中下载,一般可用来存储 Android 打包生成的 apk。
plain text_snippet
Plain Text · 10 lines|
image: python:3.6
job1:
artifacts:
paths:
- binaries/
# 设置过期时间
expire_in: 1 week

变量

Gitlab-CI 的变量有几种,分别为预先定义的环境变量,比如CI_COMMIT_SHA, CI_COMMIT_MESSAGE; 通过 Web 界面 Settings/CI-CD 设置的变量,以及自己在.gitlab-ci.yml定义的变量。
通过预先定义的环境变量,我们可以获取分支名,提交的消息,从而判断任务是否需要执行;而 Web 界面 Settings/CI-CD 设置的变量,则非常适合用于存储像公私钥,账号密码这些不便公开的数据。因为只有 Owner 和 Maintainer 能够查看。
如下图就定义了一个SSH_PRIVATE_KEY来存储私钥:
link:variables 关键字: docs.gitlab.com/ee/ci/varia… Gitlab 预定义的变量: docs.gitlab.com/ce/ci/varia… 环境变量: docs.gitlab.com/ce/ci/varia…

遇到的问题

1.!= 这个符号只在 11.11 及以上的版本中支持

参考

COMPANION ESSAYS / 思想脉络与互照篇目
同卷深读2026-05-22 ·

python3安装在centos详细教程

同属「系统工程卷」脉络衍生思考与工程推演推演阅读 →
跨界互照2026-08-22 ·

我的书架:03|金融经管:经济运行、金融体系与企业治理

我的书架:03|金融经管:经济运行、金融体系与企业治理

跨领域对照思辨 · 从「思想随笔」视界互为印证推演阅读 →
RELATED INDEX / 相关阅读索引
柯航hang.ke·© 2014—2026
CC BY-NC 4.0·