跳转至

第四章:变量与缓存

变量类型

预定义变量

job_name:
  script:
    # 项目信息
    - echo "Project: $CI_PROJECT_NAME"
    - echo "Project URL: $CI_PROJECT_URL"
    - echo "Project ID: $CI_PROJECT_ID"

    # 仓库信息
    - echo "Repo: $CI_REPOSITORY_URL"
    - echo "Branch: $CI_COMMIT_REF_NAME"
    - echo "Commit SHA: $CI_COMMIT_SHA"
    - echo "Commit Message: $CI_COMMIT_MESSAGE"
    - echo "Commit Author: $CI_COMMIT_AUTHOR"

    # Pipeline 信息
    - echo "Pipeline ID: $CI_PIPELINE_ID"
    - echo "Pipeline URL: $CI_PIPELINE_URL"
    - echo "Pipeline Source: $CI_PIPELINE_SOURCE"

    # Job 信息
    - echo "Job ID: $CI_JOB_ID"
    - echo "Job Name: $CI_JOB_NAME"
    - echo "Job Stage: $CI_JOB_STAGE"
    - echo "Job URL: $CI_JOB_URL"

    # Runner 信息
    - echo "Runner ID: $CI_RUNNER_ID"
    - echo "Runner Tags: $CI_RUNNER_TAGS"

    # 用户信息
    - echo "User: $GITLAB_USER_LOGIN"
    - echo "User Email: $GITLAB_USER_EMAIL"

    # 合并请求信息
    - echo "MR IID: $CI_MERGE_REQUEST_IID"
    - echo "MR Source Branch: $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME"
    - echo "MR Target Branch: $CI_MERGE_REQUEST_TARGET_BRANCH_NAME"

自定义变量

# 在 .gitlab-ci.yml 中定义
variables:
  APP_NAME: "myapp"
  DEPLOY_ENV: "staging"
  DATABASE_URL: "postgres://localhost:5432/mydb"

# 使用变量
deploy:
  script:
    - echo "Deploying $APP_NAME to $DEPLOY_ENV"

项目变量

GitLab → Settings → CI/CD → Variables

变量类型:
├── Variable        # 普通变量
├── File            # 文件变量
└── Masked          # 掩码变量(日志中隐藏)

变量优先级

优先级从高到低:
1. 触发变量(API 调用时传递)
2. 手动 Pipeline 变量
3. Job 变量
4. Pipeline 变量
5. 项目变量
6. 组变量
7. 实例变量

变量使用

环境变量

job_name:
  variables:
    LOCAL_VAR: "local value"
  script:
    - echo "Global: $GLOBAL_VAR"
    - echo "Local: $LOCAL_VAR"

条件变量

job_name:
  script:
    - |
      if [ "$CI_COMMIT_BRANCH" == "main" ]; then
        export DEPLOY_ENV="production"
      else
        export DEPLOY_ENV="staging"
      fi
    - echo "Deploy to $DEPLOY_ENV"

动态变量

job_name:
  script:
    - export TIMESTAMP=$(date +%Y%m%d%H%M%S)
    - export IMAGE_TAG="$CI_COMMIT_SHA-$TIMESTAMP"
    - echo "Image tag: $IMAGE_TAG"

文件变量

# 定义文件变量(在 GitLab UI 中设置)
# KUBECONFIG: 文件内容

job_name:
  script:
    - kubectl config use-context my-context
    - kubectl get pods

掩码变量

# 敏感信息设置为掩码变量
# 在日志中显示为 [MASKED]

job_name:
  script:
    - echo "API Key: $API_KEY"
    # 输出: API Key: [MASKED]

缓存配置

缓存 Key

# 分支级别缓存
cache:
  key: $CI_COMMIT_REF_SLUG
  paths:
    - node_modules/

# 项目级别缓存
cache:
  key: $CI_PROJECT_ID
  paths:
    - node_modules/

# 文件哈希缓存
cache:
  key:
    files:
      - package-lock.json
      - Gemfile.lock
    prefix: $CI_COMMIT_REF_SLUG
  paths:
    - node_modules/

# 组合 Key
cache:
  key: "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG"
  paths:
    - node_modules/

缓存策略

# 默认:拉取并推送
cache:
  policy: pull-push

# 只拉取
cache:
  policy: pull

# 只推送
cache:
  policy: push

缓存作用域

# 全局缓存
cache:
  key: $CI_COMMIT_REF_SLUG
  paths:
    - node_modules/

# Job 级别缓存
job_name:
  cache:
    key: "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG"
    paths:
      - .npm/
      - node_modules/

缓存失效

# 手动清除缓存
# GitLab → CI/CD → Pipelines → Clear Runner Caches

# 通过变量控制
cache:
  key: "$CI_COMMIT_REF_SLUG-$CACHE_VERSION"
  paths:
    - node_modules/

variables:
  CACHE_VERSION: "v1"  # 修改此值清除缓存

制品管理

制品类型

# 普通制品
artifacts:
  paths:
    - dist/
  expire_in: 1 week

# 报告制品
artifacts:
  reports:
    junit: report.xml
    coverage_report:
      coverage_format: cobertura
      path: coverage.xml

# 代码质量报告
artifacts:
  reports:
    codequality: gl-code-quality-report.json
    sast: gl-sast-report.json
    dependency_scanning: gl-dependency-scanning-report.json

制品配置

job_name:
  artifacts:
    paths:
      - dist/
      - build/
    exclude:
      - dist/*.log
      - build/.cache/
    name: "artifacts-$CI_COMMIT_REF_NAME"
    expire_in: 1 week
    when: always  # always, on_success, on_failure

制品传递

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

test:
  stage: test
  script:
    - ls dist/
  dependencies:
    - build  # 只下载 build 的制品

deploy:
  stage: deploy
  script:
    - rsync -avz dist/ server:/app/
  needs:
    - job: build
      artifacts: true

环境管理

环境定义

deploy:staging:
  stage: deploy
  script:
    - echo "Deploy to staging"
  environment:
    name: staging
    url: https://staging.app.example.com
    on_stop: stop_staging

stop_staging:
  stage: deploy
  script:
    - echo "Stop staging"
  environment:
    name: staging
    action: stop
  when: manual

动态环境

deploy:review:
  stage: deploy
  script:
    - echo "Deploy review app for $CI_COMMIT_REF_NAME"
  environment:
    name: review/$CI_COMMIT_REF_NAME
    url: https://$CI_COMMIT_REF_NAME.app.example.com
    on_stop: stop_review
  only:
    - branches
  except:
    - main

stop_review:
  stage: deploy
  script:
    - echo "Stop review app"
  environment:
    name: review/$CI_COMMIT_REF_NAME
    action: stop
  when: manual
  only:
    - branches
  except:
    - main

环境变量

deploy:production:
  stage: deploy
  script:
    - echo "Deploy to production"
  environment:
    name: production
  variables:
    DEPLOY_ENV: "production"
    KUBE_NAMESPACE: "prod"

实战示例

多环境部署

stages:
  - build
  - deploy

variables:
  REGISTRY: registry.example.com
  IMAGE_NAME: $REGISTRY/myapp

build:
  stage: build
  image: docker:latest
  services:
    - docker:dind
  script:
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $REGISTRY
    - docker build -t $IMAGE_NAME:$CI_COMMIT_SHA .
    - docker push $IMAGE_NAME:$CI_COMMIT_SHA
  only:
    - main
    - develop

.deploy_template:
  image: bitnami/kubectl:latest
  script:
    - kubectl config use-context $KUBE_CONTEXT
    - kubectl set image deployment/$APP_NAME $APP_NAME=$IMAGE_NAME:$CI_COMMIT_SHA -n $KUBE_NAMESPACE
    - kubectl rollout status deployment/$APP_NAME -n $KUBE_NAMESPACE

deploy:staging:
  extends: .deploy_template
  stage: deploy
  environment:
    name: staging
    url: https://staging.app.example.com
  variables:
    KUBE_NAMESPACE: staging
    APP_NAME: myapp
  only:
    - develop
  when: manual

deploy:production:
  extends: .deploy_template
  stage: deploy
  environment:
    name: production
    url: https://app.example.com
  variables:
    KUBE_NAMESPACE: production
    APP_NAME: myapp
  only:
    - main
  when: manual

密钥管理

# 使用 GitLab Secrets
# Settings → CI/CD → Variables

deploy:
  script:
    # SSH 部署
    - eval $(ssh-agent -s)
    - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
    - mkdir -p ~/.ssh
    - chmod 700 ~/.ssh
    - ssh-keyscan $DEPLOY_SERVER >> ~/.ssh/known_hosts
    - ssh $DEPLOY_USER@$DEPLOY_SERVER "docker pull $IMAGE && docker restart app"

    # Kubernetes 部署
    - echo "$KUBE_CONFIG" | base64 -d > ~/.kube/config
    - kubectl apply -f k8s/

小结

本章学习了:

  • ✅ 变量类型和使用
  • ✅ 缓存配置
  • ✅ 制品管理
  • ✅ 环境管理
  • ✅ 实战示例

下一章

第五章:Docker 部署 - 学习 Docker 部署实践。