首页 > 解决方案 > 单一仓库中软件包的独立版本控制

问题描述

我们刚刚开始研究可能最好被描述为公司范围的“开放”源代码框架的东西。我们的主要语言是 C#,我们使用 Jenkins 和 ProGet 来创建和共享 nuget 包。我们开始将所有内容(我的意思是所有内容。一个模块至少有三个存储库)放在它自己的 Git 存储库中。我们认为这是一个好主意,因为我们可以分别对所有内容进行版本控制和发布,但如果您想对具有依赖关系的多个存储库进行更改,结果会导致非常烦人的工作流程。

我开始环顾四周,似乎大多数项目都使用更单一的方法,我认为这可能也会让我们在这里的生活更轻松。我不太确定的是,这种方法的版本控制是如何工作的。

CoreFx 存储库是我们努力实现的一个很好的例子。一个 repo 会产生许多单独的包。当我在本地构建它时,所有包都有一个版本号,但是当我查看 nuget.org 上可用的包版本时,版本似乎是每个包。例如 System.Diagnostics.DiagnosticsSource 的版本为 4.5.1,但引用 System.Diagnostics.Debug 版本为 4.3.0。

所以这正是我认为对我们来说是一个很好的解决方案。一个 repo,许多带有独立版本的生成包。

有谁知道 corefx 项目是如何实现的,或者有任何其他建议,如何做到这一点?

标签: c#gitjenkinsnugetversioning

解决方案


monorepos 和very-many-repos 都有优势;许多小型存储库的优势之一是您可以轻松地获取git tag单个包的特定版本。在 monorepo 中做同样的事情有时会更尴尬。

但是,如果您发布的更多的是“一组相关包”,那么这毕竟不是一个坏主意:您可以拥有一个文件.bat.ps1文件来为您的存储库构建所有 NuGet 包并相应地设置版本号。像这个例子(Powershell 脚本)

您正在谈论的引用/依赖项(System.Diagnostics.DiagnosticsSource版本 4.5.1 取决于版本 4.3.0)成为“消费”包中System.Diagnostics.Debug的各个<dependency>标签(即在这种情况下。)在这里,您可以选择两种主要策略:.nuspecSystem.Diagnostics.DiagnosticsSource

  • 始终碰撞所有<dependency>版本,以便“升级一个升级所有”软件包。有时这就是你想要的,然后你应该这样做。
  • 更细粒度:仅当您以某种方式实际使用更新/更新的功能时才更新依赖项。例如,当使用包使用仅存在于特定版本的依赖项中的方法时。

后一种策略可以说是更优雅的方法,但也更复杂(可能需要更多的工作才能以好的方式完成)

.NET 特有的挑战

假设我有项目 A 和项目 B,它们都引用了 A,并且两者都在同一个存储库中。我还有一个项目 B 的 Visual Studio 解决方案,它包含对项目 A 的项目引用。

现在,我对项目 B 进行了更改并增加了它的版本,而不增加项目 A 的版本。我推送了我的更改,Jenkins 对 repo 进行了干净的检查并构建了创建两个包的解决方案,但是包 A 现在具有相同的版本与以前的版本一样,无法推送到 nuget 提要

这确实是一个有趣的问题。一些潜在的解决方法:

  • 让 Jenkins 检测/确定更改之间的增量,并仅为树中已更改的部分构建包。可能可行,但可能不太容易;.ps1在你的脚本中需要一些逻辑。也许是我能想到的最优雅的解决方案。

  • 使因“版本已存在”而失败的 NuGet 推送成为非致命错误。即检测您何时运行nuget push是否遇到特定错误(非常重要的细节!)并忽略它。您绝对不想忽略所有错误,nuget push而只想忽略这些特定错误。不太优雅,但仍然是全自动的。

  • 使发布包成为半自动而不是全自动的过程。在 Jenkins 中设置一个或多个工作,当要发布新版本的包时手动“按下按钮”,可能带有工作参数说“要发布哪个包”(可以是 Jenkins 中的下拉菜单,所以没有人有手动输入名称。)听起来可能有点手动,但这个选项让您作为一个团队可以最大程度地控制推送哪些包以及何时推送。

进一步阅读

(关于一般的monorepos,没有专门处理你提到的CoreFx案例。不过仍然可以提供有价值的信息。)


推荐阅读