Jakie są aktualne najlepsze praktyki dotyczące systematycznego numerowania kompilacji i zarządzania numerami wersji w projektach Java? Konkretnie:
Jak systematycznie zarządzać numerami kompilacji w rozproszonym środowisku programistycznym
Jak zachować numery wersji w źródle / dostępne dla aplikacji uruchomieniowej
Jak poprawnie zintegrować się z repozytorium źródeł
Jak bardziej automatycznie zarządzać numerami wersji a znacznikami repozytorium
Jak zintegrować się z infrastrukturą ciągłego budowania
Dostępnych jest wiele narzędzi, a ant (system kompilacji, którego używamy) ma zadanie, które będzie utrzymywać numer kompilacji, ale nie jest jasne, jak zarządzać tym z wieloma współbieżnymi programistami używającymi CVS, svn lub podobnych .
[EDYTOWAĆ]
Poniżej pojawiło się kilka dobrych i pomocnych odpowiedzi częściowych lub szczegółowych, więc podsumuję kilka z nich. Wydaje mi się, że nie ma w tej kwestii mocnej „najlepszej praktyki”, a raczej zbiór pokrywających się pomysłów. Poniżej znajdują się moje podsumowania i niektóre wynikające z nich pytania, na które ludzie mogą spróbować odpowiedzieć w ramach dalszych działań. [Nowość w stackoverflow… Jeśli robię to źle, podaj komentarze.]
Jeśli korzystasz z SVN, podczas jazdy pojawia się wersja konkretnego zamówienia. Numeracja kompilacji może to wykorzystać do stworzenia unikalnego numeru kompilacji, który identyfikuje konkretną kasę / wersję. [CVS, którego używamy ze starszych powodów, nie zapewnia takiego poziomu wglądu… ręczna interwencja przy użyciu tagów prowadzi do częściowego celu.]
Jeśli używasz maven jako systemu kompilacji, istnieje wsparcie dla tworzenia numeru wersji z SCM, a także moduł wydania do automatycznego tworzenia wydań. [Nie możemy używać mavena z różnych powodów, ale to pomaga tym, którzy mogą. [Podziękowania dla Marcelo-Morales ]]
Jeśli używasz ant jako systemu budowania, poniższy opis zadania może pomóc w utworzeniu pliku Java .properties przechwytującego informacje o kompilacji, które można następnie złożyć w kompilacji na wiele sposobów. [Rozszerzyliśmy ten pomysł, aby uwzględnić informacje pochodzące z hudsona , dzięki marty-lamb ].
Ant i maven (oraz hudson i cruise control) zapewniają łatwe sposoby pobierania numerów kompilacji do pliku .properties lub do pliku .txt / .html. Czy jest to wystarczająco „bezpieczne”, aby zapobiec celowej lub przypadkowej manipulacji? Czy lepiej skompilować go do klasy „wersjonowania” w czasie kompilacji?
Asercja: numeracja kompilacji powinna być zdefiniowana / uchwalona w systemie ciągłej integracji, takim jak Hudson . [Dzięki marcelo-morales ] Podjęliśmy się tej sugestii, ale otwiera ona pytanie dotyczące inżynierii wydania: Jak następuje wydanie? Czy w wydaniu jest wiele numerów kompilacji? Czy istnieje znacząca zależność między numerami kompilacji z różnych wersji?
Pytanie: Jaki jest cel numeru kompilacji? Czy jest używany do kontroli jakości? W jaki sposób? Czy jest używany głównie przez programistów do rozróżniania wielu kompilacji podczas programowania, czy też bardziej do kontroli jakości w celu ustalenia, jaką kompilację otrzymał użytkownik końcowy? Jeśli celem jest powtarzalność, teoretycznie to właśnie powinien zapewniać numer wersji wydania - dlaczego nie? (proszę odpowiedzieć na to jako część swoich odpowiedzi poniżej, pomoże to oświetlić wybory, których dokonałeś / zasugerowałeś ...)
Pytanie: Czy jest miejsce na numery kompilacji w kompilacjach ręcznych? Czy jest to tak problematyczne, że WSZYSCY powinni używać rozwiązania CI?
Pytanie: Czy numery kompilacji należy wpisywać do SCM? Jeśli celem jest niezawodne i jednoznaczne zidentyfikowanie konkretnej kompilacji, jak radzić sobie z różnymi systemami kompilacji ciągłej lub ręcznej, które mogą ulec awarii / ponownym uruchomieniu / itp.
Pytanie: Czy numer kompilacji powinien być krótki i przyjemny (tj. Monotonicznie rosnąca liczba całkowita), aby można go było łatwo umieścić w nazwach plików w celu archiwizacji, łatwo się do nich odwoływać w komunikacji itp. Lub powinien być długi i pełen nazw użytkowników, datowniki, nazwy maszyn itp.?
Pytanie: podaj szczegółowe informacje o tym, jak przypisanie numerów kompilacji pasuje do Twojego większego automatycznego procesu wydawania. Tak, kochankowie maven, wiemy, że to jest zrobione i zrobione, ale nie wszyscy z nas jeszcze wypili kool-aid ...
Naprawdę chciałbym przekształcić to w kompletną odpowiedź, przynajmniej dla konkretnego przykładu naszej konfiguracji cvs / ant / hudson, aby ktoś mógł zbudować kompletną strategię w oparciu o to pytanie. Oznaczę jako „The Answer” każdego, kto może podać opis zupy do orzechów dla tego konkretnego przypadku (w tym schemat znakowania CVS, odpowiednie elementy konfiguracji CI i procedurę wydania, która składa numer kompilacji w wydaniu tak, że jest to programowo dostępne.) Jeśli chcesz zapytać / odpowiedzieć na inną konkretną konfigurację (powiedzmy, svn / maven / cruise control), podam link do pytania tutaj. - JA
[EDYCJA 23 października 09] Przyjąłem odpowiedź, która została najwyżej oceniona, ponieważ uważam, że jest to rozsądne rozwiązanie, podczas gdy kilka innych odpowiedzi zawiera również dobre pomysły. Jeśli ktoś chce spróbować zsyntetyzować niektóre z nich z owieczkami martyrologicznymi , rozważę wybór innego. Jedynym problemem, jaki mam w przypadku marty-lamb's, jest to, że nie generuje on niezawodnie zserializowanego numeru kompilacji - zależy to od lokalnego zegara w systemie konstruktora, który zapewnia jednoznaczne numery kompilacji, co nie jest świetne.
[Edytuj 10 lipca]
Teraz dołączamy klasę taką jak poniżej. Pozwala to skompilować numery wersji do ostatecznego pliku wykonywalnego. Różne formy informacji o wersji są emitowane w danych logowania, długoterminowych zarchiwizowanych produktach wyjściowych i wykorzystywane do śledzenia naszej (czasami po latach) analizy produktów wyjściowych do określonej wersji.
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();
}
}
Zostaw komentarze, jeśli zasługuje na to, aby stać się dyskusją na wiki.
gradle
i / lub git
?