firebase / firebase-tools

The Firebase Command Line Tools
MIT License
4.01k stars 929 forks source link

firebase-functions do not deploy on node 10 if the source directory is named "firebase" #2473

Open jbreckel opened 4 years ago

jbreckel commented 4 years ago

Related issues

[REQUIRED] Version info

node: 10.21.0

firebase-functions: 3.6.1

firebase-tools: 8.5.0

firebase-admin: 8.10.0

[REQUIRED] Test case

setting functions.source in firebase.json keeps the functions from being deployed. Having the functions in the functions directory and no custom source folder defined, everything deploys like it should.

Repo with mcve: https://github.com/jbreckel/firebase-functions-source-repro

[REQUIRED] Steps to reproduce

  1. clone repo (it's a blank typescript project from firebase init)
  2. run firebase deploy --only functions

[REQUIRED] Expected behavior

firebase reads the functions.source setting from firebase.json and uploads the functions in that folder.

e.g:

$ firebase deploy --only functions

=== Deploying to 'project-id'...

i  deploying functions
<!-- yarn build in here -->
✔  functions: Finished running predeploy script.
i  functions: ensuring required API cloudfunctions.googleapis.com is enabled...
i  functions: ensuring required API cloudbuild.googleapis.com is enabled...
✔  functions: required API cloudbuild.googleapis.com is enabled
✔  functions: required API cloudfunctions.googleapis.com is enabled
i  functions: preparing functions directory for uploading...
i  functions: packaged functions (41.99 KB) for uploading
✔  functions: functions folder uploaded successfully
i  functions: creating Node.js 10 function helloWorld(us-central1)...
✔  functions[helloWorld(us-central1)]: Successful create operation.
Function URL (helloWorld): https://us-central1-project-id.cloudfunctions.net/helloWorld

✔  Deploy complete!

[REQUIRED] Actual behavior

firebase does not find any functions to upload

$ firebase deploy --only functions

=== Deploying to 'project-id'...

i  deploying functions
<!-- yarn build in here -->
✔  functions: Finished running predeploy script.
i  functions: ensuring required API cloudfunctions.googleapis.com is enabled...
i  functions: ensuring required API cloudbuild.googleapis.com is enabled...
✔  functions: required API cloudbuild.googleapis.com is enabled
✔  functions: required API cloudfunctions.googleapis.com is enabled
i  functions: preparing firebase directory for uploading...

✔  Deploy complete!

Project Console: https://console.firebase.google.com/project/project-id/overview

Were you able to successfully deploy your functions?

no error, just no functions found

google-oss-bot commented 4 years ago

I couldn't figure out how to label this issue, so I've labeled it for a human to triage. Hang tight.

samtstern commented 4 years ago

@jbreckel I was not able to reproduce this with the following setup:

file structure:

$ ls
firebase.json  mysrc/

firebase.json

{
  "functions": {
    "source": "mysrc"
  }
}

Here's the result of my deploy:

$ firebase deploy --only functions

=== Deploying to 'fir-dumpster'...

i  deploying functions
i  functions: ensuring required API cloudfunctions.googleapis.com is enabled...
i  functions: ensuring required API cloudbuild.googleapis.com is enabled...
✔  functions: required API cloudfunctions.googleapis.com is enabled
✔  functions: required API cloudbuild.googleapis.com is enabled
i  functions: preparing mysrc directory for uploading...
i  functions: packaged mysrc (27.45 KB) for uploading
✔  functions: mysrc folder uploaded successfully
i  functions: updating Node.js 10 function helloWorld(us-central1)...
✔  functions[helloWorld(us-central1)]: Successful update operation. 

✔  Deploy complete!

Project Console: https://console.firebase.google.com/project/fir-dumpster/overview

I notice this line in your logs:

i  functions: preparing firebase directory for uploading...

Just to make sure: do you have a firebase directory in the same parent directory as your firebase.json file and does firebase/package.json have a main entry which points to the file with your functions exports?

jbreckel commented 4 years ago

that is very weird.

As you can see in the repo I linked above, the firebase directory exists. the predeploy hook is working and building firebase/lib/index.js which is in turn the value of main in the package.json. it seems like it knows about the directory, it executes the predeploy hook with the correct value for RESOURCE_DIR, and it even says it prepares the upload as you saw in the log: functions: preparing firebase directory for uploading...

but after that, it just stops doing what it should and tells me the deployment is complete.

jbreckel commented 4 years ago

I found it working when the source directory is not named firebase. if I name the custom directory something else it is working...

so maybe that is the problem, which is weird as it is working with node 8

jbreckel commented 4 years ago
i  deploying functions
i  functions: ensuring required API cloudfunctions.googleapis.com is enabled...
i  functions: ensuring required API cloudbuild.googleapis.com is enabled...
✔  functions: required API cloudbuild.googleapis.com is enabled
✔  functions: required API cloudfunctions.googleapis.com is enabled
i  functions: preparing my-custom-functions directory for uploading...
i  functions: packaged my-custom-functions (39.42 KB) for uploading
✔  functions: my-custom-functions folder uploaded successfully
i  functions: creating Node.js 10 function helloWorld(us-central1)...
samtstern commented 4 years ago

That is really strange ... @mbleigh @laurenzlong do you know if there's anything special about the firebase path name?

laurenzlong commented 4 years ago

This is weird indeed and does seem to be a bug, I revised the description to be more clear.

taeold commented 1 year ago

2022 Update: Turns out that this is because require will prefers loading .json files when there is both firebase.json and ./firebase (a directory). Per package resolution algorithm

require(X) from module at path Y
1. If X is a core module,
   a. return the core module
   b. STOP
2. If X begins with '/'
   a. set Y to be the filesystem root
3. If X begins with './' or '/' or '../'
   a. LOAD_AS_FILE(Y + X)
   b. LOAD_AS_DIRECTORY(Y + X)
   c. THROW "not found"
4. If X begins with '#'
   a. LOAD_PACKAGE_IMPORTS(X, dirname(Y))
5. LOAD_PACKAGE_SELF(X, dirname(Y))
6. LOAD_NODE_MODULES(X, dirname(Y))
7. THROW "not found"

LOAD_NODE_MODULES(X, START)
1. let DIRS = NODE_MODULES_PATHS(START)
2. for each DIR in DIRS:
   a. LOAD_PACKAGE_EXPORTS(X, DIR)
   b. LOAD_AS_FILE(DIR/X)
   c. LOAD_AS_DIRECTORY(DIR/X)

Note that LOAD_AS_FILE takes precedence over LOAD_AS_DIRECTORY. That means that when you have both firebase.json and firebase/, and when the Firebase CLI imports the function source via require("./firebase"), the CLI will import the .json file which, of course, won't have any function definitions.

I think the best we can do here is to document that you cannot name your function source as "firebase" while also having a firebase.json file at the parent. Since most firebase projects will have firebase.json at the parent directory, this mostly means that using firebase as folder name isn't possible.

Will suggest we change the requirement of this issue to be

1) Update public documentation to indicate this limitation 2) Improve CLI to detect and show helpful error message on why firebase as a directory is not allowed