JVM Advent Calendar:使用Gradle构建Monorepo项目

没有复合构建的生活

让我们假设您刚刚开始在一个项目保存在单个存储库中的公司工作。每个项目都有一个单独的构建,它们之间唯一的关系是彼此依赖,因为它符合他们的需求。有些项目的依赖性比其他项目更多,有些项目甚至可能与其他项目没有依赖关系。

项目数量很重要; 当它很低时,你可以说它们都可以放在一个伞形项目下,就像用Maven及其反应堆功能完成的那样。Gradle有类似的功能; 除了,在不触发所有其他项目的情况下,更容易定位特定构建。在某种程度上,你可以说Gradle的反应堆更智能,并选择要执行的目标。

但是当一个项目数量超过十几个时,会发生什么呢,比如几百个呢?即使使用更智能的反应堆,Gradle也必须阅读所有项目的配置,然后解决相应的目标。这肯定会花费你日常工作的宝贵时间,这是一个很大的禁忌。

解决方案是将每个项目分解为单独的构建。反应堆功能已经不复存在; 因此,我们不必为阅读和配置所有项目付出代价,以后再丢弃大部分项目。但是,现在,当依赖项可能引入了错误或二进制不兼容时,我们失去了做出反应的机会,这是在monorepo中组织代码的原因之一。

现在,我们必须遵循旧的和尝试过的工作流程:

  • 对依赖项目进行更改。

  • 构建工件并将工件发布到存储库。大多数人依赖快照工件。

  • 确保依赖项目使用新发布的工件/快照。

  • 编译并运行测试以确定代码是否再次运行。

  • 冲洗并重复直至其工作。

这种方法的问题在于我们浪费时间发布中间工件,并且有时我们会忘记发布快照发布并在调试会话中花费数小时,直到我们意识到二进制文件不正确为止。

复合材料构建到救援

现在让我们看看Composite Builds如何解决我们自己遇到的问题。我们首先看一下以下项目及它们之间的依赖关系。

PROJECT1

Project2 < - 依赖 - Project1

Project3 < - 依赖 - Project2

这个小的依赖图告诉我们,对Project1所做的任何更改都会影响Project2,因此也会影响到Project3。这是因为对Project2的更改也会影响Project3。这个monorepo的目录结构如下所示:

├ ─ ─  PROJECT1
展示│    └ ─ ─  构建。gradle这个
├ ─ ─  项目2
展示│    └ ─ ─  构建。gradle这个
└ ─ ─  项目3
    └ ─ ─  构建。gradle这个


在这里,我们可以看到三个项目及其各自的构建文件。每个项目都有自己的发布生命周期和版本,我们可以在他们的构建文件中观察到

PROJECT1 /的build.gradle

apply  plugin: 'java'

group    =  'com.acme'
version  =  '1.0.0'


项目2 /的build.gradle

apply  plugin:'java'

group    =  'com.acme'
version  =  '2.3.0'

依赖 {
    编译 'com.acme:project1:1.0.0'


项目3 /的build.gradle

apply  plugin:'java'

group    =  'com.acme'
version  =  '1.2.0'

依赖 {
    编译 'com.acme:project2:2.3.0'
}


激活Composite Builds功能需要在名为settings.gradle的文件中配置项目之间的链接。项目2和3需要此文件; 因此,我们的存储库看起来像这样:

├──  项目1
展示│    └──  构建。gradle这个
├──  项目2
展示│    ├──  构建。gradle这个
展示│    └──  设置。gradle这个
└──  项目3
    ├──  建造。gradle这个
    └──  设置。gradle这个


接下来,我们写下项目之间的链接,如下所示:

项目2 / settings.gradle

includeBuild  ” ../project1'


项目3 / settings.gradle

includeBuild  ” ../project2'


大。有了这个设置,我们现在可以通过发出以下命令来构建Project3:

$ cd project3
$ pwd
的/ tmp /项目3
$ gradle课程
>任务:proce***esources
>任务:project2:proce***esources
>任务:project1:compileJava
>任务:project1:proce***esources
>任务:project1:类
>任务:project1:jar
>任务:project2:compileJava
>任务:project2:类
>任务:project2:jar
>任务:compileJava
>任务:课程


您可以理解,project1和project2都是构建的。在project1中进行更改并在project3上触发构建,将再次按预期构建所有三个项目。现在,想象一下将这个monorepo增长到几十个或几百个项目,你很快就会意识到没有必要拥有快照版本,如果有的话。Gradle还有其他功能,例如输入/输出的任务缓存,这使得构建更快。同样,最近公布的构建缓存功能通过“交换”由CI场中其他节点计算的输出来加速构建。


猜你喜欢

转载自blog.51cto.com/14009535/2330565
JVM