约定式gitlab流程使用记录以及持续集成初体验

约定式gitlab流程使用记录以及持续集成初体验

TangSong404 Lv3

Samver(语义化版本控制规范)

是什么

详见https://semver.org/lang/zh-CN/
版本格式:主版本号.次版本号.修订号,版本号递增规则如下:

主版本号:当你做了不兼容的 API 修改,
次版本号:当你做了向下兼容的功能性新增,
修订号:当你做了向下兼容的问题修正。
先行版本号及版本编译信息可以加到“主版本号.次版本号.修订号”的后面,作为延伸。

为什么

随着系统规模逐渐扩大,加入的包越来越多,软件管理越有可能落入这样的局面:如果依赖关系过高,可能面临版本控制被锁死的风险(秘方只认某牌某批次酱油;一旦断供,整桌菜做不成。)。而如果依赖关系过于松散,又将无法避免版本的混乱(家里充电器标准不统一;每天组合不同,忽快忽慢;充坏了也不知道是哪个的问题)

所以需要用一组简单的规则及条件来约束版本号的配置和增长

怎么做

1.使用语义化版本控制的软件MUST定义公共 API。该 API 可以在代码中被定义或出现于严谨的文档内。无论何种形式都应该力求精确且完整。
2.最简单的做法是以 0.1.0 作为你的初始化开发版本,并在后续的每次发行时递增次版本号。如果你每天都在改变 API,那么你应该仍在主版本号为零的阶段(0.y.z),或是正在下个主版本的独立开发分支中。
3.当你的软件被用于正式环境,它应该已经达到了 1.0.0 版。如果你已经有个稳定的 API 被使用者依赖,也会是 1.0.0 版。如果你很担心向下兼容的问题,也应该算是 1.0.0 版了。
4.同时包含 bug 修复与新功能时,次版本号+1,修订号归零。
5.有正则化的表达,大致意思是major.minor.patch-prerelease+buildmetadata,也就是主版本号.次版本号.修订号-先行版本号+版本编译信息。其中prerelease代表稍微稳定,排序低于同号正式版,而buildmetadata只用于追踪,排序完全忽略。例:1.0.0-beta+exp

Git约定式提交规范

是什么

一种与 SemVer 相互对应的提交规范,详见https://www.conventionalcommits.org/zh-hans/v1.0.0/#%e7%ba%a6%e5%ae%9a%e5%bc%8f%e6%8f%90%e4%ba%a4%e8%a7%84%e8%8c%83

<类型>[可选 范围]: <描述>
[可选 正文]
[可选 脚注]

怎么做

提交类型

  • fit: 在代码库中修复了一个 bug,相当于SemVer 中的 PATCH 版本。
  • feat: 引入了新功能,相当于SemVer 中的 MINOR 版本。
  • break: 引入了不兼容的变更,相当于SemVer 中的 MAJOR 版本。
  • docs: 仅更新了文档。
  • style: 不影响代码含义的变更(空格、格式化、缺少分号等)。
  • refactor: 既不修复 bug 也不添加功能的代码变更。
  • perf: 改进了性能的代码变更。
  • test: 添加了缺失的测试或更正了现有测试。
  • build: 用于修改项目构建系统,例如修改依赖库、外部接口或者升级 Node 版本等;
  • chore: 用于对非业务性代码进行修改,例如修改构建流程或者工具配置等;
  • ci: 用于修改持续集成流程,例如修改 Travis、Jenkins 等工作流配置;
  • revert: 用于撤销之前的提交,例如回滚到上一个版本的代码。
  • merge: 用于合并两个分支,例如将 feature 分支合并到 develop 分支。

规范

1.可选的范围字段可以包含任何描述性的内容,用于指定提交影响的范围。例如:feat(parser): add ability to parse arrays
2.在脚注中包含 BREAKING CHANGE: 或 <类型>(范围) 后面有一个 ! 的提交,表示引入了破坏性 API 变更(这和语义化版本中的 MAJOR 相对应)。 破坏性变更可以是任意 类型 提交的一部分。
3.在正文结束的一个空行之后,可以编写一行或多行脚注。每行脚注都必须包含一个键,后面紧跟 :<空格><空格># 作为分隔符,后面再紧跟键的值
4.脚注的键必须使用 - 作为连字符,比如 Acked-by (这样有助于 区分脚注和多行正文)。脚注的值可以包含空格和换行,值的解析过程必须直到下一个脚注的令牌/分隔符出现为止。

其他

Small commit指的是:每次提交(commit)只包含一个小而明确的改动。这样容易回滚,容易定位bug,Review更容易,Git历史更清晰
比如要这么做:

1
2
3
4
feat: add login api
fix: fix password validation bug
refactor: simplify user service logic
style: adjust login page UI

而不是这么做:

1
fix bug + add login api + 修改UI + 重构数据库

例子

chore!: drop support for Node 6

BREAKING CHANGE: use JavaScript features not available in Node 6.

fix: prevent racing of requests

Introduce a request id and a reference to latest request. Dismiss
incoming responses other than from latest request.

Remove timeouts which were used to mitigate the racing issue but are
obsolete now.

Reviewed-by: Z
Refs: #123

GitLab提交

写这篇笔记前一天我vibe coding了一个简单的adb文件传输桌面应用,打算以这个项目为例进行学习。
现在我的本地仓库是我的项目,远程仓库是我在GitLab上创建的一个空仓库,里面有一个初始化的README.md文件。

第一次提交

1.首先进入项目路径进行git init,这会建立一个.git目录
然后进行git add .,这会将所有文件添加到暂存区
最后进行git commit -m "chore: initial commit",这会提交所有文件到本地仓库

2.添加远程仓库git remote add origin https://gitlab.com/<用户名>/<仓库名>.git
先把远程仓库拉下来合并到本地git pull origin main --allow-unrelated-histories,本地 repo 和远程 repo 历史不一样,Git 会认为是两个独立项目,–allow-unrelated-histories 允许合并。
这个时候会发现README.md有冲突,打开这个文件删除远程的部分即可,然后将重新提交到本地仓库解决分支

1
2
git add README.md
git commit -m "docs: merge remote README"

强制命名当前分支为main git branch -M main
最后进行git push -u origin main,这会将本地main分支推送到远程仓库origin的main分支

4.版本号一般打在main分支上,我现在还处于开发中,所以版本号还在0.1.0
提交一个版本号git tag -a v0.1.0 -m "First working version"
推送到远程git push origin v0.1.0

后续提交

分支

一般来说修复bug、创建新功能都要创建分支,分别是

  • fix/xxx:修复xxx bug
  • feature/xxx:添加xxx功能
    当测试这些分支后,要将这些分支合并到develop分支,然后删除。
    当develop分支稳定后,要将develop合并到main分支,这个时候就可以更新版本号了。

实操

首先创建并切换到develop分支git checkout -b develop
并把它推送到远程git push -u origin develop


我修复了我项目中的一个bug:点完第一次同步修改后同步修改按钮不消失,点完第二次才消失,而且焦点此时会跳转到左侧的路径输入框
我创建并切换到一个修复分支git checkout -b fix/sync-button-not-disappear
执行更新

1
2
git add windows.py
git commit -m "fix: sync button not disappear"

并把它推送到远程git push -u origin fix/sync-button-not-disappear


我为我的项目添加了一个新功能:为内嵌终端添加了ctrl+c中断功能
我创建并切换到一个新功能分支git checkout -b feature/terminal-ctrl-c
执行更新

1
2
git add terminal.py
git commit -m "feat: add terminal ctrl+c interrupt"

并把它推送到远程git push -u origin feature/terminal-ctrl-c


我切换到develop分支git checkout develop
并保证他是最新的git pull origin develop
我首先合并修复分支git merge fix/sync-button-not-disappear
然后合并新功能分支git merge feature/terminal-ctrl-c
推送合并后的develop分支git push origin develop
清除临时分支

1
2
git branch -d fix/sync-button-not-disappear
git branch -d feature/terminal-ctrl-c

清除远程临时分支

1
2
git push origin --delete fix/sync-button-not-disappear
git push origin --delete feature/terminal-ctrl-c

测试稳定后,我把develop合并到main并推送

1
2
3
git checkout main
git merge develop
git push origin main

并更新版本号为0.2.0

1
2
git tag -a v0.2.0 -m "Add terminal ctrl+c interrupt"
git push origin v0.2.0

image4.png

Review流程

我为我的应用的终端添加了历史记录功能,用户可以通过向上/向下箭头键来查看之前执行的命令。
我创建了一个新的分支feature/add-terminal-history先在本地合并到develop,并将变更的develop推送到远程仓库(这次我没有在本地合并到main)
打开GitLab,如下图所示
image-10.png
点击创建合并请求
image-11.png
由于是自己的项目进行测试所以指派人和审核人填的自己,在填写完后再点击创建合并请求
作为审核人可以查看变更
image-12.png
审核完成后进行合并
image-13.png
变更被成功合并到了main分支

GitLab简单使用CI/CD

什么是 CI/CD

CI(Continuous Integration,持续集成)

每次你修改代码并提交(commit)时,系统自动帮你做两件事:
1.拉取你的最新代码
2.自动执行测试(比如 pytest)
目的:确保你的新代码不会破坏原有功能。

CD(Continuous Deployment / Delivery,持续部署/交付)

当 CI 测试通过后,自动把代码部署到服务器或发布环境。
持续交付(Delivery):测试通过,代码准备好了,但部署可以人工确认。
持续部署(Deployment):测试通过,自动部署,不需要人工干预。

配置Runner

简单来说Runner就是CI流程中跑你代码的环境
如果使用的是官方gitlab,并且你不是大陆手机号,可以跳过这一步,因为有Shared Runner可以直接使用
否则我们需要配置个人的Runner,这里推荐使用docker直接部署
先拉取镜像

1
docker run -d --name gitlab-runner --restart always -v <你要存储runner配置文件的路径>\gitlab-runner-config:/etc/gitlab-runner -v //var/run/docker.sock:/var/run/docker.sock gitlab/gitlab-runner:latest

发起Runner注册

1
docker exec -it gitlab-runner gitlab-runner register

下面有一堆让你逐个输入的

1
2
3
4
5
6
GitLab URL:如果是官方:https://gitlab.com,如果是自建:http://your-gitlab-server
Token:在你的gitlab-settings-CI/CD中可以找到并复制,参考下方图片。
description:Runner的描述,随便填
tags:随便填,但用于匹配你的CI/CD配置!后面配置时的tags要与这里设置的相匹配
executor:docker
default docker image:python:3.10

2.png
回到GitLab应该能看到Runner在线了
image6.png

推送实践

我们假设一个业务逻辑,某个函数调用后在正常的情况下一定会返回两数的和

1
2
3
# app.py
def add(a, b):
return a + b + 1

现在需要对这个函数写一个测试逻辑,断言输入1和2一定得到3

1
2
3
4
# test_app.py
from app import add
def test_add():
assert add(1, 2) == 3

一般在个人计算机上可以简单调用pytest判断业务逻辑是否出错
而现在每当我们推送代码后,由GitLab在Runner上自动发起这个pytest,并告知你结果,其实就是CI流程
在GitLab上跑这种流水线只需要项目根目录下有一个.gitlab-ci.yml文件,内容如下:

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
# 拉取的镜像
image: python:3.10

# 要执行的阶段
stages:
- test
- deploy

test:
stage: test
# tags要与你的runner的tag一致!
tags:
- test
script:
- pip install pytest
- pytest

deploy:
stage: deploy
# tags要与你的runner的tag一致!
tags:
- test
script:
- echo "Deploying application..."
# 只有在master分支上的commit才会触发部署
only:
- master

本质上就是推送后先拉python:3,10镜像、执行test中的script、如果通过则执行deploy中的script
现在将app.py,test_app.py,.gitlab-ci.yml三个文件推送到GitLab仓库,就能看到结果了,下图能看到代表CD流程的Deploying application...也被输出
1.png
3.png
那测试一下不正确的提交

1
2
3
# app
def add(a, b):
return a + b + 1

4.png
5.png

小tips

CI过程中如果让Runner主动拉镜像会非常的慢
哪怕你提前在Runner上拉好镜像不行,这是因为Runner默认的pull policyalways,意思是 GitLab Runner 被配置为每次都强制 docker pull。
我们进入到配置Runner时你填入的<你要存储runner配置文件的路径>下的config.toml文件
找到 [runners.docker],对其的配置添加一项pull_policy = "if-not-present"
然后我们本地先拉好测试用的镜像,再去推送,很快就能跑出结果了

  • Title: 约定式gitlab流程使用记录以及持续集成初体验
  • Author: TangSong404
  • Created at : 2026-03-09 00:00:00
  • Updated at : 2026-03-10 06:30:46
  • Link: https://www.tangsong404.top/2026/03/09/work/ci_cd/gitlab_note/
  • License: This work is licensed under CC BY-NC-SA 4.0.
Comments