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:
- 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.
Para incluir el hash en los metadatos del paquete nuget, <RepositoryUrl>también se debe definir.
<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 > $(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.