SVN SSH post-commit checkout hook

Wenn man mit SVN ein Webprojekt versioniert, dann ist es wünschenswert, den aktuellen Stand auch live auf einem Webserver im Internet zu haben. Dieser Wunsch lässt sich mit sogenannten „hooks“ realisieren. In jedem SVN Projektordner gibt es einen Unterordner namens „hooks“. In diesem Ordner sind Shell-Skripte für verschiedene Momente abgelegt. Diese Scripte werden zum jeweiligen Zeitpunkt automatisch vom SVN Server aufgerufen.

Das post-commit-Skript wird direkt nach einem Commit ausgeführt und bietet sich hervorragend an, um direkt nach einer Projekt-Änderung den aktuellen Stand für den Webserver zur Verfügung zu stellen. Dazu muss man im Skript nur festlegen, dass ein checkout in das gewünschte Web-Verzeichnis ausgeführt werden soll. Wie das geht, zeige ich im folgenden Artikel.

Vorab:

Mein Beispiel geht davon aus, dass sich alle SVN-Benutzer mit einem privaten Schlüssel über svn+ssh am Server anmelden um ihre Aktionen auszuführen. Das führt dazu, dass der post-commit hook immer mit dem Benutzerkonto ausgeführt wird, der gerade einen Commit begangen hat. Wenn post-commit nun die Aufgabe hat, einen automatischen Checkout auf dem Webserver zu machen, kommt es standardmäßig dazu, dass die Dateien beim Checkout alle dem Benutzer gehören, der den Commit gemacht hat. Wenn man mit mehreren SVN-Benutzern arbeitet kommt es zu einem Problem. Den anderen Benutzern fehlen die nötigen Rechte, um die Checkout-Dateien für das Webverzeichnis zu ändern. Zudem gibt es noch ein weiteres Problem. Damit das Webprojekt erfolgreich im Internet bedient werden kann, sollte das Webverzeichnis, in das ausgecheckt wird, dem Apache-Webserver gehören. Man kann zwar für den svn checkout Befehl einen Benutzer und ein Passwort festlegen, damit der Checkout immer über dasselbe Benutzerkonto ausgeführt wird, allerdings authentifizieren sich die SVN-Benutzer (wie bereits erwähnt) nicht über ein Passwort, sondern über einen Schlüssel. Trotzdem gibt es eine Lösung dafür.

Struktur:

Der Apache-Webserver läuft unter dem Benutzerkonto: www-data
Das SVN-Repository liegt in: /srv/svn/st38
Das Web-Verzeichnis ist: /srv/www/st38
Die ausführbare SVN-Datei ist: /usr/bin/svn
Alle SVN-Benutzer sind in der Gruppe: svn

Quellcode:

Meine Lösung benötigt zwei Dateien. Das Skript für den post-commit hook sowie ein Programm für das automatische svn update. Damit es während der Einrichtung keine Probleme gibt, hier schon mal die Quelltexte.

post-commit

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/bin/sh
# REPO	- Path to the repository
# REV	- Current revision number of the repository
# USER	- Name of the user who did the commit
# DATE	- Time of the commit
 
REPO="$1"
REV="$2"
USER=`whoami 2>&1`
DATE=`date +"%d.%m.%Y, %H:%Mh"`
 
/srv/svn/repos/st38/hooks/bin/svn-update /usr/bin/svn /srv/www/st38
echo "$DATE - User \"$USER\" committed Revision \"$REV\"." >> /srv/www/st38/post-commit.log

Der post-commit hook ruft das Programm svn-update auf. Dabei wird als erster Parameter der Pfad zur ausführbaren svn-Datei angegeben. Als zweiter Parameter folgt der Pfad zum Webverzeichnis, in das ausgecheckt werden soll. Nach Ausführung dieses Programms erstellt der hook noch eine Logdatei, um zu sehen wer eine Revision eingecheckt hat und wann diese Revision erstellt wurde.

svn-update.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stddef.h>
#include <stdlib.h>
#include <unistd.h>
 
/*
 argv[1] - Path to the svn executable
 argv[2] - Path to the web-directory
*/
int main(int argc, char* argv[])
{	
	if (argc == 3)
	{
		char *newenv = { NULL };
		execle(argv[1], "svn", "update", argv[2],
				"--non-interactive", "--accept", "theirs-full",
				NULL, newenv);
	}
	else
		return(EXIT_FAILURE);
	return(EXIT_SUCCESS);
}

Die Datei svn-update.c ist ein C-Programm und muss erst noch kompiliert werden (siehe [post id=1552]GCC installieren und C kompilieren[/post]). Das Programm sorgt dafür, dass svn update immer vom selben Benutzer ausgeführt wird.

Einrichtung

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
sudo usermod -a -G svn www-data
cd /srv/svn/repos/st38/hooks
scp post-commit.tmpl post-commit
vim post-commit
sudo chmod 0770 post-commit
sudo chown svn:svn post-commit
mkdir ./bin
sudo chmod -R 0770 ./bin
sudo chown svn:svn ./bin
touch ./bin/svn-update.c
gcc -o ./bin/svn-update ./bin/svn-update.c
sudo chmod -R 6750 ./bin/svn-update
sudo chown www-data:svn ./bin/svn-update
mkdir -p /srv/www/st38
cd /srv/www
svn co file:///srv/svn/repos/st38
sudo chmod -R 0775 /srv/www/st38
sudo chown www-data:svn /srv/www/st38
  1. Apache-Benutzer der Gruppe „svn“ hinzufügen
    Tipp: Mit dem Kommando sudo id www-data kann überprüft werden, in welchen Gruppen der Benutzer ist
  2. In das „hooks“-Verzeichnis des Repository wechseln
  3. „post-commit“-Hook aus Template kopieren
  4. post-commit bearbeiten (Quelltext einfügen!)
  5. Verzeichnisrechte für „post-commit“ setzen
  6. Neuen Besitzer für „post-commit“ setzen
  7. Ordner „bin“ erstellen
  8. Verzeichisrechte für Ordner „bin“ setzen
  9. Neuen Besitzer für Ordner „bin“ setzen
  10. Datei „svn-update.c“ erstellen (Quellcode einfügen nicht vergessen!)
  11. „svn-update.c“ zu „svn-update“ kompilieren (siehe [post id=1552]GCC installieren und C kompilieren[/post])
  12. CHMOD für „svn-update“ setzen (Achtung! 6750!)
  13. Besitzer für „svn-update“ ändern (es muss der Apache-User sein!)
  14. Web-Verzeichnis für das Repository anlegen
  15. „Vor“ das eigentliche Webverzeichnis wechseln
  16. Initialen Checkout machen
  17. CHMOD setzen
  18. Besitzer ändern

Ergebnis

Sobald ein SVN-Benutzer nun über seinen SVN-Client einen Commit macht, wird das Repository (/srv/svn/repos/st38) aktualisiert und der neue Stand im Webverzeichnis (/srv/www/st38) eingefügt. Die Dateien im Webverzeichnis gehören alle dem Webserver (www-data) und können so bequem über das Internet abgerufen werden (sofern ein gültiger Directory-Eintrag besteht). Außerdem wird eine Logdatei im Webordner angelegt.

Vielen Dank an gpinzone aus der Subversion Community by WANdisco.

4 Gedanken zu „SVN SSH post-commit checkout hook“

  1. Hi, ich bin gerade zufällig auf deine Seite gestossen.
    Meine ehrliche Meinung: der Hammer, hier sind so viele themen die mich ansprechen, so viel Wissen auf einem Haufen. gute Arbeit. Ich werd hier wohl noch ne ganze Weile verbleiben.

    schade, dass es kein Gästebuch gibt oder ähnliches.

    PS: wie hast du es hinbekommen, dass sich dein logo bewegt?

  2. Hallo jo, vielen Dank für dein Lob. Sowas baut auf. 🙂 Wenn ich die Zeit finde, dann werde ich meinen Blog noch erweitern. Ich finde manche Themen müssen hier noch zusammenhängender und weiterführender erläutert werden. Aber dazu später mehr. Momentan arbeite ich an einem größeren Webprojekt, das ich voran treiben möchte. Wenn es soweit ist, werde ich das hier natürlich bekannt geben. 🙂

  3. Hey,

    ich habe versucht dem Tutorial zu folgen und im groben verstanden wie du das Problem lösen willst. Jedoch bin ich zur Zeit nicht so vertraut mit der Rechtevergabe, wie den Benutzern selbst in Ubuntu. Beim versuch sudo chmod svn:svn […] auszuführen sagt Ubuntu mir das das nicht geht. Weil ungültiger Benutzer.

    Woher nimmst du diesen svn benutzer?

    MfG Iwan

    PS: Habs auch schon mit google versucht nur leider ist „svn benutzer“ ein Scheißstichwort, da sich die meisten Posts anschließend auf auf die Benutzererstellung für eine Repository beziehen. 🙁

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.