GitLab Expert

GitLab

links:

CI/CD

CI: Continuous Integration
- Detect Errors
- Reduce Integration Problem
- Team Work
CD: Continuous Delivery/Continuous Deployment
- Every Change is Releasable
- Value Quickly to Get Feedback What Users Care About

CI/CD 在开发中的流程:

  • Code

  • Commit

  • Test(CI)

    • Build
    • Unit
    • Integration
  • CD

    • Review
    • Staging
    • Production

Workflow

mr

在 每个 branch 上显示的 0|1 状态表示该分支上的提交状态,0 表示存在 0 个提交落后于 default branch, 1 表示存在 1 个提交提前于 default branch。

GitLab Badge

徽章是一种统一的方式,用于呈现有关项目的概述信息。它们由一个小图像和图像指向的 URL 组成。徽标的示例可以是管道状态、测试覆盖范围或联系项目维护人员的方式。

添加 pipeline badge

  • 进入 Settings -> General -> Badges

  • Name 字段:Pipeline Status

  • Link 字段:https://gitlab.com/%{project_path}/-/commits/%{default_branch}

  • Image URL 字段:https://gitlab.com/%{project_path}/badges/%{default_branch}/pipeline.svg

GitLab Runner

执行 GitLab CI/CD 需要配置 GitLab runner

安装

配置 gitlab-runner 为项目提供 CI/CD 的执行器。

links:

binary install

Step 1. 参考文档,根据机器架构安装下载二进制。
Step 2. 为二进制包添加执行权限。
Step 3. 配置 gitlab 工作路径 --working-directory,避免 gitlab-runner 构建的缓存撑爆硬盘,配置文件所在 /etc/systemd/system/gitlab-runner.service
Step 4. 安装 gitlab-runner 服务。

1
2
# root 用户,避免权限
gitlab-runner install --working-directory /home/gitlab-runner --user root

Step 5. 注册 gitlab-runner 的执行器,生成配置文件 /etc/gitlab-runner/config.toml

1
gitlab-runner register

可单独配置 runner 的构建目录 builds_dir,注意路径权限:

1
chmod -R 777 gitlab-runner-custom-build-dir

shell executor

使用 docker 配置 shell executor

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
docker run -d --name gitlab-runner \
--restart always \
--privileged \
--gpus=all \
# Host Docker Authentication \
-v /root/.docker/:/root/.docker/ \
# Deprecated buildx https://docs.docker.com/build/architecture/#install-buildx ,maybe including ~/.docker/cli-plugins, /usr/lib/docker/cli-plugins, /usr/libexec/docker/cli-plugins and same in /usr/local-likes
-v /usr/libexec/docker/cli-plugins/docker-buildx:/usr/libexec/docker/cli-plugins/docker-buildx \
# Build Cache as Same Path \
-v /data2/cache:/data2/cache \
# Docker Cli \
-v /usr/bin/docker:/usr/bin/docker \
# Bind hosts on Demand \
-v /etc/hosts:/etc/hosts \
# Gitlab Config \
-v /srv/gitlab-runner/config:/etc/gitlab-runner \
# Docker-compose \
-v /usr/local/bin/docker-compose:/usr/local/bin/docker-compose \
# Docker Sock \
-v /var/run/docker.sock:/var/run/docker.sock \
# Image
gitlab/gitlab-runner:latest \
run \
# Root permission \
--user=root \
# Bind as source for run docker run -v in gitlab-runner container \
--working-directory=/data2/cache

[!CAUTION]
注意 gitlab-runner 容器中用户和主机用户权限配置冲突解决,包括构建目录 /data2/cache 和 docker.sock 等挂载的访问权限都需要配置.

1
chmod -R 777 /data2/cache

向 gitlab instance 注册 runner

1
docker run --rm -it -v /srv/gitlab-runner/config:/etc/gitlab-runner gitlab/gitlab-runner register

配置完后,host 下的 gitlab runner config 如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# cat /srv/gitlab-runner/config/config.toml
concurrent = 1
check_interval = 0

[session_server]
session_timeout = 1800

[[runners]]
name = "shell"
url = "gitlab instance url"
id = 143
token = "DkJVTi5KxJJGVpSDZVEC"
token_obtained_at = 2023-07-17T10:06:40Z
token_expires_at = 0001-01-01T00:00:00Z
executor = "shell"
environment = ["DOCKER_AUTH_CONFIG={\"auths\":{\"any docker hub\":{\"auth\":\"ZmVuZ2xpOjUxYWYuOWVjZQ==\"}}}"]
[runners.custom_build_dir]
[runners.cache]
[runners.cache.s3]
[runners.cache.gcs]
[runners.cache.azure]

更新配置 /srv/gitlab-runner/config, 重启镜像,生效配置

1
docker restart gitlab-runner

docker executor

DOOD 配置: 使用主机的 docker daemon

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# cat /srv/gitlab-runner/config/config.toml
concurrent = 1
check_interval = 0

[session_server]
session_timeout = 1800

[[runners]]
# runner name as runner tag
name = "docker"
url = "gitlab instance url"
id = 73
token = "gitlab runner token"
token_obtained_at = 2022-08-31T09:27:10Z
token_expires_at = 0001-01-01T00:00:00Z
executor = "docker"
# Docker authentication, 也可以通过挂载主机的/root/.docker/config.json
environment = ["DOCKER_AUTH_CONFIG={\"auths\":{\"any docker hub\":{\"auth\":\"authentication generated by login step\"}}}"]
[runners.custom_build_dir]
[runners.cache]
[runners.cache.s3]
[runners.cache.gcs]
[runners.cache.azure]
[runners.docker]
tls_verify = false
image = "docker:latest"
privileged = false
disable_entrypoint_overwrite = false
oom_kill_disable = false
disable_cache = false
# 配置拉取镜像策略
pull_policy = "if-not-present"
# /cache 是默认的本地构建缓存目录
# /builds 是默认的本地构建目录
# 若所在路径容量优先,可考虑创建软连接到 /cache (项目中间结果缓存)及/builds (项目构建缓存)
volumes = [
"/cache:/cache",
"/builds:/builds",
"/var/run/docker.sock:/var/run/docker.sock",
"/root/.docker/config.json:/root/.docker/config.json",
]
shm_size = 0

links:

k8s install

使用 helm 在 k8s 上安装 gitlab-runner

links:

常用命令

1
2
3
4
gitlab-runner stop # 停止 runner
gitlab-runner start/restart # 开启/或重启 runner
gitlab-runner install # 安装 runner
gitlab-runner register # 注册关联执行器

集成 docker 构建环境

需要配置 gitlab-runner 访问 dockerhub 权限 DOCKER_AUTH_CONFIG

links:

更多配置

CI 在 Gitlab 中跑起来,可能需要对 runner 配置.

参考文档:

常见问题

Missing /usr/bin/gitlab-runner-helper. Creating cache is disabled

存在环境变量 variable 设置到 DEBUG,需删掉干扰环境变量。

GitLab CI/CD

参考文档:

gitlab template

使用 GitLab CI/CD 最高效的方式是使用现有的模板.

links:

variable

GitLab CI/CD Variable 变量是一种环境变量,用于:

  • 控制作业和管道的行为。

  • 存储要重复使用的值。

  • 避免在.gitlab-ci.yml 中硬编码值。

变量分为:

预置变量(Predefined variables reference)预定义的 CI/CD 变量在每个 GitLab CI/CD 管道中都可用。

links:

GIT_STRATEGY

在 GitLab CI 中,可以使用 GIT_STRATEGY 来指定 Git 操作的策略。GIT_STRATEGY 有以下几个可选值:

  • clone:每个 Job 都会执行 git clone 操作来获取代码,默认值。

  • fetch:每个 Job 都会执行 git fetch 操作来更新代码。

  • none:每个 Job 都不会执行 Git 操作,适用于无需访问代码仓库的 Job。

rules

GitLab CI/CD 中的 rules 语法允许定义灵活的条件来确定何时创建或执行作业

1
2
3
4
5
6
7
8
workflow:
rules:
- if: <expression>
changes: <array_of_files>
exists: <array_of_files>
allow_failure: <boolean>
when: <string>
start_in: <string>
  • if:确定作业是否应该被创建或执行的条件。它支持使用预定义变量、运算符和正则表达式的广泛表达式。

  • changes:可选字段,允许指定一组文件,当这些文件在提交中被修改时,作业应该触发。

  • exists:可选字段,允许指定一组文件,当这些文件存在于存储库中时,作业应该触发。

  • allow_failure:可选字段,允许指定作业是否允许失败而不影响整体流水线状态。它接受布尔值(true 或 false)。

  • when:可选字段,允许指定作业应该在何时被创建或执行。它接受以下值:on_success、on_failure、always、manual 或 never。

  • start_in:可选字段,允许通过指定时间间隔来延迟作业的开始。它接受值如 3 minutes、1 hour 或 1 day。

extends

复用 CI 脚本配置语法。

如果 my-other-block 在对应的 script 有自定义值,则它会覆盖 extend 中的 值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
my-base-block:
stage: deploy
script:
- echo "Hello, Gitlab CI!"

my-other-block:
extends:
- my-base-block
script:
- echo "Bye, Gitlab CI!"

####### 合并后的值 ######

my-base-block:
stage: deploy
script:
- echo "Hello, Gitlab CI!"

my-other-block:
stage: deploy
script:
- echo "Bye, Gitlab CI!"

links:

matrix

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
stages:
- matrix

.parallel-matrix:
parallel:
matrix:
- CLOUD: [aws, azure, gcp]
ARCH: [kubernetes, service-mesh]

Matrix:
stage: matrix
image: alpine:latest
parallel: !reference [.parallel-matrix, parallel] # or extends: [.parallel-matrix]
script:
- echo "Hello from $ARCH from $CLOUD"

links:

trigger

使用子管道,解耦 CI 复杂的 jobs.

links:

interruptible

当为 job 配置了 interruptible 时,如果当前分支存在新的提交,会自动取消当前管道.

links:

script

在 gitlab-ci 中,存在 before_script(sc), script(s), after_script(as) 三个脚本阶段,特征如下:

before_script:

  • 影响 job 状态

  • 变量能传递到 s

script:

  • 影响 job 状态

  • 能接受 bs 中变量

after_script:

  • 不影响 job 状态

  • 不接受 bss 中变量,只接受 variable 中的变量

传递环境变量到 af

1
2
3
4
5
6
7
8
9
10
pass_var_to_as:
script:
- dev_id=123
- echo "dev_id=$dev_id" > .variables.txt
after_script:
- source .variables.txt
- echo $dev_id
artifacts:
paths:
- .variables.txt

在 job 之间传递变量

1
2
3
4
5
6
7
pass_var_to_downstream:
script:
- dev_id=123
- echo "dev_id=$dev_id" > dev.env
artifacts:
reports:
dotenv: dev.env

git submodule

使用 git 子模块能保证项目依赖关系,在开发及构建能有效的保证这种关系的稳定。在 GitLab 中使用子模块可能需要做一定的配置

.gitsubmodules: 使用 Git 子模块时,项目应具有名为 .gitmodules 的文件。可能需要对其进行修改才能在 GitLab CI/CD 作业中工作。

例如,在以下情况下,配置可能如下所示:

1
2
3
[submodule "project"]
path = project
url = ../../group/project.git

当子模块位于同一 GitLab 服务器上时,应该在文件中使用相对 URL。然后,可以在所有 CI/CD 作业中使用 HTTPS 进行克隆。还可以使用 SSH 进行所有本地检出 .gitmodules。

上述配置指示 Git 自动推断克隆源时要使用的 URL。Git 对 HTTPS 和 SSH 使用相同的配置。GitLab CI/CD 使用 HTTPS 克隆源,可以继续使用 SSH 在本地克隆。

对于不在同一 GitLab 服务器上的子模块,请使用完整的 URL

1
2
3
[submodule "project-x"]
path = project-x
url = https://gitserver.com/group/project-x.git

子模块在 .gitlab-ci.yml 中 job 中的配置子模块迁出方式。

1
2
3
variables:
GIT_SUBMODULE_STRATEGY: recursive # 递归拉取子模块
GIT_SUBMODULE_UPDATE_FLAGS: --jobs 4 # 并发拉取

git lfs

要为代码仓库配置 Git LFS 拉取,需要执行以下步骤:

  • 在 GitLab CI 脚本中,添加以下命令以安装 Git LFS:

1
2
3
before_script:
- git lfs install # install lfs manually
- git lfs pull # pull manually
  • 确保项目中包含了.gitattributes 文件,并在其中指定要使用 Git LFS 进行跟踪的文件类型。例如,如果想要使用 Git LFS 跟踪所有的.mp4 文件,可以在.gitattributes 文件中添加以下内容:

1
*.mp4 filter=lfs diff=lfs merge=lfs -text

这将告诉 Git LFS 将.mp4 文件视为大文件,并使用 Git LFS 进行跟踪。

access token

在 GitLab 项目配置中配置 access token, 可根据需要配置权限,使用方式

  • make a pr or oush with gitlab project token

将代码更改推送逻辑封装到一个 .yml 文件中,然后在其他项目中通过 extends 关键字来扩展这个模板。参考的示例

参考:

workflow

使用工作流 workflow 控制管道行为。

links:

include

使用 include 在 CI/CD 配置中包含外部 YAML 文件。

links:

artifact

links:

dotenv

dotenv 保存为 artifact

将环境变量保存为 artifact

links:

job

配置 job 中的各种 artifact 行为

links:

service

gitlab ci 中定义的 service 默认以 privileged 权限启动,方便服务内部工作正常.

links:

publish release

GitLab 中发布 release 时会自动创建一个标签 (CI_COMMIT_TAG),所以可以通过检查标签是否存在来判断是否发布了 release。

links:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
job-name:
# ... other configurations ...
rules:
# using defined syntax
- if: $CI_COMMIT_TAG
# or
# prefix matches v
- if: $CI_COMMIT_TAG =~ /^(v)/
# using exists syntax
- if: $CI_COMMIT_TAG != ''
- if: $CI_COMMIT_TAG =~ /^./
- if:
exists:
- $CI_COMMIT_TAG
- exists:
- $CI_COMMIT_TAG
- manual

badges

徽章是一种统一的方式,用于显示关于项目的简化信息。徽章由一个小图像和图像所指向的 URL 组成。在 GitLab 中,徽章显示在项目描述下面。可以在项目和组级别使用徽章。

links:

cron

定时命令

1
2
3
4
5
6
7
8
9
# ┌───────────── minute (0 - 59)
# │ ┌───────────── hour (0 - 23)
# │ │ ┌───────────── day of the month (1 - 31)
# │ │ │ ┌───────────── month (1 - 12)
# │ │ │ │ ┌───────────── day of the week (0 - 6) (Sunday to Saturday)
# │ │ │ │ │
# │ │ │ │ │
# │ │ │ │ │
# * * * * * <command to execute>

links:

GitLab Deploy

native

使用 ssh 验证远程部署,主要使用 scp 及 ssh 等工具

1
2
3
4
# 传输文件到远程
scp -P 5022 local_file_path username@remote_host:remote_file_path
# 执行远程命令
ssh -p 5022 username@remote_host 'command_to_execute'

生产 ssh 密钥用于自动化部署

1
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"

将公钥添加到服务器。将 id_rsa.pub 文件的内容复制并粘贴到服务器的~/.ssh/authorized_keys 文件中。

将私钥添加到 GitLab。在 GitLab 中,转到项目的 Settings -> CI/CD -> Variables。创建一个新的变量,例如 SSH_PRIVATE_KEY,并将 id_rsa 文件的内容粘贴到值字段中。

在 .gitlab-ci.yml 文件中使用 SSH 密钥。可以在脚本中使用 SSH_PRIVATE_KEY 变量来建立 SSH 连接。例如:

1
2
3
4
5
6
7
8
9
10
11
deploy:
stage: deploy
script:
- 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
- eval $(ssh-agent -s)
- echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add - > /dev/null
- mkdir -p ~/.ssh
- chmod 700 ~/.ssh
- ssh-keyscan yourserver.com >> ~/.ssh/known_hosts
- chmod 644 ~/.ssh/known_hosts
- ssh user@yourserver.com 'your deploy command'

这个脚本首先检查是否已经安装了 ssh-agent,如果没有则安装它。然后,它启动 ssh-agent,添加私钥,并将服务器添加到 known_hosts 文件中。最后,它通过 SSH 连接到服务器并运行部署命令。

示例脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#!/usr/bin/env bash

# shellcheck disable=SC1091,SC2154

set -ex

docker_compose_file="deploy/docker/docker-compose.yml"
deploy_relative_path="/tmp"

local ssh_port=$SSH_PORT
if [[ -z "${ssh_port}" ]]; then
ssh_port=22
fi

# Define the commands for start, update, and delete
start_command="docker-compose -f $docker_compose_file up -d"
update_command="docker-compose -f $docker_compose_file pull && $start_command"
delete_command="docker-compose -f $docker_compose_file down"

# Define the function to transfer file to remote via ssh
function transfer_file() {
local host=$1
local file=$2
local destination=$3

scp -P22 "$file" "$host":"$destination"
}

# Define the function to execute commands remotely via ssh
function remote_deploy() {
local host=$1
local command=$2

ssh -p22 "$host" "$command"
}

# Define the functions for start, update, and delete
function start() {
local host=$1
transfer_file "$host" $docker_compose_file $deploy_relative_path
remote_deploy "$host" "$start_command"
}

function update() {
local host=$1
transfer_file "$host" $docker_compose_file $deploy_relative_path
remote_deploy "$host" "$update_command"
}

function delete() {
local host=$1
remote_deploy "$host" "$delete_command"
}

pages

使用 GitLab Pages 部署项目文档,参考使用 GitLab Pages

links:

GitLab API

python 操作

python 作为胶水语言及丰富的包源,很容易和其它工具配置集成。这里介绍通过 python-gitlab 集成进 gitlab 中的一种方式。

API 操作

GitLab API

create pull request

1
2
3
4
5
curl --header "PRIVATE-TOKEN: $CI_JOB_TOKEN" \
--request POST "https://gitlab.example.com/api/v4/projects/$CI_PROJECT_ID/merge_requests" \
--form "source_branch=temp_branch" \
--form "target_branch=$CI_COMMIT_REF_NAME" \
--form "title=PR from temp_branch"

[!NOTE]
需要将 https://gitlab.example.com 替换为 GitLab 实例的 URL,$CI_PROJECT_ID 是项目 ID,$CI_JOB_TOKEN 是 CI/CD 作业令牌,$CI_COMMIT_REF_NAME 是当前分支的名称。

delete tag

1
2
3
4
5
# 删除 tag v1.0.0
# --request 使用 DELETE 方法
# --header 使用访问认证 Token
curl --header "PRIVATE-TOKEN: TOKEN-ACCESS" \
--request DELETE "https://gitlab.example.com/api/v4/projects/$CI_PROJECT_ID/repository/tags/v1.0.0"

GitLab CI local

Gitlab CI local 用于本地测试 gitlab 管道,避免频繁推送到远程测试 CI 流程。

[!TIP]
建议在 vscode devcontainer 配置 nodejs 及 dind 进行测试。

安装

手动安装,参考 README.md

常用命令

1
2
3
4
5
6
# 列出job
gitlab-ci-local --list
gitlab-ci-local --list-json

# 执行job
gitlab-ci-local job <job-name>