为 .NET Core 项目设置版本号 - CSPROJ - 而不是 JSON 个项目

Setting the version number for .NET Core projects - CSPROJ - not JSON projects

这个问题和Setting the version number for .NET Core projects很相似,但又不一样。在撰写本文时使用最新稳定版本的 .NET Core (1.1) 和 VS2017,.NET Core 已从基于 JSON 的项目文件切换到 CSPROJ 文件。

所以 - 我想要做的是建立一个 CI 环境,我希望能够在其中 modify something用正确的版本号标记我的构建的构建。

如果我使用旧的(SharedAssemblyInfo.cs 技巧)这样的属性:

[assembly: AssemblyFileVersion("3.3.3.3")]
[assembly: AssemblyVersion("4.4.4.4")]

在项目的某处,我得到
CS0579 - Duplicate 'System.Reflection.AssemblyFileVersionAttribute'

CS0579 - Duplicate 'System.Reflection.AssemblyVersionAttribute'
构建时出错。

深入研究后,我发现 \obj\Debug\netcoreapp1.1:

中有一个在构建过程中生成的文件(在我构建之前它不存在)
//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//     Runtime Version:4.0.30319.42000
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

using System;
using System.Reflection;

[assembly: System.Reflection.AssemblyCompanyAttribute("TestApplication")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
[assembly: System.Reflection.AssemblyDescriptionAttribute("Package Description")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.1.99.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.1.99")]
[assembly: System.Reflection.AssemblyProductAttribute("TestApplication")]
[assembly: System.Reflection.AssemblyTitleAttribute("TestApplication")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.1.99.0")]

// Generated by the MSBuild WriteCodeFragment class.

问题 - 我该怎么做?
所以我可以看到这必须以某种方式从项目属性 'package page' 中输入的值生成,但我不知道在我的 CI 机器上更改这些值的正确方法是什么。

理想情况下,我希望能够在我的 (Jenkins) CI 脚本中指定所有这些信息,但我只满足于设置版本号。

编辑 - 更多信息
阅读第一个答案后,我想明确表示我正在创建服务和 NuGET 包 - 我更愿意使用一种方式对所有内容进行版本控制,就像旧的 JSON 项目一样,我可以只更新单个文件。

更新 我正在编写对 CSPROJ 文件的更改脚本,在我看来这相当老套,因为我需要 modify 的部分看起来像这样...

<PropertyGroup>
 <OutputType>Exe</OutputType>
 <TargetFramework>netcoreapp1.1</TargetFramework>
 <Version>1.0.7777.0</Version>
 <AssemblyVersion>1.0.8888.0</AssemblyVersion>
 <FileVersion>1.0.9999.0</FileVersion>
 <Company>MyCompany</Company>
 <Authors>AuthorName</Authors>
 <Product>ProductName</Product>
 <Description />
 <Copyright>Copyright © 2017</Copyright>
</PropertyGroup>

所以 - 这里的问题是有多个 'PropertyGroup' 元素;其他人似乎被贴上了标签——但不知道 CSPROJ 是如何组合在一起的,我不能说情况总是如此。

我的工作前提是始终填写包裹详细信息,否则值标签(上方)不会出现在 XML - 这样我就可以使用脚本更新到位的价值观。如果值标签不存在,我将不清楚要将值插入哪个 PropertyGroup 元素(以及哪个顺序,因为这似乎很重要;更改顺序使我无法在 VS2017 中加载项目)。

我仍在等待比这个更好的解决方案!

更新:在有人将这个问题标记为可能重复后 () - 我以前没有看到这个问题,现在阅读它似乎几乎相同,只是我不想设置版本号。另外,这个问题的答案并不能解决我的问题——只问我在问题中问的问题。我的问题的可接受答案正是我解决问题所需的答案 - 所以虽然另一个问题排在第一位并且看起来相同 - 但它根本没有帮助我。也许 mod 可以提供帮助?

我将 Jenkins + Octopus 用于 CI,以下工作得很好:

  1. 有一个预构建 Powershell 脚本,可以将 CI 构建号作为参数或默认为预设值。
  2. 在 CI 的项目中有一个单独的 nuspec 文件。
  3. 预构建脚本会使用最新的构建版本更新 nuspec 文件。
  4. 使用 Jenkins 发布项目。
  5. 使用来自 #2 的 nuspec 文件手动调用 Nuget
  6. nuget包推送到八达通。

您可以从命令行覆盖任何 属性,方法是将 /p:PropertyName=Value 作为参数传递给 dotnet restoredotnet builddotnet pack

目前,版本组合是这样的: 如果未设置 Version,则使用 VersionPrefix(如果未设置则默认为 1.0.0)并且 - 如果存在 - 附加 VersionSuffix.

然后所有其他版本默认为 Version

例如,您可以在 csproj 中设置 <VersionPrefix>1.2.3</VersionPrefix>,然后调用 dotnet pack --version-suffix beta1 生成 YourApp.1.2.3-beta1.nupkg(如果您有项目参考,您希望应用版本后缀同样,您需要在此之前调用 dotnet restore /p:VersionSuffix=beta1 - 这是工具中的已知错误)。

当然,您也可以使用自定义变量,请参阅 this GitHub issue 中的一些示例。

有关支持的程序集属性的完整参考,我建议查看构建逻辑的源代码 here(用 $() 包围的值是使用的属性)。 由于我已经在谈论来源,this 是构成版本和其他一些属性的逻辑。

直接回答您的问题:适用于 msbuild 的新 SDK 会自动生成程序集信息文件。您可以使用 msbuild 指令抑制它(通过示例查看它:在基于 project.json 的项目上调用 dotnet migrate)。

但是让我告诉你我的处理方式:我有多个项目共享同一个版本。我添加了一个 version.props 文件,其中包含一个 属性 组,其中包含一个名为 VersionPrefix 的项目。我通过 csproj 文件(Include 语句)包含了这个文件。我还删除了所有 AssemblyInfo.cs 文件并让 SDK 为我生成它们。

我在构建过程中修改了 version.props 文件。

正如我回答的那样 , I've made a CLI tool called dotnet-setversion 您可以使用它来对 *.csproj 风格的 .NET Core 项目进行版本控制。

在 CI 构建期间,您可以使用 GitVersion 或其他工具来确定项目的版本号,然后在项目根目录中调用 dotnet-setversion $YOUR_VERSION_STRING

如果您在项目文件中缺少它们,MsBuild 2017 将生成一些程序集信息。

如果你能阅读 msbuild 目标文件,你可以看看:

[VS Install Dir] \MSBuild\Sdks\Microsoft.NET.Sdk\build\Microsoft.NET.GenerateAssemblyInfo.targets

您会看到您可以在项目文件中使用一些 属性 来禁用生成的程序集信息,以防止与您生成的工具重复。

  • <GenerateAssemblyInfo>(这个属性会on/off全部生成汇编信息)
  • <GenerateAssemblyCompanyAttribute>
  • <GenerateAssemblyConfigurationAttribute>
  • <GenerateAssemblyCopyrightAttribute>
  • <GenerateAssemblyDescriptionAttribute>
  • <GenerateAssemblyFileVersionAttribute>
  • <GenerateAssemblyInformationalVersionAttribute>
  • <GenerateAssemblyProductAttribute>
  • <GenerateAssemblyTitleAttribute>
  • <GenerateAssemblyVersionAttribute>
  • <GenerateNeutralResourcesLanguageAttribute>
dotnet build /p:AssemblyVersion=1.2.3.4

这对你有用吗?

传递 /p:PropertyName=Value 作为参数对我不起作用(ASP.Net Core 2.0 Web App)。 我在市场上找到了清单版本控制构建任务:https://marketplace.visualstudio.com/items?itemName=richardfennellBM.BM-VSTS-Versioning-Task

在我的例子中,主键是 /property:Version=1.2.3.4。以下命令行完成了这项工作:

dotnet build SolutionName.sln -c Release /property:Version=1.2.3.4

这将覆盖程序集默认版本。

更新

所以另外只是为了在软件发布的实际用例中澄清这一点。

例如,当您发布软件时,您可以设置文件版本和产品版本,如前所述here

举个例子:

dotnet publish .\ProjectFolder\Project.csproj -r win-x64 /p:PublishSingleFile=true /p:IncludeNativeLibrariesForSelfExtract=true --self-contained true -o ReleaseFolderName -c Release /p:AssemblyVersion=1.2.3.4 /p:Version=1.2.3.4-product-version

将发布软件,右击软件点击详细信息,会出现如下图:

我在 .csproj 中做的就是这个

<Project Sdk="Microsoft.NET.Sdk.Web">
  <PropertyGroup>
    <TargetFramework>netcoreapp3.0</TargetFramework>
    <Deterministic>false</Deterministic>
    <AssemblyVersion>2.0.*</AssemblyVersion>
  </PropertyGroup>
</Project>

在 AssemblyVersion 中指定通配符,然后关闭 Deterministic 标志。将为通配符添加数字。

对于那些正在寻找不同的自动化 (CI) 方式来执行此操作的人,请考虑在基于环境变量的 .csproj 文件中使用条件。例如,您通常可能有一个硬编码的版本前缀和一个基于时间戳的后缀。但是为了正确发布,您可能希望将两者替换为您在 CI 构建期间设置的单一版本。为此,您可以在调用 dotnet build 之前设置一个环境变量:比方说,RELEASE_VERSION.

在 .csproj 文件中,在 <PropertyGroup> 下,您将拥有以下内容:

<Version Condition="'$(RELEASE_VERSION)' != ''">$(RELEASE_VERSION)</Version>
<VersionPrefix Condition="'$(RELEASE_VERSION)' == ''">0.0.1</VersionPrefix>
<VersionSuffix Condition="'$(RELEASE_VERSION)' == ''">$([System.DateTime]::UtcNow.ToString(`yyyyMMdd-HHmm`))</VersionSuffix>

上面的条件是这样设置的,如果环境变量RELEASE_VERSION为空,则使用正常的前缀和后缀标签。但如果它不为空,则使用 signular 版本标签。