在项目中,我们使用 Go 语言开发核心功能,同时使用 Python 编写功能验证测试(FVT)。随着代码库的增长,CI/CD 流水线的执行时间逐渐变长,特别是在依赖安装和代码检查阶段。为了提升开发效率,我们最近对 GitLab CI 配置进行了优化。

优化方案

1. 依赖缓存策略

通过 GitLab Runner 的缓存机制,我们为不同语言的依赖项设置了独立的缓存:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
variables:
GIT_CLONE_PATH: "${CI_BUILDS_DIR}/${CI_PROJECT_NAME}-build-${CI_JOB_ID}-${CI_PIPELINE_ID}"
PIP_CACHE_DIR: "${CI_PROJECT_DIR}/.cache/pip"
GOLANGCI_LINT_CACHE: "${CI_PROJECT_DIR}/.cache/golangci-lint"
GOPATH: ${CI_PROJECT_DIR}/.go # Gitlab只能缓存项目内的路径

cache:
- key:
files:
- go.sum
paths:
- .go/pkg/mod/
- key:
files:
- requirements.txt
paths:
- .cache/pip
- venv/
- key:
files:
- .golangci.yaml
paths:
- .cache/golangci-lint

实现细节:

  • Go 模块缓存:基于 go.sum 文件生成缓存键,当依赖发生变化时自动失效
  • Python 包缓存:使用 requirements.txt 作为缓存键,缓存 pip 下载的包和虚拟环境
  • GolangCI-Lint 缓存:基于 lint 配置文件的哈希值缓存检查结果

2. 构建日志收集

为了便于排查构建失败问题,我们配置了制品上传功能:

1
2
3
4
5
6
artifacts:
paths:
- tests/**/logs
when: on_failure
access: all
expire_in: "7 days"

该配置会在作业失败时自动上传测试日志文件,保留 7 天供开发团队查看。

效果评估

经过优化后,我们观察到以下改进:

  1. 依赖安装时间:在缓存命中的情况下,Go 模块和 Python 包的下载时间减少约 70-80%
  2. 代码检查效率:golangci-lint 的后续执行时间缩短约 50%
  3. 问题排查:通过自动收集的日志,能够快速定位测试失败的根本原因

实践经验

缓存键设计

合理的缓存键设计是关键。我们选择依赖管理文件(go.sumrequirements.txt)作为缓存键的依据,确保依赖变更时缓存自动失效。

目录结构规划

我们统一将缓存目录设置在项目路径下:

  • Go 相关:.go/.cache/golangci-lint
  • Python 相关:.cache/pipvenv/

这种结构便于管理且避免了不同项目间的缓存冲突。

资源管理

制品设置了 7 天的过期时间,平衡了存储成本与调试需求。仅在上传失败日志,避免不必要的存储占用。

总结

通过合理利用 GitLab Runner 的缓存和制品功能,我们显著提升了 CI/CD 流水线的效率。这些优化措施实施简单,效果明显,为开发团队节省了大量等待时间,同时改善了问题排查体验。

建议类似技术栈的项目可以参考此方案,根据实际需求调整缓存策略和制品配置。