ฝังคอมมิตแฮชใน. net dll


107

ฉันกำลังสร้างแอปพลิเคชัน C # โดยใช้ Git เป็นตัวควบคุมเวอร์ชัน

มีวิธีฝังแฮชคอมมิตสุดท้ายโดยอัตโนมัติในไฟล์ปฏิบัติการเมื่อฉันสร้างแอปพลิเคชันหรือไม่

ตัวอย่างเช่นการพิมพ์คอมมิตแฮชไปยังคอนโซลจะมีลักษณะดังนี้:

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

โปรดทราบว่าสิ่งนี้ต้องทำในเวลาสร้างไม่ใช่รันไทม์เนื่องจากไฟล์ปฏิบัติการที่ปรับใช้ของฉันจะไม่มี git repo ที่เข้าถึงได้

คำถามที่เกี่ยวข้องสำหรับ C ++ สามารถพบได้ที่นี่

แก้ไข

คำขอของ Per @ mattanja ฉันกำลังโพสต์สคริปต์ git hook ที่ฉันใช้ในโปรเจ็กต์ของฉัน การตั้งค่า:

  • hooks คือลินุกซ์เชลล์สคริปต์ซึ่งอยู่ภายใต้: path_to_project \ .git \ hooks
  • หากคุณกำลังใช้msysgitที่ตะขอโฟลเดอร์แล้วมีสคริปต์ตัวอย่างบางส่วน ในการเรียกคอมไพล์ให้ลบส่วนขยาย ".sample" ออกจากชื่อสคริปต์
  • ชื่อของสคริปต์ hook ตรงกับเหตุการณ์ที่เรียกใช้ ในกรณีของฉันฉันมีการปรับเปลี่ยนหลังกระทำและการโพสต์ผสาน
  • ไฟล์AssemblyInfo.csของฉันอยู่ภายใต้เส้นทางโครงการโดยตรง (ระดับเดียวกับโฟลเดอร์. git ) มันมี 23 บรรทัดและฉันใช้ git เพื่อสร้างวันที่ 24

ในฐานะที่เป็นลินุกซ์ปลอกกระสุนสนิมบิตของฉันสคริปต์ที่เพียงแค่อ่านครั้งแรก 23 สายของAssemblyInfo.csไปยังแฟ้มชั่วคราว echos คอมไพล์กัญชากับสายที่ผ่านมาและเปลี่ยนชื่อแฟ้มกลับไปยังAssemblyInfo.cs ฉันแน่ใจว่ามีวิธีที่ดีกว่านี้:

#!/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

หวังว่านี่จะช่วยได้

คำตอบ:


64

เราใช้แท็กในคอมไพล์เพื่อติดตามเวอร์ชัน

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

คุณสามารถรับเวอร์ชันที่มีแฮชจากคอมไพล์ผ่าน:

git describe --long

กระบวนการสร้างของเราทำให้แฮช git ในแอตทริบิวต์ AssemblyInformationalVersion ของไฟล์ AssemblyInfo.cs:

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

เมื่อคุณคอมไพล์แล้วคุณสามารถดูเวอร์ชันจาก windows explorer:

ป้อนคำอธิบายภาพที่นี่

คุณสามารถดาวน์โหลดแบบเป็นโปรแกรมผ่านทาง:

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

โดยที่ YOURTYPE คือ Type ใด ๆ ใน Assembly ที่มีแอตทริบิวต์ AssemblyInformationalVersion


14
สวัสดีฉันต้องการถามเดือนที่แล้ว แต่ฉันไม่มีตัวแทนเพียงพอที่จะแสดงความคิดเห็น เมื่อคุณพูดว่า "กระบวนการสร้างของเราทำให้แฮชคอมไพล์ในแอตทริบิวต์ AssemblyInformationalVersion ของ AssemblyInfo.cs" เกิดอะไรขึ้นที่นั่น? คุณกำลังสร้างวิชวลสตูดิโอหรือคุณกำลังใช้อะไรบางอย่างเช่น NAnt หรือเครื่องมืออื่น ๆ
John Jesus

3
เราใช้ทับทิม (คราด) เพื่อสร้างงานของเราโดยอัตโนมัติ หนึ่งในงานสร้างคราดของเราอัพเดตไฟล์ CommonAssemblyInfo.cs ที่ใช้กับโปรเจ็กต์ทั้งหมดในโซลูชัน งานสร้างไฟล์ CommonAssemblyInfo.cs โดยใช้ albacore - github.com/derickbailey/Albacore หนึ่งในค่า AssemblyInfo ที่ชุดงานคือ AssemblyInformationalVersion
Handcraftsman

3
@ John Jesus - ตามที่ Lazy Badger แนะนำคุณยังสามารถใช้ git hooks เพื่อเปลี่ยน AssemblyInfo.cs หลังจากกระทำ / ผสาน ฯลฯ (นี่คือสิ่งที่ฉันทำ) ดูkernel.org/pub/software/scm/git/docs/githooks.html
bavaza

เพียงแค่ FYI Albacore ได้ย้ายไปยังองค์กรฮับแห่งใหม่: github.com/Albacore/albacore
kornman00

5
โครงการต่อไปนี้https://github.com/jeromerg/NGitVersionนำเสนอโซลูชันที่สมบูรณ์ในการสร้างGlobalAssemblyInfo.*ไฟล์ในเวลาคอมไพล์สำหรับโครงการ C # และ C ++: โดยค่าเริ่มต้นเวอร์ชันแอสเซมบลีที่สร้างขึ้นประกอบด้วย: แฮชคอมมิตแฟล็กที่ส่งสัญญาณการเปลี่ยนแปลงในเครื่อง การเพิ่มขึ้นนับจำนวนคอมมิตจากรูทที่เก็บไปยังคอมมิตปัจจุบัน
jeromerg

78

คุณสามารถฝังไฟล์version.txtลงในไฟล์ปฏิบัติการจากนั้นอ่านversion.txtจากไฟล์ปฏิบัติการได้ ในการสร้างไฟล์version.txtให้ใช้git describe --long

ขั้นตอนมีดังนี้

ใช้ Build Event เพื่อเรียกคอมไพล์

  • คลิกขวาที่โครงการและเลือกคุณสมบัติ

  • ใน Build Events เพิ่มเหตุการณ์ Pre-Build ที่มี (สังเกตเครื่องหมายคำพูด):

    "C: \ Program Files \ Git \ bin \ git.exe" อธิบาย --long> "$ (ProjectDir) \ version.txt"

    ซึ่งจะสร้างไฟล์version.txtในไดเรกทอรีโครงการของคุณ

ฝัง version.txt ในไฟล์ปฏิบัติการ

  • คลิกขวาที่โครงการแล้วเลือกเพิ่มรายการที่มีอยู่
  • เพิ่มไฟล์version.txt (เปลี่ยนตัวกรองตัวเลือกไฟล์เพื่อให้คุณเห็นไฟล์ทั้งหมด)
  • หลังจากเพิ่มversion.txtแล้วให้คลิกขวาที่ Solution Explorer แล้วเลือก Properties
  • เปลี่ยน Build Action เป็น Embedded Resource
  • เปลี่ยน Copy to Output Directory เป็น Copy Always
  • เพิ่มversion.txtในไฟล์. gitignoreของคุณ

อ่านสตริงเวอร์ชันไฟล์ข้อความที่ฝัง

นี่คือโค้ดตัวอย่างสำหรับอ่านสตริงเวอร์ชันไฟล์ข้อความที่ฝัง:

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();
        }
    }
}

9
แนวทางนี้ใช้ได้ดีพอสมควร ฉันใช้ "git rev-parse --short HEAD"
Brian Reiter

3
ก็ดี. ฉันใช้ "git อธิบาย" เพราะมันน่าสนใจมาก (สำหรับฉัน) เมื่อคุณมีแท็ก ข้อมูลเวอร์ชันมีแท็กบวกจำนวนคอมมิตหลังจากใช้แท็ก ไม่เคยเห็นสิ่งที่เหมือนกับใน SCM มาก่อน
John Jesus

7
ฉันใช้git describe --dirtyซึ่งเพิ่มค่าสถานะเมื่อนักพัฒนากำลังทำงานกับทรีการทำงานที่สกปรก
paulmelnikow

2
@ TamásSzeleiเนมสเปซโปรเจ็กต์คือ TryGitDescribe หลังจากที่ไฟล์ version.txt ถูกฝังลงในส่วนปฏิบัติการ / แอสเซมบลีคุณจะต้องนำหน้าเนมสเปซเพื่อนำออก
John Jesus

2
ขอบคุณสำหรับการแก้ปัญหาที่สมบูรณ์ ในกรณีของฉันฉันเคยGetEntryAssemblyได้รับการประกอบ ไม่ว่าในกรณีใดคุณสามารถโทรGetName().Nameเพื่อหลีกเลี่ยงการเข้ารหัสชื่อได้
astrowalker

56

อัพเดท:

สิ่งต่างๆมีการพัฒนาตั้งแต่แรกที่ฉันตอบคำถามนี้ ขณะนี้Microsoft.NET.Sdk(หมายความว่าคุณต้องใช้โปรเจ็กต์สไตล์ sdk) รวมถึงการสนับสนุนสำหรับการเพิ่มแฮชคอมมิตให้กับทั้งเวอร์ชันข้อมูลแอสเซมบลีรวมถึงข้อมูลเมตาของแพ็กเกจ nuget หากตรงตามเงื่อนไขบางประการ:

  1. <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 ทำให้สิ่งนี้ถูกรันก่อนที่จะสร้างเวอร์ชันที่ให้ข้อมูลของแอสเซมบลี

  1. หากต้องการรวมแฮชไว้ในข้อมูลเมตาของแพ็กเกจ nuget <RepositoryUrl>ต้องกำหนดด้วย

  2. <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 &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>

มีสองเป้าหมายที่นี่ อันแรก "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
{
    /// <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;
    }
}

ข้อดีบางประการของการออกแบบนี้คือไม่ต้องสัมผัสกับไฟล์ใด ๆ ในโฟลเดอร์โปรเจ็กต์ของคุณไฟล์ที่กลายพันธุ์ทั้งหมดจะอยู่ในโฟลเดอร์ "obj" โครงการของคุณจะสร้างเหมือนกันจากภายใน Visual Studio หรือจากบรรทัดคำสั่ง นอกจากนี้ยังสามารถปรับแต่งได้อย่างง่ายดายสำหรับโครงการของคุณและจะถูกควบคุมแหล่งที่มาพร้อมกับไฟล์ csproj ของคุณ


2
สิ่งนี้ทำงานได้อย่างสมบูรณ์แบบ ผมติดตั้งแพคเกจ nuget และก็สามารถที่จะดึงออกกัญชาคอมไพล์ใช้แล้วตรวจสอบการชุมนุมAssembly.GetExecutingAssembly() CustomAttributes
Gavin H

1
หากนี่เป็นคำถามของฉันฉันยอมรับคำตอบนี้แล้ว สิ่งที่ดี
Drew Noakes

1
@GavinH คุณได้มาGitHashอย่างไร? ฉันเห็นว่ามีค่านั้นอยู่ แต่มีวิธีใดที่บริสุทธิ์ในการรับแอตทริบิวต์ที่กำหนดเองตามชื่อหรือไม่? ดูเหมือนว่าฉันต้องเขียนคำค้นหาที่เลือกยาวCustomAttributesๆ ขอบคุณ
Okan Kocyigit

2
@danmiser ฉันไม่รู้ว่า "UseMerge / SingleAssemblyName" คืออะไรฉันจึงไม่สามารถช่วยคุณได้ สร้างปัญหาที่github.com/MarkPflug/MSBuildGitHashและฉันอาจลองดู (นั่นไม่ใช่สัญญา)
MarkPflug

2
ขอบคุณสำหรับคำตอบที่ทันสมัย ​​- วิธีทำที่สะอาดจริงๆ สำหรับผู้อ่านในอนาคตที่มีปัญหาเดียวกันกับฉัน: สำหรับฉันที่จะทำให้สิ่งนี้ใช้งานได้ (สำหรับแนวทางโครงการ SDK) ฉันต้องการIncludeSourceRevisionInInformationalVersionคุณสมบัติเช่นกันและฉันยังSourceRevisionIdไม่ได้ตั้งค่าในเป้าหมาย InitializeSourceControlInformation แต่ใน a แยกเป้าหมายที่ประกาศด้วยBeforeTargets="InitializeSourceControlInformation".
glen3b

14

อีกวิธีหนึ่งในการทำเช่นนี้คือการใช้NetRevisionToolกับมายากล On-Board Visual Studio ฉันจะแสดงสิ่งนี้ที่นี่สำหรับ Visual Studio 2013 Professional Edition แต่จะใช้งานได้กับเวอร์ชันอื่นด้วย

ก่อนอื่นให้ดาวน์โหลด NetRevisionTool คุณรวม NetRevisionTool.exe ใน PATH ของคุณหรือตรวจสอบในที่เก็บของคุณและสร้างวิชวลสตูดิโอก่อนสร้างและการดำเนินการหลังการสร้างและเปลี่ยน AssemblyInfo.cs ของคุณ

ตัวอย่างที่จะเพิ่ม git-hash ของคุณใน AssemblyInformationVersion ของคุณจะเป็นดังต่อไปนี้: ในการตั้งค่าโปรเจ็กต์ของคุณ:

ป้อนคำอธิบายภาพที่นี่

ใน AssemblyInfo.cs ของโครงการของคุณคุณเปลี่ยน / เพิ่มบรรทัด:

[แอสเซมบลี: AssemblyInformationalVersion ("1.1. {dmin: 2015}. {chash: 6} {!} - {branch}")]

ในภาพหน้าจอที่แสดงฉันตรวจสอบใน NetRevisionTool.exe ในโฟลเดอร์ภายนอก / bin

หลังจากสร้างแล้วหากคุณคลิกขวาที่ไบนารีของคุณและไปที่คุณสมบัติคุณจะเห็นสิ่งต่อไปนี้:

ป้อนคำอธิบายภาพที่นี่

หวังว่านี่จะช่วยใครสักคนได้


แฮชคอมมิตสำหรับฉันมักจะจบลงที่ 00000 ฉันคิดว่าเป็นเพราะฉันมีการเปลี่ยนแปลงที่ไม่ได้ผูกมัด แต่ก็ยังเหมือนเดิม คิดว่าทำไม?
Viktor

3
ปัญหาคือ NetRevision ไม่พบไฟล์ปฏิบัติการคอมไพล์ของฉัน สาเหตุเป็นเพราะเราใช้ SourceTree และ git มาพร้อมกับมัน วิธีแก้ปัญหาคือคัดลอก git.exe และ libiconv-2.dll จาก% USERPROFILE% \ AppData \ Local \ Atlassian \ SourceTree \ git_local \ bin ไปยังโฟลเดอร์ที่มี NetRevision.exe ฉันต้องแก้ไขเหตุการณ์เช่นนี้: เหตุการณ์ก่อนสร้าง: cd $ (ProjectDir) Libraries NetRevisionTool.exe / patch $ (ProjectDir) เหตุการณ์หลังการสร้าง: cd $ (ProjectDir) Libraries NetRevisionTool.exe / restore $ (ProjectDir)
Viktor

เพียงเพื่อใช้อ้างอิงในอนาคตโครงการ repo URL ที่มีการเปลี่ยนแปลงบางเวลาที่ผ่านมาเพื่อgithub.com/ygoe/NetRevisionTool ข้อมูลเพิ่มเติมก็ยังมีอยู่unclassified.software/apps/netrevisiontool
ygoe

14

ฉันคิดว่าคำถามนี้คุ้มค่าที่จะให้คำตอบทีละขั้นตอนอย่างสมบูรณ์ กลยุทธ์ที่จะเรียกใช้สคริปต์ powershell จากเหตุการณ์ก่อนสร้างที่ใช้ในไฟล์เทมเพลตและสร้างไฟล์ AssemblyInfo.cs พร้อมด้วยแท็ก git + ข้อมูลจำนวนคอมมิต

ขั้นตอนที่ 1:สร้างไฟล์ AssemblyInfo_template.cs ในโฟลเดอร์ Project \ Properties ตาม AssemblyInfo.cs ดั้งเดิมของคุณ แต่มี:

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

ขั้นตอนที่ 2:สร้างสคริปต์ powershell ชื่อ InjectGitVersion.ps1 ซึ่งมีแหล่งที่มา:

# 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;       
}

ขั้นตอนที่ 3:บันทึกไฟล์ InjectGitVersion.ps1 ลงในไดเร็กทอรีโซลูชันของคุณในโฟลเดอร์ BuildScripts

ขั้นตอนที่ 4:เพิ่มบรรทัดต่อไปนี้ในเหตุการณ์ก่อนสร้างของโครงการ

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

ขั้นตอนที่ 5:สร้างโครงการของคุณ

ขั้นตอนที่ 6:เลือกที่จะเพิ่ม AssemblyInfo.cs ในไฟล์ git ละเว้น


และอย่าลืมทำให้แท็ก git ของคุณเข้ากันได้กับเวอร์ชันไฟล์เช่น 1.2.3 หากคุณมีแท็กที่ซับซ้อนมากขึ้นคุณจะต้องแยกวิเคราะห์เฉพาะส่วนที่เข้ากันได้
Atilio Jobson

2
แทนที่จะใช้เทมเพลตและ gitignoring ของจริงAssemblyInfo.csสามารถแก้ไขAssemblyInfo.csในสถานที่สร้างจากนั้น git รีเซ็ตAssemblyInfo.csเป็นเวอร์ชันสุดท้ายที่กำหนด ดังนั้นใน repo จะมีเสมอAssemblyInfo.csโดย$..$แทนที่เฉพาะช่วงเวลาที่สร้างเท่านั้น
Kuba Wyrostek

สิ่งนี้ได้ผลดี ฉันลงเอยด้วยการใช้git describe --match "v[0-9]*" --long --always --dirtyเพื่อกรองแท็กบางแท็ก (ที่มีหมายเลขเวอร์ชัน) และเพื่อระบุว่าโครงสร้างการทำงานนั้นสะอาดหรือไม่
packoman

คุณต้องแก้ไข RegEx ของคุณในสคริปต์ PS ด้วย:$gitVersion -match '[v](.*)-(\d+)-[g](.+)$';
packoman

4

ตอนนี้ง่ายมากกับ. NET Revision Task สำหรับ MSBuildและทำงานกับ Visual Studio 2019

เพียงติดตั้งแพ็คเกจNuGet Unclassified.NetRevisionTaskจากนั้นกำหนดค่าข้อมูลที่คุณต้องการในไฟล์AssemblyInfo.csแฟ้มที่อธิบายไว้ในเอกสาร GitHub

หากคุณต้องการเฉพาะแฮชของคอมมิตสุดท้าย (length = 8):

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

สร้างโครงการ / โซลูชันของคุณแล้วคุณจะมีสิ่งนี้:

ป้อนคำอธิบายภาพที่นี่


การกำหนดค่ารูปแบบในแอปพลิเค NET.core เพิ่มPropertyGroupไป.csprojไฟล์เช่นที่เห็นใน README github.com/ygoe/NetRevisionTask/blob/master/README.md
sc911

3

ดังที่คำตอบอื่นกล่าวถึงบิตคอมไพล์แล้วเมื่อคุณมี SHA คุณสามารถพิจารณาสร้างAssemblyInfo.csไฟล์ของโปรเจ็กต์ของคุณใน pre-build hook

วิธีหนึ่งในการทำเช่นนี้คือสร้างAssemblyInfo.cs.tmplไฟล์เทมเพลตโดยมีตัวยึดตำแหน่งสำหรับ SHA ของคุณในรูปแบบ $$ GITSHA $$ เช่น

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

pre build hook ของคุณจะต้องแทนที่ตัวยึดนี้และส่งออกไฟล์ AssemblyInfo.cs เพื่อให้คอมไพเลอร์ C # รับ

หากต้องการดูว่าสามารถทำได้โดยใช้ SubWCRev สำหรับ SVN ดูคำตอบนี้ ไม่ควรทำสิ่งที่คล้ายกันสำหรับคอมไพล์

วิธีอื่นจะเป็น "make stage" ตามที่กล่าวไว้เช่นเขียน MSBuild task ที่ทำคล้าย ๆ กัน อีกวิธีหนึ่งคือการโพสต์กระบวนการ DLL อย่างใดอย่างหนึ่ง (ildasm + ilasm พูด) แต่ฉันคิดว่าตัวเลือกที่กล่าวถึงข้างต้นน่าจะง่ายที่สุด


@ ไม่เป็นไรอย่าเพิ่ม AssemblyInfo.cs ที่สร้างขึ้นไปยังคอมไพล์ ถ้าคุณทำมันจะเป็นไปไม่ได้ที่จะสร้างสิ่งที่ไม่สกปรก: P
ติดตลก

3

สำหรับอัตโนมัติอย่างเต็มที่และมีความยืดหยุ่นวิธีการเช็คเอาต์https://github.com/Fody/Stamp เราใช้สิ่งนี้สำเร็จสำหรับโครงการ Git ของเรา (เช่นเดียวกับเวอร์ชันนี้สำหรับโครงการ SVN)

อัปเดต: สิ่งนี้ล้าสมัยไปแล้วเนื่องจากไม่มีการบำรุงรักษา Stamp.Fody


1
ในหน้า github ของ Stamp มีเนื้อหาระบุว่า: "โครงการนี้ไม่ได้รับการดูแลอีกต่อไป" รวมทั้งในโครงการของฉันเพิ่ม CA0052 และ CA0055
sc911

2

คุณสามารถใช้ powershell one-liner เพื่ออัพเดตไฟล์ assemblyinfo ทั้งหมดด้วยคอมมิตแฮช

$hash = git describe --long --always;gci **/AssemblyInfo.* -recurse | foreach { $content = (gc $_) -replace "\[assembly: Guid?.*", "$&`n[assembly: AssemblyMetadata(`"commithash`", `"$hash`")]" | sc $_ }

1
  1. ฉันหวังว่าคุณจะรู้วิธีเรียกโปรแกรมภายนอกและสกัดกั้นเอาต์พุตในเวลาสร้าง
  2. ฉันหวังว่าคุณจะรู้ว่าจะมีอย่างไรในไดเร็กทอรีการทำงานของ git ละเว้นไฟล์ที่ไม่ได้เวอร์ชัน

ตามที่ระบุไว้โดย @ learath2 ผลลัพธ์ของ git rev-parse HEADจะให้แฮชธรรมดาแก่คุณ

หากคุณใช้แท็กใน Git-repository (และคุณใช้แท็กมันไม่ได้สื่อความหมายและอ่านได้มากกว่าgit rev-parse) เอาต์พุตอาจได้รับจากgit describe(ในขณะที่ใช้สำเร็จในภายหลังgit checkout)

คุณสามารถเรียก rev-parse | อธิบายใน:


0

ฉันใช้การผสมผสานระหว่างคำตอบที่ยอมรับและคำพูดเล็ก ๆ น้อย ๆ ฉันติดตั้งส่วนขยาย AutoT4 แล้ว ( https://marketplace.visualstudio.com/items?itemName=BennorMcCarthy.AutoT4 ) เพื่อเรียกใช้เทมเพลตอีกครั้งก่อนสร้าง

รับเวอร์ชันจาก GIT

ฉันมี git -C $(ProjectDir) describe --long --always > "$(ProjectDir)git_version.txt"ในเหตุการณ์ก่อนสร้างในคุณสมบัติโครงการ การเพิ่ม git_version.txt และ VersionInfo.cs ลงใน. gitignore เป็นความคิดที่ดีทีเดียว

การฝังเวอร์ชันในข้อมูลเมตา

ฉันได้เพิ่มVersionInfo.ttเทมเพลตในโครงการของฉัน:

<#@ 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"));
}

#>

ตอนนี้ฉันมี git tag + แฮชใน "ProductVersion"


0

อ้างถึงคำตอบอื่น ( https://stackoverflow.com/a/44278482/4537127 ) ฉันยังใช้VersionInfo.ttเทมเพลตข้อความเพื่อสร้างAssemblyInformationalVersionโดยไม่ใช้ AutoT4

(Atleast ทำงานในแอปพลิเคชัน C # WPF ของฉัน)

ปัญหาคือเหตุการณ์ก่อนสร้างถูกรันหลังจากการแปลงเทมเพลตดังนั้นหลังจากการโคลนgit_version.txtไฟล์จึงไม่อยู่ที่นั่นและการสร้างล้มเหลว หลังจากที่สร้างได้ด้วยตนเองที่จะช่วยให้การเปลี่ยนแปลงที่จะผ่านครั้งเดียวก็ได้รับการปรับปรุงหลังจากการเปลี่ยนแปลงและมักจะเป็นหนึ่งที่อยู่เบื้องหลังการกระทำ

ฉันต้องทำการปรับเปลี่ยนสองครั้งในไฟล์. csproj (สิ่งนี้ใช้อย่างน้อยสำหรับ Visual Studio Community 2017)

1) นำเข้าเป้าหมายการแปลงข้อความและทำการแปลงเทมเพลตเพื่อรันในทุกบิลด์: (อ้างอิง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>

และหลังจากนั้น <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

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

2) ทำการgit describeรันก่อนการแปลงเทมเพลต (ดังนั้นgit_version.txtเมื่อVersionInfo.ttมีการแปลงร่าง):

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

.. และรหัส C # เพื่อรับAssemblyInformationalVersion(อ้างอิงhttps://stackoverflow.com/a/7770189/4537127 )

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

        return attribute.InformationalVersion;
    }
}

.. และเพิ่มไฟล์ที่สร้างเป็น. gitignore

VersionInfo.cs
git_version.txt

0

อีกวิธีหนึ่งคือการสร้างไฟล์ Version.cs จากขั้นตอนก่อนสร้าง ฉันสำรวจสิ่งนี้ในโครงการพิสูจน์แนวคิดเล็ก ๆ น้อย ๆ ซึ่งพิมพ์แฮชคอมมิตปัจจุบันออกมา

Tha project ถูกอัพโหลดบนhttps://github.com/sashoalm/GitCommitHashPrinter https://github.com/sashoalm/GitCommitHashPrinter

รหัสแบทช์ที่สร้างไฟล์ Version.cs คือ:

@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    

0

สถานที่

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

ใน 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;

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.