Maven を Gradle 上で実行 - SVNKit によるソースのチェックアウト付き
前回 は Groovy スクリプトで Maven を実行してみましたが、今回は Gradle 上で実行してみる事にします。
- Gradle 1.6
- Maven 3.0.5
ソースは http://github.com/fits/try_samples/tree/master/blog/20130731_2/
既存資産の pom.xml を Gradle に移行するのが困難なケース(数が多すぎるとか)で活用できるかもしれません。
Gradle 上で Maven 実行1
Gradle のビルドスクリプト内で MavenCli を使うには下記の設定が必要になります。
ここで 1つ注意点があります。
前回のように MavenCli.main(String[]) を使うと System.exit() が呼び出され Gradle 上で実行するには不都合が生じるので、System.exit() を呼び出さない下記のメソッドを使います。(どちらでも可)
- MavenCli.main(String[], ClassWorld)
- MavenCli.doMain(String[], ClassWorld)
gradle_mvn/build.gradle
import org.apache.maven.cli.MavenCli // ビルドスクリプト内で MavenCli を使うための設定 buildscript { repositories { mavenCentral() } dependencies { classpath 'org.apache.maven:maven-embedder:3.0.5' } } task mvn << { def argsLine = "-f work/sample-app/pom.xml clean package -Dmaven.test.skip=true" // Maven の実行 MavenCli.doMain(argsLine.split(' '), null) }
上記では mvn タスクに Maven の実行を割り当てているので gradle mvn で実行します。
実行結果
> gradle mvn :mvn [INFO] Scanning for projects... ・・・ [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ ・・・ BUILD SUCCESSFUL Total time: 11.482 secs
特に問題無く Maven が Gradle 上で実行されると思います。
Gradle 上で Maven 実行2
次に SVNKit を使えば、Subversion からチェックアウトしたソースを Maven を使ってビルドするような処理を Gradle 上で比較的容易に実現できます。
ついでに Maven の処理が失敗した場合に RuntimeException を throw する処理を追加しました。
gradle_mvn+svn/build.gradle
import org.tmatesoft.svn.core.* import org.tmatesoft.svn.core.wc.* import org.apache.maven.cli.MavenCli buildscript { repositories { mavenCentral() } dependencies { classpath 'org.tmatesoft.svnkit:svnkit:1.7.8' classpath 'org.apache.maven:maven-embedder:3.0.5' } } // Subversion のリポジトリURL def repoUrl = 'http://localhost/svn/sample-app' def workDir = 'work' task svnco << { def manager = SVNClientManager.newInstance() def client = manager.updateClient // Subversion のリポジトリからソースをチェックアウト def res = client.doCheckout( SVNURL.parseURIDecoded(repoUrl), new File(workDir), SVNRevision.HEAD, SVNRevision.HEAD, SVNDepth.INFINITY, true ) println "checkout revision = ${res}" } task mvn << { def cmd = "-f ${workDir}/pom.xml package -Dmaven.test.skip=true" def res = MavenCli.doMain(cmd.split(' '), null) if (res != 0) { // Maven 処理の失敗時 throw new RuntimeException() } } // タスクの依存関係を設定(mvn は svnco に依存) mvn.dependsOn svnco task clean << { delete(workDir) }
実行結果
> gradle mvn :svnco checkout revision = 1901 :mvn [INFO] Scanning for projects... ・・・ [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ ・・・ BUILD SUCCESSFUL Total time: 1 mins 25.088 secs
Gradle 上で Maven 実行3
更に、Maven のプロファイル毎(今回は prd, stg, dev の 3種)にチェックアウト・ビルドして、ビルド結果の war ファイルをリネームして同じディレクトリにまとめるような処理も Gradle なら比較的簡単に実装できます。
gradle_mvn+svn_profiles/build.gradle
import org.tmatesoft.svn.core.* import org.tmatesoft.svn.core.wc.* import org.apache.maven.cli.MavenCli buildscript { repositories { mavenCentral() } dependencies { classpath 'org.tmatesoft.svnkit:svnkit:1.7.8' classpath 'org.apache.maven:maven-embedder:3.0.5' } } // Subversion のリポジトリURL def repoUrl = 'http://localhost/svn/sample-app' def workDir = 'work' def destDir = 'dest' def profiles = ['prd', 'stg', 'dev'] task svnco << { def manager = SVNClientManager.newInstance() def client = manager.updateClient // プロファイル毎にループ profiles.each { profile -> // Subversion のリポジトリからソースをチェックアウト def res = client.doCheckout( SVNURL.parseURIDecoded(repoUrl), new File("${workDir}/${profile}"), SVNRevision.HEAD, SVNRevision.HEAD, SVNDepth.INFINITY, true ) println "${profile} checkout revision = ${res}" } } task mvn << { // プロファイル毎にループ profiles.each { profile -> def cmd = "-f ${workDir}/${profile}/pom.xml package -Dmaven.test.skip=true -P ${profile}" def res = MavenCli.doMain(cmd.split(' '), null) if (res != 0) { throw new RuntimeException() } } } task dest << { mkdir(destDir) // プロファイル毎にループ profiles.each { profile -> // 生成された war ファイルの末尾に .<profile名> を付けて // dest ディレクトリへフラットにコピー copy { from fileTree("${workDir}/${profile}") { include '**/target/*.war' }.files rename { "${it}.${profile}" } into destDir } } } mvn.dependsOn svnco dest.dependsOn mvn task clean << { delete(workDir) delete(destDir) }
なお、下記のような copy の仕方にするとディレクトリ階層を保ったまま dest にコピーされるので (例 dest/target/sample-app.war.prd にコピー)、上記では fileTree().files を使ってフラットにファイルをコピー (dest 直下にファイルを配置) するようにしています。
ディレクトリ階層を保ったままコピーする例
copy { // 下記のようにすると target ディレクトリごとコピーされてしまう from("${workDir}/${profile}") { include '**/target/*.war' } rename { "${it}.${profile}" } into destDir // 空ディレクトリをコピーさせないための設定 includeEmptyDirs = false }
実行結果
> gradle dest :svnco prd checkout revision = 1901 stg checkout revision = 1901 dev checkout revision = 1901 :mvn [INFO] Scanning for projects... ・・・ :dest BUILD SUCCESSFUL
出力されたファイルは下記のようになります。
出力ファイル
- dest ディレクトリ
- sample-app.war.dev
- sample-app.war.prd
- sample-app.war.stg