Як ви ефективно працюєте зі знімками з відміченими штампом Maven-3?


86

Тепер, коли maven-3 припинив підтримку <uniqueVersion> false </uniqueVersion> для артефактів знімків, здається, що вам дійсно потрібно використовувати SNAPSHOTS із позначкою часу. Особливо m2eclipse, який використовує maven 3 внутрішньо, здається, зазнає впливу, оновлення-знімки не працюють, коли SNAPSHOTS не є унікальними.

Перш за все здавалося найкращою практикою встановлювати всі знімки як uniqueVersion = false

Зараз, здається, не представляє великої проблеми перейти на версію із позначкою часу, адже ними керує центральне сховище nexus, яке здатне видаляти старі знімки у звичайних інтервалах.

Проблема полягає в робочих станціях місцевих розробників. Їх місцеве сховище швидко стає дуже великим завдяки унікальним знімкам.

Як боротися з цією проблемою?

Зараз я бачу наступні можливі рішення:

  • Попросіть розробників регулярно очищати сховище (що призводить до великого розчарування, оскільки видалення займає багато часу і завантаження всього необхідного)
  • Налаштуйте скрипт, який видаляє всі каталоги SNAPSHOT з локального сховища, і пропонуйте розробникам час від часу запускати цей сценарій (краще, ніж перший, але для запуску та завантаження поточних знімків потрібно досить багато часу)
  • використовувати залежність: плагін purge-local-repository (Має проблеми при запуску з eclipse через відкриті файли, потрібно запускати з кожного проекту)
  • налаштуйте nexus на кожній робочій станції та налаштуйте роботу для очищення старих знімків (найкращий результат, але я не хочу підтримувати 50+ серверів nexus, плюс пам'ять завжди обмежена на робочих станціях розробника)
  • припиніть взагалі використовувати SNAPSHOTS

Який найкращий спосіб уникнути заповнення місцевого сховища місця на жорсткому диску?

Оновлення:

Щоб перевірити поведінку та надати більше інформації, я налаштував невеликий сервер зв'язку, побудуйте два проекти (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-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

у локальному сховищі. З новою версією мітки часу кожного разу, коли я запускаю ціль розгортання. Те саме відбувається, коли я намагаюся оновити знімки з сервера nexus (закрити проект "a", видалити його з локального сховища, побудувати "b")

У середовищі , де багато знімків отримати збірки (думає Hudson сервер ...), локальна reposioty заповнюється зі старими версіями швидко

Оновлення 2:

Щоб перевірити, як і чому це не вдається, я зробив ще кілька тестів. Кожен тест запускається проти очищення всього (de / glauche отримує видалення як з машин, так і з nexus)

  • розгортання mvn за допомогою 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)

  • локальний репозитарій на машині А виглядає краще, лише одна банка, що не має позначок часу

  • лише одна баночка з часовим штампом у нексусі, метадані звучать:

    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, щоб завантажити знімки з диспетчера сховищ -> локальне сховище все ще має позначки часу:


Пов’язане запитання, що стосується лише локальної частини .m2 \ repository, зосередженої на локальному сховищі на сервері збірки (Jenkins): stackoverflow.com/q/9729076/223837 .
MarnixKlooster ReinstateMonica

Ось робоче посилання на примітки щодо сумісності Apcahe Maven - cwiki.apache.org/confluence/display/MAVEN/…
aka_sh

Відповіді:


36

<uniqueVersion>Конфігурація застосовується до артефактів , які були розгорнуті (через MVN розгортання) в Maven сховища , такі як Nexus.

Щоб видалити їх із Nexus, ви можете легко створити автоматизоване завдання для очищення сховища SNAPSHOT щодня. Він може бути налаштований на збереження певної кількості знімків або збереження їх протягом певного періоду часу. Це дуже просто і чудово працює.

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


1
Проблема полягає в тому, що мета "встановити" полягає не стільки в розподіленому середовищі з багатьма розробниками. Ми також використовуємо сервер Hudson, який створює (і розгортає) нові знімки кожного коміту, що трапляється, що трапляється досить часто щодня. Я знав про механізм видалення знімків знімків, див. Список можливих обхідних шляхів.
mglauche

Кожна машина розробки повинна мати "локальне" сховище, ~/.m2/repositoryі кожне pom.xmlповинно мати визначення сховища, яке вказує на один екземпляр Nexus у вашій локальній мережі. (так само, як ви показуєте). Ми створили це, разом із Хадсоном, яке базується на кожному комісії Subversion, і воно чудово працює. Збірки SNAPSHOT "розгортаються" у Nexus, де вони збираються та очищаються щотижня. Машини-розробники автоматично завантажують останню версію SNAPSHOT з Nexus на, ~/.m2/repositoryі вона замінює раніше завантажену. Розробники ніколи не повинні мати власний екземпляр Nexus.
HDзберегти

2
Я щойно прочитав ваше оновлення і маю додати ще одну річ: артефакти з позначкою часу ніколи не повинні бути видимими у вашому локальному сховищі (~ / .m2 / repository). Якщо вони є, щось не так. Їх слід бачити лише всередині Nexus. Всередині Nexus, так, вони швидко збираються. Потенційно сотні МБ на день. Завданням з'єднання може бути легше продувати їх щодня, щоб кількість була невеликою.
HDзберегти

6
Вони, безумовно, потрапляють до локального сховища (~ / .m2 / сховища), вони потрапляють туди після запуску цілі "розгортання" та при встановленні mvn -U на відповідному проекті (тобто проект B). Я навіть тестував його з maven 2.2.1 та maven 3, обидва мають однакову поведінку.
mglauche

2
Я думаю, я зрозумів це зараз ... вони НЕ з'являються там, коли розробник робить "розгортання", а швидше, коли розробник створює залежний проект. На той час остання версія SNAPSHOT вищого проекту завантажується з Nexus у сховище ~ / .m2 / із позначкою часу, яка залишається незмінною як частина імені файлу. Чи це правильно?
Зберегти

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 . На наших рабів Дженкінса ця програма повертає ~ 200 Мб дискового простору щодня.
yurinadestin

2

Що стосується віддаленого сховища цього, я думаю, що попередні відповіді, які обговорюють очищення SNAPSHOT регулярно, будуть працювати. Але ніхто не звертався до частини вашого запитання щодо синхронізації робочої станції для місцевих розробників.

Ми ще не почали використовувати Maven3, тому ми ще не бачимо, як SNAPSHOT починають створюватися на локальних машинах.

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

Я майже впевнений, що це зводиться до проблеми в m2eclipse, де вона не обробляє SNAPSHOT точно, як слід. Ви можете побачити на консолі Maven в eclipse, де 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 дійсно залишаються лише для однієї збірки, а потім їх скидають (і завантажують знову з нуля). Отже, ми бачили, що такий підхід спочатку з’їдає більше місця, але він, як правило, залишається стабільнішим, ніж вирішення всього питання з одного сховища. Цей параметр (на Гудзоні) називається "Використовувати приватне сховище Maven" і знаходиться під кнопкою "Додатково" розділу "Збірка" в конфігураціях проекту, коли ви вибрали будувати за допомогою Maven. Ось довідка для цього варіанту:

Зазвичай Хадсон використовує локальне сховище Maven, як визначено Maven - точний процес здається недокументованим, але це ~ / .m2 / сховище і може бути замінено в ~ / .m2 / settings.xml (докладнішу інформацію див. У посиланні) .) Це зазвичай означає, що всі завдання, що виконуються на одному вузлі, мають спільне сховище Maven. Перевагою цього є те, що ви можете заощадити місце на диску, але недоліком цього є те, що іноді ці збірки можуть заважати один одному. Наприклад, у вас можуть виникнути неправильні збірки, лише тому, що у вас є всі залежності у вашому локальному сховищі, незважаючи на той факт, що жодне зі сховищ у POM їх не може мати.

Також повідомляється про деякі проблеми щодо паралельних процесів Maven, які намагаються використовувати одне і те ж локальне сховище.

Коли цю опцію встановлено, Хадсон скаже Maven використовувати $ WORKSPACE / .repository як локальне сховище Maven. Це означає, що кожна робота отримає власне ізольоване сховище Maven лише для себе. Він виправляє вищезазначені проблеми за рахунок додаткового споживання дискового простору.

Використовуючи цю опцію, розгляньте можливість налаштування диспетчера артефактів Maven, щоб вам не довелося занадто часто натискати на віддалені сховища Maven.

Якщо ви віддаєте перевагу активувати цей режим у всіх завданнях Maven, виконаних у Гудзоні, зверніться до техніки, описаної тут.

Сподіваюся, це допоможе - якщо це не вирішить вашу проблему, повідомте мені, де я пропустив.


Виправлена ​​помилка, згадана вище: bugs.eclipse.org/bugs/show_bug.cgi?id=339527
HDave

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 , збережіть скрипт у файл та заплануйте виконання кожного тижня, запустіть, увійдіть, що вам підходить.

Або ви навіть можете підключити виконання до збірки maven, використовуючи плагін gmavenplus . Зверніть увагу, як розміщення сховища встановлюється 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")
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.