跳转至

GitLab CI/CD

一句话概述:GitLab CI/CD 是 GitLab 内置的持续集成/持续部署工具,通过 .gitlab-ci.yml 定义流水线,从代码提交到部署上线一条龙自动化。

核心知识点

概念白话解释
Pipeline流水线 = 一次完整的 CI/CD 执行过程
Stage阶段 = 流水线中的大步骤(如 build → test → deploy),按顺序执行
Job作业 = 每个阶段里的具体任务,同阶段的作业并行运行
Runner运行器 = 真正干活的机器,可以用 GitLab 共享的或自己搭
Artifact产物 = 作业生成的文件,可传递给下游作业
Cache缓存 = 跨作业复用的依赖文件(如 node_modules)
Variable变量 = 在流水线中传递配置信息
Environment环境 = 部署目标(dev/staging/production)
Include引入 = 复用其他 YAML 配置片段
DAG有向无环图 = 用 needs 打破阶段顺序,实现更灵活的依赖关系

安装配置

GitLab Runner 安装(自托管)

# Ubuntu/Debian 安装 GitLab Runner
curl -L "https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh" | sudo bash  # 添加仓库
sudo apt-get install gitlab-runner  # 安装 Runner

# 注册 Runner(将 Runner 连接到你的 GitLab 项目)
sudo gitlab-runner register  # 交互式注册
# 输入 GitLab 实例 URL(如 https://gitlab.com)
# 输入注册令牌(项目 Settings → CI/CD → Runners 中获取)
# 输入描述和标签
# 选择执行器(推荐 docker)

# Docker 方式运行 Runner
docker run -d \
  --name gitlab-runner \                    # 容器名
  --restart always \                         # 自动重启
  -v /srv/gitlab-runner/config:/etc/gitlab-runner \  # 配置持久化
  -v /var/run/docker.sock:/var/run/docker.sock \     # Docker-in-Docker
  gitlab/gitlab-runner:latest               # 使用最新镜像

基本 .gitlab-ci.yml

# .gitlab-ci.yml(放在项目根目录)
stages:          # 定义阶段顺序
  - build        # 第1阶段:构建
  - test         # 第2阶段:测试
  - deploy       # 第3阶段:部署

variables:       # 全局变量
  PIP_CACHE_DIR: "$CI_PROJECT_DIR/.pip-cache"  # pip 缓存目录

build_job:       # 构建作业
  stage: build   # 属于 build 阶段
  image: python:3.12  # 使用 Python 3.12 Docker 镜像
  script:
    - pip install -r requirements.txt  # 安装依赖
    - python setup.py build  # 构建项目
  artifacts:
    paths:
      - dist/    # 保存构建产物
    expire_in: 1 week  # 产物保留1周

test_job:        # 测试作业
  stage: test    # 属于 test 阶段
  image: python:3.12
  script:
    - pip install -r requirements.txt
    - pytest --cov=src  # 运行测试
  coverage: '/TOTAL.*\s+(\d+%)/'  # 正则提取覆盖率

deploy_job:      # 部署作业
  stage: deploy
  script:
    - echo "Deploying..."
  only:
    - main       # 只在 main 分支执行
  when: manual   # 手动触发部署
  environment:
    name: production  # 部署到生产环境
    url: https://example.com

基本使用

1. Python 项目完整流水线

stages:
  - lint      # 代码检查
  - test      # 单元测试
  - build     # 构建
  - deploy    # 部署

default:
  image: python:3.12-slim  # 默认镜像
  cache:
    key: ${CI_COMMIT_REF_SLUG}  # 缓存键用分支名
    paths:
      - .pip-cache/  # 缓存 pip 下载
  before_script:  # 所有作业前执行
    - pip install --cache-dir .pip-cache -r requirements.txt  # 安装依赖

lint:
  stage: lint
  script:
    - pip install ruff  # 安装代码检查工具
    - ruff check .  # 检查代码风格

unit_test:
  stage: test
  script:
    - pip install pytest pytest-cov  # 安装测试工具
    - pytest tests/ --cov=src --cov-report=html  # 运行测试
  artifacts:
    reports:
      coverage_report:
        coverage_format: cobertura  # GitLab 能识别的覆盖率格式
        path: coverage.xml
    paths:
      - htmlcov/  # 保存 HTML 覆盖率报告
  coverage: '/TOTAL.*\s+(\d+%)/'

build_package:
  stage: build
  script:
    - python -m build  # 构建 Python 包
  artifacts:
    paths:
      - dist/*.whl  # 保存 wheel 包
    expire_in: 30 days

deploy_prod:
  stage: deploy
  script:
    - pip install twine  # 安装上传工具
    - twine upload dist/*  # 上传到 PyPI
  only:
    - tags  # 只在打 tag 时部署
  when: manual  # 手动触发

2. 多环境部署

.deploy_template: &deploy  # YAML 锚点,定义模板
  stage: deploy
  script:
    - echo "Deploying to $ENV_NAME"
    - ./deploy.sh $ENV_NAME  # 执行部署脚本

deploy_dev:
  <<: *deploy  # 继承模板
  variables:
    ENV_NAME: development  # 开发环境
  environment:
    name: development
  only:
    - develop  # develop 分支自动部署

deploy_prod:
  <<: *deploy
  variables:
    ENV_NAME: production
  environment:
    name: production
  only:
    - main
  when: manual  # 生产环境手动触发

高级用法

1. DAG 依赖(打破阶段限制)

stages:
  - build
  - test
  - deploy

build_frontend:
  stage: build
  script: npm run build

build_backend:
  stage: build
  script: python -m build

test_frontend:
  stage: test
  needs: [build_frontend]  # 只依赖前端构建,不等后端
  script: npm test

test_backend:
  stage: test
  needs: [build_backend]  # 只依赖后端构建,不等前端
  script: pytest

deploy:
  stage: deploy
  needs: [test_frontend, test_backend]  # 两个测试都过了才部署
  script: ./deploy.sh

2. 引入外部配置(Include)

# 主 .gitlab-ci.yml
include:
  - local: '.gitlab/ci/test.yml'      # 引入本地文件
  - project: 'group/shared-ci'        # 引入其他项目的配置
    file: '/templates/python.yml'
  - template: Auto-DevOps.gitlab-ci.yml  # 引入 GitLab 官方模板

3. 规则控制(Rules)

test_job:
  script: pytest
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"  # MR 时运行
    - if: $CI_COMMIT_BRANCH == "main"  # main 分支 push 时运行
    - if: $CI_COMMIT_TAG  # 打 tag 时运行
    - changes:  # 这些文件变了才运行
        - src/**/*
        - tests/**/*

常见报错

报错信息原因解决方法
This job is stuck没有可用的 Runner检查 Runner 是否在线,标签是否匹配
yaml invalidYAML 语法错误用 GitLab 的 CI Lint 工具检查
artifacts too large产物文件超限减小产物大小或调整 expire_in
ERROR: Job failed: exit code 1脚本执行失败查看日志定位具体报错
Cache not found缓存未命中检查 key 是否匹配,路径是否正确
Permission denied权限不足检查 Runner 执行器权限和变量权限

速查表

# === 关键字 ===
stages: [build, test, deploy]     # 定义阶段
image: python:3.12                # Docker 镜像
script: [command1, command2]      # 执行命令
before_script: [setup_cmd]        # 作业前执行
after_script: [cleanup_cmd]       # 作业后执行(即使失败也执行)
only: [main, tags]                # 只在这些条件执行(旧语法)
except: [develop]                 # 排除这些条件(旧语法)
rules: [{if: '$CI == "true"'}]    # 条件规则(新语法,推荐)
when: manual | always | on_failure  # 触发方式
needs: [job_name]                 # DAG 依赖
allow_failure: true               # 允许失败
retry: 2                          # 失败重试次数
timeout: 30m                      # 超时时间
tags: [docker, linux]             # Runner 标签筛选

# === 预定义变量 ===
$CI_COMMIT_SHA                    # 提交 SHA
$CI_COMMIT_BRANCH                 # 当前分支
$CI_COMMIT_TAG                    # 当前 tag
$CI_PROJECT_DIR                   # 项目目录
$CI_PIPELINE_ID                   # 流水线 ID
$CI_JOB_TOKEN                     # 作业令牌
$CI_MERGE_REQUEST_IID             # MR 编号

# === 常用模式 ===
# 缓存
cache:
  key: ${CI_COMMIT_REF_SLUG}
  paths: [.pip-cache/]
# 产物
artifacts:
  paths: [dist/]
  expire_in: 1 week
# 环境
environment:
  name: production
  url: https://example.com

参考:GitLab CI/CD 文档 | 更新于 2026 年