Betten Sie den Git Commit-Hash in eine .NET-DLL ein

101

Ich erstelle eine C # -Anwendung und verwende Git als Versionskontrolle.

Gibt es eine Möglichkeit, den letzten Commit-Hash beim Erstellen meiner Anwendung automatisch in die ausführbare Datei einzubetten?

Das Drucken des Commit-Hashs auf die Konsole sieht beispielsweise folgendermaßen aus:

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

Beachten Sie, dass dies zur Erstellungszeit und nicht zur Laufzeit erfolgen muss , da für meine bereitgestellte ausführbare Datei das Git-Repo nicht verfügbar ist.

Eine verwandte Frage zu C ++ finden Sie hier .

EDIT

Pro @ mattanja Verlangen Ich poste das git Haken Skript , das ich in meinen Projekten verwenden. Die Einrichtung:

  • Die Hooks sind Linux-Shell-Skripte, die unter: path_to_project \ .git \ hooks abgelegt werden
  • Wenn Sie msysgit verwenden , enthält der Hooks- Ordner bereits einige Beispielskripte. Entfernen Sie die Erweiterung '.sample' aus dem Skriptnamen, damit git sie aufruft.
  • Die Namen der Hook-Skripte stimmen mit dem Ereignis überein, das sie aufruft. In meinem Fall habe ich Post-Commit und Post-Merge geändert .
  • Meine AssemblyInfo.cs- Datei befindet sich direkt unter dem Projektpfad (dieselbe Ebene wie der .git- Ordner). Es enthält 23 Zeilen und ich benutze git, um die 24. zu generieren.

Da mein Linux-Shelling etwas verrostet ist, liest das Skript einfach die ersten 23 Zeilen von AssemblyInfo.cs in eine temporäre Datei, gibt den Git-Hash in die letzte Zeile zurück und benennt die Datei wieder in AssemblyInfo.cs um . Ich bin sicher, es gibt bessere Möglichkeiten, dies zu tun:

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

Hoffe das hilft.

bavaza
quelle
git rev-parse HEADDas würde dir den Hash bringen, aber ich bin kein C # -Entwickler, also weiß ich nicht, wie du es erreichen kannst.
Learath2

Antworten:

61

Wir verwenden Tags in Git, um Versionen zu verfolgen.

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

Sie können die Version mit Hash von git erhalten über:

git describe --long

Unser Erstellungsprozess fügt den Git-Hash in das AssemblyInformationalVersion-Attribut der AssemblyInfo.cs-Datei ein:

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

Nach dem Kompilieren können Sie die Version im Windows Explorer anzeigen:

Geben Sie hier die Bildbeschreibung ein

Sie können es auch programmgesteuert über Folgendes abrufen:

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

Dabei ist YOURTYPE ein beliebiger Typ in der Assembly, der das Attribut AssemblyInformationalVersion hat.

Handwerker
quelle
13
Hallo, ich wollte vor einem Monat fragen, aber ich hatte nicht genug Repräsentanten, um einen Kommentar abzugeben. Wenn Sie sagen: "Unser Erstellungsprozess fügt den Git-Hash in das AssemblyInformationalVersion-Attribut von AssemblyInfo.cs ein", was genau ist dort los? Machst du nur einen visuellen Studio-Build oder verwendest du so etwas wie NAnt oder ein anderes Tool?
John Jesus
3
Wir verwenden Ruby (Rake), um unseren Build zu automatisieren. Eine unserer Rake-Build-Aufgaben aktualisiert die Datei CommonAssemblyInfo.cs, die für alle Projekte in der Lösung verwendet wird. Die Aufgabe generiert die Datei CommonAssemblyInfo.cs mit albacore - github.com/derickbailey/Albacore. Einer der AssemblyInfo-Werte, die von der Aufgabe festgelegt werden, ist die AssemblyInformationalVersion.
Handcraftsman
3
@ John Jesus - wie Lazy Badger vorgeschlagen hat, können Sie auch Git-Hooks verwenden, um AssemblyInfo.cs nach dem Festschreiben / Zusammenführen usw. zu ändern (dies ist, was ich letztendlich getan habe). Siehe kernel.org/pub/software/scm/git/docs/githooks.html
bavaza
1
@bavaza, das klingt nach einer guten Möglichkeit - würde es Ihnen etwas ausmachen, Ihr Hook-Skript zu teilen?
Mattanja
5
Das folgende Projekt https://github.com/jeromerg/NGitVersion bietet eine vollständige Lösung zum Generieren von GlobalAssemblyInfo.*Dateien zur Kompilierungszeit für C # - und C ++ - Projekte: Standardmäßig enthält die generierte Assemblyversion: den Commit-Hash, ein Flag, das lokale Änderungen signalisiert, und einen Inkrementieren der Anzahl der Festschreibungen vom Repository-Stamm bis zur aktuellen Festschreibung.
Jeromerg
75

Sie können eine version.txt- Datei in die ausführbare Datei einbetten und dann die version.txt aus der ausführbaren Datei lesen . Verwenden Sie zum Erstellen der Datei version.txtgit describe --long

Hier sind die Schritte:

Verwenden Sie ein Build-Ereignis, um git aufzurufen

  • Klicken Sie mit der rechten Maustaste auf das Projekt und wählen Sie Eigenschaften

  • Fügen Sie unter Build-Ereignisse ein Pre-Build-Ereignis hinzu, das Folgendes enthält (beachten Sie die Anführungszeichen):

    "C: \ Programme \ Git \ bin \ git.exe" beschreiben --long> "$ (ProjectDir) \ version.txt"

    Dadurch wird eine version.txt- Datei in Ihrem Projektverzeichnis erstellt.

Betten Sie die version.txt in die ausführbare Datei ein

  • Klicken Sie mit der rechten Maustaste auf das Projekt und wählen Sie Vorhandenes Element hinzufügen
  • Fügen Sie die Datei version.txt hinzu (ändern Sie den Filter für die Dateiauswahl, damit Sie alle Dateien sehen können).
  • Nachdem version.txt hinzugefügt wurde, klicken Sie im Projektmappen-Explorer mit der rechten Maustaste darauf und wählen Sie Eigenschaften
  • Ändern Sie die Build-Aktion in Embedded Resource
  • Ändern Sie "Kopieren in Ausgabeverzeichnis" in "Immer kopieren"
  • In version.txt auf Ihre .gitignore Datei

Lesen Sie die Versionszeichenfolge der eingebetteten Textdatei

Hier ist ein Beispielcode zum Lesen der Versionszeichenfolge für eingebettete Textdateien:

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();
        }
    }
}
Johannes Jesus
quelle
8
Dieser Ansatz funktioniert ziemlich gut. Ich habe allerdings "git rev-parse --short HEAD" verwendet.
Brian Reiter
2
Ah gut. Ich habe "git beschreiben" verwendet, weil es (für mich) wirklich interessant ist, wenn Sie ein Tag haben; Die Versionsinformationen enthalten das Tag sowie die Anzahl der Commits, nachdem das Tag angewendet wurde. Ich habe noch nie so etwas wie in einem SCM gesehen.
Johannes Jesus
6
Ich benutze git describe --dirty, was ein Flag hinzufügt, wenn Entwickler mit einem schmutzigen Arbeitsbaum arbeiten.
Paulmelnikow
2
@ TamásSzelei Der Projekt-Namespace ist TryGitDescribe. Nachdem die Datei version.txt in das Artefakt der ausführbaren Datei / Assembly eingebettet wurde, müssen Sie den Namespace voranstellen, um sie herauszuholen.
John Jesus
4
Ich benutze git describe --always, um Tags zu verwenden oder auf einen abgekürzten Hash zurückzugreifen
Ibraheem
48

AKTUALISIEREN:

Die Dinge haben sich weiterentwickelt, seit ich diese Frage ursprünglich beantwortet habe. Das Microsoft.NET.Sdk(dh Sie müssen ein Projekt im SDK-Stil verwenden) unterstützt jetzt das Hinzufügen des Commit-Hashs sowohl zur Assembly-Informationsversion als auch zu den Metadaten des Nuget-Pakets, wenn einige Bedingungen erfüllt sind:

  1. Die <SourceRevisionId>Eigenschaft muss definiert werden. Dies kann durch Hinzufügen eines Ziels wie folgt erfolgen:
<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>

Dieses Ziel führt einen Befehl aus, SourceRevisionIdder als abgekürzter (8 Zeichen) Hash festgelegt wird. Die BeforeTargets bewirken, dass dies ausgeführt wird, bevor die Assembly-Informationsversion erstellt wird.

  1. Um den Hash in die Metadaten des Nuget-Pakets aufzunehmen, <RepositoryUrl>muss auch der Hash definiert werden.

  2. <SourceControlInformationFeatureSupported>Eigenschaft muss sein true, dies bewirkt, dass die Nuget-Pack-Task auch die SourceRevisionId aufnimmt.

Ich würde Leute davon abhalten, das MSBuildGitHash-Paket zu verwenden, da diese neue Technik sauberer und beständiger ist.

ORIGINAL:

Ich habe ein einfaches Nuget-Paket erstellt, das Sie in Ihr Projekt aufnehmen können und das dies für Sie erledigt: https://www.nuget.org/packages/MSBuildGitHash/

Dieses Nuget-Paket implementiert eine "reine" MSBuild-Lösung. Wenn Sie sich nicht auf ein Nuget-Paket verlassen möchten, können Sie diese Ziele einfach in Ihre csproj-Datei kopieren. Der Git-Hash sollte als benutzerdefiniertes Assembly-Attribut enthalten sein:

<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>

Hier gibt es zwei Ziele. Der erste, "GetGitHash", lädt den Git-Hash in eine MSBuild-Eigenschaft namens BuildHash. Dies geschieht nur, wenn BuildHash noch nicht definiert ist. Auf diese Weise können Sie es in der Befehlszeile an MSBuild übergeben, wenn Sie dies bevorzugen. Sie können es wie folgt an MSBuild weitergeben:

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

Das zweite Ziel, "WriteGitHash", schreibt den Hashwert in eine Datei im temporären Ordner "obj" mit dem Namen "CustomAssemblyInfo.cs". Diese Datei enthält eine Zeile, die wie folgt aussieht:

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

Diese CustomAssemblyInfo.cs-Datei wird in Ihre Assembly kompiliert, sodass Sie mithilfe der Reflektion nach der AssemblyMetadataLaufzeit suchen können . Der folgende Code zeigt, wie dies durchgeführt werden kann, wenn die AssemblyInfoKlasse in derselben Assembly enthalten ist.

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

Einige Vorteile dieses Designs sind, dass es keine Dateien in Ihrem Projektordner berührt. Alle mutierten Dateien befinden sich im Ordner "obj". Ihr Projekt wird auch in Visual Studio oder über die Befehlszeile identisch erstellt. Es kann auch einfach an Ihr Projekt angepasst werden und wird zusammen mit Ihrer csproj-Datei quellgesteuert.

MarkPflug
quelle
2
Das hat perfekt funktioniert. Ich habe das Nuget-Paket installiert und konnte den Git-Hash mit herausziehen Assembly.GetExecutingAssembly()und dann die Baugruppe untersuchen CustomAttributes .
Gavin H
1
Wenn dies meine Frage wäre, hätte ich diese Antwort akzeptiert. Tolles Zeug.
Drew Noakes
1
@ GavinH, wie hast du das bekommen GitHash? Ich kann sehen, dass dieser Wert existiert, aber gibt es eine reine Methode, um ein benutzerdefiniertes Attribut nach Namen zu erhalten? Es scheint, dass ich lange Where-Select-Abfragen schreiben muss CustomAttributes, danke.
Okan Kocyigit
1
@ocanal ja - leider konnte ich keinen saubereren Weg finden, als das zu lesen CustomAttributes. Hier ist zum Beispiel die Funktion, mit der ich die Hash-Zeichenfolge extrahiere: pastebin.com/nVKGLhJC
Gavin H
2
@danmiser Ich habe keine Ahnung, was "UseMerge / SingleAssemblyName" ist, daher kann ich Ihnen nicht helfen. Erstellen Sie ein Problem unter github.com/MarkPflug/MSBuildGitHash, und ich könnte es mir ansehen (das ist kein Versprechen).
MarkPflug
13

Eine andere Möglichkeit, dies zu tun, besteht darin, das NetRevisionTool mit etwas On-Board Visual Studio-Magie zu verwenden. Ich werde dies hier für Visual Studio 2013 Professional Edition vorstellen, aber dies wird auch mit anderen Versionen funktionieren.

Laden Sie also zuerst das NetRevisionTool herunter. Sie fügen die Datei NetRevisionTool.exe in Ihren PATH ein oder checken sie in Ihr Repository ein, erstellen eine Visual Studio-Vor- und eine Nacherstellungsaktion und ändern Ihre AssemblyInfo.cs.

Ein Beispiel, das Ihren Git-Hash zu Ihrer AssemblyInformationVersion hinzufügen würde, wäre das Folgende: In Ihren Projekteinstellungen:

Geben Sie hier die Bildbeschreibung ein

In den AssemblyInfo.cs Ihres Projekts ändern / fügen Sie die folgende Zeile hinzu:

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

Im gezeigten Screenshot habe ich in NetRevisionTool.exe im Ordner External / bin nachgesehen

Wenn Sie nach dem Erstellen mit der rechten Maustaste auf Ihre Binärdatei klicken und zu den Eigenschaften wechseln, sollte Folgendes angezeigt werden:

Geben Sie hier die Bildbeschreibung ein

Hoffe das hilft jemandem da draußen

schmendrick
quelle
Der Commit-Hash für mich endet immer mit 00000. Ich dachte, das lag daran, dass ich nicht festgeschriebene Änderungen hatte, aber immer noch derselbe. Irgendeine Idee warum?
Viktor
3
Das Problem war, dass NetRevision meine ausführbare Git-Datei nicht fand. Der Grund dafür ist, dass wir SourceTree verwenden und Git darin eingebettet ist. Die Lösung bestand darin, git.exe und libiconv-2.dll aus% USERPROFILE% \ AppData \ Local \ Atlassian \ SourceTree \ git_local \ bin in den Ordner mit NetRevision.exe zu kopieren. Ich musste auch die Ereignisse wie folgt ändern: Pre-Build-Ereignis: cd $ (ProjectDir) Libraries NetRevisionTool.exe / patch $ (ProjectDir) Post-Build-Ereignis: cd $ (ProjectDir) Libraries NetRevisionTool.exe / restore $ (ProjectDir)
Viktor
Nur zum späteren Nachschlagen wurde die Projekt-Repo-URL vor einiger Zeit in github.com/ygoe/NetRevisionTool geändert . Weitere Informationen finden Sie auch unter unclassified.software/apps/netrevisiontool .
Ygoe
13

Ich denke, diese Frage ist es wert, Schritt für Schritt vollständig beantwortet zu werden. Die Strategie hierfür besteht darin, ein Powershell-Skript aus den Pre-Build-Ereignissen auszuführen, das eine Vorlagendatei aufnimmt und eine AssemblyInfo.cs-Datei mit den enthaltenen Informationen zum Git-Tag + Commit-Anzahl generiert.

Schritt 1: Erstellen Sie eine AssemblyInfo_template.cs-Datei im Ordner Project \ Properties, basierend auf Ihrer ursprünglichen AssemblyInfo.cs-Datei, die jedoch Folgendes enthält:

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

Schritt 2: Erstellen Sie ein Powershell-Skript mit dem Namen InjectGitVersion.ps1, dessen Quelle lautet:

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

Schritt 3: Speichern Sie die Datei InjectGitVersion.ps1 in Ihrem Lösungsverzeichnis in einem BuildScripts-Ordner

Schritt 4: Fügen Sie den Pre-Build-Ereignissen des Projekts die folgende Zeile hinzu

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

Schritt 5: Erstellen Sie Ihr Projekt.

Schritt 6: Fügen Sie optional AssemblyInfo.cs zu Ihrer Git-Ignorierdatei hinzu

Atilio Jobson
quelle
Und denken Sie daran, Ihre Git-Tags mit Dateiversionen kompatibel zu machen: z. B. 1.2.3. Wenn Sie kompliziertere Tags haben, müssen Sie nur die kompatiblen Teile analysieren
Atilio Jobson
2
Anstatt eine Vorlage und Gitignoring Real AssemblyInfo.cszu verwenden, könnte man sie AssemblyInfo.csan Ort und Stelle ändern , erstellen und dann AssemblyInfo.csauf die zuletzt festgeschriebene Version zurücksetzen. Im Repo würde es also immer geben AssemblyInfo.cs, wobei $..$nur die Bauzeit ersetzt wird.
Kuba Wyrostek
Das hat super geklappt. Am Ende habe ich git describe --match "v[0-9]*" --long --always --dirtynach bestimmten Tags gefiltert (die eine Versionsnummer enthalten) und angegeben, ob der Arbeitsbaum sauber war.
Packoman
Sie müssen auch Ihre RegEx im PS-Skript ändern:$gitVersion -match '[v](.*)-(\d+)-[g](.+)$';
Packoman
3

Da in der anderen Antwort bereits das Git-Bit erwähnt wird, können Sie nach dem SHA die AssemblyInfo.csDatei Ihres Projekts in einem Pre-Build-Hook generieren .

Eine Möglichkeit, dies zu tun, besteht darin, eine AssemblyInfo.cs.tmplVorlagendatei mit einem Platzhalter für Ihre SHA in beispielsweise $$ GITSHA $$ zu erstellen, z

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

Ihr Pre-Build-Hook muss dann diesen Platzhalter ersetzen und die AssemblyInfo.cs-Datei ausgeben, damit der C # -Compiler sie abrufen kann.

In dieser Antwort erfahren Sie, wie dies mit SubWCRev für SVN möglich ist . Es sollte nicht schwer sein, etwas Ähnliches für Git zu tun.

Andere Möglichkeiten wären eine "Make Stage", wie erwähnt, dh das Schreiben einer MSBuild-Aufgabe, die etwas Ähnliches tut. Eine weitere Möglichkeit besteht darin, die DLL irgendwie nachzubearbeiten (z. B. ildasm + ilasm), aber ich denke, die oben genannten Optionen sind wahrscheinlich am einfachsten.

Marcus
quelle
+1. Hatte ein Dilemma, welche Antwort Sie auswählen sollten, Ihre oder die des Handwerkers. Sie waren die Ersten, aber ich habe mich wegen des vollständigen Beispiels für seine entschieden. Keine harten Gefühle :-)
bavaza
Auf diese Weise ändert sich AssemblyInfo.cs jedes Mal, wenn Sie Code senden. Senden Sie diese Datei also auch an git?
Wint
@Wint nein, füge die generierten AssemblyInfo.cs nicht zu git hinzu. Wenn Sie dies tun, ist es unmöglich, einen nicht schmutzigen Build zu erstellen: P
scherzte am
3

Mit .NET Revision Task für MSBuild und der Arbeit mit Visual Studio 2019 ist dies jetzt sehr einfach .

Installieren Sie einfach das NuGet- Paket Unclassified.NetRevisionTask und konfigurieren Sie die gewünschten Informationen in der AssemblyInfo.csDatei wie in der GitHub-Dokumentation beschrieben .

Wenn Sie nur den Hash des letzten Commits (Länge = 8) möchten:

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

Erstellen Sie Ihr Projekt / Ihre Lösung und Sie haben ungefähr Folgendes:

Geben Sie hier die Bildbeschreibung ein

krlzlx
quelle
Um das Format in einer NET.core-App zu konfigurieren, fügen Sie das PropertyGroupzur .csproj- Datei hinzu, wie in der README-Datei github.com/ygoe/NetRevisionTask/blob/master/README.md
sc911
2

Für eine vollautomatische und flexible Methode checken Sie https://github.com/Fody/Stamp . Wir haben dies erfolgreich für unsere Git-Projekte verwendet (sowie diese Version für SVN-Projekte).

Update: Dies ist veraltet, da Stamp.Fody nicht mehr gepflegt wird

mamuesstack
quelle
1
Auf der Github-Seite von Stamp.Fody heißt es: "Dieses Projekt wird nicht mehr gepflegt." Durch die Aufnahme in mein Projekt wurden CA0052 und CA0055
sc911 am
1

Sie können einen Powershell-Einzeiler verwenden, um alle Assemblyinfo-Dateien mit dem Commit-Hash zu aktualisieren.

$hash = git describe --long --always;gci **/AssemblyInfo.* -recurse | foreach { $content = (gc $_) -replace "\[assembly: Guid?.*", "$&`n[assembly: AssemblyMetadata(`"commithash`", `"$hash`")]" | sc $_ }
roh85
quelle
0
  1. Ich hoffe, Sie wissen, wie Sie externe Programme aufrufen und die Ausgabe während der Erstellung abfangen können.
  2. Ich hoffe, Sie wissen, wie man im Arbeitsverzeichnis von git nicht versionierte Dateien ignoriert.

Wie von @ learath2 angegeben, erhalten Sie bei der Ausgabe von git rev-parse HEADeinen einfachen Hash.

Wenn Sie Tags im Git-Repository verwenden (und Tags verwenden, ist dies nicht aussagekräftiger und lesbarer als git rev-parse), kann die Ausgabe von empfangen werden git describe(während sie später auch erfolgreich verwendet wird git checkout).

Sie können rev-parse | description aufrufen in:

  • Einige machen Bühne
  • im Post-Commit-Hook
  • im Wischfilter, wenn Sie die Art der Implementierung für Wisch- / Reinigungsfilter auswählen
Fauler Dachs
quelle
0

Ich verwende eine Kombination aus der akzeptierten Antwort und einer kleinen Ergänzung. Ich habe die AutoT4-Erweiterung installiert ( https://marketplace.visualstudio.com/items?itemName=BennorMcCarthy.AutoT4 ), um die Vorlagen vor dem Erstellen erneut auszuführen.

Version von GIT bekommen

Ich habe git -C $(ProjectDir) describe --long --always > "$(ProjectDir)git_version.txt"in meinem Pre-Build-Event Projekteigenschaften. Das Hinzufügen von git_version.txt und VersionInfo.cs zu .gitignore ist eine gute Idee.

Einbettung der Version in Metadaten

Ich habe VersionInfo.ttmeinem Projekt eine Vorlage hinzugefügt :

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

#>

Jetzt habe ich mein Git-Tag + Hash in "ProductVersion".

jelinek.01
quelle
0

Unter Bezugnahme auf die andere Antwort ( https://stackoverflow.com/a/44278482/4537127 ) habe ich auch die VersionInfo.ttTextvorlage verwendet, um AssemblyInformationalVersionohne AutoT4 zu generieren .

(Mindestens funktioniert in meiner C # WPF-Anwendung)

Das Problem war, dass die Pre-Build-Ereignisse nach Vorlagentransformationen ausgeführt wurden. Nach dem Klonen war die git_version.txtDatei nicht vorhanden und der Build schlägt fehl. Nachdem es manuell erstellt wurde, damit die Transformation einmal bestanden werden kann, wurde es nach der Transformation aktualisiert und war immer ein Commit dahinter .

Ich musste zwei Anpassungen an der .csproj-Datei vornehmen (dies gilt zumindest für Visual Studio Community 2017).

1) Importieren Sie die Texttransformationsziele und führen Sie Vorlagentransformationen durch, die bei jedem Build ausgeführt werden sollen: (Siehe 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>

und danach <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

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

2) git describeFühren Sie den Lauf vor den Template-Transformationen durch (damit er vorhanden git_version.txtist, wenn er VersionInfo.tttransformiert wird):

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

..Und den C # -Code, um den zu erhalten 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;
    }
}

..Und fügen Sie die generierten Dateien zu .gitignore hinzu

VersionInfo.cs
git_version.txt
kimmoli
quelle
0

Eine andere Möglichkeit wäre, eine Version.cs-Datei aus einem Pre-Build-Schritt zu generieren. Ich habe dies in einem kleinen Proof-of-Concept-Projekt untersucht, in dem der aktuelle Commit-Hash ausgedruckt wird.

Das Projekt wird auf https://github.com/sashoalm/GitCommitHashPrinter hochgeladen .

Der Stapelcode, der die Datei Version.cs erstellt, lautet wie folgt:

@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
quelle
0

Platz

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

im 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
quelle