martedì 20 ottobre 2015

Using git push to deploy

Using git push to deploy

Git is extremely useful as a versioning system, but it could be used to simplify deploy process: you can configure a repository to execute operations on push received. This way, when you push you commits, you can also trigger a deploy operation!
Here it is a short how-to guide.

Create a directory to use as a git remote repository

Go on your production machine. Create a directory that will be used as a remote repository, the one that will receive you push. Append .git to your directory name to mantain a usual name-convention. We decide to deploy an application called "mountain":

cd /home/myuser/
mkdir mountain.git
cd mountain.git

Initialize a bare repository

There is a very interesting and quick to be read article which explains what is a bare repository and what is a standard repository, but to say it even quicker, a standard repository is a "working" repository (where you can perform common versioning operations) while a bare repository is a repository that works as a remote origin and is used only to be read from other repositories. We need to create a bare repository to receive push, so:

git init --bare

This command will create a non-common git structure.

A note about this repository: we could have created a standard repository and then initing it as a bare repository, but then we should have added a special configuration. This article explains pros and contros

Create a new git repository where a new working copy will be checked out on every push (the deploy directory)

Now create a directory where the project will be checked out any time a push will occur. This will be the deploy directory. So, create the directory, cd in and git clone the previously created repository:

cd /home/myuser/
mkdir mountain
cd mountain
git clone myuser@localhost:/home/myuser/mountain.git

Modify hook to execute commands on push

Now we will go back to our mountain.git repository and add a hook to execute commands when we receive push. After a push (on post-received) we will checkout the master branch to the deploy folder and can executa any command, such starting nodejs (this is an example where we restart a nodejs server application invoking a script but you can do whatever you want to do):

cd /home/myuser/mountain.git
cd hooks
touch post-receive
chmod +x post-receive
vi post-receive

and now we insert this commands:

#!/bin/sh
GIT_WORK_TREE=/home/myuser/mountain git checkout -f
cd /home/myuser
./nodejsStarter.sh

GIT_WORK_TREE is a command!!! I didn't know it and had to dig a lot to understand it! But this is the magic command that executes a checkout after the push.

Add the new remote to your working copy project

In your working copy, you must add the newly created remote so you will be able to push to it. So, go inside your working copy directory (where you develop the project) and add the remote reference. Here it is and example where we add the "production" remote to our repository :

git remote add production myuser@192.123.123.123:/home/myuser/mountain.git

If you do something wrong, use "git remote rm production" to remove remote reference and "git remote" to check references

The end!

Now everything should work well: when you git push to the "production" reference, the deploy dir containing a repository is updated by the post-receive hook.

Now that you have read my article, i would like to show you another thing: i've developed an app to help increase customers registration and customers conversion.

You can find it at appromocodes.com

sabato 23 maggio 2015

Grails and Groovy xml marshalling and unmarshalling

Grails and Groovy xml marshalling and unmarshalling

Converting JSON to a map object is a very simple task to perform in Groovy. But what if you need to marshal and unmarshal xml?
I will show a simple way on how to do it.
Suppose we have a reservation xml we want to marshal:

<ns2:roomReservation xmlns:ns2="http://an.address.com/">
    <customerId locale="en_US">F3F0C7</customer>
    <itineraryId>205216012</itineraryId>
    <rooms>
      <room>301</room>
      <room>302</room>
    </rooms>
    <info>
      <start>2015-05-23</start>
      <end>2015-05-26</end>
    </info>
</ns2:roomReservation>

Ok now we must define classes to marshal xml to. Let's define a RoomReservation groovy class which must implements Serializable

package com.test.a
import javax.xml.bind.annotation.*

@XmlRootElement(name="roomReservation", namespace="http://an.address.com/")
@XmlAccessorType(XmlAccessType.FIELD)
class RoomReservation implements Serializable {

@XmlElement String customerId
@XmlAttribute String locale
@XmlElement long itineraryId
@XmlElement(name="rooms") List<Room> roomList
@XmlElement(name="info") Info info
}

Let's have a look at this class: this class bind roomReservation tag to this class and maps all the fields within.
Any attribute is mapped by @XmlAttribute annotation and the rooms tag is mapped as a List (roomList groovy property).
Pay attention!!! Any time you define a non simple Object or type property, you must use (name="xmltag") to map it to your specific class such as for Info class and List.

Now let's have a look at our Info class:

package com.test.a
import javax.xml.bind.annotation.*

@XmlRootElement(name="info")
@XmlAccessorType(XmlAccessType.FIELD)
class Info implements Serializable {

@XmlElement String start
@XmlElement String end
}

Now that we have mapped our structures, we can unmarshal xml this way:

String xml
...
... //we omit how to get xml but it will be stored in xml variable
def jaxbContext= JAXBContext.newInstance(RoomReservation.class)
def unmarshaller = jaxbContext.createUnmarshaller()
RoomReservation roomReservation = unmarshaller.unmarshal(new StringReader(xml))

or marshal this way (using the RoomReservation already defined and populated):

def jaxbContext = JAXBContext.newInstance(RoomReservation.class)
def marshaller = jaxbContext.createMarshaller()
StringWriter writer = new StringWriter();
marshaller.marshal(roomReservation, writer)
String xml = writer.toString()

So this is a very simple way to marshal and unmarshal xml to Groovy objects.

Now that you have read my article, i would like to show you another thing: i've developed an app to help increase customers registration and customers conversion.

You can find it at appromocodes.com

domenica 1 febbraio 2015

iOS8 UIWebView how to avoid crash when adding video tag

iOS8 UIWebView how to avoid crash when adding video tag

Even if you are building a native app, UIWebView is often one of the most used components. The reason is it allow to inject into your app the flexibility of html.

iOS8 has introduced a new kind of web view, one that should bring javascript performances to a higher level: this component is called WKWebView.

This in theory...yes, because UIWebView is still a work in progress and for example, is unable to load local html files and resources! Yes, i know it sounds absurd but this is the truth (just goole a bit...).

iOS8 has also broken UIWebView and now there is a list of bug which were introduced in UIWebView exactly in iOS8.

One of the most annoyance is the one that may crash your app when loading many files (css, js, etc...) or when loading big files (for example when you load a video).

You start by getting this runtime exception:
WebThread with EXC_ARM_BREAKPOINT

then if you enable Zombie tracking you get this message:
[UIViewAnimationState release]: message sent to deallocated instance 0x14deff70

Here are two possible solutions:
  • replace UIWebView with WKWebView: this is an easy task when you load non-local html pages because WKWebView API is quite the same of UIWebView. WKWebView doesn't suffer of the UIWebView bug when loading many or big files, but if you need to load local file you have to implement a local webserver (most of the people uses GCDWebServer) and move your files to a temporary dir and serve them.
  • inject resources via javascript, on webViewDidFinishLoad method
In this post we will use the second method and here is the workaround:
  • we have our webView which loads our local html page
  • within our page we define a div we will populate with our video tag
  • in the html page we define a javascript method which inject the video tag in the div we dedicated to video tag
  • we invoke this method via webViewDidFinishLoad delegate method
This method let us avoid the bug.

Here is the code.

in our controller we define our webview and its delegate (i omit these details) and the we load the html page:

- (void)loadWebView {   

    [self.webView setDelegate:self];

    self.webView.scrollView.bounces = NO;

    // Remember that bundle resources do *not* have directories so all filenames must be unique.

    NSBundle *mainBundle = [NSBundle mainBundle];

    NSURL *homeIndexUrl = [mainBundle URLForResource:@"index" withExtension:@"html"];

    NSURLRequest *urlReq = [NSURLRequest requestWithURL:homeIndexUrl];

    [self.webView loadRequest:urlReq];

}

We have this delegate method:
- (void)webViewDidFinishLoad:(UIWebView *)webView

{

    [self.webView stringByEvaluatingJavaScriptFromString:@"placeVideoTag();"];

}



This is an extract of our index.html (we use jquery but this is obviously optional);


...
... ... ...

As you can see our placeVideoTag method will be called by objective-c and not by the html page (which would generate the exception due to UIWebView bug) and it inject a video and an audio tag in the page.

This solution avoid the bug.

Now that you have read my article, i would like to show you another thing: i've developed an app to help increase customers registration and customers conversion.

You can find it at appromocodes.com