连续部署环境中的dotnet语义版本控制

时间:2019-04-09 15:10:46

标签: .net-core gitlab csproj semantic-versioning dotnet-cli

我正在使用GitLab为我的dotnet核心应用程序和netstandard 2.0软件包配置语义版本控制。

在阅读了很多意见之后,其中一些意见是矛盾的,这对我来说很清楚。 语义版本应类似于 M.m.P.B-abc123其中

  • M是主要版本
  • m是次要版本
  • P是补丁程序版本
  • B是构建版本(可选)
  • 如果我使用预发行版,则
  • -abc123为后缀(可选)。它必须以字母开头

因此以下软件包版本有效:

  • 1.0.0
  • 1.0.1.20190301123
  • 1.0.1.20190301123-beta
  • 1.0.1-rc1

我使用以下gitlab脚本进行版本控制

#Stages
stages:
  - ci
  - pack

#Global variables
variables:
  GITLAB_RUNNER_DOTNET_CORE: mcr.microsoft.com/dotnet/core/sdk:2.2
  NUGET_REPOSITORY: $NEXUS_NUGET_REPOSITORY
  NUGET_API_KEY: $NEXUS_API_KEY
  NUGET_FOLDER_NAME: nupkgs

#Docker image
image: $GITLAB_RUNNER_DOTNET_CORE

#Jobs
ci:
  stage: ci
  script:
    - dotnet restore --no-cache --force
    - dotnet build --configuration Release
    - dotnet vstest *Tests/bin/Release/**/*Tests.dll

pack-beta-nuget:
  stage: pack
  script:
    - export VERSION_SUFFIX=beta$CI_PIPELINE_ID
    - dotnet pack *.sln --configuration Release --output $NUGET_FOLDER_NAME --version-suffix $VERSION_SUFFIX --include-symbols
    - dotnet nuget push **/*.nupkg --api-key $NUGET_API_KEY --source $NUGET_REPOSITORY
  except:
    - master

pack-nuget:
  stage: pack
  script:
    - dotnet restore
    - dotnet pack *.sln --configuration Release --output $NUGET_FOLDER_NAME
    - dotnet nuget push **/*.nupkg --api-key $NUGET_API_KEY --source $NUGET_REPOSITORY
  only:
    - master

这将生成软件包,例如: 1.0.0用于主分支(稳定或生产就绪),1.0.0-beta1234567用于主分支。

我的方法的问题是我有多个项目的VS解决方案,每个项目都是一个nuget包,每个项目都有自己的版本。有时,我修改了一个项目,但没有修改另一个项目,因此,从理论上讲,我当然不需要为我没有接触过的项目生成新的构件,也不需要新版本。

现在,我的nuget存储库阻止覆盖程序包,因此,如果有XXX.YYY 1.0.0并且我生成另一个XXX.YYY 1.0.0并将其推送到存储库,它将引发错误,并且管道将失败。 / p>

我认为,每次运行CI / CD管道时生成一个新软件包也许不是一个坏主意,所以我考虑引入内部版本号,并使用类似XXX.YYY 1.0.0.12345的名称,即使我不要触摸那里的任何东西,下次将产生新的包装XXX.YYY 1.0.0.123499

这是连续部署方案中的正确方法吗?还是我应该寻找一种方法来使我的脚本更加智能,而不是在nuget存储库中已经存在具有相同版本的新工件的情况下,不产生新工件呢?

假设始终可以使用内部版本号,如何确保仅从管道中检索内部版本号,而M.m.P版本号却按照以下说明保留在我的csproj中?

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
    <Description>Whatever</Description>
    <VersionPrefix>1.0.1</VersionPrefix>
  </PropertyGroup>
</Project>

我需要类似的东西: dotnet pack *.sln --configuration Release -p:PackageVersion=$FIXED_VERSION.$CI_PIPELINE_ID --output nupkg

但是我不知道如何通过CLI从csproj检索<VersionPrefix>内容。

假设我的方法有效,对我的方法有何建议,好书或解决方案?

谢谢

1 个答案:

答案 0 :(得分:1)

  

我的方法的问题是我有多个项目的VS解决方案,每个项目都是一个nuget包,每个项目都有自己的版本。有时候,我修改了一个项目,但没有修改另一个项目,因此,从理论上讲,我当然不需要为我没有接触过的项目生成新的构件,当然也不需要新版本。

由于持续的集成管道无法确定您的代码是新的次要版本还是主要版本,因此您将始终必须确定程序包应获取的语义版本。这使整个过程变得容易得多。

Visual Studio团队服务的人对此有话要说:

  

不可移植性和唯一的版本号   在NuGet中,特定的软件包由其名称和版本号标识。一旦发布了特定版本的软件包,就永远无法更改其内容。但是,当您生成CI程序包时,您将无法知道它是1.2.3版还是只是向1.2.3版迈进的一步。您不想在仍然需要一些错误修复的软件包上刻录1.2.3版本号。

     

SemVer可以解救!除了Major.Minor.Patch,SemVer还提供了预发行标签。发行前的标签是“-”,后跟所需的字母和数字。 1.0.0-alpha,1.0.0-beta和1.0.0-foo12345版本均为1.0.0的预发行版本。更好的是,SemVer指定当您按版本号排序时,这些预发行版本完全符合您的期望:0.99.999 <1.0.0-alpha <1.0.0 <1.0.1-beta。

     

Xavier的博客文章描述了“劫持”用于CI的预发布标签。不过,我们不认为这是在劫持。这正是我们在Visual Studio Team Services上创建CI包所要做的。我们将通过选择一个版本号,然后生成该版本的预发行版来克服这一矛盾。我们在版本号中保留预发布标签是否重要?对于大多数用例,并非如此。如果您固定到相关软件包的特定版本号,则不会有任何影响,并且如果将浮动版本范围与project.json一起使用,则意味着对您指定的版本范围进行了很小的更改。   来源:https://devblogs.microsoft.com/devops/versioning-nuget-packages-cd-1/

如前所述,您仍然需要自己为新软件包选择一个版本。对于实际发布最终软件包(在您的情况下为master分支)之前的过程,您可以使用预发行标签将内部版本号作为预发行标签。

如果不做任何聪明的事情,这将为每个运行的管道发布一个新的程序包。视觉工作室团队的服务人员,我认为这不是一件坏事,但这取决于每个人的个人喜好