Quelles sont les meilleures pratiques actuelles pour la numérotation systématique des builds et la gestion des numéros de version dans les projets Java? Plus précisément:
Comment gérer systématiquement les numéros de build dans un environnement de développement distribué
Comment gérer les numéros de version dans la source / disponibles pour l'application d'exécution
Comment s'intégrer correctement au référentiel source
Comment gérer plus automatiquement les numéros de version par rapport aux balises de référentiel
Comment s'intégrer à une infrastructure de construction continue
Il existe un certain nombre d'outils disponibles, et ant (le système de construction que nous utilisons) a une tâche qui maintiendra un numéro de version, mais on ne sait pas comment gérer cela avec plusieurs développeurs simultanés utilisant CVS, svn ou similaire. .
[ÉDITER]
Plusieurs bonnes et utiles réponses partielles ou spécifiques sont apparues ci-dessous, je vais donc en résumer quelques-unes. Il me semble qu'il n'y a pas vraiment de «bonnes pratiques» solides à ce sujet, mais plutôt une collection d'idées qui se chevauchent. Ci-dessous, retrouvez mes résumés et quelques questions qui en découlent auxquelles les gens pourraient essayer de répondre en guise de suivi. [Nouveau dans stackoverflow ... veuillez fournir des commentaires si je fais cela mal.]
Si vous utilisez SVN, la gestion des versions d'une extraction spécifique est fournie pour le trajet. La numérotation de build peut exploiter cela pour créer un numéro de build unique qui identifie l'extraction / révision spécifique. [CVS, que nous utilisons pour des raisons héritées, ne fournit pas tout à fait ce niveau de perspicacité ... une intervention manuelle avec des balises vous permet d'y arriver.]
Si vous utilisez maven comme système de construction, il existe un support pour la production d'un numéro de version à partir du SCM, ainsi qu'un module de publication pour produire automatiquement des versions. [Nous ne pouvons pas utiliser maven, pour diverses raisons, mais cela aide ceux qui le peuvent. [Merci à marcelo-morales ]]
Si vous utilisez ant comme système de construction, la description de tâche suivante peut vous aider à produire un fichier Java .properties capturant les informations de construction, qui peuvent ensuite être intégrées à votre construction de différentes manières. [Nous avons développé cette idée pour inclure des informations dérivées de Hudson , merci marty-lamb ].
Ant et maven (et hudson et régulateur de vitesse) fournissent des moyens simples pour obtenir des numéros de build dans un fichier .properties, ou dans un fichier .txt / .html. Est-ce suffisamment «sûr» pour l'empêcher d'être falsifié intentionnellement ou accidentellement? Est-il préférable de le compiler dans une classe de «gestion des versions» au moment de la construction?
Assertion: la numérotation des builds doit être définie / mise en œuvre dans un système d'intégration continue comme hudson . [Merci à marcelo-morales ] Nous avons pris cette suggestion, mais cela permet d'ouvrir la question de l'ingénierie de publication: comment une publication se produit-elle? Existe-t-il plusieurs numéros de build dans une version? Existe-t-il une relation significative entre les numéros de build de différentes versions?
Question: Quel est l'objectif derrière un numéro de build? Est-il utilisé pour l'assurance qualité? Comment? Est-il principalement utilisé par les développeurs pour lever l'ambiguïté entre plusieurs builds pendant le développement, ou plus pour le contrôle qualité afin de déterminer quelle build un utilisateur final a? Si l'objectif est la reproductibilité, c'est en théorie ce que devrait fournir un numéro de version - pourquoi pas? (veuillez répondre à cela dans le cadre de vos réponses ci-dessous, cela aidera à éclairer les choix que vous avez faits / suggérés ...)
Question: Y a-t-il une place pour les numéros de build dans les builds manuels? Est-ce si problématique que TOUT LE MONDE devrait utiliser une solution CI?
Question: Les numéros de build doivent-ils être enregistrés dans le SCM? Si l'objectif est d'identifier de manière fiable et sans ambiguïté une construction particulière, comment faire face à une variété de systèmes de construction continue ou manuelle qui peuvent planter / redémarrer / etc ...
Question: Si un numéro de build doit être court et doux (c'est-à-dire, un nombre entier croissant de manière monotone) afin qu'il soit facile de s'en tenir aux noms de fichiers pour l'archivage, de s'y référer facilement dans la communication, etc ... ou devrait-il être long et plein de noms d'utilisateur, horodatages, noms de machines, etc.?
Question: Veuillez fournir des détails sur la manière dont l'attribution des numéros de build s'intègre dans votre processus de publication automatisé plus large. Oui, amateurs de maven, nous savons que c'est fait et fait, mais nous n'avons pas tous encore bu le kool-aid ...
Je voudrais vraiment donner une réponse complète, au moins pour l'exemple concret de notre configuration cvs / ant / hudson, afin que quelqu'un puisse construire une stratégie complète basée sur cette question. Je marquerai comme "La réponse" toute personne qui peut donner une description de la soupe aux noix pour ce cas particulier (y compris le schéma de balisage cvs, les éléments de configuration CI pertinents et la procédure de publication qui replie le numéro de build dans la version de sorte qu'il soit programmé accessible.) Si vous voulez demander / répondre pour une autre configuration particulière (par exemple, svn / maven / régulateur de vitesse), je vais créer un lien vers la question à partir d'ici. --JA
[EDIT 23 octobre 09] J'ai accepté la réponse la plus votée parce que je pense que c'est une solution raisonnable, alors que plusieurs des autres réponses incluent également de bonnes idées. Si quelqu'un veut essayer de synthétiser certains d'entre eux avec des marty-lambs, j'envisagerai d'en accepter un autre. Le seul souci que j'ai avec marty-lamb's est qu'il ne produit pas de numéro de build sérialisé de manière fiable - cela dépend d'une horloge locale du système du constructeur pour fournir des numéros de build sans ambiguïté, ce qui n'est pas génial.
[Modifier le 10 juillet]
Nous incluons maintenant une classe comme ci-dessous. Cela permet aux numéros de version d'être compilés dans l'exécutable final. Différentes formes d'informations de version sont émises dans les données de journalisation, les produits de sortie archivés à long terme et utilisées pour retracer notre analyse (parfois des années plus tard) des produits de sortie jusqu'à une version spécifique.
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();
}
}
Laissez des commentaires si cela mérite de devenir une discussion wiki.
gradle
et / ou git
?