Как вы эффективно справляетесь с моментальными снимками maven-3?

Теперь, когда maven-3 сделал отказаться от поддержки для <uniqueVersion> false </uniqueVersion> для артефактов моментальных снимков кажется, что вам действительно нужно использовать timestamped SNAPSHOTS. Особенно сильно влияет на m2eclipse, который использует maven 3 внутри, обновления-моментальные снимки не работают, когда SNAPSHOTS не уникальны.

Казалось, лучше практиковать до, чтобы установить все моментальные снимки в uniqueVersion = false

Теперь нет никакой проблемы переключиться на timestamped версию, после того, как все они управляются центральным репозиторием nexus, который может удалять старые снимки в обычных интервалах.

Проблема заключается в локальных рабочих станциях разработчиков. Их локальный репозиторий быстро растет очень просто с уникальными моментальными снимками.

Как справиться с этой проблемой?

Сейчас я вижу следующие возможные решения:

  • Попросите разработчиков регулярно очищать репозиторий (что приводит к большому количеству фрустрации, так как требуется много времени для удаления и даже дольше, чтобы загрузить все необходимое).
  • Настройте несколько script, которые удаляют все каталоги SNAPSHOT из локального репозитория и просят разработчиков время от времени запускать этот script (лучше, чем первый, но все еще занимает довольно много времени для запуска и загрузки текущих снимков )
  • используйте зависимость: плагин purge-local-repository (возникают проблемы при запуске из eclipse из-за открытых файлов, которые должны запускаться из каждого проекта)
  • настроить связь на каждой рабочей станции и настроить работу по очистке старых снимков (лучший результат, но я не хочу поддерживать более 50 серверов Nexus, а память всегда плотно работает на рабочих станциях разработчиков).
  • прекратить использование SNAPSHOTS вообще

Каков наилучший способ сохранить ваш локальный репозиторий в заполнении вашего пространства на жестком диске?

Update:

Чтобы проверить beaviour и дать больше информации, я настраиваю небольшой сервер nexus, создайте два проекта (a и 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>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>

б

<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", у меня будет

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

в локальном репозитории. С новой версией timestamp каждый раз, когда я запускаю цель развертывания. То же самое происходит, когда я пытаюсь обновить снимки с сервера nexus (закрыть "a" Project, удалить его из локального репозитория, построить "b" )

В среде, где много снимков получают сборку (думаю, hudson server...), локальный reposioty заполняется старыми версиями быстро

Обновление 2:

Чтобы проверить, как и почему это происходит, я сделал еще несколько тестов. Каждый тест запускается против очистки всех (de/glauche получает удаление с обеих машин и нексуса)

  • mvn deploy with maven 2.2.1:

локальный репозиторий на машине A содержит snapshot.jar + snapshot-timestamp.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>
  • Запуск зависимостей обновления (на машине B) в m2eclipse (встроенный m3 final) → локальный репозиторий имеет snapshot.jar + snapshot-timestamp.jar: (
  • запустить цель пакета с помощью внешнего maven 2.2.1 → локальный репозиторий имеет snapshot.jar + snapshot-timestamp.jar: (

Хорошо, попробуйте с maven 3.0.1 (после удаления всех следов проекта a)

  • локальный репозиторий на машине A выглядит лучше, только один флажок без отметки времени

  • только одна метка времени в нексусе, метаданные читают:

    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>
    

  • Запуск зависимостей обновления (на машине B) в m2eclipse (встроенный m3 final) → локальный репозиторий имеет snapshot.jar + snapshot-timestamp.jar: (

  • запустить цель пакета с помощью внешнего maven 2.2.1 → локальный репозиторий имеет snapshot.jar + snapshot-timestamp.jar: (

Итак, чтобы повторить: цель "развертывания" в maven3 работает лучше, чем в 2.2.1, локальный репозиторий на создающей машине выглядит отлично. Но, ресивер всегда заканчивается множеством временных версий...

Что я делаю неправильно?

Обновление 3

Я также тестировал различные другие конфигурации, сначала заменил nexus artifactory → такое же поведение. Затем используйте linux maven 3 клиента для загрузки снимков из диспетчера репозитория → локальный репозиторий по-прежнему имеет временные снимки: (

Ответ 1

Конфигурация <uniqueVersion> применяется к артефактам, которые были развернуты (через развертывание mvn) в репозиторий Maven, таком как Nexus.

Чтобы удалить их из Nexus, вы можете легко создать автоматизированное задание для ежедневной очистки репозитория SNAPSHOT. Он может быть настроен на сохранение определенного количества снимков или сохранение их в течение определенного периода времени. Его супер легко и отлично работает.

Артефакты в локальном репозитории на машине разработчика получают от цели "установить" и не используют эти временные метки... они просто продолжают заменять одну и только версию SNAPSHOT, если вы также не увеличиваете номер версии (например, 1.0.0-SNAPSHOT до 1.0.1-SNAPSHOT).

Ответ 2

Этот плагин удаляет артефакты проекта из локального репозитория. Полезно хранить только одну копию большого локального снимка.

<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>

Ответ 3

Ну, мне не понравилось ни одно из предлагаемых решений. Удаление кеша maven часто значительно увеличивает сетевой трафик и замедляет процесс сборки. build-helper-maven-plugin помогает только с одним артефактом, мне нужно решение, которое может очистить все устаревшие временные артефакты моментального снимка из локального кеша одной простой командой. После нескольких дней поиска я сдался и решил написать небольшую программу. Заключительная программа, похоже, работает очень хорошо в нашей среде. Поэтому я решил поделиться им с другими, кому может понадобиться такой инструмент. Источники можно вытащить из github: https://github.com/nadestin/tools/tree/master/MavenCacheCleanup

Ответ 4

Что касается удаленной части репозитория, я думаю, что предыдущие ответы, которые обсуждают очистку SNAPSHOT на регулярном интервале, будут работать. Но никто не обратился к части вашей синхронизации рабочей станции локального разработчика.

Мы еще не начали использовать Maven3, поэтому нам еще предстоит увидеть, как SNAPSHOT начинают создавать локальные машины.

Но у нас были разные проблемы с m2eclipse. Когда у нас есть разрешение "Разрешение рабочей области" и проект существует в нашей рабочей области, обновления источника обычно удерживают нас на краю кровотечения. Но нам было очень сложно получить m2eclipse, чтобы обновить себя недавно опубликованными артефактами в Nexus. Мы сталкиваемся с аналогичными проблемами в нашей команде, и это особенно проблематично, потому что у нас очень большой график проектов... есть много зависимостей, которые не будут в вашей рабочей области, но будут часто публиковать публикации SNAPSHOT.

Я почти уверен, что это снова возвращается к проблеме в m2eclipse, где он не обрабатывает SNAPSHOTs точно так, как должен. Вы можете увидеть на консоли Maven в eclipse, где m2eclipse сообщает вам, что она пропускает обновление недавно опубликованной SNAPSHOT, потому что она получила кешированную версию. Если вы выполните команду -U из конфигурации запуска или из командной строки, Maven заберет метаданные. Но выбор "Обновить моментальные снимки..." должен указывать m2eclipse, чтобы Maven завершил этот кеш. Кажется, он не проходит мимо. Кажется, есть ошибка, которая подана для этого, если вы заинтересованы в голосовании за нее: https://issues.sonatype.org/browse/MNGECLIPSE-2608

Вы упомянули об этом в комментарии где-то.

Лучшим обходным решением этой проблемы, по-видимому, является то, что разработчики очищают свои локальные рабочие станции, когда что-то начинает разрушаться из-за m2eclipse. Аналогичное решение для другой проблемы... Другие сообщили о проблемах с Maven 2.2.1 и 3, поддерживающими m2eclipse, и я видел то же самое.

Я надеюсь, что если вы используете Maven3, вы можете настроить его, чтобы вытащить только последний SNAPSHOT и кеш, который за время, о котором говорит репозиторий (или пока вы не закончите его вручную). Надеюсь, вам не понадобится иметь кучу SNAPSHOTs, сидящих в вашем локальном репозитории.

То есть, если вы не говорите о сервере сборки, который вручную делает mvn install на них. Что касается того, как предотвратить создание SNAPSHOTs в среде, такой как сервер сборки, мы как бы уклонились от этой пули, поскольку каждая сборка использует свое собственное рабочее пространство и локальный репозиторий (хотя в Maven 2.2.1 некоторые вещи, такие как Кажется, что POM всегда выходят из ~/.m2/repository). Дополнительные SNAPSHOT действительно поддерживают только одну строчку, а затем они удаляются (и загружаются снова с нуля). Таким образом, мы видели, что этот подход в конечном итоге съедает больше места для начала, но он имеет тенденцию оставаться более стабильным, чем все, что разрешено из одного репозитория. Этот параметр (на Hudson) называется "Использовать частный репозиторий Maven" и находится под кнопкой "Дополнительно" раздела "Сборка" в конфигурациях проекта, когда вы выбрали для сборки с Maven. Вот описание справки для этой опции:

Обычно Хадсон использует локальный Maven хранилище, как определено Maven - точный процесс кажется без документов, но это ~/.m2/repository и может быть переопределено в ~/.m2/settings.xml(см. ссылку для более подробной информации.) Это обычно означает что все задания, которые выполняются на тот же node делится одним Maven репозиторий. Достоинством этого является то, что вы можете сохранить дисковое пространство, но Недостатком этого является то, что иногда эти сборки могут мешать каждому Другие. Например, вы можете с неправильным построением, просто потому, что у вас есть все зависимостей в вашем локальном репозитории, несмотря на тот факт, что ни одна из репозитории в POM могут иметь их.

Есть также некоторые проблемы относительно наличия параллельного Maven процессы, пытающиеся использовать один и тот же локальный хранилище.

Когда эта опция отмечена, Хадсон скажет Maven использовать $WORKSPACE/.repository как локальный Репозиторий Maven. Это означает, что каждая работа получит свое собственное изолированное Maven репозиторий только для себя. Он исправляет вышеупомянутые проблемы, за счет дополнительное дисковое пространство.

При использовании этой опции создание менеджера артефактов Maven, чтобы что вам не нужно удалять удаленные Maven репозитории слишком часто.

Если вы предпочитаете активировать этот режим во всех заданиях Maven, выполненных на Хадсон, см. Технику описанных здесь.

Надеюсь, что это поможет - если это не касается вашей проблемы, пожалуйста, сообщите мне, где я пропустил.

Ответ 5

В 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, сохраните script в файл и заплатите за выполнение каждую неделю, запустите, войдите в систему, что вам подходит.

Или вы можете даже выполнить исполнение в maven build, используя gmavenplus-plugin. Обратите внимание, как определяется местоположение хранилища 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>  

Ответ 6

Добавьте в свой файл POM следующий параметр

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")