web-dev-qa-db-fra.com

Incorporer le hachage git commit dans une dll .Net

Je construis une application C # en utilisant Git comme contrôle de version.

Existe-t-il un moyen d'incorporer automatiquement le dernier hachage de validation dans l'exécutable lorsque je construis mon application?

Par exemple, imprimer le hachage de 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 à build time, pas runtime , car mon exécutable déployé n'aura pas le git repo accessible.

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

EDIT

Selon la demande de @ mattanja, je poste le script git hook que j'utilise dans mes projets. La mise en place:

  • Les hooks sont des scripts shell Linux, placés sous: path_to_project\.git\hooks
  • Si vous utilisez msysgit , le dossier hooks contient déjà des exemples de scripts. Pour que git les appelle, supprimez l'extension '.sample' du nom du script.
  • Les noms des scripts de raccordement correspondent à l'événement qui les appelle. Dans mon cas, j’ai modifié post-commit et post-fusion.
  • Mon fichier AssemblyInfo.cs est directement sous le chemin du projet (même niveau que le dossier .git). Il contient 23 lignes et j’utilise git pour générer la 24e.

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

#!/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 t'aides.

70
bavaza

Nous utilisons des tags 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 hachage git dans l'attribut AssemblyInformationalVersion du fichier AssemblyInfo.cs:

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

Une fois que vous avez compilé, vous pouvez voir la version à partir de Windows Explorer:

enter image description here

Vous pouvez également l'obtenir par programmation via:

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

où YOURTYPE est un type quelconque de l'assembly ayant l'attribut AssemblyInformationalVersion.

47
Handcraftsman

Vous pouvez incorporer un fichierversion.txtdans l'exécutable, puis lire le fichierversion.txtde l'exécutable. Pour créer le fichierversion.txt, utilisez git describe --long

Voici les étapes:

Utiliser un événement de construction pour appeler git

  • Cliquez avec le bouton droit sur le projet et sélectionnez Propriétés.

  • Dans Build Events, ajoutez un événement Pre-Build contenant (notez les guillemets):

    "C:\Program Files\Git\bin\git.exe" décrit --long> "$ (ProjectDir)\version.txt"

    Cela créera un fichierversion.txtdans le répertoire de votre projet.

Incorporer le fichier version.txt dans l'exécutable

  • Faites un clic droit sur le projet et sélectionnez Ajouter un élément existant
  • Ajouter le fichierversion.txt(modifier le filtre de sélection de fichier pour vous permettre de voir tous les fichiers)
  • Après avoir ajoutéversion.txt, cliquez dessus avec le bouton droit de la souris dans l'explorateur de solutions et sélectionnez Propriétés.
  • Modifier l'action de génération en ressource incorporée
  • Changer la copie dans le répertoire de sortie pour toujours copier
  • Ajoutez le fichierversion.txtà votre fichier.gitignore

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 incorporé:

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

Une autre façon de faire consiste à utiliser NetRevisionTool avec de la magie On-Board Visual Studio. Je vais présenter cela ici pour Visual Studio 2013 Professional Edition, mais cela fonctionnera également avec d'autres versions.

Commencez par télécharger NetRevisionTool . Vous devez inclure NetRevisionTool.exe dans votre PATH ou l’archiver dans votre référentiel et créer une action Visual Studio de pré-génération et post-génération et modifier 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 fichier AssemblyInfo.cs de votre projet, vous modifiez/ajoutez la ligne:

[Assembly: AssemblyInformationalVersion ("1.1. {Dmin: 2015}. {Chash: 6} {!} - {branche}")]

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

Après la construction, si vous cliquez avec le bouton droit sur votre binaire et accédez à la propriété, vous devriez voir quelque chose comme ce qui suit:

enter image description here

J'espère que cela aide quelqu'un là-bas

12
schmendrick

Je pense que cette question mérite de donner une réponse complète, étape par étape. La stratégie à suivre consiste à exécuter un script PowerShell à partir des événements de pré-génération, qui prend en charge un fichier de modèle et génère un fichier AssemblyInfo.cs avec les informations git tag + commit incluses.

Étape 1: créez un fichier AssemblyInfo_template.cs dans le dossier Project\Properties, basé sur votre AssemblyInfo.cs d'origine, mais contenant:

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

Étape 2: Créez un script PowerShell nommé InjectGitVersion.ps1 dont le 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 de pré-construction du projet

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

Étape 5: Construisez votre projet.

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

11
Atilio Jobson

Comme l'autre réponse mentionne déjà le bit git, une fois que vous avez le SHA, vous pouvez envisager de générer le fichier AssemblyInfo.cs de votre projet dans un hook de pré-construction.

Une façon de procéder consiste à créer un fichier modèle AssemblyInfo.cs.tmpl avec un espace réservé pour votre SHA dans, par exemple, $$ GITSHA $$, par exemple.

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

Votre crochet de pré-génération doit alors remplacer cet espace réservé et générer le fichier AssemblyInfo.cs pour que le compilateur C # le récupère. 

Pour voir comment cela peut être fait avec SubWCRev for SVN, voir cette réponse . Il ne devrait pas être difficile de faire quelque chose de similaire pour git.

D’autres manières seraient une "étape de création" comme mentionné, c’est-à-dire écrire une tâche MSBuild qui effectue quelque chose de similaire. Une autre solution consiste peut-être à post-traiter la DLL de façon ou d'autre (ildasm + ilasm say), mais je pense que les options mentionnées ci-dessus sont probablement les plus faciles.

3
Marcus

Pour une validation de méthode totalement automatisée et flexible https://github.com/Fody/Stamp . Nous l'avons utilisé avec succès pour nos projets Git (ainsi que this version pour les projets SVN)

2
mamuesstack

Une autre méthode consiste à générer un fichier Version.cs à partir d’une étape de pré-construction. J'ai exploré cela dans un petit projet de validation de principe qui imprime son hachage de validation actuel.

Le projet est chargé sur https://github.com/sashoalm/GitCommitHashPrinter .

Le code de lot qui crée le fichier Version.cs est le suivant:

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

J'utilise une combinaison de la réponse acceptée et d'une petite addition . J'ai l'extension e AutoT4 installée ( https://marketplace.visualstudio.com/items?itemName=BennorMcCarthy.AutoT4 ) exécutez les modèles avant de construire.

obtenir une version de GIT

J'ai git -C $(ProjectDir) describe --long --always > "$(ProjectDir)git_version.txt" dans mon événement de pré-génération dans les propriétés du projet . Ajouter git_version.txt et VersionInfo.cs à .gitignore est une bonne idée.

version intégrée dans les métadonnées

J'ai ajouté un modèle VersionInfo.tt à mon projet:

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

#>

Maintenant, j'ai mon tag + hash git dans "ProductVersion".

0
jelinek.01

En se référant à une autre réponse ( https://stackoverflow.com/a/44278482/4537127 ), j'ai également utilisé le modèle de texte VersionInfo.tt pour générer AssemblyInformationalVersion sans AutoT4.

(Atleast fonctionne dans mon application C # WPF)

Le problème était que les événements de pré-génération étaient exécutés après les transformations de modèles. Ainsi, après le clonage, le fichier git_version.txt n'était pas présent et la génération échouait. Après l'avoir créé manuellement pour permettre à la transformation de passer une fois, elle a été mise à jour après la transformation et était toujours one commit derrière.

J'ai dû apporter deux modifications au fichier .csproj (ceci s'applique au moins à Visual Studio Community 2017)

1) Importez les cibles de transformation de texte et créez des transformations de modèle pour chaque construction: (Ref 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>

et après <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

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

2) Exécutez le git describe avant les transformations de modèle (pour que git_version.txt soit présent lorsque VersionInfo.tt est transformé):

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

..Et le code C # pour obtenir la 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;
    }
}

Et ajouter les fichiers générés à .gitignore

VersionInfo.cs
git_version.txt
0
kimmoli

Vous pouvez utiliser un PowerShell One-Liner pour mettre à jour tous les fichiers Assemblyinfo avec le hash de commit.

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