单一仓库中包的独立版本控制
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 案例。尽管仍然可以提供有价值的信息。)
- https://github.com/babel/babel/blob/master/doc/design/monorepo.md:为什么 Babel 是一个单一仓库?
- https://github.com/korfuri/awesome-monorepo:很棒的 Monorepo 工具、软件和架构的精选列表。
- https://github.com/pouchdb/pouchdb/issues/5128:PouchDB 迈向单一存储库的一些步骤
我们刚刚开始研究一些可能最能描述为公司范围内 "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 案例。尽管仍然可以提供有价值的信息。)
- https://github.com/babel/babel/blob/master/doc/design/monorepo.md:为什么 Babel 是一个单一仓库?
- https://github.com/korfuri/awesome-monorepo:很棒的 Monorepo 工具、软件和架构的精选列表。
- https://github.com/pouchdb/pouchdb/issues/5128:PouchDB 迈向单一存储库的一些步骤