16

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

  • 为第一个解决方案运行构建会产生我们的最终产品:一堆 DLL。这些 DLL 通过 NuGet 包交付给我们的客户。
  • 第二种解决方案用作产品测试解决方案:将 NuGet 包安装到其中,并构建和执行它 - 因此它使用我们的产品的方式与我们的客户使用的方式完全相同。

这里的挑战是我们最新的 NuGet 包应该有一种自动安装到产品测试解决方案的方法,最好是在构建这个产品测试解决方案的过程中。

基于来自类似问题的想法,我在配置产品测试解决方案方面取得了进展:

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

我目前使用上述方案来运行使用 Visual Studio 的本地构建和使用 TeamCity 的无人值守构建。该解决方案乍一看似乎适用于这两种情况,但实际上它并没有产生预期的结果:当构建产品测试解决方案时,在bin目录中我没有得到最新版本的 DLL,只有最新版本-1 版本。

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

我考虑了以下解决方案:

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

有人知道如何在构建过程中自动将 NuGet 包更新到最新版本吗?

4

3 回答 3

6

Have a look at a blog post I just did regarding this process. Instead of configuring stuff on the server, I did it by augmenting the Nuget.Targets file that's put in place with the Nuget Package Restore option. Beauty of this approach is it executes locally AND on the server (so you get to see any possible side-effects before breaking the build)

Posted details here: http://netitude.bc3tech.net/2014/11/28/auto-update-your-nuget-packages-at-build-time/

于 2014-11-28T18:35:14.397 回答
4

我认为将自动更新放到预构建步骤中,这不是 NuGet 风格。可以理解,每次做的时候都需要这个操作。主要是因为它可以增加构建时间。例如,当您使用 TDD 并经常重建项目并运行测试时,您期望它会很快完成。此外,它可以更新意外的软件包并破坏某些东西,之后您可以花费大量时间来查找问题。
我建议将更新作为单独的步骤。在 TeamCity 上,您可以使用NuGet installer构建步骤。要执行更新,只需选中步骤配置底部区域中的两个复选框: 在此处输入图像描述

此外,如果您想在成功构建并通过测试后保留更新结果,您可以添加稍后的构建步骤,将这些更改提交给 VCS(例如使用 cmd 或 PowerShell)。
当您在本地工作时,最好在开始使用项目之前运行一次更新包。您可以使用Package Manager Console命令来实现这一点Update-Package -IncludePrerelease

于 2013-02-23T09:47:57.660 回答
-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属性。否则,该属性将被重新定义并删除您的更改,因为 中的初始定义不包括 中的任何现有值。由C# 项目导入。因此,您的导入必须.Microsoft.Common.targetsMicrosoft.Common.targetsBuildDependsOnMicrosoft.Common.targetsMicrosoft.CSharp.targetsMicrosoft.CSharp.targets

于 2017-09-13T09:12:13.327 回答