Подтвердить что ты не робот

Послепроцессорная банка после сборки, но перед установкой (для получения идемпотентных сборок)

Мы используем Jenkins, которые используют отпечатки пальцев md5, чтобы идентифицировать артефакты и изменился ли артефакт с момента последней сборки. К сожалению, Maven builds всегда генерирует двоичные различные артефакты.

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

После изучения maven-jar-plugin, который использует maven-assembly-plugin, мои выводы заключаются в том, что они не собирают все файлы, которые должны быть записаны в памяти, прежде чем писать их все сразу, но пишите по одному. Это означает, что лучше обработать сгенерированную банку вместо изменения текущего поведения, чтобы я в это время мог сортировать записи, ноль временных меток и т.д.

Я не знаком с написанием плагинов Maven, поэтому мой вопрос: как мне написать плагин, который Maven знает, как определить, где находится артефакт-jar-in-progress и как я подключаю его в моем pom.xml

(Сначала мне нужно, чтобы это работало для файлов jar, но военные файлы тоже были бы хороши).

4b9b3361

Ответ 1

Как уже упоминалось, это можно сделать на основе чего-то похожего на maven-shade-plugin. Я пошел дальше и написал простой плагин, чтобы добавить эту возможность - см. https://github.com/manouti/jar-timestamp-normalize-maven-plugin (доступно на Центральное репо).

Поведение основано на плагине shade. Он состоит из одной цели, называемой normalize, которая может быть привязана к фазе жизненного цикла package и настроена в проекте POM:

<plugins>
    <plugin>
        <groupId>com.github.manouti</groupId>
        <artifactId>jar-timestamp-normalize-maven-plugin</artifactId>
        <version>1.0-SNAPSHOT</version>
        <executions>
            <execution>
                <id>jar-normalize</id>
                <goals>
                    <goal>normalize</goal>
                </goals>
                <phase>package</phase>
            </execution>
        </executions>
    </plugin>
</plugins>

Несколько заметок о плагине:

  • Доступ к артефакту под сборкой осуществляется через project#getArtifact(), где project - org.apache.maven.project.MavenProject.

  • Нормализация состоит в основном из трех шагов:

    • Установка последнего измененного времени всех записей Jar на конкретную метку времени (значение по умолчанию 1970-01-01 00:00:00AM, но может быть изменено с помощью системного свойства -Dtimestamp).

    • Переупорядочение (в алфавитном порядке) атрибутов в манифесте, за исключением Manifest-Version, которое всегда на первом месте.

    • Удаление комментариев из файла pom.properties, содержащих временную метку, которая заставляет Jar отличаться от одной сборки к другой.

После вызова цель будет генерировать выходной файл рядом с оригинальным артефактом (с именем artifactId-version-normalized.jar), то есть в каталоге project.build.directory.

Ответ 2

Чтобы создать проект плагина maven

mvn archetype:generate \
  -DgroupId=sample.plugin \
  -DartifactId=hello-maven-plugin \
  -DarchetypeGroupId=org.apache.maven.archetypes \
  -DarchetypeArtifactId=maven-archetype-plugin

вызовите эту команду, он сгенерирует проект скелета с классом MyMojo.java

напишите свой материал внутри метода execute() и установите этот плагин в ваш репозиторий mvn clean install

затем присоедините свое исполнение к вашему проекту, в вашем проекте pom.xml

 <build>
    <plugins>
      <plugin>
        <groupId>sample.plugin</groupId>
        <artifactId>hello-maven-plugin</artifactId>
        <version>1.0-SNAPSHOT</version>
        <executions>
          <execution>
            <phase>package</phase>
            <goals>
              <goal>sayhi</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>

для доступа к свойствам проекта внутри вашего Mojo

    /**
     * The Maven project.
     *
     * @parameter expression="${project}"
     * @required
     * @readonly
     */
    private MavenProject        project; 

а затем

project.getProperties("build.directory") 

и прочитать другие свойства, чтобы определить ваш упакованный файл jar.


См

Ответ 3

Я согласен на создание настраиваемого плагина maven, как лучший вариант. Я не знаю, что существующий плагин обеспечивает решение по тому, что вы просили.

Контрольная сумма

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

У меня есть 2 предложения об этом плагине:

1) Если вы думаете простыми, этот плагин должен:

  • Чтение созданной банки:
    • Извлеките все записи.
    • Исключить некоторые записи (например, MANIFEST.MF).
    • Сортировка оставшихся записей.
    • Извлеките md5 для каждого в памяти.
    • Создайте один md5 из всех извлеченных.

Однако при рассмотрении вопроса о том, где и когда независимость: в соответствии с файловой структурой .class Java_class_file имеются незначительные записи основных версий скомпилированные файлы классов. Поэтому, если компилятор изменится, файлы .class будут изменены. В этом случае нам нужно проверить уровень исходного кода с этого момента: (Таким образом, это решение становится бесполезным, если нет гарантии на версию копилятора.


2) Как очень грязное, но простое решение, этот плагин может извлечь только код вашего модуля pom.xml file md5. Но вы должны гарантировать, что каждое изменение в вашей фляге отразится на малой версии (или построенном) вручную.

Ответ 4

Вместо написания собственного плагина вы можете написать Groovy script, который выполняется groovy-maven-plugin:

<plugin>
  <groupId>org.codehaus.gmaven</groupId>
  <artifactId>groovy-maven-plugin</artifactId>
    <executions>
      <execution>
        <phase>package</phase>
        <goals>
          <goal>execute</goal>
        </goals>
        <configuration>
          <source>
              import java.util.jar.*
              String fileName = '${project.build.directory}/${project.build.finalName}.jar'
              println "Editing file ${fileName}"
              JarFile file = new JarFile(fileName);
               // do your edit
          </source>
        </configuration>
      </execution>
  </executions>
</plugin>