【问题标题】:TFS and Local Build DifferencesTFS 和本地构建差异
【发布时间】:2014-10-21 17:40:36
【问题描述】:

在我们的解决方案中,我们有一个“.nuget”文件夹。此文件夹不包含 NuGet.exe。相反,我们始终确保在构建时使用 NuGet.targets 中的此属性下载最新的 NuGet.exe:

<DownloadNuGetExe Condition=" '$(DownloadNuGetExe)' == '' ">true</DownloadNuGetExe>

这在开发人员的机器上效果很好。始终下载最新版本的 NuGet.exe。

不幸的是,TFS 构建服务器存在问题——出于安全原因(并且超出我的控制),它无法访问 Internet,因此无法根据需要下载 NuGet.exe。相反,它具有我们必须使用的 NuGet.exe 的本地副本(服务器本地)。

那么问题是,我如何告诉 Visual Studio 构建系统始终从 Internet 检索 NuGet.exe,并告诉 TFS 构建系统使用 NuGet.exe 的本地副本?我确定它与构建变量或类似的东西有关。

任何建议将不胜感激。

【问题讨论】:

  • 为什么希望本地和团队构建运行不同版本的 NuGet?
  • 我们不希望本地和团队构建使用不同版本的 NuGet.exe。我们希望两个环境始终使用最新版本。对于开发人员来说,这很简单:只需将 DownloadNuGetExe 属性设置为 true,正如我在原始帖子中所展示的那样。然而,团队构建更加困难,因为机器无法访问 Internet,因此无法下载最新版本的 NuGet.exe。相反,TFS 管理员将最新版本的 NuGet.exe 放在众所周知的位置。

标签: tfs


【解决方案1】:

为此,您需要将 Nuget.exe 检入 .Nuget 文件夹。然后,您的本地工作区和构建服务器都可以访问和使用相同的版本。

Visual Studio 会在您需要更新 NuGet 时通知您。

注意:在构建服务器上无法访问 Internet 不是安全限制。这是来自 IT 黑暗时代的严厉政策,需要重新考虑。理想情况下,您不想将任何二进制资产签入 SCM,而是在构建时下载它们。

这是最佳实践,而您的 IT 政策正迫使您出现功能障碍。

【讨论】:

  • 正如我在原始帖子中所说,我们的“.nuget”文件夹中没有 NuGet.exe。我们不希望它在那里也不想签入,因为: 1. 每个项目都会冗余签入一个通用文件 (NuGet.exe) 并且... 2. 最终,一些项目会签入更新版本的NuGet.exe,可能会导致存储库中有多个版本的 NuGet.exe。
  • 不幸的是,这是针对您的问题的推荐和官方解决方案。
  • 我对答案感到有点惊讶。对我来说,官方的解决方案是不签入与 NuGet 相关的任何内容(除了“.nuget\NuGet.config”文件,因此 VS 不会尝试签入“packages”文件夹。也就是说,从VS 2013 和 TFS 2013。NuGet 团队希望在 MSBuild 过程中完成与 NuGet 相关的工作,不推荐使用 hecne NuGet.targets。David Ebbo 解释了这一切 here 并附有 NuGet 官方网站的链接。
  • 正确 - 但是您说您在构建服务器上没有互联网访问权限,这否定了开箱即用的解决方案。唯一的其他开箱即用解决方案是使用 2013 年前的方式。每次更新 NuGet.targets 文件时,您的以下解决方法都会中断。
【解决方案2】:

答案,至少是我的答案,原来很简单。

“.nuget”文件夹包含“NuGet.targets”,可在需要时下载 NuGet.exe。有一个 DownloadNuGet 任务,其中包含用于下载 NuGet.exe 的 C# 代码的 sn-p。如前所述,我们的 TFS 服务器无法访问 Internet,因此此 sn-p 始终会引发异常。

我的解决方案是向异常处理程序添加一些代码,以将 NuGet.exe 从服务器的知名位置复制到它需要的“.nugget”文件夹。

使用此修改后的 DownloadNuGet,NuGet.exe 将下载到开发人员的计算机上,并将从 TFS 服务器上的已知位置提取。

这是更新后的 DownloadNuGet 任务,其中包含大量日志记录:

<UsingTask TaskName="DownloadNuGet" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
  <ParameterGroup>
    <OutputFilename ParameterType="System.String" Required="true" />
  </ParameterGroup>
  <Task>
    <Reference Include="System.Core" />
    <Using Namespace="System" />
    <Using Namespace="System.IO" />
    <Using Namespace="System.Diagnostics" />
    <Using Namespace="System.Net" />
    <Using Namespace="Microsoft.Build.Framework" />
    <Using Namespace="Microsoft.Build.Utilities" />
    <Code Type="Fragment" Language="cs">
     <![CDATA[
        try {
           OutputFilename = Path.GetFullPath(OutputFilename);

           Log.LogMessage("***** Downloading latest version of NuGet.exe to: \"" + OutputFilename + '"');
           WebClient webClient = new WebClient();
           webClient.DownloadFile("https://nuget.org/nuget.exe", OutputFilename);
           Log.LogMessage("***** Latest version of NuGet.exe was successfully downloaded: " + OutputFilename);

           return true;
        } catch (Exception ex) {
           // This exception handling code is what's new.
           Log.LogMessage("***** Exception while downloading latest versioln of NuGet.exe: " + ex.GetType() + " ==> " + ex.Message);
           Log.LogMessage("***** Attempting to find NuGet.exe in C:\\NuGet folder.");

           FileInfo nuGetExeFile = new FileInfo(@"C:\NuGet\NuGet.exe");
           nuGetExeFile.CopyTo(OutputFilename, true);

           String formattedFileLength = String.Format("{0:N0}", nuGetExeFile.Length);
           Log.LogMessage("***** NuGet.exe has been copied to \"" + OutputFilename + "\", File size: " + formattedFileLength);

           return true;
        }
     ]]>
    </Code>
  </Task>
</UsingTask

>

【讨论】:

  • 请记住,每次 Visual Studio 更新工具时,这都会中断。不要依赖这种方法。
猜你喜欢
  • 2013-02-22
  • 2013-09-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-25
  • 1970-01-01
相关资源
最近更新 更多