Firebase-tools: Deploying functions extremely slow

Created on 14 Nov 2017  ·  94Comments  ·  Source: firebase/firebase-tools

Version info

3.15.0

Steps to reproduce

Make a simple functions directory with only 1 function:

const functions = require('firebase-functions');
const admin = require('firebase-admin');

admin.initializeApp(functions.config().firebase);

exports.ping = functions.https.onRequest((req, res) => {
  res.status(200).send('pong');
}

Now deploy using firebase deploy --only functions.

Expected behavior

Deploy faster. Now it takes minutes to deploy a small functions file. If I compare this to the hosting upload/deploy, that one goes pretty fast and is much more then one file.

Actual behavior

Takes extremely long to upload/deploy. It hangs during the preparing functions directory for uploading... phase.

image

Debug log for firebase deploy --only functions:
_please note I used another function then in my reproduce step, but it's the same idea: a small function with only a few lines of code._

> firebase deploy --only functions --debug
[2017-11-14T10:03:55.799Z] ----------------------------------------------------------------------
[2017-11-14T10:03:55.804Z] Command:       C:\Program Files\nodejs\node.exe C:\Program Files\nodejs\node_modules\firebase-tools\bin\firebase deploy --only functions --debug
[2017-11-14T10:03:55.806Z] CLI Version:   3.15.0
[2017-11-14T10:03:55.806Z] Platform:      win32
[2017-11-14T10:03:55.806Z] Node Version:  v6.11.1
[2017-11-14T10:03:55.807Z] Time:          Tue Nov 14 2017 04:03:55 GMT-0600 (Central Standard Time (Mexico))
[2017-11-14T10:03:55.807Z] ----------------------------------------------------------------------

[2017-11-14T10:03:55.826Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
[2017-11-14T10:03:55.827Z] > authorizing via signed-in user
[2017-11-14T10:03:55.831Z] >>> HTTP REQUEST GET https://admin.firebase.com/v1/projects/marktec-itesm
 Tue Nov 14 2017 04:03:55 GMT-0600 (Central Standard Time (Mexico))
[2017-11-14T10:03:56.230Z] <<< HTTP RESPONSE 200 server=nginx, date=Tue, 14 Nov 2017 10:03:57 GMT, content-type=application/json; charset=utf-8, content-length=108, connection=close, x-content-type-options=nosniff, strict-transport-security=max-age=31536000; includeSubdomains, cache-control=no-cache, no-store
[2017-11-14T10:03:56.232Z] >>> HTTP REQUEST GET https://admin.firebase.com/v1/database/marktec-itesm/tokens
 Tue Nov 14 2017 04:03:56 GMT-0600 (Central Standard Time (Mexico))
[2017-11-14T10:03:56.622Z] <<< HTTP RESPONSE 200 server=nginx, date=Tue, 14 Nov 2017 10:03:57 GMT, content-type=application/json; charset=utf-8, content-length=262, connection=close, x-content-type-options=nosniff, strict-transport-security=max-age=31536000; includeSubdomains, cache-control=no-cache, no-store

=== Deploying to 'marktec-itesm'...

i  deploying functions
[2017-11-14T10:03:57.040Z] > [functions] package.json contents: {
  "name": "functions",
  "description": "Cloud Functions for Firebase",
  "scripts": {
    "serve": "firebase serve --only functions",
    "shell": "firebase experimental:functions:shell",
    "start": "npm run shell",
    "deploy": "firebase deploy --only functions",
    "logs": "firebase functions:log"
  },
  "dependencies": {
    "firebase-admin": "~5.4.2",
    "firebase-functions": "^0.7.1"
  },
  "private": true
}
i  functions: ensuring necessary APIs are enabled...
i  runtimeconfig: ensuring necessary APIs are enabled...
[2017-11-14T10:03:57.043Z] >>> HTTP REQUEST GET https://servicemanagement.googleapis.com/v1/services/cloudfunctions.googleapis.com/projectSettings/marktec-itesm?view=CONSUMER_VIEW
 Tue Nov 14 2017 04:03:57 GMT-0600 (Central Standard Time (Mexico))
[2017-11-14T10:03:57.044Z] >>> HTTP REQUEST GET https://servicemanagement.googleapis.com/v1/services/runtimeconfig.googleapis.com/projectSettings/marktec-itesm?view=CONSUMER_VIEW
 Tue Nov 14 2017 04:03:57 GMT-0600 (Central Standard Time (Mexico))
[2017-11-14T10:03:57.479Z] <<< HTTP RESPONSE 200 content-type=application/json; charset=UTF-8, vary=X-Origin, Referer,
Origin,Accept-Encoding, date=Tue, 14 Nov 2017 10:03:58 GMT, server=ESF, cache-control=private, x-xss-protection=1; mode=block, x-frame-options=SAMEORIGIN, x-content-type-options=nosniff, alt-svc=quic=":443"; ma=2592000; v="41,39,38,37,35", accept-ranges=none, connection=close
+  functions: all necessary APIs are enabled
[2017-11-14T10:03:57.488Z] <<< HTTP RESPONSE 200 content-type=application/json; charset=UTF-8, vary=X-Origin, Referer,
Origin,Accept-Encoding, date=Tue, 14 Nov 2017 10:03:58 GMT, server=ESF, cache-control=private, x-xss-protection=1; mode=block, x-frame-options=SAMEORIGIN, x-content-type-options=nosniff, alt-svc=quic=":443"; ma=2592000; v="41,39,38,37,35", accept-ranges=none, connection=close
+  runtimeconfig: all necessary APIs are enabled
[2017-11-14T10:03:57.489Z] >>> HTTP REQUEST GET https://appengine.googleapis.com/v1/apps/marktec-itesm
 Tue Nov 14 2017 04:03:57 GMT-0600 (Central Standard Time (Mexico))
[2017-11-14T10:03:57.490Z] >>> HTTP REQUEST GET https://apikeys.googleapis.com/v1/projects/marktec-itesm/apiKeys
 Tue Nov 14 2017 04:03:57 GMT-0600 (Central Standard Time (Mexico))
[2017-11-14T10:03:57.775Z] <<< HTTP RESPONSE 200 content-type=application/json; charset=UTF-8, vary=X-Origin, Referer,
Origin,Accept-Encoding, date=Tue, 14 Nov 2017 10:03:58 GMT, server=ESF, cache-control=private, x-xss-protection=1; mode=block, x-frame-options=SAMEORIGIN, x-content-type-options=nosniff, alt-svc=quic=":443"; ma=2592000; v="41,39,38,37,35", accept-ranges=none, connection=close
[2017-11-14T10:03:57.950Z] <<< HTTP RESPONSE 200 content-type=application/json; charset=UTF-8, vary=X-Origin, Referer,
Origin,Accept-Encoding, date=Tue, 14 Nov 2017 10:03:58 GMT, server=ESF, cache-control=private, x-xss-protection=1; mode=block, x-frame-options=SAMEORIGIN, x-content-type-options=nosniff, alt-svc=quic=":443"; ma=2592000; v="41,39,38,37,35", accept-ranges=none, connection=close
i  functions: preparing functions directory for uploading...
[2017-11-14T10:05:52.258Z] >>> HTTP REQUEST GET https://runtimeconfig.googleapis.com/v1beta1/projects/marktec-itesm/configs
 Tue Nov 14 2017 04:05:52 GMT-0600 (Central Standard Time (Mexico))
[2017-11-14T10:05:52.676Z] <<< HTTP RESPONSE 200 content-type=application/json; charset=UTF-8, vary=X-Origin, Referer,
Origin,Accept-Encoding, date=Tue, 14 Nov 2017 10:05:53 GMT, server=ESF, cache-control=private, x-xss-protection=1; mode=block, x-frame-options=SAMEORIGIN, x-content-type-options=nosniff, alt-svc=quic=":443"; ma=2592000; v="41,39,38,37,35", accept-ranges=none, connection=close
i  functions: packaged functions (22.1 KB) for uploading
[2017-11-14T10:06:01.593Z] >>> HTTP REQUEST GET https://www.googleapis.com/storage/v1/b/staging.marktec-itesm.appspot.com
 Tue Nov 14 2017 04:06:01 GMT-0600 (Central Standard Time (Mexico))
[2017-11-14T10:06:01.940Z] <<< HTTP RESPONSE 200 x-guploader-uploadid=AEnB2UpSfip_C_K1wvCJaLNVW1q05_zW3D3fph0U7sYHr6_9M5InFI0Pi_X1VFc8B5PpbZImDdZiAaZZLqWXdl-JxdzedIZeExTeX4ifDbfvg7G8tsjPm1Y, etag=CAE=, vary=Origin, X-Origin, content-type=application/json; charset=UTF-8, expires=Tue, 14 Nov 2017 10:06:02 GMT, date=Tue, 14 Nov 2017 10:06:02 GMT, cache-control=private, max-age=0, must-revalidate, no-transform, content-length=548, server=UploadServer, alt-svc=quic=":443"; ma=2592000; v="41,39,38,37,35", connection=close
[2017-11-14T10:06:01.942Z] >>> HTTP REQUEST POST https://www.googleapis.com/upload/storage/v1/b/staging.marktec-itesm.appspot.com/o?uploadType=media&name=firebase-functions-source ReadStream {
  _readableState:
   ReadableState {
     objectMode: false,
     highWaterMark: 65536,
     buffer: BufferList { head: [Object], tail: [Object], length: 1 },
     length: 22627,
     pipes: null,
     pipesCount: 0,
     flowing: null,
     ended: true,
     endEmitted: false,
     reading: false,
     sync: false,
     needReadable: false,
     emittedReadable: true,
     readableListening: false,
     resumeScheduled: false,
     defaultEncoding: 'utf8',
     ranOut: false,
     awaitDrain: 0,
     readingMore: false,
     decoder: null,
     encoding: null },
  readable: true,
  domain: null,
  _events: { end: [Function] },
  _eventsCount: 1,
  _maxListeners: undefined,
  path: 'C:\\Users\\benja\\AppData\\Local\\Temp\\firebase-functions-69565Vb7CkPZp0rr.zip',
  fd: 6,
  flags: 'r',
  mode: 438,
  start: undefined,
  end: undefined,
  autoClose: true,
  pos: undefined,
  bytesRead: 22627 }
 Tue Nov 14 2017 04:06:01 GMT-0600 (Central Standard Time (Mexico))
[2017-11-14T10:06:02.601Z] <<< HTTP RESPONSE 200 x-guploader-uploadid=AEnB2UqV_ml27ZAt9W3ouCst97NUKPW4MeltDmxl06PA4sGBy6A8fqo0bAbEKHT0vokHMXo0t0yhOY0ve3XT0RrLjsiDwXyhwA, etag=CJPx8MbovdcCEAE=, vary=Origin, X-Origin, content-type=application/json; charset=UTF-8, cache-control=no-cache, no-store, max-age=0, must-revalidate, pragma=no-cache, expires=Mon, 01
Jan 1990 00:00:00 GMT, date=Tue, 14 Nov 2017 10:06:03 GMT, content-length=860, server=UploadServer, alt-svc=quic=":443"; ma=2592000; v="41,39,38,37,35", connection=close
+  functions: functions folder uploaded successfully
[2017-11-14T10:06:02.604Z] >>> HTTP REQUEST GET https://cloudfunctions.googleapis.com/v1beta2/projects/marktec-itesm/locations/us-central1/functions
 Tue Nov 14 2017 04:06:02 GMT-0600 (Central Standard Time (Mexico))
[2017-11-14T10:06:02.845Z] <<< HTTP RESPONSE 200 content-type=application/json; charset=UTF-8, vary=X-Origin, Referer,
Origin,Accept-Encoding, date=Tue, 14 Nov 2017 10:06:03 GMT, server=ESF, cache-control=private, x-xss-protection=1; mode=block, x-frame-options=SAMEORIGIN, x-content-type-options=nosniff, alt-svc=quic=":443"; ma=2592000; v="41,39,38,37,35", accept-ranges=none, connection=close
i  functions: updating function verifyItesmDomain...
[2017-11-14T10:06:02.849Z] Trigger is:  resource=projects/marktec-itesm, eventType=providers/firebase.auth/eventTypes/user.create
[2017-11-14T10:06:02.851Z] >>> HTTP REQUEST PUT https://cloudfunctions.googleapis.com/v1beta2/projects/marktec-itesm/locations/us-central1/functions/verifyItesmDomain { sourceArchiveUrl: 'gs://staging.marktec-itesm.appspot.com/firebase-functions-source',
  name: 'projects/marktec-itesm/locations/us-central1/functions/verifyItesmDomain',
  entryPoint: 'verifyItesmDomain',
  timeout: '60s',
  availableMemoryMb: 256,
  labels: { 'deployment-tool': 'cli-firebase' },
  eventTrigger:
   { resource: 'projects/marktec-itesm',
     eventType: 'providers/firebase.auth/eventTypes/user.create' } }
 Tue Nov 14 2017 04:06:02 GMT-0600 (Central Standard Time (Mexico))
[2017-11-14T10:06:03.064Z] <<< HTTP RESPONSE 200 content-type=application/json; charset=UTF-8, vary=X-Origin, Referer,
Origin,Accept-Encoding, date=Tue, 14 Nov 2017 10:06:03 GMT, server=ESF, cache-control=private, x-xss-protection=1; mode=block, x-frame-options=SAMEORIGIN, x-content-type-options=nosniff, alt-svc=quic=":443"; ma=2592000; v="41,39,38,37,35", accept-ranges=none, connection=close
[2017-11-14T10:06:03.068Z] >>> HTTP REQUEST GET https://cloudfunctions.googleapis.com/v1beta2/operations/bWFya3RlYy1pdGVzbS91cy1jZW50cmFsMS92ZXJpZnlJdGVzbURvbWFpbi90SFM4NnhjSF9DUQ
 Tue Nov 14 2017 04:06:03 GMT-0600 (Central Standard Time (Mexico))
[2017-11-14T10:06:03.257Z] <<< HTTP RESPONSE 200 content-type=application/json; charset=UTF-8, vary=X-Origin, Referer,
Origin,Accept-Encoding, date=Tue, 14 Nov 2017 10:06:04 GMT, server=ESF, cache-control=private, x-xss-protection=1; mode=block, x-frame-options=SAMEORIGIN, x-content-type-options=nosniff, alt-svc=quic=":443"; ma=2592000; v="41,39,38,37,35", accept-ranges=none, connection=close
[2017-11-14T10:06:05.262Z] >>> HTTP REQUEST GET https://cloudfunctions.googleapis.com/v1beta2/operations/bWFya3RlYy1pdGVzbS91cy1jZW50cmFsMS92ZXJpZnlJdGVzbURvbWFpbi90SFM4NnhjSF9DUQ
 Tue Nov 14 2017 04:06:05 GMT-0600 (Central Standard Time (Mexico))
[2017-11-14T10:06:05.428Z] <<< HTTP RESPONSE 200 content-type=application/json; charset=UTF-8, vary=X-Origin, Referer,
Origin,Accept-Encoding, date=Tue, 14 Nov 2017 10:06:06 GMT, server=ESF, cache-control=private, x-xss-protection=1; mode=block, x-frame-options=SAMEORIGIN, x-content-type-options=nosniff, alt-svc=quic=":443"; ma=2592000; v="41,39,38,37,35", accept-ranges=none, connection=close
[2017-11-14T10:06:07.431Z] >>> HTTP REQUEST GET https://cloudfunctions.googleapis.com/v1beta2/operations/bWFya3RlYy1pdGVzbS91cy1jZW50cmFsMS92ZXJpZnlJdGVzbURvbWFpbi90SFM4NnhjSF9DUQ
 Tue Nov 14 2017 04:06:07 GMT-0600 (Central Standard Time (Mexico))
[2017-11-14T10:06:07.603Z] <<< HTTP RESPONSE 200 content-type=application/json; charset=UTF-8, vary=X-Origin, Referer,
Origin,Accept-Encoding, date=Tue, 14 Nov 2017 10:06:08 GMT, server=ESF, cache-control=private, x-xss-protection=1; mode=block, x-frame-options=SAMEORIGIN, x-content-type-options=nosniff, alt-svc=quic=":443"; ma=2592000; v="41,39,38,37,35", accept-ranges=none, connection=close
[2017-11-14T10:06:09.606Z] >>> HTTP REQUEST GET https://cloudfunctions.googleapis.com/v1beta2/operations/bWFya3RlYy1pdGVzbS91cy1jZW50cmFsMS92ZXJpZnlJdGVzbURvbWFpbi90SFM4NnhjSF9DUQ
 Tue Nov 14 2017 04:06:09 GMT-0600 (Central Standard Time (Mexico))
[2017-11-14T10:06:09.755Z] <<< HTTP RESPONSE 200 content-type=application/json; charset=UTF-8, vary=X-Origin, Referer,
Origin,Accept-Encoding, date=Tue, 14 Nov 2017 10:06:10 GMT, server=ESF, cache-control=private, x-xss-protection=1; mode=block, x-frame-options=SAMEORIGIN, x-content-type-options=nosniff, alt-svc=quic=":443"; ma=2592000; v="41,39,38,37,35", accept-ranges=none, connection=close
[2017-11-14T10:06:11.757Z] >>> HTTP REQUEST GET https://cloudfunctions.googleapis.com/v1beta2/operations/bWFya3RlYy1pdGVzbS91cy1jZW50cmFsMS92ZXJpZnlJdGVzbURvbWFpbi90SFM4NnhjSF9DUQ
 Tue Nov 14 2017 04:06:11 GMT-0600 (Central Standard Time (Mexico))
[2017-11-14T10:06:11.912Z] <<< HTTP RESPONSE 200 content-type=application/json; charset=UTF-8, vary=X-Origin, Referer,
Origin,Accept-Encoding, date=Tue, 14 Nov 2017 10:06:12 GMT, server=ESF, cache-control=private, x-xss-protection=1; mode=block, x-frame-options=SAMEORIGIN, x-content-type-options=nosniff, alt-svc=quic=":443"; ma=2592000; v="41,39,38,37,35", accept-ranges=none, connection=close
[2017-11-14T10:06:13.913Z] >>> HTTP REQUEST GET https://cloudfunctions.googleapis.com/v1beta2/operations/bWFya3RlYy1pdGVzbS91cy1jZW50cmFsMS92ZXJpZnlJdGVzbURvbWFpbi90SFM4NnhjSF9DUQ
 Tue Nov 14 2017 04:06:13 GMT-0600 (Central Standard Time (Mexico))
[2017-11-14T10:06:14.078Z] <<< HTTP RESPONSE 200 content-type=application/json; charset=UTF-8, vary=X-Origin, Referer,
Origin,Accept-Encoding, date=Tue, 14 Nov 2017 10:06:14 GMT, server=ESF, cache-control=private, x-xss-protection=1; mode=block, x-frame-options=SAMEORIGIN, x-content-type-options=nosniff, alt-svc=quic=":443"; ma=2592000; v="41,39,38,37,35", accept-ranges=none, connection=close
[2017-11-14T10:06:16.080Z] >>> HTTP REQUEST GET https://cloudfunctions.googleapis.com/v1beta2/operations/bWFya3RlYy1pdGVzbS91cy1jZW50cmFsMS92ZXJpZnlJdGVzbURvbWFpbi90SFM4NnhjSF9DUQ
 Tue Nov 14 2017 04:06:16 GMT-0600 (Central Standard Time (Mexico))
[2017-11-14T10:06:16.249Z] <<< HTTP RESPONSE 200 content-type=application/json; charset=UTF-8, vary=X-Origin, Referer,
Origin,Accept-Encoding, date=Tue, 14 Nov 2017 10:06:17 GMT, server=ESF, cache-control=private, x-xss-protection=1; mode=block, x-frame-options=SAMEORIGIN, x-content-type-options=nosniff, alt-svc=quic=":443"; ma=2592000; v="41,39,38,37,35", accept-ranges=none, connection=close
[2017-11-14T10:06:18.252Z] >>> HTTP REQUEST GET https://cloudfunctions.googleapis.com/v1beta2/operations/bWFya3RlYy1pdGVzbS91cy1jZW50cmFsMS92ZXJpZnlJdGVzbURvbWFpbi90SFM4NnhjSF9DUQ
 Tue Nov 14 2017 04:06:18 GMT-0600 (Central Standard Time (Mexico))
[2017-11-14T10:06:18.405Z] <<< HTTP RESPONSE 200 content-type=application/json; charset=UTF-8, vary=X-Origin, Referer,
Origin,Accept-Encoding, date=Tue, 14 Nov 2017 10:06:19 GMT, server=ESF, cache-control=private, x-xss-protection=1; mode=block, x-frame-options=SAMEORIGIN, x-content-type-options=nosniff, alt-svc=quic=":443"; ma=2592000; v="41,39,38,37,35", accept-ranges=none, connection=close
[2017-11-14T10:06:20.406Z] >>> HTTP REQUEST GET https://cloudfunctions.googleapis.com/v1beta2/operations/bWFya3RlYy1pdGVzbS91cy1jZW50cmFsMS92ZXJpZnlJdGVzbURvbWFpbi90SFM4NnhjSF9DUQ
 Tue Nov 14 2017 04:06:20 GMT-0600 (Central Standard Time (Mexico))
[2017-11-14T10:06:20.588Z] <<< HTTP RESPONSE 200 content-type=application/json; charset=UTF-8, vary=X-Origin, Referer,
Origin,Accept-Encoding, date=Tue, 14 Nov 2017 10:06:21 GMT, server=ESF, cache-control=private, x-xss-protection=1; mode=block, x-frame-options=SAMEORIGIN, x-content-type-options=nosniff, alt-svc=quic=":443"; ma=2592000; v="41,39,38,37,35", accept-ranges=none, connection=close
[2017-11-14T10:06:22.591Z] >>> HTTP REQUEST GET https://cloudfunctions.googleapis.com/v1beta2/operations/bWFya3RlYy1pdGVzbS91cy1jZW50cmFsMS92ZXJpZnlJdGVzbURvbWFpbi90SFM4NnhjSF9DUQ
 Tue Nov 14 2017 04:06:22 GMT-0600 (Central Standard Time (Mexico))
[2017-11-14T10:06:22.753Z] <<< HTTP RESPONSE 200 content-type=application/json; charset=UTF-8, vary=X-Origin, Referer,
Origin,Accept-Encoding, date=Tue, 14 Nov 2017 10:06:23 GMT, server=ESF, cache-control=private, x-xss-protection=1; mode=block, x-frame-options=SAMEORIGIN, x-content-type-options=nosniff, alt-svc=quic=":443"; ma=2592000; v="41,39,38,37,35", accept-ranges=none, connection=close
[2017-11-14T10:06:24.768Z] >>> HTTP REQUEST GET https://cloudfunctions.googleapis.com/v1beta2/operations/bWFya3RlYy1pdGVzbS91cy1jZW50cmFsMS92ZXJpZnlJdGVzbURvbWFpbi90SFM4NnhjSF9DUQ
 Tue Nov 14 2017 04:06:24 GMT-0600 (Central Standard Time (Mexico))
[2017-11-14T10:06:24.952Z] <<< HTTP RESPONSE 200 content-type=application/json; charset=UTF-8, vary=X-Origin, Referer,
Origin,Accept-Encoding, date=Tue, 14 Nov 2017 10:06:25 GMT, server=ESF, cache-control=private, x-xss-protection=1; mode=block, x-frame-options=SAMEORIGIN, x-content-type-options=nosniff, alt-svc=quic=":443"; ma=2592000; v="41,39,38,37,35", accept-ranges=none, connection=close
+  functions[verifyItesmDomain]: Successful update operation.

+  Deploy complete!

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

Most helpful comment

This issue is a real pain in the bum. I think it should be given high priority :/

All 94 comments

Thanks for filing! We know that slow deployment is a major pain point for the functions experience, and it is something that we are working to resolve through various strategies.

@laurenzlong
As a newbie to Firebase at first glance I thought I was messing up something, because the deploy always stopped at the _functions: preparing functions directory for uploading..._ part.
Giving some extra info (like: it takes 3-5 minutes to complete) would be really nice, until the problem is solved.

As a newbie, I spent many times canceling on this thinking that I was doing something wrong.

The problem is kind of obvious. The init command created a 'node modules' folder that is huge. On my machine it is: 22,903 Files, 2,782 Folders. The code copies all of that to a temp folder.

Here is what I did:

  1. Using log print statements, I identified the slow line of code. It is here:
    https://github.com/firebase/firebase-tools/blob/master/lib/prepareFunctionsUpload.js#L26

Line 26 in prepareFunctionsUpload.js:
fs.copySync(options.config.path(options.config.get('functions.source')), tmpdir.name);

  1. I printed out the parameters for that file copy call. On my machine it is:
    C:\Users\thoma\StudioProjects\LSystemAndroid\firestorefunctions
    -> C:\Users\thoma\AppData\Local\Temp\fbfn_752624vejX0cv3GEJI

The functions folder was created by the CLI command init. It looks like this:

  • node_modules (enormous size)
  • .gitignore
  • index.js
  • package.json
  • pacakge-lock.json

It seems to me that the CLI command init should NOT have created that node_modules folder. It's 165MB large. That seems unreasonable to add to every project.

@thomasfischersm

That's actually not the issue. The node_modules is not copied over to the temporary folder, as you can see from this line here: https://github.com/firebase/firebase-tools/blob/master/lib/prepareFunctionsUpload.js#L76

It is necessary for firebase init to install all the node modules locally inside of the functions source folder, otherwise locally serving the functions will not work, and trigger extraction will not work (this is how the CLI understands which events trigger each function so it can deploy them properly).

I put a debug print line before line 26 and after. That line took minutes.

Then, I added a filter to print out which files were being copied. It included all the node_modules files.

Then, I changed the filter to exclude the node_module files. The deployment progressed fast now. However a little later, it seemed that the script was trying to evaluate the correctness of the cloud functions. That code failed because it was missing the library dependencies.

The source code line that you point to seems to be a later step. It seems like the files (minus the node_modules) are archived into a zip file before uploading to the cloud. That line doesn't seem to run slow on my machine.

Yes you're right, I was mistaken, node_modules does get copied over. I think it is a valid idea to not copy over node_modules to the temp directory. What complicates this a bit is the fact that the CLI writes a ".runtimeconfig.json" to the temp folder prior to trigger parsing, and this file gets uploaded with the rest of the functions source code, and we didn't want to write this file into the actual source code directory. So there is probably a good solution that both improves deployment speed and ensures there aren't unintended side effects, but I'd have to play around with a bit. You can also feel free to make a pull request.

I'm having the same issue. It might be a good idea to print more messages during the "preparing directory..." steps so that the user doesn't think firebase-tools is hanging.

Edit: This was on Ubuntu WSL. On Linux, the "preparing" phase doesn't hang. The "creating function" step can be slow, but not as much as I experienced earlier.

This issue is a real pain in the bum. I think it should be given high priority :/

I'm trying to implement firebase functions to my project and because this error I had to postpone it.
This error made me waste a lot of time.
hope it be fixed soon!

This issue is a major hindrance. Mostly because I use firestore and in that stuff like aggregates, counters and presence can only be handled decently by cloud functions and it just hangs for 5 minutes every time.

@PulpoEnPatineta This is not an error. This is just simply an issue with the deploy time.

@McStuffins If your car takes five minutes to turn on, is it an error or simply an issue with start time?

is there a fix for this? It is really extremely slow.

I kept track of this issue from the beginning, but it's never been a problem for me since I have a CD set up and it does all the work for me. I also never deploy functions just to test if they work. So basically it didn't matter to me.

Until today, when I came across an unexpected limitation: I cannot deploy my functions anymore, cause deployment to production exceeds the daily quota (12,000 seconds). I have ~55 functions with various triggers (pubsub, firestore, https). Is it too much to handle?

Now I have to deploy my application for two days :rofl: :lollipop: :+1: :1st_place_medal: :coffin: :tada: :taco: :cactus: :dancer: :smiling_imp:

Sometimes, when I am deploying, it is extremely slow, and then there is a warning in the terminal that says "Error in the build environment"

@srinurp Please see the pull request I linked to above, it will address a part of the problem. And the backend team is working to address other parts of the issue (but it's a very complicated undertaking, so we appreciate your patience.)

@merlinnot Unless you are updating code for all of your functions with each deploy, I would recommend using the --only command to deploy individual functions or groups of functions. See https://firebase.google.com/docs/cli/#partial_deploys.

@McStuffins "Error in the build environment" usually indicates a production issue, in that case please file a support ticket at https://firebase.google.com/support/, you can see if there are any ongoing production issues by visiting the Firebase Status Dashboard

@laurenzlong I would have to configure my CI to automatically detect changes in each function between deployments (including resolving dependencies). And what if I update packages like firebase-functions, firebase-admin, lodash etc., which I use in every single function?

@merlinnot That's a very legitimate use case. Deployment quotas are controlled by the Google Cloud Functions, I would recommend filing a request on their public issues tracker: https://cloud.google.com/functions/docs/support

@laurenzlong Could node_modules folder be ignored when copying the source and then do a npm install --production or yarn install --production? As these tools may be faster than simply copying and pasting.

@horacehylee
This might be a breaking change. Some people may (myself included) still reference packages by a relative path (like "package-name": "./externs/package.tgz"), mostly 'cause of the (now fixed) issue with private repositories. The tool would have to take all of these corner cases into account.

The other thing is the caching: if Google was to download packages on your behalf, they would have to implement some internal caching mechanism. We all have local caches on our computers (both npm and yarn have caching mechanisms), therefore we don't kill npm's servers ;)

Some people might also want to simply test some changes in external libraries. It's much easier to just change a file and deploy the function than it is to create a fork, make changes, temporarily change a reference to the package, ...

Bottom line: it works just fine, leave it as it is now :+1:

@horacehylee @merlinnot Thanks for the 2 cents. Please see https://github.com/firebase/firebase-tools/pull/578, the next release of the CLI will no longer copy the functions source folder period.

I'm really not sure what firebase could be doing that takes MINUTES to deploy a 5 line, 1kb function, on a six 4GHz core machine, sitting on a 1Gbps fiber connection.

I know it sounds like I'm taking the piss, but I'm genuinely curious what is going on during "preparing directory for upload". Anyone actually know?

Copying your functions directory, including node modules, to a tmp dir.

Our next release will address this and no longer need to copy before
deploying.

On Sun, Jan 7, 2018, 5:05 PM hmexx notifications@github.com wrote:

I'm really not sure what firebase could be doing that takes MINUTES to
deploy a 5 line, 1kb function, on a six 4GHz core machine, sitting on a
1Gbps fiber connection.

I know it sounds like I'm taking the piss, but I'm genuinely curious what
is going on during "preparing directory for upload". Anyone actually know?


You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/firebase/firebase-tools/issues/536#issuecomment-355868154,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAAD_nUptJWFuYGvEXI0MwmQR-bG9_MKks5tIWm1gaJpZM4QdF3g
.

@mbleigh

Ah right. that explains it. It's kind of comedic seeing a workstation go crazy for a minute or two, only to have the next line print out "packaged functions (37.55kb !!!) successfully for uploading" lol

Look forward to the next release. Thx for responding.

H.

Day 19. Firebase still deploying. * grabs popcorn *

Yeah.

When's the next release slated for, and what % improvement in deployment times should we expect?

Just to know whether to keep going down this path.

The release should happen this week, and you can expect the "Preparing
functions directory for deploy" step to go substantially faster (I don't
have exact numbers). Other parts of the deploy will remain unchanged.

On Mon, Jan 15, 2018 at 12:42 PM hmexx notifications@github.com wrote:

Yeah.

When's the next release slating for, and what % improvement in deployment
times should we expect?

Just to know whether to keep going down this path.


You are receiving this because you were mentioned.

Reply to this email directly, view it on GitHub
https://github.com/firebase/firebase-tools/issues/536#issuecomment-357784792,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAAD_vaj-WngS9dMj7j5Q2AesM0tNMvVks5tK7hBgaJpZM4QdF3g
.

This was released!

@mbleigh Is this in release 3.17.4?

@jkossis v3.17.0

From release notes:

If you are deploying functions, you must update the firebase-functions SDK to the latest by running "npm i --save firebase-functions@latest" inside your functions directory. This enables faster functions deployment.

from minutes to seconds: good job !

For me this still takes minutes.

I have [email protected] and [email protected]. What can I do to help further debug this issue?

Here is the timed output from deploying only functions. I have changed the names but they are a combination of REST endpoints, database and auth triggers.

➜  functions git:(master) ✗ firebase --version
3.17.4
➜  functions git:(master) ✗ time firebase deploy --only functions

=== Deploying to 'XXX'...

i  deploying functions
i  functions: ensuring necessary APIs are enabled...
✔  functions: all necessary APIs are enabled
i  functions: preparing functions directory for uploading...
i  functions: packaged functions (123.07 KB) for uploading
✔  functions: functions folder uploaded successfully
i  functions: updating function 1...
i  functions: updating function 2...
i  functions: updating function 3...
i  functions: updating function 4...
i  functions: updating function 5...
i  functions: updating function 6...
✔  functions[1]: Successful update operation.
Function URL (1): https://us-central1-XXX.cloudfunctions.net/1
✔  functions[3]: Successful update operation.
✔  functions[4]: Successful update operation.
✔  functions[5]: Successful update operation.
✔  functions[6]: Successful update operation.
✔  functions[2]: Successful update operation.
Function URL (2): https://us-central1-XXX.cloudfunctions.net/2

✔  Deploy complete!

Project Console: https://console.firebase.google.com/project/XXX/overview
firebase deploy --only functions  4.59s user 1.07s system 1% cpu 6:09.26 total

@adamduren the fix was for an excessive time spent in preparing functions directory for uploading...

The deploys themselves can still take a fairly long time.

stack in the same situation:
screen shot 2018-01-31 at 18 57 02

"firebase-admin": "^5.8.2",
"firebase-functions": "^0.8.1",

npm install -g npm@latest gave me slightly different input, and removing firebase-cli seemed to change something too.

screen shot 2018-01-31 at 19 11 38

update:

okay, after running npm install -g firebase-tools it finally worked. Kudos to https://stackoverflow.com/questions/48531993/firebase-config-variables-are-not-available-error-with-deploying-functions#comment84098334_48531993

Hi, i'm having an issue at the same point ("preparing functions directory..")
but in my case it took more than 25/30 minutes to complete
I have 4 private dependencies that weigh compressed around 2.20 mb
I found that was the only way to include private dependencies, as compressed files.
am i doing something wrong? or is this the way is supposed to work?

2018-5-9
firebase deploy still slow, not sure why
image

Have you updated to the last version? I updated last week and now my deploy takes 1-3 minutes (from 25/30)

I'm seeing deploy times of 4+ minutes for something as simple as:

const functions = require('firebase-functions')

exports.test = functions.https.onRequest((req, res) => {
  res.send('Hello World')
})

i functions: updating function test... is the line that hangs.
It never used to be this slow!

@Robula Have you updated to the newest version of firebase-tools?

Yes I believe so. firebase —version reports 3.18.6.

you're on a later version than me. I am not sure if maybe they continued transferring the node_modules folder again in 3.18.6, but at the moment with 3.18.4, everything seems to be running fine...

There has not been a regression in deployment strategy in recent firebase-tools versions (the node_modules folder is not copied), however deployment time does also vary machine to machine and from time to time. Initial deploy of a function is also slower than subsequent updates.

I am seeing deploy times during the preparing functions directory for uploading... step take nearly 7 minutes on this step alone when running locally. The pre-deploy step for build takes around 5 seconds locally. All other steps in the deploy process as run from debug as very quick. I get that deploy can be somewhat slow, but I also use AWS lambda for work and very large lambda deploys are much much faster than this, on the order of 2 two 3 minutes, including python package installs & builds.

Even deploying from google cloud build it takes 2 to 3 minutes, versus 10 to 20 seconds in aws lambda. I just want to ask does the cli zipping the whole function folder before uploading?

@laurenzlong, could you elaborate if the functions are already deployed in parallel, or if this optimization is in the works?

Functions have always been deployed in parallel. However, please note that deploying 10 functions in parallel is still slower than deploying a single function.

+1 That deploying a function is extremely slow. I followed the cron job tutorial for creating the hourly-tick function, my very first tone, and it takes like a minute to deploy every single time.

@laurenzlong thank so much for responding and thanks for your hard work on Firebase!

Are there any active plans to improve deploy time? I ask because although we do like Firebase, we are actually thinking of moving away from it due to the slow deploy times. We have about 47 cloud functions and it regularly takes 3-6 minutes for our deploys. Compare that with git push heroku master which would take about 20-30 seconds to deploy the same volume of code to Heroku. And that code would then be instantly running on Heroku. With Firebase we have to wait another 20-30s (random) amount of time after deployment before the deployed functions are actually running (during this time, a mix of new and old functions run).

So compare the deployement experience:

*** Heroku:

git push heroku master

20-30s later ...

All newly-deployed functions are now running in a consistent/atomic way

*** Firebase:

firebase deploy --only functions

180-360s later ...

Functions are deployed but only some of the new ones are running, some old ones are still running

20-30s later ... 

All new functions running

It's also difficult to do atomic deploys with Firebase because after deployment, there is period of time during which some of the new functions, call them v_n+1 are running alongside some of the old functions v_n. So if you do a major update, you have a mix of new and old functions running possibly using different data formats or algorithms. This is much less safe than a Heroku deploy where either all the new functions deploy and only new functions are running or none deploy.

Further, sometimes a few of our 47 functions will fail to deploy with errors like

⚠  functions[retrieveFavorites(us-central1)]: Deployment error.
Server Error. getaddrinfo ENOTFOUND cloudfunctions.googleapis.com cloudfunctions.googleapis.com:443

We're deploying on highly reliable symmetric Gigabit internet, so the issue is not our network.

So think of Heroku deploys as a like an atomic DB transaction (all or nothing) whereas Firebase deploys are more like eventually consistent with partial failures ... This makes dev ops a lot more difficult, especially if you're pushing a bug fix in the middle of night in response to a page.

The be blunt, the deploy experience on Firebase is objectively slower and less reliable than on Heroku or AWS ... Don't get me wrong, we like Firebase and we really do appreciate all of your hard work. I don't mean this to sound like an attack, it's nothing personal, but we need Firebase to do better here or we're thinking of going elsewhere because deployments are just too painful.

Thanks again for your hard work on Firebase. We appreciate your help :-).

Thanks for sharing your datapoint! We do have some plans to improve this especially for deploying many functions at the same time (mainly improving the server-side build step after the API call is made for creating/updating the function). However, these are infrastructure changes that will take quarters, so we really appreciate your patiences in the meanwhile.

You might have already considered this, but you can make a script in your CI/CD pipeline that detects which functions have been edited, and only deploy those ones with the --only flag. That will dramatically improve your deployment speed. See this video for an example: https://www.youtube.com/watch?v=iyGHW4UQ_Ts

@laurenzlong Thanks for the info, Lauren. However, I have just one small cloud function and it still takes about 1 minute to deploy even after making the smallest change. I also use that flag even though I just have one cloud function. Seems to be something wrong going on here.

Still taking literally minutes as of April 2019 - Firebase version 6.6.0 - all I'm doing is following the tutorial here: https://firebase.google.com/docs/functions/get-started

Just downloaded and taking a few minute each time i "firebase deploy"

Last couple days deploying even hosting takes multiple minutes, when it took like 10-15 seconds couple weeks ago. Deploying functions times out as well.

And the Firebase status page is green https://status.firebase.google.com/ .

Does anyone know why this happens?

Using firebase-tools 7.0.0

$ firebase deploy --only=hosting --token xxx

=== Deploying to 'xxx'...

i  deploying hosting
i  hosting[xxx]: beginning deploy...
i  hosting[xxx]: found 1959 files in public
✔  hosting[xxx]: file upload complete
i  hosting[xxx]: finalizing version...
✔  hosting[xxx]: version finalized
i  hosting[xxx]: releasing new version...
✔  hosting[xxx]: release complete
✔  hosting: Finished running postdeploy script.

✔  Deploy complete!

Project Console: https://console.firebase.google.com/project/xxx/overview
Hosting URL: https://xxx.firebaseapp.com
✨  Done in 181.75s

@laurenzlong-

However, these are infrastructure changes that will take quarters, so we really appreciate your patiences in the meanwhile.

Any infrastructure-side updates since your last note a few quarters ago? Until these changes have been made, is it possible to re-open this issue? Closed does not seem to be the appropriate state unless tracking has moved to a different/related issue.

Firebase functions are still super slow after everything has been built/uploaded and the functions are being created/updated on the server side of things. As others have said, this is a major development velocity damper.

firebase --version
7.1.0

Many thanks for considering!

@repentsinner the backend project to improve build/deploy times is still ongoing (and going well!) but it's still not released.

Have you tried using the emulator (through firebase emulators:start) to speed up your development process? If so we'd love to get your feedback!

Thanks for the update @samtstern.

I haven't tried the emulator yet - I'm using functions.https.onCall from a flutter app as well as data in a firestore, and it seems like (at the moment anyway) redirecting everything in the test builds of the app to my development workstation is more effort than waiting for deploys.

I guess I can use the time I'm waiting to look into this 🤨.

Happy New Year to this issue that is still Closed and still not fixed! 🎉

Perhaps an admin or OP can rename this issue to "Preparing functions directory for deploy extremely slow" since it seems to have been closed based solely on a fix to that stage of the overall deploy process.

We can then open a new "Deploying functions extremely slow" issue since ... deploying functions is still extremely slow 😄

This issue was closed because there's nothing more we can do on the CLI side to improve deploy times. For local development we're continuing to invest in the emulator, we hope that people will have to run firebase deploy only when they're deploying to prod and not as part of their dev lifecycle.

Backend changes are still in progress. As you can tell, there have been unexpected delays.

Thanks for the clarification @samtstern, so I guess issues/requests against firebase/firebase-tools is only applicable to the CLI? Will hunt for a repo/project that covers the backend.

Regarding local development- from the public side of things it seems like Google is really encouraging the integration of Firebase and Flutter which on the tin seems to work very well together, but in practice we run into dev-time inconsistencies such as this. I had a quick look at the emulator as suggested when discovering this issue, but it really didn't appear to support an integrated Firebase plus Flutter development workflow at all, certainly not as smoothly as it does via the cloud backend. I haven't circled back to see if this has improved lately, but it seems unlikely.

@repentsinner yeah this repo only tracks CLI work. Of course we try to answer anything that comes in but often we have to close issues when there's nothing productive we can do here. Our backends are not open source which is why we generally point people to firebase support to file bug reports or feature requests about general Firebase things.

As for Flutter, we love it (see: https://github.com/FirebaseExtended/flutterfire) but it's important to note that it's not an official Firebase platform which means we can't offer our full support for issues like we do on native Android/iOS/Web. Maybe that will change one day but for now that's the situation.

If you have questions about how to connect your Flutter app to the Firebase Emulators, open an issue on the FlutterFire repo and cc me, then I can get the right Flutter people involved as well.

Got it, thanks for the clarification @samtstern! I've moved on to other projects for the moment, but will look in FlutterFire repo when I get back into this stuff.

The emulator doesn't support auth context so its 100% completely useless IMO.

I ended up discovering that my deployments froze because I was trying to use dotenv

Just poking my head in to remind people that this is still a pain point ✌️

For folks still coming across this - one thing I found helpful was utilizing functions.ignore to avoid uploading unnecessary bloat. I think an especially good one to include is .git:
{ "functions": { "ignore": ["node_modules", ".git", ".gitignore", ".nyc_output", ".runtimeconfig.json", "firebase-debug.log", "tslint.json", "tests"] }

I dropped functions completely as the dev workflow is beyond painful.

For folks still coming across this - one thing I found helpful was utilizing functions.ignore to avoid uploading unnecessary bloat. I think an especially good one to include is .git:

"functions": {
    "ignore": ["node_modules", ".git", ".gitignore", ".nyc_output", ".runtimeconfig.json", "firebase-debug.log", "tslint.json", "tests"]
  }

This actually yielded some results. Running in about 65-70% of the time now. Thanks!

Interesting -- by default the functions subdirectory is beneath the project root so won't have a .git folder. Folks for whom this helped -- what's your directory structure look like?

@mbleigh True. My best guess is that it's smart about this, and applies these to the functions directory.

@mbleigh I've got a functions-only repository so it seemed a little silly to have a functions directory. Everything shifted down into the root.

That's an extract from my firebase.json:

  "functions": {
    "ignore": [
      "__mocks__",
      ".cache",
      ".commitlintrc.yaml",
      ".dependabot",
      ".editorconfig",
      ".eslintrc.yaml",
      ".firebase",
      ".firebaserc",
      ".git",
      ".gitattributes",
      ".github",
      ".gitignore",
      ".lintstagedrc.js",
      ".nvmrc",
      ".prettierignore",
      ".prettierrc.yaml",
      ".vscode",
      "CHANGELOG.md",
      "cloudbuild.yaml",
      "codecov.yml",
      "CONTRIBUTING.md",
      "coverage",
      "cSpell.json",
      "decisions",
      "firebase.json",
      "firestore.indexes.json",
      "jest.config.js",
      "node_modules",
      "README.md",
      "rfcs",
      "scripts",
      "src",
      "test",
      "tsconfig.json",
      "tsconfig.production.json"
    ],
    "source": "."
  },

I'd gladly replace it with:
```
{
"include": ["lib", "package.json", "package-lock.json"]
}

FWIW I believe these accept globs so you might be able to do:

{
  "exclude": ["!{lib,package.json,package-lock.json}"]
}

Just started cloud functions, and the deploy time is painful.

painful deploy time :(

Our firebase app has 60 cloud functions running in it now. At first we started having a lot of deployment failures due to quotas so we then broke it into batches as the docs suggest. It consistently deploys now, but each batch takes ~3 minutes to deploy as part of GitHub actions CI on the default runners. The batches are about 6 each so 10 batches total making our function deployment time around 30 minutes.

The functions themselves are very small bits of code with minimal dependencies. Not sure what else we can do to speed up the pipeline.

That's really sad to hear. Another approach is to bundle multiple entrypoints/routes into a single function. This is not the best from the separation of concerns/size/security obviously, but this is what we did with all of our API endpoints (single entrypoint that then uses an internal router), and haven't experienced many quota limits since (but they do happen occasionally).

Still, this quota limit seems really low, since the official doc lists "80 per 100 seconds" for "Calls to deploy or delete functions via the Cloud Functions API". I'm assuming Google support could not raise this limit even further?

Still, this quota limit seems really low, since the official doc lists "80 per 100 seconds" for "Calls to deploy or delete functions via the Cloud Functions API". I'm assuming Google support could not raise this limit even further?

@dinvlad I was inquiring to both sales and support about getting that API limit increased, it's explicitly disabled / greyed out in the GCP console quotas section. Eventually was able to get a Google engineer on hangouts who informed me "That quota does not change".... so I guess not.

We have added .git to the standard ignore list in the next release:
https://github.com/firebase/firebase-tools/pull/2395

That should speed up releases for some. Of course there's not much we (the Firebase CLI team) can do about latency on the Cloud Functions backend.

make sure to do firebase deploy --only hosting when you're not updating functions

Over here we've also been grouping related functionality into a function, so it ends up looking like "one function per feature area” rather than “one function per individual granule of functionality”.

The performance characteristics of deployment are strongly driving the architecture of what goes into one function!

When and why did this issue get closed. It was opened in Nov 2017 and it looks like it is still just as much a problem as it was then. I can't see a reference to 'Closed' here and I would be interested to know why it was closed.

I'm not complaining, just wondering. I'm sure it's being worked on but it would be good to know about any progress.

@chriscurnow it was closed because the real cause is apparently is due to the (closed-source) server side not the CLI tools, even though it manifests to end users as a CLI issue (per @samtstern in https://github.com/firebase/firebase-tools/issues/536#issuecomment-572830647).

Unfortunately there's no good public tracker for the back end so we get updates here :(

How can we open this bug for google to fix it in their backend?
It is ridiculously slow

Like, what's even the point of using firebase functions if it's going to take this long

Hey guys, maybe we could all report this issue to google and maybe they'll listen?
https://firebase.google.com/support/troubleshooter/contact

Every time I try to use something from google for something important I'm reminded that they are one of the least consumer friendly companies in existence, but hey, we could try.

@RenFontes I just filed Case 00075974: Deploying firebase functions is so slow as to be unusable with Firebase support. I will update this message with whatever they come back with.

It's possible to deploy specific functions. Couldn't the CLI have a "checksum tracker" for each function and only deploy the changed ones (and also, track everything it uses: vars, packages, ...)?

@SrBrahma sure, but the issue is still present even if you only deploy a single function (e.g., single function deploy can still fail due to timeout).

It shouldn't have to fall on the user to manage batching function deployment, and in many cases function updates are needed atomically, therefore can't be split/batched.

Appreciate the suggestions for a workaround, but really what we need here is an SLA from Google and their adherence to it.

IT is True that Firebase Functions Sometimes?(maybe often) sucks at performance..It is really slow..You should support Rust rather.. Go? is it much faster than Node?

Still waiting for Google to improve Google Functions deploying time right ?
Going from PWA to SSR forced me to wait 7 min more for every deploy 😞

Was this page helpful?
0 / 5 - 0 ratings