# firebase-action turns the Firebase CLI into a Docker based GitHub Action

> w9jds/firebase-action is an MIT licensed GitHub Action that runs the firebase-tools command line client inside a container so a workflow can deploy to Hosting, Functions, Firestore or Remote Config with a single args input. It suits teams that want one pinned image for Firebase deployments, and it deliberately gives you nothing back except the exit code.

**w9jds/firebase-action** — GitHub Action for interacting with Firebase

- Repository: https://github.com/w9jds/firebase-action
- Stars: 947 · Forks: 207
- Language: Shell
- License: MIT
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/w9jds-firebase-action

## One input, one container, the whole firebase CLI

The premise of this Action is narrow and clean. Instead of writing a workflow that installs Node, installs the Firebase CLI, exports a token and runs a command, you use a prebuilt Docker image that already contains everything, and you pass the command you want as a single argument.

The README describes it as an Action for firebase-tools that enables arbitrary actions with the firebase command line client, and the inputs section has exactly one entry: args, marked required, and described as the arguments you want to use for the firebase cli. That is the entire interface. Anything the CLI can do, the Action can do, which is the point of wrapping rather than reimplementing.

The implementation is a container. The Dockerfile starts from the timbru31/java-node:21-jdk-jod image, so Java and Node are already present, which is what the Firebase CLI needs, and it installs jq with apt during the build. It then installs npm@10.9.2 and firebase-tools@15.34.0 globally, copies the LICENSE and README into the image, copies entrypoint.sh to the root, and sets that as the entrypoint with a default command of --help.

The labels make the Action discoverable in the marketplace, with com.github.actions.name set to GitHub Action for Firebase and a description that says it wraps the firebase-tools CLI to enable common commands. The image also carries version, repository, homepage and maintainer labels, with the version label pinned to 15.34.0 to match the bundled CLI.

Because the whole thing is a container, the Action is a Docker Action: the repository holds a Dockerfile, an action.yaml, an entrypoint.sh, a script/ directory and a test/ directory, and the primary language of the project is Shell.

## Three ways to authenticate, and a deprecation already in the docs

The authentication story is the part of this Action that deserves the most attention, because the credential is the risk.

There are three environment variables, and the documentation says which is required when. GCP_SA_KEY is required if FIREBASE_TOKEN is not set, and it accepts either a normal service account key in JSON format or a base64 encoded one, with the needed permissions for whatever you are deploying. FIREBASE_TOKEN is required if GCP_SA_KEY is not set, and the README marks that method as one that will soon be deprecated, telling you to use GCP_SA_KEY instead. GOOGLE_APPLICATION_CREDENTIALS is required if neither of the other two is set, and it points at the location of a credential JSON file, using the application default credentials path.

The service account role list is the most practically useful part of the README. The service account uses the App Engine default service account during the deploy process, so it also needs the Service Account User role. On top of that, the roles are listed per deploy target: Cloud Functions Developer for functions, Cloud Scheduler Admin if the deploy has scheduled functions, Secret Manager Viewer if the deploy requires access to secrets, Firebase Rules Admin if updating Firestore Rules, Firebase Functions Admin if the project uses blocking functions such as beforeCreate or beforeSignin, Cloud Datastore Index Admin for Firestore indexes, Firebase Hosting Admin for Hosting files, and Firebase Remote Config Admin for Remote Config.

That list is the actual instruction manual for this Action. Read it against what your pipeline deploys and grant only those roles, because the key is a repository secret that the Action will use with the full authority you gave it.

## Optional inputs cover the project, the config and the folder

Beyond args, three optional environment variables shape the run.

PROJECT_ID specifies a specific project for all commands, and is not required if you already specify a project in your .firebaserc file. The README adds the important caveat: if you use it, you need to give Viewer permission roles to your service account, otherwise the action fails with authentication errors. That is a slightly counter intuitive failure mode, since specifying the project id is what makes the deploy deterministic.

PROJECT_PATH is the path to the folder containing firebase.json when that file is not at the root of your repository, with the example ./my-app. That matters for monorepo layouts, where a single repository holds several applications and each has its own firebase.json.

CONFIG_VALUES supplies configuration values for Firebase functions that would normally be set with firebase functions:config:set, with the example stripe.secret_key=SECRET_KEY zapier.secret_key=SECRET_KEY. Note the shape of that example: it is a space separated list of key equals value pairs, passed through as a single environment variable, which is one of the places where YAML quoting in a workflow file is easy to get wrong.

One output was removed rather than added. The response output, which would have returned the full response from the Firebase command, is struck through in the README, and the note says it has been removed for now as it caused loads of issues in the bash script. So the Action gives you a command and an exit code, and if you need a URL or an ID out of the deploy you have to capture it yourself.

## Pinning a version, or pointing at master on purpose

The Action can be used two ways, and the README is unusually candid about why.

The safe way is to reference a release tag, and the repository publishes a release for each Firebase CLI version it packages. The recent releases are v15.34.0 on 2026-10-15, v15.33.0 on 2026-10-09 and v15.32.1 on 2026-10-01, and each release name carries the firebase-tools version it wraps, so the two are traceable. The README explains the intent: starting with version v2.1.2 each version release points to a versioned Docker image, allowing the pipeline to be hardened, so things do not break when something changes in the action.

The other way is to point at master:

```yaml
  name: Deploy to Firebase
  uses: docker://w9jds/firebase-action:master
  with:
    args: deploy --only hosting
  env:
    FIREBASE_TOKEN: ${{ secrets.FIREBASE_TOKEN }}
```

The README describes that as pointing to a master version if you would like to test out what might not be deployed into a release yet. That is a useful escape hatch when a CLI release lands and the action has not been rebuilt, and it is also a way to have a production deploy change behaviour without a commit, so it belongs in a test workflow rather than a release one.

The Docker image form, docker://w9jds/firebase-action, is worth noting as a category difference from the usual uses: w9jds/firebase-action@master in a step. The former pulls a published Docker image directly, the latter runs the Action definition from the repository.

## A deploy step that still needs the repository checked out

The example workflow in the README is the practical template, and it is worth reading for the shape of the deploy job rather than the details:

```yaml
      - name: Deploy to Firebase
        uses: w9jds/firebase-action@master
        with:
          args: deploy --only hosting
        env:
          FIREBASE_TOKEN: ${{ secrets.FIREBASE_TOKEN }}
```

The job structure it belongs to separates build from deploy, with a build job that checks out the repo, installs dependencies with npm install, runs npm run build-prod and uploads a dist artifact, and a deploy job that needs the build, downloads the artifact and then runs the Action. The README's recommendation section makes the point that if you do separate jobs for build and deployment, which is probably advisable, you must clone your repo as the Firebase CLI requires the firebase repo to deploy, specifically the firebase.json.

That is a real constraint that catches people out. Passing a built artifact between jobs does not remove the need for the source checkout, because the CLI reads firebase.json from the working tree to know what to deploy. If you use a container that does not carry your repository, the deploy step will not find the configuration.

Two smaller details in the same section. If you have multiple hosting environments you can specify which one in the args line, with the example args: deploy --only hosting:[environment name]. And if you want to add a message to a deployment, such as the Git commit message, you have to escape the quotes or the YAML breaks, which the README shows as args: deploy --message \"${{ github.event.head_commit.message }}\". The escaping is manual and easy to get wrong, which is a small quality of life issue for anyone deploying on every commit.

## Licence, maintenance and the release naming you can rely on

The licence is MIT, and the README is specific about its scope: the Dockerfile and associated scripts and documentation in this project are released under the MIT License, with a LICENSE file at the repository root. The wording is worth reading carefully, because it names the Dockerfile, the scripts and the documentation rather than making a blanket claim, and the Action also ships a container image containing the Firebase CLI, which is separately licensed upstream.

On maintenance, the signal is clear. The repository is not archived, the last push was on 2026-10-15, and the releases land within days of the upstream CLI versions they wrap, with 15.34.0 published on the same day as the push. The Dockerfile pins npm@10.9.2 and firebase-tools@15.34.0 globally, and the version label matches, so a release tag tells you exactly which CLI you get.

The practical upgrade model is therefore simple: when a new firebase-tools release appears, the action image is rebuilt and tagged, and you move your workflow to the new tag. That is a low ceremony upgrade, but it is also a recurring decision, since staying on an old tag means staying on an old CLI with whatever fixes have landed since.

The remaining trade-off is the one the README itself points at with the alternative project. It mentions setup-firebase as an early version of a rewrite, a more flexible implementation that allows you to choose Node and Java versions and run more than one command. The current action gives you one command in a fixed image, and the rewrite is where that constraint would be lifted.

## Conclusion

Adopt firebase-action if you deploy Firebase from GitHub Actions and want a pinned Docker image that already contains a specific firebase-tools release, and keep the setup-firebase rewrite in mind if you need to choose Node and Java versions or run several commands in one step. Before you wire it into a pipeline, decide which authentication variable you will use, since FIREBASE_TOKEN is documented as due for deprecation, grant the service account only the roles your deploy actually needs, and remember that a separate build and deploy job still has to check out the repository because the CLI needs firebase.json. The last push was on 2026-10-15 and the release tags track firebase-tools versions.

## FAQ

### What inputs does w9jds/firebase-action take?

One required input, args, which holds the arguments passed to the firebase command line client. Optional environment variables include PROJECT_ID, PROJECT_PATH and CONFIG_VALUES, and authentication comes from GCP_SA_KEY, FIREBASE_TOKEN or GOOGLE_APPLICATION_CREDENTIALS.

### How do I authenticate the firebase-action in a workflow?

Supply one of three environment variables: GCP_SA_KEY with a JSON or base64 encoded service account key, FIREBASE_TOKEN acquired through firebase login:ci, or GOOGLE_APPLICATION_CREDENTIALS pointing at a credential JSON file. The README notes that FIREBASE_TOKEN will soon be deprecated in favour of GCP_SA_KEY.

### Which IAM roles does the service account need for a Firebase deploy?

The service account needs Service Account User because the deploy uses the App Engine default service account, plus per target roles such as Firebase Hosting Admin, Cloud Functions Developer, Firebase Rules Admin, Cloud Datastore Index Admin and Firebase Remote Config Admin depending on what the deploy touches.

### Can I get the output of the Firebase command from the action?

No. The response output has been removed, and the README says it was removed for now as it caused loads of issues in the bash script, so the action gives you the command result through its exit code rather than a parsed payload.

### How do I pin a specific version of the firebase-action?

Reference a release tag such as w9jds/firebase-action@v15.34.0, where each release points to a versioned Docker image containing a matching firebase-tools version. You can also use docker://w9jds/firebase-action:master to test unreleased changes.

## Sources

- [Issues](https://github.com/w9jds/firebase-action/issues)
- [License: MIT](https://github.com/w9jds/firebase-action/blob/master/LICENSE)
- [README](https://github.com/w9jds/firebase-action/blob/master/README.md)
- [Releases](https://github.com/w9jds/firebase-action/releases)
- [w9jds/firebase-action on GitHub](https://github.com/w9jds/firebase-action)

---

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