Firebase Hosting Deployment Automation with Gitlab CI

Andro Babu
4 min readJan 14, 2018

--

Our current web era has decoupled the front-end (Single Page Application) and back-end (APIs) which enables you to scale independently.

Firebase Hosting is a production-grade hosting for simple static websites or single page applications like Angular, Ember, Backbone, and React. Key features of Firebase Hosting include:

  1. CDN-backed global content delivery
  2. Automatic and Free SSL certificate provisioning
  3. Custom (and even naked) domain support
  4. One-command deploy; One-click rollback
  5. Support for non-SNI devices, to ensure all users have a secure experience

Gitlab provides you free unlimited private repositories along with continuous integration (CI). Though you can deploy your content just in seconds with the Firebase command line interface, you can still sit back and relax with automating the deployment with CI tools like Gitlab.

Prerequisite Steps

  • Install Firebase CLI tools using npm npm i -g firebase-tools or if you’re using yarn then yarn global add firebase-tools
  • Initialise your project with $ firebase init and configure your deployment directory. In case of simple websites, maintain your code in “public” directory. In case of single page applications like React, “build” directory will be your production ready target directory. Hence configure your firebase to use “build” directory instead of “public”. You can do this while initialising with $ firebase init or manually edit firebase.json as below:
{
"hosting": {
"public": "build",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
],
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
]
}
  • Make sure you can deploy using the command $ firebase deploy from your local machine and verify the website with the url provided in terminal

Automation Steps

Assuming you have a repository in Gitlab, you can configure your CI just with “.gitlab-ci.yml” file committed in your repository. The firebase hosting deployment can be automated as per the steps below:

  1. Get the Firebase Token (used to login by CI on behalf of you)
  2. Set the Token in Gitlab CI
  3. Configure CI in YML (copy pasting snippet)

Step 1: Get the Firebase Token

Firebase CLI tools helps you control your firebase account and you can generate an access token for use in non-interactive environments with the below command

$ firebase login:ci

A browser page opens and you will be prompted to login with your google account. Once you grant the access, a token will be generated. Use this token to login on a CI server

Step 2: Set the Token in Gitlab CI

Login to your Gitlab account and navigate to your repository settings and then “CI/CD” in sidebar. Expand “Secret Variables” section and add the below:

Key   : FIREBASE_TOKEN
Value : 1/VXX-XXX-Your-Copied-Firebase-Token-XXX-XXE

These variables will be passed as environment variables to your pipeline in Gitlab Runner

Step 3: Configure CI in YML

Just create a file named .gitlab-ci.yml with the below contents and commit it into your repository. Have a look at the .gitlab-ci.yml in gist.

image: rambabusaravanan/firebase

stages:
- deploy

cache:
paths:
- node_modules/
key: "$CI_BUILD_REPO"

deploy-prod:
stage: deploy
only:
- master
script:
- yarn
- yarn run build
- firebase use <project-name> --token $FIREBASE_TOKEN
- firebase deploy --only hosting -m "Pipe $CI_PIPELINE_ID Build $CI_BUILD_ID" --token $FIREBASE_TOKEN

Replace the <project-name> with your Firebase project name and customise the deploy message if needed.

If your front-end is just a simple website (not a npm project), then below code suits best.

image: rambabusaravanan/firebase

stages:
- deploy

deploy-prod:
stage: deploy
only:
- master
script:
- firebase use <project-name> --token $FIREBASE_TOKEN
- firebase deploy --only hosting -m "Pipe $CI_PIPELINE_ID Build $CI_BUILD_ID" --token $FIREBASE_TOKEN

You’re done. Once you push this yml, you can see the magic running in “Pipelines” section of your repository in Gitlab

Explanation

Any CI job runs in container (base image) where the required software tools were installed, source code were cloned, built and then deployed. Let’s break down the .gitlab-ci.yml file for better explanation.

  1. Base Image: I have used an image rambabusaravanan/firebase, a light weight alphine based docker container that contains the required “firebase-tools” pre-installed in it, to save tools installation time
image: rambabusaravanan/firebase

2. Pipelines, Stages, Jobs: For a complex pipeline having multiple jobs, you can group jobs into different stages like build, test, deploy. Jobs of the same stage are executed in parallel. Our case is simpler pipeline having only one job named deploy-prod grouped in stage named deploy

stages:
- deploy

deploy-prod:
stage: deploy
...
...

3. Job Policy: A job can be started via various triggers like every git push or based on success/failure of previous job or manually. For our case, we need to deploy on every push on ‘master’ branch.

  only:
- master

4. Script: It’s the actual magic area where build and deployment happens. You can build a npm project by yarn run build. For some projects this might vary if the build command is not configured as npm scripts in package.json.

The value for $FIREBASE_TOKEN is passed as environment variable which is configured as CI/CD Secret Variables. Other variables like $CI_PIPELINE_ID and $CI_BUILD_ID are set by Gitlab CI Runners.

  script:
- yarn
- yarn run build
- firebase use <project-name> --token $FIREBASE_TOKEN
- firebase deploy --only hosting -m "Pipe $CI_PIPELINE_ID Build $CI_BUILD_ID" --token $FIREBASE_TOKEN

5. Cache Policy: We’ve skipped the installation time of “firebase-tools” by using special container image. But this is not enough. Everytime we run the job, fresh installation of “node_modules” happens. To avoid this we can set the policy to cache the node_modules folder for across this repository. so that upon next run installation time of existing modules skipped, only new modules take time.

cache: 
paths:
- node_modules/
key: "$CI_BUILD_REPO"

Reference:

You can find the complete .gitlab-ci.yml file and with a readme at https://gist.github.com/rambabusaravanan/4907ea46d814bc69002c6f011ae6dd48

--

--