Configure GCP Cloud Build Triggers

The gcp:cloudbuild/trigger:Trigger resource, part of the Pulumi GCP provider, defines automated build triggers that respond to repository changes, Pub/Sub messages, webhooks, or manual invocation. This guide focuses on four capabilities: repository-based triggers with branch and tag monitoring, event-driven triggers via Pub/Sub and webhooks, inline build definitions vs external config files, and service account customization and secret management.

Triggers reference repositories (Cloud Source Repositories, GitHub, GitLab, Bitbucket), Pub/Sub topics, Secret Manager secrets, and IAM service accounts. The examples are intentionally small. Combine them with your own repository connections, event sources, and build configurations.

Trigger builds from repository branches with external config

Most CI/CD pipelines monitor a repository branch and execute builds when code changes, referencing a cloudbuild.yaml file in the repository.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const filename_trigger = new gcp.cloudbuild.Trigger("filename-trigger", {
    location: "us-central1",
    triggerTemplate: {
        branchName: "main",
        repoName: "my-repo",
    },
    substitutions: {
        _FOO: "bar",
        _BAZ: "qux",
    },
    filename: "cloudbuild.yaml",
});
import pulumi
import pulumi_gcp as gcp

filename_trigger = gcp.cloudbuild.Trigger("filename-trigger",
    location="us-central1",
    trigger_template={
        "branch_name": "main",
        "repo_name": "my-repo",
    },
    substitutions={
        "_FOO": "bar",
        "_BAZ": "qux",
    },
    filename="cloudbuild.yaml")
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/cloudbuild"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := cloudbuild.NewTrigger(ctx, "filename-trigger", &cloudbuild.TriggerArgs{
			Location: pulumi.String("us-central1"),
			TriggerTemplate: &cloudbuild.TriggerTriggerTemplateArgs{
				BranchName: pulumi.String("main"),
				RepoName:   pulumi.String("my-repo"),
			},
			Substitutions: pulumi.StringMap{
				"_FOO": pulumi.String("bar"),
				"_BAZ": pulumi.String("qux"),
			},
			Filename: pulumi.String("cloudbuild.yaml"),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    var filename_trigger = new Gcp.CloudBuild.Trigger("filename-trigger", new()
    {
        Location = "us-central1",
        TriggerTemplate = new Gcp.CloudBuild.Inputs.TriggerTriggerTemplateArgs
        {
            BranchName = "main",
            RepoName = "my-repo",
        },
        Substitutions = 
        {
            { "_FOO", "bar" },
            { "_BAZ", "qux" },
        },
        Filename = "cloudbuild.yaml",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.cloudbuild.Trigger;
import com.pulumi.gcp.cloudbuild.TriggerArgs;
import com.pulumi.gcp.cloudbuild.inputs.TriggerTriggerTemplateArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var filename_trigger = new Trigger("filename-trigger", TriggerArgs.builder()
            .location("us-central1")
            .triggerTemplate(TriggerTriggerTemplateArgs.builder()
                .branchName("main")
                .repoName("my-repo")
                .build())
            .substitutions(Map.ofEntries(
                Map.entry("_FOO", "bar"),
                Map.entry("_BAZ", "qux")
            ))
            .filename("cloudbuild.yaml")
            .build());

    }
}
resources:
  filename-trigger:
    type: gcp:cloudbuild:Trigger
    properties:
      location: us-central1
      triggerTemplate:
        branchName: main
        repoName: my-repo
      substitutions:
        _FOO: bar
        _BAZ: qux
      filename: cloudbuild.yaml

The triggerTemplate property defines which repository and branch to monitor. When code is pushed to the specified branch, Cloud Build reads the cloudbuild.yaml file from the repository root and executes the defined steps. The substitutions property passes custom variables into the build, accessible as $_FOO and $_BAZ in build steps.

Define build steps inline with artifacts and secrets

Instead of maintaining a separate cloudbuild.yaml file, you can define build logic directly in the trigger configuration.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const build_trigger = new gcp.cloudbuild.Trigger("build-trigger", {
    name: "my-trigger",
    location: "global",
    triggerTemplate: {
        branchName: "main",
        repoName: "my-repo",
    },
    build: {
        steps: [
            {
                name: "gcr.io/cloud-builders/gcloud",
                args: [
                    "storage",
                    "cp",
                    "gs://mybucket/remotefile.zip",
                    "localfile.zip",
                ],
                timeout: "120s",
                secretEnvs: ["MY_SECRET"],
            },
            {
                name: "ubuntu",
                script: "echo hello",
            },
        ],
        source: {
            storageSource: {
                bucket: "mybucket",
                object: "source_code.tar.gz",
            },
        },
        tags: [
            "build",
            "newFeature",
        ],
        substitutions: {
            _FOO: "bar",
            _BAZ: "qux",
        },
        queueTtl: "20s",
        logsBucket: "gs://mybucket/logs",
        secrets: [{
            kmsKeyName: "projects/myProject/locations/global/keyRings/keyring-name/cryptoKeys/key-name",
            secretEnv: {
                PASSWORD: "ZW5jcnlwdGVkLXBhc3N3b3JkCg==",
            },
        }],
        availableSecrets: {
            secretManagers: [{
                env: "MY_SECRET",
                versionName: "projects/myProject/secrets/mySecret/versions/latest",
            }],
        },
        artifacts: {
            images: ["gcr.io/$PROJECT_ID/$REPO_NAME:$COMMIT_SHA"],
            objects: {
                location: "gs://bucket/path/to/somewhere/",
                paths: ["path"],
            },
            npmPackages: [{
                packagePath: "package.json",
                repository: "https://us-west1-npm.pkg.dev/myProject/quickstart-nodejs-repo",
            }],
            pythonPackages: [{
                paths: ["dist/*"],
                repository: "https://us-west1-python.pkg.dev/myProject/quickstart-python-repo",
            }],
            mavenArtifacts: [{
                repository: "https://us-west1-maven.pkg.dev/myProject/quickstart-java-repo",
                path: "/workspace/my-app/target/my-app-1.0.SNAPSHOT.jar",
                artifactId: "my-app",
                groupId: "com.mycompany.app",
                version: "1.0",
            }],
        },
        options: {
            sourceProvenanceHashes: ["MD5"],
            requestedVerifyOption: "VERIFIED",
            machineType: "N1_HIGHCPU_8",
            diskSizeGb: 100,
            substitutionOption: "ALLOW_LOOSE",
            dynamicSubstitutions: true,
            logStreamingOption: "STREAM_OFF",
            workerPool: "pool",
            logging: "LEGACY",
            envs: ["ekey = evalue"],
            secretEnvs: ["secretenv = svalue"],
            volumes: [{
                name: "v1",
                path: "v1",
            }],
        },
    },
});
import pulumi
import pulumi_gcp as gcp

build_trigger = gcp.cloudbuild.Trigger("build-trigger",
    name="my-trigger",
    location="global",
    trigger_template={
        "branch_name": "main",
        "repo_name": "my-repo",
    },
    build={
        "steps": [
            {
                "name": "gcr.io/cloud-builders/gcloud",
                "args": [
                    "storage",
                    "cp",
                    "gs://mybucket/remotefile.zip",
                    "localfile.zip",
                ],
                "timeout": "120s",
                "secret_envs": ["MY_SECRET"],
            },
            {
                "name": "ubuntu",
                "script": "echo hello",
            },
        ],
        "source": {
            "storage_source": {
                "bucket": "mybucket",
                "object": "source_code.tar.gz",
            },
        },
        "tags": [
            "build",
            "newFeature",
        ],
        "substitutions": {
            "_FOO": "bar",
            "_BAZ": "qux",
        },
        "queue_ttl": "20s",
        "logs_bucket": "gs://mybucket/logs",
        "secrets": [{
            "kms_key_name": "projects/myProject/locations/global/keyRings/keyring-name/cryptoKeys/key-name",
            "secret_env": {
                "PASSWORD": "ZW5jcnlwdGVkLXBhc3N3b3JkCg==",
            },
        }],
        "available_secrets": {
            "secret_managers": [{
                "env": "MY_SECRET",
                "version_name": "projects/myProject/secrets/mySecret/versions/latest",
            }],
        },
        "artifacts": {
            "images": ["gcr.io/$PROJECT_ID/$REPO_NAME:$COMMIT_SHA"],
            "objects": {
                "location": "gs://bucket/path/to/somewhere/",
                "paths": ["path"],
            },
            "npm_packages": [{
                "package_path": "package.json",
                "repository": "https://us-west1-npm.pkg.dev/myProject/quickstart-nodejs-repo",
            }],
            "python_packages": [{
                "paths": ["dist/*"],
                "repository": "https://us-west1-python.pkg.dev/myProject/quickstart-python-repo",
            }],
            "maven_artifacts": [{
                "repository": "https://us-west1-maven.pkg.dev/myProject/quickstart-java-repo",
                "path": "/workspace/my-app/target/my-app-1.0.SNAPSHOT.jar",
                "artifact_id": "my-app",
                "group_id": "com.mycompany.app",
                "version": "1.0",
            }],
        },
        "options": {
            "source_provenance_hashes": ["MD5"],
            "requested_verify_option": "VERIFIED",
            "machine_type": "N1_HIGHCPU_8",
            "disk_size_gb": 100,
            "substitution_option": "ALLOW_LOOSE",
            "dynamic_substitutions": True,
            "log_streaming_option": "STREAM_OFF",
            "worker_pool": "pool",
            "logging": "LEGACY",
            "envs": ["ekey = evalue"],
            "secret_envs": ["secretenv = svalue"],
            "volumes": [{
                "name": "v1",
                "path": "v1",
            }],
        },
    })
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/cloudbuild"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := cloudbuild.NewTrigger(ctx, "build-trigger", &cloudbuild.TriggerArgs{
			Name:     pulumi.String("my-trigger"),
			Location: pulumi.String("global"),
			TriggerTemplate: &cloudbuild.TriggerTriggerTemplateArgs{
				BranchName: pulumi.String("main"),
				RepoName:   pulumi.String("my-repo"),
			},
			Build: &cloudbuild.TriggerBuildArgs{
				Steps: cloudbuild.TriggerBuildStepArray{
					&cloudbuild.TriggerBuildStepArgs{
						Name: pulumi.String("gcr.io/cloud-builders/gcloud"),
						Args: pulumi.StringArray{
							pulumi.String("storage"),
							pulumi.String("cp"),
							pulumi.String("gs://mybucket/remotefile.zip"),
							pulumi.String("localfile.zip"),
						},
						Timeout: pulumi.String("120s"),
						SecretEnvs: pulumi.StringArray{
							pulumi.String("MY_SECRET"),
						},
					},
					&cloudbuild.TriggerBuildStepArgs{
						Name:   pulumi.String("ubuntu"),
						Script: pulumi.String("echo hello"),
					},
				},
				Source: &cloudbuild.TriggerBuildSourceArgs{
					StorageSource: &cloudbuild.TriggerBuildSourceStorageSourceArgs{
						Bucket: pulumi.String("mybucket"),
						Object: pulumi.String("source_code.tar.gz"),
					},
				},
				Tags: pulumi.StringArray{
					pulumi.String("build"),
					pulumi.String("newFeature"),
				},
				Substitutions: pulumi.StringMap{
					"_FOO": pulumi.String("bar"),
					"_BAZ": pulumi.String("qux"),
				},
				QueueTtl:   pulumi.String("20s"),
				LogsBucket: pulumi.String("gs://mybucket/logs"),
				Secrets: cloudbuild.TriggerBuildSecretArray{
					&cloudbuild.TriggerBuildSecretArgs{
						KmsKeyName: pulumi.String("projects/myProject/locations/global/keyRings/keyring-name/cryptoKeys/key-name"),
						SecretEnv: pulumi.StringMap{
							"PASSWORD": pulumi.String("ZW5jcnlwdGVkLXBhc3N3b3JkCg=="),
						},
					},
				},
				AvailableSecrets: &cloudbuild.TriggerBuildAvailableSecretsArgs{
					SecretManagers: cloudbuild.TriggerBuildAvailableSecretsSecretManagerArray{
						&cloudbuild.TriggerBuildAvailableSecretsSecretManagerArgs{
							Env:         pulumi.String("MY_SECRET"),
							VersionName: pulumi.String("projects/myProject/secrets/mySecret/versions/latest"),
						},
					},
				},
				Artifacts: &cloudbuild.TriggerBuildArtifactsArgs{
					Images: pulumi.StringArray{
						pulumi.String("gcr.io/$PROJECT_ID/$REPO_NAME:$COMMIT_SHA"),
					},
					Objects: &cloudbuild.TriggerBuildArtifactsObjectsArgs{
						Location: pulumi.String("gs://bucket/path/to/somewhere/"),
						Paths: pulumi.StringArray{
							pulumi.String("path"),
						},
					},
					NpmPackages: cloudbuild.TriggerBuildArtifactsNpmPackageArray{
						&cloudbuild.TriggerBuildArtifactsNpmPackageArgs{
							PackagePath: pulumi.String("package.json"),
							Repository:  pulumi.String("https://us-west1-npm.pkg.dev/myProject/quickstart-nodejs-repo"),
						},
					},
					PythonPackages: cloudbuild.TriggerBuildArtifactsPythonPackageArray{
						&cloudbuild.TriggerBuildArtifactsPythonPackageArgs{
							Paths: pulumi.StringArray{
								pulumi.String("dist/*"),
							},
							Repository: pulumi.String("https://us-west1-python.pkg.dev/myProject/quickstart-python-repo"),
						},
					},
					MavenArtifacts: cloudbuild.TriggerBuildArtifactsMavenArtifactArray{
						&cloudbuild.TriggerBuildArtifactsMavenArtifactArgs{
							Repository: pulumi.String("https://us-west1-maven.pkg.dev/myProject/quickstart-java-repo"),
							Path:       pulumi.String("/workspace/my-app/target/my-app-1.0.SNAPSHOT.jar"),
							ArtifactId: pulumi.String("my-app"),
							GroupId:    pulumi.String("com.mycompany.app"),
							Version:    pulumi.String("1.0"),
						},
					},
				},
				Options: &cloudbuild.TriggerBuildOptionsArgs{
					SourceProvenanceHashes: pulumi.StringArray{
						pulumi.String("MD5"),
					},
					RequestedVerifyOption: pulumi.String("VERIFIED"),
					MachineType:           pulumi.String("N1_HIGHCPU_8"),
					DiskSizeGb:            pulumi.Int(100),
					SubstitutionOption:    pulumi.String("ALLOW_LOOSE"),
					DynamicSubstitutions:  pulumi.Bool(true),
					LogStreamingOption:    pulumi.String("STREAM_OFF"),
					WorkerPool:            pulumi.String("pool"),
					Logging:               pulumi.String("LEGACY"),
					Envs: pulumi.StringArray{
						pulumi.String("ekey = evalue"),
					},
					SecretEnvs: pulumi.StringArray{
						pulumi.String("secretenv = svalue"),
					},
					Volumes: cloudbuild.TriggerBuildOptionsVolumeArray{
						&cloudbuild.TriggerBuildOptionsVolumeArgs{
							Name: pulumi.String("v1"),
							Path: pulumi.String("v1"),
						},
					},
				},
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    var build_trigger = new Gcp.CloudBuild.Trigger("build-trigger", new()
    {
        Name = "my-trigger",
        Location = "global",
        TriggerTemplate = new Gcp.CloudBuild.Inputs.TriggerTriggerTemplateArgs
        {
            BranchName = "main",
            RepoName = "my-repo",
        },
        Build = new Gcp.CloudBuild.Inputs.TriggerBuildArgs
        {
            Steps = new[]
            {
                new Gcp.CloudBuild.Inputs.TriggerBuildStepArgs
                {
                    Name = "gcr.io/cloud-builders/gcloud",
                    Args = new[]
                    {
                        "storage",
                        "cp",
                        "gs://mybucket/remotefile.zip",
                        "localfile.zip",
                    },
                    Timeout = "120s",
                    SecretEnvs = new[]
                    {
                        "MY_SECRET",
                    },
                },
                new Gcp.CloudBuild.Inputs.TriggerBuildStepArgs
                {
                    Name = "ubuntu",
                    Script = "echo hello",
                },
            },
            Source = new Gcp.CloudBuild.Inputs.TriggerBuildSourceArgs
            {
                StorageSource = new Gcp.CloudBuild.Inputs.TriggerBuildSourceStorageSourceArgs
                {
                    Bucket = "mybucket",
                    Object = "source_code.tar.gz",
                },
            },
            Tags = new[]
            {
                "build",
                "newFeature",
            },
            Substitutions = 
            {
                { "_FOO", "bar" },
                { "_BAZ", "qux" },
            },
            QueueTtl = "20s",
            LogsBucket = "gs://mybucket/logs",
            Secrets = new[]
            {
                new Gcp.CloudBuild.Inputs.TriggerBuildSecretArgs
                {
                    KmsKeyName = "projects/myProject/locations/global/keyRings/keyring-name/cryptoKeys/key-name",
                    SecretEnv = 
                    {
                        { "PASSWORD", "ZW5jcnlwdGVkLXBhc3N3b3JkCg==" },
                    },
                },
            },
            AvailableSecrets = new Gcp.CloudBuild.Inputs.TriggerBuildAvailableSecretsArgs
            {
                SecretManagers = new[]
                {
                    new Gcp.CloudBuild.Inputs.TriggerBuildAvailableSecretsSecretManagerArgs
                    {
                        Env = "MY_SECRET",
                        VersionName = "projects/myProject/secrets/mySecret/versions/latest",
                    },
                },
            },
            Artifacts = new Gcp.CloudBuild.Inputs.TriggerBuildArtifactsArgs
            {
                Images = new[]
                {
                    "gcr.io/$PROJECT_ID/$REPO_NAME:$COMMIT_SHA",
                },
                Objects = new Gcp.CloudBuild.Inputs.TriggerBuildArtifactsObjectsArgs
                {
                    Location = "gs://bucket/path/to/somewhere/",
                    Paths = new[]
                    {
                        "path",
                    },
                },
                NpmPackages = new[]
                {
                    new Gcp.CloudBuild.Inputs.TriggerBuildArtifactsNpmPackageArgs
                    {
                        PackagePath = "package.json",
                        Repository = "https://us-west1-npm.pkg.dev/myProject/quickstart-nodejs-repo",
                    },
                },
                PythonPackages = new[]
                {
                    new Gcp.CloudBuild.Inputs.TriggerBuildArtifactsPythonPackageArgs
                    {
                        Paths = new[]
                        {
                            "dist/*",
                        },
                        Repository = "https://us-west1-python.pkg.dev/myProject/quickstart-python-repo",
                    },
                },
                MavenArtifacts = new[]
                {
                    new Gcp.CloudBuild.Inputs.TriggerBuildArtifactsMavenArtifactArgs
                    {
                        Repository = "https://us-west1-maven.pkg.dev/myProject/quickstart-java-repo",
                        Path = "/workspace/my-app/target/my-app-1.0.SNAPSHOT.jar",
                        ArtifactId = "my-app",
                        GroupId = "com.mycompany.app",
                        Version = "1.0",
                    },
                },
            },
            Options = new Gcp.CloudBuild.Inputs.TriggerBuildOptionsArgs
            {
                SourceProvenanceHashes = new[]
                {
                    "MD5",
                },
                RequestedVerifyOption = "VERIFIED",
                MachineType = "N1_HIGHCPU_8",
                DiskSizeGb = 100,
                SubstitutionOption = "ALLOW_LOOSE",
                DynamicSubstitutions = true,
                LogStreamingOption = "STREAM_OFF",
                WorkerPool = "pool",
                Logging = "LEGACY",
                Envs = new[]
                {
                    "ekey = evalue",
                },
                SecretEnvs = new[]
                {
                    "secretenv = svalue",
                },
                Volumes = new[]
                {
                    new Gcp.CloudBuild.Inputs.TriggerBuildOptionsVolumeArgs
                    {
                        Name = "v1",
                        Path = "v1",
                    },
                },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.cloudbuild.Trigger;
import com.pulumi.gcp.cloudbuild.TriggerArgs;
import com.pulumi.gcp.cloudbuild.inputs.TriggerTriggerTemplateArgs;
import com.pulumi.gcp.cloudbuild.inputs.TriggerBuildArgs;
import com.pulumi.gcp.cloudbuild.inputs.TriggerBuildSourceArgs;
import com.pulumi.gcp.cloudbuild.inputs.TriggerBuildSourceStorageSourceArgs;
import com.pulumi.gcp.cloudbuild.inputs.TriggerBuildAvailableSecretsArgs;
import com.pulumi.gcp.cloudbuild.inputs.TriggerBuildArtifactsArgs;
import com.pulumi.gcp.cloudbuild.inputs.TriggerBuildArtifactsObjectsArgs;
import com.pulumi.gcp.cloudbuild.inputs.TriggerBuildOptionsArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var build_trigger = new Trigger("build-trigger", TriggerArgs.builder()
            .name("my-trigger")
            .location("global")
            .triggerTemplate(TriggerTriggerTemplateArgs.builder()
                .branchName("main")
                .repoName("my-repo")
                .build())
            .build(TriggerBuildArgs.builder()
                .steps(                
                    TriggerBuildStepArgs.builder()
                        .name("gcr.io/cloud-builders/gcloud")
                        .args(                        
                            "storage",
                            "cp",
                            "gs://mybucket/remotefile.zip",
                            "localfile.zip")
                        .timeout("120s")
                        .secretEnvs("MY_SECRET")
                        .build(),
                    TriggerBuildStepArgs.builder()
                        .name("ubuntu")
                        .script("echo hello")
                        .build())
                .source(TriggerBuildSourceArgs.builder()
                    .storageSource(TriggerBuildSourceStorageSourceArgs.builder()
                        .bucket("mybucket")
                        .object("source_code.tar.gz")
                        .build())
                    .build())
                .tags(                
                    "build",
                    "newFeature")
                .substitutions(Map.ofEntries(
                    Map.entry("_FOO", "bar"),
                    Map.entry("_BAZ", "qux")
                ))
                .queueTtl("20s")
                .logsBucket("gs://mybucket/logs")
                .secrets(TriggerBuildSecretArgs.builder()
                    .kmsKeyName("projects/myProject/locations/global/keyRings/keyring-name/cryptoKeys/key-name")
                    .secretEnv(Map.of("PASSWORD", "ZW5jcnlwdGVkLXBhc3N3b3JkCg=="))
                    .build())
                .availableSecrets(TriggerBuildAvailableSecretsArgs.builder()
                    .secretManagers(TriggerBuildAvailableSecretsSecretManagerArgs.builder()
                        .env("MY_SECRET")
                        .versionName("projects/myProject/secrets/mySecret/versions/latest")
                        .build())
                    .build())
                .artifacts(TriggerBuildArtifactsArgs.builder()
                    .images("gcr.io/$PROJECT_ID/$REPO_NAME:$COMMIT_SHA")
                    .objects(TriggerBuildArtifactsObjectsArgs.builder()
                        .location("gs://bucket/path/to/somewhere/")
                        .paths("path")
                        .build())
                    .npmPackages(TriggerBuildArtifactsNpmPackageArgs.builder()
                        .packagePath("package.json")
                        .repository("https://us-west1-npm.pkg.dev/myProject/quickstart-nodejs-repo")
                        .build())
                    .pythonPackages(TriggerBuildArtifactsPythonPackageArgs.builder()
                        .paths("dist/*")
                        .repository("https://us-west1-python.pkg.dev/myProject/quickstart-python-repo")
                        .build())
                    .mavenArtifacts(TriggerBuildArtifactsMavenArtifactArgs.builder()
                        .repository("https://us-west1-maven.pkg.dev/myProject/quickstart-java-repo")
                        .path("/workspace/my-app/target/my-app-1.0.SNAPSHOT.jar")
                        .artifactId("my-app")
                        .groupId("com.mycompany.app")
                        .version("1.0")
                        .build())
                    .build())
                .options(TriggerBuildOptionsArgs.builder()
                    .sourceProvenanceHashes("MD5")
                    .requestedVerifyOption("VERIFIED")
                    .machineType("N1_HIGHCPU_8")
                    .diskSizeGb(100)
                    .substitutionOption("ALLOW_LOOSE")
                    .dynamicSubstitutions(true)
                    .logStreamingOption("STREAM_OFF")
                    .workerPool("pool")
                    .logging("LEGACY")
                    .envs("ekey = evalue")
                    .secretEnvs("secretenv = svalue")
                    .volumes(TriggerBuildOptionsVolumeArgs.builder()
                        .name("v1")
                        .path("v1")
                        .build())
                    .build())
                .build())
            .build());

    }
}
resources:
  build-trigger:
    type: gcp:cloudbuild:Trigger
    properties:
      name: my-trigger
      location: global
      triggerTemplate:
        branchName: main
        repoName: my-repo
      build:
        steps:
          - name: gcr.io/cloud-builders/gcloud
            args:
              - storage
              - cp
              - gs://mybucket/remotefile.zip
              - localfile.zip
            timeout: 120s
            secretEnvs:
              - MY_SECRET
          - name: ubuntu
            script: echo hello
        source:
          storageSource:
            bucket: mybucket
            object: source_code.tar.gz
        tags:
          - build
          - newFeature
        substitutions:
          _FOO: bar
          _BAZ: qux
        queueTtl: 20s
        logsBucket: gs://mybucket/logs
        secrets:
          - kmsKeyName: projects/myProject/locations/global/keyRings/keyring-name/cryptoKeys/key-name
            secretEnv:
              PASSWORD: ZW5jcnlwdGVkLXBhc3N3b3JkCg==
        availableSecrets:
          secretManagers:
            - env: MY_SECRET
              versionName: projects/myProject/secrets/mySecret/versions/latest
        artifacts:
          images:
            - gcr.io/$PROJECT_ID/$REPO_NAME:$COMMIT_SHA
          objects:
            location: gs://bucket/path/to/somewhere/
            paths:
              - path
          npmPackages:
            - packagePath: package.json
              repository: https://us-west1-npm.pkg.dev/myProject/quickstart-nodejs-repo
          pythonPackages:
            - paths:
                - dist/*
              repository: https://us-west1-python.pkg.dev/myProject/quickstart-python-repo
          mavenArtifacts:
            - repository: https://us-west1-maven.pkg.dev/myProject/quickstart-java-repo
              path: /workspace/my-app/target/my-app-1.0.SNAPSHOT.jar
              artifactId: my-app
              groupId: com.mycompany.app
              version: '1.0'
        options:
          sourceProvenanceHashes:
            - MD5
          requestedVerifyOption: VERIFIED
          machineType: N1_HIGHCPU_8
          diskSizeGb: 100
          substitutionOption: ALLOW_LOOSE
          dynamicSubstitutions: true
          logStreamingOption: STREAM_OFF
          workerPool: pool
          logging: LEGACY
          envs:
            - ekey = evalue
          secretEnvs:
            - secretenv = svalue
          volumes:
            - name: v1
              path: v1

The build property contains the complete build definition. The steps array defines each build operation, including container images, arguments, and timeouts. The source property specifies where to fetch code (here, from Cloud Storage). The secrets and availableSecrets properties integrate with KMS and Secret Manager for encrypted credentials. The artifacts property defines what to publish after the build completes: container images, Cloud Storage objects, or language-specific packages.

Run builds with a custom service account

Custom service accounts let you apply least-privilege permissions and separate build identities across teams.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const project = gcp.organizations.getProject({});
const cloudbuildServiceAccount = new gcp.serviceaccount.Account("cloudbuild_service_account", {accountId: "cloud-sa"});
const actAs = new gcp.projects.IAMMember("act_as", {
    project: project.then(project => project.projectId),
    role: "roles/iam.serviceAccountUser",
    member: pulumi.interpolate`serviceAccount:${cloudbuildServiceAccount.email}`,
});
const logsWriter = new gcp.projects.IAMMember("logs_writer", {
    project: project.then(project => project.projectId),
    role: "roles/logging.logWriter",
    member: pulumi.interpolate`serviceAccount:${cloudbuildServiceAccount.email}`,
});
const service_account_trigger = new gcp.cloudbuild.Trigger("service-account-trigger", {
    triggerTemplate: {
        branchName: "main",
        repoName: "my-repo",
    },
    serviceAccount: cloudbuildServiceAccount.id,
    filename: "cloudbuild.yaml",
}, {
    dependsOn: [
        actAs,
        logsWriter,
    ],
});
import pulumi
import pulumi_gcp as gcp

project = gcp.organizations.get_project()
cloudbuild_service_account = gcp.serviceaccount.Account("cloudbuild_service_account", account_id="cloud-sa")
act_as = gcp.projects.IAMMember("act_as",
    project=project.project_id,
    role="roles/iam.serviceAccountUser",
    member=cloudbuild_service_account.email.apply(lambda email: f"serviceAccount:{email}"))
logs_writer = gcp.projects.IAMMember("logs_writer",
    project=project.project_id,
    role="roles/logging.logWriter",
    member=cloudbuild_service_account.email.apply(lambda email: f"serviceAccount:{email}"))
service_account_trigger = gcp.cloudbuild.Trigger("service-account-trigger",
    trigger_template={
        "branch_name": "main",
        "repo_name": "my-repo",
    },
    service_account=cloudbuild_service_account.id,
    filename="cloudbuild.yaml",
    opts = pulumi.ResourceOptions(depends_on=[
            act_as,
            logs_writer,
        ]))
package main

import (
	"fmt"

	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/cloudbuild"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/organizations"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/projects"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/serviceaccount"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		project, err := organizations.LookupProject(ctx, &organizations.LookupProjectArgs{}, nil)
		if err != nil {
			return err
		}
		cloudbuildServiceAccount, err := serviceaccount.NewAccount(ctx, "cloudbuild_service_account", &serviceaccount.AccountArgs{
			AccountId: pulumi.String("cloud-sa"),
		})
		if err != nil {
			return err
		}
		actAs, err := projects.NewIAMMember(ctx, "act_as", &projects.IAMMemberArgs{
			Project: pulumi.String(project.ProjectId),
			Role:    pulumi.String("roles/iam.serviceAccountUser"),
			Member: cloudbuildServiceAccount.Email.ApplyT(func(email string) (string, error) {
				return fmt.Sprintf("serviceAccount:%v", email), nil
			}).(pulumi.StringOutput),
		})
		if err != nil {
			return err
		}
		logsWriter, err := projects.NewIAMMember(ctx, "logs_writer", &projects.IAMMemberArgs{
			Project: pulumi.String(project.ProjectId),
			Role:    pulumi.String("roles/logging.logWriter"),
			Member: cloudbuildServiceAccount.Email.ApplyT(func(email string) (string, error) {
				return fmt.Sprintf("serviceAccount:%v", email), nil
			}).(pulumi.StringOutput),
		})
		if err != nil {
			return err
		}
		_, err = cloudbuild.NewTrigger(ctx, "service-account-trigger", &cloudbuild.TriggerArgs{
			TriggerTemplate: &cloudbuild.TriggerTriggerTemplateArgs{
				BranchName: pulumi.String("main"),
				RepoName:   pulumi.String("my-repo"),
			},
			ServiceAccount: cloudbuildServiceAccount.ID(),
			Filename:       pulumi.String("cloudbuild.yaml"),
		}, pulumi.DependsOn([]pulumi.Resource{
			actAs,
			logsWriter,
		}))
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    var project = Gcp.Organizations.GetProject.Invoke();

    var cloudbuildServiceAccount = new Gcp.ServiceAccount.Account("cloudbuild_service_account", new()
    {
        AccountId = "cloud-sa",
    });

    var actAs = new Gcp.Projects.IAMMember("act_as", new()
    {
        Project = project.Apply(getProjectResult => getProjectResult.ProjectId),
        Role = "roles/iam.serviceAccountUser",
        Member = cloudbuildServiceAccount.Email.Apply(email => $"serviceAccount:{email}"),
    });

    var logsWriter = new Gcp.Projects.IAMMember("logs_writer", new()
    {
        Project = project.Apply(getProjectResult => getProjectResult.ProjectId),
        Role = "roles/logging.logWriter",
        Member = cloudbuildServiceAccount.Email.Apply(email => $"serviceAccount:{email}"),
    });

    var service_account_trigger = new Gcp.CloudBuild.Trigger("service-account-trigger", new()
    {
        TriggerTemplate = new Gcp.CloudBuild.Inputs.TriggerTriggerTemplateArgs
        {
            BranchName = "main",
            RepoName = "my-repo",
        },
        ServiceAccount = cloudbuildServiceAccount.Id,
        Filename = "cloudbuild.yaml",
    }, new CustomResourceOptions
    {
        DependsOn =
        {
            actAs,
            logsWriter,
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.organizations.OrganizationsFunctions;
import com.pulumi.gcp.organizations.inputs.GetProjectArgs;
import com.pulumi.gcp.serviceaccount.Account;
import com.pulumi.gcp.serviceaccount.AccountArgs;
import com.pulumi.gcp.projects.IAMMember;
import com.pulumi.gcp.projects.IAMMemberArgs;
import com.pulumi.gcp.cloudbuild.Trigger;
import com.pulumi.gcp.cloudbuild.TriggerArgs;
import com.pulumi.gcp.cloudbuild.inputs.TriggerTriggerTemplateArgs;
import com.pulumi.resources.CustomResourceOptions;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        final var project = OrganizationsFunctions.getProject(GetProjectArgs.builder()
            .build());

        var cloudbuildServiceAccount = new Account("cloudbuildServiceAccount", AccountArgs.builder()
            .accountId("cloud-sa")
            .build());

        var actAs = new IAMMember("actAs", IAMMemberArgs.builder()
            .project(project.projectId())
            .role("roles/iam.serviceAccountUser")
            .member(cloudbuildServiceAccount.email().applyValue(_email -> String.format("serviceAccount:%s", _email)))
            .build());

        var logsWriter = new IAMMember("logsWriter", IAMMemberArgs.builder()
            .project(project.projectId())
            .role("roles/logging.logWriter")
            .member(cloudbuildServiceAccount.email().applyValue(_email -> String.format("serviceAccount:%s", _email)))
            .build());

        var service_account_trigger = new Trigger("service-account-trigger", TriggerArgs.builder()
            .triggerTemplate(TriggerTriggerTemplateArgs.builder()
                .branchName("main")
                .repoName("my-repo")
                .build())
            .serviceAccount(cloudbuildServiceAccount.id())
            .filename("cloudbuild.yaml")
            .build(), CustomResourceOptions.builder()
                .dependsOn(                
                    actAs,
                    logsWriter)
                .build());

    }
}
resources:
  service-account-trigger:
    type: gcp:cloudbuild:Trigger
    properties:
      triggerTemplate:
        branchName: main
        repoName: my-repo
      serviceAccount: ${cloudbuildServiceAccount.id}
      filename: cloudbuild.yaml
    options:
      dependsOn:
        - ${actAs}
        - ${logsWriter}
  cloudbuildServiceAccount:
    type: gcp:serviceaccount:Account
    name: cloudbuild_service_account
    properties:
      accountId: cloud-sa
  actAs:
    type: gcp:projects:IAMMember
    name: act_as
    properties:
      project: ${project.projectId}
      role: roles/iam.serviceAccountUser
      member: serviceAccount:${cloudbuildServiceAccount.email}
  logsWriter:
    type: gcp:projects:IAMMember
    name: logs_writer
    properties:
      project: ${project.projectId}
      role: roles/logging.logWriter
      member: serviceAccount:${cloudbuildServiceAccount.email}
variables:
  project:
    fn::invoke:
      function: gcp:organizations:getProject
      arguments: {}

The serviceAccount property specifies which identity runs the build. The IAMMember resources grant necessary permissions: serviceAccountUser allows Cloud Build to impersonate the account, and logWriter enables writing to Cloud Logging. The dependsOn ensures IAM bindings exist before creating the trigger.

Trigger builds from Pub/Sub messages

Event-driven architectures can trigger builds in response to messages from other systems rather than repository changes.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const mytopic = new gcp.pubsub.Topic("mytopic", {name: "my-topic"});
const pubsub_config_trigger = new gcp.cloudbuild.Trigger("pubsub-config-trigger", {
    location: "us-central1",
    name: "pubsub-trigger",
    description: "acceptance test example pubsub build trigger",
    pubsubConfig: {
        topic: mytopic.id,
    },
    sourceToBuild: {
        uri: "https://hashicorp/terraform-provider-google-beta",
        ref: "refs/heads/main",
        repoType: "GITHUB",
    },
    gitFileSource: {
        path: "cloudbuild.yaml",
        uri: "https://hashicorp/terraform-provider-google-beta",
        revision: "refs/heads/main",
        repoType: "GITHUB",
    },
    substitutions: {
        _ACTION: "$(body.message.data.action)",
    },
    filter: "_ACTION.matches('INSERT')",
});
import pulumi
import pulumi_gcp as gcp

mytopic = gcp.pubsub.Topic("mytopic", name="my-topic")
pubsub_config_trigger = gcp.cloudbuild.Trigger("pubsub-config-trigger",
    location="us-central1",
    name="pubsub-trigger",
    description="acceptance test example pubsub build trigger",
    pubsub_config={
        "topic": mytopic.id,
    },
    source_to_build={
        "uri": "https://hashicorp/terraform-provider-google-beta",
        "ref": "refs/heads/main",
        "repo_type": "GITHUB",
    },
    git_file_source={
        "path": "cloudbuild.yaml",
        "uri": "https://hashicorp/terraform-provider-google-beta",
        "revision": "refs/heads/main",
        "repo_type": "GITHUB",
    },
    substitutions={
        "_ACTION": "$(body.message.data.action)",
    },
    filter="_ACTION.matches('INSERT')")
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/cloudbuild"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/pubsub"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		mytopic, err := pubsub.NewTopic(ctx, "mytopic", &pubsub.TopicArgs{
			Name: pulumi.String("my-topic"),
		})
		if err != nil {
			return err
		}
		_, err = cloudbuild.NewTrigger(ctx, "pubsub-config-trigger", &cloudbuild.TriggerArgs{
			Location:    pulumi.String("us-central1"),
			Name:        pulumi.String("pubsub-trigger"),
			Description: pulumi.String("acceptance test example pubsub build trigger"),
			PubsubConfig: &cloudbuild.TriggerPubsubConfigArgs{
				Topic: mytopic.ID(),
			},
			SourceToBuild: &cloudbuild.TriggerSourceToBuildArgs{
				Uri:      pulumi.String("https://hashicorp/terraform-provider-google-beta"),
				Ref:      pulumi.String("refs/heads/main"),
				RepoType: pulumi.String("GITHUB"),
			},
			GitFileSource: &cloudbuild.TriggerGitFileSourceArgs{
				Path:     pulumi.String("cloudbuild.yaml"),
				Uri:      pulumi.String("https://hashicorp/terraform-provider-google-beta"),
				Revision: pulumi.String("refs/heads/main"),
				RepoType: pulumi.String("GITHUB"),
			},
			Substitutions: pulumi.StringMap{
				"_ACTION": pulumi.String("$(body.message.data.action)"),
			},
			Filter: pulumi.String("_ACTION.matches('INSERT')"),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    var mytopic = new Gcp.PubSub.Topic("mytopic", new()
    {
        Name = "my-topic",
    });

    var pubsub_config_trigger = new Gcp.CloudBuild.Trigger("pubsub-config-trigger", new()
    {
        Location = "us-central1",
        Name = "pubsub-trigger",
        Description = "acceptance test example pubsub build trigger",
        PubsubConfig = new Gcp.CloudBuild.Inputs.TriggerPubsubConfigArgs
        {
            Topic = mytopic.Id,
        },
        SourceToBuild = new Gcp.CloudBuild.Inputs.TriggerSourceToBuildArgs
        {
            Uri = "https://hashicorp/terraform-provider-google-beta",
            Ref = "refs/heads/main",
            RepoType = "GITHUB",
        },
        GitFileSource = new Gcp.CloudBuild.Inputs.TriggerGitFileSourceArgs
        {
            Path = "cloudbuild.yaml",
            Uri = "https://hashicorp/terraform-provider-google-beta",
            Revision = "refs/heads/main",
            RepoType = "GITHUB",
        },
        Substitutions = 
        {
            { "_ACTION", "$(body.message.data.action)" },
        },
        Filter = "_ACTION.matches('INSERT')",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.pubsub.Topic;
import com.pulumi.gcp.pubsub.TopicArgs;
import com.pulumi.gcp.cloudbuild.Trigger;
import com.pulumi.gcp.cloudbuild.TriggerArgs;
import com.pulumi.gcp.cloudbuild.inputs.TriggerPubsubConfigArgs;
import com.pulumi.gcp.cloudbuild.inputs.TriggerSourceToBuildArgs;
import com.pulumi.gcp.cloudbuild.inputs.TriggerGitFileSourceArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var mytopic = new Topic("mytopic", TopicArgs.builder()
            .name("my-topic")
            .build());

        var pubsub_config_trigger = new Trigger("pubsub-config-trigger", TriggerArgs.builder()
            .location("us-central1")
            .name("pubsub-trigger")
            .description("acceptance test example pubsub build trigger")
            .pubsubConfig(TriggerPubsubConfigArgs.builder()
                .topic(mytopic.id())
                .build())
            .sourceToBuild(TriggerSourceToBuildArgs.builder()
                .uri("https://hashicorp/terraform-provider-google-beta")
                .ref("refs/heads/main")
                .repoType("GITHUB")
                .build())
            .gitFileSource(TriggerGitFileSourceArgs.builder()
                .path("cloudbuild.yaml")
                .uri("https://hashicorp/terraform-provider-google-beta")
                .revision("refs/heads/main")
                .repoType("GITHUB")
                .build())
            .substitutions(Map.of("_ACTION", "$(body.message.data.action)"))
            .filter("_ACTION.matches('INSERT')")
            .build());

    }
}
resources:
  mytopic:
    type: gcp:pubsub:Topic
    properties:
      name: my-topic
  pubsub-config-trigger:
    type: gcp:cloudbuild:Trigger
    properties:
      location: us-central1
      name: pubsub-trigger
      description: acceptance test example pubsub build trigger
      pubsubConfig:
        topic: ${mytopic.id}
      sourceToBuild:
        uri: https://hashicorp/terraform-provider-google-beta
        ref: refs/heads/main
        repoType: GITHUB
      gitFileSource:
        path: cloudbuild.yaml
        uri: https://hashicorp/terraform-provider-google-beta
        revision: refs/heads/main
        repoType: GITHUB
      substitutions:
        _ACTION: $(body.message.data.action)
      filter: _ACTION.matches('INSERT')

The pubsubConfig property connects the trigger to a Pub/Sub topic. When a message arrives, Cloud Build evaluates the filter expression against the message payload. If the filter matches, Cloud Build fetches the build configuration from the specified gitFileSource and executes it. The sourceToBuild property tells Cloud Build which repository and ref to check out. The substitutions property extracts data from the Pub/Sub message using $(body.message.data.action) syntax.

Trigger builds from webhook requests

External systems can trigger builds by sending HTTP requests to a webhook URL, authenticated using Secret Manager.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const webhookTriggerSecretKey = new gcp.secretmanager.Secret("webhook_trigger_secret_key", {
    secretId: "webhook-trigger-secret-key",
    replication: {
        userManaged: {
            replicas: [{
                location: "us-central1",
            }],
        },
    },
});
const webhookTriggerSecretKeyData = new gcp.secretmanager.SecretVersion("webhook_trigger_secret_key_data", {
    secret: webhookTriggerSecretKey.id,
    secretData: "secretkeygoeshere",
});
const project = gcp.organizations.getProject({});
const secretAccessor = project.then(project => gcp.organizations.getIAMPolicy({
    bindings: [{
        role: "roles/secretmanager.secretAccessor",
        members: [`serviceAccount:service-${project.number}@gcp-sa-cloudbuild.iam.gserviceaccount.com`],
    }],
}));
const policy = new gcp.secretmanager.SecretIamPolicy("policy", {
    project: webhookTriggerSecretKey.project,
    secretId: webhookTriggerSecretKey.secretId,
    policyData: secretAccessor.then(secretAccessor => secretAccessor.policyData),
});
const webhook_config_trigger = new gcp.cloudbuild.Trigger("webhook-config-trigger", {
    name: "webhook-trigger",
    description: "acceptance test example webhook build trigger",
    webhookConfig: {
        secret: webhookTriggerSecretKeyData.id,
    },
    sourceToBuild: {
        uri: "https://hashicorp/terraform-provider-google-beta",
        ref: "refs/heads/main",
        repoType: "GITHUB",
    },
    gitFileSource: {
        path: "cloudbuild.yaml",
        uri: "https://hashicorp/terraform-provider-google-beta",
        revision: "refs/heads/main",
        repoType: "GITHUB",
    },
});
import pulumi
import pulumi_gcp as gcp

webhook_trigger_secret_key = gcp.secretmanager.Secret("webhook_trigger_secret_key",
    secret_id="webhook-trigger-secret-key",
    replication={
        "user_managed": {
            "replicas": [{
                "location": "us-central1",
            }],
        },
    })
webhook_trigger_secret_key_data = gcp.secretmanager.SecretVersion("webhook_trigger_secret_key_data",
    secret=webhook_trigger_secret_key.id,
    secret_data="secretkeygoeshere")
project = gcp.organizations.get_project()
secret_accessor = gcp.organizations.get_iam_policy(bindings=[{
    "role": "roles/secretmanager.secretAccessor",
    "members": [f"serviceAccount:service-{project.number}@gcp-sa-cloudbuild.iam.gserviceaccount.com"],
}])
policy = gcp.secretmanager.SecretIamPolicy("policy",
    project=webhook_trigger_secret_key.project,
    secret_id=webhook_trigger_secret_key.secret_id,
    policy_data=secret_accessor.policy_data)
webhook_config_trigger = gcp.cloudbuild.Trigger("webhook-config-trigger",
    name="webhook-trigger",
    description="acceptance test example webhook build trigger",
    webhook_config={
        "secret": webhook_trigger_secret_key_data.id,
    },
    source_to_build={
        "uri": "https://hashicorp/terraform-provider-google-beta",
        "ref": "refs/heads/main",
        "repo_type": "GITHUB",
    },
    git_file_source={
        "path": "cloudbuild.yaml",
        "uri": "https://hashicorp/terraform-provider-google-beta",
        "revision": "refs/heads/main",
        "repo_type": "GITHUB",
    })
package main

import (
	"fmt"

	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/cloudbuild"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/organizations"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/secretmanager"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		webhookTriggerSecretKey, err := secretmanager.NewSecret(ctx, "webhook_trigger_secret_key", &secretmanager.SecretArgs{
			SecretId: pulumi.String("webhook-trigger-secret-key"),
			Replication: &secretmanager.SecretReplicationArgs{
				UserManaged: &secretmanager.SecretReplicationUserManagedArgs{
					Replicas: secretmanager.SecretReplicationUserManagedReplicaArray{
						&secretmanager.SecretReplicationUserManagedReplicaArgs{
							Location: pulumi.String("us-central1"),
						},
					},
				},
			},
		})
		if err != nil {
			return err
		}
		webhookTriggerSecretKeyData, err := secretmanager.NewSecretVersion(ctx, "webhook_trigger_secret_key_data", &secretmanager.SecretVersionArgs{
			Secret:     webhookTriggerSecretKey.ID(),
			SecretData: pulumi.String("secretkeygoeshere"),
		})
		if err != nil {
			return err
		}
		project, err := organizations.LookupProject(ctx, &organizations.LookupProjectArgs{}, nil)
		if err != nil {
			return err
		}
		secretAccessor, err := organizations.LookupIAMPolicy(ctx, &organizations.LookupIAMPolicyArgs{
			Bindings: []organizations.GetIAMPolicyBinding{
				{
					Role: "roles/secretmanager.secretAccessor",
					Members: []string{
						fmt.Sprintf("serviceAccount:service-%v@gcp-sa-cloudbuild.iam.gserviceaccount.com", project.Number),
					},
				},
			},
		}, nil)
		if err != nil {
			return err
		}
		_, err = secretmanager.NewSecretIamPolicy(ctx, "policy", &secretmanager.SecretIamPolicyArgs{
			Project:    webhookTriggerSecretKey.Project,
			SecretId:   webhookTriggerSecretKey.SecretId,
			PolicyData: pulumi.String(secretAccessor.PolicyData),
		})
		if err != nil {
			return err
		}
		_, err = cloudbuild.NewTrigger(ctx, "webhook-config-trigger", &cloudbuild.TriggerArgs{
			Name:        pulumi.String("webhook-trigger"),
			Description: pulumi.String("acceptance test example webhook build trigger"),
			WebhookConfig: &cloudbuild.TriggerWebhookConfigArgs{
				Secret: webhookTriggerSecretKeyData.ID(),
			},
			SourceToBuild: &cloudbuild.TriggerSourceToBuildArgs{
				Uri:      pulumi.String("https://hashicorp/terraform-provider-google-beta"),
				Ref:      pulumi.String("refs/heads/main"),
				RepoType: pulumi.String("GITHUB"),
			},
			GitFileSource: &cloudbuild.TriggerGitFileSourceArgs{
				Path:     pulumi.String("cloudbuild.yaml"),
				Uri:      pulumi.String("https://hashicorp/terraform-provider-google-beta"),
				Revision: pulumi.String("refs/heads/main"),
				RepoType: pulumi.String("GITHUB"),
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    var webhookTriggerSecretKey = new Gcp.SecretManager.Secret("webhook_trigger_secret_key", new()
    {
        SecretId = "webhook-trigger-secret-key",
        Replication = new Gcp.SecretManager.Inputs.SecretReplicationArgs
        {
            UserManaged = new Gcp.SecretManager.Inputs.SecretReplicationUserManagedArgs
            {
                Replicas = new[]
                {
                    new Gcp.SecretManager.Inputs.SecretReplicationUserManagedReplicaArgs
                    {
                        Location = "us-central1",
                    },
                },
            },
        },
    });

    var webhookTriggerSecretKeyData = new Gcp.SecretManager.SecretVersion("webhook_trigger_secret_key_data", new()
    {
        Secret = webhookTriggerSecretKey.Id,
        SecretData = "secretkeygoeshere",
    });

    var project = Gcp.Organizations.GetProject.Invoke();

    var secretAccessor = Gcp.Organizations.GetIAMPolicy.Invoke(new()
    {
        Bindings = new[]
        {
            new Gcp.Organizations.Inputs.GetIAMPolicyBindingInputArgs
            {
                Role = "roles/secretmanager.secretAccessor",
                Members = new[]
                {
                    $"serviceAccount:service-{project.Apply(getProjectResult => getProjectResult.Number)}@gcp-sa-cloudbuild.iam.gserviceaccount.com",
                },
            },
        },
    });

    var policy = new Gcp.SecretManager.SecretIamPolicy("policy", new()
    {
        Project = webhookTriggerSecretKey.Project,
        SecretId = webhookTriggerSecretKey.SecretId,
        PolicyData = secretAccessor.Apply(getIAMPolicyResult => getIAMPolicyResult.PolicyData),
    });

    var webhook_config_trigger = new Gcp.CloudBuild.Trigger("webhook-config-trigger", new()
    {
        Name = "webhook-trigger",
        Description = "acceptance test example webhook build trigger",
        WebhookConfig = new Gcp.CloudBuild.Inputs.TriggerWebhookConfigArgs
        {
            Secret = webhookTriggerSecretKeyData.Id,
        },
        SourceToBuild = new Gcp.CloudBuild.Inputs.TriggerSourceToBuildArgs
        {
            Uri = "https://hashicorp/terraform-provider-google-beta",
            Ref = "refs/heads/main",
            RepoType = "GITHUB",
        },
        GitFileSource = new Gcp.CloudBuild.Inputs.TriggerGitFileSourceArgs
        {
            Path = "cloudbuild.yaml",
            Uri = "https://hashicorp/terraform-provider-google-beta",
            Revision = "refs/heads/main",
            RepoType = "GITHUB",
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.secretmanager.Secret;
import com.pulumi.gcp.secretmanager.SecretArgs;
import com.pulumi.gcp.secretmanager.inputs.SecretReplicationArgs;
import com.pulumi.gcp.secretmanager.inputs.SecretReplicationUserManagedArgs;
import com.pulumi.gcp.secretmanager.SecretVersion;
import com.pulumi.gcp.secretmanager.SecretVersionArgs;
import com.pulumi.gcp.organizations.OrganizationsFunctions;
import com.pulumi.gcp.organizations.inputs.GetProjectArgs;
import com.pulumi.gcp.organizations.inputs.GetIAMPolicyArgs;
import com.pulumi.gcp.secretmanager.SecretIamPolicy;
import com.pulumi.gcp.secretmanager.SecretIamPolicyArgs;
import com.pulumi.gcp.cloudbuild.Trigger;
import com.pulumi.gcp.cloudbuild.TriggerArgs;
import com.pulumi.gcp.cloudbuild.inputs.TriggerWebhookConfigArgs;
import com.pulumi.gcp.cloudbuild.inputs.TriggerSourceToBuildArgs;
import com.pulumi.gcp.cloudbuild.inputs.TriggerGitFileSourceArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var webhookTriggerSecretKey = new Secret("webhookTriggerSecretKey", SecretArgs.builder()
            .secretId("webhook-trigger-secret-key")
            .replication(SecretReplicationArgs.builder()
                .userManaged(SecretReplicationUserManagedArgs.builder()
                    .replicas(SecretReplicationUserManagedReplicaArgs.builder()
                        .location("us-central1")
                        .build())
                    .build())
                .build())
            .build());

        var webhookTriggerSecretKeyData = new SecretVersion("webhookTriggerSecretKeyData", SecretVersionArgs.builder()
            .secret(webhookTriggerSecretKey.id())
            .secretData("secretkeygoeshere")
            .build());

        final var project = OrganizationsFunctions.getProject(GetProjectArgs.builder()
            .build());

        final var secretAccessor = OrganizationsFunctions.getIAMPolicy(GetIAMPolicyArgs.builder()
            .bindings(GetIAMPolicyBindingArgs.builder()
                .role("roles/secretmanager.secretAccessor")
                .members(String.format("serviceAccount:service-%s@gcp-sa-cloudbuild.iam.gserviceaccount.com", project.number()))
                .build())
            .build());

        var policy = new SecretIamPolicy("policy", SecretIamPolicyArgs.builder()
            .project(webhookTriggerSecretKey.project())
            .secretId(webhookTriggerSecretKey.secretId())
            .policyData(secretAccessor.policyData())
            .build());

        var webhook_config_trigger = new Trigger("webhook-config-trigger", TriggerArgs.builder()
            .name("webhook-trigger")
            .description("acceptance test example webhook build trigger")
            .webhookConfig(TriggerWebhookConfigArgs.builder()
                .secret(webhookTriggerSecretKeyData.id())
                .build())
            .sourceToBuild(TriggerSourceToBuildArgs.builder()
                .uri("https://hashicorp/terraform-provider-google-beta")
                .ref("refs/heads/main")
                .repoType("GITHUB")
                .build())
            .gitFileSource(TriggerGitFileSourceArgs.builder()
                .path("cloudbuild.yaml")
                .uri("https://hashicorp/terraform-provider-google-beta")
                .revision("refs/heads/main")
                .repoType("GITHUB")
                .build())
            .build());

    }
}
resources:
  webhookTriggerSecretKey:
    type: gcp:secretmanager:Secret
    name: webhook_trigger_secret_key
    properties:
      secretId: webhook-trigger-secret-key
      replication:
        userManaged:
          replicas:
            - location: us-central1
  webhookTriggerSecretKeyData:
    type: gcp:secretmanager:SecretVersion
    name: webhook_trigger_secret_key_data
    properties:
      secret: ${webhookTriggerSecretKey.id}
      secretData: secretkeygoeshere
  policy:
    type: gcp:secretmanager:SecretIamPolicy
    properties:
      project: ${webhookTriggerSecretKey.project}
      secretId: ${webhookTriggerSecretKey.secretId}
      policyData: ${secretAccessor.policyData}
  webhook-config-trigger:
    type: gcp:cloudbuild:Trigger
    properties:
      name: webhook-trigger
      description: acceptance test example webhook build trigger
      webhookConfig:
        secret: ${webhookTriggerSecretKeyData.id}
      sourceToBuild:
        uri: https://hashicorp/terraform-provider-google-beta
        ref: refs/heads/main
        repoType: GITHUB
      gitFileSource:
        path: cloudbuild.yaml
        uri: https://hashicorp/terraform-provider-google-beta
        revision: refs/heads/main
        repoType: GITHUB
variables:
  project:
    fn::invoke:
      function: gcp:organizations:getProject
      arguments: {}
  secretAccessor:
    fn::invoke:
      function: gcp:organizations:getIAMPolicy
      arguments:
        bindings:
          - role: roles/secretmanager.secretAccessor
            members:
              - serviceAccount:service-${project.number}@gcp-sa-cloudbuild.iam.gserviceaccount.com

The webhookConfig property requires a Secret Manager secret containing the webhook authentication key. The SecretIamPolicy grants Cloud Build’s service account permission to read the secret. When an HTTP request arrives at the webhook URL with the correct secret, Cloud Build fetches the build configuration from gitFileSource and executes it. This pattern integrates with external CI/CD systems or custom automation that can’t use Pub/Sub.

Connect to repositories via Cloud Build v2

Cloud Build v2 connections provide a modern way to integrate with GitHub, GitLab, and other Git providers with fine-grained repository access.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const my_connection = new gcp.cloudbuildv2.Connection("my-connection", {
    location: "us-central1",
    name: "my-connection",
    githubConfig: {
        appInstallationId: 123123,
        authorizerCredential: {
            oauthTokenSecretVersion: "projects/my-project/secrets/github-pat-secret/versions/latest",
        },
    },
});
const my_repository = new gcp.cloudbuildv2.Repository("my-repository", {
    name: "my-repo",
    parentConnection: my_connection.id,
    remoteUri: "https://github.com/myuser/my-repo.git",
});
const repo_trigger = new gcp.cloudbuild.Trigger("repo-trigger", {
    location: "us-central1",
    repositoryEventConfig: {
        repository: my_repository.id,
        push: {
            branch: "feature-.*",
        },
    },
    filename: "cloudbuild.yaml",
});
import pulumi
import pulumi_gcp as gcp

my_connection = gcp.cloudbuildv2.Connection("my-connection",
    location="us-central1",
    name="my-connection",
    github_config={
        "app_installation_id": 123123,
        "authorizer_credential": {
            "oauth_token_secret_version": "projects/my-project/secrets/github-pat-secret/versions/latest",
        },
    })
my_repository = gcp.cloudbuildv2.Repository("my-repository",
    name="my-repo",
    parent_connection=my_connection.id,
    remote_uri="https://github.com/myuser/my-repo.git")
repo_trigger = gcp.cloudbuild.Trigger("repo-trigger",
    location="us-central1",
    repository_event_config={
        "repository": my_repository.id,
        "push": {
            "branch": "feature-.*",
        },
    },
    filename="cloudbuild.yaml")
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/cloudbuild"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/cloudbuildv2"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		my_connection, err := cloudbuildv2.NewConnection(ctx, "my-connection", &cloudbuildv2.ConnectionArgs{
			Location: pulumi.String("us-central1"),
			Name:     pulumi.String("my-connection"),
			GithubConfig: &cloudbuildv2.ConnectionGithubConfigArgs{
				AppInstallationId: pulumi.Int(123123),
				AuthorizerCredential: &cloudbuildv2.ConnectionGithubConfigAuthorizerCredentialArgs{
					OauthTokenSecretVersion: pulumi.String("projects/my-project/secrets/github-pat-secret/versions/latest"),
				},
			},
		})
		if err != nil {
			return err
		}
		my_repository, err := cloudbuildv2.NewRepository(ctx, "my-repository", &cloudbuildv2.RepositoryArgs{
			Name:             pulumi.String("my-repo"),
			ParentConnection: my_connection.ID(),
			RemoteUri:        pulumi.String("https://github.com/myuser/my-repo.git"),
		})
		if err != nil {
			return err
		}
		_, err = cloudbuild.NewTrigger(ctx, "repo-trigger", &cloudbuild.TriggerArgs{
			Location: pulumi.String("us-central1"),
			RepositoryEventConfig: &cloudbuild.TriggerRepositoryEventConfigArgs{
				Repository: my_repository.ID(),
				Push: &cloudbuild.TriggerRepositoryEventConfigPushArgs{
					Branch: pulumi.String("feature-.*"),
				},
			},
			Filename: pulumi.String("cloudbuild.yaml"),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    var my_connection = new Gcp.CloudBuildV2.Connection("my-connection", new()
    {
        Location = "us-central1",
        Name = "my-connection",
        GithubConfig = new Gcp.CloudBuildV2.Inputs.ConnectionGithubConfigArgs
        {
            AppInstallationId = 123123,
            AuthorizerCredential = new Gcp.CloudBuildV2.Inputs.ConnectionGithubConfigAuthorizerCredentialArgs
            {
                OauthTokenSecretVersion = "projects/my-project/secrets/github-pat-secret/versions/latest",
            },
        },
    });

    var my_repository = new Gcp.CloudBuildV2.Repository("my-repository", new()
    {
        Name = "my-repo",
        ParentConnection = my_connection.Id,
        RemoteUri = "https://github.com/myuser/my-repo.git",
    });

    var repo_trigger = new Gcp.CloudBuild.Trigger("repo-trigger", new()
    {
        Location = "us-central1",
        RepositoryEventConfig = new Gcp.CloudBuild.Inputs.TriggerRepositoryEventConfigArgs
        {
            Repository = my_repository.Id,
            Push = new Gcp.CloudBuild.Inputs.TriggerRepositoryEventConfigPushArgs
            {
                Branch = "feature-.*",
            },
        },
        Filename = "cloudbuild.yaml",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.cloudbuildv2.Connection;
import com.pulumi.gcp.cloudbuildv2.ConnectionArgs;
import com.pulumi.gcp.cloudbuildv2.inputs.ConnectionGithubConfigArgs;
import com.pulumi.gcp.cloudbuildv2.inputs.ConnectionGithubConfigAuthorizerCredentialArgs;
import com.pulumi.gcp.cloudbuildv2.Repository;
import com.pulumi.gcp.cloudbuildv2.RepositoryArgs;
import com.pulumi.gcp.cloudbuild.Trigger;
import com.pulumi.gcp.cloudbuild.TriggerArgs;
import com.pulumi.gcp.cloudbuild.inputs.TriggerRepositoryEventConfigArgs;
import com.pulumi.gcp.cloudbuild.inputs.TriggerRepositoryEventConfigPushArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var my_connection = new Connection("my-connection", ConnectionArgs.builder()
            .location("us-central1")
            .name("my-connection")
            .githubConfig(ConnectionGithubConfigArgs.builder()
                .appInstallationId(123123)
                .authorizerCredential(ConnectionGithubConfigAuthorizerCredentialArgs.builder()
                    .oauthTokenSecretVersion("projects/my-project/secrets/github-pat-secret/versions/latest")
                    .build())
                .build())
            .build());

        var my_repository = new Repository("my-repository", RepositoryArgs.builder()
            .name("my-repo")
            .parentConnection(my_connection.id())
            .remoteUri("https://github.com/myuser/my-repo.git")
            .build());

        var repo_trigger = new Trigger("repo-trigger", TriggerArgs.builder()
            .location("us-central1")
            .repositoryEventConfig(TriggerRepositoryEventConfigArgs.builder()
                .repository(my_repository.id())
                .push(TriggerRepositoryEventConfigPushArgs.builder()
                    .branch("feature-.*")
                    .build())
                .build())
            .filename("cloudbuild.yaml")
            .build());

    }
}
resources:
  my-connection:
    type: gcp:cloudbuildv2:Connection
    properties:
      location: us-central1
      name: my-connection
      githubConfig:
        appInstallationId: 123123
        authorizerCredential:
          oauthTokenSecretVersion: projects/my-project/secrets/github-pat-secret/versions/latest
  my-repository:
    type: gcp:cloudbuildv2:Repository
    properties:
      name: my-repo
      parentConnection: ${["my-connection"].id}
      remoteUri: https://github.com/myuser/my-repo.git
  repo-trigger:
    type: gcp:cloudbuild:Trigger
    properties:
      location: us-central1
      repositoryEventConfig:
        repository: ${["my-repository"].id}
        push:
          branch: feature-.*
      filename: cloudbuild.yaml

The Connection resource establishes authentication with GitHub using an App installation. The Repository resource links a specific GitHub repository to the connection. The repositoryEventConfig property monitors the repository for push events matching the branch pattern. This approach replaces the older triggerTemplate pattern and supports more Git providers.

Monitor GitHub Enterprise repositories

Organizations using GitHub Enterprise Server can trigger builds from self-hosted repositories.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const ghe_trigger = new gcp.cloudbuild.Trigger("ghe-trigger", {
    name: "ghe-trigger",
    location: "us-central1",
    github: {
        owner: "hashicorp",
        name: "terraform-provider-google",
        push: {
            branch: "^main$",
        },
        enterpriseConfigResourceName: "projects/123456789/locations/us-central1/githubEnterpriseConfigs/configID",
    },
    filename: "cloudbuild.yaml",
});
import pulumi
import pulumi_gcp as gcp

ghe_trigger = gcp.cloudbuild.Trigger("ghe-trigger",
    name="ghe-trigger",
    location="us-central1",
    github={
        "owner": "hashicorp",
        "name": "terraform-provider-google",
        "push": {
            "branch": "^main$",
        },
        "enterprise_config_resource_name": "projects/123456789/locations/us-central1/githubEnterpriseConfigs/configID",
    },
    filename="cloudbuild.yaml")
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/cloudbuild"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := cloudbuild.NewTrigger(ctx, "ghe-trigger", &cloudbuild.TriggerArgs{
			Name:     pulumi.String("ghe-trigger"),
			Location: pulumi.String("us-central1"),
			Github: &cloudbuild.TriggerGithubArgs{
				Owner: pulumi.String("hashicorp"),
				Name:  pulumi.String("terraform-provider-google"),
				Push: &cloudbuild.TriggerGithubPushArgs{
					Branch: pulumi.String("^main$"),
				},
				EnterpriseConfigResourceName: pulumi.String("projects/123456789/locations/us-central1/githubEnterpriseConfigs/configID"),
			},
			Filename: pulumi.String("cloudbuild.yaml"),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    var ghe_trigger = new Gcp.CloudBuild.Trigger("ghe-trigger", new()
    {
        Name = "ghe-trigger",
        Location = "us-central1",
        Github = new Gcp.CloudBuild.Inputs.TriggerGithubArgs
        {
            Owner = "hashicorp",
            Name = "terraform-provider-google",
            Push = new Gcp.CloudBuild.Inputs.TriggerGithubPushArgs
            {
                Branch = "^main$",
            },
            EnterpriseConfigResourceName = "projects/123456789/locations/us-central1/githubEnterpriseConfigs/configID",
        },
        Filename = "cloudbuild.yaml",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.cloudbuild.Trigger;
import com.pulumi.gcp.cloudbuild.TriggerArgs;
import com.pulumi.gcp.cloudbuild.inputs.TriggerGithubArgs;
import com.pulumi.gcp.cloudbuild.inputs.TriggerGithubPushArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var ghe_trigger = new Trigger("ghe-trigger", TriggerArgs.builder()
            .name("ghe-trigger")
            .location("us-central1")
            .github(TriggerGithubArgs.builder()
                .owner("hashicorp")
                .name("terraform-provider-google")
                .push(TriggerGithubPushArgs.builder()
                    .branch("^main$")
                    .build())
                .enterpriseConfigResourceName("projects/123456789/locations/us-central1/githubEnterpriseConfigs/configID")
                .build())
            .filename("cloudbuild.yaml")
            .build());

    }
}
resources:
  ghe-trigger:
    type: gcp:cloudbuild:Trigger
    properties:
      name: ghe-trigger
      location: us-central1
      github:
        owner: hashicorp
        name: terraform-provider-google
        push:
          branch: ^main$
        enterpriseConfigResourceName: projects/123456789/locations/us-central1/githubEnterpriseConfigs/configID
      filename: cloudbuild.yaml

The github property with enterpriseConfigResourceName connects to a GitHub Enterprise Server instance. The push property defines which branches to monitor using regular expressions. This configuration requires a separate GitHub Enterprise config resource that defines the server URL and authentication.

Beyond these examples

These snippets focus on specific trigger-level features: repository monitoring, event-driven triggers via Pub/Sub and webhooks, inline build definitions and external config files, and service account customization and secret management. They’re intentionally minimal rather than full CI/CD pipelines.

The examples may reference pre-existing infrastructure such as Cloud Source Repositories or connected Git providers, Pub/Sub topics for event-driven triggers, Secret Manager secrets for webhooks and build secrets, IAM service accounts and KMS keys, and GitHub Enterprise or Bitbucket Server configurations. They focus on configuring the trigger rather than provisioning everything around it.

To keep things focused, common trigger patterns are omitted, including:

  • File path filtering (ignoredFiles, includedFiles)
  • Manual approval workflows (approvalConfig)
  • Build failure handling (allowFailure, allowExitCodes)
  • Developer Connect integration for newer Git providers

These omissions are intentional: the goal is to illustrate how each trigger feature is wired, not provide drop-in CI/CD modules. See the Cloud Build Trigger resource reference for all available configuration options.

Let's configure GCP Cloud Build Triggers

Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.

Try Pulumi Cloud for FREE

Frequently Asked Questions

Trigger Configuration & Sources
What trigger sources can I use for Cloud Build triggers?
You can configure triggers using triggerTemplate (legacy Cloud Source Repositories), github, pubsubConfig, webhookConfig, repositoryEventConfig (Cloud Build v2), bitbucketServerTriggerConfig, or developerConnectEventConfig. These configurations are mutually exclusive; choose one based on your source control system.
When should I use filename vs gitFileSource for my build configuration?
Use filename only with triggerTemplate or github triggers. For Pub/Sub, Webhook, or Manual triggers, use gitFileSource instead to specify the build configuration file location.
What's the default location for Cloud Build triggers?
Triggers default to “global” location if not specified. You can set a regional location like “us-central1” using the location property, but note that location is immutable after creation.
What properties can't I change after creating a trigger?
The project and location properties are immutable and cannot be changed after trigger creation.
Build Definition & Execution
How do I define my build: inline config or separate file?
You have two options: use filename to reference a cloudbuild.yaml file, or use build to define the build configuration inline. Either a filename or build template must be provided, but not both.
How can I allow build steps to fail without failing the entire build?
Use allowFailure: true on a step to let it fail without failing the build, or use allowExitCodes to specify an array of exit codes (e.g., [1, 3]) that won’t cause build failure.
How do I require manual approval before builds run?
Configure approvalConfig with approvalRequired: true. Any user with a Cloud Build Approver role for the project can then approve builds created by this trigger.
File Filtering & Source Control
How do ignoredFiles and includedFiles work together?
Both use glob patterns with ** support. If ignoredFiles is set, changed files must pass that filter first. If includedFiles is also set, at least one file must match an includedFiles glob. If no files pass both filters, the build won’t trigger.
Authentication & Permissions
What service account does Cloud Build use by default?
If no serviceAccount is specified, Cloud Build uses the default service account: [PROJECT_NUM]@system.gserviceaccount.com. You can retrieve this email using the gcp.projects.ServiceIdentity resource.
What IAM permissions does a custom service account need for triggers?
Grant roles/iam.serviceAccountUser and roles/logging.logWriter to the service account. Use dependsOn in your trigger resource to ensure IAM bindings exist before creating the trigger.
Advanced Features
How do I use Pub/Sub message data in my build?
Reference message fields in substitutions using $(body.message.data.fieldName) syntax (e.g., _ACTION: "$(body.message.data.action)"), then use these substitutions in the filter property for conditional triggering.
How do I secure a webhook trigger with a secret?
Store your webhook secret in Secret Manager, grant the roles/secretmanager.secretAccessor role to the Cloud Build service account (service-[PROJECT_NUM]@gcp-sa-cloudbuild.iam.gserviceaccount.com), then reference the secret version ID in webhookConfig.secret.

Using a different cloud?

Explore integration guides for other cloud providers: