You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何减少多环境下GitLab CI带标签配置的重复代码?

重构GitLab CI Terraform作业配置的方案

核心思路

通过集中式环境配置映射+单一通用作业的方式,将所有环境的差异项(extends模板、needs依赖、Runner标签、环境变量)统一管理,避免重复定义多个作业。


方案1:JSON映射+动态变量提取(推荐,易于维护)

适合需要频繁新增/修改环境的场景,所有环境配置集中在一处,新增环境只需修改映射内容。

# 1. 集中定义所有环境的差异配置
variables:
  # 用JSON存储环境与属性的映射,方便用jq提取
  ENV_MAPPING: |
    {
      "main": {
        "runner_tags": "prod-runner",
        "tf_extends": ".terraform-prod",
        "tf_needs": ["build-prod"],
        "tf_env_vars": {"TF_VAR_ENV": "prod", "TF_WORKSPACE": "prod"}
      },
      "staging": {
        "runner_tags": "staging-runner",
        "tf_extends": ".terraform-staging",
        "tf_needs": ["build-staging"],
        "tf_env_vars": {"TF_VAR_ENV": "staging", "TF_WORKSPACE": "staging"}
      },
      "dev": {
        "runner_tags": "dev-runner",
        "tf_extends": ".terraform-dev",
        "tf_needs": ["build-dev"],
        "tf_env_vars": {"TF_VAR_ENV": "dev", "TF_WORKSPACE": "dev"}
      }
    }
  # 统一目标分支:优先取MR目标分支,否则用当前提交分支
  TARGET_BRANCH: "${CI_MERGE_REQUEST_TARGET_BRANCH_NAME:-$CI_COMMIT_BRANCH}"

# 2. 定义通用Terraform作业模板(所有重复逻辑)
.terraform-base:
  script:
    - terraform init
    - terraform plan
    - terraform apply -auto-approve
  artifacts:
    paths:
      - terraform.tfstate
    expire_in: 7d
  cache:
    paths:
      - .terraform/

# 3. 单一通用作业,动态加载对应环境的配置
terraform-deploy:
  # 动态继承环境专属模板+通用模板
  extends: ["$TF_EXTENDS", ".terraform-base"]
  # 动态设置Runner标签
  tags: ["$RUNNER_TAGS"]
  # 动态设置依赖作业
  needs: $TF_NEEDS
  # 动态注入环境变量
  variables: $TF_ENV_VARS
  # 规则:仅匹配映射中存在的分支
  rules:
    - if: '$TARGET_BRANCH =~ /^(main|staging|dev)$/'
      before_script:
        # 用jq从JSON映射中提取当前环境的配置,导出为CI变量
        - export RUNNER_TAGS=$(echo "$ENV_MAPPING" | jq -r --arg branch "$TARGET_BRANCH" '.[$branch].runner_tags')
        - export TF_EXTENDS=$(echo "$ENV_MAPPING" | jq -r --arg branch "$TARGET_BRANCH" '.[$branch].tf_extends')
        - export TF_NEEDS=$(echo "$ENV_MAPPING" | jq -r --arg branch "$TARGET_BRANCH" '.[$branch].tf_needs')
        - export TF_ENV_VARS=$(echo "$ENV_MAPPING" | jq -r --arg branch "$TARGET_BRANCH" '.[$branch].tf_env_vars')

方案2:规则分支匹配+!reference引用(兼容低版本GitLab)

如果你的GitLab版本低于14.0(不支持extends使用变量),可以用!reference引用环境专属配置,避免重复代码。

variables:
  TARGET_BRANCH: "${CI_MERGE_REQUEST_TARGET_BRANCH_NAME:-$CI_COMMIT_BRANCH}"

# 1. 定义通用Terraform模板
.terraform-base:
  script:
    - terraform init
    - terraform plan
    - terraform apply -auto-approve
  artifacts:
    paths:
      - terraform.tfstate
    expire_in: 7d

# 2. 定义各环境的专属配置模板
.terraform-prod-config:
  tags: ["prod-runner"]
  variables:
    TF_VAR_ENV: prod
    TF_WORKSPACE: prod

.terraform-staging-config:
  tags: ["staging-runner"]
  variables:
    TF_VAR_ENV: staging
    TF_WORKSPACE: staging

.terraform-dev-config:
  tags: ["dev-runner"]
  variables:
    TF_VAR_ENV: dev
    TF_WORKSPACE: dev

# 3. 单一通用作业,通过规则匹配加载对应配置
terraform-deploy:
  extends: ".terraform-base"
  rules:
    - if: '$TARGET_BRANCH == "main"'
      needs: ["build-prod"]
      tags: !reference [.terraform-prod-config, tags]
      variables: !reference [.terraform-prod-config, variables]
    - if: '$TARGET_BRANCH == "staging"'
      needs: ["build-staging"]
      tags: !reference [.terraform-staging-config, tags]
      variables: !reference [.terraform-staging-config, variables]
    - if: '$TARGET_BRANCH == "dev"'
      needs: ["build-dev"]
      tags: !reference [.terraform-dev-config, tags]
      variables: !reference [.terraform-dev-config, variables]

关键注意事项

  1. 方案1需要作业镜像预装jq工具(大部分官方Terraform镜像已包含,若没有可在before_script中安装)。
  2. 确保needs的数组格式为JSON字符串(如'["build-prod"]'),GitLab CI才能正确解析。
  3. 若环境模板(如.terraform-prod)包含专属规则或脚本,extends会自动合并这些配置。

内容的提问来源于stack exchange,提问作者Alex Harvey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 13:53:10