在构建期间无法自动将NuGet包更新到最新版本

时间:2013-02-22 15:15:04

标签: visual-studio build teamcity nuget

我们有两个独立的.NET解决方案:

  • 为第一个解决方案运行构建会生成我们的最终产品:一堆DLL。这些DLL通过NuGet包提供给我们的客户。
  • 第二个解决方案是一个产品测试解决方案:NuGet包安装在它上面,它是构建和执行的 - 因此它使用我们的产品与客户完全一样。

这里面临的挑战是,应该有一种方式将我们最新的NuGet软件包自动安装到产品测试解决方案中,最好是在构建此产品测试解决方案期间。

基于a similar question的想法,我在配置产品测试解决方案方面取得了很大的进展:

  • 首先我启用了NuGet Package Restore。这让我可以完全从VCS中删除“packages”目录,因为在build.config文件中定义的版本的包将在构建之前由NuGet自动下载。
  • 然后我在Visual Studio中添加了以下预构建事件:$(SolutionDir).nuget\nuget update -prerelease $(ProjectDir)packages.config。这让我可以在构建期间引入最新版本的NuGet包。

我目前使用上述方案使用Visual Studio运行本地构建,使用TeamCity运行无人参与构建。该解决方案似乎第一眼就适用于这两种情况,但实际上它不会产生预期结果:构建产品测试解决方案时,在bin目录中我不会获取最新版本的DLL,只获取最新版本的版本。

问题在于虽然nuget update命令按预期更新了所有内容,包括packages.config.csproj文件,但新内容未被提取因此,正如我所猜测的那样 - .csproj文件中的 HintPath 设置仍然反映了“before build”状态,因此旧的DLL被复制到bin目录。我假设.csproj文件只处理一次:在触发预构建事件之前,预构建事件所做的更改将被忽略,直到下一次构建。

我考虑了以下解决方案:

  • 显然,预建不是“预先”。如果有一个更早的点我可以插入nuget update命令,我的上述解决方案可能会有效。
  • 我读到我可以通过定义ReferencePath来覆盖.csproj文件中的HintPath-s。但我怀疑我能否轻松找出正确的路径,或者我可以尽早设置它,以便构建能够解决它。
  • 作为一种解决方法,我可以运行两次构建:在TeamCity中复制产品测试解决方案的构建步骤,我总是可以在Visual Studio中本地构建解决方案两次。

有人想出如何在构建期间自动将NuGet包更新到最新版本吗?

3 个答案:

答案 0 :(得分:6)

查看我刚刚就此过程发表的博客文章。我没有在服务器上配置东西,而是通过增加使用Nuget Package Restore选项实现的Nuget.Targets文件来实现。这种方法的优点是它在本地和服务器上执行(所以你可以在打破构建之前看到任何可能的副作用)

在此处发布详情:http://netitude.bc3tech.net/2014/11/28/auto-update-your-nuget-packages-at-build-time/

答案 1 :(得分:4)

我认为将自动更新放到预构建步骤中它不是NuGet风格。您可以理解每次执行此操作时都需要此操作。主要是因为它可以增加构建时间。例如,当您使用TDD并经常重建项目并运行测试时,您希望它能够快速完成。此外,它可以更新意外的包并破坏一些东西,之后你可以花很多时间来发现问题。
我建议将更新作为单独的步骤。在TeamCity上,您可以使用NuGet installer构建步骤。要执行更新,只需选中步骤配置底部区域中的两个复选框: enter image description here

此外,如果您希望在成功构建和传递测试后保留更新结果,则可以添加稍后的构建步骤,将此更改提交到VCS(例如,使用cmd或PowerShell)。
当你在本地工作时,在开始使用项目之前,我更好地运行更新包一次。您可以使用Package Manager Console来使用Update-Package -IncludePrerelease

答案 2 :(得分:-1)

我想出的MSBuild解决方案是覆盖BuildDependsOn属性。因此,我创建了一个UpdateNugetPackages.target,如下所示:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <BuildDependsOn>
      UpdateNugetPackages;
      $(BuildDependsOn);
    </BuildDependsOn>
    <UpdateCommand>"$(SolutionDir)pathToYourNugetExe.exe" update "$(SolutionDir)NameOfYourSolution.sln"</UpdateCommand>
  </PropertyGroup>
  <Target Name="UpdateNugetPackages">
    <Exec Command="$(UpdateCommand)"></Exec>
  </Target>
</Project>

UpdateCommand定义调用nuget.exe的位置和参数。 您可以根据自己的需要随意使用。

然后在.csproj文件中引用此目标。就这么简单:

<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
 ...
    <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
    <!-- After the initial decleration of the BuildDependsOn-Property. -->        
    <Import Project="UpdateNugetPackages.target" Condition="Exists('UpdateNugetPackages.target')" />

请记住,导入订单很重要。您必须导入目标文件(UpdateNugetPackages.targets),并覆盖(或实际装饰)BuildDependsOn属性, 定义的目标文件Microsoft.Common.targets之后它。否则,该属性将被重新定义,并将删除您的更改,因为Microsoft.Common.targets中的初始定义不包含BuildDependsOn中的任何现有值。 Microsoft.Common.targetsMicrosoft.CSharp.targets导入C#项目。因此,导入后必须 导入Microsoft.CSharp.targets