【问题标题】:TFS2010 and compile once strategyTFS2010和编译一次策略
【发布时间】:2012-01-19 07:29:10
【问题描述】:

我正在尝试在 TFS2010 上实现一次编译策略,我需要一些关于如何执行此操作的输入。在 CI 上,我想编译所有内容(例如调试版本和发布版本)并运行 unittest。在下一个构建定义中,我想在 CI 中编译的同一个二进制文件上运行集成测试。构建管道可能如下所示

checkin -> Step 1 CI:compile + unittest -> Step 2 Nightly:集成测试 -> Step 3 Release:配置和打包

我不确定是否可以从放置位置的另一个团队构建中获得最后一个成功的构建。当我需要从第 1 步获取预编译的二进制文件时,这将解决我在第 2 步中的问题。

关于从另一个构建定义中获取最后一个成功构建的任何一般性意见或建议?

【问题讨论】:

  • 仅供参考,如果基于配置的构建之间存在显着差异,则此类事情将不起作用。例如,在 Web 应用程序中使用 web.config 转换,您希望构建不同的配置,因为它们会产生不同的配置设置。
  • 另外,您的 CI 构建和发布构建之间真的存在一对一的映射关系吗?通常“n”个 CI 构建最终会为 QA 生成“m”个构建,这些构建会产生“1”个发布到生产环境。
  • 出于同样的原因,我们不使用 web.config 转换。配置要么在打包应用程序时进行,要么在安装时进行。至于流水线的想法,当然不是1-1的映射。我想要实现的是,我测试 en dev、devtest、qa 等的二进制文件也是使用或发送给用户的二进制文件。这样我就可以自信地说发布包和这些确切的二进制文件已经被测试了。由于 TFS 的性质,似乎最常用的范例是在构建管道的每个步骤/阶段进行编译。
  • 我以前也有同样的感觉,但我相信每次构建中都会构建所需的代码,这应该会产生相同的二进制文件,更多或少。 “或多或少”的部分是我可能决定我希望 QA 和生产版本之间的设置略有不同。
  • 我同意它们应该是一样的,但是为什么每次都编译呢?我们有什么收获吗?关于配置,我们不会在编译时这样做。我们要么切换配置文件,要么在部署期间对其进行转换(MSBuild),或者让 WiX 在安装时配置设置。

标签: tfs build-automation


【解决方案1】:

可以说 Step 2 Nightly 不是构建定义,它是一个控制台应用程序:

  1. 检索最新的后续构建
  2. 从构建放置位置获取此构建的二进制文件
  3. 执行测试并根据测试是否成功执行某些操作(例如发送电子邮件或在源代码管理中应用标签)。

这些操作也可以在高度定制的构建过程模板中进行,其中诸如 CreateWorkspace 和运行 MSBuild 之类的主要构建步骤被砍掉,并且上述逻辑是手动实现的。

我会去你的地方对于使用 TFS-SDK 的 C# 控制台应用程序,执行上述操作并计划每天启动一次。


编辑
考虑到您的 cmets,我不明白为什么我的提议会让您远离构建管道。
无论如何,Step2 的核心和灵魂(至少在我的理解中)是检索先前成功构建的放置位置,然后对驻留在那里的二进制文件执行一些操作。

这个检索可能类似于以下内容:

using System;
using Microsoft.TeamFoundation.Build.Client;
using Microsoft.TeamFoundation.Client;

namespace GetDropLocationOfLastGoodBuild
{
    class Program
    {
        static void Main()
        {
            TfsTeamProjectCollection tpc =
                TfsTeamProjectCollectionFactory.GetTeamProjectCollection(
                    new Uri("TFSURI"));

            IBuildServer buildService = (IBuildServer) tpc.GetService(typeof (IBuildServer));
            IBuildDefinition buildDefinition = buildService.GetBuildDefinition("TeamProject", "BuildDefinitionName");
            Uri buildUri = buildDefinition.LastGoodBuildUri;
            IBuildDetail buildDetail = buildService.GetAllBuildDetails(buildUri);

            String binariesOfLastGoodBuild = buildDetail.DropLocation;
        }
    }
}

检索到放置位置后,您应该能够开始您计划的任何活动。
您需要的所有详细信息都在buildDetail

现在,这可以作为自定义构建活动运行高度自定义的构建过程模板,或作为单独的计划控制台应用程序。
我个人会做后者并使用 Windows 任务计划程序将其设置为每天在我的构建服务器中执行一次。

【讨论】:

  • 这是我们项目之一的简化​​构建管道,因为它包含多个步骤。但是,我无法理解您为什么要从构建中删除这一步。我想创建一个构建管道,其中包含编译、单元和集成测试、性能测试、负载测试、文档、配置、打包和部署等步骤,并且我想将其保留在构建服务中。以前我与 TeamCity 合作过,它能够使用来自其他成功构建的“工件”,因此是一个管道。从构建管道中采取某些步骤只是没有意义恕我直言
  • 我了解您的方法,它可以集成到 TFS 构建定义中。您的方法可用于创建自定义任务,只是为了获取 xx 的最后一次成功构建。我想我希望有一种更“原生”的方法。在使用 TFS20xx 时,我发现关于编译一次方法的信息非常少。感谢您迄今为止的投入!
【解决方案2】:

一般来说,如果您想为构建提供输入,有两种方法:

  • 将构建 1 的结果复制到正常构建文件夹之外的安全文件夹。 Build 2 然后将它需要的内容复制回其工作文件夹。

  • 将 build 1 的结果检查到 tfs 中,为将来的 build 获取和使用做好准备。

第二种策略是最好的,因为这意味着您对每个构建都有二进制输入的历史版本 - 您可以进行历史构建或分支构建,并且构建系统将使用所有内容的适当版本。

我想到的问题是:为什么要编译一次?对于 CI,您应该以增量构建为目标,以便您可以尽快完成构建。对于夜间测试和发布构建,您希望从头开始重建所有内容,而不是依赖增量构建来完美工作(他们从来没有这样做过 - 最终源代码和二进制文件有点不同步,并且构建会产生损坏的结果,或者无法完成)。

【讨论】:

  • 检查二进制文件可能有效,但似乎有点过分。我们得到了很多签到:)。
  • 关于为什么我只想构建一次,是为了确保在每个阶段都使用相同的 bin,最后在生产中打包/使用。这可以确保这些确切的二进制文件已经过测试(注意,不是变更集)并已发布到生产环境中。这是 Jez Humble 的持续交付原则之一(好书!)。 jamesbetteley.wordpress.com/2011/08/04/continuous-delivery
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-03
  • 2014-06-30
  • 1970-01-01
  • 1970-01-01
  • 2011-02-25
相关资源
最近更新 更多