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
Comments
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. |
Seems like you're trying to replicate config across projects. Would |
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? |
@mbleigh That's exactly what I didn't know I wanted. Nice idea! |
@laurenzlong Thanks for the advice, but we are not trying to duplicate a config. @mbleigh Thanks for the information. @ahaverty No worries, I'm glad that this can be debated here. |
@jpreynat when you run |
@jpreynat I'm going to close this issue for now, but please re-open if Michael and I have misunderstood your request. |
@laurenzlong @mbleigh Sorry that I didn't answer quickly on this thread. 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. |
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. |
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." |
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:
|
Thank you for your sharing! @laurenzlong
I imported a service account json file to Firebase Cloud Functions, because I wanted to use the user management API of Firebase Admin SDK. |
Cool use case! Thanks for sharing! |
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 |
If you keep configs in git, it's trivial to read them into your functions runtime. Just put them at 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. |
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 For the time being, I'm using the following one-liner to feed the entire
where
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). |
So how is this coming along? 😄 |
Would love to see @mbleigh suggestion be implemented still! We're constantly having issues forgetting to set configs on our non-dev targets |
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. |
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 See my CircleCI config and this blog post for reference. |
@hgwood thanks for sharing! We will definitely be adding this to our CI too. |
Just wanted to leave my solution to this "problem", and my thoughts on the discussion:
My solutionI 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
./config/dev.yml (similar config files for other deployment environments)
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
During CI deployment, I use this bash shell script to obtain the key=val pairs and set them with functions:config:set
|
@kanemotos I like your |
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 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 |
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 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 Then, you can set separate environment configurations for each, like this: Then, you can deploy the same repo twice, like so: |
Yep, that's how we do it too. Separate projects for dev/test/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 filesJSON-files in
/functions/set-config.jsconst 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
|
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. |
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 |
@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 |
It didn't work |
Worked for me, I can see the config var with |
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:
|
It seems reasonable to me that I should be able to do:
and then later:
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 Note for myself: this is where I need to start for a feature pull request: firebase-tools/src/functionsConfig.js Line 142 in b17611a
|
Sorry but when do you run the script "config:set:dev" ? I don't get it... thanks ! |
I'm getting an error on when running this firebase CI command The error was |
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:
So whenever I want to deploy changes in my functions to my dev project in Firebase, I use: npm run deploy:dev:functions The |
You need to rewrite the json into single props, as:
|
The work around I found on this is is there any way I can set it directly to 'foo'? |
No. |
Did that change? Because I have been doing this for months:
|
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 |
Offtopic but related question, can we list/print our ENV variables from the GCP cloud shell? |
@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.
That works ^^^. But not
|
No sorry, i haven't used that since then. |
Can we reopen this issue please? |
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 |
This is ludicrous - we understand and we are grown up enough to just have that file on .gitignore - can you please support this? thanks! |
take off the training wheels please |
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. |
denkan
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
|
…t key (e.g. foo.bar).` cf firebase/firebase-tools#406 (comment)
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 thefirebase 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
The text was updated successfully, but these errors were encountered: