Seite wählen

NETWAYS Blog

GitLab – Webhooks

gitlab-webhooks
Da ich vor kurzem für einen unserer namhaften Kunden ein GitLab Setup aufsetzten durfte und dieser sich nun auch Automatische Checkouts seiner Live Branches auf seinen Produktiv Systemen wünschte, habe ich mich dazu entschlossen euch ein bisschen an der Einrichtung dieser Mechaniken teilhaben zu lassen, natürlich nicht im vollem Umfang des Projektes für unseren Kunden, das eine oder andere habe ich für diesen Artikel verständlicherweise leicht abwandeln müssen, das hier gezeigte funktioniert trotzdem, ich habe es selber ausprobiert.
Dann legen wir mal los…
In einem klassischen Git Setup werden die Hooks direkt im Repository im Unterordner hooks abgelegt, hier mal ein Beispiel wie das aussehen kann…

$ MyAwesomeProject/hooks $ ll
-rwxrwxr-x 1 enzo enzo  452 Jun 28 11:46 applypatch-msg.sample*
-rwxrwxr-x 1 enzo enzo  896 Jun 28 11:46 commit-msg.sample*
-rwxrwxr-x 1 enzo enzo  189 Jun 28 11:46 post-update.sample*
-rwxrwxr-x 1 enzo enzo  398 Jun 28 11:46 pre-applypatch.sample*
-rwxrwxr-x 1 enzo enzo 1642 Jun 28 11:46 pre-commit.sample*
-rwxrwxr-x 1 enzo enzo 1239 Jun 28 11:46 prepare-commit-msg.sample*
-rwxrwxr-x 1 enzo enzo 1352 Jun 28 11:46 pre-push.sample*
-rwxrwxr-x 1 enzo enzo 4898 Jun 28 11:46 pre-rebase.sample*
-rwxrwxr-x 1 enzo enzo 3611 Jun 28 11:46 update.sample*

GitLab geht hier allerdings einen anderen Weg, da dieses das hooks Verzeichnis durch einen Symbolischen Link auf System eigene Hooks umlenkt (wie hier Beispielhaft zu sehen ist)…
gitlab-webhooks-art2
…nun sollte man hier auch besser die Finger heraus lassen, da GitLab dieses Verzeichnis für allerlei anderen Mechaniken benötigt, der Weg über die Webhooks ist meiner Meinung nach aber auch flexibler (allein schon wegen der einfachen Anbindung an Web Dienste wie GitHub, Bitbucket, Heroku, etc.).
Nun direkt zum spaßigen Teil, im GitLab benötigen wir einen neuen User ohne irgendwelche besonderen Rechte incl. SSH Public Key, fangen wir mit dem Key selbst an, da der Checkout User keinen besonderen Rechte benötigt außer einen Pull/Fetch zu tätigen, reicht es uns den Key also entsprechend Unprivilegiert zu preparieren (bei der Passwortabfrage bitte nichts angeben, einfach mit Enter bestätigen)…

$ ssh-keygen -t rsa -b 2048 -O clear -O no-agent-forwarding -O no-port-forwarding -O no-pty -O no-user-rc -O no-x11-forwarding -f gitlab.key
Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in gitlab.key.
Your public key has been saved in gitlab.key.pub.
The key fingerprint is:
4b:f3:ae:60:d4:5d:5e:02:75:64:4c:7f:ce:09:ec:8a enzo@ebony
The key's randomart image is:
+--[ RSA 2048]----+
|          ...+=  |
|           ..o.. |
|            oo. o|
|       . . o.o.oo|
|      . S . .. .o|
|     . . +. .    |
|      o .E..     |
|     . . .       |
|        ...      |
+-----------------+
$ ll
insgesamt 8
-rw------- 1 enzo enzo 1675 Jun 28 11:52 gitlab.key
-rw-r--r-- 1 enzo enzo  392 Jun 28 11:52 gitlab.key.pub

…nun benötigen wir lediglich noch einen User im GitLab, das sollte keine große Herausforderung darstellen, bitte stellt auch sicher das ihr den SSH PublicKey in unserem Beispiel gitlab.key.pub dem User, lasst ihn uns hier der Einfachheit halber checkout nennen zuweist, da die Webhooks mit den Berechtigungen des Standard Apache User www-data läuft (das ist zumindest unter Debian/Ubuntu der Fall, unter Redhat Systemen heißt dieser wwwrun) solltet ihr dem Key als Identifier so etwas wie www-data to gitlab oder ähnliches benennen, damit ihr später ganz einfach den Überblick behalten könnt…
gitlab-webhooks-art4
gitlab-webhooks-art5
…nun müssen wir unserem User checkout lediglich noch in unser Projekt aufnehmen, die Rechte eines Reporter sollten dafür ausreichend sein um Fetch/Pull oder auch Clone zu können, mehr benötigen wir an dieser Stelle nicht…
gitlab-webhooks-art9
…somit sind wir auf schon fast fertig, zumindest was das GitLab Setup selbst betrifft, nun müssen wir lediglich noch die URL unseres Webhook konfigurieren und schon können wir uns dem Hook selber widmen…
gitlab-webhooks-art7
gitlab-webhooks-art8…bitte beachtet auch, das es beim Entwickeln eines Webhooks sehr hilfreich sein kann wenn ihr über den Button [Test Hook] den Push Event einfach mal Manuell triggert, ansonsten würde euer Webhook erst aufgerufen werden wenn ihr wirklich in das Repository Pusht (das geht natürlich auch, legt euch hierzu einfach ein neues Repository zum spielen an).
So nun geht es an den Server der unseren Webhook ausführen soll, ihr benötigt lediglich einen simplen Apache/NginX vHost mit Standard Rechten, man kann selbstverständlich auch ein komplizierteres Deployment bauen aber darum geht es in diesem Artikel nicht (ich nutzte hier den Apache2 mit PHP5, da dieser bereits auf dem Kunden System vorhanden wahr und zusätzliche Scriptsprachen installieren ist meist schlechte Praxis sowie auch unnötiger Aufwand).
Ich habe mich hier für den Standard Pfad des Apache Setups entschieden da der Standard vHost bereits auf diesen zeigt und dieser auch nur aus dem internen Netz bedienbar ist, somit ist sichergestellt das Niemand von außerhalb Unfug treiben kann.
Dort habe ich im DocumentRoot des Apache ein Verzeichnis api erstellt, der volle Pfad lautet hier /var/www/html/api, dort habe ich mein Webhook mit Namen on-push.php abgelegt, dieser hat nun folgenden Inhalt…

object_kind == 'push' ) {
                if( $obj->ref == 'refs/heads/'.BRANCH ) {
                    $allowed = false;
                    foreach( $USERS as $user ) {
                        msg( "permission test ( ".$obj->user_name ." == ". $user." ) ..." );
                        if( preg_match( "/$user/i", $obj->user_name ) ) {
                            msg( $user . " allowed to do updates on refs/heads/".BRANCH." branch" );
                            $allowed = true;
                            break;
                        }
                    }
                    if( $allowed ) {
                        if( $obj->before != "0000000000000000000000000000000000000000" ) {
                            msg( "changing directory to ".PROJECTROOT );
                            chdir( PROJECTROOT );
                            msg( "executing: ". COMMAND );
                            $fh = popen( COMMAND." 2>&1", "r" );
                            $result = fread( $fh );
                            while( !feof( $fh ) ) {
                                msg( rtrim(fgets( $fh, 4096 )) );
                            }
                            pclose( $fh );
                        } else {
                            msg( "it's a empty repository, we'll do nothing at this point" );
                        }
                    } else {
                        msg( "permission denied for ". $obj->user_name );
                    }
                } else {
                    msg( "everybody can push to ". $obj->ref.", but we'll do nothing, please check your project settings" );
                }
            } else {
                msg( "[ ". $obj->object_kind ." ] event handler not yet implemented" );
            }
        } else {
            msg( strtoupper($_SERVER['REQUEST_METHOD'])." from [ ".$_SERVER['REMOTE_ADDR'] ." ] is not allowed, please check your server settings" );
            return_status( ERR );
        }
    } catch( Exception $e ) {
        msg( "======= EXCEPTION BEGIN ========" );
        msg( $e->getMessage() );
        msg( "======= EXCEPTION END ==========" );
        return_status( ERR );
    }
    return_status( OK );
    // ================================ FUNCTIONS ===========================================
    function return_status( $status = ERR ) { header( $status ); }
    function getRequestBody() { return json_decode( file_get_contents('php://input') ); }
    function msg( $message ) { if( $message != null ) file_put_contents( LOGFILE, $message."\n", FILE_APPEND ); }
?>


..damit das nun funktionieren kann, müssen wir nun noch das Projekt Klonen und die SSH Settings anlegen, fangen wir daher direkt mit den SSH Settings an…

# (beginne mit Root Login)
su - -s /bin/bash www-data
mkdir -p .ssh && chmod 0600 .ssh
exit
cp gitlab.key /var/www/.ssh/ && chown www-data. /var/www/.ssh/gitlab.key && chmod 0400 /var/www/.ssh/gitlab.key
su - -s /bin/bash www-data
vi .ssh/config

…die .ssh/config sieht dabei wie folgt aus…

Host gitlab.example.org
    UserKnownHostsFile /dev/null
    StrictHostKeyChecking no
    IdentityFile ~/.ssh/gitlab.key
    User git
    LogLevel VERBOSE

…speichert nun das ganze und Klont eurer Projekt nach /var/www/project1/htdocs

# (beginne mit Root Login)
su - -s /bin/bash www-data
cd /var/www/project1
git clone git@gitlab.example.org:test/number1.git htdocs

…wenn ihr nun Lokal mit eurer Arbeitskopie arbeitet und an dem Punkt seit das ihr alles fertig zuhaben scheint und dann einen Push in euren staging Branch macht, wird GitLab jedesmal den Webhook on-push.php Aufrufen und auf dem Projekt/Web -Server einen Fetch/Pull ausführen lassen, um das Projekt auf den selben Stand wie eure Arbeitskopie zu bringen.
Zugegeben der PHP Handler oben ist keinesfalls perfekt, ich bin auch kein guter PHP Programmierer, genau genommen eigentlich gar keiner ;). Der Hook für das Kunden Projekt umfasst zudem noch mehr Fähigkeiten und würde mit seine zu diesem Zeitpunt ca. 800 Zeilen diesen Artikel in jedem Fall sprengen, aber ich denke das der gezeigte Webhook oben bereits eine gute Ausgangsbasis darstellt, sodass ich euch hoffentlich dazu Animieren konnte, das ganze doch einmal selber nachzubauen.
Zum zweck des Debugging, loggt dieser zur Kontrolle nach /var/www/html/api/on-push.log , hier lohnt also ein Blick.
Noch ein kleiner Hinweis meinerseits, der eine oder andere von euch wird schnell feststellen, das GitLab selber im Admin Panel auch einen Menü Eintrag mit der Bezeichnung [Deploy Keys] bereitstellt, womit sich das oben gezeigte auch umsetzten lässt, aufgrund einiger bedenken bzgl. Sicherheit dieses allerdings nicht immer gewünscht ist, da alle Keys die dort hinterlegt werden automatisch, für allen Projekte (auch für zukünftige) direkt verwendet werden können.
Nützliche Links:

Weekly Snap: Puppet project, Jasmine tests and VM alternatives

30 May – 3 June slipped into summer with a peek into a Puppet consulting project and tips for JavaScript testing and virtualisation.
To begin, Thomas explained his preference against large VMs. With their high overheads, he sought alternatives to hypervisors such as KVM, Xen and VMware. Instead of virtualised kernels with virtualised hardware, Thomas referred to Jails (BSD) and Zones (Solaris), or Linux-vServer and OpenVZ for Linux. Where the required patched kernels are inappropriate, he offered Linux Containers (LXC) as substitutes. In the upstream since 2.6.29 and progressing slowly, Thomas liked them as they do not need direct hardware access, do not block devices, network or memory. But most of all he liked the fact such a virtual server can perform just as well as processes on the host itself, where one single kernel manages virtual memory enabling more virtual servers to be run than on a mature VMware.
Jannis followed with his JavaSript testing tip – Jasmine. The successor to JSUnit, he recommended this test unit suite for its lack of dependencies and ability to describe tests, and even gave a user login test example to boot.
Last but not least, Birger gave us a peek into the consulting team’s latest escapades: A Puppet project at Continental, the automotive supplier. Used to help manage their heterogeneous server environment, Puppet oversees Linux and HPUX systems. Though the first is far simpler than the latter, thanks to spirit of open source the automation project was nonetheless a success.

Puppet bei Continental

Unser Projekt zur Automatisierung beim Automotiv Automobilzulieferer Continental ist inzwischen 2 Jahre alt. Es hat nicht an Reiz verloren.
Wir haben bei Planung und Einsatz von Puppet als Mittel zum Management der heterogenen Serverlandschaft unterstützt.
Linux Systeme mit Puppet zu managen ist inzwischen Alltagsgeschäft, HPUX ist aber nach wie vor kein Spaziergang. Leider gibt es für HPUX auch keinen Support von Puppetlabs. Aber möglich ist dank offener Quellen alles. Leider darf ich hier nicht weiter ins Detail gehen.
Vielen Dank für die gute Zusammenarbeit.

Weekly Snap: Training Dates, Siemens CEP CT3, an OTRS Project and a SQL Developer Release

11 – 15 October was packed with news from all sides of the office, from hardware and training course announcements, to a consulting project and a SQL Developer release.
From the consulting team, Birger shared his most recent project at the German Federal Bureau of Water and Shipping – an OTRS implementation to cover multiple locations with differing domains and user groups from one single ticketing system.
Hardware man Martin then bid his last Siemens TC35i goodbye and introduced its successor, CEP CT3. Running under the current Linux kernel, Windows (see shop for drivers) and Solaris, the modem tops its predecessor by offering a USB port and relevant accessories. With an external antenna, it is ideal for server racks with poor reception and thus a perfect USB GSM modem for sending SMS alerts from your monitoring system. Martin recommended teaming CEP CT63 GSM Terminal with Moxa NPort 6150 for smooth network integration.
Following on, Bernd forwarded news of the SQL Developer Early Adopter version release and its new features. Though he recommended MySQL Workbench for straight MySQL users, Bernd praised SQL Developer for its greater flexibility in enabling access to various databases such as Oracle, MySQL, Microsoft SQL Server and DB2. In the Oracle realm new features included new profiling and tuning functions, a migration assistant, a data modeller for graphical ER models, as well as reverse engineering that also works with MySQL. For SQL beginners, a new visual query builder simplifies the process of creating SQL statements too. All in all after his tests, Bernd found no major bugs and gave the Early Adopter version the thumbs up.
From the events team, Manuela announced the upcoming training calendar to end 2010 and start 2011. Ending 2010 with ‘Puppet Configuration Management’ for beginners on 7 – 9 December, and kick starting 2011 with ‘Nagios SLA Reporting with Jasper’ on 29 – 30 February, ‘Nagios – Availability Monitoring’ rounds it all off on 21 – 24 March for the coming months. She guaranteed all interested participants restricted class sizes for greater individual attention and accommodation at the course hotel to allow for discussion and idea exchange, consolidating all that is learnt in and out of the class. For more information, visit our training centre: www.netways.de/training

Clever Elements GmbH

Wir freuen uns, mit der Clever Elements GmbH unseren neuesten Kunden im Bereich Managed Service begrüßen zu dürfen. Clever Elements ist ein kleines Unternehmen unweit vom Moritzplatz direkt im Herzen Berlins. Namhaften Kunden wie z.B. Siemens, BMW und IBM bietet es eine Online-Software für E-Mail-Marketing, welche die Erstellung und Versendung von Newslettern so einfach und intuitiv wie nur möglich macht.
In den letzen Tagen haben wir die bestehenden Services auf ein neues HA-Cluster in unserem Rechenzentrum umgezogen. Ab sofort profitieren die Kunden von Clever Elements  von der damit verbunden Leistungssteigerung und können sich auf die hochverfügbare Umgebung 24×7 verlassen. Die vorhandene Architektur erlaubt zudem ein flexibles Wachstum in der Zukunft ohne Downtime.
Die Arbeit von Clever Elements kann man im Social Media-Zeitalter natürlich auch auf Facebook verfolgen.
Wir freuen uns auf eine weiterhin gute Zusammenarbeit mit der Clever Elements GmbH.