Práticas recomendadas / orientações para manter os números de versão de montagem

154

Estou procurando por ponteiros, sugestões e até ditados sobre como gerenciar os três números de versão de montagem diferentes para um assembly .NET. A versão do produto é a mais simples, pois isso normalmente seria ditado pelos negócios. Em seguida, a versão do arquivo parece ser para controle de versão entre implantações, onde a versão real do assembly é usada apenas no envio.

No momento, estou apenas procurando um meio simples de rotular as liberações de teste e manutenção de uma montagem da qual nenhuma depende, por isso estou analisando os números de compilação e revisão com incremento automático na versão do arquivo e a versão final, copiando a versão atual. versão do arquivo para a versão do assembly. O produto está em uso de produção, mas ainda está em desenvolvimento - você sabe - uma dessas pequenas empresas, sem situações de infraestrutura de controle de alterações.

ProfK
fonte
1
Verifique isso ... codinghorror.com/blog/2007/02/…
Rahul Soni

Respostas:

211

O controle de versão é algo pelo qual sou muito apaixonado e passei muito tempo tentando criar um sistema de controle fácil de usar. Pelo que você já disse na sua pergunta, fica claro que você entendeu um ponto importante: os números da versão do assembly não são sinônimos da versão do produto. Um é tecnicamente orientado e o outro é conduzido pelos negócios.

O seguinte pressupõe que você usa alguma forma de controle de origem e um servidor de construção. Para o contexto, usamos o TeamCity e o Subversion / Git. O TeamCity é gratuito para um número pequeno (10) de projetos e é um servidor de construção muito bom, mas existem outros, alguns dos quais são totalmente gratuitos.

O que significa um número de versão

O que uma versão significa para uma pessoa pode significar algo diferente para outra, a estrutura geral é maior, menor, macro, micro. A maneira como vejo um número de versão é dividi-lo em duas partes. A primeira metade descreve a versão principal (principal) e todas as atualizações importantes (secundária). A segunda metade indica quando foi criada e qual era a versão do código fonte. Os números de versão também significam coisas diferentes, dependendo do contexto, é uma API, um aplicativo da Web etc.

Major. Minor. Build.Revision

  • Revision Este é o número obtido do controle de origem para identificar o que realmente foi criado.
  • BuildEsse é um número cada vez maior que pode ser usado para encontrar uma construção específica no servidor de construção. É um número importante porque o servidor de compilação pode ter criado a mesma fonte duas vezes com um conjunto diferente de parâmetros. O uso do número da compilação em conjunto com o número de origem permite identificar o que foi construído e como.
  • MinorIsso deve mudar apenas quando houver uma alteração significativa na interface pública. Por exemplo, se for uma API, o código de consumo ainda poderá compilar? Esse número deve ser redefinido para zero quando o número principal for alterado.
  • Majorindica em qual versão do produto você está. Por exemplo, o principal de todos os assemblies do VisualStudio 2008 é 9 e o VisualStudio 2010 é 10.

A exceção à regra

Sempre existem exceções à regra e você terá que se adaptar à medida que as encontrar. Minha abordagem original foi baseada no uso do subversion, mas recentemente mudei para o Git. O controle de fontes, como subversão e fontes seguras, que usam um repositório central, possui um número que pode ser usado para identificar um conjunto específico de fontes a partir de um determinado momento. Este não é o caso de um controle de origem distribuído, como o Git. Como o Git usa repositórios distribuídos que estão em cada máquina de desenvolvimento, não há um número de incremento automático que você possa usar, existe um hack que usa o número de check-ins, mas é feio. Por causa disso, tive que evoluir minha abordagem.

Major. Minor. Macro.Build

O número da revisão foi agora, a compilação mudou para onde a revisão costumava estar e a Macro foi inserida. Você pode usar a macro como achar melhor, mas na maioria das vezes eu a deixo em paz. Como usamos o TeamCity, as informações perdidas no número da revisão podem ser encontradas na compilação, isso significa que há um processo em duas etapas, mas não perdemos nada e é um compromisso aceitável.

O que definir

A primeira coisa a entender é que a versão do assembly, a versão do arquivo e a versão do produto não precisam corresponder. Eu não estou defendendo ter conjuntos diferentes de números, mas facilita muito a vida ao fazer pequenas alterações em um assembly que não afeta nenhuma interface pública que você não seja forçado a recompilar os assemblies dependentes. A maneira como lida com isso é definir apenas os números Maior e Menor na Versão do Assembly, mas definir todos os valores na Versão do Arquivo. Por exemplo:

  • 1.2.0.0 (AssemblyVersion)
  • 1.2.3.4 (FileVersion)

Isso permite que você implante hot fixes que não quebram o código existente porque as versões do assembly não correspondem, mas permitem que você veja a revisão / construção de um assembly observando o número da versão do arquivo. Essa é uma abordagem comum e pode ser vista em alguns assemblies de código aberto quando você olha para os detalhes do assembly.

Você, como líder da equipe, precisaria ser responsável por aumentar o número menor sempre que uma mudança de última hora for necessária. Uma solução para implementar uma alteração necessária em uma interface, mas não quebrar o código anterior, é marcar a atual como obsoleta e criar uma nova interface. Isso significa que o código existente é avisado de que o método é obsoleto e pode ser removido a qualquer momento, mas não exige que você quebre tudo imediatamente. Você pode remover o método obsoleto quando tudo tiver sido migrado.

Como conectá-lo

Você pode fazer tudo isso manualmente, mas isso consumiria muito tempo; a seguir, é como automatizamos o processo. Cada etapa é executável.

  • Remova os atributos AssemblyVersione AssemblyFileVersionde todos os arquivos AssemblyInfo.cs do projeto.
  • Crie um arquivo de informações de montagem comum (chame-o VersionInfo.cs) e adicione-o como um item vinculado a todos os seus projetos.
  • Adicione AssemblyVersione AssemblyFileVersionatributos à versão com valores "0.0.0.0".
  • Crie um projeto MsBuild que cria seu arquivo de solução.
  • Adicione uma tarefa antes da compilação que atualiza o VersionInfo.cs. Há várias bibliotecas MsBuild de código aberto que incluem uma tarefa AssemblyInfo que pode definir o número da versão. Basta configurá-lo para um número arbitrário e testar.
  • Adicione um grupo de propriedades contendo uma propriedade para cada um dos segmentos do número da compilação. É aqui que você define o maior e o menor. O número de compilação e revisão deve ser passado como argumentos.

Com o subversion:

<PropertyGroup>
    <Version-Major>0</Version-Major>
    <Version-Minor>0</Version-Minor>
    <Version-Build Condition=" '$(build_number)' == '' ">0</Version-Build>
    <Version-Build Condition=" '$(build_number)' != '' ">$(build_number)</Version-Build>
    <Version-Revision Condition=" '$(revision_number)' == '' ">0</Version-Revision>
    <Version-Revision Condition=" '$(revision_number)' != '' ">$(revision_number)</Version-Revision>
</PropertyGroup>

Espero ter sido claro, mas há muito envolvido. Por favor, faça qualquer pergunta. Usarei qualquer feedback para montar um post de blog mais conciso.

Bronumski
fonte
Você já pensou em usar tags de versão do GitHub? Estou muito curioso sobre como isso se encaixaria no quebra-cabeça.
raRaRa
1
@raRaRa - Este é um post bastante antigo. Enquanto a maioria ainda estou de pé, há algumas coisas que eu faria diferente. O controle de versão do NuGet mudou a maneira como eu faço as coisas e utilizo as tags Git para compilações bem-sucedidas, mas no final do dia o número da versão no assembly deve ser vinculado à versão de compilação no servidor de compilação e à versão de tag no controle de origem.
Bronumski
57

O [AssemblyVersion] é um grande negócio no .NET. Uma filosofia, incentivada pela Microsoft, é que você permite o incremento automático, forçando a recompilação de todos os projetos que dependem da montagem. Funciona bem se você usar um servidor de compilação. Nunca é a coisa errada a fazer, mas cuidado com as pessoas carregando espadas.

O outro, mais intimamente associado ao seu significado real, é que o número é representativo para a versão da interface pública do assembly. Em outras palavras, você só o altera quando altera uma interface ou classe pública. Uma vez que apenas essa alteração requer que os clientes da montagem sejam recompilados. Porém, isso precisa ser feito manualmente, o sistema de compilação não é inteligente o suficiente para detectar automaticamente essa alteração.

Você pode estender ainda mais essa abordagem incrementando apenas a versão quando a montagem foi implantada em máquinas fora do seu alcance. Essa é a abordagem usada pela Microsoft; os números de versão dos assemblies .NET raramente mudam. Principalmente por causa da dor considerável que causa em seus clientes.

Portanto, o que a Microsoft prega não é o que pratica. No entanto, seu processo de construção e controle de versão são incomparáveis; eles ainda têm um engenheiro de software dedicado que monitora o processo. Não funcionou tão bem, a sobrecarga WaitHandle.WaitOne (int), em particular, causou bastante dor . Corrigido no .NET 4.0 com uma abordagem muito diferente, mas isso está ficando um pouco além do escopo.

Depende de você e de sua confiança em quão bem você pode controlar o processo de compilação e os ciclos de lançamento para fazer sua própria escolha. Fora isso, o incremento automático do [AssemblyFileVersion] automaticamente é muito apropriado. No entanto, com a inconveniência de que isso não é suportado.

Hans Passant
fonte
11

Você pode usar a parte Build do número da versão para incremento automático.

[assembly: AssemblyVersion("1.0.*")]

No seu ambiente, uma versão de teste é uma versão que possui uma versão de construção! = 0. Na liberação, você incrementa a peça secundária e define a peça de construção como 0, é assim que você identifica os assemblies liberados.

Se você instalar seus assemblies no GAC, o GAC será inundado com várias versões diferentes ao longo do tempo, lembre-se disso. Mas se você usar as DLLs apenas localmente, acho que é uma boa prática.

testalino
fonte
Eu gosto do número de compilação 0 para versões de lançamento.
ProfK
1
Obviamente, isso significa que o nome forte do seu assembly será alterado a cada build, se você quiser ou não.
Richard
9

Acrescentando à resposta de Bronumskis , quero ressaltar que após o padrão Semantic Versioning 2.0 em semver.org , Major.Minor.Build.Revisionseria ilegal devido à regra de que, após aumentar um número, todos os valores regulares à direita precisariam ser redefinidos para zero.

Uma maneira melhor de seguir o padrão seria usar Major.Minor+Build.Revision. Obviamente, isso não é para ser usado AssemblyVersionAttribute, mas um atributo personalizado ou classe estática pode ser usada.

Semver no TeamCity deve estar disponível usando o Meta-runner Power Pack. Para o git com git-flow (especialmente no mundo .NET), achei o GitVersion útil.

beira do sol
fonte
2
Interessante, vou verificar isso. O formato do número da versão que você mencionou pode ser usado no atributo AssemblyInformationalVersion.
Bronumski
1

Não existe uma regra rígida e rápida no que diz respeito aos conjuntos de versões, portanto, sinta-se à vontade para tentar o que funcionaria para você, mas eu sugiro que você faça uso da abordagem de 4 partes, pois você terá a flexibilidade, caso você queira fazer algumas alterações. no futuro.

... por ex: 1.0.0. *

Reservado - Isso adiciona flexibilidade adicional, caso você queira fazer alterações no futuro. Mas como padrão, mantenha-o como 0.

Além disso, considere assinar a montagem com uma chave forte. Isso resolverá o problema de conflito de montagem, caso você tenha várias versões de montagem registradas no GAC. Link MSDN

Karthik Mahalingam
fonte