NuGet包的问题:packages.config、项目引用和解决方案范围内的packages文件夹。

15
我们开始使用NuGet遇到了一些问题:
首先介绍一些关于NuGet的事实:
- packages.config(位于项目根目录)会在添加、更新或删除包时被创建和更新。该文件中的“version”属性反映了正在使用的完整版本号,因此在这个意义上也是一种状态。可以在包规范中添加allowedVersions属性,它限制了可以更新的版本。为了使包还原工作,此文件需要在源代码控制下。 - packages文件夹位于解决方案根目录,其中包含依赖包的下载版本,在子文件夹中命名与软件包名称相匹配(包括版本),以允许在多项目解决方案中使用同一软件包的多个版本。建议不将其纳入源代码控制,因为它们是二进制文件,而且包还原可以在需要时重新创建它们。当包被更新时,会创建一个新的与更新相匹配的文件夹,并在其中放置软件包。 - 项目文件包含对packages文件夹中软件包的引用,以便进行构建,并使Visual Studio能够提供自动完成、智能感知等功能。当软件包更新时,项目文件中的引用将更新为与软件包在packages文件夹中的新位置相匹配。
以下是问题:
1.由于packages.config文件中包条目包含完整的版本信息,我们必须不断更新源代码控制存储库中的更改。或者,我们可以忽略更改,大多数情况下,仅当版本发生更改时,我们才能够(在大多数情况下)忽略它们。这似乎非常不必要,因为NuGet还原应该能够通过allowedVersions知道哪些版本是允许的。
2.allowedVersions属性必须手动添加,有时会被遗忘。我们使用语义化版本控制,因此对于我们来说,在安装Foo-1.1.0版本时,应自动应用allowedVersions="[1,2)"。
3.添加allowedVersion后,NuGet包还原似乎无法找到预发布程序集(可能是一个错误)。
4.为什么NuGet处理解决方案级别的软件包?如果您正在使用混合匹配解决方案,其中包含project-A(repo-1)和project-B(repo-2),则解决方案级别的打包将无法正常工作。也就是说,如果您将该解决方案文件保存在单独的位置,则可能仍然可以工作。但是,如果您设置了另一个包含project-A(repo-1)和project-C(repo-3)的解决方案,则project-A将突然需要进行软件包还原,并且更糟糕的是,项目引用将因最后一次更改而更改。返回第一个解决方案将具有无法工作的引用。对这些进行检查肯定会使它们对其他人不起作用。
5.在软件包更新时,项目文件引用将被更新(以匹配其中带有版本id的新文件夹名称),并且将显示为未提交的更改。提交此更改似乎是常规操作,但在我们看来,这是不必要的。
关于ExcludeVersion的注意事项(可能会建议作为上述问题的解决方案):
- 据我所知,只有在手动执行NuGet命令时才能提供该选项。通过Visual Studio中的NuGet菜单安装/更新软件包时,无法使用该选项。使用任何自动化工具意味着必须手动修复文件夹名称和项目引用。 - 我
`<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="Foo" version="[1,2] source="Development Feed">
</packages>`

这将会:

  • 解决 package.config 文件过度提交的问题,因为版本属性不再经常更新。

  • 无需记住对语义化版本化项目设置范围。

  • 确保从所需的 feed 中获取软件包,并且不会浪费时间在错误的来源上查找。

B - Packages 文件夹和已安装软件包的名称

我希望 packages 文件夹位于每个项目根目录下,子文件夹名称仅限于软件包名称,不包括版本。 这将会:

  • 解决项目文件过度提交的问题,因为项目文件中的项目引用现在指向更新后的相同软件包文件夹。

  • 允许项目使用相同软件包的不同版本,因此它们彼此真正独立。


我们非常乐意听取有关解决上述问题的方案。


根据这个问题https://dev59.com/92Ei5IYBdhLWcg3wWLES,你有多少开发人员和开发团队? - Matthew Skelton
谢谢。我们现在有7个人,但计划在一年内翻倍。 - Spiralis
谢谢 - 这有助于回答。 - Matthew Skelton
1个回答

7

NuGet Enterprise - best practices for different maturity levels of packages中所建议的那样,我认为你比必要的更加复杂 :)

  1. 为什么不想捕获与代码编译时使用的软件包版本?这是可靠诊断和可重复构建所需的关键信息。考虑到您可能将代码更改提交回版本控制,提交有助于构建该源码所使用的软件包详细信息非常有用。
  2. "安装 i.e. Foo-1.1.0 版本时,allowedVersions="[1,2)" 应该被暗示" 我不认为 allowedVersions 能够真正地被暗示,因为并非所有 NuGet 包都遵循 SemVer(请参见 log4net 1.2.11 的混乱)。作为 CI 构建或 pre-commit/pre-push Dev 检查的一部分,设置 grep allowedVersions 应该能够捕捉到此问题。它不应经常更改,并且需要密切关注它(如果其他团队和软件包正确使用 SemVer 的话 :))。
  3. 要查找预发布软件包,您需要在 nuget install 中使用 Prerelease 或 -IncludePrerelease 标志。
  4. "如果您正在使用混合解决方案,其中包含项目 A(repo-1)和项目 B(repo-2)" - 为什么要将代码安排在这样的方式?单个解决方案的代码应该全部位于同一个 repo 中。将解决方案代码分散在不同的 repo 中肯定会非常麻烦!
  5. 您可以告诉 NuGet 使用无版本文件夹名称安装软件包(-ExcludeVersion)。

我强烈建议摒弃 Visual Studio NuGet 集成,而是改用命令行的 nuget.exe 和构建脚本。这尤其涉及到 #5,但适用于与 NuGet 的所有交互。当仅使用来自 nuget.org feed 的第三方公共软件包时,Visual Studio 集成非常好;但在处理内部 NuGet feeds 和 packages 时,它的灵活性并不足够。


首先,感谢您在此事上花费的时间。
  1. 我认为您的建议有价值,但我仍然觉得尴尬更糟。
  2. 在我们的情况下,我们将基于99%我们自己的软件包,因此我们可以相当依赖semver。
- Spiralis
2
  1. 我觉得我们在这方面遇到了问题。我需要重新审视一下。
  2. 如果你有一个实用库与你的许多产品相关联。每个产品都在单独的仓库中。但是,由于经常需要更改实用库,将其包含在其他解决方案中非常方便。VS或其他地方没有说不应该这样做。然而,NuGet却强制要求这样做。
  3. 是的,但这会破坏自动还原功能,因为NuGet无法解决这个问题。我觉得这个功能有点buggy。
- Spiralis
由于经常需要更改实用程序库,因此将其包含在其他解决方案中非常方便。VS或其他任何地方都没有说您不应该这样做。但是,NuGet则强制执行此操作。我认为并不是NuGet本身强制执行拆分 - 这只是良好的软件实践,NuGet可能会假设。如果您每天需要更改库,则建议您重新查看解决方案之间的责任边界 - 这将有助于您扩展规模。很高兴能帮忙 :) - Matthew Skelton

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接