Was sind die aktuellen Best Practices für die systematische Build-Nummerierung und das Versionsnummernmanagement in Java-Projekten? Speziell:
So verwalten Sie Build-Nummern systematisch in einer verteilten Entwicklungsumgebung
So pflegen Sie Versionsnummern in der Quelle / stehen der Laufzeitanwendung zur Verfügung
So integrieren Sie sich ordnungsgemäß in das Quell-Repository
So verwalten Sie Versionsnummern im Vergleich zu Repository-Tags automatischer
Integration in die kontinuierliche Build-Infrastruktur
Es gibt eine ganze Reihe von Tools, und ant (das von uns verwendete Build-System) hat eine Aufgabe, die eine Build-Nummer verwaltet. Es ist jedoch nicht klar, wie dies mit mehreren gleichzeitigen Entwicklern mithilfe von CVS, svn oder ähnlichem verwaltet werden kann .
[BEARBEITEN]
Im Folgenden sind einige gute und hilfreiche teilweise oder spezifische Antworten aufgeführt, daher werde ich einige davon zusammenfassen. Es klingt für mich so, als ob es nicht wirklich eine starke "Best Practice" dafür gibt, sondern eine Sammlung überlappender Ideen. Unten finden Sie meine Zusammenfassungen und einige daraus resultierende Fragen, die die Leute möglicherweise als Follow-up beantworten möchten. [Neu bei Stackoverflow ... Bitte geben Sie Kommentare ab, wenn ich das falsch mache.]
Wenn Sie SVN verwenden, wird die Versionierung einer bestimmten Kasse für die Fahrt mitgeliefert. Die Build-Nummerierung kann dies ausnutzen, um eine eindeutige Build-Nummer zu erstellen, die die spezifische Prüfung / Revision identifiziert. [CVS, das wir aus früheren Gründen verwenden, bietet nicht ganz diese Einsicht ... manuelle Eingriffe mit Tags bringen Sie auf halbem Weg dorthin.]
Wenn Sie maven als Build-System verwenden, gibt es Unterstützung für die Erstellung einer Versionsnummer aus dem SCM sowie ein Release-Modul für die automatische Erstellung von Releases. [Wir können Maven aus verschiedenen Gründen nicht verwenden, aber das hilft denen, die es können. [Danke an marcelo-morales ]]
Wenn Sie ant als Build-System verwenden, kann die folgende Aufgabenbeschreibung dazu beitragen, eine Java-Eigenschaftendatei zu erstellen, in der Build-Informationen erfasst werden, die dann auf verschiedene Arten in Ihren Build gefaltet werden können. [Wir haben diese Idee erweitert, um von Hudson abgeleitete Informationen aufzunehmen, danke Marty-Lamb ].
Ant und Maven (sowie Hudson und Cruise Control) bieten eine einfache Möglichkeit, Build-Nummern in eine .properties-Datei oder in eine .txt / .html-Datei zu übertragen. Ist dies "sicher" genug, um zu verhindern, dass es absichtlich oder versehentlich manipuliert wird? Ist es besser, es zur Erstellungszeit in eine "Versionierungs" -Klasse zu kompilieren?
Behauptung: Die Build-Nummerierung sollte in einem kontinuierlichen Integrationssystem wie Hudson definiert / festgelegt werden . [Dank an marcelo-morales ] Wir haben diesen Vorschlag angenommen, aber er wirft die Frage der Release-Technik auf: Wie kommt es zu einer Veröffentlichung? Gibt es mehrere Build-Nummern in einer Version? Gibt es eine sinnvolle Beziehung zwischen Buildnummern aus verschiedenen Releases?
Frage: Was ist das Ziel einer Build-Nummer? Wird es für die Qualitätssicherung verwendet? Wie? Wird es hauptsächlich von Entwicklern verwendet, um während der Entwicklung zwischen mehreren Builds zu unterscheiden, oder mehr, damit die Qualitätssicherung feststellt, welchen Build ein Endbenutzer erhalten hat? Wenn das Ziel die Reproduzierbarkeit ist, sollte dies theoretisch eine Versionsnummer der Veröffentlichung bieten - warum nicht? (Bitte beantworten Sie dies als Teil Ihrer Antworten unten, um die von Ihnen getroffenen / vorgeschlagenen Entscheidungen zu beleuchten ...)
Frage: Gibt es in manuellen Builds einen Platz für Build-Nummern? Ist das so problematisch, dass JEDER eine CI-Lösung verwenden sollte?
Frage: Sollten Build-Nummern im SCM eingecheckt werden? Wenn das Ziel darin besteht, einen bestimmten Build zuverlässig und eindeutig zu identifizieren, wie mit einer Vielzahl von kontinuierlichen oder manuellen Build-Systemen umzugehen ist, die abstürzen / neu starten / etc ...
Frage: Sollte eine Build-Nummer kurz und bündig sein (dh eine monoton ansteigende Ganzzahl), so dass es einfach ist, sich für die Archivierung in Dateinamen zu stecken, in der Kommunikation leicht darauf zu verweisen usw. ... oder sollte sie lang und voller Benutzernamen sein? Datenstempel, Maschinennamen usw.?
Frage: Bitte geben Sie an, wie die Zuweisung von Build-Nummern in Ihren größeren automatisierten Freigabeprozess passt. Ja, Maven-Liebhaber, wir wissen, dass dies getan und getan ist, aber noch nicht alle von uns haben die Kool-Hilfe getrunken ...
Ich möchte dies wirklich in eine vollständige Antwort umwandeln, zumindest für das konkrete Beispiel unseres cvs / ant / hudson-Setups, damit jemand eine vollständige Strategie basierend auf dieser Frage entwickeln kann. Ich werde jeden als "Die Antwort" markieren, der eine Suppe-zu-Nuss-Beschreibung für diesen speziellen Fall geben kann (einschließlich Lebenslauf-Tagging-Schema, relevanten CI-Konfigurationselementen und Freigabeverfahren, bei denen die Build-Nummer programmgesteuert in die Freigabe gefaltet wird zugänglich.) Wenn Sie nach einer anderen bestimmten Konfiguration fragen / antworten möchten (z. B. SVN / Maven / Tempomat), werde ich von hier aus auf die Frage verlinken. - JA
[EDIT 23 Oct 09] Ich habe die Antwort mit der höchsten Abstimmung akzeptiert, weil ich denke, dass dies eine vernünftige Lösung ist, während einige der anderen Antworten auch gute Ideen enthalten. Wenn jemand eine Pause einlegen möchte, um einige davon mit Marty-Lamm zu synthetisieren , werde ich in Betracht ziehen, eine andere zu akzeptieren. Das einzige Problem, das ich mit Marty-Lambs habe, ist, dass es keine zuverlässig serialisierte Build-Nummer erzeugt - es hängt von einer lokalen Uhr im Builder-System ab, um eindeutige Build-Nummern bereitzustellen, was nicht großartig ist.
[Bearbeiten 10. Juli]
Wir schließen jetzt eine Klasse wie die folgende ein. Dadurch können die Versionsnummern in die endgültige ausführbare Datei kompiliert werden. Verschiedene Formen der Versionsinformationen werden in Protokolldaten und langfristig archivierten Ausgabeprodukten ausgegeben und verwendet, um unsere (manchmal Jahre später) Analyse von Ausgabeprodukten auf einen bestimmten Build zurückzuführen.
public final class AppVersion
{
// SVN should fill this out with the latest tag when it's checked out.
private static final String APP_SVNURL_RAW =
"$HeadURL: svn+ssh://user@host/svnroot/app/trunk/src/AppVersion.java $";
private static final String APP_SVN_REVISION_RAW = "$Revision: 325 $";
private static final Pattern SVNBRANCH_PAT =
Pattern.compile("(branches|trunk|releases)\\/([\\w\\.\\-]+)\\/.*");
private static final String APP_SVNTAIL =
APP_SVNURL_RAW.replaceFirst(".*\\/svnroot\\/app\\/", "");
private static final String APP_BRANCHTAG;
private static final String APP_BRANCHTAG_NAME;
private static final String APP_SVNREVISION =
APP_SVN_REVISION_RAW.replaceAll("\\$Revision:\\s*","").replaceAll("\\s*\\$", "");
static {
Matcher m = SVNBRANCH_PAT.matcher(APP_SVNTAIL);
if (!m.matches()) {
APP_BRANCHTAG = "[Broken SVN Info]";
APP_BRANCHTAG_NAME = "[Broken SVN Info]";
} else {
APP_BRANCHTAG = m.group(1);
if (APP_BRANCHTAG.equals("trunk")) {
// this isn't necessary in this SO example, but it
// is since we don't call it trunk in the real case
APP_BRANCHTAG_NAME = "trunk";
} else {
APP_BRANCHTAG_NAME = m.group(2);
}
}
}
public static String tagOrBranchName()
{ return APP_BRANCHTAG_NAME; }
/** Answers a formatter String descriptor for the app version.
* @return version string */
public static String longStringVersion()
{ return "app "+tagOrBranchName()+" ("+
tagOrBranchName()+", svn revision="+svnRevision()+")"; }
public static String shortStringVersion()
{ return tagOrBranchName(); }
public static String svnVersion()
{ return APP_SVNURL_RAW; }
public static String svnRevision()
{ return APP_SVNREVISION; }
public static String svnBranchId()
{ return APP_BRANCHTAG + "/" + APP_BRANCHTAG_NAME; }
public static final String banner()
{
StringBuilder sb = new StringBuilder();
sb.append("\n----------------------------------------------------------------");
sb.append("\nApplication -- ");
sb.append(longStringVersion());
sb.append("\n----------------------------------------------------------------\n");
return sb.toString();
}
}
Hinterlasse Kommentare, wenn dies eine Wiki-Diskussion verdient.
quelle
gradle
und / odergit
?Antworten:
Für einige meiner Projekte erfasse ich die Versionsnummer der Subversion, die Zeit, den Benutzer, der den Build ausgeführt hat, und einige Systeminformationen, füge sie in eine .properties-Datei ein, die in die Anwendungs-JAR aufgenommen wird, und lese diese JAR zur Laufzeit.
Der Ameisencode sieht folgendermaßen aus:
Es ist einfach, dies um alle Informationen zu erweitern, die Sie möglicherweise hinzufügen möchten.
quelle
Ihre build.xml
Dein Java-Code
quelle
META-INF/maven/<project group>/<project id>/pom.properties
. Die .properties-Datei enthält die version-Eigenschaft.quelle
Software:
Hudson hat drei Builds / Jobs: Continuous, Nightly und Release.
Für einen kontinuierlichen / nächtlichen Build: Die Build-Nummer ist die SVN-Revision, die mit svntask gefunden wurde.
Für einen Release-Build / Job: Build-Nummer ist die von Ant aus einer Eigenschaftendatei gelesene Release-Nummer. Die Eigenschaftendatei kann auch mit der Version zur Anzeige der Build-Nummer zur Laufzeit verteilt werden.
Das Ant-Build-Skript fügt die Build-Nummer in die Manifest-Datei der JAR / War-Dateien ein, die während des Builds erstellt werden. Gilt für alle Builds.
Post-Build-Aktion für Release-Builds, einfach mit einem Hudson-Plug-In: Tag-SVN mit der Build-Nummer.
Leistungen:
Hoffe das hilft.
quelle
Ich benutze auch Hudson, obwohl ein viel einfacheres Szenario:
Mein Ant-Skript enthält ein Ziel, das wie folgt aussieht:
Hudson legt diese Umgebungsvariablen für mich fest, wenn mein Job ausgeführt wird.
In meinem Fall ist dieses Projekt eine Webanwendung und ich füge diese
build-number.txt
Datei in den Stammordner der Webanwendung ein - es ist mir egal, wer sie sieht.In diesem Fall wird die Quellcodeverwaltung nicht mit Tags versehen, da unser Hudson-Job bereits so eingerichtet ist, dass er bei erfolgreichem Build mit der Build-Nummer / dem Zeitstempel versehen wird.
Meine Lösung deckt nur die inkrementellen Build-Nummern für die Entwicklung ab. Wir sind in dem Projekt, in dem wir die Release-Nummern behandeln, noch nicht weit genug gekommen.
quelle
Vielleicht möchten Sie auch einen Blick auf das BuildNumber Maven-Plugin und die Ant-Aufgabe in einem Glas werfen, das Sie unter http://code.google.com/p/codebistro/wiki/BuildNumber finden . Ich habe versucht, es einfach und unkompliziert zu machen. Es ist eine sehr kleine JAR-Datei, die nur von der installierten Befehlszeilen-Subversion abhängt.
quelle
So habe ich das gelöst:
Hier ist die Java-Datei, in der die Versionsinformationen gespeichert sind:
Und hier ist die Antitask "versioninfo":
quelle
Hier sind meine 2 Cent:
Mein Build-Skript erstellt bei jedem Erstellen der App eine Build-Nummer (mit Zeitstempel!). Dies erzeugt zu viele Zahlen, aber niemals zu wenige. Wenn ich eine Änderung im Code habe, ändert sich die Build-Nummer mindestens einmal.
Ich versioniere die Build-Nummer mit jeder Veröffentlichung (wenn auch nicht dazwischen). Wenn ich das Projekt aktualisiere und eine neue Build-Nummer erhalte (weil jemand anderes eine Version erstellt hat), überschreibe ich meine lokale Version und beginne von vorne. Dies kann zu einer niedrigeren Build-Nummer führen, weshalb ich den Zeitstempel eingefügt habe.
Wenn eine Veröffentlichung erfolgt, wird die Build-Nummer als letztes Element in einem einzelnen Commit mit der Meldung "Build 1547" festgeschrieben. Danach, wenn es sich um eine offizielle Veröffentlichung handelt, wird der gesamte Baum markiert. Auf diese Weise enthält die Build-Datei immer alle Tags und es gibt eine einfache 1: 1-Zuordnung zwischen Tags und Build-Nummern.
[BEARBEITEN] Ich stelle eine version.html mit meinen Projekten bereit und kann dann mit einem Scraper einfach eine genaue Karte erfassen, was wo installiert ist. Wenn Sie Tomcat oder ähnliches verwenden, geben Sie die Build-Nummer und den Zeitstempel in das
description
Element web.xml ein . Denken Sie daran: Merken Sie sich niemals etwas, wenn Sie es von einem Computer für Sie erledigen lassen können.quelle
Wir führen unseren Build über CruiseControl aus (fügen Sie hier Ihren bevorzugten Build-Manager ein) und führen den Haupt-Build und die Tests durch.
Anschließend erhöhen wir die Versionsnummer mit Ant und BuildNumber und erstellen eine Eigenschaftendatei mit diesen Informationen sowie dem Erstellungsdatum und anderen Metadaten.
Wir haben eine Klasse, die sich dem Lesen und Bereitstellen für GUIs / Protokolle usw. widmet.
Wir packen das alles zusammen und erstellen ein Deployable, das die Build-Nummer und den entsprechenden Build miteinander verbindet. Alle unsere Server geben diese Metainformationen beim Start aus. Wir können die CruiseControl-Protokolle erneut durchgehen und die Build-Nummer mit dem Datum und den Check-ins verknüpfen.
quelle