# The Firebase Hosting action gives every pull request its own preview channel

> The FirebaseExtended hosting action deploys each pull request to a preview channel, comments the preview URL on the pull request, keeps that URL stable across commits, and can deploy to the live channel on merge. It suits teams shipping a Firebase Hosting site who want reviewers to look at the actual change rather than a description of it.

**FirebaseExtended/action-hosting-deploy** — Automatically deploy shareable previews for your Firebase Hosting sites

- Repository: https://github.com/FirebaseExtended/action-hosting-deploy
- Website: https://firebase.google.com/docs/hosting/github-integration
- Stars: 812 · Forks: 231
- Language: TypeScript
- License: Apache-2.0
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/firebaseextended-action-hosting-deploy

## One channel per pull request, one stable URL

The core behaviour is described in four bullets at the top of the README, and the third one is the part that changes how a team works. The action creates a new preview channel, and its associated preview URL, for every pull request on the repository, and adds a comment to the pull request with that URL so you and each reviewer can view and test the change in a preview version of the app. Then it updates the preview URL with the changes from each commit by automatically deploying to the associated preview channel, and the URL does not change with each new commit. That last detail is the useful one. A reviewer who opened the link on the first commit and bookmarked it will land on the newest commit, and the comment on the pull request does not need to be edited as the branch moves. A fourth, optional behaviour is deploying the current state of the repository to the live channel when the pull request is merged.

## The Firebase CLI does the setup, in one of two commands

Setup is delegated to the Firebase CLI, and the README gives one command for each of the two states you might be in. If you have not set up Hosting at all, run this from the root of your local directory:

```bash
firebase init hosting
```

If you have already set up Hosting and only need the GitHub Action part of it, run:

```bash
firebase init hosting:github
```

The second command is also the answer to the question of how to set up the service account, since the README says the easiest way to configure the `firebaseServiceAccount` option is to run `firebase init hosting:github`, though a key can also be created by hand following the document in `docs/service-account.md`. The full setup guide lives in the Firebase Hosting documentation, and the point of using the CLI here is that it writes the same project configuration the action later reads.

## The preview workflow, and where the build steps go

The preview workflow is a file at `.github/workflows/deploy-preview.yml`, and the action is the only step that matters, because the checkout and the build are yours:

```yaml
name: Deploy to Preview Channel

on:
  pull_request:

jobs:
  build_and_preview:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: FirebaseExtended/action-hosting-deploy@v0
        with:
          repoToken: "${{ secrets.GITHUB_TOKEN }}"
          firebaseServiceAccount: "${{ secrets.FIREBASE_SERVICE_ACCOUNT }}"
          expires: 30d
          projectId: your-Firebase-project-ID
```

The README notes that you can restrict the trigger to specific files with a `paths` filter, and that build steps go between the checkout and the action, for example a `run: npm ci && npm run build` line. The action is pinned to the `@v0` tag rather than a commit, so the version you get is the moving major version of the action, and the `force` option is available if you want the Firebase CLI's `--force` behaviour to accept interactive prompts automatically.

## The live channel workflow is a second file

Promoting to production is a separate workflow, at `.github/workflows/deploy-prod.yml`, triggered on pushes to the main branch rather than on pull requests. The difference in the configuration is small and deliberate. The production job does not need a `repoToken`, because there is no pull request to comment on, and it sets `channelId: live` so the action deploys to the live channel of the default Hosting site:

```yaml
name: Deploy to Live Channel

on:
  push:
    branches:
      - main

jobs:
  deploy_live_website:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: FirebaseExtended/action-hosting-deploy@v0
        with:
          firebaseServiceAccount: "${{ secrets.FIREBASE_SERVICE_ACCOUNT }}"
          projectId: your-Firebase-project-ID
          channelId: live
```

Both files can carry the same `paths` filter, so a site with a documentation directory in the same repository does not trigger a deployment for an unrelated change.

## The options decide where a deployment lands and how long it lives

Five inputs carry most of the configuration. `firebaseServiceAccount` is required and is a service account JSON key, which the README insists should be stored as an encrypted secret in the Secrets area of the repository settings so that unintended access to the Firebase project is prevented. `projectId` is the Firebase project containing the Hosting site, and if you leave it blank you must check in a `.firebaserc` file so the CLI knows which project to use. `channelId` is the channel to deploy to, and leaving it blank auto-generates a preview channel and its ID per branch or pull request, which the README says you usually want, with the exception of a long-lived channel such as a `preprod` one for a `next` branch. `target` names the Hosting site, blank meaning the default target or all targets in the `.firebaserc`. `entryPoint` is the directory holding `firebase.json` relative to the repository root, defaulting to the root itself.

## Expiry, comments and the outputs other steps can consume

Two more options control the housekeeping and the noise. `expires` is how long the preview channel stays active after the last deploy, and if it is left blank the action uses a default expiry of 7 days, with the expiry date reset to the value on every new deployment, so a long-lived review pushes the expiry out rather than letting it lapse. `disableComment` turns off the comment on the pull request. `repoToken` is the option that enables the comment, and the README notes that GitHub sets that secret automatically so you do not have to create it, and that if you omit it you will have to find the preview URL in the action's build log instead. The action also emits values that later steps in a workflow can consume, with `urls` for the URLs deployed to, `expire_time` and `expire_time_formatted` for when the deployed preview URLs expire, and `details_url` for a single URL that was deployed to.

## The support arrangement is best effort, and the README says so

There is a status badge that reads Experimental, and the paragraph under it is the one to read before you depend on this in a release process. The repository is maintained by Googlers but is not a supported Firebase product, and issues there are answered by maintainers and other community members on GitHub on a best-effort basis. That is a different promise from a vendor support contract, and the difference matters when a deployment pipeline is on the critical path of a release. The action is also referenced from the official Firebase Hosting documentation, and the setup guide lives there too, so the documented path is the vendor's documentation even though the code is community answered. Treat the combination as an officially documented workflow with community support, and keep your own rollback plan for the live channel.

## Apache-2.0, and what the repository actually contains

The licence is Apache-2.0, in a `LICENSE` file at the root, and the action is packaged as a standard GitHub Action with an `action.yml`. The implementation is TypeScript, with the source in `src/` and the entry point at `src/index.ts`, and it is bundled with microbundle into a CommonJS file at `bin/action.min.js`, which is the `main` of the package. The package is marked private, since it is distributed as an action rather than to npm. Tests run under Jest with a `jest.config.ts` and `babel.config.ts`, Husky runs pretty-quick and a build as a pre-commit hook, and there is a `demo/` directory with a `firebase.json` and a `public/` folder for trying the action against a sample site. The release history runs from a `v0` alpha tag in August 2020 to v0.10.0 in August 2025 and v0.11.0 on 2026-06-25, which is also the date of the last push.

## Conclusion

Adopt this action when your site is hosted on Firebase Hosting and you want each pull request to be reviewable at a real URL, since the action creates a channel per pull request, comments the link and can promote the merge to the live channel. Do not adopt it as a general purpose deployment pipeline, because the action only knows how to drive the Firebase CLI against Firebase Hosting, and treat the support arrangement as informal because the README marks the repository experimental and states that it is maintained by Googlers but is not a supported Firebase product. Verify first which channels and targets exist in your project, and keep the service account key in GitHub's encrypted secrets rather than in the workflow file.

## FAQ

### How does the Firebase Hosting action handle pull requests?

It creates a new preview channel and preview URL for every pull request, adds a comment on the pull request with that URL, and deploys each new commit to the same channel so the URL stays the same across commits.

### How do I set up the Firebase Hosting GitHub integration?

Run `firebase init hosting` if you have not set up Hosting, or `firebase init hosting:github` if you have already set up Hosting and only need the GitHub Action part. The second command also sets up the service account key.

### How long do preview channels live?

The `expires` option sets how long the preview channel remains active after the last deploy, and the action uses a default of 7 days when it is left blank. The expiry date is reset to that value on every new deployment.

### Is this action a supported Firebase product?

No. The README marks the repository as Experimental and states it is maintained by Googlers but is not a supported Firebase product, and that issues are answered on a best-effort basis by maintainers and community members.

## Sources

- [FirebaseExtended/action-hosting-deploy on GitHub](https://github.com/FirebaseExtended/action-hosting-deploy)
- [License: Apache-2.0](https://github.com/FirebaseExtended/action-hosting-deploy/blob/main/LICENSE)
- [Project website](https://firebase.google.com/docs/hosting/github-integration)
- [README](https://github.com/FirebaseExtended/action-hosting-deploy/blob/main/README.md)
- [Releases](https://github.com/FirebaseExtended/action-hosting-deploy/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/firebaseextended-action-hosting-deploy
