grunt task is not executing after deploying to heroku - node.js

I have a sails application which I created using the steps in the sailscasts and it works correctly in development.
But when I push it to heroku, the grunt task does not execute and the css and javascript is not linked.
I have registered the following task in the Gruntfile.js
grunt.registerTask('heroku:production', 'build');
My node version is 0.12.7 and sails version is 0.11.0
This might be related to
https://github.com/balderdashy/sails/issues/1872
but I'm not sure how to fix it.
Any help is appreciated.

The problem here that Sails has hardcoded tasks to be called. If you take a look into lib/hooks/grunt/index.js you will see initialize method that calls your tasks.
initialize: function (cb) {
sails.log.verbose('Loading app Gruntfile...');
if(sails.config.environment === 'production') {
return this.runTask('prod', cb);
}
this.runTask('default', cb);
}
So you must have two tasks with prod and default names.
If I'm not mistaken, Heroku runs your application in a production mode, so you must have your prod task (even if you modify something, you must modify prod task), but not the heroku:production.

Related

Detect whether an npm package can run on browser, node or both

I'm building a NextJs application which uses a set of abstractions to enable code from both react (Component logic etc.) and node (API logic) to utilize same types and classes. The motive here is to make the development process seem seamless across client side and server side.
For example. a call on User.create method of the User class will behave differently based on the runtime environment (ie. browser or node) - on the browser, it will call an api with a POST request and on server it will persist data to a database.
So far this pattern worked just fine, and I like how it all turned out in terms of the code structure. However, for this to work, I have to import modules responsible for working on the server and browser to a single module (which in this case is the User class) this leads to a critical error when trying to resolve dependencies in each module.
For example I'm using firebase-admin in the server to persist data to the Firebase Firestore. But it uses fs which cannot be resolved when the same code runs on the browser.
As a work around I set the resolve alias of firebase-admin to false inside the webpack configuration (given it runs on browser) see code below.
/** next.config.js **/
webpack: (config, { isServer }) => {
if (!isServer) {
// set alias of node specific modules to false
// eg: service dependencies
config.resolve.alias = {
...config.resolve.alias,
'firebase-admin': false,
}
} else {
// set alias of browser only modules to false.
config.resolve.alias = {
...config.resolve.alias,
}
}
While this does the trick, it won't be much long until the process gets really tedious to include all such dependencies within resolve aliases.
So, my approach to this is to write a script that runs prior to npm run dev (or manually) that will read all dependencies in package.json and SOMEHOW identify packages that will not run on a specific runtime environment and add them to the webpack config. In order to this, there should be a way to identify this nature of each dependency which I don't think is something that comes right out of the box from npm or the package itself.
Any suggestion on how this can be achieved is really appreciated. Thanks`

Meteor / NodeJS run own code before migration start (Meteor startup)

is there a possibility to execute own code inside a Meteor / Node application before the migrations run?
I know about Meteor.startup but this code runs after the DB Migrations afaik.
Edit: The migrations package i use idmontie:migrations#1.0.3
The migration package you use doesn't seem to support that. If, however, you are able to switch to the more common percolate:migrations then you can fully control when the migration happens, because you actually need to call it explicitly, e.g.,
Meteor.startup(() => {
/* the code you want to run first here.. */
Migrations.migrateTo('latest');
});
In the past, I've even done things like this, where I was running some code between migrations to certain versions:
Meteor.startup(() => {
/* some code to run before ... */
Migrations.migrateTo(3);
/* some code to run in between... */
Migrations.migrateTo(5);
});

how to test Cloud Functions for Firebase locally on pc

Today Firebase released its brand new product Cloud Functions for Firebase and I just created a hello world function and deploy it on my existing firebase project.
It looks like it bundles all dependencies and upload it to firebase just like aws lambda function does. But it takes too much time to be done even on minor changes in code and also need a good connectivity of internet . If you are offline for some reason, you are just in dark what code you are writing until you have a way to execute and test that functions offline on your local machine.
Is there any way to test Cloud Functions for Firebase locally?
firebaser here
Deployment of your Functions indeed takes more time than what I'm normally willing to wait for. We're working hard to improve that and (as Brendan said) are working on a local emulator.
But for the moment, I mostly write my actual business logic into a separate Node script first. That way I can test it from a local command prompt with node speech.js. Once I'm satisfied that the function works, I either copy/paste it into my actual Functions file or (better) import the speech module into my functions file and invoke it from there.
One abbreviated example that I quickly dug up is when I was wiring up text extraction using the Cloud Vision API. I have a file called ocr.js that contains:
var fetch = require('node-fetch');
function extract_text(url, gcloud_authorization) {
console.log('extract_text from image '+url+' with authorization '+gcloud_authorization);
return fetch(url).then(function(res) {
return res.buffer();
}).then(function(buffer) {
return fetch('https://vision.googleapis.com/v1/images:annotate?key='+gcloud_authorization, {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
"requests":[
{
"image":{
"content": buffer.toString('base64')
},
"features":[
{
"type":"TEXT_DETECTION",
"maxResults":1
}
]
}
]
})
});
}).then(function(res) {
var json = res.json();
if (res.status >= 200 && res.status < 300) {
return json;
} else {
return json.then(Promise.reject.bind(Promise));
}
}).then(function(json) {
if (json.responses && json.responses.length && json.responses[0].error) {
return Promise.reject(json.responses[0].error);
}
return json.responses[0].textAnnotations[0].description;
});
}
if (process.argv.length > 2) {
// by passing the image URL and gcloud access token, you can test this module
process.argv.forEach(a => console.log(a));
extract_text(
process.argv[2], // image URL
process.argv[3] // gcloud access token or API key
).then(function(description) {
console.log(description);
}).catch(function(error) {
console.error(error);
});
}
exports.extract_text = extract_text;
And then in my Functions index.js, I have:
var functions = require('firebase-functions');
var fetch = require('node-fetch');
var ocr = require('./ocr.js');
exports.ocr = functions.database().path('/messages/{room}/{id}').onWrite(function(event) {
console.log('OCR triggered for /messages/'+event.params.room+'/'+event.params.id);
if (!event.data || !event.data.exists()) return;
if (event.data.ocr) return;
if (event.data.val().text.indexOf("https://firebasestorage.googleapis.com/") !== 0) return; // only OCR images
console.log(JSON.stringify(functions.env));
return ocr.extract_text(event.data.val().text, functions.env.googlecloud.apikey).then(function(text) {
return event.data.adminRef.update({ ocr: text });
});
});
So as you can see this last file is really just about wiring up the "worker method" ocr.extract_text to the database location.
Note this is a project from a while ago, so some of the syntax (mostly the functions.env part) might have changed a bit.
firebaser here
To debug your Cloud Functions for Firebase locally, there is an emulator. See the documentation for more info.
run and debug/inspect functions locally
prerequisites (google-cloud functions and firebase-specific):
npm install -g #google-cloud/functions-emulator
npm install --save firebase-functions
npm install -g firebase-tools
To run and inspect/debug: first run functions locally, then inspect each function, and finally run each specific function to debug+inspect it. Use functions start as an alternative to firebase serve and note the documentation for each tool is available (and useful).
To run and debug the specific function myFn as-expected (eg in Nodejs via chrome://inspect and note this works using Nodejs v10 though not officially supported):
firebase serve --only functions
functions inspect myFn
functions call myFn # or call from browser
additional documentation:
https://firebase.google.com/docs/functions/local-emulator
https://cloud.google.com/functions/docs/emulator#debug-emulator
https://github.com/GoogleCloudPlatform/cloud-functions-emulator/wiki
>> Is there any way to test Cloud Functions for Firebase locally?
You can use the following command to start a firebase shell (execute in your functions directory):
npm run build && firebase functions:shell
You can invoke your functions in the shell like so:
helloWorld()
Refer this link for more information.
Answered here: https://github.com/firebase/firebase-functions/issues/4#issuecomment-286515989
Google Cloud Functions also open-sourced a local emulator, and we are
working to build a tighter integration with Cloud Functions for
Firebase. In the meanwhile, you can check it at here:
https://github.com/GoogleCloudPlatform/cloud-functions-emulator/
The emulator does allow you to run functions locally. Here's the
documentation that explains how to use it:
https://cloud.google.com/functions/docs/emulator
I couldn't get the single stepping working at first. My process was the same as documented in many answers here.
Also, these pages contain nearly all the documentation I required:
https://firebase.google.com/docs/functions/local-emulator
https://cloud.google.com/functions/docs/emulator#debugging_with_the_emulator
I had got the functions running using firebase serve --only functions, but hadn't got the debugger up and running. Then I came across the other way of directly using the emulator and managed to hit a break point like this:
# start the emulator
functions start
# allow inspection
functions inspect helloWorld
# call the function from the cli
functions call helloWorld
This worked, and I could hit a breakpoint.
However, when hitting the endpoint for the function in postman or the browser, I got no response at all.
The step I was missing was:
# deploy the function to the emulator
functions deploy helloWorld --trigger-http
# you need to toggle inspection after the deploy
functions inspect helloWorld
Now I can hit the endpoint for the function from postman or the browser, and the breakpoint is hit.
I recommend the brilliant NiM chrome extension for debugging and hope this answer helps someone, even if this is an old question.
Firstly, I suggest you to install following dependencies,
npm install --save firebase-functions
npm install -g firebase-tools
If already installed then you can update it to latest one. Generally, functions-emulator comes with above dependency but still I would recommend you to update it,
npm install -g #google-cloud/functions-emulator
Once it has been updated, go to functions folder of you application and run following command,
firebase serve --only functions
I hope it helps!
For vscode users debugging HTTP functions (webhooks, etc)...
The google cloud emulator (firebase serve --only functions) launches a separate process to run your functions. You can attach to this process with vscode, but since the emulator only creates this process after the first function is called, it's not straightforward.
create a dummy HTTP endpoint in your functions which will return the processID:
app.get("/processid", function(request, response) {
response.send(`${process.pid}`);
});
start the emulator with firebase serve --only functions
call the http://<localhost_url>/processid endpoint. This will create the process and return the processID
use vscode to attach to the specified process. You can now set breakpoints, step, etc on any of the other functions (they all use the same process).
There's probably a nicer way to glue all this together.
There is now a cloud functions emulator that lets you call functions locally
Once I have completed my PoC I will update this answer to include code and steps I used.

Correct configuration with Gulp, Mocha, Browserify to execute client side test with server side tests

I'm working on a node application utilizing gulp for our build processes and the gulp-mocha plugin for our test-runner.
gulp.task('test', function () {
return gulp.src(TESTJS)
.pipe(mocha({reporter: 'spec'}))
.on("error", function (err) {
// handle the mocha errors so that they don't cloud the test results,
// or end the watch
console.log(err.toString());
this.emit('end');
});
});
Currently TESTJS is only my server-side tests. I am wanting to use this same process to execute my client tests as well. I looked into gulp-blanket-mocha and gave it a shot but I keep running into the same issue. When trying to test my backbone code, it fails because the other client components necessary (namely jquery) are not found by the test runner and it fails. I get that I need to use some sort of headless webkit like phantomJS. But I am having real trouble figuring out how to incorporate that into this gulp process with browserify.
Anyone tried getting a setup like this going or have any ideas what I am missing here in terms of having my gulp "test" task execute my client side mocha tests as well as my server side?
A potential setup is :
Test runner - this is the glue between gulp and karma and provides option to set the karma options.files with the gulp.src() stream. Frankly if you have no steps before your karma tests, then use karma directly within gulp task, without gulp plugin.
Use associated karma plugins, to run on phantom/chrome/firefox
Use associated karma plugins for coverage, alt-js compilation
More plugins & configuring karma options for reporting of tests and coverage.
Using browserify will change the whole setup above.
Since it needs to resolve requires, it must run on all the "entry point" files. Typically your tests should require sources, and must be entry points.
Use karma-bro - it solves the problems in karma-browserify (ATM this doesnt even work - it cant work with bfy 5.0 api) & karma-browserifast.
Coverage becomes tricky since sources/vendor-sources/tests are all bundled. So I had created a custom coverage transform, that marks which code whould be instrumented while bfy is bundling
browserify should be a "preprocessor" in karma.
A bunch of "transform: []" should be configured in browserfy options
The transforms can be configured by taking an existing transform module and wrapping with a custom module like what I did above for browserify-istanbul

How can I set up a node app (ember app kit) on heroku that reads ENV variables and makes the values available to the application?

Okay, I'm new to node, and really only just using the node server to serve static js, but I can't find any info on this anywhere.
I'm running an application ember app kit, which gets built to a node server.js for deploy, and heroku runs it with node server.js.
It uses grunt for building, testing, etc.
I'd like to know how I can specify configuration variables (i.e. authentication tokens) that can be overridden by heroku config variables.
The closest I've been able to get is a custom task that reads environment variables and writes out a json file that gets built into the site (and assigned to a global var). This works locally, but doesn't take into account heroku configs.
I even wrote a deploy script that gets heroku's configs, exports them as environment variables locally, and does the build--Which works, but the configs only get updated on app deploy. So if I do a heroku config:add CONFIG_TEST=test_value, my app doesn't see that value for CONFIG_TEST until the next time I deploy the app.
I'd like for my app to start embedding that config value in the browser JS immediately.
Any way to do this with node the way my app is set up?
I am not sure I understand what's wrong with simply taking config variables, at run time, from the environment. Use process.env.KEY in your code, and embed that result into whatever template you may have, and serve that as the result.
When you change Heroku config variables your process gets restarted, so it picks up the new values.
Is the problem the fact that you serve static files? If so -- can you simply change it so that you use a template engine to do some processing on them before serving?
OK, here's a solution for ember-app-kit using grunt-sed.
In EMBER_APP_KIT_PROJECT/tasks/options/sed.js
Add something like
module.exports = {
version: {
path: "./dist/",
pattern: '{{env.API_BASE_PATH}}',
replacement: function(){
return process.env.API_BASE_PATH;
},
recursive: true
}
};
then in your code just put
"{{env.API_BASE_PATH}}"
Now, when you run
$ grunt sed
it will replace "{{env.API_BASE_PATH}}" with whatever's in the environment variable.

Resources