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 across multiple deployment targets in sequence. This guide focuses on two capabilities: sequential stage configuration and deployment parameters with profiles.

Delivery pipelines reference Cloud Deploy Target resources and deployment profiles that must exist separately. The examples are intentionally small. Combine them with your own targets, profiles, and deployment strategies.

Define a multi-stage deployment pipeline

Cloud Deploy pipelines orchestrate releases across environments, moving 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), optional profiles (deployment configuration variants), and deployParameters (key-value pairs passed to the deployment). The first stage shows both profiles and parameters; the second stage demonstrates a minimal configuration with just a target reference. Annotations and labels provide metadata for organization and filtering.

Beyond these examples

These snippets focus on specific pipeline-level features: sequential stage configuration, deployment parameters and profiles, 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 deployment profiles (referenced in stages). They focus on configuring the pipeline rather than provisioning targets or profiles.

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

  • Pipeline suspension (suspended property)
  • Deployment verification strategies
  • Stage-specific strategies beyond basic parameters
  • Conditional stage progression

These omissions are intentional: the goal is to illustrate how pipeline stages are wired, not provide drop-in deployment 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 & Immutability
What properties can't be changed after creating a delivery pipeline?
The location, name, and project properties are immutable. Changing any of these will force recreation of the pipeline.
What's the required format for pipeline names?
Pipeline names must match the format a-z? (lowercase letters, numbers, and hyphens, starting with a letter).
What's the maximum length for a pipeline description?
Descriptions are limited to 255 characters.
How can I import an existing delivery pipeline?
You can import using three formats: the full path (projects/{{project}}/locations/{{location}}/deliveryPipelines/{{name}}), project-scoped ({{project}}/{{location}}/{{name}}), or location-scoped ({{location}}/{{name}}).
Annotations & Labels
Why don't I see all annotations and labels on my pipeline?
The annotations and labels fields are non-authoritative, meaning they only manage values present in your configuration. To see all annotations and labels (including those set by other clients or services), use effectiveAnnotations and effectiveLabels.
What are the constraints for labels?
Labels have several constraints: maximum of 64 labels per resource, keys and values must be <= 128 bytes, only lowercase letters, numbers, underscores, and dashes allowed, UTF-8 encoding required, and keys must start with a lowercase letter or international character.
Pipeline Operations
How do I temporarily pause deployments without deleting the pipeline?
Set suspended to true. This prevents new releases or rollouts from being created while allowing in-progress ones to complete.
How do I configure stages in a delivery pipeline?
Use serialPipeline with a stages array. Each stage requires a targetId and can optionally include profiles (an array of profile names) and deployParameters (with values and matchTargetLabels).

Using a different cloud?

Explore integration guides for other cloud providers: