Sunday, November 27, 2016

Beware - forever list vs sudo forever list are not the same

A few days back I noticed that my Pub/Sub Listener (a node.js script that listens for events and routes data to my Datastore) for Google Cloud Platform (GCP) was behaving badly. I had recently deployed some updated Listener logic which was being bypasses altogether.

My Pub/Sub Listener were "kept alive" using the Forever npm module, as I was working on a GCP Compute Engine, I was using sudo to run all my commands.

So I launched my Pub/Sub Listener using:
sudo forever app.js

To debug the issue, I ran the following to stop all my Forever scripts:
sudo forever stopall

And verified this by doing:
sudo forever list

It shows an empty list. So what was wrong? It seemed as be as though Forever was running some hidden processes and my Pub/Sub listener was still running.

After a bit of digging around, it seemed as though, sometime in the past I had launched my Pub/Sub Listener using
forever app.js

So what was the problem?

Well my scripts were running as both root user and my user permissions, and were essentially duplicated.

As you can see:



So to fix this, just stopall on your root account.
forever stopall

And make sure you only run your Forever script using the correct user permissions.

Happy Coding!


Thursday, June 30, 2016

Pushing a Dokku App from Multiple Computers and Fixing the "Could not read from remote repository" Error

I use Dokku to push the multiple Micro Services that power my blog www.wisdomtoinspire.com (which are hosted in a Digital Ocean server)

Dokku uses Docker and is a Free open source Heroku alternative which makes a Microservices architecture possible

Initially, I worked mostly on single computer which I used to set up Dokku on Digital Ocean and set my initial SSH keys etc

Recently I wanted to push a new Micro Service (which is deployed via Dokku on my digital Ocean machine) on a different computer but I ran into multiple issues.

  • I assumed that all I had to do was clone the GIT repo, set my Dokku remote (after creating a Dokku App on the server) and then pushing via "git push dokku master"
  • But I could not access the server. So I create a new SSH key with the same email I used previously when I set up the server and stored it in "id_rsa.pub"

I then SSHed into my Digital Ocean machine, and manually copied the new SSH into ~/.ssh/authorized_keys and then assumed I need to copy it into /home/dokku/.ssh/authorized_keys as Dokku might use it. I also switched to the "dokku" user (using "su dokku") and added the key to "~/.ssh/authorized_keys"

Assuming this would fix the issues I was having trying to push my app to the Dokku remote, I pushed via "git push dokku master"

And kept getting this error:
fatal: 'appname' does not appear to be a git repository
fatal: Could not read from remote repository.

I then dug around and came across these issue on Dokku's Github:
https://github.com/dokku/dokku/issues/1608 (Gitreceive doesn't work)

This comment struck out:
"Guess there was a bug in how you initially setup your keys. The dokku user is meant to be managed solely by sshcommand, and you aren't supposed to "ssh" in as that user, hence why things seemed to break for you."

Basically, it means that I should not try and add new SSH keys like the way I did. Instead I should remotely do it from my machine like it's mentioned in this article https://www.digitalocean.com/community/questions/dokku-add-new-ssh-key

i.e. I undid all those manual keys I manually copied in my Digital Ocean server and from my local computer I ran this:

cat /path/to/public_key | ssh root@yourdokkuinstance "sudo sshcommand acl-add dokku [description]"

Read more here (in the SSH command part)
http://off-the-stack.moorman.nu/2013-11-23-how-dokku-works.html

Now when you try "git push dokku master" it should start pushing your app to Digital Ocean using Dokku.

But I then ran into this issue:

 ! [remote rejected] master -> master (pre-receive hook declined)
error: failed to push some refs to 'dokku@wisdomtoinspire.com:thumby'

:(

But I knew the above "pre-receive hook declined" usually appear when something goes wrong with the install and launch via npm. So I just enabled Dokku tracing like so "dokku trace off" (http://dokku.viewdocs.io/dokku/troubleshooting/) and fixed all my issues and my Service was good to go!

Hope this helps someone.

Happy Coding!


Wednesday, June 1, 2016

Undo/Reset last GIT Commit Locally and Remotely

If you are like me and you fork some project, make a bunch of changes and commit to your local and remote repositories only to discover that you pushed changes that should not go in.

Then here is a quick way to undo to a specific commit locally and then push that to the remote branch.


Keep in my mind that by doing this you will lose your local work (i.e. the work you want to undo) so only do this if you don't care about the work you did before you pushed the new commit.

First, find out the commit SHA you want to reset to. In Github you can get this like so:

Grab the SHA of the commit to want to go back to



In you command line run these commands one by one.
git reset --hard 0415b7a2bf2517f37f662e063ffee36706554d8f
git push --force

The reset syntax is basically:
git reset --hard target-commit-SHA (grab the full SHA by clicking the link in green above)


Your repos (local and remote) should now have gone back to the point you wanted it to.

Use at your own risk!! :)

Wednesday, May 18, 2016

Adding a "ref" to a Dynamically Inserted Child Component in React

I was working on a wizard type multi-step component for a React Application I was building (the component is called react-stepzilla in case you are interested in it)

It basically let's you throw a bunch of Child Components at it and it will take the user through those Components in a wizard type journey.

So basically it lets you build something like this.


Figure 1: react-stepzilla component look


The obvious use case for this would be to collect information from the user and validate that information as you go.

In this example, you initialise, declare and render the Component in your App (something) like this:

import Step1 from './Step1';

import Step2 from './Step2';

import StepZilla from 'react-stepzilla'

...

const steps =

    [

      {name: 'Welcome', component: <Step1 />},

      {name: 'Personals', component: <Step2 />},

      {name: 'Emergency', component: <Step3 />},

      {name: 'Medical', component: <Step4 />},

      {name: 'Review', component: <Step5 />}

    ]

...

render() {

    return (

        <div className='step-progress'>

            <StepZilla steps={steps}/>

         </div>

    )

}

and the outcome would look like figure 1.

As I was building this I hit a roadblock. Some of my Child "Step" Components (e.g. Step2) was a form that needed to be validated before we can move on to the next Step (Step3).

My Step2 Component exposed a public method called "isValidated()" which runs the entire form through validation and then returns a true/false indicator on validation state.

But Step2 was a Child Component to my StepZilla Parent Component and I didn't have access to any of it's methods via 'this.props.children' which is how I thought you should (I am fairly new to React I should add) but then I read that this is not possible (read https://facebook.github.io/react/tips/children-undefined.html)

I needed someway to reach into my Child Step2 Component and invoke isValidated() before continuing.

Upon further reading "refs" seemed to be the facility given by React to reach into Child Components (read https://facebook.github.io/react/docs/more-about-refs.html) and this seemed like the way I should do this.

But "refs" can only be declared to a Child Component in the render() method of the Parent Component. In the StepZilla Parent I was passing in a array of Child Components which was then injected into the Parent Component (something) like this:

import React, { Component, PropTypes } from 'react';


export default class StepZilla extends Component {

    ...

      _next() {

            // move to next step (if current step needs to be validated then do that first!)

            if (typeof this.refs.activeComponent.isValidated == 'undefined' ||

                this.refs.activeComponent.isValidated()) {

          

                    this._setNavState(this.state.compState + 1);

            }

      }

    ...

    render() {

        return (

            {this.props.steps[this.state.compState].component}

        )

    }

    ...

}

So I needed someway to intercept this injection and append a "ref" to the component so I can then reflect of it's validation state later on (in _next() method).

After much digging around I came up with a solution. Which is basically to clone the Child React Element and then append a "ref" to it. This was how I made it work.
export default class StepZilla extends Component {

    ...

    render() {

        const compToRender = React.cloneElement(this.props.steps[this.state.compState].component, {

            ref: 'activeComponent'

            }

        });

    return (

        {compToRender}

      )

    }

}

And this works in my situation!

A few notes relating to this design approach:
  1. Ideally in React you should not "reach into" Child and Parent Components as this goes back to a imperative modal of coding which React is trying to take us out of. But in some situations you cant avoid this. I did think of doing the above using "events" but it didn't make sense to me to overcomplicate this use case.
  2. I believe React.cloneElement does a "Shallow Clone" so it may have some adverse effects (which I still have not encountered but we cant rule it out)

Hope this helps.

Happy React Hacking!

Thursday, April 28, 2016

Using Webpack to Copy Static Files to your Build Folder

This article is relevant for: 
- node 5.8.0
- npm 3.7.3
it may or may not work for other versions.


I've recently started doing a lot of work with React and React Native. I created a React Native Starter kit  that uses webpack as the Module loader. I actually use Grunt and the "grunt-webpack" plugin but the build process uses webpack to bundle my distribution (production build).

I am fairly new to webpack so last week I hit a roadblock. I wanted to include a link to a "apple-touch-icon" static image on my app homepage so that a user can add a "shortcut" icon on their iOS device home screen. Basically I wanted to "Appify" my React App like so:

I wanted to reference this image in my homepage so that I can Appify my React App on iOS
If you have not done this before with your web apps, it's very easy to do. Basically you just create a link tag like so and put it on your homepage:

<link rel="apple-touch-icon" href="/assets/lifeletters-app-logo.png">

You will also need to add the following tags as well:

<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">

Like so:

I put this simple link tag to reference the iOS app icon image

So basically when I hit my "build" task webpack bundles all included resources (js, images, css etc) and puts it into a "dist" folder which I then deploy as my app build. But I needed webpack to pick up the "company-webapp-logo.png" and copy it to the "dist" folder as well so my "dist" folder looks like this:

I needed my "dist" folder to look like this

Unfortunately webpack only infers my JavaScript code and copies resources it finds there. I needed a way to copy "static"files over to my build folder as well. A task like this is veryeasy to do in a system like Grunt, but I wanted to stick to webpack as eventually I want to move away from Grunt.

I tried multiple webpack loaders like the webpack file loader but I could not get a simple copy to work. (with the file loader I managed to get the PNG image moved but the image got corrupted)

After more digging around I cam across the copy-webpack-plugin so I gave it a go.

And Bingo! I got the job done.

It's basically a very basic plugin to copy static file/folders to your build destination. Here is how you would configure it in your webpack config file.

Here is how you configure the copy-webpack-plugin plugin in your webpack config file

Initially I had my doubts that it would work as I was using the Grunt webpack module, but it still did.

I use webpack as part of a Grunt workflow like so...

This is a very basic workflow example but hopefully it will help some new starters to webpack.

If you have a better way to do it please let me know in the comments.

Happy Coding!

Sunday, April 17, 2016

Changing the "Entry JavaScript File" for your React Native iOS App

This article is relevant for: 
- node 5.8.0
- npm 3.7.3
- react-native-cli 0.1.10
it may or may not work for other versions.


So I've entered the world of React Native. I've been spending the last couple weeks working on a React Native Started Project for a Start Up i've working with. There are plenty of starter projects out there for React Native but I needed something that supports a Web App (built using React) and iOS and Android apps as well. The final solution should be able to compile into a Web, iOS and Android with as much code reuse as possible. (Obviously we cant have full code reuse as the UI screens will need to be different across the platforms, but most of the Business Logic can be shared)

As I wrote the Started Project, I wanted to refactor my code so that all my "Entry Point Code Files" reside in the same "src" directory. This makes the Project Structure clean and readable.

Entry Point Code Files as basically the first files that are loaded into the iOS, Android compilers.

So I wanted to have this clean structure:



But when you create a new React Native Application, you will notice that the default scaffold puts the index.ios.js and index.andriod.js files into the root like so:



As I moved these files into my "src" folder and I tried to build and run my iOS app using XCode I got this ugly error:

"Cannot find entry file index.ios.js in any of the roots" Error

I dug around and it seems as though the location of my index.ios.js was hardcoded into a file within the scaffold. I found this unusual and looked for a way to "programmatically" change the location of my file (instead of updating the core scaffold files in the "ios" directory), unfortunately I could not find a solution.

So I hacked the scaffold files to update the starter file location. This is not my preferred method but I had to get it working (If there is a better way to do this then please let me know in the comments below)

So what do you need to do to update the Starter File location for iOS?

1) In your "ios" directory locate the "AppDelegate.m" file which should be in a folder with your app name. For me it was here:



2) In that file, locate the line assigning the "jsCodeLocation" variable and update the location of the file. So change it to be like so (I've basically added the "src" folder to the string):

Click on the image to view a larger version


And we are done!

3) Close your XCode project and reopen it and when you start the app it should now work :)

It's a dirty hack and not my preferred way to so this, but until there is a official clean way to do it, it will have to do.

______________________________________________________________________
Update (25/07/2016):
In projects where I used the above method to move my index.ios.js file to a "src" folder I recently started getting the below error as I wanted to run my app in my iPhone (using local provision profiles to deploy and test my apps on my actual iPhone)

"Cannot find entry file index.ios.js in any of the roots:"... "Command /bin/sh failed with exit code 1"

I dug around and worked out that at times the none_modules/react-native/packager/react-native.xcode.sh file was still referencing the entry file as index.ios.js from the root.

Towards the bottom of this file I had to make the below change to get it working:
$NODE_BINARY "$REACT_NATIVE_DIR/local-cli/cli.js" bundle \ 
--entry-file src/index.ios.js
--platform ios \ --dev $DEV \ 
--bundle-output "$DEST/main.jsbundle" \ 
--assets-dest "$DEST"

This is so Hacky I know! but React Native seems to have all these weird issues. Hopefully it matures soon.

Tuesday, October 20, 2015

A Simple Shell Script to Generate a Manual tar.gz Build File of Your NodeJS App

Hello my fellow Code Junkies...

Who doesn't love to Shell Script??


In most of my current projects I use Dokku, which let's me deploy new versions of my NodeJS app to Production using a git push. If you have not heard of Dokku (Which is basically a Heroku Clone), you should as its pretty cool.

But I also have a bunch of Projects where I need to create a manual build of my App and then copy it to my server, unpack it and run it. I'm sure many of you do this as well.

To streamline this manual build process, I include a standard Shell Script (.sh) file in all my Projects. When you run it, it reads in your package.json file, extracts the "name" and "version" values and creates a .tar.gz build for you (thats a GZIPed Tar File) and puts it in a builds/ directory.

So basically as you work on a new version of your App (and you increment your version number in package.json) and you are ready to deploy it, you just run the Shell Script and it generates a tar.gz file for you with the naming convention appname-version.tar.gz and puts it in a builds/ directory.

e.g. myapp-0.0.1.tar.gz

To keep your build clean, the script ignores the "node_modules/" and "builds/" folders.

Copy the Shell Script below and include it in your Project and then run it in your Terminal like so:

. make_build.sh

... or better yet, include it in your package.json under the "scripts" section like so:

"scripts": {

    "start": "",

    "test": "",

    "makebuild": ". make_build.sh"

}

... and then run it like so from terminal:

npm run makebuild

Here is the source for make_build.sh:

#!/bin/bash
# Generate a tar.gz build using name and version from package.json
# In your app root you need a builds/ directory, this is where your tar.gz file will be placed. Or change this location in line 25
# The script will ignore your node_modules and builds folders

# get app name from package.json
name=`grep "name" package.json | sed 's/,//g'`
name=`sed 's/"name"://g' <<< $name`
name=`sed 's#"# #g' <<< $name`

# get app version from package.json
version=`grep "version" package.json | sed 's/,//g'`
version=`sed 's/"version"://g' <<< $version`
version=`sed 's#"# #g' <<< $version`

# append them both and remove all whitespace and append .tar.gz to the file name string
filename=$name"-"$version
filename=`sed 's/ //g' <<< $filename`
filename+='.tar.gz'

echo "--------------------------"
echo "lets make a new tar.gz"
echo "--------------------------"

# create the new tar.gz in your builds/ folder (exclude node_modules folder)
tar -zcvf "builds/"$filename --exclude "node_modules/" --exclude "builds/" *

echo "--------------------------"
echo "created new build tar.gz with filename = "$filename
echo "--------------------------"


Or grab the Gist from here if your prefer:
https://gist.github.com/newbreedofgeek/db2b3fc1fc0cac592173


Happy Coding!

Fork me on GitHub