はじめに
Ionic(Cordova/Angular)アプリのAndroidビルドに時間がかかりすぎているせいで、Jenkinsのビルドが不安定になるという問題が発生しました。
そのため、mavenリポジトリの参照先をMaven Central リポジトリから、Nexusリポジトリに変更する対応を実施します。なお、AndroidビルドはGradleで実施していて、Nexusのリポジトリは社内向けのため認証があります。
環境
- "cordova-android": "8.1.0",
- "@ionic/angular": "5.1.0",
- "@ionic/core": "5.1.0",
Cordova フックスクリプトを作成する
リポジトリの参照先をNexusに変更するには、platforms/android
配下のbuild.gradle
を修正する必要があります。ただし、build.gradle
はビルド時に生成されるファイルであるため、手動で直接修正することはできません。
そのため、今回はCordovaフックスクリプトを作成することで、build.gradle
ファイルを修正します。
下記の通り、config.xml
の<platform name="android">
配下に行を追記することで、Androidのビルド前にスクリプト(build_scripts/android-before-build.js
)を呼び出すことができます。
config.xml
<platform name="android"> <hook src="build_scripts/android-before-build.js" type="before_build" /> </platform>
続いてフックされるスクリプトを作成します。
build_scripts/android-before-build.js
/* * 最初に依存先を探すリポジトリをNexusに設定する。 */ const fs = require('fs'); const path = require('path'); const async = require('async'); module.exports = context => { 'use strict'; const repoUrl = '[NexusリポジトリのURL]'; const env = process.env; const gradleRepo = `maven { url "${repoUrl}" credentials { username "${env.NEXUS_USER}" password "${env.NEXUS_AUTH}" } }`; if (env.NEXUS_USER == null || env.NEXUS_AUTH == null) { return; } return new Promise((resolve, reject) => { const platformRoot = path.join( context.opts.projectRoot, 'platforms/android' ); const gradleFiles = findGradleFiles(platformRoot); // 最初に依存先を探すリポジトリをNexusに設定する。 async.each( gradleFiles, function(file, callback) { let fileContents = fs.readFileSync(file, 'utf8'); const insertLocations = []; const myRegexp = /\brepositories\s*{(.*)$/gm; let match = myRegexp.exec(fileContents); while (match != null) { if (match[1].indexOf(repoUrl) < 0) { insertLocations.push(match.index + match[0].length); } match = myRegexp.exec(fileContents); } if (insertLocations.length > 0) { insertLocations.reverse(); insertLocations.forEach(location => { fileContents = fileContents.substr(0, location) + gradleRepo + fileContents.substr(location); }); fs.writeFileSync(file, fileContents, 'utf8'); } callback(); }, function(err) { if (err) { reject(); } else { resolve(); } } ); }); /** * gradleファイルのパスの一覧を返す * * @param {*} dir Androidプロジェクトのパス * @return {*} gradleファイルのパスの一覧 */ function findGradleFiles(dir) { let results = []; const list = fs.readdirSync(dir); list.forEach(fileName => { const filePath = path.join(dir, fileName); const stat = fs.statSync(filePath); if (stat && stat.isDirectory()) { results = results.concat(findGradleFiles(filePath)); } else if (path.extname(filePath) === '.gradle') { results.push(filePath); } }); return results; } };
上記のスクリプトを実行するとbuild.gradle
がこのようになります。
スクリプト実行前のbuild.gradle
スクリプト実行後のbuild.gradle
スクリプト実行前には、mavenCentral
がリポジトリ探索の優先順位の一番だったのに、スクリプト実行後には、Nexusのリポジトリが探索の優先順位の一番になっていることがわかります。
スクリプトの処理内容について説明します。
上記のスクリプトは、repositories
という文字列の後に下記の文言を追加するというものです。
maven { url [NexusリポジトリURL] credentials { username [Nexusリポジトリ アカウントID] password [Nexusリポジトリ パスワード] } }
こうすることで、認証付きのNexusリポジトリにアクセスできるようになります。
参考記事
android - Specify different repositories when using Cordova gradle wrapper - Stack Overflow
gradle + bitbucket + 社内向け (認証あり) maven リポジトリの設定手順 - Qiita
Where to put Gradle configuration (i.e. credentials) that should not be committed? - Stack Overflow