Qualitätssicherung mit Monotone VCS: mtn approve
Die Mechanismen zur Unterstützung der Qualitätssicherung beim Versionsverwaltungssystem Monotone beruhen im wesentlichen auf dem Ausfiltern von Revisionen, die nicht den gewünschten Kriterien entsprechen.
Monotone betrachtet die Sammlung von Revisionen in einem Repository als gerichteten Graphen, in welchem die Revisionen die Knoten darstellen und die Änderungen zwischen diesen die Kanten. Dabei nennt man Revisionen, die aus anderen abgeleitet sind, Nachkommen, während Revisionen, aus denen andere abgeleitet wurden, Vorfahren genannt werden. Dieser Revisionsgraph enthält verschiedene Teilgraphen, die sich teilweise überlappen können. Zum Beispiel ist jeder Zweig in einem Repository ein Teilgraph, der nur Knoten (Revisionen) enthält, die ein bestimmtes Zweigzertifikat haben.
Viele Befehle von Monotone suchen bei ihrer Ausführung nach Vorfahren beziehungsweise Nachkommen einer bestimmten Revision im Repository oder sie extrahieren die Kopfversion eines Teilgraphen (eine Kopfversion hat keine Nachkommen im gerichteten Graph). Zum Beispiel sucht monotone beim update Befehl nach einer geeigneten Kopfversion in dem Subgraphen, der aus Nachkommen der Basisversion des Arbeitsverzeichnisses besteht und versucht eine Kopfversion zu finden, um das Arbeitsverzeichnis auf diese zu aktualisieren.
Monotones Mechanismen zur Qualitätssicherung beschränken den Teilgraph, mit dem jeder Befehl arbeitet. Es gibt zwei Möglichkeiten, den Teilgraph einzuschränken
Durch Beschränkung der Menge der Zweigzertifikate, denen vertraut wird, kann man erzwingen, dass definierte Qualitätssicherer jede Kante des Teilgraphen abgenommen haben, den man verwendet.
Durch Beschränkung auf vertrauenswürdige Testzertifikate kann man erzwingen, dass die Endpunkte des betreffenden Monotone-Befehls (also die Zielrevisionen) ein Zertifikat enthalten, das bestätigt, dass die Revision bestimmte Tests bestanden hat.
Der Workflow ist bei beiden ähnlich, jedoch sind die Vorkehrungen unterschiedlich. Prinzipiell sieht der Workflow wie folgt aus:
Der oder die Entwickler erzeugen neue Revisionen im Repository, die mit
sync und update zur Qualitätssicherung und zum
Produktivsystem verteilt werden.
Während die Qualitätssicherung neue
Versionen gleich in das Arbeitsverzeichnis übernimmt, verbleibt diese
beim Produktivsystem zunächst noch im Repository.
Nachdem der
Qualitätssicherer die neue Revision geprüft und für gut befunden hat,
bestätigt er das mit mtn approve
.
Auch diese Bestätigung wird mit sync und update verteilt.
Da die geprüfte Revision nun das Zweigzertifikat des
Gutachters enthält, übernimmt das Produktionssystem sie in
das Arbeitsverzeichnis.
Im Fehlerfall verweigert der Gutachter das Zertifikat und die
betreffende Revision wird vom Produktivsystem beim mtn sync --update
auf Grund des
fehlenden Zertifikats nicht in das Arbeitsverzeichnis übernommen.
Im folgenden beschäftige ich mich mit der
Beschränkung auf vertrauenswürdige Zweigzertifikate, die mit dem Befehl
mtn approve
zu einer Revision hinzugefügt wurden. Dafür kann ich den
Trust-Evaluation-Hook get_revision_cert_trust
verwenden.
Monotone verwendet diesen
Hook wenn es die verfügbaren Revisionen für die Aktualisierung des
Arbeitsverzeichnisses mit mtn update
auswählt.
Jeder Beteiligte an einem Projekt, sogar jedes Arbeitsverzeichnis kann seine eigene Implementation dieses Hooks und somit eine andere Sicht auf die verfügbaren gültigen Revisionen haben.
Die Defaultimplementierung dieses Hooks liefert immer true
zurück,
das heißt allen Schlüsseln in der Datenbank wird vertraut.
Das folgende Beispiel zeigt eine Implementation, die eine Revision genau dann in Betracht zieht, wenn sie ein Zertifikat trägt, das von mindestens einem der beiden Schlüssel qa@example.org oder qa@example.net signiert wurde.
function intersection(a,b)
local s={}
local t={}
for k,v in pairs(a) do s[v.name] = 1 end
for k,v in pairs(b) do if s[v] ~= nil then table.insert(t,v) end end
return t
end
function get_revision_cert_trust(signers, id, name, val)
local trusted_signers = { "qa@example.org",
"qa@example.net",
}
local t = intersection(signers, trusted_signers)
if t == nil then return false end
if (table.getn(t) >= 1) then
return true
else
return false
end
end
Diese Lua-Funktionen schreibe ich in die Datei _MTN/monotonerc im
Arbeitsbereich der Produktivumgebung.
Danach aktualisiert mtn update
nur auf Revisionen mit
mindestens einem der beiden Zertifikate.
Somit kann ich ein automatisiertes Build-System für die Produktivumgebung
einrichten, das regelmäßig
mtn sync --update
aufruft und werde dort immer einen Stand vorfinden, der von der Qualitätssicherung bestätigt wurde.
In einem anderen Arbeitsbereich setze ich eine Testumgebung auf und hole mir ebenfalls regelmäßig die letzten Updates der Entwickler. Diese werden getestet und bei erfolgreichen Tests werden die Bestätigungen mit
mtn approve -k qa@example.org
mtn sync
verteilt.
Durch geeignete Gestaltung der Prüffunktion get_revision_cert_trust()
in
verschiedenen Arbeitsbereichen kann ich auch Prüfketten aufbauen.
Bei diesen werden aufwendigere Tests erst dann gestartet, wenn die einfacheren
Tests bestanden und bestätigt sind.
Update (20130405): Link zum zweiten Artikel zur Qualitätssicherung mit Monotone VCS.
Posted 2013-07-12