【发布时间】:2020-07-15 10:16:21
【问题描述】:
我希望 maven 报告具有以下结构的多模块 maven Java 项目中未解决的依赖关系:
multi-module-java-app/
├── app1
│ ├── pom.xml
│ └── src
├── app2
│ ├── pom.xml
│ └── src
└── pom.xml
pom 在底部。
背景:
Maven 被用作依赖管理和构建工具。 Artifactory 是存储库管理器。工件可以在开发人员的环境或 Jenkins 构建服务器上使用本地 maven 构建。 Artifactory 会定期将工件移动到特殊的 archive 存储库,该存储库是 all 虚拟存储库的一部分。
Maven 将本地构建的工件缓存在运行 Maven 的计算机上的 ~/.m2 目录中,无论是开发人员环境还是构建服务器。
问题
可能会出现几个问题:
在开发人员的虚拟机上进行本地构建可能会成功,但在 Jenkins 中会失败。
本地构建,Jenkins 构建可能会成功,但在其他开发人员的 VM 上会失败。
原因
开发人员 .m2 缓存中存在/缺少工件,构建服务器的 .m2 缓存和/或 archive Artifactory 存储库中缺少工件
建议的解决方案
运行[path_to_maven]mvn dependency:list。 [path_to_maven] 在项目的根文件夹中有自定义 maven 安装(带有空的 .m2 缓存)。 自定义 maven 还使用 settings.xml 配置为使用特殊的 non-archived 存储库(all 存储库没有 archive)。
输出如下:
它报告未解决的依赖关系以及遗漏它们的依赖工件。 然而,这种解决方案有两个主要缺点:
- .m2 缺失会显着减慢检测速度,因为必须下载所有依赖项
- 未解决的工件或缺少它们的模块始终是快照。
运行mvn -B -q versions:set -DnewVersion=[some_version] 解决了第二个问题。无论如何,此命令在发布管道期间运行。
但不清楚如何解决第一个问题。
如何在使用.m2时找到未解决的maven依赖,以便在每次推送到特性分支后在Jenkins构建过程中快速检测到未解决的依赖?
唯一的想法是构建服务器上的 .m2 将与 Artifactory 同步。
.m2 在开发人员的机器上也可以使用某种使用 rsync 的自定义插件进行同步。有没有已知的插件可以做到这一点?
最终目标是删除archive 存储库并让构建失败。但是,首先开发人员需要将依赖项与最新版本保持一致。
根 pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany.app</groupId>
<artifactId>multi-module-java-app</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>multi-module-java-app</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<pluginRepositories>
<pluginRepository>
<id>plugins</id>
<name>plugins</name>
<url>http://localhost:8081/artifactory/all</url>
</pluginRepository>
</pluginRepositories>
<repositories>
<repository>
<id>all</id>
<name>all</name>
<url>http://localhost:8081/artifactory/all</url>
</repository>
</repositories>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>spring-boot</artifactId>
</dependency>
</dependencies>
</dependencyManagement>
<modules>
<module>app1</module>
<module>app2</module>
</modules>
</project>
应用 1 pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.mycompany.app</groupId>
<artifactId>multi-module-java-app</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>com.mycompany.app.app1</groupId>
<artifactId>app1</artifactId>
<version>1.0-SNAPSHOT</version>
<name>app1</name>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<finalName>${artifactId}</finalName>
</configuration>
</plugin>
</plugins>
</build>
<pluginRepositories>
<pluginRepository>
<id>plugins</id>
<name>plugins</name>
<url>http://localhost:8081/artifactory/all</url>
</pluginRepository>
</pluginRepositories>
<repositories>
<repository>
<id>all</id>
<name>all</name>
<url>http://localhost:8081/artifactory/all</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>spring-boot</artifactId>
<version>0.0.1-20200510.095344-1</version>
</dependency>
</dependencies>
</project>
app2 pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.mycompany.app</groupId>
<artifactId>multi-module-java-app</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>com.mycompany.app.app2</groupId>
<artifactId>app2</artifactId>
<version>1.0-SNAPSHOT</version>
<name>app2</name>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<finalName>${artifactId}</finalName>
</configuration>
</plugin>
</plugins>
</build>
<pluginRepositories>
<pluginRepository>
<id>plugins</id>
<name>plugins</name>
<url>http://localhost:8081/artifactory/all</url>
</pluginRepository>
</pluginRepositories>
<repositories>
<repository>
<id>all</id>
<name>all</name>
<url>http://localhost:8081/artifactory/all</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>spring-boot</artifactId>
<version>0.0.1-20200510.095344-1</version>
</dependency>
</dependencies>
</project>
【问题讨论】:
-
哇,这是一个学术背景。问题 1 的一部分是,它根本不是问题。这就是 Maven 的工作原理;您从空的本地 pom 开始,它会解析您列为依赖项(以及传递依赖项)的内容。你想要的是
dependency:analyze。这使您的 pom 与您的进口保持一致。干净的 pom 是要走的路。您还可以通过在根 pom 中指定 GAV 依赖项来保持模块版本对齐,但在子模块中仅指定 GA 依赖项。 -
我不确定为什么开发人员存储库和工件之间存在这种差异。开发人员是否在本地构建和安装尚未发布的依赖项?
-
@tgdavies 是的,父模块和模块在 pom.xml 中有 SNAPSHOT 版本,开发人员需要在推送到功能分支之前验证本地构建是否通过,之后将在 Jenkins 中触发构建,如果未解决应该会失败找到依赖项
-
我还不明白为什么你不能等到 Jenkins 构建完成。如果依赖项缺失,Jenkins 构建失败,开发者可以修复问题。
-
@JF Meier。这是因为 .m2 缓存存在于 Jenkins 构建服务器和开发人员的机器上。它可能有存档的工件,但 Jenkins .m2 可能没有,反之亦然。即使在不同的开发者机器之间也可能存在 .m2 缓存差异
标签: java maven jenkins artifactory maven-dependency-plugin