AGGIORNARE:
Le cose si sono evolute da quando ho originariamente risposto a questa domanda. Microsoft.NET.Sdk
( Il che significa che devi utilizzare un progetto in stile sdk) ora include il supporto per l'aggiunta dell'hash del commit sia alla versione informativa dell'assembly che ai metadati del pacchetto nuget, se vengono soddisfatte alcune condizioni:
- La
<SourceRevisionId>
proprietà deve essere definita. Questo può essere fatto aggiungendo un obiettivo come questo:
<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>
Questa destinazione esegue un comando che verrà impostato SourceRevisionId
come hash abbreviato (8 caratteri). BeforeTargets fa sì che ciò venga eseguito prima della creazione della versione informativa dell'assembly.
Per includere l'hash nei metadati del pacchetto nuget, è <RepositoryUrl>
necessario definire anche il.
<SourceControlInformationFeatureSupported>
deve essere true
, questo fa sì che l'attività del pacchetto nuget raccolga anche SourceRevisionId.
Vorrei allontanare le persone dall'usare il pacchetto MSBuildGitHash, poiché questa nuova tecnica è più pulita e coerente.
ORIGINALE:
Ho creato un semplice pacchetto nuget che puoi includere nel tuo progetto che si occuperà di questo per te: https://www.nuget.org/packages/MSBuildGitHash/
Questo pacchetto nuget implementa una soluzione MSBuild "pura". Se preferisci non dipendere da un pacchetto nuget, puoi semplicemente copiare questi Target nel tuo file csproj e dovrebbe includere l'hash git come attributo di assembly personalizzato:
<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>
Ci sono due obiettivi qui. Il primo, "GetGitHash", carica l'hash git in una proprietà MSBuild denominata BuildHash, lo fa solo se BuildHash non è già definito. Ciò ti consente di passarlo a MSBuild dalla riga di comando, se preferisci. Puoi passarlo a MSBuild in questo modo:
MSBuild.exe myproj.csproj /p:BuildHash=MYHASHVAL
La seconda destinazione, "WriteGitHash", scriverà il valore hash in un file nella cartella temporanea "obj" denominata "CustomAssemblyInfo.cs". Questo file conterrà una riga simile a:
[assembly: AssemblyMetadata("GitHash", "MYHASHVAL")]
Questo file CustomAssemblyInfo.cs verrà compilato nell'assembly, quindi puoi usare la reflection per cercare AssemblyMetadata
in fase di esecuzione. Il codice seguente mostra come eseguire questa operazione quando la AssemblyInfo
classe è inclusa nello stesso assembly.
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;
}
}
Alcuni vantaggi di questo design è che non tocca alcun file nella cartella del progetto, tutti i file modificati si trovano nella cartella "obj". Il progetto verrà anche compilato in modo identico da Visual Studio o dalla riga di comando. Può anche essere facilmente personalizzato per il tuo progetto e sarà controllato dal codice sorgente insieme al tuo file csproj.