The gcp:firebase/hostingRelease:HostingRelease resource, part of the Pulumi GCP provider, controls which Firebase Hosting version is publicly accessible on a site or channel. This guide focuses on three capabilities: deploying versions to live sites, publishing to preview channels, and disabling site access.
Releases depend on existing HostingSite and HostingVersion resources. Preview deployments also require HostingChannel. The examples are intentionally small. Combine them with your own site configuration, content versions, and channel strategy.
Deploy a version to the live site
Most deployments publish content to the default “live” channel, making it immediately accessible to all visitors.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const _default = new gcp.firebase.HostingSite("default", {
project: "my-project-name",
siteId: "site-id",
});
const defaultHostingVersion = new gcp.firebase.HostingVersion("default", {
siteId: _default.siteId,
config: {
redirects: [{
glob: "/google/**",
statusCode: 302,
location: "https://www.google.com",
}],
},
});
const defaultHostingRelease = new gcp.firebase.HostingRelease("default", {
siteId: _default.siteId,
versionName: defaultHostingVersion.name,
message: "Test release",
});
import pulumi
import pulumi_gcp as gcp
default = gcp.firebase.HostingSite("default",
project="my-project-name",
site_id="site-id")
default_hosting_version = gcp.firebase.HostingVersion("default",
site_id=default.site_id,
config={
"redirects": [{
"glob": "/google/**",
"status_code": 302,
"location": "https://www.google.com",
}],
})
default_hosting_release = gcp.firebase.HostingRelease("default",
site_id=default.site_id,
version_name=default_hosting_version.name,
message="Test release")
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/firebase"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_default, err := firebase.NewHostingSite(ctx, "default", &firebase.HostingSiteArgs{
Project: pulumi.String("my-project-name"),
SiteId: pulumi.String("site-id"),
})
if err != nil {
return err
}
defaultHostingVersion, err := firebase.NewHostingVersion(ctx, "default", &firebase.HostingVersionArgs{
SiteId: _default.SiteId,
Config: &firebase.HostingVersionConfigArgs{
Redirects: firebase.HostingVersionConfigRedirectArray{
&firebase.HostingVersionConfigRedirectArgs{
Glob: pulumi.String("/google/**"),
StatusCode: pulumi.Int(302),
Location: pulumi.String("https://www.google.com"),
},
},
},
})
if err != nil {
return err
}
_, err = firebase.NewHostingRelease(ctx, "default", &firebase.HostingReleaseArgs{
SiteId: _default.SiteId,
VersionName: defaultHostingVersion.Name,
Message: pulumi.String("Test release"),
})
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 @default = new Gcp.Firebase.HostingSite("default", new()
{
Project = "my-project-name",
SiteId = "site-id",
});
var defaultHostingVersion = new Gcp.Firebase.HostingVersion("default", new()
{
SiteId = @default.SiteId,
Config = new Gcp.Firebase.Inputs.HostingVersionConfigArgs
{
Redirects = new[]
{
new Gcp.Firebase.Inputs.HostingVersionConfigRedirectArgs
{
Glob = "/google/**",
StatusCode = 302,
Location = "https://www.google.com",
},
},
},
});
var defaultHostingRelease = new Gcp.Firebase.HostingRelease("default", new()
{
SiteId = @default.SiteId,
VersionName = defaultHostingVersion.Name,
Message = "Test release",
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.firebase.HostingSite;
import com.pulumi.gcp.firebase.HostingSiteArgs;
import com.pulumi.gcp.firebase.HostingVersion;
import com.pulumi.gcp.firebase.HostingVersionArgs;
import com.pulumi.gcp.firebase.inputs.HostingVersionConfigArgs;
import com.pulumi.gcp.firebase.HostingRelease;
import com.pulumi.gcp.firebase.HostingReleaseArgs;
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 default_ = new HostingSite("default", HostingSiteArgs.builder()
.project("my-project-name")
.siteId("site-id")
.build());
var defaultHostingVersion = new HostingVersion("defaultHostingVersion", HostingVersionArgs.builder()
.siteId(default_.siteId())
.config(HostingVersionConfigArgs.builder()
.redirects(HostingVersionConfigRedirectArgs.builder()
.glob("/google/**")
.statusCode(302)
.location("https://www.google.com")
.build())
.build())
.build());
var defaultHostingRelease = new HostingRelease("defaultHostingRelease", HostingReleaseArgs.builder()
.siteId(default_.siteId())
.versionName(defaultHostingVersion.name())
.message("Test release")
.build());
}
}
resources:
default:
type: gcp:firebase:HostingSite
properties:
project: my-project-name
siteId: site-id
defaultHostingVersion:
type: gcp:firebase:HostingVersion
name: default
properties:
siteId: ${default.siteId}
config:
redirects:
- glob: /google/**
statusCode: 302
location: https://www.google.com
defaultHostingRelease:
type: gcp:firebase:HostingRelease
name: default
properties:
siteId: ${default.siteId}
versionName: ${defaultHostingVersion.name}
message: Test release
When you create a release with a versionName, Firebase Hosting makes that version’s content publicly available. The siteId identifies which site receives the deployment. The message property documents what changed in this release. Without a channelId, the release targets the default “live” channel.
Deploy a version to a preview channel
Preview channels let teams test changes in isolated environments before promoting to production.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const _default = new gcp.firebase.HostingSite("default", {
project: "my-project-name",
siteId: "site-with-channel",
});
const defaultHostingVersion = new gcp.firebase.HostingVersion("default", {
siteId: _default.siteId,
config: {
redirects: [{
glob: "/google/**",
statusCode: 302,
location: "https://www.google.com",
}],
},
});
const defaultHostingChannel = new gcp.firebase.HostingChannel("default", {
siteId: _default.siteId,
channelId: "channel-id",
});
const defaultHostingRelease = new gcp.firebase.HostingRelease("default", {
siteId: _default.siteId,
channelId: defaultHostingChannel.channelId,
versionName: defaultHostingVersion.name,
message: "Test release in channel",
});
import pulumi
import pulumi_gcp as gcp
default = gcp.firebase.HostingSite("default",
project="my-project-name",
site_id="site-with-channel")
default_hosting_version = gcp.firebase.HostingVersion("default",
site_id=default.site_id,
config={
"redirects": [{
"glob": "/google/**",
"status_code": 302,
"location": "https://www.google.com",
}],
})
default_hosting_channel = gcp.firebase.HostingChannel("default",
site_id=default.site_id,
channel_id="channel-id")
default_hosting_release = gcp.firebase.HostingRelease("default",
site_id=default.site_id,
channel_id=default_hosting_channel.channel_id,
version_name=default_hosting_version.name,
message="Test release in channel")
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/firebase"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_default, err := firebase.NewHostingSite(ctx, "default", &firebase.HostingSiteArgs{
Project: pulumi.String("my-project-name"),
SiteId: pulumi.String("site-with-channel"),
})
if err != nil {
return err
}
defaultHostingVersion, err := firebase.NewHostingVersion(ctx, "default", &firebase.HostingVersionArgs{
SiteId: _default.SiteId,
Config: &firebase.HostingVersionConfigArgs{
Redirects: firebase.HostingVersionConfigRedirectArray{
&firebase.HostingVersionConfigRedirectArgs{
Glob: pulumi.String("/google/**"),
StatusCode: pulumi.Int(302),
Location: pulumi.String("https://www.google.com"),
},
},
},
})
if err != nil {
return err
}
defaultHostingChannel, err := firebase.NewHostingChannel(ctx, "default", &firebase.HostingChannelArgs{
SiteId: _default.SiteId,
ChannelId: pulumi.String("channel-id"),
})
if err != nil {
return err
}
_, err = firebase.NewHostingRelease(ctx, "default", &firebase.HostingReleaseArgs{
SiteId: _default.SiteId,
ChannelId: defaultHostingChannel.ChannelId,
VersionName: defaultHostingVersion.Name,
Message: pulumi.String("Test release in channel"),
})
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 @default = new Gcp.Firebase.HostingSite("default", new()
{
Project = "my-project-name",
SiteId = "site-with-channel",
});
var defaultHostingVersion = new Gcp.Firebase.HostingVersion("default", new()
{
SiteId = @default.SiteId,
Config = new Gcp.Firebase.Inputs.HostingVersionConfigArgs
{
Redirects = new[]
{
new Gcp.Firebase.Inputs.HostingVersionConfigRedirectArgs
{
Glob = "/google/**",
StatusCode = 302,
Location = "https://www.google.com",
},
},
},
});
var defaultHostingChannel = new Gcp.Firebase.HostingChannel("default", new()
{
SiteId = @default.SiteId,
ChannelId = "channel-id",
});
var defaultHostingRelease = new Gcp.Firebase.HostingRelease("default", new()
{
SiteId = @default.SiteId,
ChannelId = defaultHostingChannel.ChannelId,
VersionName = defaultHostingVersion.Name,
Message = "Test release in channel",
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.firebase.HostingSite;
import com.pulumi.gcp.firebase.HostingSiteArgs;
import com.pulumi.gcp.firebase.HostingVersion;
import com.pulumi.gcp.firebase.HostingVersionArgs;
import com.pulumi.gcp.firebase.inputs.HostingVersionConfigArgs;
import com.pulumi.gcp.firebase.HostingChannel;
import com.pulumi.gcp.firebase.HostingChannelArgs;
import com.pulumi.gcp.firebase.HostingRelease;
import com.pulumi.gcp.firebase.HostingReleaseArgs;
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 default_ = new HostingSite("default", HostingSiteArgs.builder()
.project("my-project-name")
.siteId("site-with-channel")
.build());
var defaultHostingVersion = new HostingVersion("defaultHostingVersion", HostingVersionArgs.builder()
.siteId(default_.siteId())
.config(HostingVersionConfigArgs.builder()
.redirects(HostingVersionConfigRedirectArgs.builder()
.glob("/google/**")
.statusCode(302)
.location("https://www.google.com")
.build())
.build())
.build());
var defaultHostingChannel = new HostingChannel("defaultHostingChannel", HostingChannelArgs.builder()
.siteId(default_.siteId())
.channelId("channel-id")
.build());
var defaultHostingRelease = new HostingRelease("defaultHostingRelease", HostingReleaseArgs.builder()
.siteId(default_.siteId())
.channelId(defaultHostingChannel.channelId())
.versionName(defaultHostingVersion.name())
.message("Test release in channel")
.build());
}
}
resources:
default:
type: gcp:firebase:HostingSite
properties:
project: my-project-name
siteId: site-with-channel
defaultHostingVersion:
type: gcp:firebase:HostingVersion
name: default
properties:
siteId: ${default.siteId}
config:
redirects:
- glob: /google/**
statusCode: 302
location: https://www.google.com
defaultHostingChannel:
type: gcp:firebase:HostingChannel
name: default
properties:
siteId: ${default.siteId}
channelId: channel-id
defaultHostingRelease:
type: gcp:firebase:HostingRelease
name: default
properties:
siteId: ${default.siteId}
channelId: ${defaultHostingChannel.channelId}
versionName: ${defaultHostingVersion.name}
message: Test release in channel
The channelId property routes the release to a specific preview channel instead of the live site. Each channel gets its own URL for testing. This configuration extends basic deployment by adding channel isolation, letting you validate changes before making them public.
Take a site offline without deleting it
During maintenance or decommissioning, you can disable sites while preserving their configuration.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const _default = new gcp.firebase.HostingSite("default", {
project: "my-project-name",
siteId: "site-id",
});
const defaultHostingRelease = new gcp.firebase.HostingRelease("default", {
siteId: _default.siteId,
type: "SITE_DISABLE",
message: "Take down site",
});
import pulumi
import pulumi_gcp as gcp
default = gcp.firebase.HostingSite("default",
project="my-project-name",
site_id="site-id")
default_hosting_release = gcp.firebase.HostingRelease("default",
site_id=default.site_id,
type="SITE_DISABLE",
message="Take down site")
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/firebase"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_default, err := firebase.NewHostingSite(ctx, "default", &firebase.HostingSiteArgs{
Project: pulumi.String("my-project-name"),
SiteId: pulumi.String("site-id"),
})
if err != nil {
return err
}
_, err = firebase.NewHostingRelease(ctx, "default", &firebase.HostingReleaseArgs{
SiteId: _default.SiteId,
Type: pulumi.String("SITE_DISABLE"),
Message: pulumi.String("Take down site"),
})
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 @default = new Gcp.Firebase.HostingSite("default", new()
{
Project = "my-project-name",
SiteId = "site-id",
});
var defaultHostingRelease = new Gcp.Firebase.HostingRelease("default", new()
{
SiteId = @default.SiteId,
Type = "SITE_DISABLE",
Message = "Take down site",
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.firebase.HostingSite;
import com.pulumi.gcp.firebase.HostingSiteArgs;
import com.pulumi.gcp.firebase.HostingRelease;
import com.pulumi.gcp.firebase.HostingReleaseArgs;
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 default_ = new HostingSite("default", HostingSiteArgs.builder()
.project("my-project-name")
.siteId("site-id")
.build());
var defaultHostingRelease = new HostingRelease("defaultHostingRelease", HostingReleaseArgs.builder()
.siteId(default_.siteId())
.type("SITE_DISABLE")
.message("Take down site")
.build());
}
}
resources:
default:
type: gcp:firebase:HostingSite
properties:
project: my-project-name
siteId: site-id
defaultHostingRelease:
type: gcp:firebase:HostingRelease
name: default
properties:
siteId: ${default.siteId}
type: SITE_DISABLE
message: Take down site
Setting type to SITE_DISABLE makes Firebase Hosting act as if the site never existed, blocking all traffic. This release type doesn’t reference a versionName because it’s not deploying content. The site remains configured and can be re-enabled by deploying a new version.
Beyond these examples
These snippets focus on specific release-level features: live site deployment, preview channel isolation, and site disabling. They’re intentionally minimal rather than full hosting configurations.
The examples reference pre-existing infrastructure such as Firebase Hosting sites (HostingSite), hosting versions with content configuration (HostingVersion), and preview channels (HostingChannel) for non-production deployments. They focus on controlling version visibility rather than defining site content or infrastructure.
To keep things focused, common release patterns are omitted, including:
- Rollback to previous versions (type: ROLLBACK)
- Version content configuration (redirects, rewrites, headers)
- Custom domain setup and SSL certificates
- Release scheduling and automation
These omissions are intentional: the goal is to illustrate how each release feature is wired, not provide drop-in hosting modules. See the Firebase Hosting Release resource reference for all available configuration options.
Let's deploy GCP Firebase Hosting Releases
Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.
Try Pulumi Cloud for FREEFrequently Asked Questions
Provider & Setup
terraform-provider-google-beta provider.Release Types & Deployment
DEPLOY or ROLLBACK when you provide versionName. You only need to explicitly set type when using SITE_DISABLE.type set to SITE_DISABLE and omit the versionName property.versionName parameter must be empty when the release type is SITE_DISABLE, as disabling a site doesn’t deploy any version.Channels & Targeting
channelId releases to the default “live” channel (your main site). Specifying channelId releases to a preview channel for testing before going live.Configuration & Constraints
siteId, type, channelId, message, versionName) are immutable and require resource replacement to change.versionName must be in the format sites/SITE_ID/versions/VERSION_ID and the version must belong to the same site specified in siteId.message property can be up to 512 characters.Using a different cloud?
Explore integration guides for other cloud providers: