Husky prepare script failing firebase function deployment - firebase

I have installed husky in my npm project as a prepare script like below
{
"name": "functions",
"scripts": {
"build": "tsc",
"start": "npm run serve",
"deploy": "firebase deploy --only functions",
"prepare": "husky install functions/.husky"
}
"dependencies": {
"firebase-admin": "^11.4.1",
"firebase-functions": "^4.1.1",
},
"devDependencies": {
"husky": "^8.0.2",
"typescript": "^4.9.4"
}
}
husky is declared as devDependencies as this npm module is only required while local development and has no need in runtime app.
So when I run npm run deploy, I get the below error
i functions: updating Node.js 16 function funName(us-central1)...
Build failed:
> prepare
> husky install functions/.husky
sh: 1: husky: not found
npm ERR! code 127
npm ERR! path /workspace
npm ERR! command failed
npm ERR! command sh -c -- husky install functions/.husky
This error clearly states that husky is not installed.
One possible solution is to create a prepare.js script which checks if the script is running while in local development or in the firebase server(to prepare the project) and then conditionally run the husky npm module command

I just ran into this exact same issue but with tsc. I'm not sure why, but the prepare script is also run in the cloud function (not just locally) while deploying. However, considering you likely have the node_modules directory in the functions.ignore list in the firebase.json, the node_modules directory doesn't get uploaded as part of the deployment and so the husky package isn't visible to the script when it gets run in the cloud function environment.
You likely don't need the husky script to be run in the function environment either way, so you can add a condition to check for an environment variable that is usually set in the function environment (I am using the GOOGLE_FUNCTION_TARGET environment variable in my case), and only run the command if that environment is not set. You also need to wrap this in a bash script instead of adding it inline in the package.json because of how the prepare script is run.
For example, here's the content of my scripts/prepare.sh file.
#!/bin/bash
set -o verbose
# Only run if the GOOGLE_FUNCTION_TARGET is not set
if [[ -z "$GOOGLE_FUNCTION_TARGET" ]]; then
npm run build
fi
Then I use it in my package.json prepare script:
// ...
"prepare": "./scripts/prepare.sh",
// ...
There's potentially a better solution to this, but this is how I got it to work for me. Hope this helps!

This SO answer is spot on and uses bash script. I used the same concept mentioned in the answer to write the prepare script in js in scripts/ folder with the name of prepare.mjs
"use-strict";
import * as path from "path";
import { fileURLToPath } from "url";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// Firebase sets the GOOGLE_FUNCTION_TARGET when running in the firebase environment
const isFirebase = process.env.GOOGLE_FUNCTION_TARGET !== undefined;
if (!isFirebase) {
process.chdir("../"); // path where .git file is present. In my case it was ..
const husky = await import("husky");
husky.install("functions/.husky"); // path where .husjy config file is present w.r.t. .git file
}
And in my package.json I have used the above script as follows
{
"name": "functions",
"scripts": {
"build": "tsc",
"start": "npm run serve",
"deploy": "firebase deploy --only functions",
"prepare": "node ./scripts/prepare.mjs"
}
"dependencies": {
"firebase-admin": "^11.4.1",
"firebase-functions": "^4.1.1",
},
"devDependencies": {
"husky": "^8.0.2",
"typescript": "^4.9.4"
}
}
This uses the environment variable(GOOGLE_FUNCTION_TARGET) documented by the Google at the doc

Related

a turborepo pipeline task that depends on a root package.json task that does not execute in each package

I have a root package.json task that does not execute in every package that calls yarn tsc.
Currently, I have it as a prebuild script in the root package.json:
"prebuild": "yarn tsc",
Is there anyway to specify this as a dependsOn element of build in the turborepo.json?
If I add tsc like below then it will get executed in the each package which is not what I want.
"pipeline": {
"tsc": {
"dependsOn": ["generate"],
"outputs": ["dist-types/**"]
},
"build": {
"dependsOn": ["tsc", "^build"],
"outputs": ["dist/**"]
},
Based on the documentation, your individual projects within the mono-repo need to implement a corresponding script (e.g. if you have tsc as a pipeline in turbo.json, you will need a tsc script in your package.json in your individual projects). Any project without a script matching the pipeline name will gracefully be skipped when the pipeline is run.
In your case, you would move your tsc script from the root level package.json into each project in which you want the pipeline to run against.

Firebase Functions local "file:" dependencies

I'm using a react-crud-shared as dependency for react-crud-backend which uses Firebase Cloud Functions.
At react-crud-backend I have the following:
{
"name": "react-crud-backend",
"description": "Cloud Functions for Firebase",
"scripts": {
...
},
"dependencies": {
...
"react-crud-shared": "file:../shared",
...
},
"engines": {
"node": "8"
},
"private": true,
"devDependencies": {
...
}
}
At react-crud-shared I have the following:
{
"name": "react-crud-shared",
"version": "0.0.1",
"description": "",
"main": "src/index.js",
"private": true,
"dependencies": {
"lodash": "^4.17.11"
}
}
It works fine on development: "firebase serve --only functions", but an error is thrown on deployment:
Did you list all required modules in the package.json dependencies?
Detailed stack trace: Error: Cannot find module 'react-crud-shared'
Is there a way to make it work without having to publish the private repository to NPM?
Thanks
EDIT: I found a solution for this that I like much better. I commented on this github issue here: https://github.com/firebase/firebase-tools/issues/968#issuecomment-460323113 . Basically, I have a preinstall script the runs npm pack to copy over the package under the functions directory before I use firebase deploy.
FWIW I have the exact same problem. Not exactly sure how I'm going to solve it, but this information from the doc was helpful (https://firebase.google.com/docs/functions/handle-dependencies):
To specify a dependency for your function, add it to your package.json file. If you are deploying through the gcloud command-line tool, you can also pre-install dependencies and deploy them alongside your function. By default, the node_modules folder is added to your .gcloudignore file and is not uploaded as part of your deployment. To deploy pre-installed dependencies, remove node_modules/ from the .gcloudignore file before deploying your function.
Note: Deploying pre-installed dependencies works with gcloud only; the Firebase CLI ignores the local node_modules folder.
Thus, it appears you could first run "npm install" locally, and then use gcloud for deployment, as it would copy up your node_modules directory, which would have your peer dependency in it.
Really kind of stinks, though, that I would have to switch to gcloud from firebase CLI for deployment. Ugh.
node_modules are (ordinary) being ignored for the deployment;
one can still deploy private modules with a directory structure like that:
functions/
index.js
package.json
react-crud-shared/
package.json
and a package.json alike that:
{
"dependencies": {
...
"react-crud-shared": "file:./react-crud-shared"
}
}
another method would be to blank the ignores:
{
"functions": {
"ignore": []
}
}
just think the first one is better, because this would push the whole local node_modules directory.
beside these workaround methods ...
one can install internally published modules from Cloud Source Repositories, via git+https://.
If the goal is to only share module between web and function, you may simple put the shared package under functions as file:react-crud-shared and then reference the package from web using file:../functions/react-crud-shared.
functions/
package.json
...
react-crud-shared/
package.json
...
web/
package.json
...
in functions/package.json
{
"dependencies": {
...
"react-crud-shared": "file:react-crud-shared"
}
}
in web/package.json
{
"dependencies": {
...
"react-crud-shared": "file:../functions/react-crud-shared"
}
}
It works perfectly fine for my case since I use shared protobufjs for cleaner typescript.
What I have found is that the location of your private package has to be inside your cloud functions folder (default to be functions)
So if you move your private package inside your cloud function folder and set the path of that package correctly in package.json, it should work.

How can I get "firebase deploy --only functions" command to use the package.json in the functions/ directory?

I've got the standard app structure for a Firebase/Angular application.
- functions/
|--- index.ts
|--- package.json
- src/
|--- app/
| |--- (angular stuff)
|--- index.html
|--- ...
- package.json
- firebase.json
The problem is that when I run firebase deploy --only functions, the predeploy hooks that I've defined in firebase.json, are called from inside the root/ directory, and not from inside root/functions/ directory.
So for example, in root/package.json I have
{
"name": "functions",
"scripts": {
"echo": "echo 'hello1'"
},
...
}
but in root/functions/package.json I have
{
"name": "functions",
"scripts": {
"echo": "echo 'hello2'"
},
...
}
and in my firebase.json file I have
{
...
"functions": {
"predeploy": [
"npm run echo"
]
},
No matter whether I am in root/ or root/functions, when I run firebase deploy --only functions I get hello1
How do I configure my Firebase tools to use the configurations (i.e. namely the package.json stuff) from functions/ when I run deploy --only functions ?
It seems the best way to get this working, according to the Firebase Typescript docs, is to specify the predeploy hook as follows
{
"functions": {
"predeploy": "npm --prefix functions run build",
}
}
This calls npm run build from inside the functions directory, so it will call the build script in functions/package.json and not the project root's package.json

package.json ignored during meteor build

I upgraded my meteor project to version 1.5.1. It runs fine when I just start it with the meteor run command. But as soon as I build it, it will compain about missing babel-runtime. It seems that it ignores my package.json file in the project folder. And thus babel-runtime is not being installed when running meteor npm installafter having built the project
Content of my package.json
{
"dependencies": {
"babel-runtime": "^6.26.0",
"bcrypt": "^1.0.3"
}
}
Content of package.json inside the bundle/programs/server/ folder after running meteor build
{
"name": "meteor-dev-bundle",
"version": "0.0.0",
"dependencies": {
"meteor-promise": "0.8.4",
"fibers": "1.0.15",
"promise": "7.1.1",
"underscore": "1.5.2",
"source-map-support": "https://github.com/meteor/node-source-map-support/tarball/1912478769d76e5df4c365e147f25896aee6375e",
"semver": "4.1.0",
"node-gyp": "3.6.0",
"node-pre-gyp": "0.6.34"
},
"devDependencies": {
"eachline": "https://github.com/meteor/node-eachline/tarball/ff89722ff94e6b6a08652bf5f44c8fffea8a21da",
"chalk": "0.5.1"
},
"scripts": {
"install": "node npm-rebuild.js"
}
}
Am I missing something here? Of course I ran meteor npm install --save babel-runtime many times...
Well, the solution would be to install npm modules before building production bundle (assuming you already have babel-runtime in your package.json):
cd <path_to_project>
meteor npm install
meteor build ...
Built bundle's package.json won't have babel-runtime, but it will be included in bundle from node_modules folder.
Added:
Don't forget that you still have to do npm install in your deployed bundle, as usual.

Grunt will simply not install on my Win 8.1 machine

I made a folder g in root(C:/) in where I try to install Grunt via npm.
I sucessfull made: npm install -g grunt-cli.
I configured package.json to this:
{
"name": "testing",
"version": "0.0.0",
"dependencies": {
"grunt": "~0.4.5" },
"description": "testing",
"main": "index.html",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"devDependencies": {
"grunt": "^0.4.5"
}
}
So good so far.
BUT: When I try to install Grunt: npm install grunt --save-dev and modules(plugins) then I run into this error: npm WARN package.json testing#0.0.0 No repository field...
I use GitHub where I've forked Grunt and Grunticon.
Then I can't succed with nothing towards installing Grunt...
Any good clues and help in solving this?
Okay, I think I see the problem clearly now. Here are some instructions for getting Grunt running, try to follow these exactly, do not create any other folders as it could cause issues for Grunt or Node.
Create a folder for your project, this can be anywhere on your system.
Save the file you have above as package.json in that folder.
Now install the global Grunt CLI
~$ npm install -g grunt-cli <-- Note this is "grunt-cli" NOT "grunt"
Then go to the new directory you created and run this command:
~/new-directoty$ npm install
This will install the Grunt runtime locally for your project because it is specified in package.json
Create a very simple config file in the new directory and name it Gruntfile.js:
module.exports = function(grunt) {
grunt.initConfig({ /* your config will go in here */ });
/* multi-task definitions go here */
};
Now try to run Grunt just to test that it works:
~/new-directory$ grunt
After that you are ready to start adding plugins, but that's a bigger topic. Good luck.

Resources