อัพเดท:
สิ่งต่างๆมีการพัฒนาตั้งแต่แรกที่ฉันตอบคำถามนี้ ขณะนี้Microsoft.NET.Sdk(หมายความว่าคุณต้องใช้โปรเจ็กต์สไตล์ sdk) รวมถึงการสนับสนุนสำหรับการเพิ่มแฮชคอมมิตให้กับทั้งเวอร์ชันข้อมูลแอสเซมบลีรวมถึงข้อมูลเมตาของแพ็กเกจ nuget หากตรงตามเงื่อนไขบางประการ:
<SourceRevisionId>คุณสมบัติจะต้องกำหนด สามารถทำได้โดยเพิ่มเป้าหมายดังนี้:
<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>
เป้าหมายนี้เรียกใช้คำสั่งที่จะกำหนดSourceRevisionIdให้เป็นแฮชแบบย่อ (8 อักขระ) BeforeTargets ทำให้สิ่งนี้ถูกรันก่อนที่จะสร้างเวอร์ชันที่ให้ข้อมูลของแอสเซมบลี
หากต้องการรวมแฮชไว้ในข้อมูลเมตาของแพ็กเกจ nuget <RepositoryUrl>ต้องกำหนดด้วย
<SourceControlInformationFeatureSupported>คุณสมบัติต้องเป็นtrueสิ่งนี้ทำให้งาน nuget pack รับ SourceRevisionId ด้วย
ฉันจะหลีกเลี่ยงการใช้แพคเกจ MSBuildGitHash เนื่องจากเทคนิคใหม่นี้สะอาดและสม่ำเสมอที่สุด
เดิม:
ฉันได้สร้างแพ็คเกจ nuget ง่ายๆที่คุณสามารถรวมไว้ในโครงการของคุณซึ่งจะดูแลสิ่งนี้ให้คุณ: https://www.nuget.org/packages/MSBuildGitHash/
แพคเกจนักเก็ตนี้ใช้โซลูชัน MSBuild แบบ "บริสุทธิ์" หากคุณไม่ต้องการขึ้นอยู่กับแพ็กเกจ nuget คุณสามารถคัดลอก Targets เหล่านี้ไปยังไฟล์ csproj ของคุณและควรรวมแฮช git เป็นแอตทริบิวต์แอสเซมบลีที่กำหนดเอง:
<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>
มีสองเป้าหมายที่นี่ อันแรก "GetGitHash" โหลดแฮชคอมไพล์ลงในคุณสมบัติ MSBuild ชื่อ BuildHash ซึ่งจะทำได้ก็ต่อเมื่อ BuildHash ไม่ได้กำหนดไว้ สิ่งนี้ช่วยให้คุณสามารถส่งต่อไปยัง MSBuild บนบรรทัดคำสั่งได้หากต้องการ คุณสามารถส่งต่อไปยัง MSBuild ได้ดังนี้:
MSBuild.exe myproj.csproj /p:BuildHash=MYHASHVAL
เป้าหมายที่สอง "WriteGitHash" จะเขียนค่าแฮชลงในไฟล์ในโฟลเดอร์ "obj" ชั่วคราวชื่อ "CustomAssemblyInfo.cs" ไฟล์นี้จะมีบรรทัดที่ดูเหมือน:
[assembly: AssemblyMetadata("GitHash", "MYHASHVAL")]
ไฟล์ CustomAssemblyInfo.cs นี้จะถูกคอมไพล์ไว้ในแอสเซมบลีของคุณดังนั้นคุณสามารถใช้การสะท้อนเพื่อค้นหาAssemblyMetadataรันไทม์ได้ รหัสต่อไปนี้แสดงให้เห็นว่าสามารถทำได้อย่างไรเมื่อAssemblyInfoรวมคลาสอยู่ในแอสเซมบลีเดียวกัน
using System.Linq;
using System.Reflection;
public static class AssemblyInfo
{
public static string GetGitHash()
{
var asm = typeof(AssemblyInfo).Assembly;
var attrs = asm.GetCustomAttributes<AssemblyMetadataAttribute>();
return attrs.FirstOrDefault(a => a.Key == "GitHash")?.Value;
}
}
ข้อดีบางประการของการออกแบบนี้คือไม่ต้องสัมผัสกับไฟล์ใด ๆ ในโฟลเดอร์โปรเจ็กต์ของคุณไฟล์ที่กลายพันธุ์ทั้งหมดจะอยู่ในโฟลเดอร์ "obj" โครงการของคุณจะสร้างเหมือนกันจากภายใน Visual Studio หรือจากบรรทัดคำสั่ง นอกจากนี้ยังสามารถปรับแต่งได้อย่างง่ายดายสำหรับโครงการของคุณและจะถูกควบคุมแหล่งที่มาพร้อมกับไฟล์ csproj ของคุณ