用例——构建系统的系统——为遗留应用程序创建通用的CI/CD管道

文摘:

Mark Maxey / Raytheon, 2016年5月:许多持续集成和交付(CI/CD)文献针对的是具有类似概要的项目,即小型项目发布了一些高度模块化的服务,这些服务针对互联网,它们之间使用Git、Jenkins和Chef或Puppet等自动供应工具很少或没有耦合。对于CI/CD独角兽来说,这可能是真的,但如果你不是一个很酷的孩子,你该怎么办?

讨论转录:

好吧。嗯,欢迎。我很感谢你在午饭前过来。我很高兴不是在午饭后。我想大约一个小时后,我将在这里遇到不同的观众。你们都准备好了,饿了。渴望学习。我希望。或者可能不是这样。

我叫马克·马克西。我在雷神公司工作。我的电子邮件地址就在这里。Mark下划线R下划线Maxey在Raytheon。com。所以你可以通过这个联系我,或者我们可以之后再聊。当我讲到这里的时候,我会停下来,一定要提出问题或提出评论。请不要吃烂番茄或其他类似的东西。

我们要讲的是雷神公司的一个用例。感谢我们所做的以及如何使用Artifactory。

先给大家介绍一下雷神公司。雷神公司有一大堆我们做的东西。我们有大约10万名员工。我们在美国各地有许多不同的校区。我们制造了爱国者导弹,微波,地面控制系统,GPS和气象卫星,还有一些其他的东西你们几天前从Adrien那里听到的关于头盔上的耳机显示器和其他类似的东西。但我们经常做的一件事,我最参与的一件事是建立系统的系统。

所以通常发生的情况是,我们聚在一起,我们有一个我们想要增强的系统,或者一个我们想要与其他系统结合的系统,所以我们需要把这些东西聚集在一起。大多数情况下,这些系统不是从零开始创建的。我们几乎没有绿屏创业公司,至少在我的行业是这样。我们总是在用别的东西创造东西。所以我们总是把东西放在一起,提取两种不同的东西,把一些新的东西放在一起。所以无论何时我们这样做,我们经常会面临很多挑战,这些挑战来自于处理遗留应用程序。很多时候,你把不同的技术、不同的流程和不同的管道结合在一起,这些技术以前可能存在,也可能不存在。

我们今天要讲的是我最近在研究的一个这样的用例。

所以我只是个男人。好吧,我参加一个项目,他们说,嘿,马克,你能帮我创建这个小部件吗。然后我说,好吧,我要创建这个小部件。但是,你想要这个小部件是什么样子的呢?对我来说,我开始谈论非功能性需求。您知道,可用性、可靠性是最流行的非功能性需求。但我认为速度、生产力、可靠性、效率,所有这些——成本——我认为这些也是非常重要的非功能性需求。至少这些是我感兴趣的问题。但至少当我们进入项目时,至少在我的行业中,我们经常面临固定的需求、进度和预算,这显然有点问题。

所以你一开始就有很多限制。你不能彻底检查遗留架构,你需要很长的交付时间,你有很多人并不真正理解持续集成和持续交付。很多时候,当我参与一个项目时,我只是一个有很多想法的人。我唯一的能力就是说服别人。那么当你遇到这种情况时,你会怎么做呢?这就是我今天要讲的内容。

这是我们将要学习的内容的一个简短的大纲。它会涵盖到目前为止我们学过的很多东西。我们目前正在做什么以及我们将来要做什么。当我们经历这些的时候,我将会,[…]介绍一些我认为关于Artifactory的有趣的改进,以及将来Artifactory可能会考虑与我们合作的事情。

首先,像许多人一样,我们没有一个单一的版本控制系统。我们在这个项目中使用了多个版本控制系统。不仅仅是一家公司,我们经常有多家公司合作来创造我们所创造的产品。所以第一个想法是,当你有这么多不同的风投公司,这么多不同的管道,你如何让所有这些人在一个故事中共同发挥作用。Artifactory是我们的集成平台。我们并不关心你在版本控制系统中做了什么只要它是可重复的,可靠的,有标签的等等。我们真正关心的是说,好吧,无论何时您完成了您的东西,您都将把它转储到Artifactory中,这将是我们开始执行一些策略和约束等的地方。

我们所做的其中一件事就是使用Jenkins来完成我们的构建。Jenkins工作得很好,因为它可以跨多个版本控制系统工作。每当我们跨不同的版本控制系统进行构建时,我们所做的一件事就是将单个基线的所有输出转储到单个存储库中。所以这和你从不同的人那里听到的有点不同。在过去,几年前,我,像很多人一样,有一个存储库它有各种版本,各种分支,各种基线我个人发现要保持跟踪是相当有挑战性的因为你必须开始依赖IV状态或标签和其他类似的东西来描绘它最后你的版本号变得摇摇晃晃,对我们来说,我们同时维持着大约20到30个不同的分支。把所有这些都放在一个存储库中会让人非常困惑。

所以很快,在前面,我们决定一个存储库代表一个基线代表一个分支。所以不管你的版本控制系统来自哪里。不管你的分支名称是什么,或者Git和其他等价的版本控制系统,我们通过Jenkins构建输出到所有逻辑上在一起的东西,这些东西在逻辑上是同一个分支的一部分。我们将所有这些都转储到一个存储库中。

这恰好有一些很好的副作用。你知道,你可以在一个存储库中查看一个基线的所有内容,然后你可以有不同的存储库,其中有不同的基线。然后每当你看着部署时,这是超级简单的因为我们可以部署在一个URL和一个URL代表了一个存储库,我们不需要任何复杂的逻辑来找出哪些分支或者使用哪个版本或其他东西,我们只是去最新的从一个存储库,我们知道最新的,是我们所关心的基线。

因此,为了建立所有这些,第一个挑战是回答如何将我们的东西放入Artifactory的问题。这很有挑战性,因为不是每个人都使用支持发布和解决依赖关系的构建技术。我想这个问题在今天早上的主题演讲中已经提过了关于如何利用传统技术。好吧,我要举手说,我认为我们已经想出了一个相当不错的答案,它围绕着Gradle的使用。

因此,每当我们谈论短期解决方案时,我们谈论的是我们可以轻松地将自己注入到遗留应用程序中,而不必让它们改变它们的世界。我们想要一个温和的介绍,我们可以说,好吧,这是一个非常容易实现的目标。简单的第一步,您可以使用现有的构建。我们不想把它弄得太乱。我们只是想把你现在生产出来的任何东西都放到Artifactory里。

有几种方法可以做到。Gradle的第一种方法是一种非常粗糙的方法。这不是你通常用Gradle来做的事情。但我们使用它作为下载和上传存储库。在右上角的第一个用例中,你会看到我们使用Gradle作为下载管理器,并在其中表达依赖关系。我们下载它们,把它们推到某个目录,然后每当[…]构建启动时,它可以是perl脚本、makefiles、Ant,不管我们真正关心的[…]构建方式是什么。这对我们来说很好,因为我们根本没有碰你。我们把你的依赖放在你期望的正确的地方,然后在外面,一旦你完成了构建,我们意识到构建完成了,我们会发现那些构建输出是什么。也许我们可以用rpm或zip或其他方式打包。然后我们可以把它推到Artifactory中,这样它就真的把它变成了一个设置,一个执行,一个拆卸或一个发布阶段。

所以这适用于不太好的构建。我也有同感。但对于传统上用Ant编写的构建,它们是稍微更好的解决方案,因为Gradle句柄在其中集成了非常好的Ant。因此,对于我们的一些构建,我们只是简单地在Gradle中扩展Ant构建。所以我们直接使用Gradle执行Ant构建。Ant目标,转换为Gradle任务,我们使用相同的依赖项解析,将这些依赖项作为Ant属性注入。然后在外部,我们发布Ant输出,有时以不同的形式将其打包并发布到Artifactory。

作为一个直接的步骤,这非常有效,但我们发现,当人们开始对Gradle可以为你做什么有所了解时,当他们开始看到那里的dsl时。当他们开始看到来自它的约定以及Gradle转换是多么容易时,越来越多的人开始想要转换到Gradle。所以对于我们和我们的项目来说,我们的长期战略的一部分是转换到Gradle,只使用纯Gradle构建。所以我们做的其中一件事就是我们写了几个插件,为我们介绍企业或项目特定的标准,这非常好。但我们也支持一些非标准的东西。例如,我们的构建支持,在Windows和Linux上使用Gradle的c++原生构建。我们还支持Java代码生成,例如Jax B或Sequal J, Jax WS,或任何不同的Java代码生成工具。

这样做的一个好处是,在我们的构建端,我们得到的Gradle构建脚本除了依赖声明之外几乎什么都没有。因为我们的Gradle构建脚本完全依赖于你所声明的依赖关系,然后我们的企业插件会为我们处理所有其他的构建逻辑。不仅仅是构建逻辑,还有打包、发布、依赖项解析,所有这类事情都为你做好了。所以你最终会得到5行构建脚本,而不是,你知道,有20到30个不同的项目,每个项目都有自己的一套构建技术,每个项目背后都有数百或数千行构建内容。一个相当不错的过渡。

有多少人熟悉常春藤构型?甜的。好的。所以除了你,所有人都要上一分钟艾薇课。Ivy是一种非常好的依赖声明技术。它与Ant有很好的集成,与Artifactory和Pom文件也有很好的集成。我当然更喜欢常春藤,因为常春藤有一种叫做构型的东西。Ivy配置基本上是一个文件桶。所以当你发布文件时,你会说,好吧,我想储存某些文件这些文件以某种方式相互关联。因此,例如,公共桶是数据、编译时、运行时、配置工件、文档或源文件之类的东西。 So whenever you create packages, zips, rpms, whatever that aggregates these things into nice packages, you want to take those different files and put them into buckets and so for example all of your, you know, HTML documentation of your Java docs, all of your user guides and all that kind of stuff, you may want to put into a documentation configuration and that helps you be able to aggregate things together that go together well.

另一方面,在Ivy中,你实际上依赖于配置,所以当我表达对别人的依赖时,我想表达我对他们的配置的依赖,所以每当我表达依赖时,我都是在运行时声明或API上表达它。例如,如果你有一个公共API,那么你把所有的jar或共享库或任何东西放到你的API配置中,这让我依赖于你,但让我依赖于一个抽象。我不依赖于一个特定的文件名,我依赖于一个概念,API。无论何时你改变文件名,或者你改变基数,你决定从1到2或3到1等等,这不会破坏我,因为我唯一依赖的是我依赖于你的API的概念,你要定义那个API是什么。

所以我们用它。不仅仅是在构建时,这很好,我们也在部署时使用它。因此,每当我们部署东西时,我们不会在Artifactory中寻找特定的文件,而是寻找特定的模块,我们说我们想要部署该模块的运行时配置。所以无论何时你进入团队,他们可以在运行时配置中定义什么,可以是jar,共享库,配置文件,任何他们想要的东西。但是他们可以选择是什么,但这将我们从部署时间系统中抽象出来因为部署时间系统会变得有点愚蠢。它们并不关心,它们与组件本身的耦合并不紧密,它们只是与运行时的抽象本身耦合。因此,我们发现这是一种很好的方法,可以隔离我们的构建和部署系统,并让各个团队有权决定那是什么。讽刺的是,他们只需要配置build。Gradle就能找到答案。

(观众)

我们所做的。所以Gradle配置工作得很好,我们目前在部署时不使用Gradle,这是其中一个选择,而且Artifactory本身也不使用Gradle,所以每当我们进行构建时,我们的构建都会从Gradle配置本身生成一个Ivy xml。因此Ivy xml和Gradle构建脚本在逻辑上是等价的。就像常春藤和Poms经常是相互等价的。Ivy是Artifactory的母语,就像我说的,它往往是我们构建和部署之间的一个很好的桥梁。

因此,我们必须在系统中解决的下一件事是重用。我们发现我们有相当多的整体系统存在,你知道,我们有一些东西可以构建和部署一些东西,这是非常好的,但我们发现有些系统喜欢发布35g的zip文件,然后说,嘿,部署这个。我们会说,什么?我们对这个巨大的整体是什么有点困惑。更不用说还有很多补丁和诸如此类的问题。或者表示依赖关系。

所以我们开始做的一件事是说,嘿,我们需要了解你发布了什么服务,我们需要了解你的子系统是什么。我们看了一下迈克尔·费瑟的书,有效地使用遗留代码,它说,嘿,我们需要识别接缝是什么,并开始将这些接缝独立发布到Artifactory。其中一个挑战是我们经常发现子系统有很多意大利面条代码,有很多你不想乱动的遗留东西。所以我们面临的挑战是,如何解决暴露依赖关系。我如何在颗粒级上解决补丁问题,而不必解决过去15年的历史问题。我们找到的方法是通过使用,Ivy构型,以及一些技巧。

我来讲讲Ivy构型。例如,如果你有一个构建,创建了一个大的压缩包,我们鼓励人们说,嘿,你知道,拿你的构建,做你之前做的事情,但不是创建一个巨大的jar文件或其他什么,而是创建几个不同的文件。开始将其组件化为不同的部分。我们并不是要求你改变你的源代码,我们只是要求你改变你的构建来为我们创建更好的构建工件。然后在这些构建工件中,我们开始根据它们的目的将它们弯曲成不同的配置,这样我们就可以增加部署时间,然后我们可以根据我们的需求选择部署它的不同部分。

所以没关系,这并不棒。这样做的部分挑战是,无论何时在组件级别或配置级别进行更改,所有配置的版本号都保持不变。所以它们不能独立变化。一个稍微好一点的方法是通过简单地改变你的构建系统来使用相同的源代码,但是为它创建完全不同的构建。所以有时我们拿一个大的整体组件,我们说,好吧,我们实际上要,而不是创建一个大的,你知道,所有的构建之母,我们将有两个稍微小一点的构建,或者可能是10个更小的构建,它们将创建相同的单独输出,但每个都是独立的版本,可以变化,你不必-构建时间增加因为你不必等待其他所有东西。你有独立性。当其他人成功时,一部分人可能会失败。你不需要等到整个世界都开始工作。让你的小小改变进入宇宙。

因此,我们使用这些策略来确保我们不需要更改源代码,我们不需要重构世界,只是为了能够将模块化引入我们的Artifactory,以便我们可以让其他东西表达对它的依赖以及独立的模块化部署。

这是我认为我们围绕Artifactory做了一些非常有趣的工作的第一个领域。我们目前这个项目面临的挑战之一是我们要在25到30个不同的地方进行部署,大约有4个不同的云。我们涉及多个州,多个地点,地理位置。大量不同的用户。每个子系统都独立地为我们的基线做出贡献。我们以一种松散的方式合作,但我们每个人都有不同的时间表和不同的节奏。

所以我们面临的挑战之一就是跟踪到底发生了什么。除了电子表格和人类英雄主义,我们真的没有很好的机制来做到这一点。所以我们实际上引入了一个API——一个用于Artifactory部署的API。实际上,技术上它是两个api。

第一个API是通知API。我们的部署系统,无论何时它要部署一个模块,它要做的第一件事,当然是它要从Artifactory解析它。一旦它从Artifactory中解析出来,我们就会在一个我们在Artifactory中写的用户插件上调用一个通知API。那个通知API会告诉Artifactory谁,什么,在哪里,什么时候,为什么。它会讲到特定的文件名,版本。它将讨论部署的背景。它会给Artifactory提供很多不同的上下文信息。然后Artifactory用户插件将会获取这些并了解主机做了什么,哪里没有,它有多统一,它是哪个子集。所有这些信息都被提供给了它。它会在文件名和或与它相关的版本上创建一大堆Artifactory属性。

这对我们来说是一个非常强大的概念因为我们为它写了一个API,一个查询API。现在我们可以回到Artifactory,我们可以问它,对于模块Y的X版本,它被部署在哪里。或者对于这样那样的环境,在其中部署了什么。或者说在X天内没有部署的东西。或者这件藏物,还在使用吗。因此,我们从中得出了很多问题,我们发现这些问题非常有用。我将在几分钟内多讲一点。

我们对Artifactory进行了一些增强的下一个领域是元数据领域。Artifactory在构建输出方面做得很好。它还集成了Jira和其他敏捷生命周期管理工具。但是我们发现需要加强的一件事是Artifactory跟踪元数据的能力。

就像我之前的幻灯片,我们讨论了部署跟踪。我们当然发明了大量的属性来跟踪所有这些东西,但如果我们有一个第一级的概念对象叫做部署,就像第一级的构建对象一样,那肯定会更好。所以Jenkins和各种CI服务器都有一个非常好的构建信息对象,它有一组定义良好的信息。它具有与之相关的层次结构。它有很好的数据图。我们当然可以在部署方面使用它。

当我们谈论ALM工具或版本控制集成时,元数据跟踪方面也是如此。我们当然发明了自己的元数据来跟踪所有这些数据。但事实证明,所有这些物质之间都有相当紧密的关系。例如,变更集很大程度上依赖于正在开发的特性。在我们的世界里,我们决定我们不想部署特性,抱歉,我们不想部署版本号,我们想部署特性。因此,当我们向操作员或实际部署系统的人展示时,我们不想向他们展示一个版本号,我们不想向他们展示一个链集ID,我们想用他们的自然语言向他们展示他们可以部署的东西,他们所理解的可以追溯到我们的敏捷生命周期管理工具。所以我们选择部署特性,而不是版本号,也不是变更集id。

这里有一个图表关系描述了事物之间的关系实际上我们使用Artifactory元数据来跟踪不同系统的外键。如果你在使用Jira,我们有一个键,外键,它允许我们使用Jira的REST API。对于,我们使用rational[…]concert每当我们需要从它中找到信息时,我们使用它的REST API或它的公共API来查询它。因此,我们不会试图在Artifactory元数据中重新发明世界。我们尝试在Artifactory中放入足够的元数据,这样我们就可以跳转到另一个系统中去查找它的出色内容。

然后我们有仪表板,把所有这些一起呈现给宇宙。当然,你可以进入Artifactory,进入发布选项卡,在那里你可以找到构建信息选项卡。你可以找到类似的东西,当然,build info标签你可以跳转到Jenkins或Bamboo或其他地方去找到那个构建,这非常好。但我们发现,我们需要一个全面的世界观,它说,好吧,我们的部署如何,我们的特性如何,我们的链集如何,部署编排如何,所有这些如何组合在一起?外面有什么?什么没有被使用?使用的是什么?我如何知道我发现了一个错误,写一个不一致报告针对什么?所以这是一个-我们使用这种信息作为上下文线索,能够给我们的用户以他们的语言的信息,这样他们就不必在不同的生态系统工具之间跳跃。它们单独来说都很棒,但我们需要一些能说它们语言的更高层次的表示。

在过去的几天里,我听到了很多关于净化的挑战。所以,我也发现,净化是很有挑战性的。我们的数据存储,我们的存储就像其他人一样填满了。我们有一个存储库,里面有各种各样的东西,有些很棒,有些不是。那么,我们如何区分什么是优秀的,什么不是优秀的呢?我个人认为,选择宣布一个不优秀的东西是基于,你知道,它的日期,或者它已经10天了,或者它在X天内没有被下载过。我觉得这些都是不错的政策,但不一定是最好的政策。因为你决定用什么来净化是很随意的。

你知道,当然有詹金斯,在詹金斯清洗中配置政策。Artifactory插件。那太好了。Artifactory的内容,真的很不错。但我们发现,一旦我们引入了部署跟踪,它就开启了一种全新的策略,这对我们来说是前所未有的。我们想要使用并且正在开始使用的策略是根据不再使用的东西来清除东西。因此,与等待X天,只是希望它是不对的,或设置你的清除策略等待,你知道,一个月,知道名义上的东西不会在三天后使用,然后,你知道,27天,在这种你不确定的状态下,东西处于这种不稳定的状态。

我们根据不再使用的内容来清除内容,因此我们可以查询REST API,以便能够发现工件是否已经被使用过,最后一次使用它是什么时候,然后基于它最后一次实际使用的位置,当我说使用时,我指的是在部署时。所以最后一次它被真正的个人部署和使用在真实的环境中,无论是开发人员还是prod或其他什么,我们会跟踪所有这些,所以一旦一些东西在30天,60天之后没有被使用,不管那是什么,我们会把它移到垃圾桶里,然后我们让垃圾桶照顾它的自然清除策略。

一旦它最终从Artifactory中删除,我们就会拦截那个调用,并删除与之相关的Jenkins作业。所以我们想要确保的一件事是Jenkins和Artifactory总是同步的,我们总是跟踪实际使用的东西。任何我们不再需要的东西,我们都想处理掉。我们不想保留没有人再引用的一年的快照构建。能够跟踪我们拥有的不同子系统之间的数据对于清除策略来说是一个挑战,有时一个子系统可能一天发布5个东西,有时他们可能一周不发布一些东西,这取决于他们的构建和签入策略是什么样的以及诸如此类的东西。因此,能够根据所使用的内容来跟踪内容实际上对我们来说是一个相当强大的概念。

所以我们要开始研究的一件事就是如何提升各个子系统。所以如果你能想象,有25 30 40 50 60个不同的子系统在那里,其中一些是巨大的,一些是中等大小的,很少有很小的。所以把10万的代码看作是中等大小的系统,你知道,也许几百万行代码,用于一个35g压缩文件中创建的模块。所以我们面临的挑战是,好吧,我们每个人都是独立运作的,我们如何把一个真正有效的系统组合在一起。所以,我们不是在创造,60个单独的产品,最终我们交付给一个客户,一个系统,有一大堆与之相关的功能hth华体会最新官方网站,所以我怎么知道这个子系统实际上与这个子系统集成。

我们可以用几种不同的方法来解决这个问题。第一种方法是使用语义版本控制。语义版本控制有几个挑战,但我们目前认为它的勇气——它的优点值得投资。因此语义版本控制解决了确保物理接口绑定在一起的问题。所以我知道不兼容的变化不会被解决到相同的构建中,它们不会在相同的部署中得到解决。我们保证使用语义版本控制,这很好。但是,我们面临的一个挑战是,有很多非物理的方式,东西不能工作,所以,你知道,仅仅因为你有一个Java API,你把它们连接在一起,这并不一定是我们的接口连接在一起的唯一方式。我们的很多接口都是通过JMS,或者消息键,或者web服务,或者任意数量的文件系统,或者ftp,或者任意数量的其他类型的接口来实现的,语义版本控制并不适合这些接口。因此,我们面临的挑战之一就是,当你实现并测试了一个我需要利用的接口时,我们如何识别。

这就是多阶段推广的由来。在我们当前的系统中,我们实际上有五种不同类型的发布。第一种类型的发布是当这些独立的20到60个不同子系统中的每一个都进行它们的测试时。这就是传统意义上的CI。所以你经历了一个单独的组件测试阶段,他们站在另一边,竖起大拇指,我们在这里面做了一个传统的Artifactory推广。

所以我们的每一种其他类型的面部阶段都涉及到某种类型的提升,我们将这些不同的成分聚集在一起。所以,你知道,这里的这5个已经完成了测试,这里的这3个已经完成了测试,现在我想把8个一起测试在一个单一的里面。我们怎么知道它是多少呢?我们使用Artifactory元数据来识别哪些东西通过了测试,哪些没有,然后我们运行基于AQL查询的推广,能够找出哪些东西值得放在一起,这样我们就能弄清楚,嘿,这些东西正在一起被推广到一个存储库中,我们将测试这些,我们将给它们,一旦它们通过了推广,通过了测试,我们就会推广它们。然后也许这8个和这15个放在一起,然后我们把这些东西按层聚合在一起,直到我们达到最高的级别,我们有60个在一起玩得很好。

好的,这是我们发现的第三个非常有趣的概念,我们要进行实验。这实际上是弗雷德的一个想法,但我们要在这里迈出一步,看看它是否可行。所以无论何时我们发布到Artifactory,当然,Artifactory创建并跟踪校验和,sha和[…]。所有这一切都很棒。然而,如果您要查看构建磁盘,您会发现对于您推上去的大量工件和包,磁盘总是不同的,即使它们在逻辑上是相同的。为什么它们不同?时间戳,校验和,用户名和其他类似的东西,这不会影响现实世界的执行。它不会影响界面,但它所做的是干扰你的校验和,使两个东西变得不正确。这就产生了很多困惑,一路上有很多挑战。

我们感兴趣的是看看这个叫做真校验和的东西。我们要做的是在构建时,我们要看一个包,一个压缩包,一个罐子,一个共享库,等等,我们会允许构建时技术声明true校验和是什么。现在,真正的校验和基本上是一个排除列表。不要看jar文件中的元NSF,可能会忽略其中的rpm头。我不知道具体会是什么样子,但我们会给人们,也许我们会给他们正则表达式来忽略清单的某些部分。但是我们将给他们一些能力,在创建的包中声明什么是重要的,什么是不重要的。

作为构建的一部分,我们会创建真正的校验和,我们会在它发布到Artifactory时标记它。嗯,这实际上是有趣的部分,这就是Artifactory方面的作用。我们在Artifactory端要做的一件事是有一个用户插件我们要查询它,它是否为真校验和,它是否已经存在于Artifactory中。因为如果它已经存在于Artifactory中,那么我们就不会在那里发布这个东西,因为我们只是要重用先前存在的工件,因为真正的校验和表示逻辑上等价的两个东西。真实世界的行为是相同的,即使它们的部分元数据可能由于构建输出而不完全相同。

因此,如果Artifactory中已经存在某些东西,我们不会将其部署到Artifactory中,我们只是在那里重用它。然后在构建时间结束时,如果构建没有任何变化,那么我们就不会将构建发布到Artifactory。我们只是要重用一些之前已经存在的构建。这将解决很多问题,至少我们希望它能解决我们的一些问题,因为我们的构建倾向于生成一大堆东西。我们的下游依赖倾向于构建一大堆东西,并将一大堆东西发布到Artifactory,这些东西实际上并不需要,因为它们在逻辑上已经存在。我们没有引入变更集,我们只是重新构建东西来验证上游行为。所以我们希望这将解决这个问题,同时减少我们后端数据库的负载,以更新那些实际上没有必要的东西。

我们还有一个问题是试图跟踪需求,所以我谈到了逻辑上一起发生的事情,至少在我们的世界里,我不知道你们的世界,但在我们的世界里,我们处理成百上千的需求文档。从指定接口中指定的所有东西,客户给我们的东西,内部生成的,外部生成的,各种各样的东西,所以我们必须声明合规。

因此,我们将要探索的事情之一是如何同时发布软件和文档,其中包括用户指南,以及需求和接口规范。我们CM如何以同样的方式同时控制这两者呢?因为对我来说,我们发布软件,我们有一些相当复杂的方法来处理它。但是我们的文档管理和需求管理,至少落后了几十年。而且他们的待遇也非常不同。因此,试图在它们之间画出可追溯的线是相当具有挑战性的,我认为发布和CM控制文档,构建它们,发布它们,并使用软件推广它们是一个非常有趣的概念,我们将探索。

最后我们要讲的是,快结束了,听析。一旦你在Artifactory中完成了所有这些,就能够创建版本描述文档,并能够说,在哪里部署了什么,谁部署了,以及所有这些事情都非常简单。

我就讲到这里,给你们几分钟的提问时间但我想让你们记住的两点是,我们工作在一个不完美的世界里。我们不是在绿色屏幕的土地上工作,在那里每个人都是一些,你知道,超级善意的人,总是想要克服,想要持续整合,持续交付。我们有各种遗留的挑战,但我们有一个管道。我们正在采取一些步骤,向人们介绍持续集成,持续交付管道。这是比以前更好的东西。

它并不完美,但也许在5年或10年后,我们将达到这样的地步:我们可以将这些分解为微服务,公开粒度服务,并进行自动化测试,所有这些都是一个先决条件——作为真正在一个定义良好的管道中开始工作的下一步。

我们做的方法很简单,我们只是去看看什么着火了,我们去解决那些实际可行的问题,然后我们转过身来,我们只是再次问同样的问题,什么着火了,我们如何解决它。一直这样迭代,直到我退休。

就是这样。

要么快速释放,要么死亡