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.
gradle
und / oder git
?