GitLab教程(8): Pipeline高级特性与优化

本文将介绍GitLab CI/CD的高级特性,包括并行执行、依赖管理、模板复用和Pipeline优化技巧。

并行执行

parallel关键字

# 将一个Job拆分成多个并行实例

test:
  script:
    - npm run test:shard
  parallel: 5

# 生成5个Job: test 1/5, test 2/5, test 3/5, test 4/5, test 5/5
# 使用 CI_NODE_INDEX 和 CI_NODE_TOTAL 区分

test:
  script:
    - echo "Running shard $CI_NODE_INDEX of $CI_NODE_TOTAL"
    - npm run test -- --shard=$CI_NODE_INDEX/$CI_NODE_TOTAL
  parallel: 4

# 输出示例
# test 1/4: Running shard 1 of 4
# test 2/4: Running shard 2 of 4
# test 3/4: Running shard 3 of 4
# test 4/4: Running shard 4 of 4

parallel:matrix

# 矩阵构建 - 测试多个版本组合

test:
  image: $IMAGE
  script:
    - echo "Testing with $DATABASE"
    - npm run test
  parallel:
    matrix:
      - IMAGE: ["node:16", "node:18", "node:20"]
        DATABASE: ["postgres", "mysql"]

# 生成6个Job:
# test: [node:16, postgres]
# test: [node:16, mysql]
# test: [node:18, postgres]
# test: [node:18, mysql]
# test: [node:20, postgres]
# test: [node:20, mysql]

# 多平台构建
build:
  script:
    - ./build.sh $PLATFORM $ARCH
  parallel:
    matrix:
      - PLATFORM: [linux, windows, macos]
        ARCH: [amd64, arm64]
  artifacts:
    paths:
      - dist/

Job依赖

needs关键字

# 默认情况下,同一stage的job并行,不同stage按顺序
# needs可以跳过stage限制,实现DAG (有向无环图)

stages:
  - build
  - test
  - deploy

build-frontend:
  stage: build
  script: npm run build:frontend
  artifacts:
    paths: [dist/frontend/]

build-backend:
  stage: build
  script: npm run build:backend
  artifacts:
    paths: [dist/backend/]

test-frontend:
  stage: test
  needs: [build-frontend]  # 只等待frontend完成
  script: npm run test:frontend

test-backend:
  stage: test
  needs: [build-backend]  # 只等待backend完成
  script: npm run test:backend

deploy:
  stage: deploy
  needs: [test-frontend, test-backend]
  script: ./deploy.sh

# 执行顺序:
# build-frontend ─────→ test-frontend ─┐
#                                       ├→ deploy
# build-backend ──────→ test-backend ──┘

# 不需要artifacts时
test-quick:
  stage: test
  needs:
    - job: build-frontend
      artifacts: false
  script: npm run test:quick

dependencies关键字

# dependencies控制下载哪些artifacts

build:
  stage: build
  script: npm run build
  artifacts:
    paths:
      - dist/

test:
  stage: test
  script: npm run test
  artifacts:
    paths:
      - coverage/

deploy:
  stage: deploy
  dependencies:
    - build  # 只下载build的artifacts,不下载test的
  script:
    - ls dist/
    - ./deploy.sh

# 不下载任何artifacts
notify:
  stage: deploy
  dependencies: []
  script: ./notify.sh

模板和复用

extends继承

# 定义模板 (以.开头的job不会执行)
.node-template:
  image: node:18
  cache:
    key: ${CI_COMMIT_REF_SLUG}
    paths:
      - node_modules/
  before_script:
    - npm ci

# 继承模板
build:
  extends: .node-template
  stage: build
  script:
    - npm run build

test:
  extends: .node-template
  stage: test
  script:
    - npm run test

lint:
  extends: .node-template
  stage: test
  script:
    - npm run lint

# 多重继承
.docker-template:
  image: docker:24
  services:
    - docker:24-dind

.deploy-template:
  when: manual
  only:
    - main

deploy-prod:
  extends:
    - .docker-template
    - .deploy-template
  script:
    - docker push myapp:latest

include引入外部配置

# 引入本地文件
include:
  - local: '/.gitlab/ci/build.yml'
  - local: '/.gitlab/ci/test.yml'
  - local: '/.gitlab/ci/deploy.yml'

# 引入其他项目的配置
include:
  - project: 'devops/ci-templates'
    ref: main
    file: '/templates/node.yml'

# 引入多个文件
include:
  - project: 'devops/ci-templates'
    ref: v1.0.0
    file:
      - '/templates/build.yml'
      - '/templates/test.yml'
      - '/templates/deploy.yml'

# 引入远程URL
include:
  - remote: 'https://example.com/ci-templates/node.yml'

# 引入GitLab官方模板
include:
  - template: Security/SAST.gitlab-ci.yml
  - template: Security/Dependency-Scanning.gitlab-ci.yml

# 组合使用
include:
  - local: '.gitlab-ci-vars.yml'
  - project: 'devops/ci-templates'
    file: '/node.yml'
  - template: Code-Quality.gitlab-ci.yml

stages:
  - build
  - test
  - deploy

YAML锚点

# 使用YAML锚点复用配置

.default_scripts: &default_scripts
  - echo "Starting job"
  - npm ci

.deploy_scripts: &deploy_scripts
  - echo "Deploying..."
  - ./deploy.sh

build:
  script:
    - *default_scripts
    - npm run build

test:
  script:
    - *default_scripts
    - npm run test

deploy:
  script:
    - *deploy_scripts

环境管理

# 定义部署环境

deploy-staging:
  stage: deploy
  script:
    - ./deploy.sh staging
  environment:
    name: staging
    url: https://staging.example.com
  rules:
    - if: $CI_COMMIT_BRANCH == "develop"

deploy-production:
  stage: deploy
  script:
    - ./deploy.sh production
  environment:
    name: production
    url: https://example.com
  rules:
    - if: $CI_COMMIT_BRANCH == "main"
      when: manual

# 动态环境 (Review Apps)
deploy-review:
  stage: deploy
  script:
    - ./deploy-review.sh $CI_COMMIT_REF_SLUG
  environment:
    name: review/$CI_COMMIT_REF_SLUG
    url: https://$CI_COMMIT_REF_SLUG.review.example.com
    on_stop: stop-review
    auto_stop_in: 1 week
  rules:
    - if: $CI_MERGE_REQUEST_IID

stop-review:
  stage: deploy
  script:
    - ./destroy-review.sh $CI_COMMIT_REF_SLUG
  environment:
    name: review/$CI_COMMIT_REF_SLUG
    action: stop
  rules:
    - if: $CI_MERGE_REQUEST_IID
      when: manual

# 查看环境
# Project > Deployments > Environments

触发器和多项目Pipeline

# 触发子Pipeline

trigger-deploy:
  stage: deploy
  trigger:
    project: devops/deploy-pipeline
    branch: main
    strategy: depend  # 等待子Pipeline完成

# 传递变量
trigger-with-vars:
  stage: deploy
  variables:
    APP_VERSION: $CI_COMMIT_TAG
    DEPLOY_ENV: production
  trigger:
    project: devops/deploy-pipeline

# 触发子Pipeline (同项目)
trigger-child:
  stage: deploy
  trigger:
    include:
      - local: deploy/.gitlab-ci.yml
    strategy: depend

# 多项目Pipeline
deploy-frontend:
  stage: deploy
  trigger:
    project: frontend/web-app

deploy-backend:
  stage: deploy
  trigger:
    project: backend/api-server

资源组

# 使用resource_group确保同一时间只有一个Job访问资源

deploy-production:
  stage: deploy
  script:
    - ./deploy.sh production
  resource_group: production
  # 多个Pipeline的deploy-production Job会排队执行

# 动态资源组
deploy-review:
  stage: deploy
  script:
    - ./deploy-review.sh
  resource_group: review/$CI_COMMIT_REF_SLUG
  # 同一分支的部署会排队
  # 不同分支可以并行

Pipeline优化

缓存优化

# 基于文件内容的缓存key
cache:
  key:
    files:
      - package-lock.json
  paths:
    - node_modules/

# 分离缓存策略
build:
  cache:
    - key: node-modules
      paths:
        - node_modules/
      policy: pull-push  # 读写
    - key: build-cache
      paths:
        - .cache/
      policy: pull  # 只读

test:
  cache:
    key: node-modules
    paths:
      - node_modules/
    policy: pull  # 只读,不更新缓存

使用interruptible

# 允许新Pipeline取消旧Pipeline

workflow:
  auto_cancel:
    on_new_commit: interruptible

build:
  interruptible: true  # 可被取消
  script:
    - npm run build

deploy:
  interruptible: false  # 不可取消
  script:
    - ./deploy.sh

减少不必要的Job

# 只在相关文件变更时运行

frontend-test:
  rules:
    - changes:
        - src/frontend/**/*
        - package.json

backend-test:
  rules:
    - changes:
        - src/backend/**/*
        - pom.xml

docs-build:
  rules:
    - changes:
        - docs/**/*
        - "*.md"

完整优化示例

workflow:
  auto_cancel:
    on_new_commit: interruptible

stages:
  - install
  - build
  - test
  - deploy

.node-defaults:
  image: node:18-alpine
  cache:
    key:
      files:
        - package-lock.json
    paths:
      - node_modules/
    policy: pull

install:
  extends: .node-defaults
  stage: install
  cache:
    policy: pull-push
  script:
    - npm ci
  interruptible: true

build:
  extends: .node-defaults
  stage: build
  needs: [install]
  script:
    - npm run build
  artifacts:
    paths:
      - dist/
    expire_in: 1 day
  interruptible: true

test-unit:
  extends: .node-defaults
  stage: test
  needs: [install]
  script:
    - npm run test:unit
  parallel: 3
  interruptible: true

test-e2e:
  extends: .node-defaults
  stage: test
  needs: [build]
  script:
    - npm run test:e2e
  interruptible: true

deploy:
  stage: deploy
  needs: [build, test-unit, test-e2e]
  script:
    - ./deploy.sh
  resource_group: production
  interruptible: false
  rules:
    - if: $CI_COMMIT_BRANCH == "main"
      when: manual

总结

本文介绍了GitLab CI/CD的高级特性,包括并行执行、DAG依赖、模板复用和Pipeline优化。合理使用这些特性可以大幅提升CI/CD效率。

下一篇我们将学习GitLab与Docker的集成。

发表回复

后才能评论