Apache Ivy 和本地 Maven 存储库 - 如何处理使用 Maven 3 构建的快照

Apache Ivy and local Maven repo - how to handle snapshots built with Maven 3

我们目前有一个项目设置,使用 Ivy 进行依赖管理,使用 Ant 作为通用构建工具(尽管这可能与此无关)。此外,我们有一堆库是用 Maven 构建的,项目(我们有多个)依赖这些库。我们知道这种情况远非理想,我们正在评估改善这种情况的方法,但我们无法像我们希望的那样快速改变这种情况。因此,我们必须利用目前拥有的资源。

无论如何,这就是问题所在:它与 Maven 2 和 Ivy 一起工作,但我们最近开始切换到 Maven 3 有几个原因(一个是更好的冲突解决)并且这种组合破坏了我们的构建。

首先,我将尝试描述我们的构建如何与 Maven 2 和 Ivy 一起工作。之后,我将添加切换到 Maven 3 时出现问题的地方。

Ivy + Maven 2

在开发新版本的库时,我们使用的是安装在本地 Maven 存储库 (.m2) 中的 SNAPSHOT 版本。此外,我们将这些快照部署到我们的 Artifactory 中,以便能够共享中间构建以实现一些并行开发。

然后我们的项目声明对这些快照的依赖。相应的 ivysettings.xml 看起来像这样:

<ivysettings>
  <settings defaultResolver="default" />
  <include url="${ivy.default.settings.dir}/ivysettings-local.xml" />
  <resolvers>
    <ibiblio name="public" root="path.to.our.artifactory" m2compatible="true" />

    <filesystem name="local-maven2" m2compatible="true" checkmodified="true" changingPattern=".*SNAPSHOT">      
      <ivy pattern="${user.home}/.m2/repository/[organisation]/[module]/[revision]/[module]-[revision].pom" />
      <artifact pattern="${user.home}/.m2/repository/[organisation]/[module]/[revision]/[artifact]-[revision](-[classifier]).[ext]" />
    </filesystem>
    <filesystem name="local" checkmodified="true" changingPattern=".*SNAPSHOT">
      <ivy pattern="${ivy.local.default.root}/${ivy.local.default.ivy.pattern}" />
      <artifact pattern="${ivy.local.default.root}/${ivy.local.default.artifact.pattern}" />
    </filesystem>
    <filesystem name="local2" checkmodified="true" changingPattern=".*SNAPSHOT">
      <ivy pattern="${user.home}/.ivy2/cache/[organisation]/[module]/ivy-[revision].xml" />
      <artifact pattern="${user.home}/.ivy2/cache/[organisation]/[module]/[artifact]-[revision].[ext]" />
    </filesystem>

    <chain name="default" checkmodified="true" changingPattern=".*SNAPSHOT">
      <resolver ref="local" />
      <resolver ref="local-maven2" />
      <resolver ref="public" />
    </chain>
  </resolvers>
  <include url="${ivy.default.settings.dir}/ivysettings-shared.xml" />
</ivysettings>

由于这个设置,Ivy 应该寻找更新版本的快照并正确解析它。通过比较相应 .pom 文件的文件日期来识别较新的版本。

当我们使用 Maven 2 构建快照时,相应的 .pom 将获取当前构建的文件日期,因此该检查有效并且 Ivy 解析正确的快照版本。

Ivy + Maven 3

当使用 Maven 3 构建快照时,上述解决方案中断。原因似乎是安装的 .pom 文件没有将当前时间戳作为其文件日期,而是保留了原始文件的日期 pom.xml 即被复制。因此Ivy无法检测快照是否更新了。

似乎 Maven 3 将更新时间戳存储在 maven-metadata-local.xml 中,但 Ivy 不读取这些。我们知道有 ibiblio 解析器(我们正在使用),但根据我们所知(例如 之类的问题),它旨在与真正删除的存储库一起使用,并且在应用于本地时可能会产生问题.m2 回购。

我们还考虑过跟踪其他文件的文件日期,例如maven-metadata-local.xml 或实际工件,但我们不确定这是否明智或是否会在其他情况下破坏构建。

那么 should/could 我们如何解决这个问题?

TL;DR

处理 Ivy 对使用 Maven 3 构建并部署在本地 .m2 存储库中的快照的依赖关系的 standard/suggested 方法是什么?

更新 2016-07-26

以下是我尝试解决问题的两件事,但我不确定是否会有任何我没有想到的副作用。如果有人能对此有所说明,我将不胜感激:

  1. 对本地 .m2 存储库使用文件系统解析器,但与具有 useOrigin="true"(以及可选的低 defaultTTL)的缓存结合使用。这样一来,似乎只有 xml 文件存储在 .ivy2 缓存中,并且在 .m2 存储库中引用了工件,即它们没有被复制。

    这似乎可行,但我不确定如果第一次查找会从共享快照存储库 (Artifactory) 下载快照并且稍后会由本地构建更新这些快照,它是否可行。在那种情况下,我们可能最终将工件的远程版本缓存在 .ivy2 中,并将较新版本安装到 .m2 中,并且 .pom 文件日期在这两种情况下都相同。
  2. 将 ibiblio 解析器与 root="file://${user.home}/.m2/repository/" 一起使用,它似乎能够解析大多数工件(例外情况见下文)但在读取元数据时似乎仍然失败,即它不会使用较新的更新缓存可在 .m2 存储库中找到的版本。

    虽然能够解析 .m2 存储库中的大多数工件,但我似乎遇到了一些 "urls" 的解析错误,例如 file://{user.home}/.m2/repository/javax/enterprise/cdi-api/1.0/cdi-api-1.0.jar 而工件存在,即我直接从 Windows 复制了路径资源管理器,它是 "${user.home}\.m2\repository\javax\enterprise\cdi-api.0\cdi-api-1.0.jar".

... We know that this situation is far from ideal and we're evaluating ways to improve that but we can ...

根据我的经验,这完全正常。许多大公司有很多项目混合使用 ANT、Maven 和越来越多的 Gradle。

以下是我会提出的一些建议

使用存储库管理器

集成这些不同技术的最佳方法是运行 一个中间存储库来保存所有构建输出。这将有效地将您的构建步骤与稍后使用二进制工件的方式分离开来。

推荐的存储库技术是 Maven 存储库(Java 目前是标准),您可以选择可用的开源技术来托管您的存储库:

虽然 运行增加一台额外的服务器可能看起来是一种开销,但随着依赖项目数量的增加(拥有一个大型共享文件系统无法扩展),它会得到回报。

在任何情况下,您都需要一份发布二进制文件的参考副本。这些 Maven 存储库管理器允许您控制您的项目使用的第三方依赖项并有助于缓存文件,这实际上会减少您的构建时间并简化共享依赖项管理。

最后,如何配置使用 Maven 存储库的 ivy 构建?如下使用 ibiblio 解析器(你会发现所有现代 Java 构建工具都对本地 Maven 存储库有类似的支持)

<ivysettings>
    <settings defaultResolver="myrepo"/>
    <resolvers>
        <ibiblio name="myrepo" m2compatible="true" root="http://myrepo.com/path/to/repo"/>
    </resolvers>
</ivysettings>

谨防快照发布

Snaphot 发布是 Maven 引入的一个概念,它是一个自以为是的构建框架。在我看来,使用它们时应该非常慎重:

  • Snapshots are for Dev, Release Candidates are for QA

正如您所发现的,快照在不断变化,在与期望测试结果不变的团队(如 QA)共享时不能依赖快照。

我对此的想法受到以下讨论发布管理 Maven 方法的帖子的影响:

最后,虽然我建议将快照的使用限制在密切协作的团队中,ivy 确实支持它们,但它们的使用有一些众所周知的限制。因为它们是 Maven 构造,所以它们不是 100% 由其他构建技术支持。这是存储库管理器真正有用的地方,因为他们能够重新生成正确的元数据以支持快照发布:

  • What's wrong with this Ivy changingPattern / SNAPSHOT configuration?
  • Publishing Ivy SNAPSHOTS with Maven metadata

希望这对您有所帮助。