Mavenを使っての開発では1プロジェクトを役割ごとに分割し、マルチプロジェクトとするのが鉄板ですね。

私が以前担当したJava + Spring Frameworkも、まさにこういった構成で開発を進めるスタイルでした。

[Java][Spring]Springのオレオレプロジェクト構成をチラ見せ!
Spring Frameworkで開発した、稼働実績があるプロジェクトの構成をご紹介いたします。 バージョンは以下の通りです。...

粒度を細かくし、それぞれを小さく簡潔に保つことのメリットは大きいです。

もともとは1つのプロジェクトですから、親と子が依存する関係にあります。
そのため「運用と新規開発を同時並行」で進めるようなケースでは、稀にビルド同士が干渉し「次のバージョン向けの修正が、誤ってステージングに入っちゃった」というような、まったく無意味でただただ悲しい事故が起きることもあります。

これは「タイミング悪い」だけで片付けられません。
それでは、どうやって複数環境で成果物を管理すればよいのでしょうか。

Jenkinsで環境ごとにMavenのローカルリポジトリを住み分ける方法を考えてみます。

手元で確認したバージョンはJenkins 1.601です。

Jenkins

デフォルトとして設定できるもの

Jenkinsの管理 > システムの設定に進むと、デフォルトのMavenがどのようになっているのかチェックすることができます。
Mavenプロジェクト > ローカルリポジトリを見てください。

Default

特に何も行っていない状態では~/.m2/repositoryにMavenのローカルリポジトリが生成されます。
場所は${JENKINS_HOME}/.m2/repositoryです。

Local to the executor

Jenkinsではデフォルトで2本ビルドのラインがあります。
Local to the executorはそのラインの分だけリポジトリが用意されます。

場所は${JENKINS_HOME}/maven-repositories/nです。

Local to the workspace

ジョブ単位でリポジトリを管理します。
ワークスペースの下にリポジトリが作られますので、場所は${WORKSPACE}/.repositoryです。

ジョブ単位で設定できるもの

Jenkinsではジョブ単位でもMavenの設定を行うことができます。

ジョブ設定 > Mavenの呼び出しから「高度な設定」をクリックすると追加のオプションが表示されます。
高度な設定、見落とす方多いですよね。

専用のリポジトリを使用

ジョブ単位でリポジトリを用意するもので、つまり前述のLocal to the workspaceと同じですね。

リポジトリを直接指定する

mvnコマンドに「リポジトリを指定するオプション」を与えることが可能です。

mvn -Dmaven.repo.local=/path/to/environment/repository clean install

リポジトリを直接指定する方法としてはさらに次のようなこともできます、一応。

  • Maven自体を複数用意する
  • 高度な設定 > 設定ファイルでユーザ定義のsettings.xmlを指定する

リポジトリを分けることのデメリット

肥大化

Jenkinsはただでさえログやファイルをため込むものです。
ビルドの干渉を避けるためにMavenローカルリポジトリを分離する方法は間違いがありませんが、Jenkinsのさらなる肥大化につながってしまいます。

そのため、リポジトリを乱立しないようには考慮したほうがよさそうです。

ライブラリの追加

時々Mavenで扱えず、手動でjarを追加ことがあります。

単一リポジトリであればjarのインストールも一度ですが、リポジトリが増えるとそれだけ作業が増えてしまいます。
こういう作業に限って、対応が漏れてしまって土壇場で焦ってしまうことになるんですよね、、、

私は、乱暴ですが「cp -R」してコピーしてしまいました。

最適なケースは

私の担当するプロジェクトでは、親と子の2つにプロジェクトを分離しており、ビルド手順は次の通りです。

  • git更新
  • 親プロジェクトをmvn install
  • 子プロジェクトをmvn package
  • warをサーブレットコンテナにコピー

通常では上記手順を1つのジョブにまとめて「専用のリポジトリを使用」にチェックを入れれば事足りると思います。

しかし、ここで私は「ジョブは意味のある最小単位で構成するべし」というJenkinsマイスターの教えを思い出しました。

子プロジェクトのビルドが失敗した場合に、わざわざ一からやり直すのではなく、失敗したところからやり直したいですよね。

ということで、各手順をそれぞれジョブ化していきます。

こうなると「専用のリポジトリを使用」しても、子から親が参照できませんので、リポジトリを直接指定する必要が出てきます。

アンチな解決策

以前のプロジェクトでどうやってジョブを組み立てていたか見直してみると、なんとJenkinsでローカルリポジトリを管理していませんでした。

具体的には各ホスト上でgit cloneし、mvnコマンドを実行していたのです。
Jenkisは各ホストにシェルとを飛ばすために使っていた感じ、、、今考えるとかなりの力技ですね。

ホストが異なりますから、当然Mavenも別、ローカルリポジトリも別、、、ということ問題が起きなかったのでした。

Jenkisをシェル実行マシーンとしてしか使っていないというアンチな解決策でした。

おわりに

そもそもが、バージョンをしっかり管理しましょう。
はい、私はできていませんでした。
ゴメンナサイ。

大前提としてバージョンの管理をしっかりやる。
開発中のバタバタなものについては、漏れや競合が出るのを避けるために、Jenkinsで個別のローカルリポジトリを指定しましょう、という運用がベターではないでしょうか。

私は小、中規模程度のプロジェクトなので、大規模なプロジェクトにはあまり参考にならないかもしれませんがご容赦ください。

最後に、Mavenのリポジトリについて、Apache Maven Projectを見ると次のような説明がありましたので引用を掲載いたします。

What are the different types of profile? Where is each defined?
Per Project
– Defined in the POM itself (pom.xml).

Per User
– Defined in the Maven-settings (%USER_HOME%/.m2/settings.xml).

Global
– Defined in the global Maven-settings (%M2_HOME%/conf/settings.xml).

Profile descriptor
– a descriptor located in project basedir (profiles.xml) (unsupported in Maven 3.0: see Maven 3 compatibility notes)

http://maven.apache.org/guides/introduction/introduction-to-profiles.html

参考

世界はどこまでもシンプルである
Jenkinsをたった1コマンドで公開用Mavenリポジトリにしてしまう方法 #jenkinsja
http://daipresents.com/2012/post-4367/



2016年02月04日:表示崩れを修正

スポンサーリンク
ad_336
ad_336
  • このエントリーをはてなブックマークに追加
  • Evernoteに保存Evernoteに保存