Als Dienstleister veröffentlicht man selten Software direkt auf dem Zielserver.
Meist übergibt man dem Auftraggeber ein Paket, welches sämtlichen Projektcode enthält und eine entsprechende Installationsanleitung.
Nun ist das Vorbereiten eines solchen Paketes eine mühsame Angelegenheit.
Es müssen alle Testdateien entfernt werden, da diese auf einem Produktivsystem nichts zu suchen haben.
Verschiedene SQL-Dateien müssen zu einer zusammengefügt werden, der Kunde möchte schließlich beim Deploy so einfache Anweisungen wie möglich haben.
Diese und viele weitere Aufgaben fallen an, bevor eine Software an den Kunden ausgeliefert werden kann.
Nun entwickeln wir Software, und es kommt auch bei noch so gründlicher Entwicklung und Tests immer wieder zu Bugs.
Nach dem Fixen des Bugs muss also nochmals der Deploymentprozess Schritt für Schritt durchgegangen werden.
All das kostet Zeit, da bei jeder Übergabe an den Kunden die immer gleichen Schritte durchgeführt werden müssen.
Warum also nicht automatisieren?
Ein bekanntes Tool um diese Automatisierung des Deployments zu ermöglichen ist
ANT.
ANT hat für uns PHP-Entwickler aber einen großen Nachteil. Es ist in Java geschrieben.
Da wir PHP gewohnt sind, hat sich jemand die Mühe gemacht und das Konzept von ANT portiert.
Daraus ist
PHING entstanden.
PHING selbst ist ein PEAR Package, welches ab PHP 5.2 läuft und kann folgendermaßen installiert werden:
pear channel-discover pear.phing.info
pear install phing/phing
Zusätzlich sollte man, sofern mit SVN gearbeitet wird, das
VersionControl_SVN PEAR Package installieren:
pear install VersionControl_SVN
Die Verwendung wird folgend an einem virtuellen Projekt demonstriert.
Das Projekt ist ein Zend Frameworkprojekt, hat also die folgende Ordnerstruktur:
|--application
| `--controllers
| `--models
| `--views
| `--configs
|--library
| `--zend
|--data
| `--sql
|--public
| `--js
| `--css
|--tests
| `--application
| `--models
| `--library
Unsere Schritte für das Bilden des Paketes sind, aufgeteilt auf drei Artikel:
Teil 1:
1) Laden der Einstellungsdatei
2) Abfragen der SVN Nutzerdaten
3) Das Projekt aus einem SVN Repository exportieren
Teil 2:
7) Alle SQL-Files im Data Ordner zusammenführen
Teil 3:
8) Alle dotfiles löschen, außer .htaccess
9) Den Testordner löschen
10) Data Ordner löschen
11) Archiv des Quellcodes schnüren
12) Archiv hashen und den Hash in eine Datei schreiben
13) Generiertes SQL-File, Hashfile und Archiv in den Zielordner verschieben
14) Abarbeitung der einzelnen Targets
PHING Buildfiles sind XML-Dateien die
build.xml heißen und aus einem Projekt bestehen, welches unterteilt ist in Targets.
Alternative kann das Buildscript beliebig benannt werden, dann muss PHING jedoch mit dem Argument
-buildfile filename aufgerufen werden.
Ein Target ist eine einzelne Aufgabe und kann separat ausgeführt werden über
phing
Das Gerüst für ein Buildfile sieht wie folgt aus:
Im
default Attribut des
project Tags wird das Target angegeben, welches bei einem Aufruf des Buildscripts ohne Angabe eines Targets aufgerufen wird.
Das
basedir Attribut gibt den Pfad an, auf den sich alle nicht absoluten Pfadangaben innerhalb des Buildfiles beziehen.
Ein Target hat immer einen eindeutigen Namen und sollte stets im
description Attribut eine Beschreibung enthalten, was dieser Task tut.
Innerhalb eines Targets können verschiedene vordefinierte, bzw. eigene Tasks aufgerufen werden.
Ein Task ist ein Einzelschritt, beispielsweise das Löschen einer Datei.
Eine Übersicht über die vorhandenen Tasks ist in der
Dokumentation unter
Appendix B und
Appendix C zu finden.
Unsere erste Aufgabe wird es sein eine Konfigurationsdatei einzulesen.
Konfigurationsdateien sind einfach Ini-Dateien, in welchen Key-Value-Paare abgespeichert sind.
PHING kann von Haus aus nicht mit Sektionen umgehen, es empfiehlt sich also diese nicht in der Konfigurationsdatei zu verwenden, da PHING ansonsten immer das letzte Vorkommen des Keys als Wert nimmt.
Auch auf Anführungszeichen um Werte sollte man verzichten, da diese als zum Wert zugehörig angenommen werden.
Unsere Konfigurationsdatei (
build.ini) besteht vorerst nur aus der Angabe der URL zum SVN Repository:
; SVN repository url
svn.url = svn://svn.demo.de/svnroot/trunk
Einlesen können wir diese Datei in unser Buildfile folgendermaßen:
Eine andere Möglichkeit ist es Variablen direkt zu definieren, ebenfalls mit Hilfe des
property Tasks:
Das
name Attribut gibt den Variablennamen an, unter dem innerhalb des Buildscripts auf die Variable zugegriffen werden kann und das
value Attribut den entsprechenden Wert.
Das Attribut
override gibt an ob eine gleichnamige Variable überschrieben werden soll, sofern eine solche existiert.
Das normale Verhalten ist diese nicht zu überschreiben.
Der Zugriff auf eine definierte Variable innerhalb des Buildscripts erfolgt durch
${variablenname}, in unserem Fall also durch ${svn.url}, bzw. ${svn.user}.
Nun gibt es Daten, wie etwa Passwörter, die weder in eine Konfigurationsdatei, noch direkt in das Buildscript gehören.
Solche Daten kann man innerhalb des Buildprozesses vom Nutzer abfragen.
Der zugehörige Task heißt
PropertyPrompt.
Genutzt werden kann die Eingabe wiederum durch ${svn.password}.
Sollte keine Eingabe erfolgt sein, so wird der Wert aus dem
defaultvalue Attribut genommen.
Da nun alle wichtigen Daten des SNV Repositories vorhanden sind kann ein Export gestartet werden.
Der SVN Export unterscheidet sich vom Checkout dadurch das keine
.svn Dateien übertragen werden, was einiges an Aufräumarbeit erspart.
Auch für diese Aufgabe gibt es wieder einen vordefinierten Task, welcher
SvnExport heißt.
Für das Exportieren wird ein neues Target angelegt, welches als Abhängigkeit das
define Target ausführt bevor es selbst zur Ausführung kommt:
Dieses Target holt alle Dateien aus dem angegebenen SVN Repository und kopiert diese in den unter
todir angegebenen Ordner.
Das Attribut
force sorgt dafür das eventuell schon vorhandene Dateien überschrieben werden und
ignoreexternals stellt sicher das auch externe Verweise mit kopiert werden.
Das bisherige Buildfile sollte in etwa wie folgt aussehen:
Im
nächsten Teil werden wir uns anschauen wie eigene Task geschrieben und ausgeführt werden können.