环境变量

在构建过程中可以使用环境变量,云原生构建 内置了一些默认环境变量

# 声明环境变量

  1. 通过 env 声明环境变量
  2. Pipeline 里声明的环境变量对当前 Pipeline 有效
  3. Job 里声明的环境变量对当前 Job 有效
main:
  push:
    - env:
        RELEASE_MSG: release message
      stages:
        - name: release
          type: git:release
          env:
            RELEASE_NAME: release-1
          options:
            description: ${RELEASE_MSG}
            name: ${RELEASE_NAME}

# 导入环境变量

  1. 通过 imports 指向一个 private 的 Git 仓库文件,可实现将私有票据注入到环境变量
  2. envimportskey 冲突时,优先使用 env
main:
  push:
    - services:
        - docker
      imports: https://xxx/envs.yml
      stages:
        - name: docker info
          script: docker info
        - name: docker login
          script: docker login ${imageDomain} -u $TEST_DOCKER_USER -p $TEST_DOCKER_PWD

https://xxx/envs.yml 内容示例

TEST_DOCKER_USER: your_docker_username
TEST_DOCKER_PWD: your_docker_password
TEST_NPM_USER: your_npm_username
TEST_NPM_PWD: your_npm_password

whatever_key_you_want: whatever_value_you_want

# 变量名限制

在 Shell 中,环境变量名的命名规则有一些限制。根据 POSIX 标准,环境变量名应符合以下规则:

  1. 只能包含字母(大小写均可)、数字和下划线(_)字符。
  2. 第一个字符不能是数字。

不符合上述规则的变量会被忽略

# 导出环境变量

通过 exports 属性可以在 Job 中修改、新增、删除环境变量,生命周期为当前 Pipeline

exports:
  from-key: to-key
  • exports 是一个对象,其中对象的 key 为本 Job 的输出对象的 keyvalue 为映射的环境变量名称。
    • from-key 指定转换前的 key,支持环境变量,支持深层取值,参考 lodash.get
    • to-key 指定转换后的 key

# 从 Jobs 返回值导出环境变量

script 自定义脚本任务,可设置的属性有:

  • code: 返回码

  • stdout: 标准输出

  • stderr: 标准错误

  • info: 标准输出、标准错误,按时序的混合体

    提示

    注意:推荐使用 printf "%s" "hello\nworld" 来输出变量,以消除标准输出流最后的换行符,同时保留 \n 等转义字符。

包含 ififModifyifNewBranch 等判断逻辑时,可设置的属性有:

  • skip: 如果没有跳过,那么返回空字符串;如果跳过了,那么返回因何跳过 ififModifyifNewBranch
- name: use if
  if: exit -1
  exports:
    skip: REASON
- name: tell last
  script: echo $REASON # $REASON 的值为 if 这个字符串

# 增删改查环境变量

main:
  push:
    - env:
        CUSTOM_ENV_DATE_INFO: default
        CUSTOM_ENV_FOR_DELETE: default
      stages:
        - name: set env
          script: echo -n $(date "+%Y-%m-%d %H:%M")
          exports:
            # 新增
            code: CUSTOM_ENV_DATE_CODE
            # 修改
            info: CUSTOM_ENV_DATE_INFO
            # 删除
            CUSTOM_ENV_FOR_DELETE: null
            # 删除
            # CUSTOM_ENV_FOR_DELETE:
        - name: tag
          type: xxx:xxxx
          exports:
            #支持对象深层取值
            nextRelease.gitTag: CUSTOM_ENV_GIT_TAG
        - name: echo env
          script:
            - echo $CUSTOM_ENV_DATE_CODE
            - echo $CUSTOM_ENV_DATE_INFO
            - echo $CUSTOM_ENV_DATE_STDOUT
            - echo $CUSTOM_ENV_FOR_DELETE
            - echo $CUSTOM_ENV_GIT_TAG

# 内置任务中导出环境变量

一些内置任务会有输出结果,可通过 exports 导出为环境变量。

main:
  push:
    - stages:
        - name: xxxx
          type: xxx:xxx
          options:
            product: public
            name: cnb
            dist: release/
          exports:
            version: CUSTOM_ENV_VERSION
            url: CUSTOM_ENV_URL
        - name: echo env
          script:
            - echo $CUSTOM_ENV_VERSION
            - echo $CUSTOM_ENV_URL

# 使用环境变量

# 在 脚本任务 中使用

执行脚本任务时,流水线设置的环境变量作为任务执行时的环境变量

main:
  push:
    - stages:
        - name: test internal env
          # CNB_BRANCH 为内置环境变量
          script: echo $CNB_BRANCH
        - name: test self defined env
          env:
            cat_name: tomcat
          script: echo $cat_name

# 变量替换

配置文件中的一些属性值会进行变量替换。

如有环境变量 env_name=env_value,那么属性值中 $env_name 会被替换成 env_value,若 env_name 无值,则会替换成空字符串。

下面列出了会进行变量替换的属性:

  • 内置任务

内置任务 options 内的属性值和 optionsFrom 会进行变量替换。

# options.yml
name: Nightly
main:
  push:
    - env:
        address: options.yml
        description: publish for xx task
      stages:
        - name: git release
          type: git:release
          # $address 会被替换成 env 中的 "options.yml"
          optionsFrom: $address
          # options.yml 中的 name 会合并到 options 中
          options:
            # $description 会被替换成 env 中的 "publish for xx task"
            description: $description

options 的最终内容为:

name: Nightly
description: publish for xx task
  • 插件任务

插件任务 settings 内的属性值和 settingsFrom 会进行变量替换。

# settings.yml
robot: https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxx
main:
  push:
    - env:
        address: settings.yml
        message: pr check
      stages:
        - name: notify
          image: tencentcom/wecom-message
          # $address 会被替换成 env 中的 "settings.yml"
          settingsFrom: $address
          # settings.yml 中的 robot 会合并到 settings 中
          settings:
            # $message 会被替换成 env 中的 "pr check"
            content: $message

settings 的最终内容为:

robot: https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxx
message: pr check

另外写在 Dockerfile 中的 LABEL 指定的 settingsFrom 同样可以进行变量替换

FROM node:20

LABEL cnb.cool/settings-from="$address"
  • env

env 下声明的属性值可以引用上层 env 中的变量进行替换

# .cnb.yml
main:
  push:
    - env:
        cat_name: tomcat
      stages:
        - name: echo env
          env:
            # 使用上层 env 声明的 cat_name 值进行替换
            name: "cat $cat_name"
            # 输出 cat tomcat
            script: echo $name
  • imports

imports 的属性值以及所声明的文件中的属性值均会进行变量替换。

若 imports 为数组,数组前面文件中声明的变量对数组后面元素有效。

# env1.yml
address: env2.yml
platform: amd64
# env2.yml
# 读取 env1.yml 中的 platform 属性值进行替换
action: build for $platform
# .cnb.yml
main:
  push:
    - imports:
        - env1.yml
        # env1.yml 中声明了 address,$address 会被替换成 env2.yml
        - $address
      stages:
        - name: echo action
          # 读取 env2.yml 中的 action 属性值进行替换
          script: echo $action
  • pipeline.runner.tags
# 构建不同架构下的镜像
.build: &build
  runner:
    tags: cnb:arch:$CNB_PIPELINE_NAME
  services:
    - docker
  stages:
    - name: docker build
      script: echo "docker build for $CNB_PIPELINE_NAME"
main:
  push:
    # 下面 "amd64" 和 "arm64:v8" 会被声明为内置环境变量 CNB_PIPELINE_NAME 的值
    amd64: *build
    "arm64:v8": *build
  • pipeline.docker.volumes
.docker-volume: &docker-volume
  docker:
    image: node:22-alpine
    volumes:
      - $volume_path
main:
  push:
    install:
      env:
        volume_path: node_modules
      <<: *docker-volume
      stages:
        - name: install
          script: npm install axios
        # 通知其他流水线执行
        - name: resolve
          type: cnb:resolve
          options:
            key: install
    build:
      env:
        volume_path: node_modules
      <<: *docker-volume
      stages:
        # 等待 install 流水线
        - name: await
          type: cnb:await
          options:
            key: install
        - name: ls
          script: ls node_modules
  • ifModify
# 不同模块下代码有变更才进行对应模块的编译
.build: &build
  ifModify: $CNB_PIPELINE_NAME/*
  stages:
    - name: build $CNB_PIPELINE_NAME
      script: echo "build $CNB_PIPELINE_NAME"
main:
  push:
    module-a: *build
    module-b: *build
  • name

pipeline.name 和 job.name 的属性值会进行变量替换。

与其他属性值不同的是 name 属性只能使用内置环境变量进行变量替换。

main:
  push:
    - name: build in $CNB_REPO_SLUG
      env:
        platform: amd64
      imports:
        - env1.yml
        - env2.yml
      stages:
        - name: echo
          script: echo "hello world"
  • lock.key
# env.yml
build_key: build key
.build: &build
  imports: env.yml
  lock:
    key: $build_key
  stages:
    - name: echo
      script: echo "hello world"
main:
  push:
    # 以下两条流水线,一条占用了锁成功执行,另一条位占到锁执行失败
    - *build
    - *build
  • allowFailure
main:
  push:
    - env:
        allow_fail: true
      stages:
        - name: echo
          allowFailure: $allow_fail
          # 脚本执行会报错,但 allowFailure 为 true,任务被认为是成功的
          script: echo1 1

# 阻止变量替换

如果不希望 $env_name 被替换,可以通过 \$ 阻止替换

main:
  push:
    - stages:
        - name: git release
          type: git:release
          options:
            name: Development
            # 属性值是 "some code update $description"
            description: some code update \$description