GitLab CI YAML 配置深度解析
GitLab CI使用YAML格式的.gitlab-ci.yml文件定义CI/CD流水线,这个配置文件是整个自动化流程的核心。本文详细解析YAML配置的各个组件、语法规则、高级特性和实战配置模式。
📋 YAML 配置基础语法
核心配置元素
yaml
# .gitlab-ci.yml 基础结构
# 全局配置段
image: node:16-alpine # 默认镜像
services: # 全局服务
- redis:6-alpine
- postgres:13
variables: # 全局变量
NODE_ENV: "production"
API_VERSION: "v1"
stages: # 流水线阶段定义
- build
- test
- security
- deploy
- cleanup
# 全局脚本钩子
before_script: # 每个作业前执行
- echo "Starting pipeline"
- date
after_script: # 每个作业后执行
- echo "Job completed"
- cleanup_temp_files
# 作业定义
build_job: # 作业名称
stage: build # 所属阶段
image: maven:3.8-openjdk-11 # 作业专用镜像
script: # 执行脚本
- mvn clean compile
- mvn package
artifacts: # 构件配置
paths:
- target/*.jar
expire_in: 1 hour
cache: # 缓存配置
key: maven-$CI_COMMIT_REF_NAME
paths:
- .m2/repository/
rules: # 执行条件
- if: $CI_COMMIT_BRANCH == "main"yaml
# GitLab CI变量类型和作用域
variables:
# 全局变量
GLOBAL_VAR: "global_value"
# 环境变量
DATABASE_URL: "postgres://localhost:5432/myapp"
# 多行变量
MULTI_LINE_VAR: |
This is a multi-line
variable that can span
multiple lines
# 引用其他变量
APP_URL: "https://$CI_PROJECT_NAME.example.com"
# 条件变量
BUILD_ENV:
value: "production"
description: "Build environment"
# 作业级变量
job_with_variables:
variables:
# 作业专用变量
JOB_SPECIFIC_VAR: "job_value"
# 覆盖全局变量
GLOBAL_VAR: "overridden_value"
script:
- echo "Global var: $GLOBAL_VAR"
- echo "Job var: $JOB_SPECIFIC_VAR"
# 预定义变量使用
predefined_variables_example:
script:
- echo "Pipeline ID: $CI_PIPELINE_ID"
- echo "Commit SHA: $CI_COMMIT_SHA"
- echo "Branch: $CI_COMMIT_BRANCH"
- echo "Project name: $CI_PROJECT_NAME"
- echo "Job stage: $CI_JOB_STAGE"
- echo "Runner description: $CI_RUNNER_DESCRIPTION"
# 受保护变量
protected_variables_usage:
script:
- |
if [ "$CI_COMMIT_REF_PROTECTED" = "true" ]; then
echo "Using protected variables"
echo "Production token: $PROD_API_TOKEN"
echo "SSH key: $PROD_SSH_KEY"
else
echo "Using development variables"
echo "Dev token: $DEV_API_TOKEN"
fi
rules:
- if: $CI_COMMIT_BRANCH == "main"
# 文件变量
file_variables:
variables:
# 引用文件内容作为变量
CONFIG_FILE: file
CERTIFICATE: file
script:
- cat $CONFIG_FILE
- openssl x509 -in $CERTIFICATE -text -nooutyaml
# rules: 现代条件控制语法
rules_examples:
# 基于分支的规则
deploy_main:
script: echo "Deploying to production"
rules:
- if: $CI_COMMIT_BRANCH == "main"
- if: $CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+$/
# 基于变更的规则
test_backend:
script: echo "Testing backend"
rules:
- changes:
- backend/**/*
- api/**/*
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
# 复杂条件组合
security_scan:
script: echo "Running security scan"
rules:
- if: $CI_COMMIT_BRANCH == "main"
when: always
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
when: manual
allow_failure: true
- when: never # 默认不执行
# 变量条件
conditional_deploy:
script: echo "Conditional deployment"
rules:
- if: $DEPLOY_ENABLED == "true" && $CI_COMMIT_BRANCH == "main"
- if: $CI_COMMIT_TAG && $TAG_DEPLOY == "true"
# only/except: 传统条件控制(已弃用,建议使用rules)
legacy_conditions:
deploy_legacy:
script: echo "Legacy deployment"
only:
- main
- /^release\/.*$/
except:
- schedules
test_legacy:
script: echo "Legacy testing"
only:
refs:
- merge_requests
- main
changes:
- src/**/*
variables:
- $ENABLE_TESTS == "true"
# when: 作业执行时机
execution_timing:
# 自动执行
auto_job:
script: echo "Auto execution"
when: on_success # 默认值
# 手动执行
manual_job:
script: echo "Manual execution"
when: manual
# 总是执行
cleanup_job:
script: echo "Always cleanup"
when: always
# 失败时执行
failure_job:
script: echo "On failure"
when: on_failure
# 延迟执行
delayed_job:
script: echo "Delayed execution"
when: delayed
start_in: 30 minutes高级配置特性
yaml
# 并行执行配置
parallel_jobs:
# 基础并行
simple_parallel:
script: echo "Parallel job $CI_NODE_INDEX of $CI_NODE_TOTAL"
parallel: 5
# 矩阵并行
matrix_build:
script:
- echo "Testing with $RUBY_VERSION and $DATABASE"
- bundle install
- bundle exec rspec
parallel:
matrix:
- RUBY_VERSION: ["2.7", "3.0", "3.1"]
DATABASE: ["mysql", "postgres"]
- RUBY_VERSION: "3.2"
DATABASE: "sqlite"
# 复杂矩阵配置
complex_matrix:
image: $IMAGE
script:
- echo "OS: $OS, Version: $VERSION, Arch: $ARCH"
- run_tests.sh
parallel:
matrix:
- IMAGE: "ubuntu:20.04"
OS: "ubuntu"
VERSION: ["20.04", "22.04"]
ARCH: ["amd64", "arm64"]
- IMAGE: "alpine:3.16"
OS: "alpine"
VERSION: "3.16"
ARCH: "amd64"
# 动态并行
dynamic_parallel:
generate_jobs:
stage: prepare
script:
- |
# 生成动态作业配置
echo "Generating parallel jobs..."
for i in {1..10}; do
echo "test_job_$i:" >> generated-jobs.yml
echo " script: echo 'Dynamic job $i'" >> generated-jobs.yml
echo " parallel: 1" >> generated-jobs.yml
done
artifacts:
paths:
- generated-jobs.yml
# 包含生成的作业
include:
- local: generated-jobs.yml
# 资源配置
resource_management:
heavy_job:
script: echo "Heavy computation"
tags:
- high-memory
- gpu
resource_group: heavy-jobs # 资源组限制
light_job:
script: echo "Light task"
tags:
- shared-runneryaml
# needs: DAG流水线依赖
dependency_management:
# 简单依赖
compile:
stage: build
script: gcc -o app main.c
artifacts:
paths:
- app
test:
stage: test
needs: ["compile"] # 只依赖compile作业
script: ./app --test
# 跨阶段依赖
integration_test:
stage: test
needs:
- job: compile
artifacts: true # 下载构件
- job: prepare_data
artifacts: false # 不下载构件,仅等待完成
script:
- ./app --integration-test
- use_prepared_data.sh
# 条件依赖
deploy:
stage: deploy
needs:
- job: test
artifacts: false
- job: security_scan
artifacts: false
optional: true # 可选依赖
script: deploy_application.sh
# 构件管理
artifacts_configuration:
build_artifacts:
script:
- make build
- make docs
artifacts:
# 基础配置
paths:
- build/
- docs/
expire_in: 1 week
when: on_success
# 构件名称
name: "$CI_JOB_NAME-$CI_COMMIT_REF_NAME"
# 排除文件
exclude:
- build/**/*.tmp
- docs/draft/
# 报告类型
reports:
junit: test-results.xml
coverage_report:
coverage_format: cobertura
path: coverage/cobertura-coverage.xml
codequality: codequality.json
sast: security-report.json
dependency_scanning: dependency-scanning.json
container_scanning: container-scanning.json
dast: dast-report.json
license_scanning: license-scanning.json
performance: performance.json
load_performance: load-performance.json
metrics: metrics.txt
# 动态构件路径
dynamic_artifacts:
script:
- build_version=$(cat VERSION)
- make build
- tar -czf "app-${build_version}.tar.gz" build/
artifacts:
paths:
- "app-*.tar.gz"
expire_in: 30 days
# 缓存配置
cache_strategies:
# 基础缓存
basic_cache:
cache:
key: "$CI_COMMIT_REF_NAME"
paths:
- node_modules/
- .npm/
script:
- npm ci --cache .npm
- npm run build
# 多级缓存
multilevel_cache:
cache:
- key:
files:
- package-lock.json
paths:
- node_modules/
- key: "$CI_COMMIT_REF_NAME"
paths:
- .npm/
policy: pull # 只拉取,不推送
script:
- npm ci --cache .npm
- npm run build
# 分布式缓存
distributed_cache:
cache:
key: "global-cache"
paths:
- vendor/
policy: pull-push
script:
- composer install --no-dev --optimize-autoloaderyaml
# 容器镜像配置
image_configuration:
# 全局镜像
image:
name: node:16-alpine
entrypoint: [""] # 覆盖默认入口点
# 作业级镜像
custom_image_job:
image:
name: custom-registry.com/my-image:latest
pull_policy: always
script: echo "Using custom image"
# 私有镜像仓库
private_registry_job:
image:
name: private.registry.com/app:$CI_COMMIT_SHA
pull_policy: if-not-present
before_script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
script: echo "Using private registry image"
# 服务配置
services_configuration:
# 全局服务
services:
- name: postgres:13
alias: database
variables:
POSTGRES_DB: testdb
POSTGRES_USER: testuser
POSTGRES_PASSWORD: testpass
- redis:6-alpine
- name: elasticsearch:7.17.0
alias: search
command: ["elasticsearch", "-Xms512m", "-Xmx512m"]
# 作业级服务
integration_test:
services:
- name: mysql:8.0
alias: mysql
variables:
MYSQL_ROOT_PASSWORD: rootpass
MYSQL_DATABASE: testdb
- name: mongo:5.0
alias: mongodb
variables:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: rootpass
script:
- echo "Testing with MySQL and MongoDB"
- mysql -h mysql -u root -prootpass -e "SHOW DATABASES;"
- mongo --host mongodb --username root --password rootpass
# 网络配置
network_configuration:
custom_network:
image: docker:20.10.16
services:
- name: docker:20.10.16-dind
alias: docker
command: ["dockerd", "--host=tcp://0.0.0.0:2376"]
variables:
DOCKER_HOST: tcp://docker:2376
script:
- docker info
- docker build -t test-image .
# 资源限制
resource_limits:
memory_cpu_limits:
image: python:3.9
script:
- python memory_intensive_task.py
variables:
# 容器资源限制
KUBERNETES_MEMORY_LIMIT: "2Gi"
KUBERNETES_CPU_LIMIT: "1000m"
KUBERNETES_MEMORY_REQUEST: "1Gi"
KUBERNETES_CPU_REQUEST: "500m"🔧 实战配置模式
企业级配置模板
yaml
# Java Spring Boot应用完整流水线
stages:
- validate
- build
- test
- security
- package
- deploy
variables:
MAVEN_OPTS: "-Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository"
MAVEN_CLI_OPTS: "--batch-mode --errors --fail-at-end --show-version"
DOCKER_REGISTRY: "harbor.company.com"
APP_NAME: "spring-boot-app"
# 模板定义
.java_template: &java_template
image: maven:3.8-openjdk-11
cache:
key: maven-$CI_COMMIT_REF_NAME
paths:
- .m2/repository/
before_script:
- mkdir -p .m2/repository
# 代码质量验证
validate:
<<: *java_template
stage: validate
script:
- mvn $MAVEN_CLI_OPTS validate
- mvn $MAVEN_CLI_OPTS spotbugs:check
- mvn $MAVEN_CLI_OPTS checkstyle:check
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_COMMIT_BRANCH == "main"
# 编译构建
compile:
<<: *java_template
stage: build
script:
- mvn $MAVEN_CLI_OPTS clean compile
artifacts:
paths:
- target/classes/
expire_in: 1 hour
# 单元测试
unit_tests:
<<: *java_template
stage: test
needs: ["compile"]
script:
- mvn $MAVEN_CLI_OPTS test
coverage: '/Total.*?([0-9]{1,3})%/'
artifacts:
reports:
junit:
- target/surefire-reports/TEST-*.xml
coverage_report:
coverage_format: jacoco
path: target/site/jacoco/jacoco.xml
paths:
- target/surefire-reports/
expire_in: 1 day
# 集成测试
integration_tests:
<<: *java_template
stage: test
services:
- name: postgres:13
alias: database
variables:
POSTGRES_DB: testdb
POSTGRES_USER: testuser
POSTGRES_PASSWORD: testpass
- redis:6-alpine
variables:
SPRING_PROFILES_ACTIVE: integration
DATABASE_URL: "jdbc:postgresql://database:5432/testdb"
REDIS_URL: "redis://redis:6379"
script:
- mvn $MAVEN_CLI_OPTS verify -Pintegration-tests
artifacts:
reports:
junit:
- target/failsafe-reports/TEST-*.xml
rules:
- if: $CI_COMMIT_BRANCH == "main"
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
when: manual
# 安全扫描
security_scan:
<<: *java_template
stage: security
script:
- mvn $MAVEN_CLI_OPTS dependency-check:check
- mvn $MAVEN_CLI_OPTS org.sonarsource.scanner.maven:sonar-maven-plugin:sonar
artifacts:
reports:
dependency_scanning: target/dependency-check-report.json
variables:
SONAR_HOST_URL: $SONAR_HOST_URL
SONAR_TOKEN: $SONAR_TOKEN
allow_failure: true
# 应用打包
package:
<<: *java_template
stage: package
needs: ["unit_tests"]
script:
- mvn $MAVEN_CLI_OPTS package -DskipTests
- echo "APP_VERSION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout)" >> version.env
artifacts:
paths:
- target/*.jar
reports:
dotenv: version.env
expire_in: 1 week
# Docker镜像构建
build_image:
stage: package
image: docker:20.10.16
services:
- docker:20.10.16-dind
needs: ["package"]
variables:
DOCKER_DRIVER: overlay2
DOCKER_TLS_CERTDIR: "/certs"
before_script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $DOCKER_REGISTRY
script:
- docker build -t $DOCKER_REGISTRY/$CI_PROJECT_PATH:$CI_COMMIT_SHA .
- docker build -t $DOCKER_REGISTRY/$CI_PROJECT_PATH:$APP_VERSION .
- docker push $DOCKER_REGISTRY/$CI_PROJECT_PATH:$CI_COMMIT_SHA
- docker push $DOCKER_REGISTRY/$CI_PROJECT_PATH:$APP_VERSION
rules:
- if: $CI_COMMIT_BRANCH == "main"
- if: $CI_COMMIT_TAG
# 部署到开发环境
deploy_dev:
stage: deploy
image: alpine/helm:latest
needs: ["build_image"]
variables:
ENVIRONMENT: "development"
NAMESPACE: "app-dev"
before_script:
- kubectl config use-context $DEV_KUBE_CONTEXT
script:
- |
helm upgrade --install $APP_NAME ./helm-chart \
--namespace $NAMESPACE \
--create-namespace \
--set image.repository=$DOCKER_REGISTRY/$CI_PROJECT_PATH \
--set image.tag=$CI_COMMIT_SHA \
--set environment=$ENVIRONMENT \
--wait --timeout 10m
environment:
name: development
url: https://app-dev.company.com
on_stop: stop_dev
rules:
- if: $CI_COMMIT_BRANCH == "develop"
# 部署到生产环境
deploy_prod:
stage: deploy
image: alpine/helm:latest
needs: ["security_scan"]
variables:
ENVIRONMENT: "production"
NAMESPACE: "app-prod"
before_script:
- kubectl config use-context $PROD_KUBE_CONTEXT
script:
- |
helm upgrade --install $APP_NAME ./helm-chart \
--namespace $NAMESPACE \
--set image.repository=$DOCKER_REGISTRY/$CI_PROJECT_PATH \
--set image.tag=$APP_VERSION \
--set environment=$ENVIRONMENT \
--set resources.requests.memory=1Gi \
--set resources.limits.memory=2Gi \
--wait --timeout 15m
environment:
name: production
url: https://app.company.com
rules:
- if: $CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+$/
when: manual
# 停止环境
stop_dev:
stage: deploy
image: alpine/helm:latest
script:
- helm uninstall $APP_NAME --namespace app-dev
environment:
name: development
action: stop
when: manualyaml
# 前端React/Vue应用流水线
stages:
- deps
- build
- test
- security
- deploy
variables:
NODE_VERSION: "18"
NPM_CACHE_FOLDER: "$CI_PROJECT_DIR/.npm"
CYPRESS_CACHE_FOLDER: "$CI_PROJECT_DIR/.cypress"
# 依赖安装
install_deps:
stage: deps
image: node:$NODE_VERSION-alpine
cache:
key:
files:
- package-lock.json
paths:
- node_modules/
- $NPM_CACHE_FOLDER
script:
- npm ci --cache $NPM_CACHE_FOLDER --prefer-offline
artifacts:
paths:
- node_modules/
expire_in: 1 hour
# 代码质量检查
lint:
stage: build
image: node:$NODE_VERSION-alpine
needs: ["install_deps"]
script:
- npm run lint
- npm run type-check
artifacts:
reports:
codequality: lint-report.json
# 构建应用
build_app:
stage: build
image: node:$NODE_VERSION-alpine
needs: ["install_deps"]
script:
- npm run build
- echo "BUILD_SIZE=$(du -sh dist/ | cut -f1)" >> build.env
artifacts:
paths:
- dist/
reports:
dotenv: build.env
expire_in: 1 day
variables:
NODE_ENV: "production"
# 单元测试
unit_tests:
stage: test
image: node:$NODE_VERSION-alpine
needs: ["install_deps"]
script:
- npm run test:unit -- --coverage --watchAll=false
coverage: '/All files[^|]*\|[^|]*\s+([\d\.]+)/'
artifacts:
reports:
junit: test-results.xml
coverage_report:
coverage_format: cobertura
path: coverage/cobertura-coverage.xml
paths:
- coverage/
# E2E测试
e2e_tests:
stage: test
image: cypress/included:12.0.0
needs: ["build_app"]
services:
- name: nginx:alpine
alias: app-server
cache:
key: cypress-$CI_COMMIT_REF_NAME
paths:
- $CYPRESS_CACHE_FOLDER
before_script:
- cp -r dist/* /usr/share/nginx/html/
- nginx -g 'daemon off;' &
- sleep 5
script:
- cypress run --config baseUrl=http://app-server
artifacts:
when: on_failure
paths:
- cypress/screenshots/
- cypress/videos/
expire_in: 1 week
rules:
- if: $CI_COMMIT_BRANCH == "main"
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
when: manual
# 安全扫描
security_audit:
stage: security
image: node:$NODE_VERSION-alpine
needs: ["install_deps"]
script:
- npm audit --audit-level high
- npx retire --js --node
allow_failure: true
artifacts:
reports:
dependency_scanning: security-audit.json
# 部署到CDN
deploy_cdn:
stage: deploy
image: amazon/aws-cli:latest
needs: ["build_app", "unit_tests"]
before_script:
- aws configure set aws_access_key_id $AWS_ACCESS_KEY_ID
- aws configure set aws_secret_access_key $AWS_SECRET_ACCESS_KEY
- aws configure set region $AWS_DEFAULT_REGION
script:
- aws s3 sync dist/ s3://$S3_BUCKET_NAME --delete
- aws cloudfront create-invalidation --distribution-id $CLOUDFRONT_DISTRIBUTION_ID --paths "/*"
environment:
name: production
url: https://app.example.com
rules:
- if: $CI_COMMIT_BRANCH == "main"
# 性能测试
lighthouse_audit:
stage: deploy
image: markhobson/node-chrome:latest
needs: ["deploy_cdn"]
script:
- npm install -g lighthouse
- lighthouse https://app.example.com --output json --output-path lighthouse-report.json
- lighthouse https://app.example.com --output html --output-path lighthouse-report.html
artifacts:
reports:
performance: lighthouse-report.json
paths:
- lighthouse-report.html
expire_in: 1 week
rules:
- if: $CI_COMMIT_BRANCH == "main"
when: manualyaml
# 微服务单体仓库(Monorepo)流水线
stages:
- changes
- build
- test
- deploy
variables:
DOCKER_REGISTRY: "harbor.company.com"
KUBERNETES_NAMESPACE: "microservices"
# 检测变更服务
detect_changes:
stage: changes
image: alpine/git:latest
script:
- |
# 检测每个服务的变更
services=(user-service order-service payment-service notification-service)
changed_services=()
for service in "${services[@]}"; do
if git diff --quiet HEAD~1 HEAD -- "services/$service/"; then
echo "No changes in $service"
else
echo "Changes detected in $service"
changed_services+=("$service")
fi
done
# 生成动态变量
echo "CHANGED_SERVICES=${changed_services[*]}" > changes.env
echo "TOTAL_CHANGES=${#changed_services[@]}" >> changes.env
# 为每个变更的服务生成构建标志
for service in "${changed_services[@]}"; do
service_upper=$(echo $service | tr '[:lower:]' '[:upper:]' | tr '-' '_')
echo "BUILD_${service_upper}=true" >> changes.env
done
artifacts:
reports:
dotenv: changes.env
# 服务构建模板
.build_service: &build_service
stage: build
image: docker:20.10.16
services:
- docker:20.10.16-dind
before_script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $DOCKER_REGISTRY
script:
- |
cd services/$SERVICE_NAME
docker build -t $DOCKER_REGISTRY/$CI_PROJECT_PATH/$SERVICE_NAME:$CI_COMMIT_SHA .
docker push $DOCKER_REGISTRY/$CI_PROJECT_PATH/$SERVICE_NAME:$CI_COMMIT_SHA
artifacts:
reports:
dotenv: service-version.env
# 具体服务构建
build_user_service:
<<: *build_service
variables:
SERVICE_NAME: "user-service"
rules:
- if: $BUILD_USER_SERVICE == "true"
build_order_service:
<<: *build_service
variables:
SERVICE_NAME: "order-service"
rules:
- if: $BUILD_ORDER_SERVICE == "true"
build_payment_service:
<<: *build_service
variables:
SERVICE_NAME: "payment-service"
rules:
- if: $BUILD_PAYMENT_SERVICE == "true"
build_notification_service:
<<: *build_service
variables:
SERVICE_NAME: "notification-service"
rules:
- if: $BUILD_NOTIFICATION_SERVICE == "true"
# 集成测试
integration_test:
stage: test
image: docker/compose:latest
services:
- docker:20.10.16-dind
needs:
- job: detect_changes
artifacts: true
script:
- |
if [ "$TOTAL_CHANGES" -gt 0 ]; then
echo "Running integration tests for changed services"
docker-compose -f docker-compose.test.yml up --build --abort-on-container-exit
docker-compose -f docker-compose.test.yml down
else
echo "No services changed, skipping integration tests"
fi
rules:
- if: $TOTAL_CHANGES != "0"
# 部署模板
.deploy_service: &deploy_service
stage: deploy
image: bitnami/kubectl:latest
script:
- |
if [ -n "${!BUILD_FLAG}" ]; then
echo "Deploying $SERVICE_NAME"
envsubst < k8s/$SERVICE_NAME-deployment.yaml | kubectl apply -f -
kubectl rollout status deployment/$SERVICE_NAME -n $KUBERNETES_NAMESPACE
else
echo "No changes in $SERVICE_NAME, skipping deployment"
fi
environment:
name: $CI_COMMIT_REF_NAME
url: https://$SERVICE_NAME-$CI_COMMIT_REF_NAME.company.com
# 具体服务部署
deploy_user_service:
<<: *deploy_service
variables:
SERVICE_NAME: "user-service"
BUILD_FLAG: "BUILD_USER_SERVICE"
needs:
- job: detect_changes
artifacts: true
- job: build_user_service
artifacts: false
optional: true
deploy_order_service:
<<: *deploy_service
variables:
SERVICE_NAME: "order-service"
BUILD_FLAG: "BUILD_ORDER_SERVICE"
needs:
- job: detect_changes
artifacts: true
- job: build_order_service
artifacts: false
optional: true
# 通知部署结果
notify_deployment:
stage: deploy
image: alpine:latest
script:
- |
if [ "$TOTAL_CHANGES" -gt 0 ]; then
echo "Deployment completed for services: $CHANGED_SERVICES"
# 发送Slack通知
curl -X POST -H 'Content-type: application/json' \
--data "{\"text\":\"🚀 Deployed services: $CHANGED_SERVICES\"}" \
$SLACK_WEBHOOK_URL
fi
needs:
- job: detect_changes
artifacts: true
rules:
- if: $TOTAL_CHANGES != "0"
when: always📋 YAML配置面试重点
语法基础类
GitLab CI YAML的基本结构?
- 全局配置元素
- 作业定义规范
- 阶段和依赖关系
- 变量和环境设置
variables的类型和作用域?
- 全局变量vs作业变量
- 预定义变量使用
- 受保护变量机制
- 文件变量的应用
rules与only/except的区别?
- 现代条件控制语法
- 复杂条件组合
- 性能和可维护性对比
- 迁移最佳实践
高级特性类
如何实现复杂的并行构建?
- parallel关键字使用
- 矩阵构建配置
- 动态并行生成
- 资源管理和优化
needs和artifacts的协作机制?
- DAG流水线设计
- 跨阶段依赖配置
- 构件传递策略
- 性能优化考虑
缓存策略的设计原则?
- 缓存键值策略
- 分布式缓存配置
- 多级缓存设计
- 缓存失效处理
实战应用类
企业级配置模板设计?
- YAML模板和继承
- 环境配置管理
- 安全和合规要求
- 可维护性设计
容器化应用的CI/CD配置?
- Docker集成配置
- 镜像构建优化
- 多阶段构建策略
- 安全扫描集成
单体仓库的流水线设计?
- 变更检测机制
- 智能构建策略
- 服务依赖管理
- 部署协调配置
🔗 相关内容
- GitLab CI概述 - GitLab CI/CD平台整体介绍
- GitOps实践指南 - GitOps概念和ArgoCD实现
- CI/CD策略对比 - 不同CI/CD工具的选择策略
- Jenkins Pipeline对比 - Pipeline设计模式对比
GitLab CI的YAML配置是实现高效CI/CD流水线的核心,通过掌握其丰富的语法特性和配置模式,可以构建适应各种复杂场景的自动化工作流。深入理解YAML配置的各个组件和最佳实践,是成为GitOps专家的重要基础。
