Configure GCP Cloud Deploy Delivery Pipelines

The gcp:clouddeploy/deliveryPipeline:DeliveryPipeline resource, part of the Pulumi GCP provider, defines a Cloud Deploy delivery pipeline that orchestrates application releases through sequential deployment stages. This guide focuses on two capabilities: multi-stage pipeline configuration and stage-specific parameters.

Delivery pipelines reference Cloud Deploy Target resources (GKE clusters, Cloud Run services) and Skaffold profiles that define how to build and deploy your application. The examples are intentionally small. Combine them with your own Target resources and deployment configuration.

Define a multi-stage deployment pipeline

Cloud Deploy pipelines move code from development through staging to production in a controlled sequence.

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

const primary = new gcp.clouddeploy.DeliveryPipeline("primary", {
    location: "us-west1",
    name: "pipeline",
    description: "basic description",
    project: "my-project-name",
    serialPipeline: {
        stages: [
            {
                deployParameters: [{
                    values: {
                        deployParameterKey: "deployParameterValue",
                    },
                    matchTargetLabels: {},
                }],
                profiles: [
                    "example-profile-one",
                    "example-profile-two",
                ],
                targetId: "example-target-one",
            },
            {
                profiles: [],
                targetId: "example-target-two",
            },
        ],
    },
    annotations: {
        my_first_annotation: "example-annotation-1",
        my_second_annotation: "example-annotation-2",
    },
    labels: {
        my_first_label: "example-label-1",
        my_second_label: "example-label-2",
    },
});
import pulumi
import pulumi_gcp as gcp

primary = gcp.clouddeploy.DeliveryPipeline("primary",
    location="us-west1",
    name="pipeline",
    description="basic description",
    project="my-project-name",
    serial_pipeline={
        "stages": [
            {
                "deploy_parameters": [{
                    "values": {
                        "deployParameterKey": "deployParameterValue",
                    },
                    "match_target_labels": {},
                }],
                "profiles": [
                    "example-profile-one",
                    "example-profile-two",
                ],
                "target_id": "example-target-one",
            },
            {
                "profiles": [],
                "target_id": "example-target-two",
            },
        ],
    },
    annotations={
        "my_first_annotation": "example-annotation-1",
        "my_second_annotation": "example-annotation-2",
    },
    labels={
        "my_first_label": "example-label-1",
        "my_second_label": "example-label-2",
    })
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := clouddeploy.NewDeliveryPipeline(ctx, "primary", &clouddeploy.DeliveryPipelineArgs{
			Location:    pulumi.String("us-west1"),
			Name:        pulumi.String("pipeline"),
			Description: pulumi.String("basic description"),
			Project:     pulumi.String("my-project-name"),
			SerialPipeline: &clouddeploy.DeliveryPipelineSerialPipelineArgs{
				Stages: clouddeploy.DeliveryPipelineSerialPipelineStageArray{
					&clouddeploy.DeliveryPipelineSerialPipelineStageArgs{
						DeployParameters: clouddeploy.DeliveryPipelineSerialPipelineStageDeployParameterArray{
							&clouddeploy.DeliveryPipelineSerialPipelineStageDeployParameterArgs{
								Values: pulumi.StringMap{
									"deployParameterKey": pulumi.String("deployParameterValue"),
								},
								MatchTargetLabels: pulumi.StringMap{},
							},
						},
						Profiles: pulumi.StringArray{
							pulumi.String("example-profile-one"),
							pulumi.String("example-profile-two"),
						},
						TargetId: pulumi.String("example-target-one"),
					},
					&clouddeploy.DeliveryPipelineSerialPipelineStageArgs{
						Profiles: pulumi.StringArray{},
						TargetId: pulumi.String("example-target-two"),
					},
				},
			},
			Annotations: pulumi.StringMap{
				"my_first_annotation":  pulumi.String("example-annotation-1"),
				"my_second_annotation": pulumi.String("example-annotation-2"),
			},
			Labels: pulumi.StringMap{
				"my_first_label":  pulumi.String("example-label-1"),
				"my_second_label": pulumi.String("example-label-2"),
			},
		})
		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 primary = new Gcp.CloudDeploy.DeliveryPipeline("primary", new()
    {
        Location = "us-west1",
        Name = "pipeline",
        Description = "basic description",
        Project = "my-project-name",
        SerialPipeline = new Gcp.CloudDeploy.Inputs.DeliveryPipelineSerialPipelineArgs
        {
            Stages = new[]
            {
                new Gcp.CloudDeploy.Inputs.DeliveryPipelineSerialPipelineStageArgs
                {
                    DeployParameters = new[]
                    {
                        new Gcp.CloudDeploy.Inputs.DeliveryPipelineSerialPipelineStageDeployParameterArgs
                        {
                            Values = 
                            {
                                { "deployParameterKey", "deployParameterValue" },
                            },
                            MatchTargetLabels = null,
                        },
                    },
                    Profiles = new[]
                    {
                        "example-profile-one",
                        "example-profile-two",
                    },
                    TargetId = "example-target-one",
                },
                new Gcp.CloudDeploy.Inputs.DeliveryPipelineSerialPipelineStageArgs
                {
                    Profiles = new() { },
                    TargetId = "example-target-two",
                },
            },
        },
        Annotations = 
        {
            { "my_first_annotation", "example-annotation-1" },
            { "my_second_annotation", "example-annotation-2" },
        },
        Labels = 
        {
            { "my_first_label", "example-label-1" },
            { "my_second_label", "example-label-2" },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.clouddeploy.DeliveryPipeline;
import com.pulumi.gcp.clouddeploy.DeliveryPipelineArgs;
import com.pulumi.gcp.clouddeploy.inputs.DeliveryPipelineSerialPipelineArgs;
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 primary = new DeliveryPipeline("primary", DeliveryPipelineArgs.builder()
            .location("us-west1")
            .name("pipeline")
            .description("basic description")
            .project("my-project-name")
            .serialPipeline(DeliveryPipelineSerialPipelineArgs.builder()
                .stages(                
                    DeliveryPipelineSerialPipelineStageArgs.builder()
                        .deployParameters(DeliveryPipelineSerialPipelineStageDeployParameterArgs.builder()
                            .values(Map.of("deployParameterKey", "deployParameterValue"))
                            .matchTargetLabels(Map.ofEntries(
                            ))
                            .build())
                        .profiles(                        
                            "example-profile-one",
                            "example-profile-two")
                        .targetId("example-target-one")
                        .build(),
                    DeliveryPipelineSerialPipelineStageArgs.builder()
                        .profiles()
                        .targetId("example-target-two")
                        .build())
                .build())
            .annotations(Map.ofEntries(
                Map.entry("my_first_annotation", "example-annotation-1"),
                Map.entry("my_second_annotation", "example-annotation-2")
            ))
            .labels(Map.ofEntries(
                Map.entry("my_first_label", "example-label-1"),
                Map.entry("my_second_label", "example-label-2")
            ))
            .build());

    }
}
resources:
  primary:
    type: gcp:clouddeploy:DeliveryPipeline
    properties:
      location: us-west1
      name: pipeline
      description: basic description
      project: my-project-name
      serialPipeline:
        stages:
          - deployParameters:
              - values:
                  deployParameterKey: deployParameterValue
                matchTargetLabels: {}
            profiles:
              - example-profile-one
              - example-profile-two
            targetId: example-target-one
          - profiles: []
            targetId: example-target-two
      annotations:
        my_first_annotation: example-annotation-1
        my_second_annotation: example-annotation-2
      labels:
        my_first_label: example-label-1
        my_second_label: example-label-2

The serialPipeline property defines stages that execute in order. Each stage references a targetId (a Cloud Deploy Target resource) and optional profiles (Skaffold profile names). The deployParameters block passes key-value pairs to the deployment, allowing stage-specific configuration like feature flags or environment variables. The first stage shows both profiles and parameters; the second stage demonstrates a minimal configuration with just a target reference.

Beyond these examples

These snippets focus on specific pipeline-level features: sequential stage configuration, deploy parameters and profile selection, and annotations and labels for metadata. They’re intentionally minimal rather than full deployment workflows.

The examples reference pre-existing infrastructure such as Cloud Deploy Target resources (referenced by targetId) and Skaffold profiles (referenced in stages). They focus on configuring the pipeline rather than provisioning targets or build configuration.

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

  • Pipeline suspension (suspended property)
  • Deployment verification strategies
  • Stage-specific strategies (canary, custom)
  • Approval requirements between stages

These omissions are intentional: the goal is to illustrate how pipeline stages are wired, not provide drop-in CI/CD modules. See the Cloud Deploy DeliveryPipeline resource reference for all available configuration options.

Let's configure GCP Cloud Deploy Delivery Pipelines

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

Try Pulumi Cloud for FREE

Frequently Asked Questions

Configuration & Constraints
What's the required format for the pipeline name?
The name must match the format a-z? (lowercase letters, numbers, and hyphens).
What are the constraints on labels?
Labels must use lowercase letters, numbers, underscores, and dashes with UTF-8 encoding. Keys must start with a lowercase letter or international character. Each resource supports a maximum of 64 labels, with keys and values limited to 128 bytes each.
What's the maximum length for the pipeline description?
The description field has a maximum length of 255 characters.
Immutability & Updates
What properties can't I change after creating a delivery pipeline?
The location, name, and project properties are immutable and cannot be changed after creation.
Why aren't all my annotations and labels showing up in my configuration?
The annotations and labels fields are non-authoritative and only manage values present in your configuration. To access all annotations and labels on the resource (including those set by other clients or services), use the effectiveAnnotations and effectiveLabels output properties.
Pipeline Behavior
What happens when I set suspended to true?
When suspended is true, no new releases or rollouts can be created, but in-progress ones will complete.
What does serialPipeline define?
The serialPipeline property defines a sequential set of stages for the delivery pipeline, specifying the order in which deployments progress through targets.
Import & Management
What import formats are supported?
You can import a DeliveryPipeline using three formats: projects/{{project}}/locations/{{location}}/deliveryPipelines/{{name}}, {{project}}/{{location}}/{{name}}, or {{location}}/{{name}}.

Using a different cloud?

Explore integration guides for other cloud providers: