Quali sono le migliori pratiche attuali per la numerazione sistematica delle build e la gestione dei numeri di versione nei progetti Java? In particolare:
Come gestire i numeri di build in modo sistematico in un ambiente di sviluppo distribuito
Come mantenere i numeri di versione in origine / disponibili per l'applicazione runtime
Come integrarsi correttamente con il repository di origine
Come gestire più automaticamente i numeri di versione rispetto ai tag del repository
Come integrarsi con l'infrastruttura a build continua
Ci sono molti strumenti disponibili e ant (il sistema di build che stiamo usando) ha un compito che manterrà un numero di build, ma non è chiaro come gestirlo con più sviluppatori simultanei che usano CVS, svn o simili .
[MODIFICARE]
Di seguito sono apparse diverse risposte parziali o specifiche valide e utili, quindi ne riassumerò alcune. Mi sembra che non ci sia davvero una "buona pratica" forte su questo, piuttosto una raccolta di idee sovrapposte. Di seguito, trova i miei riassunti e alcune domande che ne conseguono a cui la gente potrebbe provare a rispondere come follow-up. [Nuovo su StackOverflow ... si prega di fornire commenti se sto sbagliando.]
Se stai usando SVN, arriva il controllo delle versioni di un checkout specifico. La numerazione delle build può sfruttare questa possibilità per creare un numero di build univoco che identifichi il checkout / la revisione specifici. [CVS, che stiamo usando per motivi legacy, non fornisce questo livello di intuizione ... l'intervento manuale con i tag ti porta da lì.]
Se si utilizza Maven come sistema di compilazione, è disponibile il supporto per la produzione di un numero di versione da SCM, nonché un modulo di rilascio per la produzione automatica di rilasci. [Non possiamo usare Maven, per una serie di ragioni, ma questo aiuta chi può farlo. [Grazie a marcelo-morales ]]
Se si utilizza la formica come sistema di compilazione, la seguente descrizione dell'attività può aiutare a produrre un file Java .properties che acquisisce le informazioni di compilazione, che possono quindi essere piegate nella compilazione in diversi modi. [Abbiamo ampliato questa idea per includere informazioni derivate da hudson, grazie marty-lamb ].
Ant e maven (e hudson e cruise control) forniscono mezzi facili per ottenere i numeri di build in un file .properties o in un file .txt / .html. Questo è "sicuro" abbastanza per evitare che venga manomesso intenzionalmente o accidentalmente? È meglio compilarlo in una classe di "versioning" al momento della compilazione?
Asserzione: la numerazione delle build deve essere definita / attuata in un sistema di integrazione continua come hudson . [Grazie a marcelo-morales ] Abbiamo preso questo suggerimento, ma apre la domanda di ingegneria del rilascio: come avviene un rilascio? Ci sono più buildnumber in una versione? Esiste una relazione significativa tra i numeri di build di versioni diverse?
Domanda: Qual è l'obiettivo alla base di un numero di build? È usato per il controllo qualità? Come? Viene utilizzato principalmente dagli sviluppatori per chiarire le ambiguità tra più build durante lo sviluppo o più per il QA per determinare quale build ha ottenuto un utente finale? Se l'obiettivo è la riproducibilità, in teoria questo è ciò che dovrebbe fornire un numero di versione di rilascio - perché non lo fa? (per favore rispondi a questo come parte delle tue risposte qui sotto, ti aiuterà a illuminare le scelte che hai fatto / suggerito ...)
Domanda: c'è un posto per i numeri di build nelle build manuali? È così problematico che TUTTI dovrebbero usare una soluzione CI?
Domanda: i numeri di build devono essere archiviati in SCM? Se l'obiettivo è identificare in modo affidabile e inequivocabile una particolare build, come far fronte a una varietà di sistemi di build continui o manuali che potrebbero bloccarsi / riavviare / ecc ...
Domanda: se un numero di build deve essere breve e dolce (ad es. Intero monotonicamente crescente) in modo che sia facile attenersi ai nomi dei file per l'archiviazione, facile da consultare nella comunicazione, ecc ... o dovrebbe essere lungo e pieno di nomi utente, datestamp, nomi di macchine, ecc.?
Domanda: Fornisci dettagli su come l'assegnazione dei numeri di build si adatta al tuo più ampio processo di rilascio automatico. Sì, amanti della cucina, sappiamo che questo è fatto e fatto, ma non tutti abbiamo ancora bevuto il kool-aid ...
Mi piacerebbe davvero approfondire questo in una risposta completa, almeno per l'esempio concreto della nostra configurazione cvs / ant / hudson, così qualcuno potrebbe costruire una strategia completa basata su questa domanda. Contrassegnerò come "la risposta" chiunque sia in grado di fornire una descrizione dettagliata per questo caso particolare (incluso schema di codifica cvs, elementi di configurazione CI rilevanti e procedura di rilascio che piega il numero di build nel rilascio in modo che sia programmaticamente accessibile.) Se vuoi chiedere / rispondere per un'altra configurazione particolare (ad esempio, svn / maven / cruise control), collegherò alla domanda da qui. --JA
[EDIT 23 ott 09] Ho accettato la risposta più votata perché penso che sia una soluzione ragionevole, mentre molte delle altre risposte includono anche buone idee. Se qualcuno vuole fare una pausa nel sintetizzare alcuni di questi con quelli di Marty-Lamb , prenderò in considerazione l'idea di accettarne uno diverso. L'unica preoccupazione che ho con marty-lamb's è che non produce un numero di build serializzato in modo affidabile - dipende da un orologio locale nel sistema del costruttore per fornire numeri di build inequivocabili, il che non è eccezionale.
[Modifica 10 lug]
Ora includiamo una classe come la seguente. Ciò consente di compilare i numeri di versione nell'eseguibile finale. Forme diverse di informazioni sulla versione vengono emesse nei dati di registrazione, nei prodotti di output archiviati a lungo termine e utilizzate per tracciare la nostra analisi (a volte anni dopo) dei prodotti di output su una build specifica.
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();
}
}
Lascia commenti se questo merita di diventare una discussione wiki.
gradle
e / o git
?