Mejores prácticas / orientación para mantener los números de versión de ensamblaje

154

Estoy buscando punteros, sugerencias e incluso dictados sobre cómo administrar los tres números de versión de ensamblaje diferentes para un ensamblado .NET. La versión del producto es la más simple, ya que parece que normalmente sería dictada por las empresas. Luego, la versión del archivo parece ser para el control de versiones entre implementaciones, donde la versión de ensamblaje real solo se usa cuando se envía.

En este momento solo estoy buscando un medio simple de etiquetar las versiones de prueba y mantenimiento de un ensamblaje del que ninguno depende, por lo que estoy buscando un incremento automático de números de compilación y revisión en la versión del archivo, y para la versión final, copiando el actual versión de archivo a la versión de ensamblaje. El producto está en uso de producción, pero todavía está en desarrollo, ya sabes, una de esas pequeñas empresas, sin situaciones de infraestructura de control de cambios.

ProfK
fuente
1
Mira esto ... codinghorror.com/blog/2007/02/…
Rahul Soni

Respuestas:

211

El control de versiones es algo que me apasiona mucho y he pasado mucho tiempo tratando de encontrar un sistema de control de versiones fácil de usar. Por lo que ya ha dicho en su pregunta, está claro que ha entendido un punto importante, los números de versión de ensamblaje no son sinónimos de la versión del producto. Uno está impulsado técnicamente y el otro está impulsado por el negocio.

Lo siguiente asume que usa alguna forma de control de origen y un servidor de compilación. Para el contexto utilizamos TeamCity y Subversion / Git. TeamCity es gratuito para un pequeño (10) número de proyectos y es un servidor de compilación muy bueno, pero hay otros, algunos de los cuales son completamente gratuitos.

Qué significa un número de versión

Lo que una versión significa para una persona puede significar algo diferente para otra, la estructura general es mayor, menor, macro, micro. La forma en que veo un número de versión es dividirlo en dos partes. La primera mitad describe la versión principal (Mayor) y cualquier actualización clave (Menor). La segunda mitad indica cuándo se creó y cuál era la versión del código fuente. Los números de versión también significan cosas diferentes según el contexto, es una API, aplicación web, etc.

Major. Minor. Build.Revision

  • Revision Este es el número tomado del control de origen para identificar lo que realmente se construyó.
  • BuildEste es un número cada vez mayor que se puede utilizar para encontrar una compilación particular en el servidor de compilación. Es un número importante porque el servidor de compilación puede haber construido la misma fuente dos veces con un conjunto diferente de parámetros. El uso del número de compilación junto con el número de origen le permite identificar qué se compiló y cómo.
  • MinorEsto solo debería cambiar cuando haya un cambio significativo en la interfaz pública. Por ejemplo, si es una API, ¿el código consumidor aún podría compilarse? Este número debe restablecerse a cero cuando cambia el número mayor.
  • Majorindica en qué versión del producto estás. Por ejemplo, el mayor de todos los ensamblados de VisualStudio 2008 es 9 y VisualStudio 2010 es 10.

La excepción a la regla.

Siempre hay excepciones a la regla y tendrá que adaptarse a medida que las encuentre. Mi enfoque original se basaba en el uso de la subversión, pero recientemente me mudé a Git. El control de fuente como Subversion y Source Safe que usan un repositorio central tienen un número que puede usarse para identificar un conjunto particular de fuentes de un momento dado. Este no es el caso para un control de fuente distribuida como Git. Debido a que Git usa repositorios distribuidos que se encuentran en cada máquina de desarrollo, no hay un número de incremento automático que pueda usar, hay un truco que usa el número de registros pero es feo. Debido a esto, he tenido que evolucionar mi enfoque.

Major. Minor. Macro.Build

El número de revisión ahora se ha ido, la compilación ha cambiado a donde solía estar la revisión y se ha insertado Macro. Puede usar la macro como mejor le parezca, pero la mayoría de las veces lo dejo solo. Debido a que usamos TeamCity, la información perdida del número de revisión se puede encontrar en la compilación, significa que hay un proceso de dos pasos, pero no hemos perdido nada y es un compromiso aceptable.

Qué configurar

Lo primero que hay que entender es que la versión de ensamblaje, la versión del archivo y la versión del producto no tienen que coincidir. No estoy abogando por tener diferentes conjuntos de números, pero hace la vida mucho más fácil al hacer pequeños cambios en un ensamblaje que no afecta a ninguna interfaz pública que no se ve obligado a recompilar ensamblados dependientes. La forma en que trato con esto es establecer solo los números mayores y menores en la versión de ensamblaje, pero establecer todos los valores en la versión del archivo. Por ejemplo:

  • 1.2.0.0 (versión de ensamblaje)
  • 1.2.3.4 (FileVersion)

Esto le brinda la capacidad de implementar correcciones urgentes que no romperán el código existente porque las versiones del ensamblaje no coinciden, pero le permiten ver la revisión / compilación de un ensamblaje mirando su número de versión del archivo. Este es un enfoque común y puede verse en algunos ensambles de código abierto cuando mira los detalles del ensamblaje.

Usted, como líder del equipo, deberá ser responsable de incrementar el número menor cuando se requiera un cambio importante. Una solución para implementar un cambio requerido en una interfaz pero no romper el código anterior es marcar el actual como obsoleto y crear una nueva interfaz. Significa que el código existente advierte que el método es obsoleto y podría eliminarse en cualquier momento, pero no requiere que rompa todo de inmediato. Luego puede eliminar el método obsoleto cuando todo se haya migrado.

Cómo conectarlo

Podrías hacer todo lo anterior manualmente, pero llevaría mucho tiempo, lo siguiente es cómo automatizamos el proceso. Cada paso es ejecutable.

  • Elimine los atributos AssemblyVersiony AssemblyFileVersionde todos los archivos AssemblyInfo.cs del proyecto.
  • Cree un archivo de información de ensamblaje común (llámelo VersionInfo.cs) y agréguelo como elemento vinculado a todos sus proyectos.
  • Agregar AssemblyVersiony AssemblyFileVersionatributos a la versión con valores de "0.0.0.0".
  • Cree un proyecto MsBuild que construya su archivo de solución.
  • Agregue una tarea antes de la compilación que actualice VersionInfo.cs. Hay varias bibliotecas de código abierto MsBuild que incluyen una tarea AssemblyInfo que puede establecer el número de versión. Simplemente configúrelo en un número arbitrario y pruebe.
  • Agregue un grupo de propiedades que contenga una propiedad para cada uno de los segmentos del número de compilación. Aquí es donde configuras el mayor y el menor. El número de compilación y revisión debe pasarse como argumentos.

Con subversión:

<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 haber sido claro pero hay mucho involucrado. Por favor haga cualquier pregunta. Usaré cualquier comentario para armar una publicación de blog más concisa.

Bronumski
fuente
¿Has considerado usar etiquetas de versión de GitHub? Tengo mucha curiosidad sobre cómo encajaría eso en el rompecabezas.
raRaRa
1
@raRaRa: esta es una publicación bastante antigua. Si bien la mayoría de las veces sigo esperando, hay algunas cosas que haría de manera diferente. El control de versiones de NuGet ha cambiado la forma en que hago las cosas y uso las etiquetas Git para compilaciones exitosas, pero al final del día, el número de versión en el ensamblaje debería vincularse con la versión de compilación en el servidor de compilación y la versión de etiqueta en el control de código fuente.
Bronumski
57

[AssemblyVersion] es un gran problema en .NET. Una filosofía, alentada por Microsoft es que permite que se incremente automáticamente, lo que obliga a que se vuelvan a compilar todos los proyectos que dependen del ensamblaje. Funciona bien si usa un servidor de compilación. Nunca es incorrecto , pero ten cuidado con las personas que llevan espadas.

El otro, más estrechamente asociado con su significado real, es que el número es representativo de la versión de la interfaz pública del ensamblado. En otras palabras, solo lo cambia cuando altera una interfaz o clase pública. Como solo un cambio de este tipo requiere que los clientes del ensamblado se vuelvan a compilar. Sin embargo, esto debe hacerse manualmente, el sistema de compilación no es lo suficientemente inteligente como para detectar automáticamente dicho cambio.

Puede ampliar aún más este enfoque al incrementar solo la versión cuando el ensamblaje se implementó en máquinas fuera de su alcance. Este es el enfoque que utiliza Microsoft, sus números de versión de ensamblados .NET rara vez cambian. Principalmente por el dolor muy considerable que causa a sus clientes.

Entonces, lo que Microsoft predica no es lo que practica. Sin embargo, su proceso de creación y control de versiones no tiene paralelo, incluso tienen un ingeniero de software dedicado que supervisa el proceso. No funcionó tan bien, la sobrecarga WaitHandle.WaitOne (int) en particular causó bastante dolor . Se corrigió en .NET 4.0 con un enfoque muy diferente, pero eso está yendo un poco más allá del alcance.

Depende de usted y de su confianza en qué tan bien puede controlar el proceso de compilación y los ciclos de lanzamiento para tomar su propia decisión. Aparte de eso, el incremento automático de [AssemblyFileVersion] automáticamente es muy apropiado. Sin embargo, con el inconveniente de que esto no es compatible.

Hans Passant
fuente
11

Puede usar la parte Build del número de versión para el incremento automático.

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

En su entorno, una versión de prueba es una versión que tiene una versión de compilación! = 0. Al liberar, incrementa la parte menor y establece la parte de compilación en 0, así es como identificaría los ensamblajes liberados.

Si instala sus ensamblajes en el GAC, su GAC se inunda con muchas versiones diferentes con el tiempo, así que tenga esto en cuenta. Pero si usa los dlls solo localmente, creo que esta es una buena práctica.

testalino
fuente
Me gusta el número de compilación 0 para las versiones de lanzamiento.
ProfK
1
Por supuesto, esto significa que el nombre seguro de su ensamblaje cambiará con cada compilación, lo quiera o no.
Richard
9

Además de la respuesta de Bronumskis , quiero señalar que después del estándar Semantic Versioning 2.0 en semver.org , Major.Minor.Build.Revisionsería ilegal debido a la regla de que después de aumentar un número, todos los valores regulares a la derecha tendrían que restablecerse a cero.

Una mejor manera de seguir el estándar sería usar Major.Minor+Build.Revision. Obviamente, esto no se debe usar AssemblyVersionAttribute, pero en su lugar se podría usar un atributo personalizado o una clase estática.

Semver en TeamCity debería estar disponible usando el Power Pack Meta-runner. Para git con git-flow (especialmente en el mundo .NET), encontré que GitVersion es útil.

sol
fuente
2
Interesante, comprobaré esto. El formato del número de versión que mencionó podría usarse en el atributo AssemblyInformationalVersion.
Bronumski
1

No existe una regla estricta y rápida cuando se trata de versiones de ensamblajes, así que siéntase libre de probar cuál funcionaría para usted, pero le sugiero que utilice el enfoque de 4 partes, ya que tendrá la flexibilidad en caso de que desee realizar algunos cambios. en el futuro.

... por ejemplo: 1.0.0. *

Reservado: esto agrega flexibilidad adicional, en caso de que desee realizar algún cambio en el futuro. Pero por defecto, manténgalo como 0.

Además, considere firmar el ensamblaje con una clave segura. Esto resolverá el problema de conflicto de ensamblaje en caso de que tenga varias versiones de ensamblaje registradas en el GAC. Enlace MSDN

Karthik Mahalingam
fuente