Création et numérotation de version pour les projets Java (ant, cvs, hudson)



Answers

Votre build.xml

...
<property name="version" value="1.0"/>
...
<target name="jar" depends="compile">
    <buildnumber file="build.num"/>
    <manifest file="MANIFEST.MF">
        ...
        <attribute name="Main-Class" value="MyClass"/>
        <attribute name="Implementation-Version" value="${version}.${build.number}"/>
        ...
    </manifest>
</target>
...

Votre code java

String ver = MyClass.class.getPackage().getImplementationVersion();
Question

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 les numéros de build systématiquement 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 intégrer correctement avec le référentiel source

  • Comment gérer plus automatiquement les numéros de version par rapport aux tags de référentiel

  • Comment intégrer avec l'infrastructure de construction continue

Il y a 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 build, mais on ne sait pas comment gérer cela avec plusieurs développeurs simultanés utilisant CVS, svn, ou similaire .

[MODIFIER]

Plusieurs bonnes réponses partielles ou spécifiques sont apparues ci-dessous. Je vais en résumer quelques-unes. Il me semble qu'il n'y a pas vraiment de «meilleure pratique» à cet égard, mais plutôt une collection d'idées qui se chevauchent. Ci-dessous, retrouvez mes résumés et quelques questions qui en résulteront auxquelles les gens pourraient essayer de répondre en tant que suivis. [Nouveau sur ... s'il vous plaît fournir des commentaires si je me trompe.]

  • Si vous utilisez SVN, le contrôle de version d'un contrôle spécifique vient pour le tour. La numérotation de construction peut exploiter ceci pour créer un numéro de build unique qui identifie la vérification / révision spécifique. [CVS, que nous utilisons pour des raisons héritées, ne fournit pas ce niveau de compréhension ... l'intervention manuelle avec des tags vous permet d'y arriver.]

  • Si vous utilisez maven comme système de construction, il existe un support pour produire un numéro de version à partir du SCM, ainsi qu'un module de lancement 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 aider à produire un fichier Java .properties capturant des informations de construction, qui peuvent ensuite être pliées dans votre construction de plusieurs façons. [Nous avons développé cette idée pour inclure l'information dérivée de marty-lamb , merci marty-lamb ].

  • Ant et maven (et hudson et cruise control) fournissent des moyens simples d'obtenir les numéros de build dans un fichier .properties ou dans un fichier .txt / .html. Est-ce assez «sûr» pour ne pas être altéré intentionnellement ou accidentellement? Est-il préférable de le compiler dans une classe "versioning" au moment de la construction?

  • Affirmation: La numérotation des constructions devrait être définie / mise en œuvre dans un système d'intégration continue tel que hudson . [Merci à marcelo-morales ] Nous avons pris cette suggestion, mais elle ouvre la question de l'ingénierie des versions: Comment se passe une publication? Y a-t-il plusieurs numéros de build dans une version? Existe-t-il une relation significative entre les numéros de build des 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 utilisé principalement par les développeurs pour désambiguïser entre plusieurs générations au cours du développement, ou plus pour l'assurance qualité afin de déterminer ce que l'utilisateur final obtient? Si le but est la reproductibilité, en théorie c'est ce que devrait fournir un numéro de version - pourquoi pas? (répondez s'il vous plaît ceci comme une partie 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 archivés dans le SCM? Si l'objectif est d'identifier de façon fiable et sans ambiguïté une construction particulière, comment faire face à une variété de systèmes de construction continus ou manuels qui peuvent planter / redémarrer / etc ...

  • Question: Un nombre de build doit-il être court et doux (c'est-à-dire monotone augmentant l'entier) pour qu'il soit facile de coller dans les noms de fichier pour l'archivage, facile à référencer dans la communication, etc ... ou devrait être long et plein de noms d'utilisateurs, datestamps, 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 libération automatique plus important. Oui, les amateurs de maven, nous savons que cela est fait et fait, mais nous n'avons pas encore tous bu le kool-aid ...

J'aimerais vraiment donner une réponse complète, du 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 désignerai comme "la réponse" quiconque peut donner une description de la soupe aux noix pour ce cas particulier (y compris le système de marquage cvs, les éléments de configuration CI pertinents, et la procédure de publication qui plie le numéro de build dans la version. accessible.) Si vous voulez demander / répondre pour une autre configuration particulière (par exemple, svn / maven / régulateur de vitesse) je vais lier à la question d'ici. --JA

[EDIT 23 oct 09] J'ai accepté la réponse la mieux votée parce que je pense que c'est une solution raisonnable, alors que plusieurs des autres réponses incluent aussi de bonnes idées. Si quelqu'un veut marty-lamb synthétiser certaines d'entre elles avec un marty-lamb , je vais envisager d'en accepter une autre. La seule préoccupation que j'ai avec marty-agneau est qu'il ne produit pas un numéro de construction sériellement sérialisé - il dépend d'une horloge locale dans le système du constructeur pour fournir des numéros de construction non ambigus, ce qui n'est pas génial.

[Modifier juil. 10]

Nous incluons maintenant une classe comme ci-dessous. Cela permet de compiler les numéros de version 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 tracer notre analyse (parfois des années plus tard) des produits de sortie vers une construction 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.




Logiciel:

  • SVN
  • Fourmi
  • Hudson, pour une intégration continue
  • svntask, une tâche Ant pour trouver la révision SVN: http://code.google.com/p/svntask/

Hudson a trois builds / jobs: Continuous, Nightly et Release.

Pour une construction Continuous / Nightly: Le numéro de build est la révision SVN, trouvée en utilisant svntask.

Pour une version build / job: Build number est le numéro de version, lu par Ant, à partir d'un fichier de propriétés. Le fichier de propriétés peut également être distribué avec la version pour afficher le numéro de build au moment de l'exécution.

Le script de génération Ant place le numéro de build dans le fichier manifeste des fichiers jar / war créés lors de la construction. S'applique à toutes les générations.

Action post-construction pour les versions Release, effectuée facilement à l'aide d'un plug-in Hudson: balise SVN avec le numéro de build.

Avantages:

  • Pour une version de développement d'un jar / war, le développeur peut trouver la révision SVN depuis le jar / war et chercher le code correspondant dans SVN
  • Pour une version, la révision SVN est celle correspondant à la balise SVN qui contient le numéro de version.

J'espère que cela t'aides.




Voici mes 2 cents:

  • Mon script de construction crée un numéro de build (avec horodatage!) Chaque fois que je construis l'application. Cela crée trop de nombres mais jamais trop peu. Si j'ai un changement dans le code, le numéro de build changera au moins une fois.

  • Je version le numéro de build avec chaque version (mais pas entre les deux). Lorsque je mets à jour le projet et que je reçois un nouveau numéro de build (parce que quelqu'un d'autre a fait une version), j'écris ma version locale et recommence. Cela peut conduire à un nombre de build inférieur, c'est pourquoi j'ai inclus l'horodatage.

  • Lorsqu'une version arrive, le numéro de build est validé en tant que dernier élément dans un seul commit avec le message "build 1547". Après cela, quand c'est une version officielle, l'arbre entier est étiqueté. De cette façon, le fichier de construction contient toujours toutes les balises et il existe un simple mappage 1: 1 entre les balises et les numéros de build.

[EDIT] Je déploie une version.html avec mes projets et ensuite, je peux utiliser un grattoir pour simplement collecter une carte précise de ce qui est installé où. Si vous utilisez Tomcat ou similaire, placez le numéro de build et l'horodatage dans l'élément de web.xml de web.xml . Rappelez-vous: ne jamais mémoriser quelque chose quand vous pouvez avoir un ordinateur le faire pour vous.




Vous pouvez également jeter un coup d'œil au plugin BuildNumber Maven et à la tâche Ant dans un pot à l' http://code.google.com/p/codebistro/wiki/BuildNumber . J'ai essayé de le rendre simple et direct. C'est un très petit fichier jar qui ne dépend que de la ligne de commande Subversion installée.




Links