Environment Variables
About 1513 wordsAbout 5 min
Environment variables can be used during builds. Cloud Native Build
includes some built-in environment variables.
Declaring Environment Variables
- Use
env
to declare environment variables - Variables declared in
Pipeline
are valid for the currentPipeline
- Variables declared in
Job
are valid for the currentJob
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}
Importing Environment Variables
- Use
imports
to import a secrets file, injecting sensitive information into environment variables for subsequent tasks - When there's a conflict between
env
andimports
keys,env
takes precedence
main:
push:
- services:
- docker
# Import secrets file as environment variables
imports: cnb.cool/<your-repo-slug>/-/blob/main/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
Example content of cnb.cool/<your-repo-slug>/-/blob/main/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
Variable Naming Restrictions
In Shell, environment variable names have some restrictions. According to POSIX standards, environment variable names should follow these rules:
- Can only contain letters (upper/lower case), numbers and underscore (_) characters
- First character cannot be a number
Variables that don't meet these rules will be ignored
Exporting Environment Variables
After a Job
completes execution, there is a result
object. You can use exports to export properties from result
to environment variables, with a lifecycle limited to the current Pipeline
.
Syntax format:
exports:
from-key: to-key
from-key
: The property name from theJob result
object to export, supports environment variables and deep property access (similar tolodash.get
)to-key
: The environment variable name to map to
There are three ways to set result:
- Script task execution results
- Parsing custom variables from output
- Built-in task results
Script Task Execution Results
After a script
task executes, the Job result
has these properties:
code
: Return codestdout
: Standard outputstderr
: Standard errorinfo
: Mixed output of stdout and stderr in chronological order
Note: Use printf "%s" "hello\nworld"
to output variables, which removes trailing newlines while preserving escape characters like \n
.
main:
push:
- stages:
- name: set env
script: echo -n $(date "+%Y-%m-%d %H:%M")
exports:
code: CUSTOM_ENV_DATE_CODE
info: CUSTOM_ENV_DATE_INFO
- name: echo env
script:
- echo $CUSTOM_ENV_DATE_CODE
- echo $CUSTOM_ENV_DATE_INFO
For tasks with if
, ifModify
, ifNewBranch
etc. logic, you can set:
skip
: If the task is skipped due to these conditions, contains the skip reason, otherwise empty string
- name: use if
if: exit -1
exports:
skip: REASON
- name: tell last
# $REASON value is the string "if"
script: echo $REASON
Parsing Custom Variables from Output
CI will parse lines in stdout matching ##[set-output key=value]
format and automatically add them to the result
object.
If variable values contain newlines \n
, you can encode them with base64
or escape
.
If a variable value starts with base64,
, Cloud Native Build
will decode the content after base64,
as base64. Otherwise it will unescape the variable value.
Example Node.js code:
// test.js
const value = 'Test string\ntest string';
// Output base64 encoded variable
console.log(`##[set-output redline_msg_base64=base64,${Buffer.from(value, 'utf-8').toString('base64')}]`);
// Output escape encoded variable
console.log(`##[set-output redline_msg_escape=${escape(value)}]`)
main:
push:
- docker:
image: node:20-alpine
stages:
- name: set output env
script: node test.js
# Export variables from test.js as environment variables
exports:
redline_msg_base64: BASE64_KEY
redline_msg_escape: ESCAPE_KEY
- name: echo env
script:
- echo "BASE64_KEY $BASE64_KEY"
- echo "ESCAPE_KEY $ESCAPE_KEY"
Example using echo
:
main:
push:
- stages:
- name: set output env
script: echo "##[set-output redline_msg_base64=base64,$(echo -e "Test string\ntest string" | base64 -w 0)]"
exports:
redline_msg_base64: BASE64_KEY
- name: echo env
script:
- echo -e "BASE64_KEY $BASE64_KEY"
Note: On Unix-like systems, the base64 command adds newlines every 76 characters by default. Use -w 0
to disable line wrapping to ensure CI can parse variables correctly.
For values without \n
, you can output directly:
echo "##[set-output redline_msg=some value]"
Tips
Due to system environment variable length limits, excessively large variable values are invalid.
CI will ignore variable values >= 100KB
. For large values, write to files and parse them yourself.
For sensitive information, consider using the read-file built-in task.
Exporting Environment Variables from Built-in Tasks
Some built-in tasks have output results that can be exported as environment variables via 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
# Supports deep object property access
nextRelease.gitTag: CUSTOM_ENV_GIT_TAG
- name: echo env
script:
- echo $CUSTOM_ENV_VERSION
- echo $CUSTOM_ENV_URL
Refer to each built-in task's documentation for result
content.
Managing Environment Variables
You can override existing environment variables. Setting to empty string or null removes them.
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:
# Add new
code: CUSTOM_ENV_DATE_CODE
# Modify
info: CUSTOM_ENV_DATE_INFO
# Delete
CUSTOM_ENV_FOR_DELETE: null
# Alternative delete syntax
# CUSTOM_ENV_FOR_DELETE:
- 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
Using Environment Variables
In Script Tasks
When executing script tasks, pipeline environment variables are available as task execution environment variables
main:
push:
- stages:
- name: test internal env
# CNB_BRANCH is a built-in environment variable
script: echo $CNB_BRANCH
- name: test self defined env
env:
cat_name: tomcat
script: echo $cat_name
Variable Substitution
Some property values in configuration files undergo variable substitution.
If there's an environment variable env_name=env_value
, then $env_name
in property values will be replaced with env_value
. If env_name
has no value, it's replaced with empty string.
The following properties support variable substitution:
- Built-in tasks
Properties in built-in task options
and optionsFrom
undergo substitution.
# options.yml
name: Nightly
main:
push:
- env:
address: options.yml
description: publish for xx task
stages:
- name: git release
type: git:release
# $address is replaced with "options.yml" from env
optionsFrom: $address
# name from options.yml is merged into options
options:
# $description is replaced with "publish for xx task" from env
description: $description
Final options
content:
name: Nightly
description: publish for xx task
- Plugin tasks
Properties in plugin task settings
and settingsFrom
undergo substitution.
# 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 is replaced with "settings.yml" from env
settingsFrom: $address
# robot from settings.yml is merged into settings
settings:
# $message is replaced with "pr check" from env
content: $message
Final settings
content:
robot: https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxx
message: pr check
Additionally, settingsFrom
specified in Dockerfile LABEL
also supports substitution
FROM node:20
LABEL cnb.cool/settings-from="$address"
- env
Property values under env
can reference variables from parent env
for substitution
# .cnb.yml
main:
push:
- env:
cat_name: tomcat
stages:
- name: echo env
env:
# Use cat_name from parent env
name: "cat $cat_name"
# Outputs "cat tomcat"
script: echo $name
- imports
Property values in imports
and in imported files support substitution.
If imports
is an array, variables declared in earlier files affect later array elements.
# env1.yml
address: env2.yml
platform: amd64
# env2.yml
# Reads platform from env1.yml for substitution
action: build for $platform
# .cnb.yml
main:
push:
- imports:
- env1.yml
# env1.yml declares address, $address is replaced with env2.yml
- $address
stages:
- name: echo action
# Reads action from env2.yml
script: echo $action
- pipeline.runner.tags
# Build images for different architectures
.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" and "arm64:v8" are set as CNB_PIPELINE_NAME values
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
# Notify other pipelines
- name: resolve
type: cnb:resolve
options:
key: install
build:
env:
volume_path: node_modules
<<: *docker-volume
stages:
# Wait for install pipeline
- name: await
type: cnb:await
options:
key: install
- name: ls
script: ls node_modules
- ifModify
# Only build modules with code changes
.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
, stage.name
and job.name
support substitution.
main:
push:
- name: build in $CNB_REPO_SLUG
env:
platform: amd64
imports:
- env1.yml
- env2.yml
stages:
- name: stage_$SOME_ENV
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:
# Of these two pipelines, one will acquire the lock and execute, the other will fail
- *build
- *build
- allowFailure
main:
push:
- env:
allow_fail: true
stages:
- name: echo
allowFailure: $allow_fail
# Script will error but allowFailure is true, so task is considered successful
script: echo1 1
Preventing Variable Substitution
To prevent $env_name
from being substituted, escape it with \$
main:
push:
- stages:
- name: git release
type: git:release
options:
name: Development
# Property value is "some code update $description"
description: some code update \$description
Limitations
Environment variable names must consist of letters, numbers or _
, and cannot start with a number.
Variable values cannot exceed 100KiB
in length.