Control automático de versiones en Visual Studio 2017 (. NET Core)


He pasado la mayor parte de unas pocas horas tratando de encontrar una manera de auto-incrementar las versiones en una .NETCoreApp 1.1 (Visual Studio 2017).

Conozco el AssemblyInfo.cs se crea dinámicamente en la carpeta: obj/Debug/netcoreapp1.1/

No acepta el antiguo método de: [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.*")]

Si establezco el proyecto en paquete puedo establecer versiones allí, pero esto parece ser utilizado para construir el AssemblyInfo.archivo CS.

Mi pregunta es, ¿alguien ha descubierto cómo controlar la versión en . NET Core (or .NETStandard para el caso) proyectos.

Author: Jason H, 2017-03-25

13 answers

He estado buscando un incrementador de versión para una aplicación Net Core en VS2017 utilizando el formato de configuración csproj.

Encontré un proyecto llamado dotnet bump que funcionó para el proyecto.formato json, pero tuvo problemas para encontrar una solución para el .formato csproj. El escritor el dotnet bump realmente se le ocurrió la solución para el .formato csproj y se llama MSBump.

Hay un proyecto en GitHub para ello at:

Https://github.com/BalassaMarton/MSBump

Donde se puede ver el código y su disponible en Nuget también. Solo busca MSBump en Nuget.

 12
Author: ravetroll,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-08 13:00:31

Si está utilizando Visual Studio Team Services / TFS o algún otro proceso de compilación de CI para tener incorporado el control de versiones, puede utilizar el atributo Condition de msbuild, por ejemplo:

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

Esto le dirá al compilador de.NET Core que use lo que esté en la variable de entorno BUILD_BUILDNUMBER si está presente, o que use 0.0.1-local si está haciendo una compilación en su máquina local.

 31
Author: joelsand,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-17 15:06:30

Añadir <Deterministic>False</Deterministic> dentro de una sección <PropertyGroup> de .csproj

La solución para hacer que AssemblyVersion * funcione se describe en "Mensaje de error confuso para comodín en [AssemblyVersion] en. Net Core #22660"

Los comodines solo se permiten si la compilación no es determinista, lo que es el valor predeterminado para los proyectos.Net Core. Agregar <Deterministic>False</Deterministic> a csproj soluciona la cuestión.

Las razones por las que los Desarrolladores de. Net Core consideran Compilaciones Deterministas beneficioso descrito en http://blog.paranoidcoding.com/2016/04/05/deterministic-builds-in-roslyn.html y Los compiladores deben ser deterministas: las mismas entradas generan las mismas salidas #372

Sin embargo, si está utilizando TeamCity, TFS u otra herramienta CI/CD, probablemente sea mejor mantener el número de versión controlado e incrementado por ellos y pasar a build como parámetro (como se sugirió en otras respuestas) , por ejemplo,

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

Número de paquete para NuGet paquetes

msbuild /t:pack /p:Version=YourVersionNumber   
 26
Author: Michael Freidgeim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-09 21:48:25

Se me ocurrió una solución que funcionaba casi igual que el viejo atributo AssemblyVersioncon star (*) - AssemblyVersion("1.0.")*

Los valores para AssemblyVersiony AssemblyFileVersion están en MSBuild project .archivo csproj (no en AssemblyInfo.cs) como propiedad FileVersion (genera AssemblyFileVersionAttribute) y AssemblyVersion (genera AssemblyVersionAttribute). En el proceso de MSBuild usamos nuestra tarea personalizada de MSBuild para generar números de versión y luego sobrescribimos los valores de estas propiedades FileVersion y AssemblyVersion con nuevos valores de task.

Así que primero creamos nuestra tarea personalizada de MSBuild 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();
    }
}

La clase de tarea hereda de Microsoft.Construir.Utilidad.Tarea clase de Microsoft.Construir.Utilidad.Core Paquete NuGet. Toma la propiedad BaseVersion (opcional) en la entrada y devuelve generado versión en la propiedad de salida de versión. La lógica para obtener los números de versión es la misma que el control de versiones automático de. NET (el número de compilación es el número de días desde el 1/1/2000 y la revisión es de medio segundo desde la medianoche).

Para construir esta tarea de MSBuild, usamos . NET Standard 1.3 class library tipo de proyecto con esta clase.

.el archivo csproj puede tener este aspecto:

<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 proyecto de tarea también está disponible en mi GitHub holajan / DC.Construir.Tareas

Ahora configuramos MSBuild para usar esta tarea y establecer las propiedades FileVersion y AssemblyVersion . En .archivo csproj se ve así:

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

Cosas importantes aquí:

  • Mencionado Usando Taskimporta la tarea GetCurrentBuildVersion desde DC.Construir.Tarea.dll . Se asume que este archivo dll se encuentra en el directorio padre de su .archivo csproj.
  • Nuestro destino BeforeBuildActionsProject1 que llama a la tarea debe tener un nombre único por proyecto en caso de que tengamos más proyectos en la solución que llame a la tarea GetCurrentBuildVersion.

La ventaja de esta solución es que no solo funciona a partir de compilaciones en build server, sino también en compilaciones manuales desde dotnet build o Visual Studio.

 12
Author: HolaJan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-15 13:00:15

Estos valores ahora se establecen en el archivo .csproj:

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

Estos son los mismos valores que ves si vas a la pestaña Package en la configuración del proyecto. Si bien no creo que pueda usar * para aumentar automáticamente la versión, lo que puede hacer es introducir un paso de posprocesamiento que reemplace las versiones por usted (por ejemplo, como parte de su integración continua).

 8
Author: Gigi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-25 18:08:04

Dotnet build /p:AssemblyVersion=1.2.3.4

Estaba respondiendo a: "¿alguien ha descubierto cómo controlar la versión en .NET Core (or.NETStandard para el caso) proyectos."Encontré esta pregunta tratando de resolver este problema en el contexto de una construcción de CI. Quería establecer la versión de ensamblaje en el número de compilación CI.

 7
Author: Chris McKenzie,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-30 17:15:21

Hice una herramienta de CLI simple para configurar .csproj. NET Core version strings aquí . Puede combinarlo con herramientas como GitVersion para el choque automático de versiones durante las compilaciones de CI, si eso es lo que busca.

 6
Author: Tagc,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-03 21:28:52

Acepté la respuesta anterior porque @Gigi es correcta (a partir de ahora), pero me molestó y se me ocurrieron los siguientes scripts de PowerShell.

Primero tengo el script en mi carpeta de solución (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)

He añadido esto al archivo 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>

Incluso a través de su conjunto para ser un PreBuildEvent, el hecho es que los números de versión no se actualizan hasta DESPUÉS de que el archivo se ha cargado en la memoria, por lo que el número de versión no se reflejará hasta la próxima compilación. En de hecho, podría cambiarlo a un PostBuildEvent y tendría el mismo efecto.

También creé los siguientes dos scripts: (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)
 5
Author: Jason H,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-17 16:23:01

Para habilitar el control de versiones de su. Net Core/. Net Cualquier proyecto basado en su configuración de GIT, utilizando las etiquetas / describir funcionalidad de GIT.

He estado usando un Prebuild.objetivo.archivo xml que se encuentra en la carpeta raíz del proyecto e incluido en el archivo csproj como:

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

Use la etiqueta "GenerateAssembyInfo" para deshabilitar la generación automática de información de ensamblaje.

Entonces el Prebuild.objetivo.xml generará un CommonAssemblyInfo.cs archivo donde se puede incluye las etiquetas de versión que quieras según tu versión de GIT

NOTA: He encontrado los Prediseñados.objetivo.xml en otro lugar, así que no me he molestado en limpiarlo .)

El Prebuild.objetivo.archivo 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: Si está construyendo usando MSBUILD,

 $(SolutionDir)

Podría causarle problemas, use

 $(ProjectDir)

En cambio

 3
Author: Tue Skeltved,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-09 11:06:19

La extensión Automatic Versions para Visual Studio ahora admite.Net Core y. Net Standard autoincrementing en una interfaz de usuario sencilla.

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

 2
Author: madamission,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-26 20:51:00

Creo que esta Respuesta de @joelsand es la respuesta correcta para establecer el número de versión para dotnet core que se ejecuta en VSTS

Para agregar más información para esta respuesta,

BUILD_BUILDNUMBER es en realidad una variable predefinida .

Resulta que hay 2 versiones de variable predefinida.

Uno es build.xxxx, el otro es BUILD_XXXX.

Solo puedes usar Environment Variable Name en cproj.

 1
Author: maxisam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-15 22:33:10

Puede usar una función de propiedad de MSBuild para establecer el sufijo de versión basado en la fecha actual:

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

Esto producirá un paquete con un nombre como: Nombrepaquete.1.0.0-pre20180807-1711.nupkg .

Más detalles sobre las funciones de propiedad de MSBuild: https://docs.microsoft.com/en-us/visualstudio/msbuild/property-functions

 1
Author: Fabricio Godoy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-07 21:08:16

Podemos usar un parámetro especial para dotnet publish -- version-suffix 1.2.3

Para la versión del archivo:

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

Para la versión:

<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.
 0
Author: zxxc,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-10 15:15:38