¿Cuáles son las mejores prácticas actuales para la numeración de compilación sistemática y la gestión del número de versión en proyectos Java? Específicamente:
Cómo administrar números de compilación sistemáticamente en un entorno de desarrollo distribuido
Cómo mantener los números de versión en origen / disponibles para la aplicación en tiempo de ejecución
Cómo integrarse correctamente con el repositorio de origen
Cómo administrar más automáticamente los números de versión frente a las etiquetas de repositorio
Cómo integrarse con una infraestructura de construcción continua
Hay bastantes herramientas disponibles, y ant (el sistema de compilación que estamos usando) tiene una tarea que mantendrá un número de compilación, pero no está claro cómo administrar esto con múltiples desarrolladores concurrentes que usan CVS, svn o similar .
[EDITAR]
Varias respuestas parciales o específicas buenas y útiles han aparecido a continuación, así que resumiré algunas de ellas. Me parece que en realidad no hay una "mejor práctica" sólida sobre esto, sino una colección de ideas superpuestas. A continuación, encuentre mis resúmenes y algunas preguntas resultantes que la gente podría intentar responder como seguimientos. [Nuevo en stackoverflow ... proporcione comentarios si estoy haciendo esto mal]
Si está utilizando SVN, la versión de un pago específico aparece para el viaje. La numeración de compilación puede explotar esto para crear un número de compilación único que identifique la comprobación / revisión específica. [CVS, que estamos utilizando por razones heredadas, no proporciona este nivel de conocimiento ... la intervención manual con etiquetas lo lleva a la mitad del camino].
Si está utilizando Maven como su sistema de compilación, hay soporte para producir un número de versión desde SCM, así como un módulo de lanzamiento para producir lanzamientos automáticamente. [No podemos usar Maven, por una variedad de razones, pero esto ayuda a aquellos que sí pueden. [Gracias a marcelo-morales ]]
Si está utilizando hormiga como su sistema de compilación, la siguiente descripción de tarea puede ayudarlo a producir un archivo .properties de Java que capture la información de compilación, que luego se puede plegar en su compilació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 compilación en un archivo .properties, o en un archivo .txt / .html. ¿Es esto lo suficientemente "seguro" como para evitar que sea manipulado intencionalmente o accidentalmente? ¿Es mejor compilarlo en una clase de "versiones" en tiempo de compilación?
Afirmación: La numeración de compilación debe definirse / promulgarse en un sistema de integración continua como Hudson . [Gracias a marcelo-morales ] Hemos tomado esta sugerencia, pero abre la pregunta de ingeniería de lanzamiento: ¿Cómo ocurre un lanzamiento? ¿Hay varios números de compilación en una versión? ¿Existe una relación significativa entre los números de compilación de diferentes versiones?
Pregunta: ¿Cuál es el objetivo detrás de un número de compilación? ¿Se usa para el control de calidad? ¿Cómo? ¿Lo utilizan principalmente los desarrolladores para desambiguar entre varias compilaciones durante el desarrollo, o más para el control de calidad para determinar qué compilación obtuvo un usuario final? Si el objetivo es la reproducibilidad, en teoría esto es lo que debe proporcionar un número de versión de lanzamiento, ¿por qué no? (responda esto como parte de sus respuestas a continuación, ayudará a iluminar las elecciones que ha hecho / sugerido ...)
Pregunta: ¿Hay un lugar para los números de compilación en las compilaciones manuales? ¿Es esto tan problemático que TODOS deberían usar una solución de CI?
Pregunta: ¿Deberían registrarse los números de compilación en el SCM? Si el objetivo es identificar de manera confiable e inequívoca una compilación en particular, cómo hacer frente a una variedad de sistemas de compilación continua o manual que pueden bloquearse / reiniciarse, etc.
Pregunta: ¿Debe un número de compilación ser corto y dulce (es decir, un número entero que aumenta monotónicamente) para que sea fácil pegarse en los nombres de archivo para el archivo, fácil de consultar en la comunicación, etc., o debe ser largo y lleno de nombres de usuario, sellos de fecha, nombres de máquinas, etc.
Pregunta: Proporcione detalles sobre cómo la asignación de números de compilación se ajusta a su proceso de lanzamiento automatizado más grande. Sí, amantes de Maven, sabemos que esto ya está 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 este caso en particular (incluido el esquema de etiquetado cvs, los elementos de configuración de CI relevantes y el procedimiento de lanzamiento que dobla el número de compilación en el lanzamiento de manera programática). accesible.) Si desea preguntar / responder para otra configuración particular (por ejemplo, svn / maven / control de crucero), enlazaré con la pregunta desde aquí. --JA
[EDITAR 23 oct 09] Acepté la respuesta mejor votada porque creo que es una solución razonable, mientras que varias de las otras respuestas también incluyen buenas ideas. Si alguien quiere probar sintetizar algunos de estos con marty-lamb 's, consideraré aceptar uno diferente. La única preocupación que tengo con marty-lamb's es que no produce un número de compilación serializado confiablemente; depende de un reloj local en el sistema del constructor para proporcionar números de compilación inequívocos, lo cual no es genial.
[Editar 10 de julio]
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 la información de versión en los datos de registro, productos de salida archivados a largo plazo, y se utilizan para rastrear nuestro análisis (a veces años después) de productos de salida a una compilació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.
fuente
gradle
y / ogit
.Respuestas:
Para varios de mis proyectos, capturo el número de revisión de subversión, el tiempo, el usuario que ejecutó la compilación y cierta información del sistema, los guardo 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 hormiga se ve así:
Es simple extender esto para incluir cualquier información que desee agregar.
fuente
Tu build.xml
Tu código java
fuente
META-INF/maven/<project group>/<project id>/pom.properties
. El archivo .properties contendrá la propiedad de versión.fuente
Software:
Hudson tiene tres compilaciones / trabajos: continuo, nocturno y de lanzamiento.
Para una compilación continua / nocturna: el número de compilación es la revisión SVN, que se encuentra usando svntask.
Para una compilación / trabajo de lanzamiento: el número de compilación es el número de lanzamiento, leído por Ant, de un archivo de propiedades. El archivo de propiedades también se puede distribuir con la versión para mostrar el número de compilación en tiempo de ejecución.
El script de compilación Ant coloca el número de compilación en el archivo de manifiesto de los archivos jar / war que se crean durante la compilación. Se aplica a todas las compilaciones.
Acción posterior a la compilación para las versiones de lanzamiento, realizada fácilmente usando un complemento de Hudson: etiqueta SVN con el número de compilación.
Beneficios:
Espero que esto ayude.
fuente
También estoy usando Hudson, aunque un escenario mucho más simple:
Mi script Ant tiene un objetivo que se ve así:
Hudson establece estas variables de entorno para mí cada vez que se ejecuta mi trabajo.
En mi caso, este proyecto es una aplicación web y estoy incluyendo este
build-number.txt
archivo 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 Hudson configurado para etiquetarlo con el número de compilación / marca de tiempo cuando la compilación es exitosa.
Mi solución solo cubre los números de compilación incrementales para el desarrollo, aún no hemos llegado lo suficientemente lejos en el proyecto donde estamos cubriendo los números de lanzamiento.
fuente
También puede echar un vistazo al complemento BuildNumber Maven y la tarea Ant en un jar 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 instalada en Subversion.
fuente
Así es como resolví esto:
Aquí está el archivo java que almacena la información de la versión:
Y aquí está la antitarea "versioninfo":
fuente
Aquí están mis 2 centavos:
Mi script de compilación crea un número de compilación (¡con marca de tiempo!) Cada vez que construyo la aplicación. Esto crea demasiados números pero nunca muy pocos. Si tengo un cambio en el código, el número de compilación cambiará al menos una vez.
Modifico el número de compilación con cada versión (aunque no en el medio). Cuando actualizo el proyecto y obtengo un nuevo número de compilación (porque alguien más realizó un lanzamiento), sobrescribo mi versión local y empiezo de nuevo. Esto puede conducir a un número de compilación más bajo, por eso he incluido la marca de tiempo.
Cuando ocurre una versión, el número de compilación se confirma como el último elemento en una única confirmación con el mensaje "compilación 1547". Después de eso, cuando se trata de un lanzamiento oficial, se etiqueta todo el árbol. De esta manera, el archivo de compilación siempre tiene todas las etiquetas y hay una asignación simple 1: 1 entre etiquetas y números de compilación.
[EDITAR] Despliegue una versión.html con mis proyectos y luego, puedo usar un raspador para simplemente recopilar un mapa preciso de lo que está instalado donde. Si está utilizando Tomcat o similar, coloque el número de compilación y la marca de tiempo en el
description
elemento de web.xml . Recuerde: nunca memorice nada cuando pueda hacer que una computadora lo haga por usted.fuente
Ejecutamos nuestra compilación a través de CruiseControl (inserte aquí su administrador de compilación favorito) y realizamos la compilación principal y las pruebas.
Luego incrementamos el número de versión usando Ant y BuildNumber y creamos un archivo de propiedades con esta información más la fecha de compilación y otros metadatos.
Tenemos una clase dedicada a leer esto y proporcionarlo a GUI / logs, etc.
Luego empaquetamos todo esto y construimos un enlace desplegable junto con el número de compilación y la compilación correspondiente. Todos nuestros servidores vuelcan esta metainformación al inicio. Podemos volver a revisar los registros de CruiseControl y vincular el número de compilación a la fecha y los registros.
fuente