gcloud deploy fails nodejs - node.js

I'm trying to deploy to google app engine. When I do so, the initial information all seems correct, the docker build is successful, but after docker it tries the following and fails:
Beginning teardown of remote build environment (this may take a few seconds).
Updating module [default].../Deleted [https://www.googleapis.com/compute/v1/projects/jamsesh-1219/zones/us-central1-f/instances/gae-builder-vm-20160213t114355].
Updating module [default]...failed.
ERROR: (gcloud.preview.app.deploy) Error Response: [13] Timed out when starting VMs. It's possible that the application code is unhealthy. (0/2 ready, 2 still deploying).
I know that I'm running es6 code transpiled to run on node 4.1.2 which is the version I'm told I can use here - I just have to run nvm install v4.1.2 which will switch me over, so I include that in my scripts. Here are my scripts in package.json:
"scripts": {
"test": "test",
"clean": "rm -rf lib",
"watch-js": "./node_modules/.bin/babel --plugins transform-es2015-classes src --presets react -d lib",
"dev-server": "./node_modules/.bin/webpack lib/client/entry.js",
"lint": "./node_modules/.bin/eslint ./src",
"server": "node lib/server/server",
"start-dev": "npm run lint && npm run build && npm run dev-server && npm run server",
"start": "nvm install v4.1.2 && node lib/server/server",
"styles": "./node_modules/.bin/lessc ./public/less/bundle.less ./public/css/bundle.css",
"build": "npm run clean && ./node_modules/.bin/babel --plugins transform-es2015-classes src --presets react -d lib && npm run styles"
},
and my docker file:
# Dockerfile extending the generic Node image with application files for a
# single application.
FROM gcr.io/google_appengine/nodejs
COPY . /app/
# You have to specify "--unsafe-perm" with npm install
# when running as root. Failing to do this can cause
# install to appear to succeed even if a preinstall
# script fails, and may have other adverse consequences
# as well.
# This command will also cat the npm-debug.log file after the
# build, if it exists.
RUN npm install --unsafe-perm || \
((if [ -f npm-debug.log ]; then \
cat npm-debug.log; \
fi) && false)
CMD npm start
So yeah, I've got no clue why the deployment failing. I could definitely benefit from some more thorough documentation on deploying node on GAE. It works on a test repo. Is there something else I need to be doing to run node on GAE with my babel6 transpiled code? Or should something be different in my scripts? In the Google Shell I can run locally fine once I switch to node v4.1.2

Related

Heroku Build Not Copying React Files

I have a Node application, including an express server, set to respond to various backend requests and then to try to serve static content from a React app's build folder. It works great locally. The two different package.json files in the server and client respectively build the React app, copy its build files into the server's ./dist folder, then builds the server app and does the same, then runs the server. Everything is perfect.
However, on Heroku, the React build folder is never copied into the server's dist folder, and I get 404 errors trying to load the app. I know this worked at some point but I'm not sure what I changed that broke it and nothing is making sense to me to get it working again.
"scripts" section of the client (react) package.json:
"scripts": {
"start": "react-scripts start",
"react-build": "react-scripts build",
"build": "npm run clean && npm run react-build && npm run copy && cd server && npm run client-build",
"clean": "rimraf server/dist/",
"copy": "copyfiles build/**/* server/dist -E",
"test": "react-scripts test",
"eject": "react-scripts eject",
"prod": "cd server && npm run start"
},
and the "scripts" section of the server's package.json:
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "nodemon -i dist -i creds index.ts",
"clean": "rimraf dist/",
"copy-files": "copyfiles views/**/* assets/**/* creds/**/* dist/",
"copy-web": "copyfiles -u 1 ../build/**/* dist/ -E",
"build": "cd .. && npm run react-build && cd server && npm run clean && tsc && npm run copy-files && npm run copy-web",
"client-build": "npm i && tsc && npm run copy-files",
"start": "node dist/index.js"
},
Heroku, of course, runs npm run build from the root folder to kick off the build process, which is the client's package.json, so it runs:
npm run clean && npm run react-build && npm run copy && cd server && npm run client-build
Specifically the npm run copy doesn't seem to be doing anything. When I hit the ls through the heroku-cli, the folder is not there. I'm not getting any errors in the build.
I have been able to put a cludgey piece of code into the main server so that it checks to see if the build folder exists where it's supposed to exist before setting up the static middleware, and to go up the file tree to where they're supposed to be copied from if it doesn't, so it's working, but I don't think I should have to do this and I can't just point to the initial React build location or I'd be serving stale build's while I'm in dev locally instead of a specific dev page that links to the webpack npm run start instance that updates as I hack at it.
I understand that between the workaround in prod and just not relying on the server's static files in dev is "good enough" for me to move on, but my OCD won't let me until I understand why copyfiles works fine copying the server's extra files into dist but can't manage to copy the React app to the place it's supposed to go.
This seems like a pretty basic thing, and long run my plan here is to serve multiple independent React applications as "widgets" from different paths on the server and if I can't get the root path to behave because I'm an idiot then idk what kinds of problems I'm going to run into down the line.
TIA, lmk if any additional info is needed.
CORRECTION: I had been building an outdated version without the -E flag on the copyfiles call. Once I updated that, I did in fact get an error that no files were copied. To reiterate though, the files ARE in the build folder where they were supposed to be copied from, just not in the dist/build folder where they're supposed to go, as confirmed now by copyfiles deciding it had nothing to copy.
Is this an async issue? I thought the && suggested that the left side (the build) had to finish before the right side (the copy) would execute?

How to Serve a React App with Django on Elastic Beanstalk?

I used to have my app on Heroku and the way it worked there was that I had 2 buildpacks. One for NodeJS and one for Python. Heroku ran npm run build and then Django served the files from the build folder.
I use Code Pipeline on AWS to deploy a new version of my app every time there is a new push on my GitHub repository.
Since I couldn't figure out how to run npm run build in a python environment in EB, I had a workaround. I ran npm run build and pushed it to my repository (removed the build folder from .gitignore) and then Django served the files on EB.
However, this is not the best solution and I was wondering if anyone knows how to run npm run build the way Heroku can do it with their NodeJS buildpack for a python app on EB.
So I figured out one solution that worked for me.
Since I want to create the build version of my app on the server the way Heroku does it with the NodeJS buildpack, I had to create a command that installs node like this:
container_commands:
01_install_node:
command: "curl -sL https://rpm.nodesource.com/setup_12.x | sudo bash - && sudo yum install nodejs"
ignoreErrors: false
And then to create the build version of the react app on a Python Environment EB, I added the following command:
container_commands:
02_react:
command: "npm install && npm run build"
ignoreErrors: false
So of course, after the build version is created, you should collect static files, so here is how my working config file looked at the end:
option_settings:
aws:elasticbeanstalk:container:python:
WSGIPath: <project_name>/wsgi.py
aws:elasticbeanstalk:application:environment:
DJANGO_SETTINGS_MODULE: <project_name>.settings
aws:elasticbeanstalk:container:python:staticfiles:
/static/: staticfiles/
container_commands:
01_install_node:
command: "curl -sL https://rpm.nodesource.com/setup_12.x | sudo bash - && sudo yum install nodejs"
ignoreErrors: false
02_react:
command: "npm install && npm run build"
ignoreErrors: false
03_collectstatic:
command: "django-admin.py collectstatic --noinput"
Hope this helps anyone who encounters the same 🙂
I don't know exactly Python but I guess you can adapt for you case.
Elastic Beanstalk for Node.js platform use by default app.js, then server.js, and then npm start (in that order) to start your application.
You can change this behavior with configuration files. Below the steps to accomplish with Node.js:
Create the following file .ebextensions/<your-config-file-name>.config with the following content:
option_settings:
aws:elasticbeanstalk:container:nodejs:
NodeCommand: "npm run eb:prod"
Edit your package.json to create the eb:prod command. For instance:
"scripts": {
"start": "razzle start",
"build": "razzle build",
"test": "razzle test --env=jsdom",
"start:prod": "NODE_ENV=production node build/server.js",
"eb:prod": "npm run build && npm run start:prod"
}
You may faced permission denied errors during your build. To solve this problem you can create .npmrc file with the following content:
# Force npm to run node-gyp also as root
unsafe-perm=true
If you need more details, I wrote a blogpost about it: I deployed a server-side React app with AWS Elastic Beanstalk. Here’s what I learned.

How to run npm test after npm start in bash script

In my docker file, I want to run test script inside it after app is up in Docker dev version. Problem is when I created a bash script and add like that, test script is not working.
Here is my package json file:
"scripts": {
"build": "./node_modules/babel-cli/bin/babel.js src --out-dir lib --copy-files lib --plugins transform-react-jsx --presets es2015",
"bundle": "./node_modules/browserify/bin/cmd.js lib/client.js -o public/js/bundle.js",
"start": "npm run build && npm run bundle && node lib/server.js",
"test": "mocha ./src/*.test.js"
},
and here is bash script file
#!/bin/bash
npm start
npm run start
npm test
npm run test
Please let me know how to fix it, thanks much.
#!/bin/bash
npm run build
npm run bundle
forever start ./lib/server.js
npm test
I've found solution that I need to install forever or pm2 first.

why package.json script works fine on local project but doesn't work on a dependency project

I have created a npm module(let call it ModuleA) and defined clean script in its package.json file like below:
"scripts": {
"test": "nyc mocha tests/ --opts mocha.opts",
"build": "babel -d dist/ src/",
"prepublish": "yarn run clean && yarn run build",
"postinstall": "yarn run clean && yarn run build",
"clean": "rimraf ./dist"
},
I use rimraf to remove the dist directory. This dependency is defined in devDependencies as "rimraf": "^2.6.1". It works fine on this project. But in one of my other project (let call it ModuleB) which has a dependency on this module, the yarn install doesn't work and I get below error:
$ rimraf ./dist
sh: 1: rimraf: not found
this error happens when npm/yarn is building the ModuleB. I have checked that rimraf exist in node_modules/.bin directory in ModuleB. It works fine if I install rimraf globally. I wonder how I can make the npm/yarn to use rimraf from node_modules/.bin/rimraf?
BTW, I also put the rimraf in devDependencies in ModuleB.
I tried to update the script in ModuleA to use rimraf from node_modules/.bin/rimraf as below:
"clean": "node_modules/.bin/rimraf ./dist"
it works fine on ModuleA. But I got below error when run yarn install on ModuleB:
$ node_modules/.bin/rimraf ./dist
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
sh: node_modules/.bin/rimraf: No such file or directory
error Command failed with exit code 127.
See those issues:
https://github.com/yarnpkg/yarn/issues/721 (postinstall hook doesn't appear to be run #721)
https://github.com/yarnpkg/yarn/issues/853 (preinstall and postinstall are not run #853)
https://github.com/yarnpkg/yarn/issues/614 (Bug: issue with postinstall scripts in git-hooks package)
Now make sure that yarn clean and npm clean works as expected.
For example this will not work if you didn't install rimraf globally:
$ rimraf ./dist
But this should work:
$ ./node_modules/.bin/rimraf ./dist
Test those commands first:
npm run clean
and:
yarn run clean
to use the "clean": "rimraf ./dist" script defined in package.json.
Note that ./node_modules/.bin is added to your PATH when you run package.json scripts.
Try running the commands from the simple ones where you run the script directly without npm or yarn, then test with both npmand yarn, and then finally try to narrow down the problem with postinstall hooks.

How to run Procfile with multiple commands on Heroku?

I'm trying to deploy the static website to Heroku and I struggle how to correctly setup the Procfile.
I have next command to run on the server:
npm install
gulp build (will make a build with /public folder)
http-server (will serve /public by default)
What I've tried:
web: npm install; gulp build; http-server
web: npm install & gulp build & http-server
Okay, so I've spent a bit of time on that and came up with the answer. By default, heroku is installing all packages from the package.json file, so npm install is no longer required. Then what was left - gulp build and http-server.
For that case, I've added "postinstall" : "gulp build" to my package.json and it left me with web: http-server.
Simplifying things have actually solved the problem. Not sure how useful that information might be to you, but it's worth to share.
You may also have been looking for && or a library like concurrently.
Regardless, and per the docs, use Procfile as nothing more than an entry point to your npm start script.
Use the npm scripts lifecycle as stated (npm-scripts).
Directly From The Documentation (heroku-build-process).
"scripts": {
"start": "node index.js",
"test": "mocha",
"postinstall": "bower install && grunt build"
}
Heroku has adopted the 'there's an app for everything' mantra, but for buildpacks. Whatever you're building, there's a buildpack for it.
You can run multiple command inside Procfile using sh -c command :
worker: sh -c 'firstCommand && secondCommand && etc...'
Notes : Procfile should be at the project root level.
For example :
worker: sh -c 'cd backend && yarn install && yarn build && yarn start-worker'
Or in your case (if u have Procfile at the same level as package.json) :
web: sh -c 'npm install && gulp build && npm run http-server'

Resources