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

Firebase emulator does not pick up environment variables even though it reports they have been loaded (Follow-up for #5219) #5669

Closed
sceee opened this issue Apr 7, 2023 · 12 comments

Comments

@sceee
Copy link
Contributor

sceee commented Apr 7, 2023

[REQUIRED] Environment info

firebase-tools: 11.25.3

Platform: Windows

[REQUIRED] Test case

See #5219 (comment)

[REQUIRED] Steps to reproduce

The following issue was closed but the behavior described in #5219 (comment) still occurs and the environment variables are not loaded.

[REQUIRED] Expected behavior

Firebase emulator does pick up the environment variables from the .env files correctly.

[REQUIRED] Actual behavior

#5219 (comment)

@Jasonkoolman
Copy link

Jasonkoolman commented Apr 7, 2023

Same issue here on pretty much a fresh install:

image

Using the latest versions:
firebase-tools@11.25.3
firebase-functions@4.2.1

@starlight-akouri
Copy link

I am experiencing the same exact issues as described above. I am totally new to firebase/functions so I wasn't sure if I was doing something wrong, but I've now invested a couple of hours into this, and it's looking like this has been an issue for over a year. I think I may seek to use another library.

@taeold taeold assigned taeold and colerogers and unassigned Berlioz and taeold May 5, 2023
@colerogers
Copy link
Contributor

Hi @sceee sorry it's taken so long for us to respond, thanks for your patience. So I read the closed thread with your comments about the setup that you have and I'm unable to reproduce the bug on my end. Here's what my setup looks like: (maybe you can spot something that you are doing differently)

firebase-functions: v4.4.0
firebase-tools: v11.30.0

.env:

.env-local:

FUNCTIONS_EMULATOR=true

enviroment.ts:

import { defineBoolean } from "firebase-functions/params";

const environmentVariable_FunctionsEmulator = defineBoolean('FUNCTIONS_EMULATOR')

export function isRunningInEmulator(): boolean {
  console.log(`Process env: ${process.env.FUNCTIONS_EMULATOR}`)
  console.log(`defineBoolean: ${environmentVariable_FunctionsEmulator.value()}`)
  return environmentVariable_FunctionsEmulator.value() === true
}

index.ts:

import * as v2 from "firebase-functions/v2";
import * as environment from "./environment";

export const myfunc = v2.https.onRequest((request, response) => {
  console.log(`Running Emulator: ${environment.isRunningInEmulator()}`);
  response.send();
});

my-test.sh:

curl http://127.0.0.1:5001/$PROJECT/us-central1/myfunc

Then I'm running firebase emulators:exec "./my-test.sh" --only functions and it's correctly picking up the .envs with this as the result:

>  Process env: true
>  defineBoolean: true
>  Running Emulator: true

@colerogers colerogers added the Needs: Author Feedback Issues awaiting author feedback label May 9, 2023
@sceee
Copy link
Contributor Author

sceee commented May 9, 2023

Hi @colerogers , thanks for your reply.
One immediate difference I spotted is that you are using v2 functions while I am using v1 functions (can't upgrade due to v2's current limitations).
Also I am using v1 callable cloud functions instead of regular http functions for most functions.

Maybe the difference between using v1 vs. v2 functions could be the issue? Are the environment variables maybe only supported with v2 functions and not with v1 functions?

@google-oss-bot google-oss-bot added Needs: Attention and removed Needs: Author Feedback Issues awaiting author feedback labels May 9, 2023
@colerogers
Copy link
Contributor

@sceee I just tried using a v1 function and I'm still able to correctly obtain the environment variable. Are you using a monorepo setup?

@colerogers colerogers added Needs: Author Feedback Issues awaiting author feedback and removed Needs: Attention labels May 9, 2023
@sceee
Copy link
Contributor Author

sceee commented May 9, 2023

@colerogers yes, it is a monorepo setup.
I have no idea how to further trace it down why it does not pick up the env variables. Do you have an idea because you asked about the monorepo setup?

@google-oss-bot google-oss-bot added Needs: Attention and removed Needs: Author Feedback Issues awaiting author feedback labels May 9, 2023
@colerogers
Copy link
Contributor

Okay this is making a bit more sense to me. When you invoke the emulator or deployment process, we try to read your .env files using a function called loadUserEnvs(). In the emulator, that functions source string is populated at start time here. My guess right now is that your .env files aren't in the path that the emulator is expecting b/c of how monorepos structure the project. Officially, we don't support monorepo setups, only standard npm workflows (here's the feature request for deployment: #653). What monorepo are you using? Does this only happen in the emulator or in GCP too? Can we try to move the .env files to unblock you?

@colerogers colerogers added Needs: Author Feedback Issues awaiting author feedback and removed Needs: Attention labels May 9, 2023
@sceee
Copy link
Contributor Author

sceee commented May 10, 2023

@colerogers when mentioning that I am using a monorepo setup, I only meant that I use one git repository that contains multiple npm projects in multiple root directories like this:

backend
- functions
- - package.json
- - .env
- - ...
- firebase.json
- ...
client
- package.json
- firebase.json
- ...

The projects itself (e.g. backend) are regular "single" npm projects. So I think it's not the monorepo structure you thought and that is unsupported.

Anyway, I tried to further trace it down by debugging into the code of firebase-tools you mentioned.
This line in functionsEmulator.js in discoverTriggers()
image
correctly contains my environment variables. So userEnvs correctly contains the variables and they could be loaded correctly from the .env files.

But for resolution two lines later
image
it seems the userEnvs are passed into resolveBackend but they end up not being used there.

Is there anything line you can think of that I can further debug to further trace this down?

@google-oss-bot google-oss-bot added Needs: Attention and removed Needs: Author Feedback Issues awaiting author feedback labels May 10, 2023
@colerogers
Copy link
Contributor

Hmm interesting... I think the best path forward is if you could create a minimal reproducible example that I could use to debug on my machine, otherwise we'd just go back-and-forth on this thread. I made https://github.com/colerogers/issue-5669 which works shows true in the output. If you could create something similar that fails for you, that would be great. Thanks

@colerogers colerogers added the Needs: Author Feedback Issues awaiting author feedback label May 11, 2023
@sceee
Copy link
Contributor Author

sceee commented May 13, 2023

@colerogers thanks, I forked your repo here https://github.com/sceee/issue-5669 and made some changes to adjust it to the way my project is structured. By this I can demo the behavior that fails for me. The changes basically are:

  • I converted it to a Typescript project
  • Added an Callable HTTPS function in index.ts
  • Moved the reading of the environment to SystemEnvironment.ts
  • Added a test to functions.spec.ts that is executed using mocha (via firebase emulators:exec) and calls the callable HTTPS function

Running

npm run build
npm run test:execute

inside the functions directory starts the emulator and executes npm test using firebase emulators:exec internally.

The log shows the environment files are loaded but the environment variable FUNCTIONS_EMULATOR is not populated correctly in the function

...
i  functions: Loaded environment variables from .env.default, .env.local.
...
Process env: undefined
defineBoolean: false
Running Emulator: false


    1) execute some test


  0 passing (12ms)
  1 failing

  1)
       execute some test:

      AssertionError: expected false to equal true
      + expected - actual

      -false
      +true

The Process env, defineBoolean, Running Emulator output are from the function's/SystemEnvironment.ts console.log.

Also, the test fails (it just asserts on the return value of the Function that is isInEmulator and should therefore be true as this should be set to true based on the setting in env.local).

I hope this simple repro helps so you might possibly also be able to reproduce the failing behavior?

@google-oss-bot google-oss-bot added Needs: Attention and removed Needs: Author Feedback Issues awaiting author feedback labels May 13, 2023
@colerogers
Copy link
Contributor

@sceee so I believe this setup is actually WAI. Basically, you are just calling the raw imported function as a normal js/ts function from mocha without going through the emulator, so the emulated envs do not exist. If you changed up the function invocation to HTTP (or probably more correct to use the Firebase JS SDK to invoke the callable, not sure if you can do that in mocha), you'd go through the emulator and pickup all the correct runtime properties.

Also, the firebase-functions-test SDK is meant for unit testing your functions. If you wanted to strictly unit test them, a common pattern in mocha is to directly define your env vars in your test suite or pass in a .env file with the -r flag.

Sorry about the headache but I'm gonna mark this as closed. Let me know If you think I made a mistake

@sceee
Copy link
Contributor Author

sceee commented May 15, 2023

@colerogers ah I see.
Actually the usecase is indeed unit testing the functions, therefore firebase-functions-test is used.
My intention is to use the FUNCTIONS_EMULATOR environment variable to "mock out" some calls to external systems in the unit test runs.

Handing over the env variables additionally directly mocha was exactly what I was already doing before trying to migrate to the new params possibility, I just thought this would now become obsolete since the emulators now "natively" support the environment variables but I understand the unit tests do not run "through" the emulator.

So as maybe someone else might benefit from this: I will now try to get it running again for all environments by doing both:

  • Hand over the environment variables as before directly to mocha to provision them for the unit tests (provision the same environment variables as in .env.local directly to mocha)
  • Use the emulator-loaded .env.local for the integration tests' function executions that are executed "through" the emulators by the automated clients (browsers) etc.

This should make it working

  • for the unit tests (via environment variables handed over directly to mocha)
  • as well as the integration tests (environment variables loaded by emulator from .env.local)
  • as well as production (no environment variables loaded from .env.local)

😃

Thanks for your help!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants