Maven 通过存储库定义从项目依赖项中排除插件

maven exclude plugin from project dependencies by repository definition

我正在评估用于构建公司软件的 Maven。 我的特殊情况是所有允许在生产中使用的工件都受到限制。

批准的库在一个特殊的存储库中维护(在 Artifactory 实例中)。

虽然最终产品受到限制,但我们可能会使用更多的依赖项来构建(maven 插件及其依赖项的限制较少)。

所以我在 pom 和 pluginRepository.

中配置了 repository 部分

现在的问题是所有已解决的工件(对于插件和项目)都只缓存在一个本地 repository/folder 中。 如果有人不小心将编译依赖项添加到任何仅在缓存中的项目,因为 maven-plugin 它将在没有任何警告的情况下使用。

我删除了本地存储库并重新编译了测试项目,但由于无法解析的依赖关系,构建失败了。

我在网上搜索过,但没有找到这个问题的具体答案。 maven 上有一个待处理的请求,用于分离每个存储库的本地缓存,但这似乎只在审查 maven 4 状态: https://cwiki.apache.org/confluence/display/MAVEN/Local+Repository+Separation

https://issues.apache.org/jira/browse/MNG-3655 https://issues.apache.org/jira/browse/MNG-4302

maven-enforcer-plugin 在这里有一个关于 bannedDependencies 的概念,但这需要广泛的配置才能开始,理想情况下我想跟上当前批准的版本而无需手动交互.

有什么想法吗?我错过了配置吗?

更新 1:

好吧,即使尝试列出 enforcer 插件中所有允许的依赖项对我来说也不起作用:

   <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
        <version>2.2</version>
    </dependency>
    ...
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-enforcer-plugin</artifactId>
            <version>1.4.1</version>
            <executions>
                <execution>
                    <id>enforce-versions</id>
                    <goals>
                      <goal>enforce</goal>
                    </goals>
                    <configuration>
                        <rules>
                            <bannedDependencies>
                                <excludes>
                                    <exclude>*:*</exclude>
                                </excludes>
                                <includes>
                                    <include>commons-io:commons-io:1.4</include>
                                    ...
                                </includes>
                            </bannedDependencies>
                        </rules>
                        <fail>true</fail>
                    </configuration>
                </execution>
            </executions>
        </plugin>

此处构建应该会失败,但是 [INFO] BUILD SUCCESS

更新 2:

更令人惊讶的是,在 maven 文档中,这个问题已经被解决,并在版本 3 中进行了更改: https://cwiki.apache.org/confluence/display/MAVEN/Maven+3.x+Compatibility+Notes#Maven3.xCompatibilityNotes-ResolutionfromLocalRepository

Resolution from Local Repository The local repository used by Maven 3.x has been enhanced to keep track from what remote repositories an artifact was resolved from. This information about an artifact's origin is used to ensure builds can only access locally cached artifacts if they have the proper repositories configured. Hence, projects that lack required remote repositories in their POM might fail when being built with Maven 3. This improves reproducibility of a build by eliminating the effects of unintended artifact sharing via the local repository.

好吧,我终于明白是什么导致了我的头痛。 首先,我想要一个独立的项目。没有特殊用户 settings.xml 到 运行(如果您需要切换,镜像会阻止其他项目继续工作)。

正如我所说,我不希望该构建使用他不允许的工件,因此我必须重新配置 Maven Central 以使其无法访问。 所以这就是我的方法:

<repository>
  <id>central</id>
  <url>http://${company-repo-manager}/${project-repository}</url>
</repository>
...
<pluginRepository>
  <id>central</id>
  <url>http://${company-repo-manager}/${plugin-repository}</url>
</pluginRepository>

我看起来是个好主意,但遇到了上述问题,混淆了插件和项目依赖项中的本地缓存工件。

现在我知道 Maven 3 应该引入一种 local repo management 我仔细查看了我的本地存储库并找到了一个名为 _remote.repositories 的文件,其中包含以下内容:

commons-io-2.2.jar>central=
commons-io-2.2.pom>central=

在这里您可以看到 maven 记住了工件来自的存储库,但它记住了存储库 ID 而不是 url! 正如我确实使用 id central 配置我的插件存储库和我的项目存储库一样,maven 混合了两个存储库的缓存工件。

最终的解决方案是尝试禁用中央存储库并使用单独的名称配置项目和插件存储库:

<repository>
  <id>${project-repository}</id>
  <url>http://${company-repo-manager}/${project-repository}</url>
</repository>
<repository>
  <id>central</id>
  <name>Maven Central</name>
  <url>http://repo1.maven.org/maven2</url>
  <releases>
     <enabled>false</enabled>
  </releases>
  <snapshots>
    <enabled>false</enabled>
  </snapshots>
</repository>
...
<pluginRepository>
  <id>maven-plugins-repo</id>
  <url>http://${company-repo-manager}/${plugin-repository}</url>
</pluginRepository>
<pluginRepository>
  <id>central</id>
  <name>Maven Central</name>
  <url>http://repo1.maven.org/maven2</url>
  <releases>
     <enabled>false</enabled>
  </releases>
  <snapshots>
    <enabled>false</enabled>
  </snapshots>
</pluginRepository>

不幸的是 you can not remove central 来自决议,因此如果不同的项目使用名为 central 的存储库,它们将与本地构建交互。

Maven Enforcer 是一个我仍然会寻找的插件,但这至少是我试图解决的基本配置问题。

如果我从一个干净的缓存开始(例如在 CI 构建中),我会得到我预期的构建失败。

希望这能帮助那些试图达到这种隔离水平的人。它仍然不完美,因为您不能删除中央存储库,并且所有存储库中的工件描述符应该相同,但我们至少有最低限度的支持。