154 votes

Intégrer un hash de commit git dans une dll .Net

Je suis en train de construire une application C#, en utilisant Git comme contrôle de version.

Existe-t-il un moyen d'intégrer automatiquement le dernier hash de commit dans l'exécutable lorsque je construis mon application ?

Par exemple, l'impression du hash du commit sur la console ressemblerait à quelque chose comme :

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

Notez que cela doit être fait à construire temps, pas temps de fonctionnement car mon exécutable déployé n'aura pas accès au dépôt git.

Une question connexe pour C++ peut être trouvée ici .

EDIT

A la demande de @mattanja, je poste le hook git script que j'utilise dans mes projets. La configuration :

  • Les hooks sont des scripts shell linux, qui sont placés sous : chemin_vers_le_projet \.git\hooks
  • Si vous utilisez msysgit le crochets contient déjà quelques exemples de scripts. Pour que git les appelle, enlevez l'extension '.sample' du nom du scripts.
  • Les noms des scripts de crochet correspondent à l'événement qui les invoque. Dans mon cas, j'ai modifié post-commission y post-fusion .
  • Mon AssemblyInfo.cs se trouve directement sous le chemin du projet (au même niveau que le fichier .git ). Il contient 23 lignes, et j'utilise git pour générer la 24ème.

Comme mon linux-shelling est un peu rouillé, le script lit simplement les 23 premières lignes de AssemblyInfo.cs dans un fichier temporaire, ajoute le hash git à la dernière ligne, et renomme le fichier sous le nom de AssemblyInfo.cs . Je suis sûr qu'il existe de meilleures façons de procéder :

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

J'espère que cela vous aidera.

113voto

Mark Points 7136

UPDATE :

Les choses ont évolué depuis que j'ai répondu à cette question. Le site Microsoft.NET.Sdk (ce qui signifie que vous devez utiliser un projet de type sdk) inclut maintenant la prise en charge de l'ajout du hash de validation à la fois à la version informative de l'assemblage et aux métadonnées du paquet nuget, si certaines conditions sont remplies :

  1. El <SourceRevisionId> doit être définie. Ceci peut être fait en ajoutant une cible comme ceci :

    <Target Name="SetSourceRevisionId" BeforeTargets="InitializeSourceControlInformation"> <Exec Command="git describe --long --always --dirty --exclude=* --abbrev=8" ConsoleToMSBuild="True" IgnoreExitCode="False"

    <Output PropertyName="SourceRevisionId" TaskParameter="ConsoleOutput"/> </Exec> </Target>

Cette cible exécute une commande qui va définir SourceRevisionId pour être le hachage abrégé (8 caractères). L'option BeforeTargets fait en sorte qu'il soit exécuté avant la création de la version informative de l'assemblage.

  1. Pour inclure le hachage dans les métadonnées du paquet nuget, la commande <RepositoryUrl> doit également être défini.

  2. <SourceControlInformationFeatureSupported> La propriété doit être true ce qui fait que la tâche d'empaquetage de nuget prend également en compte le SourceRevisionId.

Je conseillerais aux gens de ne pas utiliser le paquet MSBuildGitHash, car cette nouvelle technique est plus propre et plus cohérente.

ORIGINAL :

J'ai créé un paquet nuget simple que vous pouvez inclure dans votre projet et qui s'occupera de cela pour vous : https://www.nuget.org/packages/MSBuildGitHash/

Ce paquet nuget implémente une solution MSBuild "pure". Si vous préférez ne pas dépendre d'un paquet nuget, vous pouvez simplement copier ces cibles dans votre fichier csproj et il devrait inclure le hash git comme un attribut d'assemblage personnalisé :

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

Il y a deux cibles ici. La première, "GetGitHash", charge le hash git dans une propriété MSBuild nommée BuildHash, elle uniquement fait cela si BuildHash n'est pas déjà défini. Cela vous permet de le passer à MSBuild sur la ligne de commande, si vous préférez. Vous pouvez le passer à MSBuild comme ceci :

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

La deuxième cible, "WriteGitHash", écrira la valeur de hachage dans un fichier du dossier temporaire "obj" nommé "CustomAssemblyInfo.cs". Ce fichier contiendra une ligne qui ressemble à ceci :

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

Ce fichier CustomAssemblyInfo.cs sera compilé dans votre assemblage, de sorte que vous pouvez utiliser la réflexion pour rechercher le fichier AssemblyMetadata au moment de l'exécution. Le code suivant montre comment cela peut être fait lorsque la fonction AssemblyInfo est incluse dans le même assemblage.

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

Les avantages de cette conception sont qu'elle ne touche aucun fichier dans le dossier de votre projet, tous les fichiers mutés se trouvent dans le dossier "obj". Votre projet sera également construit de manière identique à partir de Visual Studio ou de la ligne de commande. Il peut également être facilement personnalisé pour votre projet, et sera contrôlé par la source avec votre fichier csproj.

92voto

John Jesus Points 850

Vous pouvez intégrer un version.txt dans l'exécutable, puis lire le fichier version.txt de l'exécutable. Pour créer le version.txt utilisez git describe --long

Voici les étapes :

Utiliser un événement de construction pour appeler git

  • Cliquez avec le bouton droit de la souris sur le projet et sélectionnez Propriétés

  • Dans Build Events, ajoutez Pre-Build event containing (remarquez les guillemets) :

    " C:\Program Fichiers \Git\bin\git.exe " describe --long > "$(ProjectDir) \version.txt "

    Cela va créer un version.txt dans le répertoire de votre projet.

Intégrer la version.txt dans l'exécutable

  • Cliquez avec le bouton droit de la souris sur le projet et sélectionnez Ajouter un élément existant.
  • Ajouter le version.txt fichier (changez le filtre du sélecteur de fichiers pour que vous puissiez voir tous les fichiers)
  • Après version.txt est ajouté, cliquez avec le bouton droit de la souris sur celui-ci dans l'explorateur de solutions et sélectionnez Propriétés
  • Changez l'action de construction en ressource intégrée
  • Modifier la copie dans le répertoire de sortie pour qu'il soit toujours copié
  • Ajouter version.txt à votre .gitignore fichier

Lire la chaîne de version du fichier texte incorporé

Voici un exemple de code permettant de lire la chaîne de version du fichier texte intégré :

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

70voto

Handcraftsman Points 3166

Nous utilisons des balises dans git pour suivre les versions.

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

Vous pouvez obtenir la version avec hash de git via :

git describe --long

Notre processus de construction place le hash git dans l'attribut AssemblyInformationalVersion du fichier AssemblyInfo.cs :

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

Une fois la compilation effectuée, vous pouvez visualiser la version à partir de l'explorateur Windows :

enter image description here

Vous pouvez également l'obtenir de manière programmatique via :

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

où YOURTYPE est un type quelconque de l'ensemble qui possède l'attribut AssemblyInformationalVersion.

17voto

Atilio Jobson Points 439

Je pense que cette question mérite une réponse complète, étape par étape. La stratégie ici est d'exécuter un script powershell à partir des événements de pré-construction qui prend un fichier modèle et génère un fichier AssemblyInfo.cs avec le tag git + les informations du nombre de commit inclus.

Étape 1 : créer un fichier AssemblyInfo_template.cs dans le Projet \Properties basé sur votre AssemblyInfo.cs original mais contenant :

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

Étape 2 : Créer un script powershell nommé InjectGitVersion.ps1 dont la source est :

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

Étape 3 : Enregistrez le fichier InjectGitVersion.ps1 dans le répertoire de votre solution, dans un dossier BuildScripts.

Étape 4 : Ajoutez la ligne suivante aux événements Pre-Build du projet

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

Étape 5 : Construisez votre projet.

Étape 6 : Optionnellement, ajoutez AssemblyInfo.cs à votre fichier git ignore

14voto

schmendrick Points 451

Une autre façon de procéder est d'utiliser l'option NetRevisionTool avec un peu de magie de Visual Studio embarqué. Je vais présenter ici cette méthode pour Visual Studio 2013 Professional Edition, mais elle fonctionnera également avec d'autres versions.

Donc, téléchargez d'abord l'outil NetRevisionTool. Vous incluez le NetRevisionTool.exe dans votre PATH ou vous l'enregistrez dans votre dépôt et vous créez une action pré-build et post-build dans Visual Studio et vous modifiez votre AssemblyInfo.cs.

Un exemple qui ajouterait votre git-hash à votre AssemblyInformationVersion serait le suivant : Dans les paramètres de votre projet :

enter image description here

dans le AssemblyInfo.cs de votre projet vous changez/ajoutez la ligne :

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

Dans la capture d'écran montrée, j'ai vérifié NetRevisionTool.exe dans le dossier External/bin.

Après la construction, si vous cliquez avec le bouton droit de la souris sur votre binaire et allez dans les propriétés, vous devriez voir quelque chose comme ce qui suit :

enter image description here

J'espère que cela aidera quelqu'un d'autre

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X