我应该如何使用Nuget进行企业内部开发?

我们使用Nuget进行内部开发,使我们能够跨团队共享代码。 然而,当一个人正在处理将同时在多个nuget软件包中部署的代码时,我们遇到了一些问题。 例如

A取决于B取决于C

A,B和C的工件被推送到Nuget,这就是我们如何pipe理A,B和C之间的依赖关系。我们发现的麻烦是,如果开发人员想要在C中进行更改并快速看到A中反映出来的变化,必须经过以下过程。

  1. 在C中做出改变
  2. 推变化为混帐
  3. CI接替C,build立并部署新的nuget包。
  4. 进入B并使用nuget update package命令更新对C的引用。
  5. 将更改推送到packages.config文件直到git
  6. CI接替B,为B构build和部署新的nuget包
  7. 现在打开A并将引用更改为B和nuget更新包
  8. 在A中进行更改以符合B(和C的过渡)

这看起来非常痛苦,正在导致我们的一些开发人员对我们内部开发的代码的Nuget的select提出质疑。 每个人都喜欢消耗外部包装。

有没有更好的内部使用Nuget的工作stream程?

在我们公司,我们用下面的设置解决了级联更新问题。 首先,我们为我们的NuGet存储库和构build服务器进行以下设置。

  • 有一个内部NuGet存储库,它包含公司所有已发布的软件包。 这个存储库只是我们其中一台服务器上的一个共享目录。
  • 每个开发者可以在自己的机器上拥有(但不需要)一个或多个目录,作为本地的NuGet包库。 通过使用特定于用户的NuGet configuration ,开发人员可以控制NuGet通过包存储库search的顺序来查找包。

    <?xml version="1.0" encoding="utf-8"?> <configuration> <packageRestore> <add key="enabled" value="True" /> </packageRestore> <packageSources> <add key="Dev" value="D:\dev\testpackages" /> <add key="Company" value="<UNC_ADDRESS_COMPANY_REPOSITORY>" /> <add key="NuGet official package source" value="https://nuget.org/api/v2/" /> </packageSources> <disabledPackageSources /> <activePackageSource> <add key="All" value="(Aggregate source)" /> </activePackageSource> </configuration> 
  • 所有的解决scheme都打开了自动的软件包恢复function,所以我们不必将软件包提交到​​我们的版本控制系统。

  • 开发人员只能控制4个版本号中的3个,例如,如果版本是<MAJOR>.<MINOR>.<BUILD>.<REVISION>那么开发人员只能更改主版本号和次版本号,版本号设置为0,除非构build服务器在构build版本号的地方完成构build。 这一点很重要,因为这意味着对于由主要版本,次要版本和内部版本组成的给定版本,构build服务器将始终生成更高的版本号。 这也意味着NuGet会更喜欢从公司软件包仓库(仅通过构build服务器获取软件包)获取软件包版本。

为了改变其中一个基本库,有两个可能的进程正在使用。 第一个过程是:

  1. 对基础库(A)进行更改。 如果需要更新(A)的版本。
  2. 运行MsBuild脚本来构build二进制文件,并创build(A)的NuGet包
  3. 将新的NuGet包复制到本地机器上的包库中
  4. 在依赖项目(B)中升级到刚刚放置在本地机器软件包仓库中的(A)的新软件包(应该是比公司版本库或NuGet.org上可用版本更高的版本)
  5. 对(B)进行更改。

如果需要更改(A),则重复步骤1,2和3,然后从(B)的工作目录中删除(A)的包。 下一次构build运行NuGet会去寻找(A)的特定版本,在本地机器库find它,并将其拉回来。请注意, NuGetcaching可能会阻止这个过程的一些时间,虽然它看起来像NuGet可能不caching来自同一台机器的软件包(?)。

一旦变更完成后,我们:

  1. 提交更改(A)。 构build服务器将运行集成构build来validation一切正常。
  2. 告诉构build服务器运行释放构build,构build二进制文件并将NuGet包推送到公司范围的NuGet存储库。
  3. 在(B)中,升级到(A)的最新版本(应该比testing包具有更高的版本号,因为testing包应该具有版本abc0,而公司版本库中的新build版本应该是abc, 0
  4. 将变更提交给(B)。 等待构build服务器完成集成testing
  5. 告诉构build服务器运行(B)的发布版本。

开发工作的另一种方法是采取以下步骤

  1. 对基础库(A)进行更改。 如果需要更新(A)的版本。
  2. build立二进制文件
  3. 将二进制文件复制到NuGet解压缩项目(B)的(A)包的位置(例如c:\mysource\projectB\packages\ProjectA.1.2.3.4
  4. 对项目进行必要的修改(B)

提交过程仍然是一样的,需要首先提交项目(A),在项目(B)中需要升级(A)的NuGet引用。

第一种方法稍微整洁一点,因为如果(A)的NuGet包中有错误(例如忘记添加一个新的程序集),这个过程也会发出警告,而在第二个过程中,开发者直到(A )已经出版。

你有两个select:

  1. 在您的组织中运行NuGet Gallery的一个实例。 这是运行nuget.org的代码
  2. 获得Artifactory Pro的许可证, Artifactory Pro具有内置的Nuget支持并充当Nuget存储库。

我已经使用了这两个,#1是一个合理的select,但NuGet Galley优化和devisenuget.org,而不是本地/企业使用,所以像删除包是一个痛苦(手动SQL需要)。

我想说,你应该支付Artifactory Pro的(低)许可费 – 这是一个很好的产品,而且JFrog团队非常热衷和开启。

内部/企业软件包不应该使用nuget.org; nuget.org是为第三方/开源库devise的,而不是内部的构build依赖。

编辑 :在工作stream方面,为什么你把共享代码放到多个包中? 如果代码需要共享,则需要使用独立的包。

编辑2 :为了加速开发人员的代码更改工作stream程,您可以使用nuget.exe (命令行客户端)并使用命令行可访问的构build,以便您可以定位“开发人员”构build运行。 然后在你的“开发者”版本(而不是CI版本)中,当你想把新更新的B作为一个依赖项时,指定nuget install B -Source C:\Code\B作为本地path(例如nuget install B -Source C:\Code\B )并build立反对; 同样适用于C或其他本地新近更新的软件包。 那么,当ABC都build立好的时候,你可以git push所有的东西都git push顺序依次git push ,让CI做它的事情。

但是 ,如果你必须经常这样做“跳舞”,你也应该质疑你的包分离是否真的合适,因为这意味着所有的代码应该在一个包中,或者可能沿不同的包中的不同行分开。 一个定义良好的软件包的一个关键特性是它不应该对其他软件包产生连锁反应,当然,如果你正在有效地使用语义版本pipe理的话 。

编辑3 marcelo-oliveira所要求的一些说明:“命令行可访问的构build”是可以完全从命令行完成的构build,不需要使用Visual Studio,通常是通过batch file。 “开发人员构build”是开发人员从其工作站运行的构build版本,而不是在CI服务器上运行的CI构build版本(两个构build版本应基本相同)。

如果A,B和C使用相同的解决scheme ,则可以在一个版本中为它们创buildNuGet包。

只要确保使用的软件包有新的版本号(假设你的版本不会随机改变它),它所依赖的软件包。

如果A,B和C有意地处于不同的解决scheme中,例如A在基础设施解决scheme下,B在产品解决scheme下,那么我唯一的build议就是在检查时定义您的CI构build运行而不是定期。

编辑:

另一个select是在本地构build期间为您的NuGet服务器创build推送预发布包 (例如版本1.0.0-alpha),这样开发人员可以在创build发布版本之前试用这个包。

Nuget被devise为共享第三方库文件。 我们计划在内部使用Nuget来共享可以在项目之间共享的代码。 像常见的数据层,string和其他正则expression式函数,电子邮件组件和其他工件。

我看到Nuget有任何帮助的唯一方法是当你在团队/项目中共享的组件,代码或工件是稳定的,并且有自己的发布周期,这与你的项目的发布周期不同。 为了您的需要,Nuget是一个矫枉过正的问题。 在同一个解决scheme中,你可能有更好的生产力链接所有这些项目 您的解决scheme结构应包括三个项目A,B和C作为依赖项目,在需要时内部引用。