GitLab CI/CD

GitLab 是一个完整的 DevOps 平台,提供代码托管、CI/CD、项目管理等一站式解决方案。与 GitHub 类似,GitLab 提供 Git 仓库管理功能,两者都内置了 CI/CD 功能(GitLab CI/CD 和 GitHub Actions),无需依赖第三方服务(如 Travis CI、CircleCI、Jenkins)。

文档:docs.gitlab.com

GitLab CI/CD 简介

GitLab CI/CD 是 GitLab 内置的持续集成和持续部署工具。通过在项目根目录添加 .gitlab-ci.yml 文件,你就可以定义自动化的构建、测试和部署流程。

核心概念

scss 复制代码
Pipeline (流水线)
  ├── Stage (阶段)
  │     ├── Job (任务)
  │     ├── Job
  │     └── Job
  ├── Stage
  └── Stage

每次 git push 触发一个 Pipeline
Pipeline 包含多个 Stage(如 build, test, deploy)
同一 Stage 内的 Job 并行执行
不同 Stage 按顺序执行

工作流程

markdown 复制代码
┌─────────────┐
│  git push   │
└──────┬──────┘
       ↓
┌─────────────────┐
│ GitLab 检测到   │
│ .gitlab-ci.yml  │
└──────┬──────────┘
       ↓
┌─────────────────┐
│ 创建 Pipeline   │
└──────┬──────────┘
       ↓
┌─────────────────┐
│ GitLab Runner   │ ← 执行 Job 的服务
│ 执行各个 Job    │
└──────┬──────────┘
       ↓
┌─────────────────┐
│ 反馈执行结果    │
└─────────────────┘

.gitlab-ci.yml 配置详解

基础结构

yaml 复制代码
# .gitlab-ci.yml

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

# 定义 Job(具体任务)
build-job:
  stage: build
  script:
    - echo "Building the app..."
    - npm install
    - npm run build

test-job:
  stage: test
  script:
    - echo "Running tests..."
    - npm run test

deploy-job:
  stage: deploy
  script:
    - echo "Deploying..."
    - npm run deploy

1. stages(阶段定义)

yaml 复制代码
stages:
  - install      # 安装依赖
  - lint         # 代码检查
  - test         # 测试
  - build        # 构建
  - deploy       # 部署

特点:

  • Stage 按顺序执行
  • 只有前一个 Stage 全部成功,才会执行下一个
  • 同一 Stage 内的 Job 并行执行

2. Job 配置

每个 Job 的基本结构:

yaml 复制代码
job-name:
  stage: build           # 属于哪个 Stage
  image: node:20         # 使用的 Docker 镜像
  before_script:         # 在 script 之前执行
    - npm install
  script:                # 主要执行脚本(必需)
    - npm run build
  after_script:          # 在 script 之后执行(即使失败也会执行)
    - echo "Cleanup..."
  cache:                 # 缓存配置
    paths:
      - node_modules/
  artifacts:             # 保存构建产物
    paths:
      - dist/
  only:                  # 仅在特定分支/标签执行
    - main
  except:                # 排除特定分支
    - develop
  when: manual           # 手动触发
  allow_failure: true    # 允许失败
  needs:                 # 依赖其他 Job
    - install-job
  retry: 2               # 失败重试次数

3. image(Docker 镜像)

指定运行 Job 的容器环境:

yaml 复制代码
# 全局指定
image: node:20

# 单个 Job 指定
build-job:
  image: node:20-alpine
  script:
    - npm run build

# 使用私有镜像
test-job:
  image: registry.example.com/my-image:latest
  script:
    - npm test

常用镜像:

  • node:20 - Node.js
  • python:3.11 - Python
  • golang:1.21 - Go
  • alpine:latest - 轻量级 Linux
  • docker:latest - Docker-in-Docker

4. script(执行脚本)

yaml 复制代码
script:
  # 单行命令
  - npm install

  # 多行脚本
  - |
    if [ "$CI_COMMIT_BRANCH" == "main" ]; then
      echo "Building for production"
      npm run build:prod
    else
      echo "Building for development"
      npm run build:dev
    fi

  # 检查命令执行结果
  - npm test || exit 1

  # 链式命令
  - npm install && npm run build && npm test

5. cache(缓存)

加速构建的关键:

yaml 复制代码
# 全局缓存
cache:
  key: ${CI_COMMIT_REF_SLUG}  # 基于分支名生成缓存 key
  paths:
    - node_modules/
    - .npm/
  policy: pull-push  # pull: 只拉取, push: 只推送, pull-push: 默认

# Job 级别缓存
install-job:
  cache:
    key: npm-$CI_COMMIT_REF_SLUG
    paths:
      - node_modules/

# 多个缓存
test-job:
  cache:
    - key: npm-cache
      paths:
        - node_modules/
    - key: build-cache
      paths:
        - dist/

6. artifacts(构建产物)

保存 Job 生成的文件,供后续 Job 使用或下载:

yaml 复制代码
build-job:
  script:
    - npm run build
  artifacts:
    paths:
      - dist/              # 保存 dist 目录
      - coverage/          # 保存测试覆盖率
    exclude:
      - dist/**/*.map      # 排除 sourcemap
    expire_in: 1 week      # 保存 1 周(默认 30 天)
    when: on_success       # on_success, on_failure, always
    reports:
      coverage_report:
        coverage_format: cobertura
        path: coverage/cobertura-coverage.xml

7. needs(Job 依赖)

打破 Stage 顺序限制,实现跨 Stage 并行:

yaml 复制代码
stages:
  - build
  - test
  - deploy

# 传统方式:test 必须等 build stage 全部完成
# build-a -> build-b ->  等待  -> test-a -> test-b

# 使用 needs:test-a 只等待 build-a
build-a:
  stage: build
  script:
    - npm run build:a

build-b:
  stage: build
  script:
    - npm run build:b

test-a:
  stage: test
  needs:
    - build-a  # 只依赖 build-a,不等 build-b
  script:
    - npm run test:a

test-b:
  stage: test
  needs:
    - build-b
  script:
    - npm run test:b

8. only/except 和 rules(条件执行)

传统方式:only/except

yaml 复制代码
# 只在特定分支执行
deploy-job:
  only:
    - main
    - /^release-.*$/  # 正则匹配 release-* 分支
  script:
    - npm run deploy

# 排除特定分支
test-job:
  except:
    - develop
  script:
    - npm test

现代方式:rules(更强大)

yaml 复制代码
# 基于分支和变更文件
test-job:
  script:
    - npm test
  rules:
    - if: '$CI_COMMIT_BRANCH == "main"'
      when: always
    - if: '$CI_COMMIT_BRANCH =~ /^feature-/'
      when: manual
    - changes:
        - "src/**/*.ts"
      when: on_success
    - when: never

# 基于 MR(Merge Request)
mr-pipeline:
  script:
    - npm run lint
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'

# 组合条件
deploy-job:
  script:
    - npm run deploy
  rules:
    - if: '$CI_COMMIT_TAG'  # 有 tag
      when: manual
    - if: '$CI_COMMIT_BRANCH == "main" && $CI_PIPELINE_SOURCE == "push"'
      when: on_success

9. variables(变量)

yaml 复制代码
# 全局变量
variables:
  NODE_ENV: "production"
  API_URL: "https://api.example.com"

# Job 级别变量
build-job:
  variables:
    BUILD_MODE: "release"
  script:
    - echo "Building in $BUILD_MODE mode"
    - echo "API URL: $API_URL"

# 使用 CI 内置变量
deploy-job:
  script:
    - echo "Deploying branch $CI_COMMIT_BRANCH"
    - echo "Commit SHA: $CI_COMMIT_SHA"
    - echo "Pipeline ID: $CI_PIPELINE_ID"

常用内置变量:

  • $CI_COMMIT_BRANCH - 分支名
  • $CI_COMMIT_SHA - Commit SHA
  • $CI_COMMIT_TAG - Tag 名
  • $CI_PROJECT_NAME - 项目名
  • $CI_PIPELINE_ID - Pipeline ID
  • $CI_JOB_NAME - Job 名称
  • $CI_REGISTRY - GitLab 容器镜像仓库地址

10. environment(环境)

定义部署环境,GitLab 会自动追踪部署历史:

yaml 复制代码
deploy-production:
  stage: deploy
  script:
    - npm run deploy
  environment:
    name: production
    url: https://example.com
    on_stop: stop-production  # 指定停止环境的 Job
    auto_stop_in: 1 week      # 自动停止环境

# 动态环境
deploy-review:
  stage: deploy
  script:
    - npm run deploy:review
  environment:
    name: review/$CI_COMMIT_REF_NAME
    url: https://$CI_COMMIT_REF_SLUG.example.com
    on_stop: stop-review
  only:
    - merge_requests

stop-review:
  stage: deploy
  script:
    - npm run cleanup:review
  environment:
    name: review/$CI_COMMIT_REF_NAME
    action: stop
  when: manual

高级功能

1. 多项目 Pipeline

触发其他项目的 Pipeline:

yaml 复制代码
trigger-downstream:
  stage: deploy
  trigger:
    project: group/downstream-project
    branch: main
    strategy: depend  # 等待下游 Pipeline 完成

2. 父子 Pipeline

将复杂 Pipeline 拆分成多个文件:

yaml 复制代码
# .gitlab-ci.yml
trigger-child:
  trigger:
    include: .gitlab-ci-child.yml
    strategy: depend

# .gitlab-ci-child.yml
stages:
  - child-build
  - child-test

child-build:
  stage: child-build
  script:
    - echo "Child pipeline job"

3. include(复用配置)

yaml 复制代码
# 引入本地文件
include:
  - local: .gitlab-ci/build.yml
  - local: .gitlab-ci/deploy.yml

# 引入远程文件
include:
  - remote: 'https://example.com/ci-templates/build.yml'

# 引入项目文件
include:
  - project: 'group/ci-templates'
    ref: main
    file: '/templates/build.yml'

# 引入模板
include:
  - template: Auto-DevOps.gitlab-ci.yml

调试和优化

1. 本地调试 CI

使用 gitlab-runner 在本地运行:

bash 复制代码
# 安装 gitlab-runner
brew install gitlab-runner

# 本地执行 Job
gitlab-runner exec docker build-job --docker-image=node:20

# 调试特定 Job
gitlab-runner exec docker test-job

2. 优化 Pipeline 速度

使用缓存:

yaml 复制代码
cache:
  key: npm-cache
  paths:
    - node_modules/
    - .npm/

并行执行:

yaml 复制代码
test:
  parallel: 4
  script:
    - npm test -- --shard=$CI_NODE_INDEX/$CI_NODE_TOTAL

使用 needs 打破顺序:

yaml 复制代码
build:
  stage: build
  script:
    - npm run build

deploy:
  stage: deploy
  needs:
    - build  # 不等待 build stage 的其他 Job
  script:
    - npm run deploy

减小 Docker 镜像:

yaml 复制代码
# 使用 alpine 版本
image: node:20-alpine

# 或自定义轻量镜像
image: registry.example.com/minimal-node:20

GitLab Runner

GitLab Runner 是执行 CI/CD Job 的服务。

相关推荐
明月心95212 小时前
git remote add 用法
gitlab
only_Klein18 小时前
jenkins流水线报错:Connection reset by peer
ci/cd·kubernetes·gitlab·jenkins·ssl
梁萌2 天前
docker部署gitlab和gitlab runner
docker·eureka·gitlab
johnnyAndCode2 天前
Idea 设置GitLab时使用账密,而不是token的配置方法
gitlab·idea
天外飞雨2 天前
Gitlab使用
gitlab
BUTCHER53 天前
GitLab SSH 密钥配置
运维·ssh·gitlab
明月心9523 天前
GitLab使用
gitlab
明月心9524 天前
gitlab pull requets
gitlab
BUTCHER54 天前
GitLab基本设置
gitlab
张小凡vip4 天前
Kubernetes---gitlab的ci/cd发布基于k8s的项目示例参考
ci/cd·kubernetes·gitlab