强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

Git 完全指南 / 16 - GitLab 工作流:CI/CD、Runner、Auto DevOps

第十六章:GitLab 工作流

GitLab 是一个完整的 DevOps 平台,提供从规划到监控的全生命周期工具。


16.1 GitLab 概述

GitLab 提供了比 GitHub 更全面的内置 DevOps 功能,特别适合企业私有化部署。

GitLab vs GitHub 对比

特性 GitLab GitHub
CI/CD 内置,功能强大 需要 GitHub Actions
私有仓库 免费无限 免费无限
私有化部署 ✅ 完整支持 需要 GitHub Enterprise
包注册表 内置 npm/Maven/PyPI 需要外部服务
容器注册表 内置 需要 GHCR
代码审查 Merge Request Pull Request
Auto DevOps 需要手动配置
内置安全扫描 需要第三方

16.2 Merge Request (MR)

16.2.1 创建 MR

# 使用 GitLab CLI (glab)
$ glab mr create --title "feat: add user auth" --description "实现用户认证模块"

# 或使用 Git Push Options
$ git push -u origin feature/auth \
  -o merge_request.create \
  -o merge_request.target=main \
  -o merge_request.title="feat: add user auth" \
  -o merge_request.description="实现用户认证" \
  -o merge_request.merge_when_pipeline_succeeds

# 添加审查者
$ git push origin feature/auth \
  -o merge_request.create \
  -o merge_request.reviewer="user1,user2"

16.2.2 MR 模板

创建 .gitlab/merge_request_templates/Default.md

## 变更描述
<!-- 描述此 MR 的变更内容 -->

## 变更类型
- [ ] Feature
- [ ] Bug Fix
- [ ] Refactor
- [ ] Documentation

## 关联 Issue
Closes #

## 测试
- [ ] 单元测试通过
- [ ] 集成测试通过
- [ ] 手动测试通过

## 部署说明
<!-- 是否需要特殊部署步骤 -->

16.3 GitLab CI/CD

16.3.1 .gitlab-ci.yml 基础

# 定义执行阶段
stages:
  - build
  - test
  - deploy

# 定义变量
variables:
  NODE_VERSION: "20"

# 构建阶段
build:
  stage: build
  image: node:${NODE_VERSION}
  script:
    - npm ci
    - npm run build
  artifacts:
    paths:
      - dist/
    expire_in: 1 hour

# 测试阶段
test:
  stage: test
  image: node:${NODE_VERSION}
  script:
    - npm ci
    - npm test
  coverage: '/Statements\s*:\s*(\d+\.?\d*)%/'

# 部署阶段
deploy_staging:
  stage: deploy
  image: alpine
  script:
    - apk add --no-cache rsync openssh
    - rsync -avz dist/ deploy@staging:/var/www/app/
  environment:
    name: staging
    url: https://staging.example.com
  only:
    - develop

deploy_production:
  stage: deploy
  image: alpine
  script:
    - apk add --no-cache rsync openssh
    - rsync -avz dist/ deploy@production:/var/www/app/
  environment:
    name: production
    url: https://example.com
  when: manual
  only:
    - main

16.3.2 复杂工作流示例

stages:
  - lint
  - test
  - build
  - security
  - deploy

# 代码检查
lint:
  stage: lint
  image: node:20
  script:
    - npm ci
    - npm run lint
    - npm run type-check
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
    - if: '$CI_COMMIT_BRANCH == "main"'

# 单元测试矩阵
test:unit:
  stage: test
  image: node:$NODE_VERSION
  parallel:
    matrix:
      - NODE_VERSION: ["18", "20", "22"]
  script:
    - npm ci
    - npm test
  coverage: '/Statements\s*:\s*(\d+\.?\d*)%/'
  artifacts:
    reports:
      junit: junit.xml
      coverage_report:
        coverage_format: cobertura
        path: coverage/cobertura-coverage.xml

# 集成测试
test:integration:
  stage: test
  image: node:20
  services:
    - postgres:15
    - redis:7
  variables:
    POSTGRES_DB: test_db
    POSTGRES_USER: test
    POSTGRES_PASSWORD: test
    DATABASE_URL: "postgresql://test:test@postgres/test_db"
  script:
    - npm ci
    - npm run test:integration

# Docker 构建
build:docker:
  stage: build
  image: docker:24
  services:
    - docker:24-dind
  variables:
    DOCKER_TLS_CERTDIR: "/certs"
  script:
    - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
    - docker tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA $CI_REGISTRY_IMAGE:latest
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
    - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
    - docker push $CI_REGISTRY_IMAGE:latest
  rules:
    - if: '$CI_COMMIT_BRANCH == "main"'

# 安全扫描
include:
  - template: Security/SAST.gitlab-ci.yml
  - template: Security/Dependency-Scanning.gitlab-ci.yml
  - template: Security/Secret-Detection.gitlab-ci.yml

16.3.3 CI/CD 变量管理

# 使用 glab CLI 设置变量
$ glab ci variable set DATABASE_URL "postgresql://..." --scope production
$ glab ci variable set API_KEY "secret-key" --masked

# 在 GitLab 界面设置
# Settings → CI/CD → Variables
变量类型 说明
Protected 仅在受保护分支/标签上可用
Masked 在日志中隐藏
File 将值写入文件,变量为文件路径
Variable 普通字符串变量

16.4 GitLab Runner

16.4.1 Runner 类型

类型 说明 适用场景
Shared Runner GitLab.com 提供 小型项目,快速开始
Group Runner 组级别共享 团队项目
Project Runner 项目专用 特殊环境需求

16.4.2 安装自托管 Runner

# Linux 安装
$ curl -L "https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh" | sudo bash
$ sudo apt install gitlab-runner

# 注册 Runner
$ sudo gitlab-runner register
# Enter the GitLab instance URL: https://gitlab.com/
# Enter the registration token: <from project Settings > CI/CD > Runners>
# Enter a description: my-runner
# Enter tags: docker,linux
# Enter executor: docker
# Enter default Docker image: alpine:latest

# 查看 Runner 状态
$ sudo gitlab-runner status
$ sudo gitlab-runner list

16.4.3 Runner 执行器

执行器 说明 隔离性
shell 直接在主机执行
docker Docker 容器执行
docker+machine 自动伸缩 Docker
kubernetes K8s Pod 执行
virtualbox 虚拟机执行

16.4.4 Runner 配置

# /etc/gitlab-runner/config.toml
concurrent = 4
check_interval = 0

[session_server]
  session_timeout = 1800

[[runners]]
  name = "my-runner"
  url = "https://gitlab.com/"
  token = "xxxxx"
  executor = "docker"
  [runners.docker]
    tls_verify = false
    image = "alpine:latest"
    privileged = false
    disable_entrypoint_overwrite = false
    oom_kill_disable = false
    disable_cache = false
    volumes = ["/cache"]
    shm_size = 0
    pull_policy = ["if-not-present"]

16.5 Auto DevOps

GitLab 的 Auto DevOps 自动检测项目类型并配置完整的 CI/CD 流程。

# .gitlab-ci.yml - 启用 Auto DevOps
include:
  - template: Auto-DevOps.gitlab-ci.yml

variables:
  AUTO_DEVOPS_DEPLOY_TARGET: production
  KUBE_NAMESPACE: my-app

Auto DevOps 自动包含:

  • 构建 Docker 镜像
  • 代码质量扫描 (Code Climate)
  • 安全扫描 (SAST, DAST, Dependency Scanning)
  • 容器扫描
  • 自动部署到 Kubernetes
  • 性能测试

16.6 GitLab 包管理

# 发布 npm 包
publish:
  stage: deploy
  image: node:20
  script:
    - npm ci
    - npm run build
    - npm publish --registry=https://gitlab.com/api/v4/projects/${CI_PROJECT_ID}/packages/npm/
  rules:
    - if: '$CI_COMMIT_TAG'

16.7 GitLab API

# 使用 glab CLI
$ glab api projects/:id/merge_requests | jq '.[].title'

# 使用 curl
$ curl --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
  "https://gitlab.com/api/v4/projects/1234/merge_requests?state=opened"

# 创建 Issue
$ glab issue create --title "Bug report" --description "详细描述"

# 触发流水线
$ glab ci run

业务场景

场景 推荐方案
小型团队 CI/CD Shared Runner + .gitlab-ci.yml
企业私有部署 自建 GitLab + Group Runner
微服务部署 Auto DevOps + Kubernetes
多环境部署 Environment + Manual Trigger
包发布 GitLab Package Registry
安全合规 内置安全扫描模板

扩展阅读


🔗 上一章15 - GitHub 工作流 | 下一章17 - 排错