Substituting variable values

Usesubstitutions in your build config file to substitute specific variables atbuild time.

Substitutions are helpful for variables whose value isn't known untilbuild time, or to re-use an existing build request with different variablevalues.

Cloud Build provides built-in substitutions or you can define your ownsubstitutions. Usesubstitutions in your build'ssteps andimagesto resolve their values at build time.

This page explains how to use default substitutions or define your ownsubstitutions.

Using default substitutions

Cloud Build provides the following default substitutions for allbuilds:

  • $PROJECT_ID: ID of your Cloud project
  • $BUILD_ID: ID of your build
  • $PROJECT_NUMBER: your project number
  • $LOCATION: the region associated with your build

Cloud Build provides the following default substitutions for buildsinvoked by triggers:

  • $TRIGGER_NAME: the name associated with your trigger
  • $COMMIT_SHA: the commit ID associated with your build
  • $REVISION_ID: the commit ID associated with your build
  • $SHORT_SHA : the first seven characters ofCOMMIT_SHA
  • $REPO_NAME: the name of your repository
  • $REPO_FULL_NAME: the full name of your repository, including either the user or organization
  • $BRANCH_NAME: the name of your branch
  • $TAG_NAME: the name of your tag
  • $REF_NAME: the name of your branch or tag
  • $TRIGGER_BUILD_CONFIG_PATH: the path to your build configuration file usedduring your build execution; otherwise, an empty string if your build isconfigured inline on the trigger or uses aDockerfile orBuildpack.
  • $SERVICE_ACCOUNT_EMAIL: email of the service account you are using for thebuild. This is either a default service account or a user-specified serviceaccount.
  • $SERVICE_ACCOUNT: the resource name of the service account, in the formatprojects/PROJECT_ID/serviceAccounts/SERVICE_ACCOUNT_EMAIL
Note: Both$COMMIT_SHA and$REVISION_ID represent the commit ID associatedwith your build. Support for both substitutions is available.

Cloud Build provides the following GitHub-specific defaultsubstitutions available for pull request triggers:

  • $_HEAD_BRANCH : head branch of the pull request
  • $_BASE_BRANCH : base branch of the pull request
  • $_HEAD_REPO_URL : URL of the head repository of the pull request
  • $_PR_NUMBER : number of the pull request

If a default substitution is not available (such as with sourceless builds,or with builds that use storage source), then occurrences of the missingvariable are replaced with an empty string.

When starting a build usinggcloud builds submit, you can specifyvariables that would normally come from triggered builds with the--substitutions argument. Specifically,you can manually provide values for:

  • $TRIGGER_NAME
  • $COMMIT_SHA
  • $REVISION_ID
  • $SHORT_SHA
  • $REPO_NAME
  • $REPO_FULL_NAME
  • $BRANCH_NAME
  • $TAG_NAME
  • $REF_NAME
  • $TRIGGER_BUILD_CONFIG_PATH
  • $SERVICE_ACCOUNT_EMAIL
  • $SERVICE_ACCOUNT

For example, the following command uses theTAG_NAME substitution:

gcloudbuildssubmit--config=cloudbuild.yaml\--substitutions=TAG_NAME="test"

The following example uses the default substitutions$BUILD_ID,$PROJECT_ID,$PROJECT_NUMBER, and$REVISION_ID.

YAML

steps:# Uses the ubuntu build step:# to run a shell script; and# set env variables for its execution-name:'ubuntu'args:['bash','./myscript.sh']env:-'BUILD=$BUILD_ID'-'PROJECT_ID=$PROJECT_ID'-'PROJECT_NUMBER=$PROJECT_NUMBER'-'REV=$REVISION_ID'# Uses the docker build step to build an image called my-image-name:'gcr.io/cloud-builders/docker'args:['build','-t','${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/my-image','.']# my-image is pushed to Artifact Registryimages:-'${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/my-image'

JSON

{"steps":[{"name":"ubuntu","args":["bash","./myscript.sh"],"env":["BUILD=$BUILD_ID","PROJECT_ID=$PROJECT_ID","PROJECT_NUMBER=$PROJECT_NUMBER","REV=$REVISION_ID"]},{"name":"gcr.io/cloud-builders/docker","args":["build","-t","gcr.io/$PROJECT_ID/my-image","."]}],"images":["gcr.io/$PROJECT_ID/my-image"]}

The following example shows a build request using thedocker build step tobuild an image, then pushes the image to Artifact Registry using the default$PROJECT_ID substitution:

In this example:

  • The build request has one build step, which uses thedocker build step ingcr.io/cloud-builders to build the Docker image.
    • Theargs field in the step specifies the arguments to pass to thedocker command, in this casebuild -t gcr.io/my-project/cb-demo-img .,will be invoked (after$PROJECT_ID is substituted with your project ID).
  • Theimagesfield contains the image's name. If the build is successful, the resultingimage is pushed to Artifact Registry. If the image is not created successfullyby the build, the build will fail.

YAML

steps:-name:gcr.io/cloud-builders/dockerargs:["build","-t","${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/cb-demo-img","."]images:-'${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/cb-demo-img'

JSON

{"steps":[{"name":"gcr.io/cloud-builders/docker","args":["build","-t","${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/cb-demo-img","."]}],"images":["${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/cb-demo-img"]}

Using user-defined substitutions

You can also define your own substitutions. User-defined substitutions must conform to the following rules:

  • Substitutions must begin with an underscore (_) and useonly uppercase-letters and numbers (respecting the regular expression_[A-Z0-9_]+). This prevents conflicts with built-in substitutions. To usean expression starting with$ you must use$$. For example:
    • $FOO is invalid since it is not a built-in substitution.
    • $$FOO evaluates to the literal string$FOO.
  • The number of parameters is limited to 200 parameters. The length of aparameter key is limited to 100 bytes and the length of a parameter value islimited to 4000 bytes.

You can specify variables in one of two ways:$_FOO or${_FOO}:

  • Both$_FOO and${_FOO} evaluate to the value of_FOO. However,${}lets the substitution work without surrounding spaces, which allows forsubstitutions like${_FOO}BAR.
  • $$ lets you include a literal$ in the template. For example:
    • $_FOO evaluates to the value of_FOO.
    • $$_FOO evaluates to the literal string$_FOO.
    • $$$_FOO evaluates to the literal string$ followed by the value of_FOO.

To use the substitutions, use the--substitutionsargument in thegcloud commandor specify them in the config file.

The following example shows a build config with two user-defined substitutionscalled_NODE_VERSION_1 and_NODE_VERSION_2:

YAML

steps:-name:'gcr.io/cloud-builders/docker'args:['build','--build-arg','node_version=${_NODE_VERSION_1}','-t','${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/build-substitutions-nodejs-${_NODE_VERSION_1}','.']-name:'gcr.io/cloud-builders/docker'args:['build','--build-arg','node_version=${_NODE_VERSION_2}','-t','${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/build-substitutions-nodejs-${_NODE_VERSION_2}','.']substitutions:_NODE_VERSION_1:v6.9.1# default value_NODE_VERSION_2:v6.9.2# default valueimages:['${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/build-substitutions-nodejs-${_NODE_VERSION_1}','${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/build-substitutions-nodejs-${_NODE_VERSION_2}']

JSON

{"steps":[{"name":"gcr.io/cloud-builders/docker","args":["build","--build-arg","node_version=${_NODE_VERSION_1}","-t","${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/build-substitutions-nodejs-${_NODE_VERSION_1}","."]},{"name":"gcr.io/cloud-builders/docker","args":["build","--build-arg","node_version=${_NODE_VERSION_2}","-t","${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/build-substitutions-nodejs-${_NODE_VERSION_2}","."]}],"substitutions":{"_NODE_VERSION_1":"v6.9.1","_NODE_VERSION_2":"v6.9.2",},"images":["${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/build-substitutions-nodejs-${_NODE_VERSION_1}","${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/build-substitutions-nodejs-${_NODE_VERSION_2}"]}

To override the substitution value you specified in the build config file,use the--substitutions flag in thegcloud builds submit command. Notethat substitutions are a mapping of variables to values rather than arrays orsequences. You can override default substitution variablevalues except for$PROJECT_ID and$BUILD_ID. The following command overridesthe default value for_NODE_VERSION_1 specified in the previous build configfile:

gcloudbuildssubmit--config=cloudbuild.yaml\--substitutions=_NODE_VERSION_1="v6.9.4",_NODE_VERSION_2="v6.9.5".

By default, the build returns an error if there's amissing substitution variable or a missing substitution. However, you can settheALLOW_LOOSE option to skip this check.

The following snippet prints "hello world" and defines an unused substitution.Because theALLOW_LOOSE substitution option is set, the build will besuccessful despite the missing substitution.

YAML

steps:-name:'ubuntu'args:['echo','helloworld']substitutions:_SUB_VALUE:unusedoptions:substitutionOption:'ALLOW_LOOSE'

JSON

{"steps":[{"name":"ubuntu","args":["echo","hello world"]}],"substitutions":{"_SUB_VALUE":"unused"},"options":{"substitution_option":"ALLOW_LOOSE"}}

If your build is invoked by a trigger, theALLOW_LOOSE option is set bydefault. In this case, your build won't return an error if there is amissing substitution variable or a missing substitution. You cannot overridetheALLOW_LOOSE option for builds invoked by triggers.

If theALLOW_LOOSE option is not specified, unmatched keys in your substitutionsmapping or build request will result in error. For example, if your build requestincludes$_FOO and the substitutions mapping doesn't define_FOO, youwill receive an error after running your build or invoking a trigger if yourtrigger includes substitution variables.

The following substitution variables always contain a default empty-stringvalue even if you don't set theALLOW_LOOSE option:

  • $REPO_NAME
  • $REPO_FULL_NAME
  • $BRANCH_NAME
  • $TAG_NAME
  • $COMMIT_SHA
  • $SHORT_SHA

When defining a substitution variable, you aren't limited to static strings.You also have access to the event payload that invoked your trigger. Theseare available as payload bindings. You can also apply bash parameter expansionson substitution variables and store the resulting string as a newsubstitution variable. To learn more, seeUsing payload bindings and bash parameter expansions in substitutions.

Dynamic substitutions

You can reference the value of another variable within a user-definedsubstitution by setting thedynamicSubstitutions option totrue inyour build config file. If your build is invoked by a trigger, thedynamicSubstitutions field is always set totrue and does not need tobe specified in your build config file. If your build is invoked manually,you must set thedynamicSubstitutions field totrue for bash parameterexpansions to be interpreted when running your build.

The following build config file shows the substitution variable${_IMAGE_NAME} referencing the variable,${PROJECT_ID}. ThedynamicSubstitutions field is set totrue so the referenceis applied when invoking a build manually:

YAML

steps:-name:'gcr.io/cloud-builders/docker'args:['build','-t','${_IMAGE_NAME}','.']substitutions:_IMAGE_NAME:'${_LOCATION}-docker.pkg.dev/${PROJECT_ID}/${_REPOSITORY}/test-image'options:dynamicSubstitutions:true

JSON

{"steps":[{"name":"gcr.io/cloud-builders/docker","args":["build","-t","${_IMAGE_NAME}","."]}],"substitutions":{"_IMAGE_NAME":"${_LOCATION}-docker.pkg.dev/${PROJECT_ID}/${_REPOSITORY}/test-image"},"options":{"dynamic_substitutions":true}}

For more information, seeApplying bash parameter expansions.

Mapping substitutions to environment variables

Scripts don't directly support substitutions, but they support environmentvariables. You can map substitutions to environment variables, eitherautomatically all at once, or manually by defining every environment variableyourself.

Map substitutions automatically

  • At the build level. To automatically map all the substitutions toenvironment variables, which will be available throughout the entire build,setautomapSubstitutions totrue as an option at the build level. Forexample, the following build config file shows the user-definedsubstitution$_USER and the default substitution$PROJECT_ID mapped toenvironment variables:

    YAML

    steps:-name:'ubuntu'script:|#!/usr/bin/env bashecho "Hello $_USER"-name:'ubuntu'script:|#!/usr/bin/env bashecho "Your project ID is $PROJECT_ID"options:automapSubstitutions:truesubstitutions:_USER:"GoogleCloud"

    JSON

    {"steps":[{"name":"ubuntu","script":"#!/usr/bin/env bash echo 'Hello $_USER'"},{"name":"ubuntu","script":"#!/usr/bin/env bash echo 'Your project ID is $PROJECT_ID'"}],"options":{"automap_substitutions":true},"substitutions":{"_USER":"Google Cloud"}}
  • At the step level. To automatically map all the substitutions and makethem available as environment variables in a single step, set theautomapSubstitutions field totrue in that step. In the followingexample, only the second step will show the substitutions correctly,because it's the only one with automatic substitutions mapping enabled:

    YAML

    steps:-name:'ubuntu'script:|#!/usr/bin/env bashecho "Hello $_USER"-name:'ubuntu'script:|#!/usr/bin/env bashecho "Your project ID is $PROJECT_ID"automapSubstitutions:truesubstitutions:_USER:"GoogleCloud"

    JSON

    {"steps":[{"name":"ubuntu","script":"#!/usr/bin/env bash echo 'Hello $_USER'"},{"name":"ubuntu","script":"#!/usr/bin/env bash echo 'Your project ID is $PROJECT_ID'","automap_substitutions":true}],},"substitutions":{"_USER":"Google Cloud"}

    Additionally, you can make the substitutions available as environmentvariables in the entire build, then ignore them in one step. SetautomapSubstitutions totrue at the build level, then set the samefield tofalse in the step where you want to ignore the substitutions. Inthe following example, even though mapping substitutions is enabled at thebuild level, the project ID will not be printed in the second step, becauseautomapSubstitutions is set tofalse in that step:

    YAML

    steps:-name:'ubuntu'script:|#!/usr/bin/env bashecho "Hello $_USER"-name:'ubuntu'script:|#!/usr/bin/env bashecho "Your project ID is $PROJECT_ID"automapSubstitutions:falseoptions:automapSubstitutions:truesubstitutions:_USER:"GoogleCloud"

    JSON

    {"steps":[{"name":"ubuntu","script":"#!/usr/bin/env bash echo 'Hello $_USER'"},{"name":"ubuntu","script":"#!/usr/bin/env bash echo 'Your project ID is $PROJECT_ID'","automap_substitutions":false}],"options":{"automap_substitutions":true},},"substitutions":{"_USER":"Google Cloud"}

Map substitutions manually

You can manually map the substitutions to environment variables. Everyenvironment variable is defined at the step level usingtheenvfield, and the scope of the variables is restricted to the stepwhere they are defined. This field takes a list of keys and values.

The following example shows how to map the substitution$PROJECT_ID to theenvironment variableBAR:

YAML

steps:-name:'ubuntu'env:-'BAR=$PROJECT_ID'script:'echo$BAR'

JSON

{"steps":[{"name":"ubuntu","env":["BAR=$PROJECT_ID"],"script":"echo $BAR"}]}

What's next

Except as otherwise noted, the content of this page is licensed under theCreative Commons Attribution 4.0 License, and code samples are licensed under theApache 2.0 License. For details, see theGoogle Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.

Last updated 2026-02-18 UTC.