Incorporar hash git commit em uma dll .Net

102

Estou construindo um aplicativo C #, usando Git como meu controle de versão.

Existe uma maneira de incorporar automaticamente o último hash de confirmação no executável quando eu construo meu aplicativo?

Por exemplo, imprimir o hash de confirmação no console seria algo como:

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

Observe que isso deve ser feito em tempo de compilação , não em tempo de execução , pois meu executável implantado não terá o repositório git acessível.

Uma questão relacionada ao C ++ pode ser encontrada aqui .

EDITAR

Por solicitação de @mattanja, estou postando o script git hook que uso em meus projetos. A configuração:

  • Os ganchos são scripts de shell do Linux, que são colocados em: path_to_project \ .git \ hooks
  • Se você estiver usando msysgit , a pasta de ganchos já contém alguns scripts de amostra. Para fazer o git chamá-los, remova a extensão '.sample' do nome do script.
  • Os nomes dos scripts de gancho correspondem ao evento que os invoca. No meu caso, eu modifiquei post-commit e post-merge .
  • Meu arquivo AssemblyInfo.cs está diretamente no caminho do projeto (mesmo nível da pasta .git ). Ele contém 23 linhas e uso git para gerar a 24ª.

Como meu linux está um pouco enferrujado, o script simplesmente lê as primeiras 23 linhas de AssemblyInfo.cs em um arquivo temporário, ecoa o hash git para a última linha e renomeia o arquivo de volta para AssemblyInfo.cs . Tenho certeza de que existem maneiras melhores de fazer isso:

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

Espero que isto ajude.

bavaza
fonte

Respostas:

63

Usamos tags no git para rastrear versões.

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

Você pode obter a versão com hash do git via:

git describe --long

Nosso processo de criação coloca o hash git no atributo AssemblyInformationalVersion do arquivo AssemblyInfo.cs:

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

Depois de compilar, você pode ver a versão no Windows Explorer:

insira a descrição da imagem aqui

Você também pode obtê-lo programaticamente por meio de:

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

onde YOURTYPE é qualquer tipo no Assembly que possui o atributo AssemblyInformationalVersion.

Artesão
fonte
14
Olá, queria perguntar há um mês, mas não tive representantes suficientes para comentar. Quando você diz: "Nosso processo de construção coloca o hash git no atributo AssemblyInformationalVersion do AssemblyInfo.cs", o que exatamente está acontecendo lá? Você está apenas fazendo um build de estúdio visual ou está usando algo como NAnt ou alguma outra ferramenta?
João Jesus
3
Usamos ruby ​​(rake) para automatizar nossa construção. Uma de nossas tarefas de construção de rake atualiza o arquivo CommonAssemblyInfo.cs que é usado em todos os projetos da solução. A tarefa gera o arquivo CommonAssemblyInfo.cs usando albacore - github.com/derickbailey/Albacore Um dos valores AssemblyInfo que define a tarefa é o AssemblyInformationalVersion.
Artesão
3
@John Jesus - como Lazy Badger sugeriu, você também pode usar git hooks para alterar AssemblyInfo.cs após commit / merge etc (foi isso que acabei fazendo). Consulte kernel.org/pub/software/scm/git/docs/githooks.html
bavaza
Apenas para sua informação, Albacore mudou para uma nova organização de hub: github.com/Albacore/albacore
kornman00
5
A seguir o projeto https://github.com/jeromerg/NGitVersion oferece uma solução completa para gerar GlobalAssemblyInfo.*arquivos em tempo de compilação para projetos C # e C ++: Por padrão, a versão do assembly gerada contém: o hash de confirmação, um sinalizador que sinaliza as alterações locais e um incremento contando a quantidade de commit da raiz do repositório até o commit atual.
jeromerg
77

Você pode incorporar um arquivo version.txt ao executável e então ler o version.txt do executável. Para criar o arquivo version.txt , usegit describe --long

Aqui estão as etapas:

Use um Build Event para chamar git

  • Clique com o botão direito no projeto e selecione Propriedades

  • Em Build Events, adicione o evento Pre-Build contendo (observe as aspas):

    "C: \ Arquivos de programas \ Git \ bin \ git.exe" describe --long> "$ (ProjectDir) \ version.txt"

    Isso criará um arquivo version.txt no diretório do projeto.

Incorpore o version.txt no executável

  • Clique com o botão direito no projeto e selecione Adicionar Item Existente
  • Adicione o arquivo version.txt (altere o filtro de seleção de arquivo para permitir que você veja todos os arquivos)
  • Após a adição de version.txt , clique com o botão direito do mouse no Solution Explorer e selecione Propriedades
  • Altere a ação de construção para recurso incorporado
  • Alterar Copiar para Diretório de Saída para Copiar Sempre
  • Adicione version.txt ao seu arquivo .gitignore

Leia a string de versão do arquivo de texto incorporado

Aqui está um exemplo de código para ler a string de versão do arquivo de texto incorporado:

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();
        }
    }
}
Joao jesus
fonte
9
Essa abordagem funciona razoavelmente bem. Eu usei "git rev-parse --short HEAD", no entanto.
Brian Reiter,
3
Ah bom. Usei "git describe" porque é realmente interessante (para mim) quando você tem uma tag; a informação da versão tem a tag mais o número de commits depois que a tag foi aplicada; nunca vi algo como em um SCM antes.
João Jesus de
7
Eu uso git describe --dirty, que adiciona um sinalizador quando os desenvolvedores estão trabalhando com uma árvore de trabalho suja.
paulmelnikow
2
@ TamásSzelei o namespace do projeto é TryGitDescribe. Depois que o arquivo version.txt é incorporado ao artefato executável / assembly, você precisa preceder o namespace para retirá-lo.
João Jesus,
2
Obrigado pela solução completa. No meu caso costumava GetEntryAssemblyfazer montagem. Em qualquer caso, você pode ligar GetName().Namepara evitar a codificação do nome.
astrowalker
51

ATUALIZAR:

As coisas evoluíram desde que originalmente respondi a esta pergunta. O Microsoft.NET.Sdk(o que significa que você deve usar um projeto no estilo sdk) agora inclui suporte para adicionar o hash de confirmação tanto à versão informativa do assembly quanto aos metadados do pacote nuget, se algumas condições forem atendidas:

  1. A <SourceRevisionId>propriedade deve ser definida. Isso pode ser feito adicionando um alvo como este:
<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>

Este destino executa um comando que será definido SourceRevisionIdcomo o hash abreviado (8 caracteres). O BeforeTargets faz com que isso seja executado antes que a versão informativa do assembly seja criada.

  1. Para incluir o hash nos metadados do pacote nuget, o <RepositoryUrl>também deve ser definido.

  2. <SourceControlInformationFeatureSupported>deve ser true, isso faz com que a tarefa do pacote nuget pegue o SourceRevisionId também.

Eu evitaria que as pessoas usassem o pacote MSBuildGitHash, já que essa nova técnica é mais limpa e consistente.

ORIGINAL:

Eu criei um pacote nuget simples que você pode incluir em seu projeto que cuidará disso para você: https://www.nuget.org/packages/MSBuildGitHash/

Este pacote nuget implementa uma solução MSBuild "pura". Se você preferir não depender de um pacote nuget, pode simplesmente copiar esses alvos em seu arquivo csproj e ele deve incluir o hash git como um atributo de assembly personalizado:

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

Existem dois alvos aqui. O primeiro, "GetGitHash", carrega o hash git em uma propriedade MSBuild chamada BuildHash, ele faz isso se BuildHash ainda não estiver definido. Isso permite que você passe para o MSBuild na linha de comando, se preferir. Você poderia passá-lo para o MSBuild assim:

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

O segundo destino, "WriteGitHash", gravará o valor hash em um arquivo na pasta temporária "obj" chamada "CustomAssemblyInfo.cs". Este arquivo conterá uma linha semelhante a:

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

Este arquivo CustomAssemblyInfo.cs será compilado em seu assembly, para que você possa usar a reflexão para procurar o AssemblyMetadatatempo de execução. O código a seguir mostra como isso pode ser feito quando a AssemblyInfoclasse está incluída no mesmo assembly.

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

Alguns benefícios deste design é que ele não toca em nenhum arquivo na pasta do projeto, todos os arquivos modificados estão na pasta "obj". Seu projeto também será construído de forma idêntica no Visual Studio ou na linha de comando. Ele também pode ser facilmente personalizado para o seu projeto e terá o código-fonte controlado junto com o arquivo csproj.

MarkPflug
fonte
2
Funcionou perfeitamente. Instalei o pacote nuget e consegui retirar o hash git usando e Assembly.GetExecutingAssembly(), em seguida, examinando o assembly CustomAttributes .
Gavin H
1
Se essa fosse minha pergunta, eu teria aceito a resposta. Coisas boas.
Drew Noakes em
1
@GavinH, como você conseguiu o GitHash? Eu posso ver que esse valor existe, mas existe algum método puro para obter o atributo personalizado por nome? Parece que tenho que escrever uma longa consulta where-select CustomAttributes, obrigado.
Okan Kocyigit
1
@ocanal sim - infelizmente não consegui encontrar uma maneira mais limpa de fazer isso do que lendo o CustomAttributes. Por exemplo, aqui está a função que uso para extrair a string hash: pastebin.com/nVKGLhJC
Gavin H
2
@danmiser Não tenho ideia do que seja "UseMerge / SingleAssemblyName", então não posso ajudá-lo. Crie um problema em github.com/MarkPflug/MSBuildGitHash e posso dar uma olhada nele (não é uma promessa).
MarkPflug
14

Outra maneira de fazer isso é usar o NetRevisionTool com alguma mágica do Visual Studio integrado . Vou mostrar isso aqui para o Visual Studio 2013 Professional Edition, mas também funcionará com outras versões.

Portanto, primeiro baixe o NetRevisionTool. Você inclui o NetRevisionTool.exe em seu PATH ou faz o check-in em seu repositório e cria uma ação de pré-construção e pós-construção do Visual Studio e altera seu AssemblyInfo.cs.

Um exemplo que adicionaria seu git-hash à sua AssemblyInformationVersion seria o seguinte: Nas configurações do projeto:

insira a descrição da imagem aqui

no AssemblyInfo.cs do seu projeto, você altera / adiciona a linha:

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

na imagem mostrada, verifiquei no NetRevisionTool.exe na pasta External / bin

Após a compilação, se você clicar com o botão direito do mouse no binário e for para as propriedades, verá algo como o seguinte:

insira a descrição da imagem aqui

Espero que isso ajude alguém lá fora

Schmendrick
fonte
O hash de commit para mim sempre termina em 00000. Eu pensei que era porque eu tinha alterações não confirmadas, mas ainda o mesmo. Alguma ideia do porquê?
Viktor
3
O problema era que a NetRevision não estava encontrando meu executável git. A razão é porque estamos usando SourceTree e git vem embutido com ele. A solução foi copiar git.exe e libiconv-2.dll de% USERPROFILE% \ AppData \ Local \ Atlassian \ SourceTree \ git_local \ bin para a pasta que contém NetRevision.exe. Também tive que modificar os eventos como: Evento de pré-construção: cd $ (ProjectDir) Bibliotecas NetRevisionTool.exe / patch $ (ProjectDir) Evento de pós-construção: cd $ (ProjectDir) Bibliotecas NetRevisionTool.exe / restore $ (ProjectDir)
Viktor
Apenas para referência futura, o URL do repositório do projeto mudou há algum tempo para github.com/ygoe/NetRevisionTool . Mais informações também estão disponíveis em unclassified.software/apps/netrevisiontool .
ygoe
14

Acho que vale a pena dar uma resposta completa passo a passo para essa pergunta. A estratégia aqui é executar um script do PowerShell a partir dos eventos de pré-compilação que leva em um arquivo de modelo e gera um arquivo AssemblyInfo.cs com a tag git + informações de contagem de confirmação incluídas.

Etapa 1: crie um arquivo AssemblyInfo_template.cs na pasta Project \ Properties, com base em seu AssemblyInfo.cs original, mas contendo:

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

Etapa 2: crie um script PowerShell denominado InjectGitVersion.ps1, cuja fonte é:

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

Etapa 3: salve o arquivo InjectGitVersion.ps1 no diretório da solução em uma pasta BuildScripts

Etapa 4: adicione a seguinte linha aos eventos de pré-construção do projeto

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

Etapa 5: Construa seu projeto.

Etapa 6: opcionalmente, adicione AssemblyInfo.cs ao seu arquivo git ignore

Atilio Jobson
fonte
E lembre-se de tornar suas tags git compatíveis com versões de arquivo: como 1.2.3. Se você tiver tags mais complicadas, terá que analisar apenas as partes compatíveis
Atílio Jobson,
2
Em vez de usar um template e gitignoring real, AssemblyInfo.cspode-se modificar AssemblyInfo.csno local, construir e então fazer git reset AssemblyInfo.cspara a última versão confirmada. Então no repo sempre haveria AssemblyInfo.cs, com $..$substituído apenas pelo tempo de construção.
Kuba Wyrostek
Isso funcionou muito bem. Acabei usando git describe --match "v[0-9]*" --long --always --dirtypara filtrar por certas tags (aquelas que contêm um número de versão) e para indicar se a árvore de trabalho estava limpa.
packoman de
Você também deve modificar seu RegEx no script PS:$gitVersion -match '[v](.*)-(\d+)-[g](.+)$';
packoman
4

Agora é muito fácil com a Tarefa de revisão do .NET para MSBuild e trabalhar com o Visual Studio 2019.

Basta instalar o pacote NuGet Unclassified.NetRevisionTask e configurar as informações desejadas no AssemblyInfo.csarquivo conforme descrito na documentação do GitHub .

Se você quiser apenas o hash do último commit (comprimento = 8):

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

Construa seu projeto / solução e você terá algo assim:

insira a descrição da imagem aqui

Krlzlx
fonte
Para configurar o formato em um aplicativo NET.core, adicione o PropertyGroupao arquivo .csproj como visto no README github.com/ygoe/NetRevisionTask/blob/master/README.md
sc911
3

Como a outra resposta já menciona o git bit, uma vez que você tenha o SHA, você pode considerar a geração do AssemblyInfo.csarquivo do seu projeto em um gancho de pré-construção.

Uma maneira de fazer isso é criar um AssemblyInfo.cs.tmplarquivo de modelo, com um espaço reservado para seu SHA, digamos $$ GITSHA $$, por exemplo

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

Seu gancho de pré-compilação deve então substituir esse espaço reservado e gerar o arquivo AssemblyInfo.cs para o compilador C # selecionar.

Para ver como isso pode ser feito usando SubWCRev para SVN, consulte esta resposta . Não deve ser difícil fazer algo semelhante para o git.

Outras formas seriam um "estágio de criação" conforme mencionado, ou seja, escrever uma tarefa MSBuild que faça algo semelhante. Ainda outra maneira pode ser postar o processo de alguma forma (digamos ildasm + ilasm), mas acho que as opções mencionadas acima são provavelmente as mais fáceis.

Marcus
fonte
@Wint não, não adicione o AssemblyInfo.cs gerado ao git. Se você fizer isso, será impossível fazer uma compilação não suja: P
brincadeira de
3

Para um método totalmente automatizado e flexível, verifique https://github.com/Fody/Stamp . Nós usamos isso com sucesso para nossos projetos Git (bem como esta versão para projetos SVN)

Atualização: desatualizado, pois Stamp.Fody não é mais mantido

mamuesstack
fonte
1
na página github do Stamp.Fody diz: "Este projeto não é mais mantido.". Incluí-lo no meu projeto levantou um CA0052 e CA0055
sc911
2

Você pode usar um powerhell one-liner para atualizar todos os arquivos assemblyinfo com o hash de confirmação.

$hash = git describe --long --always;gci **/AssemblyInfo.* -recurse | foreach { $content = (gc $_) -replace "\[assembly: Guid?.*", "$&`n[assembly: AssemblyMetadata(`"commithash`", `"$hash`")]" | sc $_ }
roh85
fonte
1
  1. Espero que você saiba como chamar programas externos e interceptar a saída no momento da construção.
  2. Espero que você saiba como fazer com que o diretório de trabalho do git ignore os arquivos não versionados.

Conforme observado por @ learath2, a saída de git rev-parse HEADfornecerá um hash simples.

Se você usar tags no repositório Git (e usar tags, não é mais descritivo e legível do que git rev-parse), a saída pode ser recebida de git describe(embora também seja usada com sucesso posteriormente em git checkout)

Você pode chamar rev-parse | describe em:

  • alguns fazem palco
  • no gancho post-commit
  • no filtro de borrar, se você selecionar a forma de implementação dos filtros de borrar / limpar
Texugo Preguiçoso
fonte
0

Estou usando uma combinação da resposta aceita e uma pequena adição. Eu tenho a extensão AutoT4 instalada ( https://marketplace.visualstudio.com/items?itemName=BennorMcCarthy.AutoT4 ) para executar novamente os modelos antes de construir.

obtendo versão do GIT

Tenho git -C $(ProjectDir) describe --long --always > "$(ProjectDir)git_version.txt"no meu evento de pré-construção nas propriedades do projeto. Adicionar git_version.txt e VersionInfo.cs a .gitignore é uma boa ideia.

incorporando versão em metadados

Eu adicionei um VersionInfo.ttmodelo ao meu projeto:

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

#>

Agora eu tenho minha tag git + hash em "ProductVersion".

jelinek.01
fonte
0

Referindo-me à outra resposta ( https://stackoverflow.com/a/44278482/4537127 ), também usei o VersionInfo.ttmodelo de texto para gerar AssemblyInformationalVersionsem AutoT4.

(Pelo menos funciona em meu aplicativo C # WPF)

O problema era que os eventos de pré-construção foram executados após as transformações do modelo, portanto, após a clonagem, o git_version.txtarquivo não estava lá e a construção falhou. Depois de criá-lo manualmente para permitir que a transformação passasse uma vez, ele foi atualizado após a transformação e sempre foi um commit por trás .

Tive que fazer dois ajustes no arquivo .csproj (isso se aplica pelo menos para Visual Studio Community 2017)

1) Importe os Text Transformation Targets e faça transformações de modelo para executar em cada compilação: (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>

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

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

2) Faça a git describeexecução antes das transformações do modelo (para que git_version.txtesteja lá quando VersionInfo.ttfor transformado):

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

..E o código C # para obter o 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;
    }
}

..E adicionar os arquivos gerados a .gitignore

VersionInfo.cs
git_version.txt
Kimmoli
fonte
0

Outra maneira seria gerar um arquivo Version.cs a partir de uma etapa de pré-construção. Eu explorei isso em um pequeno projeto de prova de conceito que imprime seu hash de commit atual.

O projeto está carregado em https://github.com/sashoalm/GitCommitHashPrinter .

O código de lote que cria o arquivo Version.cs é este:

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

Lugar, colocar

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

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