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.
fonte
gradle
e / ougit
?Respostas:
Para vários de meus projetos, capto o número da revisão do subversion, a hora, o usuário que executou a compilação e algumas informações do sistema, coloco-as em um arquivo .properties que é incluído no jar do aplicativo e leio esse jar no tempo de execução.
O código formiga fica assim:
É simples estender isso para incluir qualquer informação que você queira adicionar.
fonte
Seu build.xml
Seu código Java
fonte
META-INF/maven/<project group>/<project id>/pom.properties
. O arquivo .properties conterá a propriedade version.fonte
Programas:
Hudson tem três builds / jobs: Contínuo, Noturno e Release.
Para uma compilação contínua / noturna: o número da compilação é a revisão do SVN, encontrada usando o svntask.
Para um build / trabalho da versão: Número da versão é o número da versão, lido por Ant, a partir de um arquivo Propriedades. O arquivo de propriedades também pode ser distribuído com o release para exibir o número da compilação no tempo de execução.
O script de construção do Ant coloca o número da construção no arquivo de manifesto dos arquivos jar / war que são criados durante a construção. Aplica-se a todas as compilações.
Ação pós-compilação para compilações do Release, feita facilmente usando um plug-in Hudson: identifique o SVN com o número da compilação.
Benefícios:
Espero que isto ajude.
fonte
Também estou usando o Hudson, embora um cenário muito mais simples:
Meu script Ant tem um destino que se parece com:
Hudson define essas variáveis de ambiente para mim sempre que meu trabalho é executado.
No meu caso, este projeto é um aplicativo da web e estou incluindo esse
build-number.txt
arquivo na pasta raiz do aplicativo - eu realmente não me importo com quem o vê.Não identificamos o controle de origem quando isso é feito, porque já temos nosso trabalho no Hudson configurado para identificá-lo com o número / carimbo de data / hora da compilação quando a compilação é bem-sucedida.
Minha solução cobre apenas os números de compilação incrementais para desenvolvimento, ainda não chegamos longe o suficiente no projeto em que cobrimos os números de versão.
fonte
Você também pode dar uma olhada no plug-in BuildNumber Maven e na tarefa Ant em um jar encontrado em http://code.google.com/p/codebistro/wiki/BuildNumber . Eu tentei torná-lo simples e direto. É um arquivo jar muito pequeno que depende apenas da linha de comando Subversion instalada.
fonte
Isto é como eu resolvi isso:
Aqui está o arquivo java que armazena as informações da versão:
E aqui está o anttask "versioninfo":
fonte
Aqui estão os meus 2 centavos:
Meu script de compilação cria um número de compilação (com registro de data e hora!) Toda vez que crio o aplicativo. Isso cria muitos números, mas nunca poucos. Se eu tiver uma alteração no código, o número da compilação será alterado pelo menos uma vez.
Eu versão o número da compilação a cada versão (embora não entre elas). Quando atualizo o projeto e recebo um novo número de compilação (porque outra pessoa fez um release), substituo minha versão local e recomeço. Isso pode levar a um número menor de compilação, motivo pelo qual incluí o carimbo de data / hora.
Quando uma liberação acontece, o número da compilação é confirmado como o último item em uma única confirmação com a mensagem "compilação 1547". Depois disso, quando é um lançamento oficial, toda a árvore é marcada. Dessa forma, o arquivo de compilação sempre possui todas as tags e existe um mapeamento 1: 1 simples entre tags e números de compilação.
[EDIT] Implantei um version.html com meus projetos e, em seguida, posso usar um raspador para simplesmente coletar um mapa preciso do que está instalado onde. Se você estiver usando o Tomcat ou similar, coloque o número da compilação e o carimbo de data e hora no
description
elemento web.xml . Lembre-se: nunca memorize nada quando puder que um computador faça isso por você.fonte
Executamos nossa compilação via CruiseControl (insira seu gerente de compilação favorito aqui) e executamos a compilação e os testes principais.
Em seguida, incrementamos o número da versão usando Ant e BuildNumber e criamos um arquivo de propriedades com essas informações, mais a data da compilação e outros metadados.
Temos uma classe dedicada a ler isso e fornecê-lo a GUIs / logs etc.
Em seguida, empacotamos tudo isso e construímos um conjunto implementável unindo o número da compilação e a compilação correspondente. Todos os nossos servidores despejam essas informações meta na inicialização. Podemos voltar pelos logs do CruiseControl e vincular o número da compilação à data e aos checkins.
fonte