Search code examples
node.jstypescriptfirebasegoogle-cloud-functionstypescript-eslint

Error Firebase cli cloud function deploy. npm ERR! Failed at the functions@ lint script


I am trying to deploy a typescript cloud function to the google cloud using firebase cli. My reason for doing it like this is because I had a javascript funtions which gave me warnings about firebase environment variable being estimated. So using the firebase cli worked.

Now I have another function in typescript.

  • npm: 6.14.15
  • firebase: 9.19.0
  • node: 14.17.6

Here is the code.

"use strict";

import cbor = require("cbor");

import * as admin from "firebase-admin";
import * as functions from "firebase-functions";
import iot = require("@google-cloud/iot");
const client = new iot.v1.DeviceManagerClient();

// start cloud function
exports.configFirestorev2 = functions
    .region("europe-west1")
    .firestore
    .document("Configs/{deviceId}")
    .onWrite(async (change: functions.Change<admin.firestore.DocumentSnapshot>,
        context?: functions.EventContext) => {
      if (context) {
        console.log(context.params.deviceId);
        const request = generateRequest(context.params.deviceId, change.after.data(), false);
        return client.modifyCloudToDeviceConfig(request);
      } else {
        throw (Error("no context from trigger"));
      }
    });

function generateRequest(deviceId: string, configData: any, isBinary: boolean) {
  const formattedName = client.devicePath(process.env.GCLOUD_PROJECT!, functions.config().iot.core.region, functions.config().iot.core.registry, deviceId);
  let dataValue;
  if (isBinary) {
    const encoded = cbor.encode(configData);
    dataValue = encoded.toString("base64");
  } else {
    dataValue = Buffer.from(JSON.stringify(configData)).toString("base64");
  }
  return {
    name: formattedName,
    binaryData: dataValue,
  };
}

here is the .eslintrc.js

module.exports = {
  root: true,
  env: {
    es6: true,
    node: true,
  },
  extends: [
    "eslint:recommended",
    "plugin:import/errors",
    "plugin:import/warnings",
    "plugin:import/typescript",
    "google",
    "plugin:@typescript-eslint/recommended",
  ],
  parser: "@typescript-eslint/parser",
  parserOptions: {
    project: ["tsconfig.json", "tsconfig.dev.json"],
    sourceType: "module",
  },
  ignorePatterns: [
    "/lib/**/*", // Ignore built files.
  ],
  plugins: [
    "@typescript-eslint",
    "import",
  ],
  rules: {
    "quotes": ["error", "double"],
    "import/no-unresolved": 0,
  }, 
};

Here is the package.json file

{
  "name": "functions",
  "scripts": {
    "lint": "eslint --ext .js,.ts .",
    "build": "tsc",
    "serve": "npm run build && firebase emulators:start --only functions",
    "shell": "npm run build && firebase functions:shell",
    "start": "npm run shell",
    "deploy": "firebase deploy --only functions",
    "logs": "firebase functions:log"
  },
  "engines": {
    "node": "14"
  },
  "main": "lib/index.js",
  "dependencies": {
    "firebase-admin": "^9.8.0",
    "firebase-functions": "^3.14.1",
    "@google-cloud/iot": "2.0.0",
    "@types/cbor": "^5.0.0",
    "cbor": "^5.0.2"
  },
  "devDependencies": {
    "@typescript-eslint/eslint-plugin": "^3.9.1",
    "@typescript-eslint/parser": "^3.8.0",
    "eslint": "^7.6.0",
    "eslint-config-google": "^0.14.0",
    "eslint-plugin-import": "^2.22.0",
    "firebase-functions-test": "^0.2.0",
    "typescript": "^3.8.0"
  },
  "private": true
}

when I try to deploy it using firebase deploy --only functions

I get an error see the terminal log.

PS C:\firebase\configFirestore\functions> firebase deploy --only functions

=== Deploying to 'pti-tag-copy'...

i  deploying functions
Running command: npm --prefix functions run lint && npm --prefix functions run build

> functions@ lint C:\firebase\configFirestore\functions
> tslint -p tslint.json

'tslint' is not recognized as an internal or external command,
operable program or batch file.
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! functions@ lint: `tslint -p tslint.json`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the functions@ lint script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     C:\Users\Shabir\AppData\Roaming\npm-cache\_logs\2021-10-06T06_44_06_259Z-debug.log
events.js:377
      throw er; // Unhandled 'error' event
      ^

Error: spawn npm --prefix functions run lint && npm --prefix functions run build ENOENT
    at notFoundError (C:\Users\Shabir\AppData\Roaming\npm\node_modules\firebase-tools\node_modules\cross-env\node_modules\cross-spawn\lib\enoent.js:6:26)
    at verifyENOENT (C:\Users\Shabir\AppData\Roaming\npm\node_modules\firebase-tools\node_modules\cross-env\node_modules\cross-spawn\lib\enoent.js:40:16)
    at ChildProcess.cp.emit (C:\Users\Shabir\AppData\Roaming\npm\node_modules\firebase-tools\node_modules\cross-env\node_modules\cross-spawn\lib\enoent.js:27:25)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:277:12)
Emitted 'error' event on ChildProcess instance at:
    at ChildProcess.cp.emit (C:\Users\Shabir\AppData\Roaming\npm\node_modules\firebase-tools\node_modules\cross-env\node_modules\cross-spawn\lib\enoent.js:30:37)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:277:12) {
  code: 'ENOENT',
  errno: 'ENOENT',
  syscall: 'spawn npm --prefix functions run lint && npm --prefix functions run build',
  path: 'npm --prefix functions run lint && npm --prefix functions run build',
  spawnargs: []
}

Error: functions predeploy error: Command terminated with non-zero exit code1

and here is a complete debug log

0 info it worked if it ends with ok
1 verbose cli [
1 verbose cli   'C:\\Program Files\\nodejs\\node.exe',
1 verbose cli   'C:\\Program Files\\nodejs\\node_modules\\npm\\bin\\npm-cli.js',
1 verbose cli   '--prefix',
1 verbose cli   'functions',
1 verbose cli   'run',
1 verbose cli   'lint'
1 verbose cli ]
2 info using npm@6.14.15
3 info using node@v14.17.6
4 verbose run-script [ 'prelint', 'lint', 'postlint' ]
5 info lifecycle functions@~prelint: functions@
6 info lifecycle functions@~lint: functions@
7 verbose lifecycle functions@~lint: unsafe-perm in lifecycle true
8 verbose lifecycle functions@~lint: PATH: C:\Program Files\nodejs\node_modules\npm\node_modules\npm-lifecycle\node-gyp-bin;C:\firebase\configFirestore\functions\node_modules\.bin;C:\Users\Shabir\AppData\Local\cloud-code\installer\google-cloud-sdk\bin;C:\Users\Shabir\AppData\Local\Programs\Python\Python39\Scripts\;C:\Users\Shabir\AppData\Local\Programs\Python\Python39\;C:\Program Files\Common Files\Oracle\Java\javapath;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Program Files\NVIDIA Corporation\NVIDIA NvDLISR;C:\Program Files (x86)\NVIDIA Corporation\PhysX\Common;C:\ProgramData\chocolatey\bin;C:\Program Files (x86)\Bitvise SSH Client;C:\Program Files\PuTTY\;C:\Program Files\Git\cmd;C:\Program Files\php-8.0.3-Win32-vs16-x64;C:\Program Files\dotnet\;C:\Program Files\Go\bin;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;C:\WINDOWS\System32\OpenSSH\;C:\Program Files\Intel\Intel(R) Memory and Storage Tool\;C:\Program Files\nodejs\;C:\Program Files\Docker\Docker\resources\bin;C:\ProgramData\DockerDesktop\version-bin;C:\Program Files (x86)\Google\Cloud SDK\google-cloud-sdk\bin;C:\Program Files\MinGW\bin;C:\Users\Shabir\AppData\Local\Microsoft\WindowsApps;;C:\Users\Shabir\AppData\Local\Programs\Microsoft VS Code\bin;C:\Users\Shabir\AppData\Roaming\cabal\bin;C:\ProgramData\chocolatey\lib\ghc\tools\ghc-8.10.4\bin;C:\tools\msys64;C:\Users\Shabir\go\bin;C:\Users\Shabir\AppData\Roaming\npm
9 verbose lifecycle functions@~lint: CWD: C:\firebase\configFirestore\functions
10 silly lifecycle functions@~lint: Args: [ '/d /s /c', 'tslint -p tslint.json' ]
11 silly lifecycle functions@~lint: Returned: code: 1  signal: null
12 info lifecycle functions@~lint: Failed to exec lint script
13 verbose stack Error: functions@ lint: `tslint -p tslint.json`
13 verbose stack Exit status 1
13 verbose stack     at EventEmitter.<anonymous> (C:\Program Files\nodejs\node_modules\npm\node_modules\npm-lifecycle\index.js:332:16)
13 verbose stack     at EventEmitter.emit (events.js:400:28)
13 verbose stack     at ChildProcess.<anonymous> (C:\Program Files\nodejs\node_modules\npm\node_modules\npm-lifecycle\lib\spawn.js:55:14)
13 verbose stack     at ChildProcess.emit (events.js:400:28)
13 verbose stack     at maybeClose (internal/child_process.js:1055:16)
13 verbose stack     at Process.ChildProcess._handle.onexit (internal/child_process.js:288:5)
14 verbose pkgid functions@
15 verbose cwd C:\firebase\configFirestore
16 verbose Windows_NT 10.0.22468
17 verbose argv "C:\\Program Files\\nodejs\\node.exe" "C:\\Program Files\\nodejs\\node_modules\\npm\\bin\\npm-cli.js" "--prefix" "functions" "run" "lint"
18 verbose node v14.17.6
19 verbose npm  v6.14.15
20 error code ELIFECYCLE
21 error errno 1
22 error functions@ lint: `tslint -p tslint.json`
22 error Exit status 1
23 error Failed at the functions@ lint script.
23 error This is probably not a problem with npm. There is likely additional logging output above.
24 verbose exit [ 1, true ]

Solution

  • I didn't managed to reproduce your issue but I was able to deploy your function in a Debian environment by following the next steps:

    1. I run the following command firebase init functions (I picked TS and selected yes in all options)
    2. cd functions
    3. npm install cbor
    4. npm install @google-cloud/iot
    5. Copied your function inside the directory functions/src/index.ts
    6. I modified the.eslintrc.js.
    7. I run firebase deploy --only functions

    In the .eslintrc.js I added the following lines in the rules section:

    "max-len": ["error", {"code": 200}],
    "require-jsdoc": 0,
    

    Here is the final .eslintrc.js:

    module.exports = {
      root: true,
      env: {
        es6: true,
        node: true,
      },
      extends: [
        "eslint:recommended",
        "plugin:import/errors",
        "plugin:import/warnings",
        "plugin:import/typescript",
        "google",
        "plugin:@typescript-eslint/recommended",
      ],
      parser: "@typescript-eslint/parser",
      parserOptions: {
        project: ["tsconfig.json", "tsconfig.dev.json"],
        sourceType: "module",
      },
      ignorePatterns: [
        "/lib/**/*", // Ignore built files.
      ],  plugins: [
        "@typescript-eslint",
        "import",
      ],
      rules: {
        "quotes": ["error", "double"],
        "import/no-unresolved": 0,
        "max-len": ["error", {"code": 200}],
        "require-jsdoc": 0,
      },
    };
    

    Could you verify that you followed this steps?

    EDIT

    As stated in the comments. The issue was solved by following the steps in this answer. In summary, what OP did was set tsconfigRootDir to __dirname in the .eslintrc.js file:

    module.exports = {
      // ...
      parserOptions: {
        project: "tsconfig.json",
        tsconfigRootDir: __dirname,
        sourceType: "module",
      },
      // ...
    }