单一仓库中包的独立版本控制

Independent versioning of packages in a mono-repo

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

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

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

所以这正是我认为对我们来说是一个很好的解决方案。一个回购协议,许多具有独立版本的结果包。

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

monorepos 和very-many-repos 都有优点;许多小型回购的优势示例之一是您可以 git tag 一个单独的包的 特定 版本很容易。在 monorepo 中做同样的事情有时会更尴尬。

但是,如果您 发布 更像是 "set of related packages",那也许毕竟不是一个坏主意:您可以有一个 .bat.ps1 文件,为您的存储库构建所有 NuGet 包并相应地设置版本号。喜欢 this example(Powershell 脚本)

你说的 references/dependencies(System.Diagnostics.DiagnosticsSource 4.5.1 版取决于 System.Diagnostics.Debug 4.3.0 版)成为 [= "consuming" 包的 16=](即本例中的 System.Diagnostics.DiagnosticsSource。)在这里,您可以选择两个主要策略:

  • 始终修改所有 <dependency> 版本,以便 "upgrading one upgrades all" 软件包。有时候这就是你想要的,然后你就应该那样做。
  • 更细粒度:仅当您以某种方式实际使用 newer/updated 功能时才更新依赖项。例如,当消费包使用仅存在于特定版本的依赖项中的方法时。

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

.NET 特定挑战

Assume that I have project A and project B, which has a reference to A and that both are in the same repository. Also I have a Visual Studio solution for project B, which holds a project reference to project A.

Now, I make a change to project B and increment it's version, without incrementing the version of project A. I push my changes and Jenkins makes a clean checkout of the repo and build the solution creating both packages but package A now has the same version as it had on a previous build and can not be pushed to the nuget feed

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

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

  • 将因 "version already exists" 导致失败的 NuGet 推送设为非致命错误。 IE。检测你何时 运行 nuget push 如果你得到 那个特定的错误 (非常重要的细节!)并忽略它。您绝对不想忽略 nuget push 中的 所有 错误,而只想忽略这些特定的错误。不太优雅,但仍然是全自动的。

  • 使发布包成为一个半自动而不是全自动过程。在 Jenkins 中设置一个或多个作业,当要发布新版本的软件包时,您可以在其中手动 "press the button" ,可能带有一个作业参数说 "which package to release" (可以是 Jenkins 中的下拉菜单,因此没有人必须手动输入名称。)听起来可能有点手动,但这个选项是让你作为一个团队最大程度地控制 推送什么包和什么时候推送的选项。

进一步阅读

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