Numeración de comstackción y versión para proyectos de Java (ant, cvs, hudson)

¿Cuáles son las mejores prácticas actuales para la numeración de comstackción sistemática y la gestión del número de versión en los proyectos de Java? Específicamente:

  • Cómo administrar los números de comstackción sistemáticamente en un entorno de desarrollo distribuido

  • Cómo mantener los números de versión en fuente / disponible para la aplicación en tiempo de ejecución

  • Cómo integrarse correctamente con el repository fuente

  • Cómo gestionar más automáticamente los números de versión frente a las tags de repository

  • Cómo integrarse con la infraestructura de construcción continua

Hay bastantes herramientas disponibles, y ant (el sistema de comstackción que estamos usando) tiene una tarea que mantendrá un número de comstackción, pero no está claro cómo administrar esto con múltiples desarrolladores simultáneos que usan CVS, svn o similar. .

[EDITAR]

Varias respuestas parciales o específicas buenas y útiles aparecieron a continuación, por lo que resumiré algunas de ellas. Me parece que no hay una “buena práctica” fuerte en esto, sino una colección de ideas superpuestas. A continuación, encuentre mis resúmenes y algunas preguntas resultantes que la gente podría tratar de responder como seguimiento. [Nuevo en stackoverflow … por favor proporcione comentarios si estoy haciendo esto mal.]

  • Si está utilizando SVN, el versionado de un pago específico viene para el viaje. La numeración de comstackción puede explotar esto para crear un número de comstackción único que identifique la revisión / revisión específica. [CVS, que estamos usando por razones heredadas, no proporciona este nivel de conocimiento … la intervención manual con tags lo lleva a un lugar intermedio allí].

  • Si está utilizando maven como su sistema de comstackción, existe soporte para producir un número de versión del SCM, así como un módulo de lanzamiento para producir automáticamente las versiones. [No podemos usar maven, por una variedad de razones, pero esto ayuda a quienes sí pueden. [Gracias a Marcelo-Morales ]]

  • Si está utilizando ant como su sistema de comstackción, la siguiente descripción de tareas puede ayudar a producir un archivo Java .properties que capture la información de comstackción, que luego se puede incorporar a su comstackción de varias maneras. [Ampliamos esta idea para incluir información derivada de hudson, gracias marty-lamb ].

  • Ant y maven (y Hudson y control de crucero) proporcionan medios fáciles para obtener números de comstackción en un archivo .properties, o en un archivo .txt / .html. ¿Es esto “seguro” suficiente para evitar que sea manipulado de forma intencional o accidental? ¿Es mejor comstackrlo en una clase de “control de versiones” en tiempo de comstackción?

  • Afirmación: la numeración de comstackción debe definirse / promulgarse en un sistema de integración continua como Hudson . [Gracias a marcelo-morales ] Hemos tomado esta sugerencia, pero abre la cuestión de la ingeniería de lanzamiento: ¿cómo ocurre un lanzamiento? ¿Hay varios buildnumbers en una versión? ¿Existe una relación significativa entre buildnumbers de diferentes lanzamientos?

  • Pregunta: ¿Cuál es el objective detrás de un número de comstackción? ¿Se usa para QA? ¿Cómo? ¿Lo utilizan principalmente los desarrolladores para eliminar la ambigüedad entre varias comstackciones durante el desarrollo, o más para QA determinar qué comstackción obtuvo un usuario final? Si el objective es la reproducibilidad, en teoría esto es lo que debe proporcionar un número de versión de lanzamiento, ¿por qué no? (Por favor, responda esto como parte de sus respuestas a continuación, esto ayudará a iluminar las elecciones que ha hecho / sugerido …)

  • Pregunta: ¿Hay un lugar para construir números en comstackciones manuales? ¿Es esto tan problemático que TODOS deberían usar una solución de CI?

  • Pregunta: ¿Deben registrarse los números de construcción en el SCM? Si el objective es identificar de manera confiable e inequívoca una comstackción en particular, cómo hacer frente a una variedad de sistemas de comstackción continuos o manuales que pueden bloquearse / reiniciarse / etc …

  • Pregunta: ¿Debería un número de comstackción ser breve y atractivo (es decir, un número entero que aumenta monótonamente) para que sea fácil incluir los nombres de los archivos para el archivo, sea fácil referirlo a la comunicación, etc. o debería ser largo y estar lleno de nombres de usuario, datestamps, nombres de máquinas, etc.

  • Pregunta: proporcione detalles sobre cómo la asignación de los números de comstackción se ajusta a su proceso de lanzamiento automatizado más grande. Sí, amantes de los maven, sabemos que esto está hecho y hecho, pero no todos hemos bebido el kool-aid todavía …

Realmente me gustaría desarrollar esto en una respuesta completa, al menos para el ejemplo concreto de nuestra configuración cvs / ant / hudson, para que alguien pueda construir una estrategia completa basada en esta pregunta. Marcaré como “La respuesta” a cualquiera que pueda dar una descripción de sopa a nueces para este caso particular (incluido el esquema de etiquetado de cvs, elementos de configuración de CI relevantes y procedimiento de liberación que pliega el número de comstackción en el lanzamiento de manera programática accesible.) Si desea preguntar / responder por otra configuración en particular (por ejemplo, svn / maven / control de crucero) voy a vincular a la pregunta desde aquí. –JA

[EDIT 23 oct 09] Acepté la respuesta más votadas porque creo que es una solución razonable, mientras que varias de las otras respuestas también incluyen buenas ideas. Si alguien quiere intentar descifrar algunos de estos con marty-lamb ‘s, consideraré aceptar uno diferente. La única preocupación que tengo con Marty-lamb es que no produce un número de comstackción confiablemente serializado; depende de un reloj local en el sistema del constructor para proporcionar números de construcción no ambiguos, lo cual no es muy bueno.

[Editar Jul 10]

Ahora incluimos una clase como la siguiente. Esto permite que los números de versión se compilen en el ejecutable final. Se emiten diferentes formas de información de versión en datos de registro, productos de salida archivados a largo plazo, y se usan para rastrear nuestro análisis (a veces años después) de productos de salida para una comstackción específica.

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(); } } 

Deje comentarios si esto merece convertirse en una discusión wiki.

Para varios de mis proyectos, capturo el número de revisión de subversión, el tiempo, el usuario que ejecutó la comstackción y cierta información del sistema, los rellene en un archivo .properties que se incluye en el archivo jar de la aplicación, y lo leo en tiempo de ejecución.

El código de la ant se ve así:

                  

Es simple extender esto para incluir cualquier información que desee agregar.

Tu build.xml

 ...  ...    ...   ...   ... 

Tu código java

 String ver = MyClass.class.getPackage().getImplementationVersion(); 
  • Los números de comstackción deben asociarse con un servidor de integración continua como Hudson . Use diferentes trabajos para diferentes twigs / equipos / distribuciones.
  • Para mantener el número de versión en la comstackción final, recomendaría usar maven para el sistema de comstackción. Creará un archivo .properties archivado en el .jar / .war / .whatever-ar final en META-INF/maven///pom.properties . El archivo .properties contendrá la propiedad de la versión.
  • Como estoy recomendando a Maven, le recomiendo que revise el complemento de publicación para preparar el lanzamiento en el repository de origen y mantener sincronizadas las versiones.

Software:

Hudson tiene tres builds / jobs: Continuous, Nightly y Release.

Para una construcción Continua / Nocturna: el número de comstackción es la revisión SVN, que se encuentra usando svntask.

Para una comstackción / tarea de lanzamiento: el número de comstackción es el número de la versión, leída por Ant, desde un archivo de propiedades. El archivo de propiedades también se puede distribuir con el lanzamiento para mostrar el número de comstackción en tiempo de ejecución.

El script de comstackción Ant coloca el número de comstackción en el archivo de manifiesto de los archivos jar / war que se crean durante la comstackción. Se aplica a todas las construcciones.

Acción posterior a la construcción para comstackciones de Release, realizada fácilmente con un complemento de Hudson: etiquetar SVN con el número de comstackción.

Beneficios:

  • Para una versión dev de un jar / war, el desarrollador puede encontrar la revisión SVN del jar / war y buscar el código correspondiente en SVN
  • Para un lanzamiento, la revisión SVN es la que corresponde a la etiqueta SVN que tiene el número de versión en ella.

Espero que esto ayude.

También estoy usando Hudson, aunque es un escenario mucho más simple:

Mi script Ant tiene un objective que se ve así:

   Build: ${env.BUILD_TAG}, Id: ${env.BUILD_ID}, URL: ${env.HUDSON_URL}  

Hudson establece estas variables de entorno cada vez que se ejecuta mi trabajo.

En mi caso, este proyecto es una aplicación web y estoy incluyendo este archivo build-number.txt en la carpeta raíz de la aplicación web; realmente no me importa quién lo vea.

No etiquetamos el control de origen cuando esto se hace porque ya tenemos nuestro trabajo de Hudson configurado para etiquetarlo con el número de comstackción / marca de tiempo cuando la construcción es exitosa.

Mi solución solo cubre los números incrementales de desarrollo, no hemos llegado lo suficientemente lejos en el proyecto donde cubrimos los números de lanzamiento todavía.

También puede consultar el plugin BuildNumber Maven y la tarea Ant en un contenedor que se encuentra en http://code.google.com/p/codebistro/wiki/BuildNumber . Traté de hacerlo simple y directo. Es un archivo jar muy pequeño que solo depende de la línea de comando Subversion instalada.

Así es como resolví esto:

  • las fonts se copian en el directorio de comstackción
  • entonces se aplica la anttask “versioninfo”
  • comstackr las fonts modificadas

Aquí está el archivo java que almacena la información de la versión:

 public class Settings { public static final String VERSION = "$VERSION$"; public static final String DATE = "$DATE$"; } 

Y aquí está la anttask “versioninfo”:

                   

Aquí está mi 2 centavos:

  • Mi script de comstackción crea un número de comstackción (con timestamp!) Cada vez que construyo la aplicación. Esto crea demasiados números, pero nunca demasiado pocos. Si tengo un cambio en el código, el número de comstackción cambiará al menos una vez.

  • Versión del número de comstackción con cada versión (aunque no entre medio). Cuando actualizo el proyecto y obtengo un nuevo número de comstackción (porque alguien más hizo un lanzamiento), sobrescribo mi versión local y comienzo de nuevo. Esto puede llevar a un número de comstackción menor, razón por la cual he incluido la marca de tiempo.

  • Cuando ocurre una publicación, el número de comstackción se confirma como el último elemento en una única confirmación con el mensaje “comstackr 1547”. Después de eso, cuando se trata de un lanzamiento oficial, todo el árbol está etiquetado. De esta forma, el archivo de comstackción siempre tiene todas las tags y existe una asignación simple 1: 1 entre tags y números de comstackción.

[EDITAR] Desplegué un version.html con mis proyectos y luego, puedo usar un raspador para simplemente recolectar un mapa preciso en el que está instalado. Si usa Tomcat o similar, coloque el número de comstackción y la marca de tiempo en el elemento de description de web.xml . Recuerde: Nunca memorice nada cuando pueda hacer que una computadora lo haga por usted.

Ejecutamos nuestra comstackción a través de CruiseControl (inserte aquí su administrador de comstackción favorito) y realizamos la comstackción principal y las pruebas.

Luego incrementamos el número de versión usando Ant y BuildNumber y creamos un archivo de propiedad con esta información más la fecha de comstackción y otros metadatos.

Tenemos una clase dedicada a leer esto y proporcionarlo a las GUI / registros, etc.

A continuación, empaquetamos todo esto y creamos un despliegue que vincula el número de comstackción y la comstackción correspondiente. Todos nuestros servidores vuelcan esta meta información en el arranque. Podemos retroceder a través de los registros de CruiseControl y vincular el número de comstackción a la fecha y los registros.