Quais são as melhores práticas atuais para numeração de compilação sistemática e gerenciamento de número de versão em projetos Java? Especificamente:
Como gerenciar números de compilação sistematicamente em um ambiente de desenvolvimento distribuído
Como manter os números de versão na origem / disponíveis para o aplicativo de tempo de execução
Como integrar corretamente com o repositório de origem
Como gerenciar automaticamente números de versão x tags de repositório
Como integrar-se à infraestrutura de criação contínua
Existem várias ferramentas disponíveis, e o ant (o sistema de compilação que estamos usando) tem uma tarefa que manterá um número de compilação, mas não está claro como gerenciar isso com vários desenvolvedores simultâneos usando CVS, svn ou similar .
[EDITAR]
Várias respostas parciais ou específicas, boas e úteis, apareceram abaixo; portanto, resumirei algumas delas. Parece-me que não há realmente uma "boa prática" forte sobre isso, mas uma coleção de idéias sobrepostas. Abaixo, encontre meus resumos e algumas perguntas resultantes que as pessoas podem tentar responder como acompanhamento. [Novo no stackoverflow ... forneça comentários se estiver fazendo isso errado.]
Se você estiver usando SVN, a versão de um checkout específico será fornecida durante o passeio. A numeração de compilação pode explorar isso para criar um número de compilação exclusivo que identifica o checkout / revisão específico. [O CVS, que estamos usando por motivos herdados, não fornece esse nível de insight ... a intervenção manual com tags leva você a meio caminho.]
Se você estiver usando o maven como seu sistema de construção, há suporte para a produção de um número de versão do SCM, bem como um módulo de release para a produção automática de releases. [Não podemos usar maven, por várias razões, mas isso ajuda aqueles que podem. [Obrigado a marcelo-morales ]]
Se você estiver usando ant como seu sistema de construção, a descrição da tarefa a seguir pode ajudar a produzir um arquivo Java .properties que captura informações de construção, que podem ser dobradas na construção de várias maneiras. [Expandimos essa idéia para incluir informações derivadas de hudson, graças a marty-lambe ].
Ant e maven (e hudson e cruise control) fornecem meios fáceis para obter números de compilação em um arquivo .properties ou em um arquivo .txt / .html. Isso é "seguro" o suficiente para impedir que ela seja violada intencionalmente ou acidentalmente? É melhor compilá-lo em uma classe "versioning" no momento da criação?
Afirmação: A numeração de compilação deve ser definida / promulgada em um sistema de integração contínua como hudson . [Graças a marcelo-morales ] Aceitamos essa sugestão, mas ela abre a questão da engenharia de lançamento: como acontece um lançamento? Existem vários buildnumbers em uma liberação? Existe uma relação significativa entre os números de compilação e as diferentes versões?
Pergunta: Qual é o objetivo por trás de um número de compilação? É usado para controle de qualidade? Quão? É usado principalmente pelos desenvolvedores para desambiguar entre várias compilações durante o desenvolvimento ou mais para o controle de qualidade determinar qual a compilação que um usuário final obteve? Se o objetivo é a reprodutibilidade, em teoria é isso que o número da versão do release deve fornecer - por que não? (responda a isso como parte de suas respostas abaixo, isso ajudará a iluminar as escolhas que você fez / sugeriu ...)
Pergunta: Existe um local para números de compilação nas compilações manuais? Isso é tão problemático que TODOS devem usar uma solução de IC?
Pergunta: Os números de compilação devem ser registrados no SCM? Se o objetivo é identificar de maneira confiável e inequívoca uma compilação específica, como lidar com uma variedade de sistemas de compilação contínua ou manual que podem travar / reiniciar / etc ...
Pergunta: Se um número de compilação for curto e agradável (ou seja, um número inteiro crescente monotonicamente), para facilitar a inserção de nomes de arquivos para arquivamento, consulta fácil na comunicação, etc ... ou deve ser longo e cheio de nomes de usuários, carimbos de data, nomes de máquinas, etc?
Pergunta: forneça detalhes sobre como a atribuição dos números de compilação se encaixa no seu processo de liberação automatizada. Sim, amantes espertos, sabemos que isso é feito e feito, mas nem todos nós já bebemos o kool-aid ainda ...
Eu realmente gostaria de explicar isso em uma resposta completa, pelo menos para o exemplo concreto de nossa configuração cvs / ant / hudson, para que alguém pudesse construir uma estratégia completa com base nessa pergunta. Marcarei como "A resposta" qualquer pessoa que possa fornecer uma descrição detalhada para esse caso em particular (incluindo esquema de marcação cvs, itens de configuração de IC relevantes e procedimento de liberação que dobra o número da compilação na liberação, de forma programática) acessível.) Se você quiser pedir / responder por outra configuração específica (por exemplo, svn / maven / cruise control), irei linkar a pergunta a partir daqui. --JA
[EDIT 23 Out 09] Aceitei a resposta mais votada porque acho que é uma solução razoável, enquanto várias das outras respostas também incluem boas idéias. Se alguém quiser tentar sintetizar alguns deles com o martir-cordeiro , considerarei aceitar outro. A única preocupação que tenho com o marty-lambs é que ele não produz um número de compilação serializado confiável - depende de um relógio local no sistema do construtor para fornecer números de compilação inequívocos, o que não é ótimo.
10 de julho
Agora incluímos uma classe como a abaixo. Isso permite que os números de versão sejam compilados no executável final. Diferentes formas das informações da versão são emitidas nos dados de log, nos produtos de saída arquivados a longo prazo e usados para rastrear nossa análise (às vezes anos depois) dos produtos de saída para uma construção 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();
}
}
Deixe comentários se isso merece se tornar uma discussão na wiki.
gradle
e / ou git
?