Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Accept JSON file for functions:config:set #406

Closed
jpreynat opened this issue Jul 20, 2017 · 53 comments
Closed

Accept JSON file for functions:config:set #406

jpreynat opened this issue Jul 20, 2017 · 53 comments

Comments

@jpreynat
Copy link
Contributor

Currently, it is possible to get the whole functions config as a JSON file using firebase functions:config:get, but we have to manually inline each variable when using the firebase functions:config:set command, which makes it practically unusable when working on different environments.

Ideally, we should be able to do:

firebase functions:config:get > config.json
firebase functions:config:set -f config.json
@ahaverty
Copy link

I agree with @jpreynat, we're dreading the day we forget to set a config var before deploying to our production. Tying config:set into our custom deploy scripts with a config.json would be a nice feature to see added.
Are there any workarounds right now, maybe piping in the config?

@laurenzlong
Copy link
Contributor

Seems like you're trying to replicate config across projects. Would firebase functions:config:clone work for you?

@mbleigh
Copy link
Contributor

mbleigh commented Jul 20, 2017

To give some context, we've intentionally leaned away from file-based config because we think it encourages bad practices (namely, keeping a file full of secrets stored with your code, potentially even checked into your source repository).

What would you think about some way (mechanics TBD) to declare "required" config variables -- and if you tried to deploy without required config in the current project it would error out before anything was changed. Would that solve your main concerns? If not, why is having a file specifically useful to you?

@ahaverty
Copy link

ahaverty commented Jul 20, 2017

@mbleigh That's exactly what I didn't know I wanted. Nice idea!
Probably a given/what you meant by 'Mechanics TBD', but: Defining the keys/config structure in some file within our project rather than remotely, so that it goes through the git/PR review process like everything else.
@jpreynat Sorry for hijacking issue

@jpreynat
Copy link
Contributor Author

@laurenzlong Thanks for the advice, but we are not trying to duplicate a config.
Our main concern is to update different projects configuration depending on our deployment stage.
So basically, we have a config file per environment (dev, staging and prod), and set the Firebase config respectively (for PRs, push on master and tags).

@mbleigh Thanks for the information.
However, we aren't exactly sure how we can store all these envs another way than using config files.
They are currently formatted as JSON for reading simplicity, but we are thinking of formatting them as key/value pairs to pass them directly to the functions:config:set command.
I'll agree with you that this is no more secure than passing a JSON file.
Do you have any recommendations on how we could store our environment variables for different stages other than using files?

@ahaverty No worries, I'm glad that this can be debated here.

@mbleigh
Copy link
Contributor

mbleigh commented Jul 27, 2017

@jpreynat when you run functions:config:set it is stored with the current project. If you're using firebase use to switch between projects, your config will be persistent. So you can run set once per project and then it will always be there. This should solve the "different config for different environments" issue, so maybe I'm not understanding the real probleM?

@laurenzlong
Copy link
Contributor

@jpreynat I'm going to close this issue for now, but please re-open if Michael and I have misunderstood your request.

@jpreynat
Copy link
Contributor Author

jpreynat commented Aug 9, 2017

@laurenzlong @mbleigh Sorry that I didn't answer quickly on this thread.
We found a workaround for this issue for now, but here is some context to clarify my request:

We are deploying our app using Travis (note that this would be great with any CI or even locally). Since we deploy our app to different stages depending on the branch and tag, it would be great to be able to use a different JSON file based on the environment.
For instance, this would allow to do either firebase config:set -f staging.json or firebase config:set -f prod.json depending on this condition.
Our workaround was to use firebase as a node module, but we still have to inline our JSON configuration, which is prone to errors.

@laurenzlong
Copy link
Contributor

Hey @jpreynat I'm still a bit confused by your answer. Once you set the config once, it always stays there, even across deployments, unless you explicty unset the config values by running firebase functions:config:unset. So there's no need to have this as part of the CI process.

@bobrosoft
Copy link

Can somebody reopen this? %) @jpreynat @mbleigh That's really one of the things which is missing. Atm I have near 15 config variables (and more coming) and that will be very handy if functions:config:set can accept JSON in some way.

@ahaverty
Copy link

ahaverty commented Nov 9, 2017

Big vote from us for @mbleigh suggestion on "declare "required" config variables -- and if you tried to deploy without required config in the current project it would error out before anything was changed."
Becoming a pain point for us too, but that would solve all our issues and would fit nicely into the version control/review process 👍

@laurenzlong
Copy link
Contributor

Hey @yaronyosef You can directly supply JSON to the firebase functions:config:set command, it's just that you have to format it in a way that's appropriate for your platform. For Linux, the following should work:

firebase functions:config:set foo='{"bar":"something","faz":"other"}'

@kanemotos
Copy link

kanemotos commented Dec 20, 2017

Thank you for your sharing! @laurenzlong
I wanted to import from a file, so I used command like this.

firebase functions:config:set service_account="$(cat service-account.json)"

I imported a service account json file to Firebase Cloud Functions, because I wanted to use the user management API of Firebase Admin SDK.

@laurenzlong
Copy link
Contributor

Cool use case! Thanks for sharing!

@dinvlad
Copy link

dinvlad commented Feb 22, 2018

We would also prefer tracking non-secret configs through Git, where the committed JSON runtime config files (for multiple environments) will be authoritative and the CI environment would then apply functions:config:set from the file corresponding to a particular environment (and each environment corresponds to a separate Firebase project).

@mbleigh
Copy link
Contributor

mbleigh commented Feb 22, 2018

If you keep configs in git, it's trivial to read them into your functions runtime. Just put them at configs/<project_id>.json and then:

let config = {};
try {
  config = require(`./configs/${process.env.GCLOUD_PROJECT}.json`);
} catch (e) {
  console.log('No config found for project', process.env.GCLOUD_PROJECT);
}

The runtime config used by Firebase is specifically designed to avoid having config checked into git, as (especially with secrets) we've found it to be a pattern that causes more problems than it solves.

@dinvlad
Copy link

dinvlad commented Feb 22, 2018

That's true, although then we no longer use Config API for this purpose at all. It may be beneficial to still go through Config API for storing sensitive values (which seems to be an appropriate use case, based on Firebase docs) and load both source-controlled and untracked values in the same exact way (i.e. through config() provided by firebase-functions).

For the time being, I'm using the following one-liner to feed the entire .runtimeconfig to functions:config:set:

firebase functions:config:set $(jq -r 'to_entries[] | [.key, (.value | tojson)] | join("=")' < .runtimeconfig/${FIREBASE_ENV}.json)

where FIREBASE_ENV is the name of the environment used in deployment (e.g. dev). It would be nice to be able to shorten this further, e.g.

firebase functions:config:set -f .runtimeconfig/${FIREBASE_ENV}.json

Ultimately though, even that may not be necessary if Config API enabled simple-to-use audit trails of all changes (please correct me if that's already the case, I'd like to explore that).

@vongohren
Copy link

So how is this coming along? 😄

@ahaverty
Copy link

Would love to see @mbleigh suggestion be implemented still! We're constantly having issues forgetting to set configs on our non-dev targets

@mbleigh
Copy link
Contributor

mbleigh commented Jul 11, 2018

Thanks for the thread bump. Nothing to report yet, but I'll bring this up again in our planning meetings to see if we can start to make some progress on it.

@hgwood
Copy link

hgwood commented Jul 25, 2018

I validate my config with a JSON schema file to ensure it has all the values I expect. This validation is part of my CI pipeline and prevents deployment if it fails. If like me you use TypeScript to write your functions, you may generate the JSON schema from your types.

It works great, with the limitation that the functions config only accepts strings, so the schema cannot validate that a config value is a number. For booleans it's OK because I can use an enum with "true" and "false" as the only valid values.

See my CircleCI config and this blog post for reference.

@ahaverty
Copy link

@hgwood thanks for sharing! We will definitely be adding this to our CI too.

@ATXMJ
Copy link

ATXMJ commented Oct 26, 2018

Just wanted to leave my solution to this "problem", and my thoughts on the discussion:

  1. I understand that secret/sensitive values should NOT be stored in the repo. My solution is only for non-secret values. Secret values are set manually, but a way to mark config values as required would be wonderful for those secret values.
  2. I think this is more important than some seem to think. It's a PITA to have to manually set individual configuration values for different deployment environment projects, and not be able to simultaneously view/compare them easily. Defining configurations in files makes the process a LOT less of a hassle.
  3. I think adding a functions config editor to the web console would improve this a lot, but it would be really nice if there was a way to simultaneously view configurations for multiple projects, so you could easily compare configurations for different deployment environments.
  4. I have been saying forever that firebase needs to allow environments to be defined within a single project, so you don't need multiple projects to use as deployment environments. If this existed, it'd be very easy to simultaneously view configurations for multiple environments within a single project.
  5. My solution probably has issues, don't trust my code verbatim, but I do like the general concept.

My solution

I use cascading yaml configuration files, which is useful for default values and values that apply to all configurations regardless of deployment environment.

./config/default.yml

app:
  name: My App
featureFlags:
  someFeature:
    enabled: false

./config/dev.yml (similar config files for other deployment environments)

imports:
  - {resource: default.yml}
app:
  environmentName: Development
services:
  someOtherService:
    baseUrl: https://dev.someotherservice.com/api
featureFlags:
  someFeature:
    enabled: true

Then, I've written a small node script that loads the resolved configuration, and returns a space-delimited list of key=val pairs

yaml_to_keyval.ts

import * as configYaml from "config-yaml"
import * as flat from "flat"


const yamlFile = process.argv[2]
const config = configYaml(yamlFile)
const flatConfig = flat(config)

const key_val_list = Object.keys(flatConfig).map(function(key){
    return `${key}=${flatConfig[key]}`
})

console.log(key_val_list.join(' '))

During CI deployment, I use this bash shell script to obtain the key=val pairs and set them with functions:config:set

# env is set to the desired deployment environment (eg "dev"), which is passed as an argument to the CI script command
config_in="$(readlink -f ./config/$env.yml)"
key_vals="$(ts-node ./scripts/node/yaml_to_keyval.ts $config_in)"
firebase functions:config:set $key_vals

@mqln
Copy link

mqln commented Dec 6, 2018

@kanemotos I like your cat solution, but did you not encounter a Precondition check failed error when trying to upload your cert file?

@dinvlad
Copy link

dinvlad commented Dec 7, 2018

We ended up using Deployment Manager for these reasons.

We set all configuration through "config Yaml" for DM. Then DM creates appropriate Runtime Configs and Variables, and firebase deploy retrieves and sets their values at deploy time without having to use firebase config:set at all. This also allows us to set up other resources (e.g. buckets and their access control) and set their values in RC without having to supply them externally to the template. Additionally, this allows us to use camelCase config and variable names.

The only time we set a value externally is when we need to pass an (encrypted) service account key through runtime config, because DM cannot encrypt values securely. But we still use gcloud beta runtime-config configs variables set for that (after the DM deployment and prior to firebase deploy) and not firebase config:set, because the former accepts stdout from KMS.

@george43g
Copy link

george43g commented Jan 5, 2019

I just wanted to add - reading through this it seems that some people missed a crucial point that leads to some confusion. It would be really useful if this was cleared up in the documentation too.

Basically, the functions.config() persists in between deployments, but can ALSO be set separately between different firebase projects!

This means that for dev, staging and prod environments, you must set up multiple identical firebase projects (rather than using multi-site hosting, or deploying to the SAME project... 👎 ) which each persistently hold their own - different - environment variables.

Once you've set aliases (or just switched between projects with firebase use) you can deploy the same repo to multiple, separate firebase projects. This is how you set up a dev environment, staging, and production - as separate firebase projects.

Then, you can set separate environment configurations for each, like this:
firebase -P dev config:set - set variables for your development env
firebase -P prod config:set - set variables for your production env...

Then, you can deploy the same repo twice, like so:
firebase deploy -P dev
firebase deploy -P prod
and they will both deploy, to their respective firebase project, and will contain their own, separate environment configuration that will persist in-between deploys.

@dinvlad
Copy link

dinvlad commented Jan 7, 2019

Yep, that's how we do it too. Separate projects for dev/test/prod.

@denkan
Copy link

denkan commented Dec 21, 2019

Just sharing my vanilla JS solution which works regarding which platform you develop on (Windows, MacOS, Linux) :

Using separate projects for dev/test/prod.

/.firebaserc

{
  "projects": {
    "dev": "my-project-name-dev",
    "test": "my-project-name-test",
    "prod": "my-project-name-prod"
  }
}

Config files

JSON-files in /functions/config folder:

/functions/config/config.dev.json 
/functions/config/config.test.json 
/functions/config/config.prod.json 
/functions/config/config.SAMPLE.json <-- only file tracked in git

Example content:
{
    "google": {
        "key": "my-api-key",
        "storage_bucket": "firebase-storage-bucket"
    },
    "another_vendor": {
        "my_prop": "my value"
    },
    ...
}

/functions/set-config.js

const fs = require('fs');
const env = process.argv[2];

const configPath = `./config/config.${env}.json`;

if (!(configPath && fs.existsSync(configPath))) {
    return;
}

const collectConfigLines = (o, propPath, configLines) => {
    propPath = propPath || '';
    configLines = configLines || [];
    for (const key of Object.keys(o)) {
        const newPropPath = propPath + key;
        if (typeof o[key] === 'object') {
            collectConfigLines(o[key], newPropPath + '.', configLines);
        } else if (o[key] != null && o[key] !== '') {
            configLines.push(`${newPropPath}=${JSON.stringify(o[key])}`);
        }
    }
}

const config = require(configPath);
const configLines = [];
collectConfigLines(config, '', configLines);

const cp = require('child_process');
cp.execSync(`firebase -P ${env} functions:config:set ${configLines.join(' ')}`);

/functions/package.json

...
"scripts": {
    "config:set:dev": "node set-config dev",
    "config:set:test": "node set-config test",
    "config:set:prod": "node set-config prod",
    ...
},
...

@baasbank
Copy link

If anyone is still looking, there's the method used in this medium article https://medium.com/indielayer/deploying-environment-variables-with-firebase-cloud-functions-680779413484. Saved my life.

@bezysoftware
Copy link

bezysoftware commented Feb 29, 2020

What I am personally missing is the ability to set a config variable without doing a deploy. We have CICD pipeline which does deployment to our different environments and we don't want a developer to build the code locally and deploy it, especially not to production. That's how things break.

Also if we want to change an existing variable later, with some feature being developed, right now you have checkout the last released tag, build it, deploy, checkout back to your feature branch, continue. That really makes this unusable.

Essentially we would want remote config for cloud functions

@serweb-labs
Copy link

@bezysoftware I think you need to use environment variables (instead of enviroment configuration), you can skip the firebase layer and do it on google cloud platform, check it out https://cloud.google.com/functions/docs/env-var

@md-abdul-halim-rafi
Copy link

Thank you for your sharing! @laurenzlong
I wanted to import from a file, so I used command like this.

firebase functions:config:set service_account="$(cat service-account.json)"

I imported a service account json file to Firebase Cloud Functions, because I wanted to use the user management API of Firebase Admin SDK.

It didn't work

@dnhyde
Copy link

dnhyde commented May 15, 2020

@md-abdul-halim-rafi

firebase functions:config:set service_account="$(cat service-account.json)"

Worked for me, I can see the config var with firebase functions:config:get.
It did not work the first time because I was not in the project folder and did not select the firebase project on which to set the config variable, to select the firebase project use firebase use --add, the CLI will prompt you with the list of projects on your firebase console (assuming you are logged in the CLI with firebase login)

@alekseykarpenko
Copy link

@dnhyde

firebase functions:config:set service_account="$(cat service-account.json)"

Seems this will not work while using in your json file any other value types except strings (e.g. boolean or number):

{
   "test": {
        "hmm": true
    }
}

fails with:

Error: HTTP Error: 400, Invalid value at 'variable.text' (TYPE_STRING), true

@rgant
Copy link

rgant commented Jul 1, 2020

It seems reasonable to me that I should be able to do:

firebase functions:config:get > config.json

and then later:

firebase functions:config:set < config.json

It just makes sense to have these two commands be complementary.

Having the config in a file allows for me to version control it and see how it has changed over time.

It's unfortunate that the only way we have to accomplish this right now (using env=$(cat config.json)) also results in breaking my ability to have config.json be the actual values since I cannot wrap them in { env: ... }.

Note for myself: this is where I need to start for a feature pull request:

exports.parseSetArgs = function(args) {

@sloosh
Copy link

sloosh commented Oct 29, 2020

Just sharing my vanilla JS solution which works regarding which platform you develop on (Windows, MacOS, Linux) :

Using separate projects for dev/test/prod.

/.firebaserc

{
  "projects": {
    "dev": "my-project-name-dev",
    "test": "my-project-name-test",
    "prod": "my-project-name-prod"
  }
}

Config files

JSON-files in /functions/config folder:

/functions/config/config.dev.json 
/functions/config/config.test.json 
/functions/config/config.prod.json 
/functions/config/config.SAMPLE.json <-- only file tracked in git

Example content:
{
    "google": {
        "key": "my-api-key",
        "storage_bucket": "firebase-storage-bucket"
    },
    "another_vendor": {
        "my_prop": "my value"
    },
    ...
}

/functions/set-config.js

const fs = require('fs');
const env = process.argv[2];

const configPath = `./config/config.${env}.json`;

if (!(configPath && fs.existsSync(configPath))) {
    return;
}

const collectConfigLines = (o, propPath, configLines) => {
    propPath = propPath || '';
    configLines = configLines || [];
    for (const key of Object.keys(o)) {
        const newPropPath = propPath + key;
        if (typeof o[key] === 'object') {
            collectConfigLines(o[key], newPropPath + '.', configLines);
        } else if (o[key] != null && o[key] !== '') {
            configLines.push(`${newPropPath}=${JSON.stringify(o[key])}`);
        }
    }
}

const config = require(configPath);
const configLines = [];
collectConfigLines(config, '', configLines);

const cp = require('child_process');
cp.execSync(`firebase -P ${env} functions:config:set ${configLines.join(' ')}`);

/functions/package.json

...
"scripts": {
    "config:set:dev": "node set-config dev",
    "config:set:test": "node set-config test",
    "config:set:prod": "node set-config prod",
    ...
},
...

Just sharing my vanilla JS solution which works regarding which platform you develop on (Windows, MacOS, Linux) :

Using separate projects for dev/test/prod.

/.firebaserc

{
  "projects": {
    "dev": "my-project-name-dev",
    "test": "my-project-name-test",
    "prod": "my-project-name-prod"
  }
}

Config files

JSON-files in /functions/config folder:

/functions/config/config.dev.json 
/functions/config/config.test.json 
/functions/config/config.prod.json 
/functions/config/config.SAMPLE.json <-- only file tracked in git

Example content:
{
    "google": {
        "key": "my-api-key",
        "storage_bucket": "firebase-storage-bucket"
    },
    "another_vendor": {
        "my_prop": "my value"
    },
    ...
}

/functions/set-config.js

const fs = require('fs');
const env = process.argv[2];

const configPath = `./config/config.${env}.json`;

if (!(configPath && fs.existsSync(configPath))) {
    return;
}

const collectConfigLines = (o, propPath, configLines) => {
    propPath = propPath || '';
    configLines = configLines || [];
    for (const key of Object.keys(o)) {
        const newPropPath = propPath + key;
        if (typeof o[key] === 'object') {
            collectConfigLines(o[key], newPropPath + '.', configLines);
        } else if (o[key] != null && o[key] !== '') {
            configLines.push(`${newPropPath}=${JSON.stringify(o[key])}`);
        }
    }
}

const config = require(configPath);
const configLines = [];
collectConfigLines(config, '', configLines);

const cp = require('child_process');
cp.execSync(`firebase -P ${env} functions:config:set ${configLines.join(' ')}`);

/functions/package.json

...
"scripts": {
    "config:set:dev": "node set-config dev",
    "config:set:test": "node set-config test",
    "config:set:prod": "node set-config prod",
    ...
},
...

Sorry but when do you run the script "config:set:dev" ? I don't get it... thanks !

@raseminiano00
Copy link

I'm getting an error on when running this firebase CI command
firebase functions:config:set foo='{"bar":"something","faz":"other"}'

The error was
Error: Invalid argument, each config value must have a 2-part key (e.g. foo.bar).

@denkan
Copy link

denkan commented Dec 18, 2020

@sloosh

Sorry but when do you run the script "config:set:dev" ? I don't get it... thanks !

For example, in one simpler project I deploy changes to Firebase manually (to a project for dev environment) and I have following in package.json:

"scripts": {
    "config:set:dev": "node set-config dev",
    "config:set:prod": "node set-config prod",
    "config:get": "firebase functions:config:get > .runtimeconfig.json",
    "serve": "npm run config:get && npm run build && firebase serve --only functions,hosting,storage",
    "watch": "nodemon --exec \"npm run build\"",
    "deploy:dev:functions": "npm run config:set:dev && firebase -P dev deploy --only functions",
    "deploy:dev:hosting": "firebase -P dev deploy --only hosting",
    "deploy:dev": "npm run config:set:dev && firebase -P dev deploy --only functions,hosting"
  },

So whenever I want to deploy changes in my functions to my dev project in Firebase, I use:

npm run deploy:dev:functions

The deploy:dev:functions command will first set the variables to the server, using npm run config:set:dev - and then run the deployment (firebase -P dev deploy --only functions).

@denkan
Copy link

denkan commented Dec 18, 2020

@raseminiano00

I'm getting an error on when running this firebase CI command
firebase functions:config:set foo='{"bar":"something","faz":"other"}'

The error was
Error: Invalid argument, each config value must have a 2-part key (e.g. foo.bar).

You need to rewrite the json into single props, as:

firebase functions:config:set foo.bar="something" foo.faz:"other"

@raseminiano00
Copy link

@raseminiano00

I'm getting an error on when running this firebase CI command
firebase functions:config:set foo='{"bar":"something","faz":"other"}'
The error was
Error: Invalid argument, each config value must have a 2-part key (e.g. foo.bar).

You need to rewrite the json into single props, as:

firebase functions:config:set foo.bar="something" foo.faz:"other"

The work around I found on this
firebase functions:config:set foo='{"bar":"something","faz":"other"}'

is
firebase functions:config:set foo.bar='{"faz":"something","qux":"other"}'

is there any way I can set it directly to 'foo'?

@denkan
Copy link

denkan commented Dec 18, 2020

@raseminiano00

firebase functions:config:set foo.bar='{"faz":"something","qux":"other"}'

is there any way I can set it directly to 'foo'?

No.
Not by using the CLI out of the box, afaik.
You need tricks - some specified in this thread.

@rgant
Copy link

rgant commented Dec 18, 2020

Did that change? Because I have been doing this for months:

firebase functions:config:unset env && firebase functions:config:set env="$(cat functions/env.json)"

# env.json
{
  "mailchimp": {
    "api_key": "",
    "audience_id": ""
  },
  "site": {
    "base_url": "",
    "company": ""
  },
  "slack": {
    "webhook_host": "hooks.slack.com",
    "webhook_path": ""
  }
}

# use in functions
  const funcConfig: Config = config().env;
  const mcConfig: MailchimpConfig = funcConfig.mailchimp;

@tonioriol
Copy link

With the help of node, having a json config like this:

//.runtimeconfig.prod.json
{
  "func1": {
    "send_notification": "true",
    "notification_email": "foo@bar"
  "fun2": {
    "client_secret": "asdf",
    "client_id": "sdg"
  }
}
// config.js
const config = require('./.runtimeconfig.prod.json');


const stringifiedConfigsBySection = Object.entries(config).map(([key, value]) => {
  return Object.entries(value).map(([k, v]) => {
    return `${key}.${k}=${v}`;
  }).join(' ');
});

console.log(stringifiedConfigsBySection.join(' '));

Then you can do firebase functions:config:set $(node config.js).

@MorenoMdz
Copy link

Offtopic but related question, can we list/print our ENV variables from the GCP cloud shell?

@morgs32
Copy link

morgs32 commented Nov 16, 2021

@tonioriol happen to know how I could add some parentheses to that value? If I have some all caps in there then the firebase command breaks and if I call the firebase command directly it works.

firebase functions:config:set func1.send_notification="TRUE"

That works ^^^. But not firebase functions:config:set $(node config.js)

//.runtimeconfig.prod.json
{
  "func1": {
    "send_notification": "TRUE",
   }
}

@tonioriol
Copy link

@tonioriol happen to know how I could add some parentheses to that value? If I have some all caps in there then the firebase command breaks and if I call the firebase command directly it works.

firebase functions:config:set func1.send_notification="TRUE"

That works ^^^. But not firebase functions:config:set $(node config.js)

//.runtimeconfig.prod.json
{
  "func1": {
    "send_notification": "TRUE",
   }
}

No sorry, i haven't used that since then.

@dahu33
Copy link

dahu33 commented Dec 10, 2021

Can we reopen this issue please?

@adinvadim
Copy link

I need this feature too. I'am using firebase set in my CD. Get secrets from Github Secrets and push their to the firebase config

@joantune
Copy link

joantune commented Apr 5, 2022

This is ludicrous - we understand and we are grown up enough to just have that file on .gitignore - can you please support this? thanks!

@bswanwick
Copy link

take off the training wheels please

@joehan
Copy link
Contributor

joehan commented May 9, 2022

Hey all! We recently released a support for a new way to configure your functions via .env files that should address the problems raised in this thread. It also includes first class support for secret env variables. Check out https://firebase.google.com/docs/functions/config-env for instructions on how to get started with it.

@johnico
Copy link

johnico commented May 10, 2022

denkan
very nice thanks!
can you add support for arrays and removing item from array?

x:["1","2"]

when i will try to remove the "2" and running the script again nothing will happen

also if prams does not exist , adding an option to remove it

i tried to that by myself did not manage
great job

Just sharing my vanilla JS solution which works regarding which platform you develop on (Windows, MacOS, Linux) :

Using separate projects for dev/test/prod.

/.firebaserc

{
  "projects": {
    "dev": "my-project-name-dev",
    "test": "my-project-name-test",
    "prod": "my-project-name-prod"
  }
}

Config files

JSON-files in /functions/config folder:

/functions/config/config.dev.json 
/functions/config/config.test.json 
/functions/config/config.prod.json 
/functions/config/config.SAMPLE.json <-- only file tracked in git

Example content:
{
    "google": {
        "key": "my-api-key",
        "storage_bucket": "firebase-storage-bucket"
    },
    "another_vendor": {
        "my_prop": "my value"
    },
    ...
}

/functions/set-config.js

const fs = require('fs');
const env = process.argv[2];

const configPath = `./config/config.${env}.json`;

if (!(configPath && fs.existsSync(configPath))) {
    return;
}

const collectConfigLines = (o, propPath, configLines) => {
    propPath = propPath || '';
    configLines = configLines || [];
    for (const key of Object.keys(o)) {
        const newPropPath = propPath + key;
        if (typeof o[key] === 'object') {
            collectConfigLines(o[key], newPropPath + '.', configLines);
        } else if (o[key] != null && o[key] !== '') {
            configLines.push(`${newPropPath}=${JSON.stringify(o[key])}`);
        }
    }
}

const config = require(configPath);
const configLines = [];
collectConfigLines(config, '', configLines);

const cp = require('child_process');
cp.execSync(`firebase -P ${env} functions:config:set ${configLines.join(' ')}`);

/functions/package.json

...
"scripts": {
    "config:set:dev": "node set-config dev",
    "config:set:test": "node set-config test",
    "config:set:prod": "node set-config prod",
    ...
},
...

adrienjoly added a commit to adrienjoly/telegram-scribe-bot that referenced this issue Sep 18, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests