The gcp:cloudbuild/bitbucketServerConfig:BitbucketServerConfig resource, part of the Pulumi GCP provider, defines the connection between Cloud Build and a Bitbucket Server instance: authentication credentials, network access configuration, and repository selection. This guide focuses on three capabilities: basic authentication and webhook setup, repository selection, and VPC peering for private instances.
Bitbucket Server configurations require Secret Manager secrets for authentication tokens and may reference VPC networks for private connectivity. The examples are intentionally small. Combine them with your own Secret Manager secrets, IAM permissions, and build trigger configurations.
Connect Cloud Build to a Bitbucket Server host
Teams using self-hosted Bitbucket Server establish authentication and webhook configuration so Cloud Build can monitor repositories.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const bbs_config = new gcp.cloudbuild.BitbucketServerConfig("bbs-config", {
configId: "bbs-config",
location: "us-central1",
hostUri: "https://bbs.com",
secrets: {
adminAccessTokenVersionName: "projects/myProject/secrets/mybbspat/versions/1",
readAccessTokenVersionName: "projects/myProject/secrets/mybbspat/versions/1",
webhookSecretVersionName: "projects/myProject/secrets/mybbspat/versions/1",
},
username: "test",
apiKey: "<api-key>",
});
import pulumi
import pulumi_gcp as gcp
bbs_config = gcp.cloudbuild.BitbucketServerConfig("bbs-config",
config_id="bbs-config",
location="us-central1",
host_uri="https://bbs.com",
secrets={
"admin_access_token_version_name": "projects/myProject/secrets/mybbspat/versions/1",
"read_access_token_version_name": "projects/myProject/secrets/mybbspat/versions/1",
"webhook_secret_version_name": "projects/myProject/secrets/mybbspat/versions/1",
},
username="test",
api_key="<api-key>")
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.NewBitbucketServerConfig(ctx, "bbs-config", &cloudbuild.BitbucketServerConfigArgs{
ConfigId: pulumi.String("bbs-config"),
Location: pulumi.String("us-central1"),
HostUri: pulumi.String("https://bbs.com"),
Secrets: &cloudbuild.BitbucketServerConfigSecretsArgs{
AdminAccessTokenVersionName: pulumi.String("projects/myProject/secrets/mybbspat/versions/1"),
ReadAccessTokenVersionName: pulumi.String("projects/myProject/secrets/mybbspat/versions/1"),
WebhookSecretVersionName: pulumi.String("projects/myProject/secrets/mybbspat/versions/1"),
},
Username: pulumi.String("test"),
ApiKey: pulumi.String("<api-key>"),
})
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 bbs_config = new Gcp.CloudBuild.BitbucketServerConfig("bbs-config", new()
{
ConfigId = "bbs-config",
Location = "us-central1",
HostUri = "https://bbs.com",
Secrets = new Gcp.CloudBuild.Inputs.BitbucketServerConfigSecretsArgs
{
AdminAccessTokenVersionName = "projects/myProject/secrets/mybbspat/versions/1",
ReadAccessTokenVersionName = "projects/myProject/secrets/mybbspat/versions/1",
WebhookSecretVersionName = "projects/myProject/secrets/mybbspat/versions/1",
},
Username = "test",
ApiKey = "<api-key>",
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.cloudbuild.BitbucketServerConfig;
import com.pulumi.gcp.cloudbuild.BitbucketServerConfigArgs;
import com.pulumi.gcp.cloudbuild.inputs.BitbucketServerConfigSecretsArgs;
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 bbs_config = new BitbucketServerConfig("bbs-config", BitbucketServerConfigArgs.builder()
.configId("bbs-config")
.location("us-central1")
.hostUri("https://bbs.com")
.secrets(BitbucketServerConfigSecretsArgs.builder()
.adminAccessTokenVersionName("projects/myProject/secrets/mybbspat/versions/1")
.readAccessTokenVersionName("projects/myProject/secrets/mybbspat/versions/1")
.webhookSecretVersionName("projects/myProject/secrets/mybbspat/versions/1")
.build())
.username("test")
.apiKey("<api-key>")
.build());
}
}
resources:
bbs-config:
type: gcp:cloudbuild:BitbucketServerConfig
properties:
configId: bbs-config
location: us-central1
hostUri: https://bbs.com
secrets:
adminAccessTokenVersionName: projects/myProject/secrets/mybbspat/versions/1
readAccessTokenVersionName: projects/myProject/secrets/mybbspat/versions/1
webhookSecretVersionName: projects/myProject/secrets/mybbspat/versions/1
username: test
apiKey: <api-key>
The hostUri points to your Bitbucket Server instance. The secrets block references Secret Manager versions containing admin tokens, read tokens, and webhook secrets. Cloud Build uses the username and apiKey to authenticate API calls and verify webhook requests. The configId becomes part of the resource name and must be unique within the location.
Register specific repositories for build triggers
After connecting to Bitbucket Server, you specify which repositories Cloud Build should monitor rather than granting access to all repositories.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const bbs_config_with_repos = new gcp.cloudbuild.BitbucketServerConfig("bbs-config-with-repos", {
configId: "bbs-config",
location: "us-central1",
hostUri: "https://bbs.com",
secrets: {
adminAccessTokenVersionName: "projects/myProject/secrets/mybbspat/versions/1",
readAccessTokenVersionName: "projects/myProject/secrets/mybbspat/versions/1",
webhookSecretVersionName: "projects/myProject/secrets/mybbspat/versions/1",
},
username: "test",
apiKey: "<api-key>",
connectedRepositories: [
{
projectKey: "DEV",
repoSlug: "repo1",
},
{
projectKey: "PROD",
repoSlug: "repo1",
},
],
});
import pulumi
import pulumi_gcp as gcp
bbs_config_with_repos = gcp.cloudbuild.BitbucketServerConfig("bbs-config-with-repos",
config_id="bbs-config",
location="us-central1",
host_uri="https://bbs.com",
secrets={
"admin_access_token_version_name": "projects/myProject/secrets/mybbspat/versions/1",
"read_access_token_version_name": "projects/myProject/secrets/mybbspat/versions/1",
"webhook_secret_version_name": "projects/myProject/secrets/mybbspat/versions/1",
},
username="test",
api_key="<api-key>",
connected_repositories=[
{
"project_key": "DEV",
"repo_slug": "repo1",
},
{
"project_key": "PROD",
"repo_slug": "repo1",
},
])
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.NewBitbucketServerConfig(ctx, "bbs-config-with-repos", &cloudbuild.BitbucketServerConfigArgs{
ConfigId: pulumi.String("bbs-config"),
Location: pulumi.String("us-central1"),
HostUri: pulumi.String("https://bbs.com"),
Secrets: &cloudbuild.BitbucketServerConfigSecretsArgs{
AdminAccessTokenVersionName: pulumi.String("projects/myProject/secrets/mybbspat/versions/1"),
ReadAccessTokenVersionName: pulumi.String("projects/myProject/secrets/mybbspat/versions/1"),
WebhookSecretVersionName: pulumi.String("projects/myProject/secrets/mybbspat/versions/1"),
},
Username: pulumi.String("test"),
ApiKey: pulumi.String("<api-key>"),
ConnectedRepositories: cloudbuild.BitbucketServerConfigConnectedRepositoryArray{
&cloudbuild.BitbucketServerConfigConnectedRepositoryArgs{
ProjectKey: pulumi.String("DEV"),
RepoSlug: pulumi.String("repo1"),
},
&cloudbuild.BitbucketServerConfigConnectedRepositoryArgs{
ProjectKey: pulumi.String("PROD"),
RepoSlug: pulumi.String("repo1"),
},
},
})
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 bbs_config_with_repos = new Gcp.CloudBuild.BitbucketServerConfig("bbs-config-with-repos", new()
{
ConfigId = "bbs-config",
Location = "us-central1",
HostUri = "https://bbs.com",
Secrets = new Gcp.CloudBuild.Inputs.BitbucketServerConfigSecretsArgs
{
AdminAccessTokenVersionName = "projects/myProject/secrets/mybbspat/versions/1",
ReadAccessTokenVersionName = "projects/myProject/secrets/mybbspat/versions/1",
WebhookSecretVersionName = "projects/myProject/secrets/mybbspat/versions/1",
},
Username = "test",
ApiKey = "<api-key>",
ConnectedRepositories = new[]
{
new Gcp.CloudBuild.Inputs.BitbucketServerConfigConnectedRepositoryArgs
{
ProjectKey = "DEV",
RepoSlug = "repo1",
},
new Gcp.CloudBuild.Inputs.BitbucketServerConfigConnectedRepositoryArgs
{
ProjectKey = "PROD",
RepoSlug = "repo1",
},
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.cloudbuild.BitbucketServerConfig;
import com.pulumi.gcp.cloudbuild.BitbucketServerConfigArgs;
import com.pulumi.gcp.cloudbuild.inputs.BitbucketServerConfigSecretsArgs;
import com.pulumi.gcp.cloudbuild.inputs.BitbucketServerConfigConnectedRepositoryArgs;
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 bbs_config_with_repos = new BitbucketServerConfig("bbs-config-with-repos", BitbucketServerConfigArgs.builder()
.configId("bbs-config")
.location("us-central1")
.hostUri("https://bbs.com")
.secrets(BitbucketServerConfigSecretsArgs.builder()
.adminAccessTokenVersionName("projects/myProject/secrets/mybbspat/versions/1")
.readAccessTokenVersionName("projects/myProject/secrets/mybbspat/versions/1")
.webhookSecretVersionName("projects/myProject/secrets/mybbspat/versions/1")
.build())
.username("test")
.apiKey("<api-key>")
.connectedRepositories(
BitbucketServerConfigConnectedRepositoryArgs.builder()
.projectKey("DEV")
.repoSlug("repo1")
.build(),
BitbucketServerConfigConnectedRepositoryArgs.builder()
.projectKey("PROD")
.repoSlug("repo1")
.build())
.build());
}
}
resources:
bbs-config-with-repos:
type: gcp:cloudbuild:BitbucketServerConfig
properties:
configId: bbs-config
location: us-central1
hostUri: https://bbs.com
secrets:
adminAccessTokenVersionName: projects/myProject/secrets/mybbspat/versions/1
readAccessTokenVersionName: projects/myProject/secrets/mybbspat/versions/1
webhookSecretVersionName: projects/myProject/secrets/mybbspat/versions/1
username: test
apiKey: <api-key>
connectedRepositories:
- projectKey: DEV
repoSlug: repo1
- projectKey: PROD
repoSlug: repo1
The connectedRepositories array lists Bitbucket projects and repositories by their projectKey and repoSlug identifiers. Cloud Build creates webhooks for these repositories to receive push and pull request events. This example monitors two repositories: DEV/repo1 and PROD/repo1.
Connect to on-premises Bitbucket via VPC peering
Organizations hosting Bitbucket Server on-premises without public internet access use VPC peering to allow Cloud Build to reach the instance privately.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
import * as std from "@pulumi/std";
const project = gcp.organizations.getProject({});
const servicenetworking = new gcp.projects.Service("servicenetworking", {service: "servicenetworking.googleapis.com"});
const vpcNetwork = new gcp.compute.Network("vpc_network", {name: "vpc-network"}, {
dependsOn: [servicenetworking],
});
const privateIpAlloc = new gcp.compute.GlobalAddress("private_ip_alloc", {
name: "private-ip-alloc",
purpose: "VPC_PEERING",
addressType: "INTERNAL",
prefixLength: 16,
network: vpcNetwork.id,
});
const _default = new gcp.servicenetworking.Connection("default", {
network: vpcNetwork.id,
service: "servicenetworking.googleapis.com",
reservedPeeringRanges: [privateIpAlloc.name],
}, {
dependsOn: [servicenetworking],
});
const bbs_config_with_peered_network = new gcp.cloudbuild.BitbucketServerConfig("bbs-config-with-peered-network", {
configId: "bbs-config",
location: "us-central1",
hostUri: "https://bbs.com",
secrets: {
adminAccessTokenVersionName: "projects/myProject/secrets/mybbspat/versions/1",
readAccessTokenVersionName: "projects/myProject/secrets/mybbspat/versions/1",
webhookSecretVersionName: "projects/myProject/secrets/mybbspat/versions/1",
},
username: "test",
apiKey: "<api-key>",
peeredNetwork: pulumi.all([vpcNetwork.id, project, project]).apply(([id, project, project1]) => std.replaceOutput({
text: id,
search: project.name,
replace: project1.number,
})).apply(invoke => invoke.result),
sslCa: `-----BEGIN CERTIFICATE-----
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
-----END CERTIFICATE-----
`,
}, {
dependsOn: [_default],
});
import pulumi
import pulumi_gcp as gcp
import pulumi_std as std
project = gcp.organizations.get_project()
servicenetworking = gcp.projects.Service("servicenetworking", service="servicenetworking.googleapis.com")
vpc_network = gcp.compute.Network("vpc_network", name="vpc-network",
opts = pulumi.ResourceOptions(depends_on=[servicenetworking]))
private_ip_alloc = gcp.compute.GlobalAddress("private_ip_alloc",
name="private-ip-alloc",
purpose="VPC_PEERING",
address_type="INTERNAL",
prefix_length=16,
network=vpc_network.id)
default = gcp.servicenetworking.Connection("default",
network=vpc_network.id,
service="servicenetworking.googleapis.com",
reserved_peering_ranges=[private_ip_alloc.name],
opts = pulumi.ResourceOptions(depends_on=[servicenetworking]))
bbs_config_with_peered_network = gcp.cloudbuild.BitbucketServerConfig("bbs-config-with-peered-network",
config_id="bbs-config",
location="us-central1",
host_uri="https://bbs.com",
secrets={
"admin_access_token_version_name": "projects/myProject/secrets/mybbspat/versions/1",
"read_access_token_version_name": "projects/myProject/secrets/mybbspat/versions/1",
"webhook_secret_version_name": "projects/myProject/secrets/mybbspat/versions/1",
},
username="test",
api_key="<api-key>",
peered_network=vpc_network.id.apply(lambda id: std.replace(text=id,
search=project.name,
replace=project.number)).apply(lambda invoke: invoke.result),
ssl_ca="""-----BEGIN CERTIFICATE-----
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
-----END CERTIFICATE-----
""",
opts = pulumi.ResourceOptions(depends_on=[default]))
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/cloudbuild"
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/compute"
"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/servicenetworking"
"github.com/pulumi/pulumi-std/sdk/go/std"
"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
}
servicenetworking, err := projects.NewService(ctx, "servicenetworking", &projects.ServiceArgs{
Service: pulumi.String("servicenetworking.googleapis.com"),
})
if err != nil {
return err
}
vpcNetwork, err := compute.NewNetwork(ctx, "vpc_network", &compute.NetworkArgs{
Name: pulumi.String("vpc-network"),
}, pulumi.DependsOn([]pulumi.Resource{
servicenetworking,
}))
if err != nil {
return err
}
privateIpAlloc, err := compute.NewGlobalAddress(ctx, "private_ip_alloc", &compute.GlobalAddressArgs{
Name: pulumi.String("private-ip-alloc"),
Purpose: pulumi.String("VPC_PEERING"),
AddressType: pulumi.String("INTERNAL"),
PrefixLength: pulumi.Int(16),
Network: vpcNetwork.ID(),
})
if err != nil {
return err
}
_default, err := servicenetworking.NewConnection(ctx, "default", &servicenetworking.ConnectionArgs{
Network: vpcNetwork.ID(),
Service: pulumi.String("servicenetworking.googleapis.com"),
ReservedPeeringRanges: pulumi.StringArray{
privateIpAlloc.Name,
},
}, pulumi.DependsOn([]pulumi.Resource{
servicenetworking,
}))
if err != nil {
return err
}
invokeReplace, err := std.Replace(ctx, &std.ReplaceArgs{
Text: id,
Search: project.Name,
Replace: project.Number,
}, nil)
if err != nil {
return err
}
_, err = cloudbuild.NewBitbucketServerConfig(ctx, "bbs-config-with-peered-network", &cloudbuild.BitbucketServerConfigArgs{
ConfigId: pulumi.String("bbs-config"),
Location: pulumi.String("us-central1"),
HostUri: pulumi.String("https://bbs.com"),
Secrets: &cloudbuild.BitbucketServerConfigSecretsArgs{
AdminAccessTokenVersionName: pulumi.String("projects/myProject/secrets/mybbspat/versions/1"),
ReadAccessTokenVersionName: pulumi.String("projects/myProject/secrets/mybbspat/versions/1"),
WebhookSecretVersionName: pulumi.String("projects/myProject/secrets/mybbspat/versions/1"),
},
Username: pulumi.String("test"),
ApiKey: pulumi.String("<api-key>"),
PeeredNetwork: pulumi.String(vpcNetwork.ID().ApplyT(func(id string) (std.ReplaceResult, error) {
%!v(PANIC=Format method: runtime error: invalid memory address or nil pointer dereference)).(std.ReplaceResultOutput).ApplyT(func(invoke std.ReplaceResult) (*string, error) {
return invoke.Result, nil
}).(pulumi.StringPtrOutput)),
SslCa: pulumi.String("-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----\n"),
}, pulumi.DependsOn([]pulumi.Resource{
_default,
}))
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;
using Std = Pulumi.Std;
return await Deployment.RunAsync(() =>
{
var project = Gcp.Organizations.GetProject.Invoke();
var servicenetworking = new Gcp.Projects.Service("servicenetworking", new()
{
ServiceName = "servicenetworking.googleapis.com",
});
var vpcNetwork = new Gcp.Compute.Network("vpc_network", new()
{
Name = "vpc-network",
}, new CustomResourceOptions
{
DependsOn =
{
servicenetworking,
},
});
var privateIpAlloc = new Gcp.Compute.GlobalAddress("private_ip_alloc", new()
{
Name = "private-ip-alloc",
Purpose = "VPC_PEERING",
AddressType = "INTERNAL",
PrefixLength = 16,
Network = vpcNetwork.Id,
});
var @default = new Gcp.ServiceNetworking.Connection("default", new()
{
Network = vpcNetwork.Id,
Service = "servicenetworking.googleapis.com",
ReservedPeeringRanges = new[]
{
privateIpAlloc.Name,
},
}, new CustomResourceOptions
{
DependsOn =
{
servicenetworking,
},
});
var bbs_config_with_peered_network = new Gcp.CloudBuild.BitbucketServerConfig("bbs-config-with-peered-network", new()
{
ConfigId = "bbs-config",
Location = "us-central1",
HostUri = "https://bbs.com",
Secrets = new Gcp.CloudBuild.Inputs.BitbucketServerConfigSecretsArgs
{
AdminAccessTokenVersionName = "projects/myProject/secrets/mybbspat/versions/1",
ReadAccessTokenVersionName = "projects/myProject/secrets/mybbspat/versions/1",
WebhookSecretVersionName = "projects/myProject/secrets/mybbspat/versions/1",
},
Username = "test",
ApiKey = "<api-key>",
PeeredNetwork = Output.Tuple(vpcNetwork.Id, project, project).Apply(values =>
{
var id = values.Item1;
var project = values.Item2;
var project1 = values.Item3;
return Std.Replace.Invoke(new()
{
Text = id,
Search = project.Apply(getProjectResult => getProjectResult.Name),
Replace = project1.Number,
});
}).Apply(invoke => invoke.Result),
SslCa = @"-----BEGIN CERTIFICATE-----
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
-----END CERTIFICATE-----
",
}, new CustomResourceOptions
{
DependsOn =
{
@default,
},
});
});
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.projects.Service;
import com.pulumi.gcp.projects.ServiceArgs;
import com.pulumi.gcp.compute.Network;
import com.pulumi.gcp.compute.NetworkArgs;
import com.pulumi.gcp.compute.GlobalAddress;
import com.pulumi.gcp.compute.GlobalAddressArgs;
import com.pulumi.gcp.servicenetworking.Connection;
import com.pulumi.gcp.servicenetworking.ConnectionArgs;
import com.pulumi.gcp.cloudbuild.BitbucketServerConfig;
import com.pulumi.gcp.cloudbuild.BitbucketServerConfigArgs;
import com.pulumi.gcp.cloudbuild.inputs.BitbucketServerConfigSecretsArgs;
import com.pulumi.std.StdFunctions;
import com.pulumi.std.inputs.ReplaceArgs;
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 servicenetworking = new Service("servicenetworking", ServiceArgs.builder()
.service("servicenetworking.googleapis.com")
.build());
var vpcNetwork = new Network("vpcNetwork", NetworkArgs.builder()
.name("vpc-network")
.build(), CustomResourceOptions.builder()
.dependsOn(servicenetworking)
.build());
var privateIpAlloc = new GlobalAddress("privateIpAlloc", GlobalAddressArgs.builder()
.name("private-ip-alloc")
.purpose("VPC_PEERING")
.addressType("INTERNAL")
.prefixLength(16)
.network(vpcNetwork.id())
.build());
var default_ = new Connection("default", ConnectionArgs.builder()
.network(vpcNetwork.id())
.service("servicenetworking.googleapis.com")
.reservedPeeringRanges(privateIpAlloc.name())
.build(), CustomResourceOptions.builder()
.dependsOn(servicenetworking)
.build());
var bbs_config_with_peered_network = new BitbucketServerConfig("bbs-config-with-peered-network", BitbucketServerConfigArgs.builder()
.configId("bbs-config")
.location("us-central1")
.hostUri("https://bbs.com")
.secrets(BitbucketServerConfigSecretsArgs.builder()
.adminAccessTokenVersionName("projects/myProject/secrets/mybbspat/versions/1")
.readAccessTokenVersionName("projects/myProject/secrets/mybbspat/versions/1")
.webhookSecretVersionName("projects/myProject/secrets/mybbspat/versions/1")
.build())
.username("test")
.apiKey("<api-key>")
.peeredNetwork(vpcNetwork.id().applyValue(_id -> StdFunctions.replace(ReplaceArgs.builder()
.text(_id)
.search(project.name())
.replace(project.number())
.build())).applyValue(_invoke -> _invoke.result()))
.sslCa("""
-----BEGIN CERTIFICATE-----
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
-----END CERTIFICATE-----
""")
.build(), CustomResourceOptions.builder()
.dependsOn(default_)
.build());
}
}
resources:
servicenetworking:
type: gcp:projects:Service
properties:
service: servicenetworking.googleapis.com
vpcNetwork:
type: gcp:compute:Network
name: vpc_network
properties:
name: vpc-network
options:
dependsOn:
- ${servicenetworking}
privateIpAlloc:
type: gcp:compute:GlobalAddress
name: private_ip_alloc
properties:
name: private-ip-alloc
purpose: VPC_PEERING
addressType: INTERNAL
prefixLength: 16
network: ${vpcNetwork.id}
default:
type: gcp:servicenetworking:Connection
properties:
network: ${vpcNetwork.id}
service: servicenetworking.googleapis.com
reservedPeeringRanges:
- ${privateIpAlloc.name}
options:
dependsOn:
- ${servicenetworking}
bbs-config-with-peered-network:
type: gcp:cloudbuild:BitbucketServerConfig
properties:
configId: bbs-config
location: us-central1
hostUri: https://bbs.com
secrets:
adminAccessTokenVersionName: projects/myProject/secrets/mybbspat/versions/1
readAccessTokenVersionName: projects/myProject/secrets/mybbspat/versions/1
webhookSecretVersionName: projects/myProject/secrets/mybbspat/versions/1
username: test
apiKey: <api-key>
peeredNetwork:
fn::invoke:
function: std:replace
arguments:
text: ${vpcNetwork.id}
search: ${project.name}
replace: ${project.number}
return: result
sslCa: |
-----BEGIN CERTIFICATE-----
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
-----END CERTIFICATE-----
options:
dependsOn:
- ${default}
variables:
project:
fn::invoke:
function: gcp:organizations:getProject
arguments: {}
The peeredNetwork property references a VPC network configured for private service connection. Cloud Build uses this network when making requests to the Bitbucket Server instance. The sslCa property provides the SSL certificate chain in PEM format for validating HTTPS connections. This example creates the VPC peering infrastructure (network, IP allocation, service connection) before configuring the Bitbucket connection.
Beyond these examples
These snippets focus on specific Bitbucket Server configuration features: authentication and webhook configuration, repository selection, and VPC peering for private access. They’re intentionally minimal rather than full CI/CD pipelines.
The examples rely on pre-existing infrastructure such as Secret Manager secrets for authentication tokens, a Bitbucket Server instance (on-premises or cloud-hosted), and VPC networks for peered network configurations. They focus on connection configuration rather than provisioning the surrounding infrastructure.
To keep things focused, common integration patterns are omitted, including:
- Secret Manager secret creation and rotation
- IAM permissions for Cloud Build service account
- Build trigger configuration (separate resource)
- SSL certificate generation and management
These omissions are intentional: the goal is to illustrate how each Bitbucket Server connection feature is wired, not provide drop-in CI/CD modules. See the BitbucketServerConfig resource reference for all available configuration options.
Let's configure GCP Cloud Build Bitbucket Server Integration
Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.
Try Pulumi Cloud for FREEFrequently Asked Questions
Configuration & Immutability
apiKey, hostUri, configId, location, and project properties are immutable. Changing apiKey or hostUri will delete and recreate the resource, so plan accordingly or create a new config instead.secrets property: adminAccessTokenVersionName, readAccessTokenVersionName, and webhookSecretVersionName.Networking & Private Connectivity
peeredNetwork property to connect via VPC peering. The VPC network must be enabled for private service connection. If peeredNetwork is empty, Cloud Build will connect over the public internet.projects/{project}/global/networks/{network}, where {project} is a project number or ID and {network} is the VPC network name. The peered network example shows transforming the network ID to this format.sslCa property accepts PEM format certificates with .pem, .cer, or .crt extensions.Repository Management
connectedRepositories array with projectKey and repoSlug for each repository you want to connect.projects/{{project}}/locations/{{location}}/bitbucketServerConfigs/{{config_id}}, or the shorter formats {{project}}/{{location}}/{{config_id}} or {{location}}/{{config_id}}.Using a different cloud?
Explore integration guides for other cloud providers: