Comment spécifier la distribution de maven à l'échelle de l'organisation?

110

J'essaie de comprendre comment organiser de nombreux projets maven2 (environ 50+), afin qu'ils puissent se déployer dans un référentiel central nexus. Lors de l'utilisation de l' mvn deployobjectif, il est nécessaire de spécifier la cible dans la balise distributionManagement comme ceci:

<distributionManagement>
   <repository>
      <id>nexus-site</id>
        <url>http://central_nexus/server</url>
   </repository>
</distributionManagement>

Maintenant, je ne veux pas que chaque pom.xml (de ces 50+) contienne ce bloc encore et encore. Mon premier serait le settings.xmlfichier, mais il semble qu'il n'est pas possible (de par sa conception) de le définir ici. Alors, la première question serait: pourquoi est-ce le cas? Si cela était possible, je pourrais le spécifier dans le fichier settings.xml de la distribution maven2, qui pourrait être distribué à tous les développeurs.

La seule solution possible que j'ai trouvée était de créer un projet master-pom à l'échelle de l'organisation, qui contient ces paramètres, et de faire en sorte que tous les autres pom.xml dépendent de ce master-pom via <parent>tag. Mais cela semble un peu étrange dans les versions multi-modules:

- master configuration POM (pm)
- Project 1 parent pom (p1 with module 1 and module 2 as modules)
    - Project 1 module pom (with pm as parent)
    - Project 2 module pom (with pm as parent)

Habituellement, je lis dans toute la documentation que le module poms doit utiliser le pom parent, pas un autre. Mais après avoir lu le site Web maven sur l'héritage contre l'agrégation, il est écrit que c'est effectivement possible.

Un problème que j'ai trouvé était avec la génération de site maven, qui semble avoir des problèmes avec cette configuration (les modules ne sont pas liés correctement s'ils n'ont pas de référence directe)

Alors, est-ce une approche valable? Une autre solution plus évidente et plus simple au problème?

mglauche
la source
5
@OhadR: Ils n'écrivent comment l'écrire que dans un seul projet. Le fait est que je ne voulais pas le dupliquer environ 500 fois ...
mglauche
1
je vois. point pris. donc comme celui qui a répondu l'a dit, vous pouvez avoir un pom principal pour le projet, qui contiendra le 'distribMngmnt' ...
OhadR

Réponses:

144

La meilleure solution pour cela est de créer un projet de fichier pom parent simple (avec l'empaquetage «pom») de manière générique pour tous les projets de votre organisation.

<?xml version="1.0" encoding="UTF-8"?>
<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/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>your.company</groupId>
    <artifactId>company-parent</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>pom</packaging>

    <distributionManagement>
        <repository>
            <id>nexus-site</id>
            <url>http://central_nexus/server</url>
        </repository>
    </distributionManagement>

</project>

Cela peut être construit, publié et déployé dans votre nexus local afin que tout le monde ait accès à son artefact.

Maintenant, pour tous les projets que vous souhaitez utiliser, incluez simplement cette section:

<parent>
  <groupId>your.company</groupId>
  <artifactId>company-parent</artifactId>
  <version>1.0.0</version>
</parent>

Cette solution vous permettra d'ajouter facilement d'autres éléments communs à tous les projets de votre entreprise. Par exemple, si vous souhaitez standardiser votre utilisation de JUnit vers une version spécifique, ce serait l'endroit idéal pour cela.

Si vous avez des projets qui utilisent des structures multi-modules qui ont leur propre parent, Maven prend également en charge l'héritage de chaînage, il est donc parfaitement acceptable que le fichier pom parent de votre projet fasse référence au pom parent de votre entreprise et que les modules enfants du projet ne soient même pas conscients de votre société mère.

Je vois à partir de votre exemple de structure de projet que vous essayez de mettre votre projet parent au même niveau que votre agrégateur pom. Si votre projet a besoin de son propre parent, la meilleure approche que j'ai trouvée est d'inclure le parent au même niveau que le reste des modules et d'avoir votre fichier d'agrégateur pom.xml à la racine de l'emplacement de tous les répertoires de vos modules.

- pom.xml (aggregator)
    - project-parent
    - project-module1
    - project-module2

Ce que vous faites avec cette structure est d'inclure votre module parent dans l'agrégateur et de tout construire avec un à mvn installpartir du répertoire racine.

Nous utilisons cette solution exacte dans mon organisation et elle a résisté à l'épreuve du temps et a très bien fonctionné pour nous.

Jesse Webb
la source
Voici une autre réponse où je décris plus en détail l'héritage du projet et comment gérer sa complexité hériter, pardonner le jeu de mots. ;) stackoverflow.com/questions/6347913
Jesse Webb
7
Juste une petite note: pour les raisons pour lesquelles la société mère est la meilleure solution, consultez la discussion Impossible de spécifier distributionManagement dans settings.xml dans la liste des utilisateurs Maven.
Premek Brada
Dans le modèle de conseil classique, dans lequel «le client possède le code», mon équipe de développement devra travailler sur le projet hors site, puis apporter le dernier code au site client et le reconstruire. Dans ma situation, travaillant avec un projet multi-modules, si je référence le POM de l'entreprise dans le POM parent du projet, je devrai mettre à jour cette référence pour pointer vers le POM de l'entreprise du client. Je préfère m'efforcer de conserver tous les paramètres spécifiques à l'environnement dans settings.xml si je peux l'aider. Quelle est l'approche recommandée pour ma situation?
Web utilisateur
2
@WebUser Votre problème ressemble plus à une situation où vous avez besoin de valeurs différentes dans vos fichiers POM, par opposition à ce que cette réponse aborde: éviter les paramètres dupliqués sur plusieurs modules. Je pense que vous devriez essayer d' injecter des propriétés via un fichier settings.xml . Si cela ne vous aide pas, posez une nouvelle question ici sur SO, lien vers elle ici, et je vais essayer de vous aider davantage.
Jesse Webb
Merci @JesseWebb J'ai fini par essayer cela et il est utile d'abstraire ces valeurs du POM pour la situation que j'ai décrite. Pour mes besoins, j'ai ajouté des propriétés pertinentes sous le profil actif et celles résolues dans le POM.
Web utilisateur
36

Il n'y a pas besoin d'un POM parent.

Vous pouvez omettre la partie distributionManagement entièrement dans vos poms et la définir soit sur votre serveur de construction, soit dans settings.xml.

Pour le faire sur le serveur de build, passez simplement à la mvncommande:

-DaltSnapshotDeploymentRepository=snapshots::default::https://YOUR_NEXUS_URL/snapshots
-DaltReleaseDeploymentRepository=releases::default::https://YOUR_NEXUS_URL/releases

Voir https://maven.apache.org/plugins/maven-deploy-plugin/deploy-mojo.html pour plus de détails sur les options pouvant être définies.

Il est également possible de définir cela dans votre fichier settings.xml.

Créez simplement un profil qui est activé et contient la propriété.

Exemple settings.xml:

<settings>
[...]
  <profiles>
    <profile>
      <id>nexus</id>
      <properties>
        <altSnapshotDeploymentRepository>snapshots::default::https://YOUR_NEXUS_URL/snapshots</altSnapshotDeploymentRepository>
        <altReleaseDeploymentRepository>releases::default::https://YOUR_NEXUS_URL/releases</altReleaseDeploymentRepository>
      </properties>
    </profile>
  </profiles>

  <activeProfiles>
    <activeProfile>nexus</activeProfile>
  </activeProfiles>

</settings>

Assurez-vous que les informations d'identification pour les "instantanés" et les "versions" se trouvent dans la <servers>section de votre settings.xml

Les propriétés altSnapshotDeploymentRepository et altReleaseDeploymentRepository sont introduites avec maven-deploy-plugin version 2.8. Les anciennes versions échoueront avec le message d'erreur

Deployment failed: repository element was not specified in the POM inside distributionManagement element or in -DaltDeploymentRepository=id::layout::url parameter

Pour résoudre ce problème, vous pouvez appliquer une version plus récente du plug-in:

        <build>
          <pluginManagement>
            <plugins>
              <plugin>
                <artifactId>maven-deploy-plugin</artifactId>
                <version>2.8</version>
              </plugin>
            </plugins>
          </pluginManagement>
        </build>
Michael Wyraz
la source
J'essaye continuellement cette solution mais seule la propriété altDeploymentRepository fonctionne. altReleaseDeploymentRepository et altSnapshotDeploymentRepository ne sont pas reconnus et j'obtiens cette erreur: Le déploiement a échoué: l'élément de référentiel n'a pas été spécifié dans le POM à l'intérieur de l'élément distributionManagement ou dans -DaltDeploymentRepository = id :: layout :: url paramete. Toute suggestion aiderait. Merci
Shabirmean
@Shabirmean La raison est une version trop ancienne du plug-in de déploiement. J'ai étendu ma réponse avec une solution.
Michael Wyraz
Ouais, je l'ai compris. Merci beaucoup :)
Shabirmean