GitLab 是一个完整的 DevOps 平台,提供代码托管、CI/CD、项目管理等一站式解决方案。与 GitHub 类似,GitLab 提供 Git 仓库管理功能,两者都内置了 CI/CD 功能(GitLab CI/CD 和 GitHub Actions),无需依赖第三方服务(如 Travis CI、CircleCI、Jenkins)。
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.jspython:3.11
- Pythongolang:1.21
- Goalpine:latest
- 轻量级 Linuxdocker: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 的服务。