When firebase meets CD/CI
This is part 1 of a series of devops 101 with firebase cloud functions.
You can check the working repo here.
Well, at this point I’m a fan of this, migrating all our platform from AWS to gcloud it’s been a great experience (pun intended), this time I want to show you how easy is to deploy your firebase projects with Cloud Build, direct to the point.
I made this approach to work with several projects and services. You will need to change to the Blaze plan and activate billing (this is important if you are using firebase in production and you want to keep track of your cost).
I will assume you have several projects, for the sake of the example, I will use only two production and staging.
Let’s say you have a master account firstname.lastname@example.org, based on this account you two firebase projects:
In this case, you will give unlimited access to developers to work on my-company-dev but the access to my-company-prod is limited, this is key cause we are going to set all this project on this account. The whole project looks like this:
All secrets are going to be handled via the production account. Commits to the master and staging branch in github will trigger the process. How to should manage your PRs is out of the scope of this post.
##The process Using your operations account you should create both of your projects on the firebase console.
After you create your project following the instructions set here, your files should look like this:
I only picked cloud functions but it can be extended to hosting, storage, rules, etc. Let’s do a couple of things here before move on, first open the
.firebaserc file and make sure it looks like this:
You can use whatever naming convention (duh) you want to.
Also, add a
.env file in the root of the project and lastly, make sure you add
.env to your
We will come back here later, let’s move to the google console.
Before moving any further, you need to install the gcloud sdk, you can do it using this link. Make sure you download the right installation for your system and more important login using your master account.
Go into the gcloud console and using the top search bar type Cloud Build and enable the API:
Click Triggers and after enabling it, you will get something like this:
Make sure you select your github project and set the following configuration:
This will be our trigger to the staging.
Cloud Build configuration file
my-company-prod, make sure you select
Cloud Build configuration file.
By default, the firebase tool is not available on the npm image, we could install it but I’ve found out that is way easier going to this process instead.
You will need to clone the repo from the cloud builder community.
git clone https://github.com/GoogleCloudPlatform/cloud-builders-community cd cloud-builders-community/firebase gcloud builds submit --config cloudbuild.yaml .
After the process is completed, you can delete the repo from your computer.
Note: If you are managing multiple projects into your gcloud account SDK, you should set the my-company-prod first
gcloud config set project my-company-prod
We are almost there! let’s go back to your project IDE.
We need to generate the firebase ci token, on your terminal using the firebase tool type:
firebase use production // our whatever you main project is firebase login:ci
This will generate a token, copy and paste it into your .env (remember this file should be added to your
Now we need to do a couple of stuff:
Note: I like to keep this token encrypted but maybe this is not your case, if so, you can just copy and paste it as it is on the Cloud Build items where I mentioned you can set your environment variables and ignore this part.
Let’s go by parts…
Cryptographic Keys on the top search bar and enable the service.
Alright! now let’s go to encrypt your secrets!
Go back to your terminal and
into your project folder type the following command:
gcloud kms encrypt --plaintext-file=.env --ciphertext-file=.env.enc --location=global --keyring=ci-ring --key=deployment
No answer will be returned but you will see that a filed called
.env.enc was created.
If you are on mac you can type the following command:
Note: I’m not sure about equivalent on windows or linux :( but it shouldn’t be that hard to find ;-)
This will generate a filed called
.env.enc.txt you will need it on the next step.
Finally! we just have a couple missing parts and we are done! promised!
Create a file called
.cloudbuild.yml in the root of the project and paste the following:
steps: - name: 'gcr.io/$PROJECT_ID/firebase' args: [ 'use', '$_PROJECT_NAME'] secretEnv: ['FIREBASE_TOKEN'] - name: 'gcr.io/cloud-builders/npm' dir: 'functions' args: ['install'] - name: 'gcr.io/$PROJECT_ID/firebase' args: [ 'deploy', '--only', 'functions'] secretEnv: ['FIREBASE_TOKEN'] secrets: - kmsKeyName: 'projects/YOUR_PROJECT_NAME/locations/global/keyRings/YOUR_RING_NAME/cryptoKeys/YOUR_KEY_NAME' secretEnv: FIREBASE_TOKEN: <YOUR KEY GOES HERE>
kmsKeyName in our sample the value should be:
Adjust your according.
- name: 'gcr.io/cloud-builders/npm' dir: 'functions' args: ['run', 'test']
I’m running an install cause my build process uses typescript and I need the linter to run before.
You can use the same pattern to add more steps and also deploy other services, for example, your firestore security rules:
- name: 'gcr.io/$PROJECT_ID/firebase' args: ['deploy', '--only', 'firestore:rules']
Also, notice how the cloud build substitutions are available here as PROJECTNAME on the first step. Using this pattern you can assemble your own ci process. Just be aware we are using different images per steps.
gcr.io/$PROJECT_ID/firebase which we installed in a previous step.
Lastly Finally! we just need to give cloud build permissions to
decrypt this secrets.
gcloud console top search bar type
IAM & admin find our your list one
Member which looks like
email@example.com and click on the edit button.
Add the role
Cloud KMS CryptoKey Decrypter
Let’s test this, on your terminal type the following command:
gcloud builds submit . --config=cloudbuild.yaml --substitutions=_PROJECT_NAME=my-company-dev
Make sure you change
my-company-dev for your real project name.
If everything went good you will see something like (beside the logs) on your cloud build console.
Now commit your project to github and after you merge stuff into master or staging it would deploy your respective projects :)
I hope you like this! It took me several hours and frustration to find the right approach that works easy enough for me and my team. I hope you can get the most of it with all the pain.
Now you have to another tool under your belt to avoid bugs in prod ;-).
You can check the working repo here.