¿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.
gradle
y / o git
.