PHP Deployment via Git

Source Code

Source Code verwalte ich in Bitbucket. Ja, Bitbucket und nicht Github. Auf Bitbucket kann ich eine unbegrenzte Anzahl an privaten Projekten haben. Für meine privaten Sachen perfekt geeignet. Auf Github wiederum habe ich meine öffentlichen Projekte.

Entwicklung

Selbstverständliche entwickle ich den ganzen Code lokal auf meinem Desktop Rechner. Dazu hätte ich noch einen kleinen Homeserver, den ich eigentlich zum Testen einsetzen könnte, doch der ist aktuell noch nicht im Einsatz.

In meinem Git Repository habe ich einen Entwicklungs Branch. Dort wird entwickelt und gemacht. Ist ein Feature fertig, dann merge ich Entwicklungs Branch und Master.

Deployment

Bitbucket bietet sogenannte Services an:

Bitbucket offers integration with external services via a set of service brokers that run when certain events happen. These brokers are simple Python scripts, that receive information about the event and then take action. For example, there is a broker for sending email messages, another for posting information to an arbitrary URL, and another for posting updates to a Twitter account.

Bei mir sieht das im Konkreten wie folgt aus:

- Push to Bitbucket
- Trigger Post request nach http://www.sample.com/deploy.php
- Das PHP Script überprüft, ob es eine Änderung im Master Branch gegeben hat. Falls ja, dann wird eine Datei leere Datei "dodeploy.true" auf dem Webserver geschrieben
- Ein Cron überprüft im Minutentakt, ob diese Datei vorhanden ist
- Falls dodeploy.true vorhanden ist, wird Deployment Script ausgeführt.

That's it.

Das Deployment Script

#!/bin/bash

# check if there is new code in the repository
if [ -f /var/www/deployment/deploy-wordpress.true ]
then

DATE=`date +%m-%d-%y-%H:%M:%S`
#echo "Backup Database"
/home/ubuntu/deployments/backup-db.sh

git clone [email protected]:rapsli/wordpress.git /home/ubuntu/deployments/wordpress/wordpress-$DATE

rm -Rf /home/ubuntu/deployments/wordpress/wordpress-$DATE/.git

# copy the config file, since this doesn't get deployed
cp /home/ubuntu/deployments/wp-config.php /home/ubuntu/deployments/wordpress/wordpress-$DATE/wp-config.php

# remove old installations
rm -Rf /home/ubuntu/deployments/wordpress/wordpress-old

# rename currently working folder, as it will become the older 
# folder -- this will break the site now
mv /home/ubuntu/deployments/wordpress/wordpress /home/ubuntu/deployments/wordpress/wordpress-old

# we make the new wordpress active
mv /home/ubuntu/deployments/wordpress/wordpress-$DATE /home/ubuntu/deployments/wordpress/wordpress

# symlinking the userdata in
ln -s /home/ubuntu/userdata/uploads/ /home/ubuntu/deployments/wordpress/wordpress/wp-content/uploads
ln -s /home/ubuntu/userdata/cache/ /home/ubuntu/deployments/wordpress/wordpress/wp-content/cache
ln -s /home/ubuntu/userdata/blogs.dir/ /home/ubuntu/deployments/wordpress/wordpress/wp-content/blogs.dir

# make sure the symlink here is active
ln -nsf /home/ubuntu/deployments/wordpress/wordpress/ /var/www/wordpress

# and finally make sure the next cron run doesn't execute the deployment script again
rm -f /var/www/deployment/deploy-wordpress.true

fi

Ist eigentlich ziemlich trivial und sogar gut kommentiert. Falls fragen sind, einfach einen Kommentar posten.

Zwei Bemerkungen

Symlink und Apache ist problematisch. Nach einem Deployment kann es ab und zu mal vorkommen, dass die Seite hängt. Ich vermute, dass dies damit zu tun hat, dass ich einen Apache Worker habe, der noch irgendwie in der alten Version hängt. Ein /etc/init.d/apache2 restart verhilft da jeweils immer Abhilfe. Nein, das ist noch nicht perfekt und ich überlege mir, ob ich einfach komplett auf die Symlinks verzichten soll und einfach mit mv arbeiten soll.

Der Umweg über diese deploy-wordpress.true Datei ist aus folgendem Grund notwendig. Der Request von Bitbucket kommt mit dem www User rein. Dieser hat jedoch nicht die entsprechenden Schreibrechte im home Verzeichnis und kann daher den Clone Befehl dort nicht ausführen. Daher wird lediglich signalisiert, dass es etwas Neues gibt und dann kann der normale User das Deployment durchführen.

Ich finde diesen Ansatz gar nicht mal übel, da er doch auch eine gewisse Sicherheit bringt.

Die Zukunft

Wahrscheinlich wird dieses Script noch ein bisschen wachsen. Das ist das Schöne am Web, es gibt immer etwas Neues und Besseres, aber es ist ein riesiger Schritt nach vorne… die FTP Upload Zeiten sind definitiv vorbei!

Ich bin gespannt zu hören, wie du das Deployment machst. Let me know.