PracticeVideosBlogFlashcards

11.3 Builders, Substitutions, Triggers, and IAM

Key Takeaways

  • Custom substitution names begin with an underscore.

  • Approval gates apply before the triggered build executes, not to an arbitrary middle step.

  • Build identity, deployer and runtime service account need separate least-privilege permissions.

Last updated: October 2026

Standard Builders vs. Custom Builders

Cloud Build does not require proprietary DSLs; any Docker container image can serve as a builder image.

Standard Cloud Builders

Google Cloud publishes and maintains open-source, builder container images; permissions come from the build identity known as Standard Cloud Builders. Historically hosted on gcr.io/cloud-builders/ and modern mirrors, these images come pre-installed with essential toolchains:

  • docker: Docker CLI client configured to interact with the host Docker daemon.
  • gcloud: Google Cloud SDK CLI for managing cloud resources, IAM, and deployments.
  • kubectl: Kubernetes command-line tool configured to deploy workloads to GKE.
  • git: Git source control client for shallow clones, branch checkouts, and submodule initialization.
  • gsutil: Cloud Storage CLI tool for staging build tarballs and static website assets.
  • Language Runtimes: golang, npm, mvn, gradle, python, bazel.

Custom Builders

When your pipeline requires specialized toolchains not covered by standard builders (such as Terraform, Helm, Ansible, Trivy, or custom compilation scripts), you can create and execute a Custom Builder.

A custom builder is simply any public or private container image containing your required executable:

  1. If public (e.g., Docker Hub or Quay), specify the full image URI in the name field (e.g., hashicorp/terraform:1.7).
  2. If private, build the image in an initial build step, push it to Artifact Registry, and call it in subsequent pipeline steps.
steps:
  # Using a custom builder from Docker Hub to run Helm lint
  - name: 'alpine/helm:3.14.0'
    args: ['lint', './helm/payment-service']

Substitutions and Variables

Substitutions allow developers to parameterize cloudbuild.yaml configurations across multiple deployment environments, branches, and repositories without hardcoding strings.

Built-In Substitutions

Cloud Build provides variables according to invocation context; trigger-only variables can be empty for manual builds:

Variable NameDescriptionExample Value
$PROJECT_IDThe Google Cloud project ID where the build is runningcorp-finance-prod
$BUILD_IDThe unique UUID identifier assigned to the build execution3d4f8a7e-1234-5678-abcd-ef0123456789
$COMMIT_SHAThe complete 40-character Git commit hash triggering the build7c1b2f4893708a984f1839201a0d829374019283
$SHORT_SHAThe first seven characters of the commit SHA7c1b2f4
$BRANCH_NAMEThe Git branch name (available on branch triggers)main or feature/login
$TAG_NAMEThe Git tag name (available on tag triggers)v1.2.0
$REPO_NAMEThe name of the source repositorypayment-service

User-Defined Substitutions & The Underscore Rule

Developers can define custom substitution keys under the substitutions block.

Exam Trap: All user-defined substitution variables MUST begin with an underscore (e.g., $_ENVIRONMENT, $_CLUSTER_NAME, $_RELEASE_TAG). If you declare a custom substitution variable that does not start with an underscore (such as ENVIRONMENT: staging), Cloud Build will reject the configuration with a schema validation error before the build executes.

Substitution Handling Options

For a manually submitted build, Cloud Build normally operates in strict matching mode (substitutionOption: 'MUST_MATCH'). If your YAML template references a substitution variable that is not supplied by the trigger, or if a supplied substitution is never referenced in the configuration, Cloud Build halts execution with an error.

To allow optional parameters across dynamic multi-branch workflows, specify:

options:
  substitutionOption: 'ALLOW_LOOSE'

Triggered builds always use ALLOW_LOOSE. Several built-in source variables have empty defaults even without it; user-defined missing substitution handling must not be mistaken for a required value being validated. Explicitly validate required configuration inside the pipeline.


Build Triggers and Automation

Build Triggers connect source code repositories directly to Cloud Build, automatically launching builds upon incoming webhook events or code repository lifecycle actions.

Supported Source Repositories

Cloud Build natively connects to:

  • GitHub & GitHub Enterprise: Via the official Google Cloud Build GitHub App.
  • Bitbucket Cloud & Server: Via secure OAuth and API tokens.
  • GitLab: Via 2nd gen developer connections.
  • Cloud Source Repositories: Google Cloud's private Git repository service.
  • Webhook Triggers: Arbitrary HTTP targets triggered by third-party systems (such as Jenkins, Spinnaker, or custom Slack bots) using the documented webhook-secret authentication mechanism.

Trigger Filters and Matchers

  • Branch Name / Tag Regex: Specify regex patterns (such as ^main$ or ^v[0-9]+\.[0-9]+\.[0-9]+$) to restrict triggers to production releases or release candidate branches.
  • File Inclusion and Exclusion (includedFiles / ignoredFiles): In mono-repositories containing multiple microservices, code modifications to one service should not trigger rebuilds of all other services. Use glob patterns (such as services/order-api/**) to scope execution:
## Trigger specification snippet
filename: 'services/order-api/cloudbuild.yaml'
includedFiles:
  - 'services/order-api/**'
ignoredFiles:
  - 'services/order-api/docs/**'
  - 'services/order-api/*.md'

Manual Approval Gates

Approval applies to the entire triggered build before it executes, not to an arbitrary middle step. Separate CI and production-deployment builds when tests and artifact creation must finish before a reviewer approves deployment. Give approvers the appropriate role and keep approval, build, and runtime identities distinct. A build that pauses before execution has not yet run its tests.


Service Account Permissions & Least Privilege

When Cloud Build executes, it acts under the identity of a service account. Understanding this identity model is crucial for resolving common permission failures on the exam.

Legacy Default vs. User-Managed Service Accounts

  • Legacy Default Cloud Build Account: Format [PROJECT_NUMBER]@cloudbuild.gserviceaccount.com. The selected default account depends on project history and organization policy; newer projects commonly use the Compute Engine default service account. The legacy account can have the Cloud Build Service Account role, whose role is not an explicit deny: its actual permissions and any additional grants determine access. Do not assume it is selected or sufficiently privileged for a particular deployment.
  • Modern Best Practice (User-Managed Service Accounts): Create a dedicated, user-managed service account (e.g., sa-cloudbuild-runner@my-project.iam.gserviceaccount.com) and associate it directly with the Build Trigger. This adheres to the Principle of Least Privilege and isolates CI/CD permissions per pipeline.

Required IAM Roles for Common Deployment Targets

If your pipeline deploys to Cloud Run or GKE, the Cloud Build service account requires specific IAM grants:

Deployment TargetRequired IAM Role GrantsPurpose
Cloud Runroles/run.developer (Run Admin only for needed additional operations)Permission to deploy new revisions and route traffic
Cloud Run Service Accountroles/iam.serviceAccountUserPermission for Cloud Build to "act as" the runtime service account assigned to the Cloud Run service
Google Kubernetes Engineroles/container.developerPermission to apply Kubernetes manifests and update deployments
Artifact Registryroles/artifactregistry.writerPermission to push Docker images and package manifests
Secret Managerroles/secretmanager.secretAccessorPermission to retrieve API keys, tokens, and deployment credentials

Exam Trap: When Cloud Build fails with Error: Permission 'iam.serviceAccounts.actAs' denied on service account [RUNTIME_SA], granting roles/run.developer (or Run Admin only when the deployment also needs its additional permissions) is insufficient. Cloud Build must also be granted roles/iam.serviceAccountUser on the specific runtime service account that Cloud Run uses, allowing the build process to bind that identity to the newly deployed container revision.

Official references checked October 18, 2026: Google Cloud 1.

Loading diagram...
Cloud Build Worker Pool Network Topologies
Loading diagram...
Cloud Build DAG Pipeline Execution Flow
Test Your Knowledge

A developer writes a custom cloudbuild.yaml file and defines a user-specified variable under the 'substitutions' block as 'ENVIRONMENT: production'. When pushing the commit to trigger a build, Cloud Build fails immediately with an error before executing any pipeline steps. What is the cause of this failure?

A

Custom substitutions must be stored in Secret Manager rather than declared in cloudbuild.yaml

B

Cloud Build requires all substitution values to be specified entirely in lowercase alphanumeric characters

C

User-defined substitution variable keys must begin with an underscore, such as '_ENVIRONMENT'

D

The Cloud Build service account lacks the roles/cloudbuild.builds.editor IAM permission to read substitutions

Sections you finish are checked off in the contents.