您如何有效地处理Maven-3带时间戳的快照?


86

既然maven-3确实放弃了对快照工件的<uniqueVersion> false </ uniqueVersion>的支持,看来您确实需要使用带有时间戳的SNAPSHOTS。特别是在内部确实使用maven 3的m2eclipse似乎受到它的影响,当SNAPSHOTS不是唯一的时,update-snapshots无法正常工作。

将所有快照设置为uniqueVersion = false之前,这似乎是最佳实践

现在,切换到带有时间戳的版本似乎没什么大问题,毕竟它们都由中央关系存储库管理,该存储库能够定期删除旧快照。

问题是本地开发人员工作站。他们在当地的仓库很快就成长非常大的独特的快照。

如何解决这个问题?

现在,我看到了以下可能的解决方案:

  • 要求开发人员定期清除存储库(这导致很多麻烦,因为删除它需要很长时间,甚至下载所有所需的时间也更长)
  • 设置一些脚本,该脚本确实会从本地存储库中删除所有SNAPSHOT目录,并要求开发人员不时运行该脚本(比第一个要好,但仍然需要花费一些时间来运行和下载当前快照)
  • 使用dependency:purge-local-repository插件(从eclipse运行时会出现问题,由于打开的文件,需要从每个项目中运行)
  • 在每个工作站上设置nexus并设置作业以清理旧快照(最佳结果,但我不想维护50台以上nexus服务器,而开发人员工作站上的内存总是很紧)
  • 完全停止使用SNAPSHOTS

防止本地存储库填满硬盘空间的最佳方法是什么?

更新:

为了验证行为并提供更多信息,我安装了一个小型的nexus服务器,构建两个项目(a和b),然后尝试:

A:

<project xmlns="http://maven.apache.org/POM/4.0.0" 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>de.glauche</groupId>
  <artifactId>a</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <distributionManagement>
    <snapshotRepository>
        <id>nexus</id>
        <name>nexus</name>
        <url>http://server:8081/nexus/content/repositories/snapshots</url>
    </snapshotRepository>
  </distributionManagement>

</project>

b:

<project xmlns="http://maven.apache.org/POM/4.0.0" 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>de.glauche</groupId>
  <artifactId>b</artifactId>
  <version>0.0.1-SNAPSHOT</version>
    <distributionManagement>
    <snapshotRepository>
        <id>nexus</id>
        <name>nexus</name>
        <url>http://server:8081/nexus/content/repositories/snapshots/</url>
    </snapshotRepository>
  </distributionManagement>
 <repositories>
    <repository>
        <id>nexus</id>
        <name>nexus</name>
        <snapshots>
            <enabled>true</enabled>
        </snapshots>
        <url>http://server:8081/nexus/content/repositories/snapshots/</url>
    </repository>
 </repositories>
  <dependencies>
    <dependency>
        <groupId>de.glauche</groupId>
        <artifactId>a</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </dependency>
  </dependencies>
</project>

现在,当我使用maven并在“ a”上运行“ deploy”时,

a-0.0.1-SNAPSHOT.jar
a-0.0.1-20101204.150527-6.jar
a-0.0.1-SNAPSHOT.pom
a-0.0.1-20101204.150527-6.pom

在本地存储库中。每次运行部署目标时,都会使用新的时间戳版本。当我尝试从关系服务器更新快照时,也会发生同样的情况(关闭“ a”项目,从本地存储库中删除它,构建“ b”)

在构建大量快照的环境中(想想哈德森服务器...),本地存储库很快就会用旧版本填充

更新2:

为了测试失败的方式和原因,我进行了更多测试。每次测试都对所有内容进行清洁(de / glauche会从计算机和链接中删除)

  • 使用maven 2.2.1部署mvn:

机器A上的本地存储库确实包含snapshot.jar + snapshot-timestamp.jar

但是:在连结中只有一个带有时间戳的jar,元数据显示为:

<?xml version="1.0" encoding="UTF-8"?>
<metadata>
  <groupId>de.glauche</groupId>
  <artifactId>a</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <versioning>
    <snapshot>
      <timestamp>20101206.200039</timestamp>

      <buildNumber>1</buildNumber>
    </snapshot>
    <lastUpdated>20101206200039</lastUpdated>
  </versioning>
</metadata>
  • 在m2eclipse中运行更新依赖项(在计算机B上)(嵌入式m3 final)->本地存储库具有snapshot.jar + snapshot-timestamp.jar :(
  • 使用外部Maven 2.2.1运行软件包目标->本地存储库具有snapshot.jar + snapshot-timestamp.jar :(

好的,接下来尝试使用Maven 3.0.1(在删除项目a的所有痕迹之后)

  • 机器A上的本地存储库看起来更好,只有一个未加时间戳的jar

  • 在关联中只有一个带有时间戳的jar,元数据显示为:

    de.glauche 0.0.1-SNAPSHOT

    <snapshot>
      <timestamp>20101206.201808</timestamp>
      <buildNumber>3</buildNumber>
    </snapshot>
    <lastUpdated>20101206201808</lastUpdated>
    <snapshotVersions>
      <snapshotVersion>
        <extension>jar</extension>
        <value>0.0.1-20101206.201808-3</value>
        <updated>20101206201808</updated>
      </snapshotVersion>
      <snapshotVersion>
        <extension>pom</extension>
        <value>0.0.1-20101206.201808-3</value>
        <updated>20101206201808</updated>
      </snapshotVersion>
    </snapshotVersions>
    

  • 在m2eclipse中运行更新依赖项(在计算机B上)(嵌入式m3 final)->本地存储库具有snapshot.jar + snapshot-timestamp.jar :(

  • 使用外部Maven 2.2.1运行软件包目标->本地存储库具有snapshot.jar + snapshot-timestamp.jar :(

因此,回顾一下:maven3中的“部署”目标比2.2.1中的工作更好,创建机器上的本地存储库看起来不错。但是,接收器总是以很多带有时间戳的版本结尾...

我究竟做错了什么 ?

更新3

我还测试了各种其他配置,首先用人工制品->相同行为替换了关系。然后使用linux maven 3客户端从存储库管理器下载快照->本地存储库仍带有时间戳的快照:(


有关仅本地.m2 \ repository部分的相关问题,重点放在(Jenkins)构建服务器上的本地存储库:stackoverflow.com/q/9729076/223837
MarnixKlooster恢复状态莫妮卡2014年

这里正在链接到Apcahe Maven的Comptability说明- cwiki.apache.org/confluence/display/MAVEN/...
aka_sh

Answers:


36

<uniqueVersion>配置适用于已部署(通过mvn deploy)到Maven存储库(例如Nexus)的工件。

要从Nexus中删除这些文件,您可以轻松地创建一个自动作业,每天清除SNAPSHOT存储库。可以将其配置为保留一定数量的快照或保留一定时间。它超级简单,效果很好。

开发人员机器上本地存储库中的工件从“安装”目标到达此处,并且不使用这些时间戳记...它们只是继续替换一个和唯一的SNAPSHOT版本,除非您还增加了修订号(例如1.0.0-快照到1.0.1-快照)。


1
问题是,“安装”目标并没有在具有许多开发人员的分布式环境中大量使用。我们还使用hudson服务器,该服务器确实在每个cvs提交上构建(和部署)新快照,这种情况每天都经常发生。我知道有关nexus快照删除方法的信息,请参阅可能的解决方法列表。
mglauche 2010年

每个开发机器都应在其下具有一个“本地”存储库,~/.m2/repository并且每个存储机应具有一个存储pom.xml库定义,该定义指向您LAN上的Nexus的单个实例。(就像您展示的一样)。我们已经建立了此设置,并且在每个Subversion提交的基础上构建了Hudson,并且效果很好。SNAPSHOT版本会“部署”到Nexus,每周一次收集并清除。开发人员机器会自动将最新的SNAPSHOT从Nexus下载到~/.m2/repository,并替换以前下载的快照 。开发人员永远不要拥有自己的Nexus实例。
HDave 2010年

2
我刚刚阅读了您的更新,还有一件事要补充:带时间戳的工件永远都不会在本地(〜/ .m2 / repository)存储库中看到。如果是的话,那是不对的。它们只能在Nexus内部看到。是的,在Nexus内部,它们可以快速收集。每天可能有数百MB。日常工作可以更轻松地每天清理这些东西,以保持数量少。
HDave 2010年

6
它们肯定确实存在于本地存储库(〜/ .m2 /存储库之一)中,它们在运行“部署”目标在依赖项目(即B项目)上的mvn -U安装之后结束。我什至用maven 2.2.1和maven 3进行了测试,它们的行为相同。
mglauche 2010年

2
我想我现在明白了……当开发人员进行“部署”时,它们不会出现在此处,而是当开发人员构建相关项目时,它们不会出现在此处。那时,上游项目的最新SNAPSHOT已从Nexus下载到〜/ .m2 /存储库,而时间戳记作为文件名的一部分保留不变。这是正确的吗?
HDave 2010年

13

该插件从本地存储库中删除项目的工件。仅保留一个大型本地快照的副本很有用。

<plugin>         
    <groupId>org.codehaus.mojo</groupId>         
    <artifactId>build-helper-maven-plugin</artifactId>         
    <version>1.7</version>         
    <executions>           
        <execution>             
            <id>remove-old-artifacts</id>             
            <phase>package</phase>             
            <goals>               
                <goal>remove-project-artifact</goal>             
            </goals>            
            <configuration>  
                <removeAll>true</removeAll><!-- When true, remove all built artifacts including all versions. When false, remove all built artifacts of this project version -->             
            </configuration>          
        </execution>         
    </executions>       
</plugin>

7

好吧,我不喜欢任何建议的解决方案。删除Maven缓存通常会大大增加网络流量,并减慢构建过程。build-helper-maven-plugin仅对一个工件有用,我想要一种可以通过一个简单命令从本地缓存中清除所有已过时戳的快照工件的解决方案。经过几天的搜索,我放弃了,决定编写小程序。最终程序在我们的环境中似乎运行良好。因此,我决定与可能需要这种工具的其他人分享。可以从github上获取源代码:https : //github.com/nadestin/tools/tree/master/MavenCacheCleanup


@HDave我无法在此处正确格式化pom片段,请在https://github.com/nadestin/tools/wiki/m2cachecleanup-maven-plugin中进行检查。在我们的Jenkins从站上,此实用程序每天回收约200Mb的磁盘空间。
yurinadestin

2

至于远程存储库,我认为前面讨论定期清除SNAPSHOT的答案将起作用。但是没有人解决您的问题的本地开发人员工作站同步部分。

我们尚未开始使用Maven3,因此尚未看到SNAPSHOT开始在本地计算机上构建。

但是我们在使用m2eclipse时遇到了不同的问题。当启用“工作空间解析”并且项目存在于工作空间中时,源更新通常使我们处于最前沿。但是我们发现要让m2eclipse用Nexus中最近发布的工件进行更新非常困难。我们的团队内部也遇到了类似的问题,这特别有问题,因为我们的项目图非常大……有很多依赖项不会出现在您的工作区中,但会经常发布SNAPSHOT。

我很确定这可以归结为m2eclipse中的一个问题,即它无法完全正确地处理SNAPSHOT。您可以在eclipse的Maven控制台中看到,其中m2eclipse告诉您由于缓存的版本,它跳过了最近发布的SNAPSHOT的更新。如果从运行配置或命令行执行-U,则Maven将获取元数据更改。但是,选择“更新快照...”应该告诉m2eclipse让Maven使该缓存过期。它似乎没有得到通过。如果您有兴趣对此进行投票,那么似乎有一个对此提出的错误:https : //issues.sonatype.org/browse/MNGECLIPSE-2608

您在某处的评论中提到了此。

解决此问题的最佳方法似乎是让开发人员在m2eclipse中开始崩溃时清除其本地工作站。针对不同问题的类似解决方案...其他人报告了Maven 2.2.1和3支持m2eclipse的问题,而且我见过同样的问题。

我希望如果您使用的是Maven3,则可以将其配置为仅拉出最新的SNAPSHOT,并在存储库所说的时间内缓存该时间(或直到您手动使它过期)。希望那时您不需要在本地存储库中放一堆SNAPSHOT。

除非您是在谈论手动执行构建服务器的构建服务器 mvn install在他们。至于如何防止SNAPSHOT在诸如构建服务器之类的环境上构建,我们通过让每个构建都使用其自己的工作区和本地存储库来躲避这一点(尽管在Maven 2.2.1中,诸如POM似乎总是来自〜/ .m2 /存储库。额外的SNAPSHOT实际上只停留在一个构建中,然后被丢弃(并从头开始重新下载)。因此,我们已经看到,这种方法的确会占用更多的空间,但是与将所有内容都从单个存储库中解析出来相比,它往往保持更稳定。该选项(在Hudson上)称为“使用私有Maven存储库”,当您选择使用Maven进行构建时,该选项位于项目配置的“构建”部分的“高级”按钮下。这是该选项的帮助说明:

通常,Hudson使用由Maven确定的本地Maven存储库-确切的过程似乎没有记录,但是它是〜/ .m2 / repository,可以在〜/ .m2 / settings.xml中进行覆盖(有关更多详细信息,请参见参考资料)。 。)通常意味着在同一节点上执行的所有作业共享一个Maven存储库。这样做的好处是可以节省磁盘空间,但是缺点是有时这些构建可能相互干扰。例如,尽管POM中的所有存储库都没有依赖关系,但您可能最终会导致构建错误地成功,只是因为您拥有本地存储库中的所有依赖项。

关于并发的Maven进程尝试使用相同的本地存储库,还有一些报告的问题。

选中此选项后,Hudson将告诉Maven使用$ WORKSPACE / .repository作为本地Maven存储库。这意味着每个作业将只为自己获得一个独立的Maven存储库。它解决了上述问题,但以额外的磁盘空间消耗为代价。

使用此选项时,请考虑设置Maven工件管理器,这样就不必经常访问远程Maven存储库。

如果您希望在Hudson上执行的所有Maven作业中激活此模式,请参考此处介绍的技术。

希望这会有所帮助-如果无法解决您的问题,请让我知道我错过的地方。


上面提到的错误已修复:bugs.eclipse.org/bugs/show_bug.cgi?id=339527
HDave 2013年

1

在groovy中,删除artifact-0.0.1-20101204.150527-6.jar带有时间戳的文件可能非常简单:

root = 'path to your repository'

new File(root).eachFileRecurse {
  if (it.name.matches(/.*\-\d{8}\.\d{6}\-\d+\.[\w\.]+$/)) {
    println 'Deleting ' + it.name
    it.delete()
  }
}

安装Groovy,将脚本保存到文件中,并安排每周执行的时间,开始,登录(如果适合)。

或者,您甚至可以使用gmavenplus-plugin将执行链接到Maven构建中。注意,maven将仓库位置设置为属性settings.localRepository,然后通过配置将其绑定到变量中repository

  <plugin>
    <groupId>org.codehaus.gmavenplus</groupId>
    <artifactId>gmavenplus-plugin</artifactId>
    <version>1.3</version>
    <executions>
      <execution>
        <phase>install</phase>
        <goals>
          <goal>execute</goal>
        </goals>
      </execution>
    </executions>
    <configuration>
      <properties>
        <property>
          <name>repository</name>
          <value>${settings.localRepository}</value>
        </property>
      </properties>
      <scripts>
        <script><![CDATA[
          new File(repository).eachFileRecurse {
            if (it.name.matches(/.*\-\d{8}\.\d{6}\-\d+\.[\w\.]+$/)) {
              println 'Deleting snapshot ' + it.getAbsolutePath()
              it.delete()
            }
          }
        ]]></script>
      </scripts>
    </configuration>
    <dependencies>
      <dependency>
        <groupId>org.codehaus.groovy</groupId>
        <artifactId>groovy-all</artifactId>
        <version>2.3.7</version>
        <scope>runtime</scope>
      </dependency>
    </dependencies>
  </plugin>  

0

将以下参数添加到您的POM文件中

聚甲醛

<configuration>
<outputAbsoluteArtifactFilename>true</outputAbsoluteArtifactFilename>
</configuration>

https://maven.apache.org/plugins/maven-dependency-plugin/copy-mojo.html

POM示例

<plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-dependency-plugin</artifactId>
        <version>2.10</version>
        <executions>
          <execution>
            <id>copy</id>
            <phase>package</phase>
            <goals>
              <goal>copy</goal>
            </goals>
            <configuration>
              <artifactItems>
                <artifactItem>
                  <groupId>junit</groupId>
                  <artifactId>junit</artifactId>
                  <version>3.8.1</version>
                  <type>jar</type>
                  <overWrite>false</overWrite>
                  <outputDirectory>${project.build.directory}/alternateLocation</outputDirectory>
                  <destFileName>optional-new-name.jar</destFileName>
                </artifactItem>
              </artifactItems>
              **<outputAbsoluteArtifactFilename>true</outputAbsoluteArtifactFilename>**
              <outputDirectory>${project.build.directory}/wars</outputDirectory>
              <overWriteReleases>false</overWriteReleases>
              <overWriteSnapshots>true</overWriteSnapshots>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>

在Jenkins中配置:

// copy artifact 
copyMavenArtifact(artifact: "commons-collections:commons-collections:3.2.2:jar", outputAbsoluteArtifactFilename: "${pwd()}/target/my-folder/commons-collections.jar")
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.