0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Galleonプロビジョニングが特定のCI環境でのみ失敗する — JBoss Modulesの隠れたアーティファクト解決メカニズム

0
Posted at

TL;DR

WildFly/EAPのGalleonプロビジョニングを含むMavenビルドにおいて、CIのローカルリポジトリパスをデフォルト(${user.home}/.m2/repository)から変更すると、Galleonプロビジョニングが XMLPullParserException で失敗する場合がある。原因はGalleonのconfig生成フェーズで使われるJBoss Modulesの MavenResolver が、Mavenのsettings.xmlや -Dmaven.repo.local を一切参照せず、独自のシステムプロパティのみに依存しているため。

環境

項目 OpenShift(成功) GitLab CI(失敗)
ベースイメージ ubi8-openjdk-17 ubi9-minimal + OpenJDK 17
Maven 3.8系 3.9系
Java 17 17
Galleonプラグイン 同一バージョン 同一バージョン
settings.xml 同一 同一
Nexus 同一 同一
ローカルリポジトリ ${user.home}/.m2/repository(デフォルト) /builds/.../.m2/repository(カスタム)

事象

GitLab CIでGalleonプロビジョニングを含むMavenビルドを実行すると、以下のエラーチェーンでビルドが失敗する。

org.jboss.modules.xml.XmlPullParserException:
  Failed to resolve artifact 'org.jboss:jboss-vfs:3.3.0.Final-redhat-00001'
  (position: END_TAG seen ...@30:72)
    → could not load module org.jboss.vfs
    → error loading module
    → failed to resolve artifact
    → provisioning failed

OpenShiftでは同一の設定・同一のpom.xmlで成功する。Maven/Java/Galleonのバージョンをすべて揃えても再現する。

調査の経緯

排除した仮説

仮説 検証結果
Nexusのネットワーク疎通 問題なし。jarは取得できていた
settings.xml の差異 effective-settings で同一であることを確認
Maven バージョン差異(3.8 vs 3.9) GitLab CI上でMaven 3.8に変更しても同じエラー
Java バージョン差異 両環境ともOpenJDK 17
Galleonプラグインバージョン 同一
Nexus上のpom/jarの破損 両方正常に存在(pom: 7.5KB, jar: 137.3KB)
_remote.repositories のキャッシュ 削除しても同じエラー。そもそもキャッシュゼロで再現

ブレークスルーとなった観察

  1. ビルド後のローカルリポジトリにvfsのjarはあるが、pomがない。Maven本体の依存解決(warビルド)では、推移的依存の解決が不要な場合にpomの取得をスキップすることがある。

  2. エラーの起点は org.jboss.modules.xml.ModuleXmlParser。これはMaven本体のクラスではなく、JBoss Modulesのクラスである。

  3. ビルド成果物(target/bootable-jar-build-artifacts/)内のmodule.xmlに <artifact name="org.jboss:jboss-vfs:..."/> がそのまま残っていた。fat server(デフォルト)では <resource-root path="jboss-vfs-....jar"/> に書き換わるべきだが、書き換えに失敗していた。

根本原因

Galleonプロビジョニングのconfig生成フェーズでは、embedded WildFlyサーバーがフォークされて起動する。このプロセス内でmodule.xmlが読み込まれ、<artifact> 要素のアーティファクト解決にはJBoss Modulesの MavenResolver が使われる。

このResolverはMaven本体とは完全に独立した仕組みであり、以下の特性を持つ:

  • settings.xml一切読まない
  • -s /path/to/settings.xml(Mavenの設定ファイル指定)を無視する
  • -Dmaven.repo.local(Maven本体のローカルリポジトリ指定)を無視する
  • ローカルリポジトリは独自のシステムプロパティ maven.repo.local で指定する(デフォルト: ${user.home}/.m2/repository
  • リモートリポジトリは独自のシステムプロパティ remote.maven.repo で指定する(デフォルト: なし)

注意: JBoss Modulesのシステムプロパティ maven.repo.local とMaven本体の -Dmaven.repo.local は同名だが、JBoss Modulesは自身のResolverインスタンス生成時にこのプロパティを読む。Mavenの -D で渡したプロパティはMavenのJVMプロセスには設定されるが、Galleonからフォークされたembeddedサーバープロセスには引き継がれない場合がある

GitLab CI環境では、ローカルリポジトリのパスがデフォルトの ${user.home}/.m2/repository から /builds/.../.m2/repository に変更されていた。Maven本体は -Dmaven.repo.local や settings.xml の <localRepository> でこのカスタムパスを認識するが、JBoss Modulesの MavenResolver はデフォルトの ${user.home}/.m2/repository を参照し続ける。そこにはアーティファクトが存在しないため、解決に失敗する。

OpenShiftではローカルリポジトリがデフォルトパスにあったため、同じビルドプロセス内でMaven本体がダウンロードしたアーティファクトを、JBoss Modulesの MavenResolver もそのまま参照でき、問題が発生しなかった。

対処

推奨: ローカルリポジトリをデフォルトパスに戻す

CI環境でローカルリポジトリのパスを変更している設定をすべてコメントアウトまたは削除し、デフォルトの ${user.home}/.m2/repository を使用する。これが最もシンプルかつ確実な対処。

代替: JBoss Modules固有のシステムプロパティを設定する

ローカルリポジトリのパスを変更する必要がある場合は、Mavenコマンドに以下のシステムプロパティを追加する。

mvn package verify \
  -Dmaven.repo.local=/path/to/custom-repo \
  -Dremote.maven.repo=https://nexus.example.com/repository/your-group-repo/

maven.repo.local だけでは不十分な場合がある。Maven本体がpomをダウンロードしないアーティファクトが存在し、JBoss Modulesがpomも含めて解決を試みるため、remote.maven.repo でリモートからの取得を可能にする必要がある。

さらに、integration-test/verifyフェーズでbootable jarを起動するプラグインがある場合は、フォークされるサーバーのJVMにも同じプロパティを渡す必要がある。

教訓

MavenのビルドにはMaven以外のアーティファクト解決が含まれている

Galleonを使うWildFly/EAPのビルドでは、以下の3つのアーティファクト解決メカニズムが混在する:

  1. Maven本体のResolver(Apache Maven Resolver / Aether): pom.xmlの <dependencies> を処理。settings.xmlを読む。
  2. GalleonのArtifactResolver: feature-packの取得やmodule.xmlテンプレートのartifact書き換えを処理。Maven本体のResolverを内部的に利用する。
  3. JBoss Modulesの MavenResolver: config生成やembedded server起動時にmodule.xmlの <artifact> 要素を処理。Maven本体とは完全に独立。settings.xmlを読まない。

CI環境でローカルリポジトリのパスを変更すると、1と2は追従するが、3は追従しない。これが今回の問題の本質である。

既知の同類の問題

以前の調査で判明した「JBoss Modules の MavenResolver${user.home}/.m2/repository をハードコードする」という挙動は、Galleon以外の文脈でも問題になりうる。

参考リンク

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?