¿Cómo puedo incrementar automáticamente la versión de ensamblaje de C # a través de nuestra plataforma de CI (Hudson)?


Mi grupo y yo somos horrendos al incrementar los números de versión de ensamblaje y frecuentemente enviamos ensamblajes con versiones 1.0.0.0. Obviamente, esto causa muchos dolores de cabeza.

Estamos mejorando mucho con nuestras prácticas a través de nuestra plataforma CI y realmente me gustaría configurarla para aumentar automáticamente los valores dentro del archivo assemblyinfo.cs para que las versiones de nuestros ensamblados se actualicen automáticamente con los cambios de código en ese ensamblaje.

Yo había establecido previamente (antes de que found Hudson ) una forma de incrementar el valor a través de msbuild o la línea de comandos (no puedo recordar), pero con Hudson, eso actualizará el repositorio SVN y activará OTRA compilación. Eso resultaría en un bucle infinito lento como Hudson encuestas SVN cada hora.

¿Es mala idea que Hudson incremente el número de versión? ¿Cuál sería una forma alternativa de hacerlo?

Idealmente, mi criterio para una solución sería uno que:

  • Incrementa el número de compilación en assemblyinfo.cs antes de una compilación
  • Solo incrementa el número de compilación en ensamblados que han cambiado. Esto puede no ser posible ya que Hudson borra la carpeta del proyecto cada vez que hace una compilación
  • Confirma el assemblyinfo modificado.cs en el repositorio de código (actualmente VisualSVN)
  • No causa que Hudson active una nueva compilación la próxima vez que busque cambios

Resolviendo esto en mi cabeza, fácilmente podría encontrar una solución a la mayor parte de esto a través de archivos por lotes / comandos, pero todas mis ideas harían que Hudson activara una nueva compilación la próxima vez que escanee. No estoy buscando a alguien que haga todo por mí, solo me apunte en la dirección correcta, tal vez una técnica para hacer que Hudson ignore ciertas confirmaciones de SVN, etc.

Todo lo que he encontrado hasta ahora es solo un artículo que explica cómo obtener el número de versión incrementado automáticamente, nada tiene en cuenta una plataforma de CI que podría girar en un bucle infinito.

Author: Tim, 2009-07-14

12 answers

Una alternativa simple es dejar que el entorno C# incremente la versión del ensamblado por usted estableciendo el atributo version en major.minor.* (como se describe en la plantilla del archivo AssemblyInfo.)

Es posible que esté buscando una solución más completa, sin embargo.

EDITAR (Respuesta a la pregunta en un comentario):

De AssemblyInfo.cs:

// Version information for an assembly consists of the following four values:
//
//      Major Version
//      Minor Version 
//      Build Number
//      Revision
//
// You can specify all the values or you can default the Build and Revision Numbers 
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
 60
Author: Greg D,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-02-11 14:40:13

Esto es lo que hice, para sellar el atributo AssemblyFileVersion.

Se ha eliminado el AssemblyFileVersion de AssemblyInfo.cs

Agregue un nuevo archivo vacío llamado AssemblyFileInfo.cs al proyecto.

Instale el conjunto de herramientas MSBuild community tasks en la máquina de compilación de Hudson o como una dependencia NuGet en su proyecto.

Edite el archivo project (csproj), es solo un archivo msbuild, y agregue lo siguiente.

En algún lugar habrá un <PropertyGroup> indicando la versión. Cambie eso para que se lea, por ejemplo,

 <Major>1</Major>
 <Minor>0</Minor>
 <!--Hudson sets BUILD_NUMBER and SVN_REVISION -->
 <Build>$(BUILD_NUMBER)</Build>
 <Revision>$(SVN_REVISION)</Revision>

Hudson proporciona esas variables env que se ven allí cuando el proyecto se construye en Hudson (suponiendo que se obtiene de subversion).

En la parte inferior del archivo del proyecto, agregue

 <Import Project="$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets" Condition="Exists('$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets')" />
  <Target Name="BeforeBuild" Condition="Exists('$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets')">
    <Message Text="Version: $(Major).$(Minor).$(Build).$(Revision)" />
    <AssemblyInfo CodeLanguage="CS" OutputFile="AssemblyFileInfo.cs" AssemblyFileVersion="$(Major).$(Minor).$(Build).$(Revision)" AssemblyConfiguration="$(Configuration)" Condition="$(Revision) != '' " />
  </Target>

Esto usa las tareas de MSBuildCommunityTasks para generar el AssemblyFileVersion.cs para incluir un atributo AssemblyFileVersion antes de construir el proyecto. Puede hacer esto para cualquiera / todos los atributos de la versión si lo desea.

El el resultado es que, cada vez que se emite una compilación de Hudson, el ensamblado resultante obtiene una AssemblyFileVersion de 1.0.HUDSON_BUILD_NR. SVN_REVISION e. g. 1.0.6.2632, que significa la 6'th build # en hudson, buit de la revisión de subversion 2632.

 64
Author: nos,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-22 22:57:29

Aquí hay una solución elegante que requiere un poco de trabajo por adelantado al agregar un nuevo proyecto, pero maneja el proceso muy fácilmente.

La idea es que cada proyecto se vincule a un archivo de solución que solo contenga la información de la versión del ensamblado. Por lo tanto, su proceso de compilación solo tiene que actualizar un solo archivo y todas las versiones de ensamblado extraen del único archivo al compilarlo.

Pasos:

  1. Agregue una clase a su archivo de solución *.archivo cs, he llamado min Compartir propiedades de conjunto.cs
  2. Elimine toda la información cs de ese nuevo archivo
  3. Cortar la información del ensamblado de un archivo AssemblyInfo: [asamblea: AssemblyVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")]
  4. Agregue la instrucción "using System.Reflexión; " al archivo y luego pegar los datos en su nuevo archivo cs (ex SharedAssemblyProperties.cs)
  5. Agregue un elemento existente a su proyecto (espere... leer antes de agregar el archivo)
  6. Seleccione el archivo y antes de hacer clic en Agregar, haga clic en el menú desplegable junto al botón agregar y seleccione "Agregar como enlace".
  7. Repita los pasos 5 y 6 para todos los proyectos existentes y nuevos en la solución

Cuando agrega el archivo como un enlace, almacena los datos en el archivo de proyecto y, al compilarlo, extrae la información de la versión del ensamblado de este archivo.

En su control de código fuente, agrega un archivo bat o un archivo de script que simplemente incrementa las propiedades de Sharedassemblyp.archivo cs y todos sus proyectos serán actualice su información de ensamblaje de ese archivo.

 42
Author: sondlerd,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-04-15 04:00:47

Hudson se puede configurar para ignorar los cambios en ciertas rutas y archivos para que no solicite una nueva compilación.

En la página de configuración del trabajo, en Gestión del código fuente, haga clic en el botón Avanzado. En el cuadro Regiones excluidas introduzca una o más expresiones regulares que coincidan con exclusiones.

Por ejemplo, para ignorar los cambios en la versión .properties archivo que puede utilizar:

/MyProject/trunk/version.properties

Esto funcionará para lenguajes distintos de C # y le permite almacenar la información de su versión dentro de subversion.

 11
Author: Matthew Blackford,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-07-22 07:15:30

. NET hace esto por usted. En su AssemblyInfo.archivo cs, establezca su versión de ensamblaje en mayor.menor.* (por ejemplo: 1.0.*).

Cuando compila su proyecto, la versión se genera automáticamente.

Los números de compilación y revisión se generan en función de la fecha, usando la época de unix, creo. La compilación se basa en el día actual, y la revisión se basa en el número de segundos desde la medianoche.

 10
Author: Kyle Trauberman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-07-14 17:42:15

Nunca he visto ese 1.0.* función de trabajo en VS2005 o VS2008. ¿Hay algo que deba hacerse para establecer VS para incrementar los valores?

If AssemblyInfo.cs está codificado con 1.0.* , entonces, ¿dónde se almacena la compilación/revisión real?

Después de poner 1.0.* en AssemblyInfo, no podemos usar la siguiente instrucción porque ProductVersion ahora tiene un valor no válido - está usando 1.0.* y no el valor asignado por VS:

Version version = new Version(Application.ProductVersion);

Suspiro - este parece ser uno de esos cosas que todo el mundo pregunta pero de alguna manera nunca hay una respuesta sólida. Hace años vi soluciones para generar un número de revisión y guardarlo en AssemblyInfo como parte de un proceso posterior a la compilación. Esperaba que ese tipo de baile no fuera necesario para VS2008. Tal vez VS2010?

 8
Author: TonyG,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-10-15 23:43:41

Asumo que también se podría hacer esto con una plantilla de texto donde se crean los atributos de ensamblado en cuestión sobre la marcha desde el entorno como AssemblyVersion.tt lo hace a continuación.

<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ output extension=".cs" #>
<#
var build = Environment.GetEnvironmentVariable("BUILD_NUMBER");
build = build == null ? "0" : int.Parse(build).ToString();
var revision = Environment.GetEnvironmentVariable("SVN_REVISION");
revision = revision == null ? "0" : int.Parse(revision).ToString();    
#>
using System.Reflection;
[assembly: AssemblyVersion("1.0.<#=build#>.<#=revision#>")]
[assembly: AssemblyFileVersion("1.0.<#=build#>.<#=revision#>")]
 5
Author: MikeS,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-02-03 23:23:04

Como continuación de la respuesta de MikeS, quería agregar que VS + Visual Studio Visualization and Modeling SDK debe instalarse para que esto funcione, y también debe modificar el archivo del proyecto. También se debe mencionar que uso Jenkins como servidor de compilación que se ejecuta en una caja de servidor R2 de Windows 2008 con el módulo de versión, donde obtengo el BUILD_NUMBER.

Mi archivo de plantilla de texto version.tt se ve así

<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ output extension=".cs" #>
<#
var build = Environment.GetEnvironmentVariable("BUILD_NUMBER");
build = build == null ? "0" : int.Parse(build).ToString();
var revision = Environment.GetEnvironmentVariable("_BuildVersion");
revision = revision == null ? "5.0.0.0" : revision;    
#>
using System.Reflection;
[assembly: AssemblyVersion("<#=revision#>")]
[assembly: AssemblyFileVersion("<#=revision#>")]

Tengo lo siguiente en los Grupos de Propiedades

<PropertyGroup>
    <TransformOnBuild>true</TransformOnBuild>
    <OverwriteReadOnlyOutputFiles>true</OverwriteReadOnlyOutputFiles>
    <TransformOutOfDateOnly>false</TransformOutOfDateOnly>
</PropertyGroup>

Después importación de Microsoft.CSharp.objetivos, tengo esto (depende de donde se instala VS

<Import Project="C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\TextTemplating\v10.0\Microsoft.TextTemplating.targets" />

En mi servidor de compilación tengo el siguiente script para ejecutar la transformación de texto antes de la compilación real, para obtener el último número de conjunto de cambios en TFS

set _Path="C:\Build_Source\foo"

pushd %_Path% 
"%ProgramFiles(x86)%\Microsoft Visual Studio 10.0\Common7\IDE\tf.exe" history . /r /noprompt /stopafter:1 /Version:W > bar
FOR /f "tokens=1" %%foo in ('findstr /R "^[0-9][0-9]*" bar') do set _BuildVersion=5.0.%BUILD_NUMBER%.%%foo
del bar
popd

echo %BUILD_NUMBER%
echo %_BuildVersion%
cd C:\Program Files (x86)\Jenkins\jobs\MyJob\workspace\MyProject
MSBuild MyProject.csproj /t:TransformAll 
...
<rest of bld script>

De esta manera puedo realizar un seguimiento de las compilaciones Y los conjuntos de cambios, por lo que si no he comprobado nada desde la última compilación, el último dígito no debería cambiar, sin embargo, podría haber realizado cambios en el proceso de compilación, de ahí la necesidad de la penúltima numero. Por supuesto, si realiza múltiples check-ins antes de una compilación, solo obtendrá el último cambio reflejado en la versión. Supongo que podría concatenar de que se requiere.

Estoy seguro de que puede hacer algo más elegante y llamar a TFS directamente desde la plantilla tt, sin embargo, esto funciona para mí.

Entonces puedo obtener mi versión en tiempo de ejecución como este

Assembly assembly = Assembly.GetExecutingAssembly();
FileVersionInfo fvi = FileVersionInfo.GetVersionInfo(assembly.Location);
return fvi.FileVersion;
 3
Author: aggaton,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-04-03 01:34:31

Mi solución no requiere la adición de herramientas externas o lenguajes de scripting's está prácticamente garantizado que funcionará en su máquina de compilación. Resuelvo este problema en varias partes. Primero, he creado una CONSTRUCCIÓN.Archivo BAT que convierte el parámetro Jenkins BUILD_NUMBER en una variable de entorno. Utilizo la función "Execute Windows batch command" de Jenkins para ejecutar el archivo de compilación por lotes ingresando la siguiente información para la compilación de Jenkins:

     ./build.bat --build_id %BUILD_ID% -build_number %BUILD_NUMBER%

En la compilación medio ambiente, tengo una constitución.archivo bat que comienza de la siguiente manera:

     rem build.bat
     set BUILD_ID=Unknown
     set BUILD_NUMBER=0
     :parse_command_line
     IF NOT "%1"=="" (
         IF "%1"=="-build_id" (
             SET BUILD_ID=%2
             SHIFT
             )
         IF "%1"=="-build_number" (
             SET BUILD_NUMBER=%2
             SHIFT
         )
         SHIFT
         GOTO :parse_command_line
     )
     REM your build continues with the environmental variables set
     MSBUILD.EXE YourProject.sln

Una vez que hice eso, hice clic con el botón derecho en el proyecto que se compilará en el panel Explorador de Soluciones de Visual Studio y seleccioné Propiedades, seleccioné Eventos de compilación e ingresé la siguiente información como la Línea de comandos del Evento de Compilación previa, que crea automáticamente un .archivo cs que contiene información del número de compilación basada en la configuración actual de la variable de entorno:

     set VERSION_FILE=$(ProjectDir)\Properties\VersionInfo.cs
     if !%BUILD_NUMBER%==! goto no_buildnumber_set
     goto buildnumber_set
     :no_buildnumber_set
     set BUILD_NUMBER=0
     :buildnumber_set
     if not exist %VERSION_FILE% goto no_version_file
     del /q %VERSION_FILE%
     :no_version_file
     echo using System.Reflection; >> %VERSION_FILE%
     echo using System.Runtime.CompilerServices; >> %VERSION_FILE%
     echo using System.Runtime.InteropServices; >> %VERSION_FILE%
     echo [assembly: AssemblyVersion("0.0.%BUILD_NUMBER%.1")] >> %VERSION_FILE%
     echo [assembly: AssemblyFileVersion("0.0.%BUILD_NUMBER%.1")] >> %VERSION_FILE%

Es posible que deba ajustarse a su gusto de construcción. Yo construyo el proyecto manualmente una vez para generar una versión inicial.archivo cs en el directorio de propiedades del proyecto principal. Por último, incluyo manualmente la versión.archivo cs en la solución de Visual Studio arrastrándolo al panel Explorador de soluciones, debajo de la ficha Propiedades para ese proyecto. En futuras compilaciones, Visual Studio lo lee .cs file at Jenkins build time y obtiene la información correcta del número de compilación.

 1
Author: johnwbyrd,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-05-24 00:42:45

Por lo tanto, tenemos un proyecto con una solución que contiene varios proyectos que tienen ensamblados con diferentes números de versión.

Después de investigar varios de los métodos anteriores, acabo de implementar un paso de compilación para ejecutar un script de Powershell que hace un find-and-replace en el AssemblyInfo.archivo CS. Todavía uso el 1.0.* número de versión en el control de código fuente, y Jenkins simplemente actualiza manualmente el número de versión antes de que se ejecute msbuild.

dir **/Properties/AssemblyInfo.cs | %{ (cat $_) | %{$_ -replace '^(\s*)\[assembly: AssemblyVersion\("(.*)\.\*"\)', "`$1[assembly: AssemblyVersion(`"`$2.$build`")"} | Out-File $_ -Encoding "UTF8" }
dir **/Properties/AssemblyInfo.cs | %{ (cat $_) | %{$_ -replace '^(\s*)\[assembly: AssemblyFileVersion\("(.*)\.\*"\)', "`$1[assembly: AssemblyFileVersion(`"`$2.$build`")"} | Out-File $_ -Encoding "UTF8" }

He añadido la opción-Encoding "UTF8" porque git comenzó a tratar el .cs archivo como archivos binarios si no lo hice. Concedido, esto no importa, ya que nunca en realidad confirmar el resultado; simplemente surgió como yo estaba probando.

Nuestro entorno de CI ya tiene una facilidad para asociar la compilación de Jenkins con la confirmación de git en particular (gracias complemento de Stash!), así que no me preocupa que no haya ninguna confirmación de git con el número de versión adjunto.

 1
Author: jonnybot,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-25 16:38:32

Este es un mecanismo más simple. Simplemente implica la adición de un paso de compilación de tareas de comando de Windows Batch antes del paso de MSBuild y el uso de un simple programa de búsqueda y reemplazo (PEDO).

El Paso del Lote

fart --svn -r AssemblyInfo.cs "[assembly: AssemblyVersion(\"1.0.0.0\")]" "[assembly: AssemblyVersion(\"1.0.%BUILD_NUMBER%.%SVN_REVISION%\")]"
if %ERRORLEVEL%==0 exit /b 1
fart --svn -r AssemblyInfo.cs "[assembly: AssemblyFileVersion(\"1.0.0.0\")]" "[assembly: AssemblyFileVersion(\"1.0.%BUILD_NUMBER%.%SVN_REVISION%\")]"
if %ERRORLEVEL%==0 exit /b 1
exit /b 0

Si está utilizando un control de código fuente distinto de svn, cambie la opción sv svn por la opción adecuada para su entorno scm.

Descargar Pedo

 0
Author: sweetfa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-09-04 06:33:04

Decidí usar un par de métodos usando un script prebuild Powershell ( https://gist.github.com/bradjolicoeur/e77c508089aea6614af3 ) para incrementar en cada compilación exitosa luego en Global.asax voy algo como esto:

  // We are using debug configuration, so increment our builds.
  if (System.Diagnostics.Debugger.IsAttached)
  {
      string version = System.Reflection.Assembly.GetExecutingAssembly()
                                                       .GetName()
                                                       .Version
                                                       .ToString();

      var psi = new ProcessStartInfo(@"svn", "commit -m \"Version: " + version + "\n \"");
      psi.WorkingDirectory = @"C:\CI\Projects\myproject";
      Process.Start(psi); 
  }

Todavía creo que todo el proceso es demasiado complicado y voy a buscar un método más eficiente para lograr el mismo resultado. Quería esto principalmente para pasar la versión en SVN y luego en Jenkin sin demasiados addtional herramienta.

 0
Author: Netferret,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-13 07:53:09