Controle de versão automático no Visual Studio 2017 (.NET Core)

112

Passei a maior parte de algumas horas tentando encontrar uma maneira de incrementar automaticamente as versões em um .NETCoreApp 1.1 (Visual Studio 2017).

Eu sei que o AssemblyInfo.cs está sendo criado dinamicamente na pasta: obj/Debug/netcoreapp1.1/

Não aceita o antigo método de: [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.*")]

Se eu definir o projeto para o pacote, posso definir as versões lá, mas isso parece ser usado para construir o arquivo AssemblyInfo.cs.

Minha pergunta é, alguém descobriu como controlar a versão em projetos do .NET Core (ou .NETStandard para esse assunto).

Jason H
fonte
Não sei até onde você avançou com isso, mas parece que fiz quase a mesma pergunta de maneira diferente ( stackoverflow.com/a/43280282/685341 ) - Talvez a resposta aceita para essa pergunta o ajude; você pode simplesmente passar a /p:bandeira para dotnet msbuildem seu script de construção e definir versão, empresa, direitos autorais ... todas essas coisas boas.
Jay,
2
Obrigado pela informação. Isso apenas abre opções adicionais.
Jason H,
Anteriormente * tinha suporte para AssemblyVersion, não para AssemblyFileVersion- consulte Posso incrementar automaticamente a versão de compilação do arquivo ao usar o Visual Studio?
Michael Freidgeim
4
FWIW o curinga na versão do assembly não é suportado porque para esses novos projetos, o modo "determinístico" do compilador está ativo por padrão. Como o incremento automático quebraria o determinismo (mesma entrada> mesma saída), ele não é permitido nesse modo. Você pode definir <Deterministic>False</Deterministic>no csproj para usá-lo. (ou use qualquer outra lógica MSbuild para calcular <VersionPrefix>/ <Version>)
Martin Ullrich

Respostas:

23

Estou procurando um incrementador de versão para um aplicativo Net Core no VS2017 usando o formato de configuração csproj.

Encontrei um projeto chamado dotnet bump que funcionou para o formato project.json, mas teve dificuldade para encontrar uma solução para o formato .csproj. O escritor do dotnet bump realmente veio com a solução para o formato .csproj, que se chama MSBump.

Há um projeto no GitHub para isso em:

https://github.com/BalassaMarton/MSBump

onde você pode ver o código e também está disponível no Nuget. Basta pesquisar MSBump no Nuget.

ravetroll
fonte
1
Eu recomendo usar a versão 2.1.0 mais recente do MSBump. Ele oferece melhor suporte à troca de configurações e também define a versão para a compilação atual, não a próxima (como a versão anterior).
Márton Balassa
Vejo que agora também oferece suporte ao MSBuild, ao passo que antes exigia o Visual Studio.
ravetroll de
2
Sim, e também oferece suporte a projetos de segmentação múltipla.
Márton Balassa
4
Considere o uso de GitVersioning. Pode ser adequado para execução em seu ambiente de CI. github.com/AArnott/Nerdbank.GitVersioning
Henrique
1
O MSBump incrementa a versão em cada compilação, mesmo que você não tenha alterado nada, isso causa muitos problemas a longo prazo. E às vezes as versões ficam fora de sincronia e uma versão fica atrás da outra.
Konrad,
68

Adicionar <Deterministic>False</Deterministic> dentro de uma <PropertyGroup>seção de .csproj

A solução alternativa para fazer o AssemblyVersion * funcionar é descrita em “Mensagem de erro confusa para curinga em [AssemblyVersion] no .Net Core # 22660”

Os curingas são permitidos apenas se a construção não for determinística, que é o padrão para projetos .Net Core. Adicionar  <Deterministic>False</Deterministic> ao csproj corrige o problema.

As razões pelas quais os desenvolvedores .Net Core consideram as compilações determinísticas benéficas descritas em http://blog.paranoidcoding.com/2016/04/05/deterministic-builds-in-roslyn.html e os compiladores devem ser determinísticas: as mesmas entradas geram as mesmas saídas # 372

No entanto, se você estiver usando TeamCity, TFS ou outra ferramenta de CI / CD, é provavelmente melhor manter o número da versão controlado e incrementado por eles e passar a construir como um parâmetro (como foi sugerido em outras respostas), por exemplo

msbuild /t:build /p:Version=YourVersionNumber /p:AssemblyVersion=YourVersionNumber

Número do pacote para pacotes NuGet

msbuild /t:pack /p:Version=YourVersionNumber   
Michael Freidgeim
fonte
Obrigado! Eu sabia que havia uma alavanca escondida para abrir a sala do tesouro! Estou migrando um projeto antigo para o novo .NET SDK e realmente queria fazer isso rápido, sem o incômodo de encontrar soluções automatizadas de incremento de versão. Na verdade, quanto mais compatível com os métodos antigos, melhor para o meu caso.
Ivaylo Slavov
Esta é a melhor resposta da IMO. Isso permite que as ferramentas de construção funcionem corretamente. Pelo menos posso usar um mecanismo externo para alimentar o número na compilação agora.
Michael Yanni
Expanda sua resposta um pouco mais: a adição sugerida precisa ir para a seção <PropertyGroup> de .csproj. E obrigado por essa ótima resposta, claro!
GerardV
1
@gerardv, pronto, mas você pode melhorar as edições sozinho stackoverflow.com/help/editing
Michael Freidgeim
61

Se estiver usando o Visual Studio Team Services / TFS ou algum outro processo de construção de CI para ter controle de versão integrado, você pode utilizar o Conditionatributo msbuild , por exemplo:

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <Version Condition=" '$(BUILD_BUILDNUMBER)' == '' ">0.0.1-local</Version>
    <Version Condition=" '$(BUILD_BUILDNUMBER)' != '' ">$(BUILD_BUILDNUMBER)</Version>
    <TargetFramework>netcoreapp1.1</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <Folder Include="wwwroot\" />
  </ItemGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.0.0" />
    <PackageReference Include="Microsoft.AspNetCore" Version="1.1.2" />
    <PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="1.1.2" />
  </ItemGroup>

</Project>

Isso dirá ao compilador do .NET Core para usar o que quer que esteja na BUILD_BUILDNUMBERvariável de ambiente, se estiver presente, ou fallback para 0.0.1-localse você estiver fazendo uma compilação em sua máquina local.

joelsand
fonte
Legal, eu gosto dessa abordagem porque as variáveis ​​de ambiente podem apenas ser definidas no servidor de compilação enquanto essas condicionais determinam o conjunto de conjuntos nos binários.
jbooker de
Não parece funcionar no TFS 2010, mas esperamos que isso comece em breve!
Mark Adamson,
Não é uma solução ruim, embora possa ser um pouco trabalhosa se a solução tiver muitos projetos.
tofutim
Boa solução. Eu recebi uma exceção Build embora. Tive que mudar um pouco a configuração para consertar. stackoverflow.com/a/59858009/106227
Stu Harper
Isso funciona muito bem com .NET Core 2.1.2 e TFS2017U3
Dave Johnson
15

Eu vim com uma solução que funcionava quase da mesma forma que o antigo atributo AssemblyVersion com estrela (*) - AssemblyVersion ("1.0. ") *

Os valores para AssemblyVersion e AssemblyFileVersion estão no arquivo .csproj do projeto MSBuild (não em AssemblyInfo.cs ) como propriedade FileVersion (gera AssemblyFileVersionAttribute ) e AssemblyVersion (gera AssemblyVersionAttribute ). No processo MSBuild, usamos nossa tarefa MSBuild personalizada para gerar números de versão e, em seguida, substituímos os valores dessas propriedades FileVersion e AssemblyVersion por novos valores da tarefa.

Portanto, primeiro criamos nossa tarefa MSBuild personalizada GetCurrentBuildVersion :

public class GetCurrentBuildVersion : Task
{
    [Output]
    public string Version { get; set; }
 
    public string BaseVersion { get; set; }
 
    public override bool Execute()
    {
        var originalVersion = System.Version.Parse(this.BaseVersion ?? "1.0.0");
 
        this.Version = GetCurrentBuildVersionString(originalVersion);
 
        return true;
    }
 
    private static string GetCurrentBuildVersionString(Version baseVersion)
    {
        DateTime d = DateTime.Now;
        return new Version(baseVersion.Major, baseVersion.Minor,
            (DateTime.Today - new DateTime(2000, 1, 1)).Days,
            ((int)new TimeSpan(d.Hour, d.Minute, d.Second).TotalSeconds) / 2).ToString();
    }
}

Tarefa classe herde de Microsoft.Build.Utilities.Task classe de Microsoft.Build.Utilities.Core pacote NuGet. Ele recebe a propriedade BaseVersion (opcional) na entrada e retorna a versão gerada na propriedade de saída da Versão. A lógica para obter os números de versão é a mesma do controle de versão automático do .NET (o número da compilação é a contagem de dias desde 01/01/2000 e a revisão é de meio segundo desde a meia-noite).

Para construir esta tarefa MSBuild, usamos o tipo de projeto de biblioteca de classes .NET Standard 1.3 com esta classe.

O arquivo .csproj pode ter a seguinte aparência:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>netstandard1.3</TargetFramework>
    <AssemblyName>DC.Build.Tasks</AssemblyName>
    <RootNamespace>DC.Build.Tasks</RootNamespace>
    <PackageId>DC.Build.Tasks</PackageId>
    <AssemblyTitle>DC.Build.Tasks</AssemblyTitle>
  </PropertyGroup>
 
  <ItemGroup>
    <PackageReference Include="Microsoft.Build.Framework" Version="15.1.1012" />
    <PackageReference Include="Microsoft.Build.Utilities.Core" Version="15.1.1012" />
  </ItemGroup>
</Project>

Este projeto de tarefa também está disponível em meu GitHub holajan / DC.Build.Tasks

Agora configuramos o MSBuild para usar esta tarefa e definir FileVersion propriedades e AssemblyVersion . No arquivo .csproj, tem a seguinte aparência:

<Project Sdk="Microsoft.NET.Sdk">
  <UsingTask TaskName="GetCurrentBuildVersion" AssemblyFile="$(MSBuildThisFileFullPath)\..\..\DC.Build.Tasks.dll" />
 
  <PropertyGroup>
    ...
    <AssemblyVersion>1.0.0.0</AssemblyVersion>
    <FileVersion>1.0.0.0</FileVersion>
  </PropertyGroup>
 
  ...
 
  <Target Name="BeforeBuildActionsProject1" BeforeTargets="BeforeBuild">
    <GetCurrentBuildVersion BaseVersion="$(FileVersion)">
      <Output TaskParameter="Version" PropertyName="FileVersion" />
    </GetCurrentBuildVersion>
    <PropertyGroup>
      <AssemblyVersion>$(FileVersion)</AssemblyVersion>
    </PropertyGroup>
  </Target>
 
</Project>

Coisas importantes aqui:

  • UsingTask mencionado importa a tarefa GetCurrentBuildVersion de DC.Build.Tasks.dll . Ele presume que esse arquivo dll está localizado no diretório pai do arquivo .csproj.
  • Nosso BeforeBuildActionsProject1 Target que chama a tarefa deve ter um nome exclusivo por projeto, caso tenhamos mais projetos na solução que chama a tarefa GetCurrentBuildVersion.

A vantagem dessa solução é que ela funciona não apenas em compilações no servidor de compilação, mas também em compilações manuais de compilação dotnet ou Visual Studio.

HolaJan
fonte
4
Eu recomendaria usar em DateTime.UtcNowvez de DateTime.Nowno método GetCurrentBuildVersionString()em particular se o código for executado em máquinas de construção automatizadas. Eles podem funcionar às 2h ou 3h da manhã, quando o computador muda de / para o horário de verão. Com DateTime.Nownesse cenário que você pode estar indo para trás em termos de versão. Reconheço que este é um caso esquivo e também admito que sou exigente. :-) Além disso, o problema também desaparece se você configurar o mesmo fuso horário em todas as máquinas de construção e não ajustar para o horário de verão.
Manfred
Já existe um pacote NuGet para isso?
Jonathan Allen
@Jonathan Allen Não, não tenho planos para o pacote nuget, por causa do nome diferente em cada projeto. Você pode baixar compilado construção tarefa assemby em github.com/holajan/DC.Build.Tasks/tree/master/dist pasta
HolaJan
Estamos usando um aplicativo de console personalizado para extrair nossa versão de um servidor e gerar o arquivo AssemblyInfo.cs antes das compilações. Essa abordagem é perfeita para o que fazemos. Você conseguiu usar este método para enviar a versão em "Versão" do recurso de pacote dos novos projetos? Seria bom, mas acho que podemos voltar a usar o nuget.exe para empacotar também, pois precisaremos dele para publicar também.
David Ritchie
15

Você pode usar uma função de propriedade MSBuild para definir o sufixo da versão com base na data atual:

<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
  <VersionSuffix>pre$([System.DateTime]::UtcNow.ToString(yyyyMMdd-HHmm))</VersionSuffix>
</PropertyGroup>

Isso irá gerar um pacote com um nome como: PackageName.1.0.0-pre20180807-1711.nupkg .

Mais detalhes sobre as funções de propriedade do MSBuild: https://docs.microsoft.com/en-us/visualstudio/msbuild/property-functions

O Versioné formado pela combinação de VersionPrefixe VersionSuffix, ou se VersionSuffixestiver em branco, VersionPrefixapenas.

<PropertyGroup>
  <VersionPrefix>1.0.0</VersionPrefix>
</PropertyGroup>
Fabricio Godoy
fonte
Isso é realmente útil
Jerry Nixon
11

Aceitei a resposta acima porque @Gigi está correto (no momento), mas fiquei chateado e criei os scripts do PowerShell a seguir.

Primeiro, tenho o script na minha pasta de solução (UpdateBuildVersion.ps1):

#Get Path to csproj
$path = "$PSScriptRoot\src\ProjectFolder\ProjectName.csproj"

#Read csproj (XML)
$xml = [xml](Get-Content $path)

#Retrieve Version Nodes
$assemblyVersion = $xml.Project.PropertyGroup.AssemblyVersion
$fileVersion = $xml.Project.PropertyGroup.FileVersion

#Split the Version Numbers
$avMajor, $avMinor, $avBuild  = $assemblyVersion.Split(".")
$fvMajor, $fvMinor, $fvBuild = $fileVersion.Split(".")

#Increment Revision
$avBuild = [Convert]::ToInt32($avBuild,10)+1
$fvBuild = [Convert]::ToInt32($fvBuild,10)+1

#Put new version back into csproj (XML)
$xml.Project.PropertyGroup.AssemblyVersion = "$avMajor.$avMinor.$avBuild"
$xml.Project.PropertyGroup.FileVersion = "$fvMajor.$fvMinor.$fvBuild"

#Save csproj (XML)
$xml.Save($path)

Eu adicionei isso ao arquivo csproj:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <AssemblyVersion>0.0.1</AssemblyVersion>
    <FileVersion>0.0.1</FileVersion>
    <PreBuildEvent>powershell.exe NonInteractive ExecutionPolicy Unrestricted -command "& {$(SolutionDir)UpdateBuildVersion.ps1}"</PreBuildEvent>
  </PropertyGroup>
</Project>

Mesmo sendo definido como um PreBuildEvent, o fato é que os números da versão não são atualizados até DEPOIS que o arquivo foi carregado na memória, portanto, o número da versão não refletirá até a próxima compilação. Na verdade, você poderia alterá-lo para PostBuildEvent e teria o mesmo efeito.

Também criei os dois scripts a seguir: (UpdateMinorVersion.ps1)

#Get Path to csproj
$path = "$PSScriptRoot\src\ProjectFolder\ProjectName.csproj"

#Read csproj (XML)
$xml = [xml](Get-Content $path)

#Retrieve Version Nodes
$assemblyVersion = $xml.Project.PropertyGroup.AssemblyVersion
$fileVersion = $xml.Project.PropertyGroup.FileVersion

#Split the Version Numbers
$avMajor, $avMinor, $avBuild  = $assemblyVersion.Split(".")
$fvMajor, $fvMinor, $fvBuild = $fileVersion.Split(".")

#Increment Minor Version - Will reset all sub nodes
$avMinor = [Convert]::ToInt32($avMinor,10)+1
$fvMinor = [Convert]::ToInt32($fvMinor,10)+1
$avBuild = 0
$fvBuild = 0

#Put new version back into csproj (XML)
$xml.Project.PropertyGroup.AssemblyVersion = "$avMajor.$avMinor.$avBuild"
$xml.Project.PropertyGroup.FileVersion = "$fvMajor.$fvMinor.$fvBuild"

#Save csproj (XML)
$xml.Save($path)

(UpdateMajorVersion.ps1)

#Get Path to csproj
$path = "$PSScriptRoot\src\ProjectFolder\ProjectName.csproj"

#Read csproj (XML)
$xml = [xml](Get-Content $path)

#Retrieve Version Nodes
$assemblyVersion = $xml.Project.PropertyGroup.AssemblyVersion
$fileVersion = $xml.Project.PropertyGroup.FileVersion

#Split the Version Numbers
$avMajor, $avMinor, $avBuild  = $assemblyVersion.Split(".")
$fvMajor, $fvMinor, $fvBuild = $fileVersion.Split(".")

#Increment Major Version - Will reset all sub nodes
$avMajor = [Convert]::ToInt32($avMajor,10)+1
$fvMajor = [Convert]::ToInt32($fvMajor,10)+1
$avMinor = 0
$fvMinor = 0
$avBuild = 0
$fvBuild = 0

#Put new version back into csproj (XML)
$xml.Project.PropertyGroup.AssemblyVersion = "$avMajor.$avMinor.$avBuild"
$xml.Project.PropertyGroup.FileVersion = "$fvMajor.$fvMinor.$fvBuild"

#Save csproj (XML)
$xml.Save($path)
Jason H
fonte
10

dotnet build /p:AssemblyVersion=1.2.3.4

Eu estava respondendo a: "Alguém descobriu como controlar a versão em projetos do .NET Core (ou .NETStandard para esse assunto)." Eu encontrei essa pergunta tentando resolver esse problema no contexto de um build de CI. Eu queria definir a versão do assembly para o número de compilação do CI.

Chris McKenzie
fonte
1
O título diz "Controle de versão automático no Visual Studio 2017 (.NET Core)". Onde exatamente compilá-lo manualmente está em conformidade com o "Visual Studio 2017"?
JCKödel
4
Eu estava respondendo a: "Alguém descobriu como controlar a versão em projetos do .NET Core (ou .NETStandard para esse assunto)." Encontrei essa pergunta tentando resolver esse problema no contexto de um build de CI. Eu queria definir a versão do assembly para o número de compilação do CI. Lamento se você acha que isso não foi relevante para a questão em questão.
Chris McKenzie
É um componente útil para mim, obrigado. Vou usar isso como parte de uma solução de CI
Mark Adamson
1
@ChrisMcKenzie: seu comentário deve ser incluído em sua resposta para deixar sua intenção clara
Michael Freidgeim
** isso não funciona para mim em projetos netstandard quando assemblyinfo.cs não é especificado e a versão está no csproj ...
tofutim
9

Esses valores agora são definidos no .csprojarquivo:

<PropertyGroup>
    <TargetFramework>netcoreapp1.1</TargetFramework>
    <AssemblyVersion>1.0.6.0</AssemblyVersion>
    <FileVersion>1.0.6.0</FileVersion>
    <Version>1.0.1</Version>
</PropertyGroup>

Esses são os mesmos valores que você verá se for na guia Pacote nas configurações do projeto. Embora eu não ache que você possa usar o *incremento automático da versão, o que você pode fazer é introduzir uma etapa de pós-processamento que substitui as versões para você (por exemplo, como parte de sua integração contínua).

Gigi
fonte
6
Eu temia que essa fosse a resposta. Vou ver se consigo fazer uma etapa de pré-construção para incrementá-lo.
Jason H
3
Como apontado em outro tópico, o novo formato csproj permite que você desative a geração automática do arquivo assemblyinfo e especifique o seu próprio. Segui o conselho da resposta do natemcmaster aqui e usei um arquivo AssemblyInfo.cs padrão: stackoverflow.com/questions/42138418/…
James Eby
5
Por que eles removeram o incremento automático? Funcionou muito bem e de forma muito simples para mim durante anos. Eu empurro mestre, compilações de CI e incrementos, então a versão é lida diretamente da DLL construída usando algum script PS, então uso essa versão como um argumento ao enviar para NuGet. Tão simples. Agora quebrado.
Luke Puplett
1
@LukePuplett mesmo aqui. tão frustrante!
Shimmy Weitzhandler,
@LukePuplett: Consulte [“Mensagem de erro confusa para curinga em AssemblyVersion em .Net Core # 22660”] ( github.com/dotnet/roslyn/issues/22660 ), As razões pelas quais eles consideram Compilações Determinísticas benéficas descritas em blog.paranoidcoding.com / 2016/04/05 /… e os compiladores devem ser determinísticos: as mesmas entradas geram as mesmas saídas # 372 < github.com/dotnet/roslyn/issues/372 >
Michael Freidgeim
5

Fiz uma ferramenta CLI simples para definir strings de versão .csproj .NET Core aqui . Você pode combiná-lo com ferramentas como GitVersion para alteração automática de versão durante compilações de CI, se é isso que você procura.

Tagc
fonte
@JasonH Obrigado, deixe-me saber se você tiver qualquer problema com isso.
Tagc
maldito gênio. adoro!
pms1969
4

Para habilitar o controle de versão de seu projeto .Net Core / .Net Whatever com base em sua configuração GIT, usando a funcionalidade tags / describe do GIT.

Tenho usado um arquivo Prebuild.targets.xml que está localizado na pasta raiz do projeto e incluído no arquivo csproj como:

<Project Sdk="Microsoft.NET.Sdk">
  <Import Project="PreBuild.targets.xml" />
  ...
  <PropertyGroup>
    <GenerateAssemblyInfo>false</GenerateAssemblyInfo>

Use a tag "GenerateAssembyInfo" para desativar a geração automática de informações de montagem.

Em seguida, o Prebuild.targets.xml irá gerar um arquivo CommonAssemblyInfo.cs onde você pode incluir as marcas de versão que deseja com base em sua versão GIT

NOTA: Eu encontrei o Prebuilds.targets.xml em outro lugar, então não me preocupei em limpá-lo.)

O arquivo Prebuild.targets.xml:

    <?xml version="1.0" encoding="utf-8" ?>
    <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

      <UsingTask
        TaskName="GetVersion"
        TaskFactory="CodeTaskFactory"
        AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll" >
        <ParameterGroup>
          <VersionString ParameterType="System.String" Required="true" />
          <Version ParameterType="System.String" Output="true" />
          <Commit ParameterType="System.String" Output="true" />
          <VersionSuffix ParameterType="System.String" Output="true" />
        </ParameterGroup>
        <Task>
          <!--<Reference Include="" />-->
          <Using Namespace="System"/>
          <Using Namespace="System.IO"/>
          <Using Namespace="System.Text.RegularExpressions" />
          <Code Type="Fragment" Language="cs">
            <![CDATA[
              var match = Regex.Match(VersionString, @"^(?<major>\d+)\.(?<minor>\d+)(\.?(?<patch>\d+))?-(?<revision>\d+)-(?<commit>[a-z0-9-]+)$");
              int major, minor, patch, revision;
              Int32.TryParse(match.Groups["major"].Value, out major);
              Int32.TryParse(match.Groups["minor"].Value, out minor);
              Int32.TryParse(match.Groups["patch"].Value, out patch);
              Int32.TryParse(match.Groups["revision"].Value, out revision);
              _Version = new Version(major, minor, patch, revision).ToString();
              _Commit = match.Groups["commit"].Value;
            ]]>
          </Code>
        </Task>
      </UsingTask>

      <UsingTask
        TaskName="GitExistsInPath"
        TaskFactory="CodeTaskFactory"
        AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll" >
        <ParameterGroup>
          <Exists ParameterType="System.Boolean" Output="true" />
        </ParameterGroup>
        <Task>
          <!--<Reference Include="" />-->
          <Using Namespace="System"/>
          <Using Namespace="System.IO"/>
          <Using Namespace="System.Text.RegularExpressions" />
          <Code Type="Fragment" Language="cs">
            <![CDATA[
            var values = Environment.GetEnvironmentVariable("PATH");
            foreach (var path in values.Split(';')) {
                var exeFullPath = Path.Combine(path, "git.exe");
                if (File.Exists(exeFullPath)) {
                    Exists = true;
                    return true;
                }
                var cmdFullPath = Path.Combine(path, "git.cmd");
                if (File.Exists(cmdFullPath)) {
                    Exists = true;
                    return true;
            }
            }
            Exists = false;
            ]]>
          </Code>
        </Task>
      </UsingTask>

      <Target Name="CreateCommonVersionInfo" BeforeTargets="CoreCompile">
        <Message Importance="high" Text="CreateCommonVersionInfo" />

        <GitExistsInPath>
          <Output TaskParameter="Exists" PropertyName="GitExists"/>
        </GitExistsInPath>
        <Message Importance="High" Text="git not found!" Condition="!$(GitExists)"/>

        <Exec Command="git describe --tags --long --dirty > $(ProjectDir)version.txt" Outputs="$(ProjectDir)version.txt" WorkingDirectory="$(SolutionDir)" IgnoreExitCode="true" Condition="$(GitExists)">
          <Output TaskParameter="ExitCode" PropertyName="ExitCode" />
        </Exec>
        <Message Importance="high" Text="Calling git failed with exit code $(ExitCode)" Condition="$(GitExists) And '$(ExitCode)'!='0'" />

        <ReadLinesFromFile File="$(ProjectDir)version.txt" Condition="$(GitExists) And '$(ExitCode)'=='0'">
          <Output TaskParameter="Lines" ItemName="OutputLines"/>
        </ReadLinesFromFile>
        <Message Importance="High" Text="Tags: @(OutputLines)" Condition="$(GitExists) And '$(ExitCode)'=='0'"/>

        <Delete Condition="Exists('$(ProjectDir)version.txt')" Files="$(ProjectDir)version.txt"/>

        <GetVersion VersionString="@(OutputLines)" Condition="$(GitExists) And '$(ExitCode)'=='0'">
          <Output TaskParameter="Version" PropertyName="VersionString"/>
          <Output TaskParameter="Commit" PropertyName="Commit"/>
        </GetVersion>

        <PropertyGroup>
          <VersionString Condition="'$(VersionString)'==''">0.0.0.0</VersionString>
        </PropertyGroup>

        <Message Importance="High" Text="Creating CommonVersionInfo.cs with version $(VersionString) $(Commit)" />

        <WriteLinesToFile Overwrite="true" File="$(ProjectDir)CommonAssemblyInfo.cs" Encoding="UTF-8" Lines='using System.Reflection%3B

    // full version: $(VersionString)-$(Commit)

    [assembly: AssemblyVersion("$(VersionString)")]
    [assembly: AssemblyInformationalVersion("$(VersionString)")] 
    [assembly: AssemblyFileVersion("$(VersionString)")]' />

      </Target>
    </Project>

EDITAR: Se você estiver construindo usando o MSBUILD o

 $(SolutionDir)

Pode causar problemas, use

 $(ProjectDir)

em vez de

Tue Skeltved
fonte
Agradável! O VersionSuffix acaba sendo configurado ou usado? Não parece ser
Mark Adamson,
4

Você pode fazer o seguinte, dentro do arquivo csproj. Eu não descobri a matemática. Eu descobri isso em outro lugar no stackoverflow. Mas isso funciona e lhe dará algo semelhante a 1.0. * Para a versão.

<PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
    <FileVersion>1.0.$([System.DateTime]::UtcNow.Date.Subtract($([System.DateTime]::Parse("2000-01-01"))).TotalDays).$([System.Math]::Floor($([MSBuild]::Divide($([System.DateTime]::UtcNow.TimeOfDay.TotalSeconds), 1.32))))</FileVersion>
    <Version>1.0.$([System.DateTime]::UtcNow.Date.Subtract($([System.DateTime]::Parse("2000-01-01"))).TotalDays)</Version>
</PropertyGroup>
Clarke76
fonte
3

A extensão de versões automáticas para Visual Studio agora oferece suporte ao autoincremento .Net Core e .Net Standard em uma interface de usuário simples.

https://marketplace.visualstudio.com/items?itemName=PrecisionInfinity.AutomaticVersions

madamissão
fonte
1
Fiz um teste rápido com solução demo (aplicativo windows) e funciona, também com projeto padrão .net. Foi um teste rápido então temos que mergulhar mais fundo para verificar se faz tudo o que queremos. Mas com certeza você poderia tentar este.
ArieKanarie
2

Podemos usar parâmetros especiais para dotnet publish -- version-suffix 1.2.3

Para a versão do arquivo:

<AssemblyVersion Condition=" '$(VersionSuffix)' == '' ">0.0.1.0</AssemblyVersion>
<AssemblyVersion Condition=" '$(VersionSuffix)' != '' ">$(VersionSuffix)</AssemblyVersion>

Para a versão:

<Version Condition=" '$(VersionSuffix)' == '' ">0.0.1</Version>
<Version Condition=" '$(VersionSuffix)' != '' ">$(VersionSuffix)</Version>

https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-publish?tabs=netcore21

--version-suffix <VERSION_SUFFIX>     Defines the value for the $(VersionSuffix) property in the project.
Anatoli Klamer
fonte
2

Obrigado a @joelsand por me apontar na direção certa.

Tive que mudar sua resposta ligeiramente, pois quando o DevOps Build foi executado, recebi a seguinte exceção

The specified version string does not conform to the recommended format - major.minor.build.revision

Tive que adicionar $ (BUILD_BUILDNUMBER) no final da seção major.minor.build. Para eliminar a duplicação da versão real, também uso um prefixo de versão:

<PropertyGroup>
    <VersionPrefix>1.0.3</VersionPrefix>
    <Version Condition=" '$(BUILD_BUILDNUMBER)' == '' ">$(VersionPrefix)-local</Version>
    <Version Condition=" '$(BUILD_BUILDNUMBER)' != '' ">$(VersionPrefix)-$(BUILD_BUILDNUMBER)</Version>
</PropertyGroup>
Stu Harper
fonte
Eu tive exatamente o mesmo problema e sua resposta o corrigiu. Obrigado.
Participante da reunião
1

Acho que esta resposta de @joelsand é a resposta correta para definir o número da versão para dotnet core rodando em VSTS

Para adicionar mais informações para esta resposta,

BUILD_BUILDNUMBERé na verdade uma variável predefinida .

Acontece que existem 2 versões de variáveis ​​predefinidas.

Um é build.xxxx, o outro é BUILD_XXXX.

Você só pode usar Environment Variable Nameem cproj.

maxisam
fonte
Não é build.xxxxusado no front end para fazer referência em um pipeline e BUILD_XXXXtem o mesmo valor, mas com sintaxe ligeiramente modificada necessária para fazer referência à variável no PS?
dst3p de