web-dev-qa-db-ja.com

Mavenで子モジュールのバージョンを更新するにはどうすればよいですか?

子モジュールのバージョンを更新するには?このようなStackoverflowの質問はたくさんありますが、この正確なシナリオに当てはまる質問を見つけることができませんでした。

次のプロジェクトを検討してください。

parent
  --mod1
  --mod2

開発リリースサイクルの最初に、親と​​モジュールを同じバージョンに更新する必要があります。親とモジュールのバージョンがリリース全体で同じであった場合、モジュールから<version>タグを省略し、versions:set -DnewVersion=1.1.1を実行して開発サイクルを開始します。しかし、結局のところ、すべてのモジュールが同じバージョンでサイクルを終了するわけではありません。バグと修正が具体化されると、バグのあるモジュールのみが具体化され、更新されます。たとえば、親とmod2はバージョン1.1.1-RC1である可能性がありますが、mod1は1.1.1-RC2である可能性があります。

そのため、次のことを行う必要があります。
1)モジュールに<version>タグを含めて、各モジュールのバージョンを個別に追跡します。

2)mod2が依存関係としてmod1を必要とする場合、mod2がmod1の最新バージョンを参照していることを確認する必要があります。

これは、次の2つの質問につながります。

1)サイクルの最初に、1つのMavenコマンドで親とモジュールを同じバージョンに設定するにはどうすればよいですか?私はversion:set -DnewVersion=1.1.1を試しましたが、これはすべてのPOMの親のバージョンのみを更新し、モジュールのバージョンは更新しません。私も-N versions:update-child-modulesを試しましたが、何もしないので間違って使用していると思います。すべてのモジュールでスキップされただけです。

2)これは少し難しく、上記の項目2と一致します。 mod1のバージョンとmod2の参照の両方を一度にmod1のバージョンに更新するにはどうすればよいですか?私は2つのステップでそれを行う方法を知っています:

親pom:

<properties>
    <!-- update this manually if mod1's version no longer matches parent -->
    <mod1.version>${project.version}</mod1.version>
</properties>

mod2 pom:

    <dependency>
        <groupId>com.xxx</groupId>
        <artifactId>mod1</artifactId>
        <version>${mod1.version}</version>
    </dependency>

Mod1が1.1.1-RC2に達すると、親POMとmod1 POMを更新してこれを反映します。これらは2つのステップです。とにかく、それを1つのステップに変えますか?

私の例は小さいですが、実際には、この重要な時間を節約する多くのモジュールがあり、それに興味があります。

18
Jose Martinez

質問1)

アプリケーションのライフサイクルとリリースを管理する最良の方法は、リリースプラグインを使用することです。

ご存じかもしれませんが、Mavenの哲学は構成よりも慣例です。 Mavenの慣習では、開発中にスナップショットバージョン(-SNAPSHOTで終わるバージョン)を使用し、リリースにのみ非スナップショットバージョンを割り当てます。

バージョン1.1.1を開発しているとしましょう。開発中は、1.1.1-SNAPSHOTを使用するだけです。 Mavenがスナップショットの更新を処理します。アーティファクトリポジトリを使用している場合は、-Uを使用して、常に最新バージョンのスナップショットがあることを確認できます。

リリースの準備ができると、リリースプラグインはバージョン1.1.1を生成してデプロイし、POMを1.1.2-SNAPSHOTなどの新しい開発バージョンで更新します。

マルチモジュールプロジェクトについては、2つのシナリオがあります。モジュールは関連しているが独立している(複数のWebアプリケーションなど)、または単一の大きなアプリケーションまたはライブラリのモジュールであり、バージョンを共有している。あなたは後者に興味があるようです。

この場合の最良の方法は、バージョンを含め、同じ親(おそらくルート)モジュールを継承することです。親group:artifact:versionを参照し、子のバージョンを指定しません。通常、グループも継承するため、子pomは次のようになります。

<parent>
   <groupId>com.mycompany.myproject</groupId>
   <artifactId>myproject-parent</artifactId>
   <version>1.1.1-SNAPSHOT</version>
   <relativePath>../myproject-parent</relativePath>
</parent>
<artifactId>myproject-module1</artifactId>

次に、リリースプラグインを使用して、親の正しいバージョンを指す子の世話をする必要があります。

子供のことを知るのを助けるために、後で示すように、modulesセクションを含めることにより、親pomもルートpomにする必要があります。

質問2)通常、参照される可能性のあるすべてのアーティファクトのすべてのバージョンを使用して、親でプロパティを宣言します。複数のモジュールがバージョンを共有している場合、必要なプロパティは1つだけです。親は次のようになります。

<groupId>com.mycompany.myproject</groupId>
<artifactId>myproject-parent</artifactId>
<version>1.1.1-SNAPSHOT</version>
<packaging>pom</packaging>
<properties>
   <myproject.version>1.1.1-SNAPSHOT</myproject.version>
</properties>

.......

<modules>
   <module>../myproject-module1</module>
   ...
</modules>

子供は他のモジュールを参照できます

<version>${myproject.version}</version>

LATESTを使用して依存関係を宣言することは非常に悪い習慣です。バージョン1.1.1でこれを行うとしましょう。これで、バージョン1.1.2-SNAPSHOTを使用して作業しています。おそらく、このバージョンのアーティファクトがローカルリポジトリにインストールされています。

ここで、何らかの理由で、たとえば本番環境のバグのために、バージョン1.1.1を再構築する必要があるとしましょう。ビルドは新しいバージョンを使用します。運が良ければ、ビルドが失敗します。運が悪いと、気付かれずに本番環境に入る場合もあります。

最後に重要なことですが、一部の人々は、プロパティ値を使用して子バージョンを宣言することを好みます。これは強く非推奨であり、mavenによって警告として報告されます。私は個人的にそれをしません。この理由は、ビルドの再現性、およびMavenがリリースビルドは決して変更されないと想定しているという事実にも関連しています。モジュールのバージョンを外部から調整できるようにすることは、実際には良い考えではありません。

編集:

モジュールのバージョンが揃っていない場合。

実際には、両方のシナリオを混在させることができます。たとえば、次のことができます。

---コンポーネント1

---コンポーネント2

---コンポーネント3

------ Comp3Module1

------ Como3Module2

------ Comp3Module3

親と3つのコンポーネントのバージョンが異なり、component3の3つのモジュールが前に説明したように同じバージョンを共有している場合。

質問1)この場合、各モジュールにはバージョンが個別に指定されています。前に述べたように、プロパティを使用してモジュールのバージョンを指定するのは悪いことです。理由は、バージョンを文字で指定することしか推奨できない理由です。すでに述べたように、バージョニングを管理するための最良の方法は、リリースプラグインを使用して、SVNなどのバージョン管理システムと統合することです。他の回答はそれを使用する方法の詳細を与えるので、要求されない限り、それをさらに詳しく述べることはしません。

質問2)推奨されるアプローチは、同じバージョンを共有する場合の説明と同じですが、いくつかのプロパティが必要です。親は次のようになります。

<properties>
   <myproject.group>com.mycompany.myproject</myproject.group>
   <component1.version>1.1.1-RC1</component1.version>
   <component2.version>1.1.1-RC2</component2.version>
   <component3.version>2.0.0</component3.version>
<properties>

次に、依存関係管理を使用して、バージョン管理を親で一元化できます。

たとえば、親pomでは、

<dependencyManagement>
   <dependencies>
      <dependency>
         <groupId>${myproject.group}</groupId>
         <artifactId>component1</artifactId>
         <version>${component1.version}</version>
      </dependency>
      <dependency>
        <groupId>${myproject.group}</groupId>
         <artifactId>component2</artifactId>
         <version>${component2.version}</version>
         <type>war</type>
      </dependency>
      <dependency>
         <groupId>${myproject.group}</groupId>
         <artifactId>comp3module1</artifactId>
         <version>${component3.version}</version>
        <type>ejb</type>
      </dependency>
      <dependency>
         <groupId>${myproject.group}</groupId>
         <artifactId>comp3module1</artifactId>
         <version>${component3.version}</version>
        <type>ejb-client</type>
      </dependency>
      <dependency>
         <groupId>${myproject.group}</groupId>
         <artifactId>comp3module2</artifactId>
         <version>${component3.version}</version>
        <type>war</version>
      </dependency>
   </dependencies>
</dependencyManagement>

これで、他のモジュールから任意のモジュールを参照するには、次のように簡単です。

<dependency>
   <groupId>${myproject.group}</groupId>
   <artifactId>component1</artifactId>
</dependency>
<dependency>
   <groupId>${myproject.group}</groupId>
   <artifactId>comp3module1</artifactId>
   <type>ejb-client</type>
</dependency>

バージョンは、親から自動的に管理されます。子の依存関係でそれらを維持する必要はありませんが、これも冗長ではなくなります。

5
Juan

これは私が思いついたものです。これは、この continuous-releasing-of-maven-artifacts 記事に基づいています。

親POM:

<properties>
    <!-- versions of modules -->
    <main.version>1.0</main.version>
    <revision>SNAPSHOT</revision> <!-- default revision -->
    <Module1.revision>${revision}</Module1.revision>
    <Module2.revision>${revision}</Module2.revision>
    <Module3.revision>${revision}</Module3.revision>
    <Module4.revision>${revision}</Module4.revision>
    <Module5.revision>${revision}</Module5.revision>
    <Module1.version>${main.version}-${Module1.revision}</Module1.version>
    <Module2.version>${main.version}-${Module2.revision}</Module2.version>
    <Module3.version>${main.version}-${Module3.revision}</Module3.version>
    <Module4.version>${main.version}-${Module4.revision}</Module4.version>
    <Module5.version>${main.version}-${Module5.revision}</Module5.version>
</properties>

プロジェクト間の依存関係がある子POMの例:

    <groupId>com.xyz</groupId>
    <artifactId>Module4</artifactId>
    <packaging>jar</packaging>
    <version>${Module4.version}</version>

    <parent>
        <groupId>com.xyz</groupId>
        <artifactId>ParentProject</artifactId>
        <version>1.0</version>
    </parent>   

    <dependencies>
        <dependency>
            <groupId>com.xyz</groupId>
            <artifactId>Module1</artifactId>
            <version>${Module1.version}</version>
        </dependency>
        <dependency>
            <groupId>com.xyz</groupId>
            <artifactId>Module2</artifactId>
            <version>${Module2.version}</version>
        </dependency>
        <dependency>
            <groupId>com.xyz</groupId>
            <artifactId>Module3</artifactId>
            <version>${Module3.version}</version>
            <type>jar</type>
        </dependency>
    <dependencies>

1)サイクルの最初に、1つのMavenコマンドで親とモジュールを同じバージョンに設定するにはどうすればよいですか?

もう必要ありません。親POMは同じバージョンのままにすることができ、親POMが変更された場合にのみ変更されます。その場合、mvn version:set -DnewVersion=1.1.1を使用できます。ただし、このアプローチを行う必要はありません。

代わりに、プロパティmain.versionを使用してバージョンを動的に設定できます。例えば。 mvn clean deploy -Dmain.version=1.1.1また、バージョン番号を動的に渡すように強制するには、上記の親POMに含めたデフォルトのmain.versionプロパティを省略できます。

2)mod1のバージョンとmod2の参照の両方を一度にmod1のバージョンに更新するにはどうすればよいですか?

これは基本的に、リビジョンの管理方法に要約されます。 mvnコマンドでrevisionプロパティを設定しない場合、すべてのモジュールでSNAPSHOTがリビジョンとして使用されます。 revisionプロパティをRC1に設定すると、すべてのモジュールがそのリビジョンを取得します。さらに、revisionRC1に設定し、Module4.revisionRC2に設定すると、Module4はRC2を取得し、他のすべてのモジュールはRC1を取得します。これは、モジュールごとに動的なリビジョンを持つことを求めるクライアントの要求を満たします。

ここではいくつかの例を示します。

  • mvn clean deploy -Dmain.version=1.1.1すべてのモジュールをバージョン1.1.1-SNAPSHOTに設定します。
  • mvn clean deploy -Dmain.version=1.1.1 -Drevision=RC1すべてのモジュールをバージョン1.1.1-RC1に設定します。
  • mvn clean deploy -Dmain.version=1.1.1 -Drevision=RC1 -DModule4.revision=RC2バージョン1.1.1-RC1に設定されているModule4を除き、すべてのモジュールをバージョン1.1.1-RC2に設定します。

言及しなければならない警告があります。依存するモジュールのバージョン(たとえば、Module1)をRC2にインクリメントする場合、それを使用するすべてのモジュールのバージョンもインクリメントする必要があります。たとえば、Module4もRC2(または次のバージョン)にインクリメントしないでください。これはクライアントが認識しているものであり、すべてのモジュールが同じバージョンであることが望ましい理由でもあります。しかし、私はそれがいかにダイナミックであるかが本当に好きです。基本的に、バージョンはコマンドラインで設定され、POMファイルの更新は必要ありません。

1
Jose Martinez

1)過去にversion:setも試しましたが、正しく動作しませんでした。これはrelease:prepareと同じプロセスを行うことになっていますが、実際には行いません。だからあなたが試すことができるのはmvn release:prepare -DautoVersionSubmodules -DdryRun。これは、リポジトリに何もチェックせず、タグを作成せずにすべての更新を行うことになっています。

2)ClearTKプロジェクトは、あなたが行ったのと同じような戦略に従っていたと私は信じています。彼らは、各モジュールが独自のリリースサイクルを持つマルチモジュールプロジェクトを維持していました。状況を常に把握するために、依存関係バージョンの不一致について警告するカスタムmavenプラグインを実装しました。

https://github.com/ClearTK/cleartk/tree/master/consistent-versions-plugin

このようなプラグインでは、要求された更新は行われませんが、少なくとも更新が必要な場合は通知する必要があります。問題を実際に修正するには、ClearTKと同じルートをたどって独自のMavenプラグインを実装することを検討してください(または、ClearTKが最終的に行ったことを実行します:同期リリースサイクルに切り替えます;))。

1
rec

1)@recが言ったように、Mavenリリースプラグインはトリックを行います

$ mvn release:prepare -DautoVersionSubmodules=true
$ mvn release:perform

2)mod2からmod1への依存関係を次のように定義できます。

<dependency>
    <groupId>com.xxx</groupId>
    <artifactId>mod1</artifactId>
    <version>LATEST</version>
</dependency>

詳細: Mavenに最新バージョンの依存関係を使用するように指示するにはどうすればよいですか?

私は両方のソリューションをテストしましたが、うまくいきました!それがあなたを助けることを願っています:)

0
Andrés