I have a Firebase code project with Functions meant to be deployed to multiple Firebase projects over multiple regions.
I used to set the deployment region like this:
return functions
.region(process.env.REGION)
// ...
and used this command to deploy:
$ REGION=us-central1 firebase deploy --only functions
it worked like a charm until recently. Now it seems to completely ignore REGION=us-central1 even if I export it before I run firebase deploy.
EDIT 2022-06-13 - Possible solution
I changed the code to dump the contents of process.env to a file during deployment. This is what I got:
{
"FIREBASE_CONFIG": "{\"projectId\":\"REDACTED\",\"storageBucket\":\"REDACTED.appspot.com\",\"locationId\":\"us-central\"}",
"GCLOUD_PROJECT": "REDACTED",
"CLOUD_RUNTIME_CONFIG": "{REDACTED}",
"__CF_USER_TEXT_ENCODING": "REDACTED"
}
so definitely is not the same list of variables I have in my local environment.
I could use the locationId from FIREBASE_CONFIG to get the target location, or CLOUD_RUNTIME_CONFIG (it contains the dump of the functions .config() object, so I could set the target there).
I also believe that I could use the .env and .env.{project alias or ID} files and their contents would be available in process.env at deployment time.
As per Osvaldo López's suggestion, here are some other details:
Running on MacOS
No errors are reported
No recent changes to the CLI
Any input would be very welcome! Thanks.
Related
Say I have the following four functions in my Firebase projects:
openDoor(europe-west1)
closeDoor(europe-west1)
openWindow(europe-west1)
closeWindow(europe-west1)
Now, these functions live in two separate Node packages, i.e. one that contains openDoor and closeDoor and another one that contains openWindow and closeWindow.
Error
If I try to run firebase deploy from the package with the door functions, the following error will be thrown (in non-interactive mode):
Error: The following functions are found in your project but do not exist in your local source code:
openWindow(europe-west1)
closeWindow(europe-west1)
This is a problem because it will cancel any CD workflow that tries to deploy these functions.
Force delete
There is an option to force-delete any existing functions:
-f, --force delete Cloud Functions missing from the current
working directory without confirmation
However, I want the opposite. I want to keep all existing functions.
Theoretical workaround
There is one workaround that I found would work in theory, which is:
yes N | firebase deploy --interactive
Piping N into the interactive deploy command, which will answer N to the deletion prompt:
The following functions are found in your project but do not exist in your local source code:
openWindow(europe-west1)
closeWindow(europe-west1)
If you are renaming a function or changing its region, it is recommended that you create the new function first before deleting the old one to prevent event loss. For more info, visit https://firebase.google.com/docs/functions/manage-functions#modify
? Would you like to proceed with deletion? Selecting no will continue the rest of the deployments. (y/N)
The problem now is that I am using https://github.com/w9jds/firebase-action to deploy the functions, which means that I need to have a built-in Firebase solution.
You can make use of the new codebases feature in Firebase.
By specifying a codebase in your firebase.json functions configuration, this problem is solved. The Firebase CLI will no longer prompt you to delete other functions as it only considers the functions of the same codebase.
If your firebase.json previously looked like this:
{
"functions": {
"source": "cloud_functions",
"ignore": [...],
"predeploy": [...],
"postdeploy": [...]
}
}
You only need to add "codebase": "<name>" to the config:
{
"functions": {
"source": "cloud_functions",
"codebase": "window",
"ignore": [...],
"predeploy": [...],
"postdeploy": [...]
}
}
The deploy will now look like this:
i functions: updating Node.js 16 function window:openWindow(europe-west1)...
i functions: updating Node.js 16 function window:closeWindow(europe-west1)...
Note that the actual function name does not change, i.e. the function will still only be called openWindow (without the prefix) in the Firebase / Google Cloud Console. So this is basically the perfect solution to the problem.
Alternatively, you can also specify the function names when performing deployment.
firebase deploy --only functions:openDoor,functions:closeDoor
I followed this doc and added .env file with variables in a Firebase Cloud Function project.
When trying to deploy, I get this message: Loaded environment variables from .env.
However, it is always undefined when I try to use process.env.ENV_VAR. Am I missing something?
I'm using firebase-cli 11.0.1 and firebase-functions 3.21.2
I used env variables for firebase credentials. Seems like it was loaded before env var. So my solution is to use firebase function config
I'm trying to set an environment variable for an API key that I don't want in my code. My source javascript looks something like this :
.get(`http://api-url-and-parameters&api-key=${process.env.API_KEY}`)
I'm using webpack and the package dotenv-webpack https://www.npmjs.com/package/dotenv-webpack to set API_KEY in a gitignored .env file and it's all running fine on my local. I'd like to also be able to set that variable when deploying through Netlify, I've tried adding it through to GUI to the 'build environment variables', and also to set it directly in the build command, but without success.
Any idea what might be the issue ?
WARNING: If this is a secret key, you will not want to expose this environment variable value in any bundle that gets returned to the client. It should only be used by your build scripts to be used to create your content during build.
Issue
dotenv-webpack expects there to be a .env file to load in your variables during the webpack build of your bundle. When the repository is checked out by Netlify, the .env does not exist because for good reason it is in .gitignore.
Solution
Store your API_KEY in the Netlify build environment variables and build the .env using a script prior to running the build command.
scripts/create-env.js
const fs = require('fs')
fs.writeFileSync('./.env', `API_KEY=${process.env.API_KEY}\n`)
Run the script as part of your build
node ./scripts/create-env.js && <your_existing_webpack_build_command>
Caveats & Recommendations
Do not use this method with a public facing repository [open] because any PR or branch deploy could create a simple script into your code to expose the API_KEY
The example script above is for simplicity so, make any script you use be able to error out with a code other than 0 so if the script fails the deploy will fail.
You can set Dotenv-webpack to load system environment variables as well as those you have declared in your .env file by doing the following:
plugins: [
new Dotenv({
systemvars: true
})
]
I.e Setting the systemvars attribute of your webpack dotenv plugin to true.
Note that system environment variables with the same name will overwrite those defined in your .env file.
Source: https://www.npmjs.com/package/dotenv-webpack#properties
if you go to corresponding site's settings in Netlify, under build&deploy you can find a section called environment variables you can easily add your environment variables from there. if you add MY_API_KEY variable to environment variables you will be able to access it inside your project via process.env.MY_API_KEY.
If you're using Nuxt JS there is a more "straight forward" approach.
Just edit the nuxt.config.js like so:
module.exports = {
env: {
GOOGLE_API_KEY: process.env.GOOGLE_API_KEY
},
// ...
Then add the GOOGLE_API_KEY to Netlify through the build environment variables as usual.
Credit goes to yann-linn and his answer on github.
What you can also do is also to define a global constant in Webpack. Netlify environment variables defined in UI will work with it. You don't need dotenv or dotenv-webpack.
webpack.config.js
const webpack = require("webpack");
module.exports = {
plugins: [
new webpack.DefinePlugin({
"process.env.API_KEY": JSON.stringify(process.env.API_KEY)
}),
]
}
However again, of course you shouldn't do it just inputting enviornmental variables in the frontend if your API key is confidential and project public. The API key will appear in the source code of the website and will be easily accessible for everyone visiting it. Lambda function would be a better option.
You can use the Netlify's config file also ...
You can find documentation here.
Also i wanted to have the same ENV variables with with different values per branch/environment.
This workaround worked for me:
Create a netlify.toml file like:
[build]
NUXT_ENV_BASE_API = "/api"
NUXT_ENV_HOST_DOMAIN = "https://your-domain.gr"
[context.branch-deploy]
environment = { NUXT_ENV_BASE_API = "/dev-api", NUXT_ENV_HOST_DOMAIN = "https://dev.your-domain.gr" }
[context.production]
environment = { NUXT_ENV_BASE_API = "/api", NUXT_ENV_HOST_DOMAIN = "https://your-domain.gr" }
And deploy in Netlify ...
irregularly my firebase deployment get stuck at this log:
i functions: updating function [FUNCTION NAME]...
After canceling the deploy and retrying it throws the following error message:
⚠ functions: failed to update function resetBadgeCount
⚠ functions: HTTP Error: 400, An operation on function [FUNCTION NAME]
in region us-central1 in project [PROJECT NAME] is already in progress.
Please try again later.
So it seams like that the deploy got stuck and kept in the pipeline blocking further deploys. After a while it let me deploy the functions normally again.
But is there an explanation for this? Or maybe even a word around?
Go to Google cloud functions console and see if there is red exclamation mark against your function. Then select that particular function and try to delete. once it gets deleted from there, you can deploy again successfully. if it is showing spinner, then wait till it shows red mark.
Try this
You can fix the issue much easier by examining the actual logs using this command to open the log
firebase functions:log
The specific issue will be visible there. I sometimes even had errors as simple as a missing package in package.json
You can temporarily rename your function:
$ firebase deploy --only functions
...
i functions: deleting function onSameDataChanged...
i functions: creating function onSameDataChanged1...
...
✔ functions: all functions deployed successfully!
✔ Deploy complete!
Comment or cut your function
Deploy
Uncomment or paste back the function
Rename the function
Deploy
Rename the function back
Deploy
also you can wait a few minutes and you will get an error with {"code":10,"message":"ABORTED"}, then you can deploy again.
just copy your index.js to some where else and delete function form firebasa function console
firebase init -and overe write all file again
past index.js text again
deploy...
For me it was the node version. Turns out I had the 15.x on my machine and the 12.x on the server. Just updating it solved my upload issue
Make sure you've installed dependencies in the functions directory.
for more information about you function you can go to this page
Set your directory to your project directory \functions then run this command:
npm install -g firebase-tools
In my Meteor (1.2) app I've separated files for development and production
e.g.
client/lib/appVars.config.PROD.js
client/lib/appVars.config.CONFIG.js
Ideally the "twin" files have the same variables, functions etc. with little differences but (global) variables and functions which are common to debug and production have the same name.
Is there a way to call meteor run with a command line parameter DEBUG_MODE = true | false so that I cad load either one or the other file, depending on the current mode (debug, production)?
Set different environmental variables and run via CLI with meteor run --settings settings.json
Then you just need a development and production (and staging?) settings.json
Example of a settings file:
{
"awsBucket": "my-example-staging",
"awsAccessKeyId": "AABBCCddEEff12123131",
"awsSecretKey": "AABBCCddEEff12123131+AABBCCddEEff12123131",
"public": {
"awsBucketUrl": "https://my-meteor-example.s3.amazonaws.com",
"environment": "staging"
},
"googleApiKey": "AABBCCddEEff12123131"
}
EDIT ADD:
To access your environmental keys, just select
Meteor.settings.awsBucket
Security Update (thanks Dave Weldon)
See https://docs.meteor.com/#/full/structuringyourapp
Re production vs development, you should have two settings.json files, the standard one for production (.config/settings.json) and a development one (.config/development/config.json) and when you boot outside of production you boot meteor --settings .config/development/settings.json
Re client side, note that if you make the key public e.g.
{
"service_id":"...",
"service_secret":"...",
"public":{
"service_name":"..."
}
}
Then only Meteor.settings.public.service_name will be accessible on the client