37

I'm using Cloud Functions for Firebase with three different projects for development, testing and production purposes. Each project has a service-account.json. When I deploy the sources to an environment, the initialization looks like this:

var serviceAccount = require("./service-account-dev.json");

firebase.initializeApp({
    credential: firebase.credential.cert(serviceAccount),
    databaseURL: "https://nwDEV.firebaseio.com"
});

This is a bit difficult to handle, because I have to change the code everytime I want to deploy to a different environment. Is there a way to have an overall configuration, e.g. in firebase.json or.firebasesrc, which allows to integrate the service-account and decides on deployment which configuration to choose?

Otherwise is there a possibility to detect under which environment the code is running and to load the specific service-account.json and to set the databaseURL-property?

KENdi
  • 7,576
  • 2
  • 16
  • 31
user7930645
  • 371
  • 1
  • 3
  • 3
  • https://firebase.google.com/docs/functions/config-env – camden_kid Apr 27 '17 at 11:10
  • Okay, so there is no built-in alternative to manage different projects than setting an environment property in the CLI? – user7930645 Apr 27 '17 at 16:13
  • If you're deploying to different machines I would have thought you could just use an if-else based on the `window.location`. – camden_kid Apr 27 '17 at 16:20
  • 2
    Is there a reason you need to do service account auth instead of using the built-in auth for the admin SDK? [This snippet](https://firebase.google.com/docs/functions/get-started#import_the_required_modules_and_initialize) shows how to use the Admin SDK to initialize for the *currently deployed project* automatically. If that doesn't work for you, can you clarify in the question why not? – Michael Bleigh Apr 27 '17 at 18:13
  • @camden_kid while deploying firebase tells me that window is not defined. – user7930645 Apr 28 '17 at 10:06
  • 1
    @MichaelBleigh I'm using custom token because we are implementing SMS authentication. – user7930645 Apr 28 '17 at 10:08
  • Sorry, I mean this - http://stackoverflow.com/a/38460544/782358 – camden_kid Apr 28 '17 at 17:40
  • Thanks for the hint. Unfortunately I don't know how to use it, because the initialization is done outside each trigger, there is no request-object. So how do I get the information to pass to that function? – user7930645 Apr 29 '17 at 14:08

3 Answers3

28

You can use environment variables. https://firebase.google.com/docs/functions/config-env

  1. Select the project (you can use the command firebase projects:list to see them): firebase use my-project-development

  2. Set an environment variable firebase functions:config:set app.environment="dev"

  3. In your functions file, apply a conditional to choose the file: const serviceAccount = functions.config().app.environment === 'dev' ? 'credentials-dev.json' : 'credentials-prod.json';

Then you can use the file depending on the project:

firebase.initializeApp({
    credential: firebase.credential.cert(serviceAccount),
    databaseURL: "https://nwDEV.firebaseio.com"
});
Mohsen Esmaeili
  • 368
  • 3
  • 10
Diego
  • 709
  • 7
  • 18
  • If it is node.js project, in most cases it uses `process.env.NODE_ENV == 'production'` But we can't change `process.env` of Firebase server so we have to use `firebase functions:config:set some.key="value"` as Diego's answer. This should be accepted answer. – wonsuc Sep 14 '17 at 20:31
  • 1
    And I prefer to use like this `functions:config:set app.env="dev"` or `functions:config:set app.env="prd"` – wonsuc Sep 14 '17 at 20:43
8

From what I understand of your question, what you are looking for boils down to a solution to translate the cloud functions you are deploying to the appropriate settings, i.e. production, development, and testing, which I assume means each of these is a unique project, and therefore database, in your Firebase environment.

If the above is true then the following should help.

Firebase Cloud Functions, and CLI more generally, is able to deploy to a specific project in your Firebase environment. To do this execute the following command in the terminal while in the cloud functions directory.

    $ firebase use --add

This will allow you to pick your additional project (for instance, development) and assign it an alias (I recommend "development" if it is as such). Then when deploying your functions you can choose which project (and therefore database) to deploy to by using the alias.

    $ firebase use default # sets environment to the default alias
    $ firebase use development # sets environment to the development alias

For more information please see: https://firebase.googleblog.com/2016/07/deploy-to-multiple-environments-with.html

One thing you may have to do for this to work would be to use the default config settings for Cloud Functions.

    $ admin.initializeApp(functions.config().firebase);
bradchattergoon
  • 452
  • 4
  • 14
8

Short answer: the GCLOUD_PROJECT environment variable will be unique to your project, hence you can utilise it like this (sample code is for 2 different projects but you can extend it using switch or any other conditional statement):

const env = process.env.GCLOUD_PROJECT === 'my-app-prod' ? 'prod' : 'dev';

then use that env variable to load intended configuration.

Full example: (TypeScript)

  1. update .firebaserc file

    {
     "projects": {
        "default": "my-app-dev",
        "prod": "my-app-prod",
      }
     }
    
  2. create and modify your ./somewhere/config.ts file accordingly, let's say you're using AWS services (please ensure to secure your configuration details)

    export const config = {
      dev: {
        awsRegion: 'myDevRegion',
        awsAccessKey: 'myDevKey',
        awsSecretKey: 'myDevSecretKey'
      },
      prod: {
        awsRegion: 'myProdRegion',
        awsAccessKey: 'myProdKey',
        awsSecretKey: 'myProdSecretKey'
      }
    };
    
  3. now above items can be used in the index.ts file

    import { config } from './somewhere/config';
    import * as aws  from 'aws-sdk';
    . . .
    const env = process.env.GCLOUD_PROJECT === 'my-app-prod' ? 'prod' : 'dev';
    const awsCredentials = {
        region: config[env].awsRegion,
        accessKeyId: config[env].awsAccessKey,
        secretAccessKey: config[env].awsSecretKey
    };
    aws.config.update(awsCredentials);
    . . . 
    export const myFuncToUseAWS = functions....       
    
  4. Now the deployment

    Dev environment deployment: $ firebase deploy --only functions -P default

    Prod environment deployment: $ firebase deploy --only functions -P prod

p4309027
  • 301
  • 4
  • 5