如何让 Hudson 正确构建由单次提交更改的多个模块

发布于 2024-12-07 10:55:16 字数 736 浏览 6 评论 0原文

考虑一个具有多个相互依赖的模块的 Maven 项目:比方说,三个 jar 模块 A、B 和 C,它们是 war 模块 Z 的依赖项。我为每个模块都有一个单独的 Hudson 构建,因此只有已更改的模块是重建的。

我的问题是,如果我提交一个更改模块 A 和模块 Z 的变更集,则 Z 可能在 A 之前构建并失败,然后在 A 完成并触发 Z 的重建(现在已通过)之前。允许构建经常因为与构建顺序有关的原因而失败,而不是“真正的”失败,这会让我们对真正的失败变得不敏感;我们最终会忽略那些已经合理损坏的构建,因为我们习惯于假设它最终会恢复正常。

我一直通过使用安静期、在上游构建运行时阻塞等来管理此问题。但实际上,我的构建比我给出的示例具有更多的模块,其中许多模块需要一段时间来构建和测试。我还有一小群勤奋的开发人员经常进行提交。

这意味着我的 jar 模块会不断构建,很少为我的 war 模块的构建留下间隙。因此,战争不会经常发生,这意味着我们需要很长时间才能找出破坏它的时间,也需要更长的时间才能确定是哪个变化破坏了它。

另外,构建的持续运行意味着,如果我提交涉及 jar A 和 B 的更改,则可能会为 jar A 构建一次 war 文件 Z(构建速度很快),然后再为 jar B 构建一次(需要更长的时间)。这使得很难理解给定提交的结果。

我考虑过使用 join 插件,但这似乎需要每次都构建所有模块。因为我实际上有相当多的 jar 模块,所以我真的不想每次都构建它们,我只想构建针对给定提交更改的模块。

有没有更好的方法来处理这个问题?

谢谢

Consider a Maven project with multiple interdependent modules: let's say, three jar modules A, B, and C, which are dependencies for a war module Z. I have a separate Hudson build for each of these modules, so that only modules that have changed are re-built.

My issue is that if I commit a changeset that changes both module A and module Z, Z may be built before A and fail, before A completes and triggers a rebuild of Z which now passes. Allowing builds to regularly fail for reasons to do with build ordering rather than "real" failures desensitizes us to real failures; we end up ignoring builds which have legitimately broken because we are used to assuming it will eventually flip back.

I have been managing this through the use of quiet periods, blocking when upstream builds are running, etc. But in practice, my build has more modules than the example I've given, many of which take a while to build and test. I also have a small horde of diligent developers making frequent commits.

This means my jar modules are constantly building, only rarely leaving a gap for my war module(s) to build. So the war doesn't build very frequently, meaning it takes a long time to find out when we've broken it, and also takes longer to identify which change broke it.

Also, the constant running of builds means that if I commit a change that touches jars A and B, the war file Z may be built once for jar A (which builds quickly), and then again for jar B (which takes longer). This makes it hard to understand the results of a given commit.

I've considered using the join plugin, but this appears to require all of the modules to build every time. Since I actually have quite a few jar modules, I really don't want to have to build them all every time, I only want to build the ones that have changed for a given commit.

Are there any better ways to handle this?

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

泅人 2024-12-14 10:55:16

这始终是一个难题(我已经不止一次地重写了这个答案!)

就技术解决方案而言,您需要一些能够等待多个不同作业的构建在开始运行之前不运行的东西。如果难以量化,就很难落实到位。我非常有兴趣了解该主题中建议的技术解决方案。

我想你必须看看你的工作运行的原因和频率。如果您的 WAR 中有任何代码需要进行单元测试,您能否将其移至其自己的模块中?这样,您就可以使用 war 每小时/30 分钟运行一次集成测试,而不必担心各个模块的位置和时间。

您可能还想查看您的模块包含的内容。它们都必须是模块吗?您是否可以减少碎片 - 它可能有助于减少您尝试安排的复杂性:)

我理解并赞赏您为尽快进行尽可能多的测试所做的努力 - 但有时,如果有的话,烟雾测试就是您所能做的不断地搅动代码。

This is always a difficult problem (and I've re-written this answer more than once!)

In terms of a technical solution, you want something that will wait for the build of several different jobs to be not running before it starts to run. If it's difficult to quantify, it's going to be difficult to put in place. I'll be very interested to see what technical solutions are suggested in this thread.

I guess you have to look at why your jobs are being run, and how often. If there's any code that requires unit testing in your WAR, could you move it out into it's own module? That way you can run only integration tests every hour/30 mins using the war and not worry about where and when the individual modules are at.

You may want to also look at what your modules contain. Do they ALL have to be modules? Can you perhaps reduce the fragmentation - it might help reduce the complexity of what you are attempting to schedule :)

I understand and applaud your efforts to get as much tested as soon as possible - but sometimes a smoke test is all you can do if there's a constant churn of code.

萌酱 2024-12-14 10:55:16

我们现在考虑的方法是将一些 Maven 模块组合到单个 Hudson 作业中,而不是模块到作业的一对一映射。

具体来说,如果 war 模块的依赖项相当小并且可以快速自行构建,则在与 war 相同的作业中构建它们可以确保单个提交中的所有代码都构建在一起,至少对于给定的 war 文件而言是如此。

这确实会导致重复 - 我们有多个使用相同 jar 的 war 文件,因此基本上会为每次 war 重建这些 jar,而不是只重建一次。但在实践中,jar 的构建速度很快,这使得 war 文件在概念上更清晰。

如果 jars 需要一段时间来构建和测试,那么这将不太有吸引力,因为 jars + war 工作的组合会相当长,给我们 jars 内的问题提供很长的反馈循环。取得正确的平衡很重要。

所以我的结论是:不要认为每个模块一个 Hudson/Jenkins 作业是最好的方法,并且不要害怕在多个作业中重建相同的代码。

The approach we're now looking at is combining some Maven modules into single Hudson jobs, rather than having a one to one mapping of modules to jobs.

Specifically, if a war module's dependencies are fairly small and quick to build on their own, building them in the same job with the war ensures that all of the code from a single commit is built together, at least for that given war file.

This does result in duplication - we have multiple war files using the same jars, so the jars are essentially rebuilt for every war, rather than once only. But in practice, the jars are quick to build, and this makes the war files conceptually cleaner.

This would be less attractive if the jars took a while to build and test, since the combined jars + war job would then be quite long, giving us long feedback loops for problems within the jars. Getting the balance right is important.

So my takeaway: don't assume that one Hudson/Jenkins job per module is the best way to go, and don't be afraid to rebuild the same code in multiple jobs.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文