Incrustar hash de confirmación de git en un .Net dll

102

Estoy construyendo una aplicación C #, usando Git como mi control de versiones.

¿Hay alguna manera de incrustar automáticamente el último hash de confirmación en el ejecutable cuando construyo mi aplicación?

Por ejemplo, imprimir el hash de confirmación en la consola se vería así:

class PrintCommitHash
{
    private String lastCommitHash = ?? // What do I put here?
    static void Main(string[] args)
    {
        // Display the version number:
        System.Console.WriteLine(lastCommitHash );
    }
}

Tenga en cuenta que esto debe hacerse en el momento de la compilación , no en el tiempo de ejecución , ya que mi ejecutable implementado no tendrá el repositorio de git accesible.

Aquí se puede encontrar una pregunta relacionada con C ++ .

EDITAR

Por la solicitud de @ mattanja, estoy publicando el script de git hook que uso en mis proyectos. La puesta en marcha:

  • Los ganchos son scripts de shell de Linux, que se colocan en: path_to_project \ .git \ hooks
  • Si está utilizando msysgit , la carpeta hooks ya contiene algunos scripts de muestra. Para hacer que git los llame, elimine la extensión '.sample' del nombre del script.
  • Los nombres de los scripts de gancho coinciden con el evento que los invoca. En mi caso, modifiqué post-commit y post-merge .
  • Mi archivo AssemblyInfo.cs está directamente debajo de la ruta del proyecto (mismo nivel que la carpeta .git ). Contiene 23 líneas y uso git para generar el 24.

Como mi linux-shelling está un poco oxidado, el script simplemente lee las primeras 23 líneas de AssemblyInfo.cs en un archivo temporal, hace eco del hash de git en la última línea y cambia el nombre del archivo a AssemblyInfo.cs . Estoy seguro de que hay mejores formas de hacer esto:

#!/bin/sh
cmt=$(git rev-list --max-count=1 HEAD)
head -23 AssemblyInfo.cs > AssemblyInfo.cs.tmp
echo [assembly: AssemblyFileVersion\(\"$cmt\"\)] >> AssemblyInfo.cs.tmp
mv AssemblyInfo.cs.tmp AssemblyInfo.cs

Espero que esto ayude.

bavaza
fuente

Respuestas:

63

Usamos etiquetas en git para rastrear versiones.

git tag -a v13.3.1 -m "version 13.3.1"

Puede obtener la versión con hash de git a través de:

git describe --long

Nuestro proceso de compilación coloca el hash de git en el atributo AssemblyInformationalVersion del archivo AssemblyInfo.cs:

[assembly: AssemblyInformationalVersion("13.3.1.74-g5224f3b")]

Una vez que haya compilado, puede ver la versión desde el explorador de Windows:

ingrese la descripción de la imagen aquí

También puede obtenerlo mediante programación a través de:

var build = ((AssemblyInformationalVersionAttribute)Assembly
  .GetAssembly(typeof(YOURTYPE))
  .GetCustomAttributes(typeof(AssemblyInformationalVersionAttribute), false)[0])
  .InformationalVersion;

donde YOURTYPE es cualquier tipo en el ensamblado que tiene el atributo AssemblyInformationalVersion.

Artesano
fuente
14
Hola, quería preguntar hace un mes, pero no tenía suficiente representante para comentar. Cuando dices, "Nuestro proceso de compilación coloca el hash de git en el atributo AssemblyInformationalVersion del AssemblyInfo.cs", ¿qué está pasando exactamente allí? ¿Está simplemente creando un estudio visual o está usando algo como NAnt o alguna otra herramienta?
Juan Jesús
3
Usamos ruby ​​(rastrillo) para automatizar nuestra construcción. Una de nuestras tareas de generación de rake actualiza el archivo CommonAssemblyInfo.cs que se utiliza en todos los proyectos de la solución. La tarea genera el archivo CommonAssemblyInfo.cs utilizando albacore: github.com/derickbailey/Albacore Uno de los valores de AssemblyInfo que establece la tarea es AssemblyInformationalVersion.
Handcraftsman
3
@John Jesus: como sugirió Lazy Badger, también puede usar git hooks para cambiar AssemblyInfo.cs después de confirmar / fusionar, etc. (esto es lo que terminé haciendo). Ver kernel.org/pub/software/scm/git/docs/githooks.html
bavaza
Solo para su información, Albacore se ha mudado a una nueva organización central: github.com/Albacore/albacore
kornman00
5
El siguiente proyecto https://github.com/jeromerg/NGitVersion ofrece una solución completa para generar GlobalAssemblyInfo.*archivos en tiempo de compilación para proyectos C # y C ++: De forma predeterminada, la versión de ensamblado generada contiene: el hash de confirmación, una bandera que indica cambios locales y una Incremento contando la cantidad de confirmación desde la raíz del repositorio hasta la confirmación actual.
jeromerg
77

Puede incrustar un archivo version.txt en el ejecutable y luego leer el version.txt del ejecutable. Para crear el archivo version.txt , usegit describe --long

Estos son los pasos:

Usa un evento de compilación para llamar a git

  • Haga clic derecho en el proyecto y seleccione Propiedades

  • En Build Events, agregue el evento Pre-Build que contenga (observe las comillas):

    "C: \ Archivos de programa \ Git \ bin \ git.exe" describa - largo> "$ (ProjectDir) \ version.txt"

    Eso creará un archivo version.txt en el directorio de su proyecto.

Incruste el version.txt en el ejecutable

  • Haga clic derecho en el proyecto y seleccione Agregar elemento existente
  • Agregue el archivo version.txt (cambie el filtro del selector de archivos para que pueda ver Todos los archivos)
  • Después de agregar version.txt , haga clic derecho sobre él en el Explorador de soluciones y seleccione Propiedades
  • Cambiar la acción de compilación a recurso integrado
  • Cambiar la copia al directorio de salida para copiar siempre
  • Agregue version.txt a su archivo .gitignore

Leer la cadena de versión del archivo de texto incrustado

Aquí hay un código de muestra para leer la cadena de versión del archivo de texto incrustado:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Reflection;

namespace TryGitDescribe
{
    class Program
    {
        static void Main(string[] args)
        {
            string gitVersion= String.Empty;
            using (Stream stream = Assembly.GetExecutingAssembly()
                    .GetManifestResourceStream("TryGitDescribe." + "version.txt"))
            using (StreamReader reader = new StreamReader(stream))
            {
                gitVersion= reader.ReadToEnd();
            }

            Console.WriteLine("Version: {0}", gitVersion);
            Console.WriteLine("Hit any key to continue");
            Console.ReadKey();
        }
    }
}
Juan jesus
fuente
9
Este enfoque funciona razonablemente bien. Sin embargo, usé "git rev-parse --short HEAD".
Brian Reiter
3
Ah bueno. Usé "git describe" porque es realmente interesante (para mí) cuando tienes una etiqueta; la información de la versión tiene la etiqueta más el número de confirmaciones después de que se aplicó la etiqueta; nunca antes había visto algo como en un SCM.
Juan Jesús
7
Yo uso git describe --dirty, que agrega una bandera cuando los desarrolladores están trabajando con un árbol de trabajo sucio.
Paulmelnikow
2
@ TamásSzelei, el espacio de nombres del proyecto es TryGitDescribe. Después de que el archivo version.txt se incrusta en el artefacto ejecutable / ensamblador, debe anteponer el espacio de nombres para obtenerlo.
Juan Jesús
2
Gracias por la solución completa. En mi caso solía GetEntryAssemblyconseguir montaje. En cualquier caso, puede llamar GetName().Namepara evitar codificar el nombre.
astrowalker
51

ACTUALIZAR:

Las cosas han evolucionado desde que respondí originalmente a esta pregunta. El Microsoft.NET.Sdk(lo que significa que debe estar usando un proyecto de estilo sdk) ahora incluye soporte para agregar el hash de confirmación tanto a la versión informativa del ensamblado como a los metadatos del paquete nuget, si se cumplen algunas condiciones:

  1. La <SourceRevisionId>propiedad debe estar definida. Esto se puede hacer agregando un objetivo como este:
<Target Name="InitializeSourceControlInformation" BeforeTargets="AddSourceRevisionToInformationalVersion">
    <Exec 
      Command="git describe --long --always --dirty --exclude=* --abbrev=8"
      ConsoleToMSBuild="True"
      IgnoreExitCode="False"
      >
      <Output PropertyName="SourceRevisionId" TaskParameter="ConsoleOutput"/>
    </Exec>
  </Target>

Este objetivo ejecuta un comando que se configurará SourceRevisionIdcomo el hash abreviado (8 caracteres). BeforeTargets hace que esto se ejecute antes de que se cree la versión informativa del ensamblado.

  1. Para incluir el hash en los metadatos del paquete nuget, <RepositoryUrl>también se debe definir.

  2. <SourceControlInformationFeatureSupported>debe ser la propiedad true, esto hace que la tarea del paquete nuget también recoja el SourceRevisionId.

Alejaría a la gente de usar el paquete MSBuildGitHash, ya que esta nueva técnica es más limpia y consistente.

ORIGINAL:

He creado un paquete nuget simple que puede incluir en su proyecto y que se encargará de esto por usted: https://www.nuget.org/packages/MSBuildGitHash/

Este paquete nuget implementa una solución MSBuild "pura". Si prefiere no depender de un paquete nuget, simplemente puede copiar estos Targets en su archivo csproj y debe incluir el hash de git como un atributo de ensamblaje personalizado:

<Target Name="GetGitHash" BeforeTargets="WriteGitHash" Condition="'$(BuildHash)' == ''">
  <PropertyGroup>
    <!-- temp file for the git version (lives in "obj" folder)-->
    <VerFile>$(IntermediateOutputPath)gitver</VerFile>
  </PropertyGroup>

  <!-- write the hash to the temp file.-->
  <Exec Command="git -C $(ProjectDir) describe --long --always --dirty &gt; $(VerFile)" />

  <!-- read the version into the GitVersion itemGroup-->
  <ReadLinesFromFile File="$(VerFile)">
    <Output TaskParameter="Lines" ItemName="GitVersion" />
  </ReadLinesFromFile>
  <!-- Set the BuildHash property to contain the GitVersion, if it wasn't already set.-->
  <PropertyGroup>
    <BuildHash>@(GitVersion)</BuildHash>
  </PropertyGroup>    
</Target>

<Target Name="WriteGitHash" BeforeTargets="CoreCompile">
  <!-- names the obj/.../CustomAssemblyInfo.cs file -->
  <PropertyGroup>
    <CustomAssemblyInfoFile>$(IntermediateOutputPath)CustomAssemblyInfo.cs</CustomAssemblyInfoFile>
  </PropertyGroup>
  <!-- includes the CustomAssemblyInfo for compilation into your project -->
  <ItemGroup>
    <Compile Include="$(CustomAssemblyInfoFile)" />
  </ItemGroup>
  <!-- defines the AssemblyMetadata attribute that will be written -->
  <ItemGroup>
    <AssemblyAttributes Include="AssemblyMetadata">
      <_Parameter1>GitHash</_Parameter1>
      <_Parameter2>$(BuildHash)</_Parameter2>
    </AssemblyAttributes>
  </ItemGroup>
  <!-- writes the attribute to the customAssemblyInfo file -->
  <WriteCodeFragment Language="C#" OutputFile="$(CustomAssemblyInfoFile)" AssemblyAttributes="@(AssemblyAttributes)" />
</Target>

Aquí hay dos objetivos. El primero, "GetGitHash", carga el hash de git en una propiedad de MSBuild llamada BuildHash, solo lo hace si BuildHash aún no está definido. Esto le permite pasarlo a MSBuild en la línea de comandos, si lo prefiere. Podría pasarlo a MSBuild así:

MSBuild.exe myproj.csproj /p:BuildHash=MYHASHVAL

El segundo objetivo, "WriteGitHash", escribirá el valor hash en un archivo en la carpeta temporal "obj" llamado "CustomAssemblyInfo.cs". Este archivo contendrá una línea que se parece a:

[assembly: AssemblyMetadata("GitHash", "MYHASHVAL")]

Este archivo CustomAssemblyInfo.cs se compilará en su ensamblado, por lo que puede usar la reflexión para buscar el AssemblyMetadataen tiempo de ejecución. El siguiente código muestra cómo se puede hacer esto cuando la AssemblyInfoclase está incluida en el mismo ensamblado.

using System.Linq;
using System.Reflection;

public static class AssemblyInfo
{
    /// <summary> Gets the git hash value from the assembly
    /// or null if it cannot be found. </summary>
    public static string GetGitHash()
    {
        var asm = typeof(AssemblyInfo).Assembly;
        var attrs = asm.GetCustomAttributes<AssemblyMetadataAttribute>();
        return attrs.FirstOrDefault(a => a.Key == "GitHash")?.Value;
    }
}

Algunos de los beneficios de este diseño es que no toca ningún archivo en la carpeta de su proyecto, todos los archivos mutados están en la carpeta "obj". Su proyecto también se compilará de manera idéntica desde Visual Studio o desde la línea de comandos. También se puede personalizar fácilmente para su proyecto y se controlará en origen junto con su archivo csproj.

MarkPflug
fuente
2
Esto funcionó perfectamente. Instalé el paquete nuget y pude extraer el hash de git usando Assembly.GetExecutingAssembly(), luego examinando el ensamblaje CustomAttributes .
Gavin H
1
Si esta fuera mi pregunta, habría aceptado esta respuesta. Buena cosa.
Drew Noakes
1
@GavinH, ¿cómo obtuviste el GitHash? Puedo ver que ese valor existe, pero ¿hay algún método puro para obtener un atributo personalizado por nombre? Parece que tengo que escribir una consulta larga donde seleccionar CustomAttributes, gracias.
Okan Kocyigit
1
@ocanal sí, desafortunadamente no pude encontrar una manera más limpia de hacerlo que leyendo el CustomAttributes. Por ejemplo, aquí está la función que utilizo para extraer la cadena hash: pastebin.com/nVKGLhJC
Gavin H
2
@danmiser No tengo idea de qué es "UseMerge / SingleAssemblyName", así que no puedo ayudarte. Cree un problema en github.com/MarkPflug/MSBuildGitHash y podría echarle un vistazo (eso no es una promesa).
MarkPflug
14

Otra forma de hacer esto es usar NetRevisionTool con algo de magia de Visual Studio integrada . Mostraré esto aquí para Visual Studio 2013 Professional Edition, pero esto también funcionará con otras versiones.

Primero descargue NetRevisionTool. Incluya NetRevisionTool.exe en su PATH o lo registre en su repositorio y cree una acción previa y posterior a la compilación de Visual Studio y cambie su AssemblyInfo.cs.

Un ejemplo que agregaría su git-hash a su AssemblyInformationVersion sería el siguiente: En la configuración de su proyecto:

ingrese la descripción de la imagen aquí

en AssemblyInfo.cs de su proyecto cambia / agrega la línea:

[ensamblado: AssemblyInformationalVersion ("1.1. {dmin: 2015}. {chash: 6} {!} - {branch}")]

en la captura de pantalla que se muestra, verifiqué NetRevisionTool.exe en la carpeta Externa / bin

Después de la compilación, si luego hace clic derecho en su binario y va a propiedades, entonces debería ver algo como lo siguiente:

ingrese la descripción de la imagen aquí

Espero que esto ayude a alguien

Schmendrick
fuente
El hash de confirmación para mí siempre termina como 00000. Pensé que era porque tenía cambios no confirmados, pero aún así. ¿Alguna idea de por qué?
Viktor
3
El problema era que NetRevision no encontraba mi ejecutable git. La razón es porque estamos usando SourceTree y git viene integrado con él. La solución fue copiar git.exe y libiconv-2.dll de% USERPROFILE% \ AppData \ Local \ Atlassian \ SourceTree \ git_local \ bin a la carpeta que contiene NetRevision.exe. También tuve que modificar los eventos de esta manera: Evento previo a la compilación: cd $ (ProjectDir) Bibliotecas NetRevisionTool.exe / patch $ (ProjectDir) Evento posterior a la compilación: cd $ (ProjectDir) Bibliotecas NetRevisionTool.exe / restore $ (ProjectDir)
Viktor
Solo para referencia futura, la URL del repositorio del proyecto ha cambiado hace algún tiempo a github.com/ygoe/NetRevisionTool . También hay más información disponible en unclassified.software/apps/netrevisiontool .
ygoe
14

Creo que vale la pena dar una respuesta completa paso a paso a esta pregunta. La estrategia aquí es ejecutar un script de PowerShell desde los eventos previos a la compilación que toma un archivo de plantilla y genera un archivo AssemblyInfo.cs con la etiqueta git + información de recuento de confirmaciones incluida.

Paso 1: cree un archivo AssemblyInfo_template.cs en la carpeta Project \ Properties, basado en su AssemblyInfo.cs original pero que contenga:

[assembly: AssemblyVersion("$FILEVERSION$")]
[assembly: AssemblyFileVersion("$FILEVERSION$")]
[assembly: AssemblyInformationalVersion("$INFOVERSION$")]

Paso 2: Cree un script de PowerShell llamado InjectGitVersion.ps1 cuya fuente es:

# InjectGitVersion.ps1
#
# Set the version in the projects AssemblyInfo.cs file
#


# Get version info from Git. example 1.2.3-45-g6789abc
$gitVersion = git describe --long --always;

# Parse Git version info into semantic pieces
$gitVersion -match '(.*)-(\d+)-[g](\w+)$';
$gitTag = $Matches[1];
$gitCount = $Matches[2];
$gitSHA1 = $Matches[3];

# Define file variables
$assemblyFile = $args[0] + "\Properties\AssemblyInfo.cs";
$templateFile =  $args[0] + "\Properties\AssemblyInfo_template.cs";

# Read template file, overwrite place holders with git version info
$newAssemblyContent = Get-Content $templateFile |
    %{$_ -replace '\$FILEVERSION\$', ($gitTag + "." + $gitCount) } |
    %{$_ -replace '\$INFOVERSION\$', ($gitTag + "." + $gitCount + "-" + $gitSHA1) };

# Write AssemblyInfo.cs file only if there are changes
If (-not (Test-Path $assemblyFile) -or ((Compare-Object (Get-Content $assemblyFile) $newAssemblyContent))) {
    echo "Injecting Git Version Info to AssemblyInfo.cs"
    $newAssemblyContent > $assemblyFile;       
}

Paso 3: guarde el archivo InjectGitVersion.ps1 en el directorio de su solución en una carpeta BuildScripts

Paso 4: agregue la siguiente línea a los eventos previos a la construcción del proyecto

powershell -ExecutionPolicy ByPass -File  $(SolutionDir)\BuildScripts\InjectGitVersion.ps1 $(ProjectDir)

Paso 5: construye tu proyecto.

Paso 6: opcionalmente, agregue AssemblyInfo.cs a su archivo git ignore

Atilio Jobson
fuente
Y recuerde hacer que sus etiquetas git sean compatibles con las versiones de archivo: como 1.2.3. Si tiene etiquetas más complicadas, tendrá que analizar solo las partes compatibles
Atilio Jobson
2
En lugar de usar una plantilla y gitignoring real, AssemblyInfo.csse podría modificar AssemblyInfo.csen su lugar, compilar y luego restablecer AssemblyInfo.csa la última versión confirmada. Entonces, en el repositorio siempre habría AssemblyInfo.cs, con $..$sustituidos solo para el momento de la construcción.
Kuba Wyrostek
Esto funcionó muy bien. Terminé usando git describe --match "v[0-9]*" --long --always --dirtypara filtrar ciertas etiquetas (las que contienen un número de versión) e indicar si el árbol de trabajo estaba limpio.
packoman
También debe modificar su $gitVersion -match '[v](.*)-(\d+)-[g](.+)$';
expresión regular
4

Ahora es muy fácil con .NET Revision Task para MSBuild y trabajar con Visual Studio 2019.

Simplemente instale el paquete NuGet Unclassified.NetRevisionTask , luego configure la información que desea en el AssemblyInfo.csarchivo como se describe en la documentación de GitHub .

Si solo desea el hash de la última confirmación (longitud = 8):

[assembly: AssemblyInformationalVersion("1.0-{chash:8}")]

Construya su proyecto / solución y tendrá algo como esto:

ingrese la descripción de la imagen aquí

krlzlx
fuente
Para configurar el formato en una aplicación NET.core, agregue PropertyGroupal archivo .csproj como se ve en el archivo
sc911
3

Como la otra respuesta ya menciona el bit git, una vez que tenga el SHA, puede considerar generar el AssemblyInfo.csarchivo de su proyecto en un gancho de precompilación.

Una forma de hacerlo es crear un AssemblyInfo.cs.tmplarchivo de plantilla, con un marcador de posición para su SHA en, por ejemplo, $$ GITSHA $$, por ejemplo

[assembly: AssemblyDescription("$$GITSHA$$")]

Su enlace previo a la compilación debe reemplazar este marcador de posición y generar el archivo AssemblyInfo.cs para que el compilador de C # lo recoja.

Para ver cómo se puede hacer esto usando SubWCRev para SVN, vea esta respuesta . No debería ser difícil hacer algo similar para git.

Otras formas serían una "etapa de creación" como se mencionó, es decir, escribir una tarea de MSBuild que haga algo similar. Otra forma más puede ser postprocesar la DLL de alguna manera (digamos ildasm + ilasm), pero creo que las opciones mencionadas anteriormente son probablemente las más fáciles.

Marcus
fuente
@Wint no, no agregue el AssemblyInfo.cs generado a git. Si lo hace, será imposible hacer una compilación no sucia: P
bromeó el
3

Para obtener un método de pago completamente automatizado y flexible https://github.com/Fody/Stamp . Hemos utilizado esto con éxito para nuestros proyectos Git (así como esta versión para proyectos SVN)

Actualización: esto está desactualizado ya que Stamp.Fody ya no se mantiene

mamuesstack
fuente
1
en la página de github de Stamp.Fody dice: "Este proyecto ya no se mantiene". Incluirlo en mi proyecto generó un CA0052 y CA0055
sc911
2

Puede usar un resumen de PowerShell para actualizar todos los archivos de información de ensamblaje con el hash de confirmación.

$hash = git describe --long --always;gci **/AssemblyInfo.* -recurse | foreach { $content = (gc $_) -replace "\[assembly: Guid?.*", "$&`n[assembly: AssemblyMetadata(`"commithash`", `"$hash`")]" | sc $_ }
roh85
fuente
1
  1. Espero que sepa cómo llamar a programas externos e interceptar la salida en el momento de la compilación.
  2. Espero que sepas cómo hacer que en el directorio de trabajo de git se ignoren los archivos no versionados.

Como lo señaló @ learath2, la salida de git rev-parse HEADle dará un hash simple.

Si usa etiquetas en Git-repository (y usa etiquetas, ¿no es más descriptivo y legible que git rev-parse), la salida se puede recibir de git describe(aunque también se usa con éxito más adelante git checkout)

Puede llamar a rev-parse | describe en:

  • algunos hacen escenario
  • en el gancho posterior a la confirmación
  • en el filtro de manchas, si selecciona la forma de implementación de los filtros de manchas / limpieza
Tejón perezoso
fuente
0

Estoy usando una combinación de la respuesta aceptada y una pequeña adición. Tengo instalada la extensión AutoT4 ( https://marketplace.visualstudio.com/items?itemName=BennorMcCarthy.AutoT4 ) para volver a ejecutar las plantillas antes de la compilación.

obteniendo la versión de GIT

Tengo git -C $(ProjectDir) describe --long --always > "$(ProjectDir)git_version.txt"en mi evento de pre-construcción en propiedades del proyecto. Agregar git_version.txt y VersionInfo.cs a .gitignore es una buena idea.

incrustación de versión en metadatos

He agregado una VersionInfo.ttplantilla a mi proyecto:

<#@ template debug="false" hostspecific="true" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.IO" #>
<#@ output extension=".cs" #>

using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

<#
if (File.Exists(Host.ResolvePath("git_version.txt")))
{
    Write("[assembly: AssemblyInformationalVersion(\""+ File.ReadAllText(Host.ResolvePath("git_version.txt")).Trim() + "\")]");
}else{
    Write("// version file not found in " + Host.ResolvePath("git_version.txt"));
}

#>

Ahora tengo mi etiqueta git + hash en "ProductVersion".

jelinek.01
fuente
0

En referencia a la otra respuesta ( https://stackoverflow.com/a/44278482/4537127 ), también utilicé la VersionInfo.ttplantilla de texto para generar AssemblyInformationalVersionsin AutoT4.

(Al menos funciona en mi aplicación C # WPF)

El problema era que los eventos previos a la compilación se ejecutaban después de las transformaciones de la plantilla, por lo que después de la clonación, el git_version.txtarchivo no estaba allí y la compilación falla. Después de crearlo manualmente para permitir que la transformación pasara una vez, se actualizó después de la transformación y siempre fue una confirmación por detrás .

Tuve que hacer dos ajustes en el archivo .csproj (esto se aplica al menos para Visual Studio Community 2017)

1) Importe los objetivos de transformación de texto y realice transformaciones de plantilla para ejecutar en cada compilación: (Ref https://msdn.microsoft.com/en-us/library/ee847423.aspx )

<PropertyGroup>
    <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">15.0</VisualStudioVersion>
    <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
    <TransformOnBuild>true</TransformOnBuild>
    <TransformOutOfDateOnly>false</TransformOutOfDateOnly>
</PropertyGroup>

y después <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

<Import Project="$(VSToolsPath)\TextTemplating\Microsoft.TextTemplating.targets" />

2) Realice la git describeejecución antes de las transformaciones de la plantilla (de modo que git_version.txtesté ahí cuando VersionInfo.ttse transforme):

<Target Name="PreBuild" BeforeTargets="ExecuteTransformations">
  <Exec Command="git -C $(ProjectDir) describe --long --always --dirty &gt; $(ProjectDir)git_version.txt" />
</Target>

.. Y el código C # para obtener el AssemblyInformationalVersion(Ref https://stackoverflow.com/a/7770189/4537127 )

public string AppGitHash
{
    get
    {
        AssemblyInformationalVersionAttribute attribute = (AssemblyInformationalVersionAttribute)Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyInformationalVersionAttribute), false).FirstOrDefault();

        return attribute.InformationalVersion;
    }
}

.. Y agregue los archivos generados a .gitignore

VersionInfo.cs
git_version.txt
kimmoli
fuente
0

Otra forma sería generar un archivo Version.cs a partir de un paso de precompilación. Exploré esto en un pequeño proyecto de prueba de concepto que imprime su hash de confirmación actual.

El proyecto está cargado en https://github.com/sashoalm/GitCommitHashPrinter .

El código de lote que crea el archivo Version.cs es este:

@echo off

echo "Writing Version.cs file..."

@rem Pushd/popd are used to temporarily cd to where the BAT file is.
pushd $(ProjectDir)

@rem Verify that the command succeeds (i.e. Git is installed and we are in the repo).
git rev-parse HEAD || exit 1

@rem Syntax for storing a command's output into a variable (see https://stackoverflow.com/a/2340018/492336).
@rem 'git rev-parse HEAD' returns the commit hash.
for /f %%i in ('git rev-parse HEAD') do set commitHash=%%i

@rem Syntax for printing multiline text to a file (see https://stackoverflow.com/a/23530712/492336).
(
echo namespace GitCommitHashPrinter
echo {
echo     class Version
echo     {
echo         public static string CommitHash { get; set; } = "%commitHash%";
echo     }
echo }
)>"Version.cs"

popd    
sashoalm
fuente
0

Sitio

<Target Name="UpdateVersion" BeforeTargets="CoreCompile">
  <Exec Command="php &quot;$(SolutionDir)build.php&quot; $(SolutionDir) &quot;$(ProjectDir)Server.csproj&quot;" />
</Target>

en YOUR_PROJECT_NAME.csproj

<?php

function between(string $string, string $after, string $before, int $offset = 0) : string{
    return substr($string, $pos = strpos($string, $after, $offset) + strlen($after),
        strpos($string, $before, $pos) - $pos);
}

$pipes = [];
$proc = proc_open("git rev-parse --short HEAD", [
    0 => ["pipe", "r"],
    1 => ["pipe", "w"],
    2 => ["pipe", "w"]
], $pipes, $argv[1]);

if(is_resource($proc)){
    $rev = stream_get_contents($pipes[1]);
    proc_close($proc);
}

$manifest = file_get_contents($argv[2]);
$version = between($manifest, "<Version>", "</Version>");
$ver = explode("-", $version)[0] . "-" . trim($rev);
file_put_contents($argv[2], str_replace($version, $ver, $manifest));

echo "New version generated: $ver" . PHP_EOL;
PeratX
fuente