Montaje de versiones con TeamCity

Estoy trabajando en un proyecto C # / VB.Net que usa SVN y el server de compilation TeamCity. Una docena de asambleas son producidas por la construcción. Quiero controlar las versiones de ensamblaje para que coincidan y también coincidan con la label de compilation de TeamCity.

Configuré TeamCity para usar una label de compilation de

Major.Minor. {Build}. {Revision}

Cuando Major y Minor son constantes que establezco manualmente, {Review} está determinado por la versión del repository SVN en el process de pago y {Build} es un contador de compilation autoincrementado de TeamCity. Entonces, una label de construcción de ejemplo sería

2.5.437.4423

¿Qué técnicas sugeriría para asegurarse de que todas las versiones de ensamblaje coincidan con la label de compilation de TeamCity?

Estamos usando CruiseControl.net y SVN. Lo conducimos de otra manera. Estamos utilizando la tarea MSBuildCommunityTasks Version en una secuencia de commands de MSBuild para incrementar el número de versión para las comstackciones de CI y usar ese número de versión para labelr el código fuente.

EDIT: pedido más detalles sobre los objectives de MSBuild …
Usamos un script separado que es para la compilation de CI y no se usa para las comstackciones de desarrollador. Intentamos usar diferentes objectives en los files de MSBuild que el estudio usa como files de proyecto, pero esto fue un dolor de cabeza y requirió la edición manual de los files que el estudio estaba generando.
La estructura del file MSBuild es bastante sencilla:

  1. Importar piezas adicionales

    <Import Project="$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets" />
    <!-- contains some variables that set project names, paths etc. -->
    <Import Project="Properties.msbuild"/>

  2. BeforeBuild: establezca un nuevo número de versión y vuelva a escribir el file AssemblyInfo

    <Version VersionFile="$(VersionFile)" BuildType="None" RevisionType="Increment">
    <Output TaskParameter="Major" PropertyName="Major" />
    <Output TaskParameter="Minor" PropertyName="Minor" />
    <Output TaskParameter="Build" PropertyName="Build" />
    <Output TaskParameter="Revision" PropertyName="Revision" />
    </Version>

    <!--Modify Assembly Info-->
    <AssemblyInfo CodeLanguage="CS"
    OutputFile="Properties\AssemblyInfo.cs"
    AssemblyTitle="$(TargetAssembly)"
    AssemblyDescription="$(AssemblyDescription) svn:@(SanitizedSvnUrl) revision:$(SvnRevision)"
    AssemblyCompany="Your company name"
    AssemblyProduct="Name of product"
    AssemblyCopyright="Copyright © your company 2009"
    ComVisible="false" Guid="$(WindowGuid)"
    AssemblyVersion="$(Major).$(Minor).$(Build).$(Revision)"
    AssemblyFileVersion="$(Major).$(Minor).$(Build).$(Revision)"
    Condition="$(Revision) != '0' " />

  3. Build: comstack el file de proyecto actual Script de MSBuild en modo de lanzamiento

  4. AfterBuild: ejecutamos nuestros proyectos de testing unitaria (como protección contra la creación de tags para construcciones rotas en los próximos pasos), usamos las tareas SvnInfo y algunas tareas RegexReplace para configurar algunas variables con routes y nombres de tags, y usamos la tarea SvnCopy para crear la label.

<SvnCopy UserName="username"
Password="password"
SourcePath="@(SvnTrunkPath)"
DestinationPath="@(SvnTagsPath)/BUILD-$(TargetAssembly)-$(Major).$(Minor).$(Build).$(Revision)" Message="Tagging successful build" />

Sugeriría usar la característica de compilation AssemblyInfo de TeamCity:

http://confluence.jetbrains.net/display/TCD65/AssemblyInfo+Patcher

Simplemente cree sus proyectos desde VisualStudio, configure la function de compilation en la página BuildSteps (consulte http://confluence.jetbrains.net/display/TCD65/Adding+Build+Features ), y siempre que mantenga el file pnetworkingeterminado AssemblyInfo.cs , funcionará.

Este enfoque funciona muy bien para mí.

Ventajas:

  • Los desarrolladores pueden build la solución en sus máquinas.
  • No necesita tocar los files .sln o .csproj. Simplemente funciona.
  • Al usar las variables de TeamCity, puede hacer que el número de versión coincida fácilmente con la versión de otro proyecto, etc.

Desventajas:

  • No se puede cambiar fácilmente a otro server de CI de TeamCity porque no tiene un script de compilation (pero cambiar los serveres de CI es como cambiar el ORM o la database: es muy poco probable y requerirá mucho trabajo de todos modos).

Dejo la respuesta de Hamish como la respuesta aceptada, pero, para completar, pensé que valía la pena documentar el enfoque que finalmente adoptamos.

Mantengo 2 configuraciones de compilation separadas en TeamCity, una es la compilation de CI y otra es una compilation que se ejecuta semanalmente cuando hay cambios (o manualmente) y es nuestra versión de lanzamiento oficial. Fui a por el enfoque de dos comstackciones porque la compilation lleva quizás unos 40 minutos de extremo a extremo y quería que los desarrolladores obtuvieran una respuesta rápida sobre cualquier problema de compilation cuando realizaran cambios. La construcción de CI por lo tanto es un subset de la compilation de lanzamiento completo, pero construye todo el código. El control de versiones también difiere entre las dos versiones:

  • La construcción de CI tiene numbers de versión {Major.minor.BuildCounter.SvnRevision}
    • BuildCounter comienza desde 0
    • no label el repository svn
  • La versión Weekly / Release tiene un sistema de control de versiones similar, pero
    • el contador de compilation comienza en (Mayor * 1000), por lo que si Mayor es '8', el contador de compilation comienza desde 8000.
    • Crea una label llamada 'Build_ {Version}' en el repository svn

La razón de esta elección un tanto arbitraria es permitirnos distinguir clara y simplemente entre comstackciones CI y comstackciones Release.

Tenemos un file para toda la solución llamado AssemblyVersionInfo que se incluye (enlaces suaves) en cada proyecto de la solución. El file contiene (en esencia) esto:

 using System.Reflection; // Revision and Build both set to 9999 indicates a private build on a developer's private workstation. [assembly: AssemblyFileVersion("6.0.9999.9999")] // Win32 File Version (not used by .NET) 

Así que todas las construcciones de desarrolladores usan el mismo número de versión estático y fácilmente identificable, que es más alto que cualquier cosa producida por el server de compilation, de modo que en un conflicto de versiones, el file del desarrollador gana.

En el server de compilation, utilizamos MSBuild Community Tasks para generar un nuevo file AssemblyVersionInfo que sobrescribe el contenido pnetworkingeterminado. Usamos la cadena de compilation de TeamCity como la nueva versión. De esta manera, podemos distinguir fácilmente entre las siguientes 3 situaciones:

  • Una compilation privada realizada en la estación de trabajo del desarrollador
  • Una compilation de CI realizada en el server de compilation pero que no debe ser liberada
  • Una compilation de lanzamiento sancionada oficialmente, que está labelda en el repository de Svn

En otro giro, tenga en count que estoy configurando AssemblyFileVersion , no AssemblyVersion . Obligamos a nuestras versiones de ensamblaje a ser una cadena de versión fija y estática de 'Major.Minor.0.0'. Hacemos esto para que podamos emitir versiones de corrección de errores sin tener que preocuparnos por problemas de versiones. AssemblyFileVersion nos permite descubrir qué construcción ha instalado un usuario sin que forme parte de la identidad del ensamblado.

Aunque esto ya tiene una respuesta aceptada, me gustaría agregar una idea que hemos utilizado.

Para proyectos grandes, puede haber muchos files de información de ensamblaje para actualizar, y con un factorización constante siempre existe el riesgo de que el script de construcción no tenga conocimiento de los nuevos files que necesitan actualizarse.

Por esta razón, hemos creado un file de código simple que define una constante para la versión actual y luego todos los proyectos henetworkingan esta constante y nosotros en el file de información del ensamblado. Entonces, la secuencia de commands de compilation solo necesita actualizar un file.

Otro beneficio aquí es que esto también está acelerando el process de compilation ya que no necesita pasar por muchos files y cambiar.