Συνδέοντας το git με τον apache σε ubuntu server

May 11th, 2010

Καθώς μεγαλώνει η ομάδα του social whale, και ταυτόχρονα οι απαιτήσεις (βλ. διαγωνισμός vodafone), αρχίζει η ανάγκη για version control system. Έτσι αποφασίσαμε να πειραματιστούμε με το git σε έναν Ubuntu server.

Έτσι, ξεκινώντας από το 0 και με σύμμαχο το google, αρχίσαμε τα tests. Όποιο tutorial και να βρίσκαμε δεν είχε ακριβώς αυτό που θέλαμε να πετύχουμε. Πιο συγκεκριμένα θέλαμε, όταν κάνει μια αλλαγή κάποιος developer/designer και την ανεβάζει στο repository, αυτόματα να μπορεί να βλέπει την αλλαγή σε ένα dev url. Η λύση που σκεφτήκαμε ήταν να φτιάξουμε ένα client που έκανε αυτόματα sync από το repository και ταυτόχρονα να είναι το virtual host που βλέπει ο apache. Αυτό το πετύχαμε με ένα hook στο repository, ώστε σε κάθε update που δέχεται να κάνει sync τον client του apache. Ας το δούμε στην πράξη:

1. Εγκατάσταση του git στον server (ip: 192.168.0.2)
user@ubuntu_server: sudo apt-get install git-core

2. Δημιουργία ενός git share repository στον server
user@ubuntu_server: sudo mkdir /myapp.git
user@ubuntu_server: sudo chown user:group /myapp.git
user@ubuntu_server: cd /myapp.git
user@ubuntu_server: git --bare init

3. Δημιουργία ενός κλώνου του repository για την σύνδεση με τον apache
user@ubuntu_server: cd /var/www
user@ubuntu_server: git clone /myapp.git

Σε μερικές εκδόσεις του git (πχ. 1.4, 1.5) δεν επιτρέπει το clone σε empty repository οπότε πρέπει να δημιουργήσουμε ένα empty και απλά να το συνδέσουμε με το master repository.
user@ubuntu_server: cd /var/www
user@ubuntu_server: mkdir myapp
user@ubuntu_server: cd myapp
user@ubuntu_server: git init
user@ubuntu_server: git remote add origin /myapp.git
user@ubuntu_server: git config branch.master.remote origin
user@ubuntu_server: git config branch.master.merge refs/heads/master

4. Σύνδεση του VirtualHost με το clone folder στο DocumentRoot
user@ubuntu_server: sudo vi /etc/apache2/site-enabled/myapp
<VirtualHost *:80>
ServerName myapp.com
DocumentRoot /var/www/myapp
</VirtualHost>

user@ubuntu_server: cd /var/www/myapp
user@ubuntu_server: echo 'MyApp (ver 1.00)' > index.html
user@ubuntu_server: git add index.html
user@ubuntu_server: git commit -a -m 'Add index.html'
user@ubuntu_server: git push origin master

Με την git clone φτιάξαμε ένα κλώνο από το myapp git repository, με την git add προσθέσαμε ένα αρχείο, με την git commit στείλαμε την αλλαγή στο τοπικό μας repository (κάθε clone έχει και δικό του repository), και τέλος με την git push στείλαμε την αλλαγή και στο κεντρικό μας repository. Τώρα αν ανοίξουμε ένα browser και δώσουμε το url του VirtualHost θα πρέπει να εμφανιστεί το “MyApp (ver 1.00)”.

5. Στείνουμε σε ένα ubuntu desktop client το git και κατεβάζουμε (clone) το repository από τον server (desktop ip:192.168.0.3)
user@ubuntu_desktop: sudo apt-get install git-core
user@ubuntu_desktop: git clone ssh://user@192.168.0.2/myapp.git

Ετσι δημιουργήθηκε ένα folder myapp που μέσα έχει την index.html

6. Αλλάζουμε την index.html και την ανεβάζουμε στο repository στο server
user@ubuntu_desktop: echo 'MyApp (ver 2.00)' > index.html
user@ubuntu_desktop: git commit -a -m 'Modify index.html'
user@ubuntu_desktop: git push

Τώρα αν κάνουμε refresh τον browser, θα διαπιστώσουμε ότι δεν άλλαξε τίποτα. Καλά δεν θα ήταν να μας έδειχνε αυτόματα την διορθωμένη index.html; Για να γίνει αυτό θα πρέπει να πάμε πάλι πίσω στον server και συγκεκριμένα στο clone repository που βλέπει ο apache και να δώσουμε:
user@ubuntu_server: git pull

Τώρα στο refresh θα δούμε το αλλαγμένο ver την σελίδα μας.

7. Δημιουργία script για αυτόματο sync του apache από το κεντρικό repository
To git έχει hook scripts που εκτελούνται μετά η πριν από συγκεκριμένες διαδικασίες. Αυτό που θέλουμε εδώ είναι κάνουμε hook το after post.

user@ubuntu_server: cd /myapp.git/hooks
user@ubuntu_server: vi post-update
#!/bin/sh
cd /var/www/myapp
env -i git pull

user@ubuntu_server: chmod +x post-update

Τώρα πάμε πίσω στον client να το δοκιμάσουμε, επαναλαμβάνουμε το βήμα 6 απλά αντί για ver 2.0 βάζουμε 3.0. Στο refresh, η σελίδα μας έχει αλλάξει, χωρίς να δώσουμε git pull στον server, αυτό γίνεται αυτόματα με το hook.

8. Δημιουργία script για αυτόματο push με από κάθε commit
Δεν μας έφτασε αυτό, θέλαμε να αποφύγουμε και το git push στους clients γιατί επειδή είναι με ssh και μας ζητάει password συνέχεια, και όταν υπάρχουν συνεχόμενες αλλαγές (πχ σε ένα css element) είναι πολύ χρονοβόρα διαδικασία. Σκεφτήκαμε ότι θα μπορούσαμε να βάλουμε ένα hook όπου μετά από ένα commit να γίνεται αυτόματα το push. Όλα ωραία στην θεωρία άλλα όταν πας στην πράξη αρχίζουν τα προβλήματα. Το πρόβλημα είναι κάπως πρέπει να δωσεις το password. Η λύση εδώ είναι το expect command line script.

user@ubuntu_desktop: sudo apt-get install expect
user@ubuntu_desktop: cd .git/hooks
user@ubuntu_desktop: vi post-commit
#!/usr/bin/expect
spawn git push
expect "password:"
send "mypass\r"
interact

Δεν πρέπει να ξεχνάμε ότι πριν από ένα commit, push θα πρέπει να έχει προηγηθεί ένα pull.

9. Τελευταίo test
user@ubuntu_desktop: cd ../..
user@ubuntu_desktop: echo 'MyApp (ver 4.00)' > index.html
user@ubuntu_desktop: git commit -a -m 'Modify index.html'

Τώρα αν κάνουμε refresh τον browser, βλέπουμε το ver 4.00, και το έχουμε πετύχει με μόνο μια εντολή την commit.

Νομίζω ότι ένα τέτοιο σενάριο είναι πολύ καλό για δημιουργία projects με πολλούς developers/designers και μάλιστα χωρίς να είναι στον ίδιο χώρο αν ανοίξουμε το http και το ssh στον server.

server , , , ,

Google Maps: Markers σε ομάδες με τον MarkerClusterer

March 8th, 2010

Το παρών άρθρο είναι ένα guest post απο τον Αλέξη Μπρέσσα. Στο άρθρο προϋποθέτουμε ότι ο αναγνώστης γνωρίζει javascript, και θα βοηθούσε να έχει ασχοληθεί με το Google Maps API στο παρελθόν.

Το Google Maps API έδωσε τη δυνατότητα στους web developers να προσθέτουν χάρτες σε ιστοσελίδες, και να “σημαδεύουν” σημεία με markers.
Έτσι, έχει γίνει standard για πολλές κατηγορίες ιστοσελίδων, όπως μεσητικά, κατάλογοι επιχειρήσεων κ.α. ή για τη σελίδα επικοινωνίας εταιρειών.
Εάν όμως οι καταχωρήσεις μιας ιστοσελίδας αυξηθούν αρκετά, τότε τα πολλά markers μειώνουν τη χρηστικότητα ενός χάρτη, ενώ μπορεί κανείς να φτάσει και σε τραγική
κατάληξη όπως αυτή:

Προς μεγάλη ευκολία όποιου αντιμετωπίσει αυτό το πρόβλημα, έχει αναπτυχθεί ένα εργαλείο το οποίο φαίνεται να μην είναι ευρέως γνωστό: το MarkerClusterer.
To MarkerClusterer λύνει το πρόβλημα με το να φτιάχνει ομάδες από markers, όταν αυτά είναι το ένα πολύ κοντά στο άλλο. Το παραπάνω τραγικό παράδειγμα,
τώρα γίνεται πιο συμμαζεμένο, όμορφο, μέχρι και εντυπωσιακό:

Για να δούμε πώς μπορεί κανείς να χρησιμοποιήσει το MarkerClusterer:

function map_init( mapElement ) {
var greece = new GLatLng( 39.1130, 24.0313 );
var thessaloniki = new GLatLng( 40.5408, 23.0480 );

var gmap = new GMap2( mapElement );
gmap.setUIToDefault();
gmap.setCenter( greece, 7 );

// σε αυτό τον πίνακα θα προσθέσεις τα markers που θέλεις
var markers = [];

// εδώ προσθέτουμε markers σε 20 τυχαία σημεία κοντά στη Θεσσαλονίκη
for ( var i = 0; i < 20; ++i ) {
var latoffset = Math.random() - 0.5;
var lngoffset = Math.random() - 0.5;
var latlng = new GLatLng( thessaloniki.lat() + latoffset, thessaloniki.lng() + lngoffset );
var marker = new GMarker( latlng );

// προσθήκη του marker στον πίνακα
markers.push( marker );
}

// δημιουργία του clusterer και προσθήκη των markers στο χάρτη
var clusterer = new MarkerClusterer( gmap, markers );
}

Αρκεί λοιπόν τώρα κανείς να καλέσει τη συνάρτηση map_init με παράμετρο ένα <div> που θα χρησιμοποιηθεί
για το χάρτη. Συνήθως θα καλείται όταν φορτώσει η ιστοσελίδα. Με jquery, αν το div έχει id=”map_canvas”:

$( document ).ready( function() {
map_init( $( 'map_canvas' )[ 0 ] );
} );

Θα πρέπει επίσης να προσθέσετε το javascript αρχείο του Google Maps (με το απαραίτητο key) και του MarkerClusterer
(και βέβαια το jquery αν χρησιμοποιηθεί αυτό) στον HTML κώδικά σας:

<script type="text/javascript" src="http://maps.google.com/maps?file=api&amp;v=2&amp;key=GOOGLE_MAPS_KEY"></script>
<script type="text/javascript" src="http://gmaps-utility-library-dev.googlecode.com/svn/tags/markerclusterer/1.0/src/markerclusterer_packed.js" />

Μπορείτε επίσης να δείτε τον MarkerClusterer εν δράσει στο business catalogue.

Ο MarkerClusterer είναι μέρος μιας βιβλιοθήκης πολλών εργαλείων για Google Maps που ονομάζεται “GMaps Utility Library” και μπορεί κανείς να τη βρει εδώ.

jQuery, javascript , ,

Social Whale Groups jQuery plugin

February 4th, 2010

Όπως θα έχετε διαπιστώσει το SocialWhale είναι το project που αφιερώνω τον περισσότερο χρόνο μου στο development. Αυτό μου δίνει το πλεονέκτημα να ασχολούμαι με πολύ ενδιαφέροντα αντικείμενα (ff extensions, betavine, jquery plugins, api’s κτλ). Έτσι έχω εμπλουτίσει τις γνώσεις μου πάνω στην javascript και ποιο συγκεκριμένα στο jquery framework.

Η συνεισφορά της ομάδας του SocialWhale για το wordcampGR event ήταν και η αφορμή για την δημιουργία ενός jquery plugin (thek27) σε συνδυασμό με ένα wordpress plugin (humanworks) το οποίο παρουσιάζει ένα SocialWhale Group σε ένα widget. Για τους registered χρήστες υπάρχει και η δυνατότητα για vote και post στο group.

Αν και έχω ασχοληθεί παρά πολύ με τα plugins του jquery (ui, autocomplete, bt, fancybox, jGrowl, κ.α.) δεν είχα κάνει ποτέ κάποιο δικό μου όποτε ξεκίνησα από την αρχή, με reverse σε υπάρχοντα plugins και search στο google για tutorials και παραδείγματα.

Αφού βρήκα το skeleton για το plugin η συνέχεια ήταν εύκολη υπόθεση, copy/paste από κώδικα socialwhale, εκτός από 2 σημεία που έπρεπε να βρούμε μια έξυπνη λύση. Το πρώτο ήταν το oauth login που έπρεπε να γίνει από το site του socialwhale και στην συνέχεια να γίνεται redirect πίσω, ώστε να εμφανιστεί η φόρμα για το post και το action για το vote. Το δεύτερο ήταν και το ποιο ενδιαφέρον, γιατί ήθελα να βρω μια λύση με iframe για να αποφύγω το cross site scripting που δεν παίζει με ajax post.

Ας τα πάρουμε από την αρχή, το socialwhale είναι έτσι φτιαγμένο που έχει δικό του api (extended πάνω στο twitter), έτσι για να καταλάβουμε αν ένας χρήστης είναι logged on ελέγχουμε το attribute voted από το json result (πχ groups_api/timeline/both/1.json), και αν αυτό είναι null, τότε δεν είναι, διαφορετικά σημαίνει αν έχει κάνει vote το συγκεκριμένο update. Τώρα για το login απλά φτιάξαμε ένα button στο http://socialwhale.com/oauth όπου το φορτώνουμε με iframe, έτσι όλος ο υπόλοιπος κώδικας βρίσκεται στον server, ώστε να μπορούμε να ελέγχουμε όλα τα widget από ένα oauth login, αυτό του socialwhale. Έτσι αν ένας χρήστης είναι login στο socialwhale, τότε είναι ταυτόχρονα login σε όλα τα widgets  ανεξαρτήτου group.

Τώρα όσο αφορά το submit της φόρμας, σκέφτηκα την λογική του iframe, αλλά με δυναμικό τρόπο, ώστε να έχω και τον έλεγχο του onload event. Ποιο συγκεκριμένα να δημιουργείτε στο runtime ένα iframe με src=”about:blank” και να γεμίζει με την φόρμα που στην συνέχεια γίνεται submit στο socialwhale. Μόλις επιστρέψει το post εμφανίζει στο body ένα div που έχει μέσα το json object και γίνεται trigger το load event του iframe. Έτσι στην συνέχεια γίνεται refresh το timeline και εμφανίζονται τα νέα posts.

Όπως και μάθε plugin έτσι και αυτό έχει options για πόσα rows, αν θα έχει auto refresh κτλ.
Παράδείγματα μπορείτε να δείτε στο wordcamp.gr και στο blog.socialwhale.com.

Το plugin είναι κάτω από GPL licence το Copyright ανήκει στο SocialWhale και βρίσκεται στο  google code με την ονομασία jwhale.

jQuery , ,

Ζητούνται Web developers

September 25th, 2009

Αν είστε subscriber στο blog μου σίγουρα θα σας ενδιαφέρει η παρακάτω αγγελία. Η αγγελία αφορά το Social Whale, το project με το οποίο ασχολούμαι τους τελευταίους μήνες.

Uncategorized, php , ,

Ένα firefox extension για twitterholics

May 6th, 2009

Τελευταία και αφού μπήκα στο development team του social whale, ασχολούμαι αρκετά με development γύρω απο το twitter. Μετά το winamp plugin για το audiotwit, σκεφτήκαμε να κάνουμε κάτι πιό χρήσιμο για την κοινότητα του twitter.

The social whale firefox extension

To social whale firefox extension είναι ένα απλό addon το οποίο μπορείτε να χρησιμοποιήτε για να δημιουργήσετε short urls μέσω του twt.gs και για να κάνετε upload φωτογραφίες μέσω του twitpic.com.

Για οδηγίες ανατρέξτε εδώ, ενώ άν έχετε οποιοδήποτε σχόλιο ή παρατήρηση αφήστε ένα σχόλιο.

twitter , ,