Configure Firebase project for Continuous Integration builds

TL;DR: If you want to use Continuous Integration without exposing your production
google-services.json
in public Git repository, create new Build Variant and store a dummygoogle-services.json
with fake API credentials.
Firebase (and Google Cloud Services) have become very popular with developers. It’s easy if you only develop your app on local machine, until you use some kind of Continuous Integration service (e.g: Travis CI).
What is google-services.json ?
From the Firebase documents:
Firebase manages all of your API settings and credentials through a single configuration file: google-service.json
In general, it’s safe to check it in to your Git repository. This JSON file does not contain any super-sensitive information (e.g: server API key).

It contains information like: Database URL, Android key, storage bucket,.. These are not secret, but if your Security Rules & API Restrictions are not set up correctly attackers could use them against you.

According to many discussions on StackOverflow/Google+, it makes sense to add it to .gitignore
and not include it in a public Git repo.
Firebase project with Continuous Integration
Because you’ve added google-services.json
to .gitignore
, it will not exist in your Git remote repo. When new CI build triggered, it will be FAILED with an error message like:
“File google-services.json is missing from module root folder. The Google Services Plugin cannot function without it.”
There are some approaches to resolve this:
- Use Travis Encrypting Files to encrypt your production
google-services.json
. - Create new Build Variant for your builds on CI service.
- Upload production
google-service.json
, but enable Security Rules & API Restrictions to protect your Firebase/Google Cloud account.
The third approach is not recommended. Many projects — like googlesamples/google-services
— does have it in its .gitignore
. So we will only talk about first two approach.
First approach: Use Travis Encrypting Files
Use this command: travis encrypt-file google-services.json
This will encrypt your file using a symmetric encryption (AES-256) and store the secret in a secure variable (openssl aes-256-cbc
key).
$ travis encrypt-file google-services.jsonencrypting google-services.json for nhoxbypass/travis-encrypt-ex
storing result as google-services.json.enc
storing secure env variables for decryption
Add the secret key to your build script (.travis.yml
), add encrypted google-services.json.enc
to your Git repo. Then Travis CI will be able to decrypt your file when execute build. See documents.
Second approach: Configure Build Variants for CI
Create new Build Variant and store a dummy google-services.json
— with fake API credentials — that will be used for your builds on CI service.
What is Build Variant?
Each Build Variant represents a different version of your app that you can build.
Ex: you might want to build a free
version of your app (with limited features), and another paid
version (with full features).
Build Variants are the result of Gradle using a specific set of rules to combine settings, code, resources configured in your build types and product flavors. You can configure them in app/build.gradle
, inside the android
block:
Create new development Build Variant for CI builds
As I said above, we will create new Build Variants. Let’s call them mock
and prod
(use mock
instead of dev
because we may use it to support mock testing in the future).
Add these build variants by updating buildTypes
& productFlavors
like:
After Gradle synced, create a dummy google-services.json
inside app/src/mock
package:
app/
├── src/
│ ├── main/
│ └── mock/
│ └── google-services.json (dummy)
├── google-services.json
└── build.gradle
Update this file with the fake content below. Remember to replace com.yourapp.packagename
with your app package name.
Now we’ve successfully added new variant with dummy config file.

But how can build tools know where the build being executed — on CI service or just local machine — to select a proper variant?
We specify build parameter -Pbuild
. Update build script in .travis.yml
:
script:
- ./gradlew clean build -Pbuild=devCI
The -Pbuild=devCI
tells build tools to only select & build mock
variant using our dummy app/src/mock/google-services.json
. Trigger CI build again, you will see it PASSED. Everything is done in just a few line of code!
Optimize your build speed
From now on, the project have 4 variants, and the build process seem to be slowed down, you can monitor it with Gradle build scan:

Because command ./gradlew build
will build all variants of your project! To ignore mock
when -Pbuild=devCI
not specified, update app/build.gradle
Why recommended the second approach?
This approach is recommended because sometimes your project use other cloud services (e.g: Facebook login SDK), then you will have other API keys to secure. In this case, you can store these keys in a secrets.xml
, then upload dummy one to Git repo in mock
package:
app/
├── src/
├── main/res/values/secrets.xml
└── main/res/values/secrets.xml (dummy)
Furthermore, this approach is not limited to CI and can be extended for your production build also. Ex: When you require different production google-services.json
or different AndroidManifest.xml
(with some specific properties) for your free
and paid
version of your app.
But, what about UI testing on CI?
Yes, this solution has one drawback. Because we use dummy config files with fake API credentials, so when deploy the app into emulators for automation UI testing, it will not work properly and the test will FAILED.
In that case you can use middleware to mount these config files on CI service. Or just generate another google-services.json
file for mock
variant. This is a real config file from Firebase, but you only use for CI building and testing. You can disable it anytime without affecting your production app.

In conclusion
When working with Firebase (and Google Cloud Services), you might want to trigger build on Continuous Integration service without exposing your production google-services.json
in public Git repository. In that case the build will FAILED.
To resolve this issue, use Travis Encrypting Files to encrypt it. Or create new Build Variant and store a dummy google-services.json
— with fake API credentials — that will be used for your builds on CI service.
Happy coding~