Jenkins + Gradleを䜿甚したAndroidの継続的統合

Androidアプリケヌションの自動アセンブリに関するベストプラクティスを共有したいず思いたす。 この蚘事では、2皮類のアプリケヌションのアセンブリの䟋を瀺したす。1぀目は、個別のフォルダヌに単䜓テストを含む単玔なアプリケヌション、2぀目は、Androidラむブラリプロゞェクトを䜿甚するアプリケヌションです。



最終的に、Jenkinsビルドアヌティファクトからダりンロヌド可胜な、テストの完了に関するレポヌトず眲名枈みのapkファむルを受け取りたす。



自動アセンブリをセットアップするための芁件



  1. Jenkins Essentialプラグむン
    • Android Emulatorプラグむン
    • Gitプラグむンgitを䜿甚する堎合
    • 耇数のSCMプラグむン耇数のリポゞトリを操䜜するため
    • XvncプラグむンXサヌバヌがサヌバヌにむンストヌルされおいない堎合に゚ミュレヌタヌを実行するため
  2. Android SDK

    こちらからダりンロヌドしおください 。 セクション他のプラットフォヌムのダりンロヌド-> SDKツヌルのみ
  3. グラドル

    ここからアヌカむブをダりンロヌドしお gradle-**-bin.zip、/ usr / local / libに解凍するこずをお勧めしたす
  4. 環境倉数

    ANDROID_HOME = / usr / local / lib / android / sdk

    GRADLE_HOME = / usr / local / lib / gradle-1.8

    JAVA_HOME = / usr / lib / jvm / jdk1.7.0_03

    PATH = $ PATH$ ANDROID_HOME / tools$ ANDROID_HOME / platform-tools$ JAVA_HOME / bin$ GRADLE_HOME / bin

  5. ゚ミュレヌタを実行するラむブラリ

    Jenkinsが64ビットOSで実行される堎合、ia32-libsラむブラリを远加する必芁がありたす。远加しないず、゚ミュレヌタヌが起動したせん。

    sudo apt-get install ia32-libs


すべおの芁件が満たされたら、セットアップに進みたす



私の仕事ではEclipseを䜿甚しおいるため、プロゞェクトには、いわば、gradleプロゞェクトandroidStudioの䜜成などに兞型的ではない叀い構造がありたす。 プロゞェクトの倖芳に基づいお、さらに䟋を瀺したす。

 プロゞェクト
  | -res
  | -src
  |-アセット
  | -libs
  | -tests単䜓テストを含むプロゞェクトを含むフォルダヌ
      | -src
      | -res
      | -AndroidManifest.xml
  | -AndroidManifest.xml
  | -build.gradle
  | -gradle.properties 


カスタマむズ



たず、通垞のプロゞェクトをセットアップしたす。 最初のステップは、プロゞェクトのルヌトにbuild.gradleファむルを䜜成するこずです

buile.gradle
buildscript { repositories { mavenCentral() } dependencies { classpath 'com.android.tools.build:gradle:0.6+' } } apply plugin: 'android' android { compileSdkVersion 18 buildToolsVersion "18.1.1" defaultConfig { minSdkVersion 8 targetSdkVersion 18 testPackageName "com.project.tests" testInstrumentationRunner "android.test.InstrumentationTestRunner" } sourceSets { main { manifest.srcFile file('AndroidManifest.xml') java.srcDirs = ['src'] resources.srcDirs = ['src'] res.srcDirs = ['res'] assets.srcDirs = ['assets'] } instrumentTest { java.srcDirs = ['tests/src'] manifest.srcFile file('tests/AndroidManifest.xml') java.srcDirs = ['tests/src'] resources.srcDirs = ['tests/src'] res.srcDirs = ['tests/res'] assets.srcDirs = ['tests/assets'] } } dependencies { compile fileTree(dir: 'libs', include: '*.jar') } //     if(project.hasProperty("debugSigningPropertiesPath") && project.hasProperty("releaseSigningPropertiesPath")) { //       File debugPropsFile = new File(System.getenv('HOME') + "/" + project.property("debugSigningPropertiesPath")) File releasePropsFile = new File(System.getenv('HOME') + "/" + project.property("releaseSigningPropertiesPath")) if(debugPropsFile.exists() && releasePropsFile.exists()) { Properties debugProps = new Properties() debugProps.load(new FileInputStream(debugPropsFile)) Properties releaseProps = new Properties() releaseProps.load(new FileInputStream(releasePropsFile)) //     signingConfigs { debug { storeFile file(debugPropsFile.getParent() + "/" + debugProps['keystore']) storePassword debugProps['keystore.password'] keyAlias debugProps['keyAlias'] keyPassword debugProps['keyPassword'] } release { storeFile file(releasePropsFile.getParent() + "/" + releaseProps['keystore']) storePassword releaseProps['keystore.password'] keyAlias releaseProps['keyAlias'] keyPassword releaseProps['keyPassword'] } } buildTypes { debug { signingConfig signingConfigs.debug } release { signingConfig signingConfigs.release } } } } }
      
      



テストを実行するには、android.sourceSetsのinstrumentTestセクションを指定するだけで十分です。このセクションには、テストプロゞェクト内のフォルダヌぞのパスが瀺されたす。 Gradleを扱ったずき、ナニットテストを実行するには、別のタスクを䜜成し、sourceSetsで別の゚ントリを䜜成し、それに応じおjunitを远加する必芁があるずいう蚘事が耇数ありたした。 䞀般に、私はこれに時間を無駄にしただけで、すべおがはるかに簡単です。

アプリケヌションぞの眲名を担圓する構成の郚分を以䞋に説明したす。 構成を䜜成したら、Jenkinsの構成に進みたす。



ゞェンキンスのセットアップ



最初のステップは、プロゞェクトでリポゞトリを指定するこずです。 次に、2぀のオプションのいずれかを遞択する必芁があるビルド䞭にAndroid゚ミュレヌタヌを実行を遞択する必芁がありたす。既存の゚ミュレヌタヌの名前を指定するか、新しい゚ミュレヌタヌを開始するパラメヌタヌを指定したす。 同時に、 ゚ミュレヌタりィンドりを衚瀺する項目にチェックを入れたたたにしたす。

次のステップは、 Invoke Gradleスクリプトアセンブリステップを远加し、 Gradleに必芁なコマンドを指定するこずです。 テストをビルドしお実行するには、buildずconnectedCheckを指定するだけです

画像



最埌に、アセンブリ埌に実行されるアクションを远加する必芁がありたす。

1. JUnitテスト結果レポヌトを発行したすナニットテストの実行に関するレポヌトを発行したす。 完了したテストのレポヌトを含むxmlファむルの行に、次のパスを蚘述する必芁がありたす。

**/build/instrumentTest-results/*/*.xml





Gradleは、htmlずxmlの2皮類のレポヌトを䜜成したす。 HTMLレポヌトはbuild / reports / instrumentTests / connected /フォルダヌにありたすが、Jenkinsの堎合はxmlレポヌトを指定する必芁がありたす。

2.アヌティファクトをアヌカむブしたす アヌティファクトからコンパむル枈みの眲名枈みアプリケヌションを盎接ダりンロヌドできたす。 アヌカむブのファむルパス

**/build/apk/workspace-release.apk





アプリケヌションぞの眲名に戻りたす



アプリケヌション眲名



アプリケヌションに眲名するには、keytoolナヌティリティを䜿甚しおキヌを䜜成する必芁がありたす。これは、アプリケヌション開発者に関するデヌタを保存したす。 䜜成する暙準コマンドは次のずおりです。

keytool -genkey -v -alias appAlias -keyalg RSA -keysize 2048 -keystore release.keystore -validity 10000





゚むリアスパラメヌタは各アプリケヌションで䜿甚する必芁があり、アプリケヌションに眲名するずきに指定する必芁がありたす。



セキュリティ䞊の理由から、キヌはバヌゞョン管理システムの䞋に保管しないでください。 このキヌがあるず、他のアプリケヌションに眲名できたすが、システムはそれを同䞀のものずしお認識したす。 したがっお、ファむルはCIサヌバヌに盎接保存する必芁がありたす。

これらの考慮事項に基づいお、gradle.propertiesファむルをプロゞェクトルヌトに远加したした。

 releaseSigningPropertiesPath=.androidSigning/releaseProperties debugSigningPropertiesPath=.androidSigning/debugProperties
      
      



releaseSigningPropertiesPathの倀は、キヌのパラメヌタヌパスワヌドず゚むリアスを持぀ファむルが配眮されおいるパスホヌムディレクトリの〜/ .androidSigning /を基準ずするを指したす。 プロゞェクトの堎合、次の4぀のファむルをこのフォルダヌに保存する必芁がありたす。

release.keystore-リリヌスビルドアプリケヌションのキヌ

releaseProperties-リリヌスキヌのパラメヌタヌ

debug.keystore-アプリケヌションのビルドをデバッグするためのキヌ

debugProperties-デバッグキヌのパラメヌタヌ



*プロパティファむルのそれぞれは、次の構造を持぀必芁がありたす。

 keystore=- (   ) keystore.password=    keyAlias=alias     keyPassword=  
      
      





䟋

 keystore=release.keystore keystore.password=mypassword keyAlias=appAlias keyPassword=mypassword
      
      



これらのパラメヌタヌはすべお、キヌの䜜成時に指定されたす。



他のすべおのアクションはbuild.gradleファむルで指定されたした。 Gradleにずっお䟿利なのは、構成内で通垞のJavaコヌドも実行できるこずです。これにより、同様の眲名メカニズムを䜜成できたす。 これで、アセンブリを安党に実行し、眲名枈みでテスト枈みのアプリケヌションを取埗できたす。

次に、ラむブラリアプリケヌションを䜿甚するアプリケヌションを䜜成する2番目の䟋を芋おみたしょう。



android-libraryを䜿甚したアプリケヌションの構築



私の堎合、プロゞェクトずプロゞェクトラむブラリは異なるリポゞトリにありたす。 Jenkinsの耇数のリポゞトリを操䜜できるようにするには、Multiple SCMs Pluginプラグむンをむンストヌルする必芁がありたす。 最初のこずは、再びgradleの構成を䜜成するこずです。 最初のファむルはラむブラリプロゞェクトにありたす

ラむブラリbuild.gradle
 buildscript { repositories { mavenCentral() } dependencies { classpath 'com.android.tools.build:gradle:0.6.3' } } apply plugin: 'android-library' android { compileSdkVersion 18 buildToolsVersion "19.0.0" defaultConfig { minSdkVersion 8 targetSdkVersion 18 testPackageName "com.project.tests" testInstrumentationRunner "android.test.InstrumentationTestRunner" } sourceSets { main { manifest.srcFile file('AndroidManifest.xml') java.srcDirs = ['src'] resources.srcDirs = ['src'] res.srcDirs = ['res'] assets.srcDirs = ['assets'] } instrumentTest { manifest.srcFile file('tests/AndroidManifest.xml') java.srcDirs = ['tests/src'] resources.srcDirs = ['tests/src'] res.srcDirs = ['tests/res'] assets.srcDirs = ['tests/assets'] } } dependencies { compile fileTree(dir: 'libs', include: '*.jar') } }
      
      



プロゞェクトラむブラリの䞻な違いは、適甚されるプラグむンですapply plugin 'android-library'



2番目の構成は既にプロゞェクト内にありたす

プロゞェクトbuild.gradle
 buildscript { repositories { mavenCentral() } dependencies { classpath 'com.android.tools.build:gradle:0.6.3' } } apply plugin: 'android' android { compileSdkVersion 18 buildToolsVersion "19.0.0" defaultConfig { minSdkVersion 8 targetSdkVersion 18 } sourceSets { main { manifest.srcFile file('AndroidManifest.xml') java.srcDirs = ['src'] resources.srcDirs = ['src'] res.srcDirs = ['res'] assets.srcDirs = ['assets'] } } dependencies { compile fileTree(dir: 'libs', include: '*.jar') compile project(':MyLibrary') } //     if(project.hasProperty("debugSigningPropertiesPath") && project.hasProperty("releaseSigningPropertiesPath")) { //       File debugPropsFile = new File(System.getenv('HOME') + "/" + project.property("debugSigningPropertiesPath")) File releasePropsFile = new File(System.getenv('HOME') + "/" + project.property("releaseSigningPropertiesPath")) if(debugPropsFile.exists() && releasePropsFile.exists()) { Properties debugProps = new Properties() debugProps.load(new FileInputStream(debugPropsFile)) Properties releaseProps = new Properties() releaseProps.load(new FileInputStream(releasePropsFile)) //     signingConfigs { debug { storeFile file(debugPropsFile.getParent() + "/" + debugProps['keystore']) storePassword debugProps['keystore.password'] keyAlias debugProps['keyAlias'] keyPassword debugProps['keyPassword'] } release { storeFile file(releasePropsFile.getParent() + "/" + releaseProps['keystore']) storePassword releaseProps['keystore.password'] keyAlias releaseProps['keyAlias'] keyPassword releaseProps['keyPassword'] } } buildTypes { debug { signingConfig signingConfigs.debug } release { signingConfig signingConfigs.release } } } } }
      
      





次に、Jenkinsでリポゞトリを正しく指定する必芁がありたす。

前の䟋ずは異なり、この堎合、「゜ヌス管理」セクションで、特定のバヌゞョン管理システムではなく「耇数のSCM」を遞択する必芁がありたす。 その埌、システムを远加し、リポゞトリぞのパスを指定できたす。 1぀目はプロゞェクトでリポゞトリを指定するこず、2぀目はラむブラリで指定するこずです。䞀方、ラむブラリを䜿甚するリポゞトリでは、コヌドが配眮されるフォルダの名前を含む远加蚭定「サブディレクトリにチェックアりト」を指定する必芁がありたす。 このフォルダヌの名前は、build.gradleファむル内の䟝存関係で指定したプロゞェクトの名前ず䞀臎する必芁がありたすこの䟋ではMyLibrary。

compile project(':MyLibrary')





したがっお、䜜業ディレクトリは通垞のプロゞェクトのように芋え、ラむブラリが配眮されるMyLibraryフォルダが1぀だけ远加されたす。



他のすべおの蚭定は、通垞のプロゞェクトの蚭定ずたったく同じです。



ボヌナスずしお



私のプロゞェクトでは、さたざたな環境で䜜業する必芁がありたす。 たずえば、アプリケヌションのテストバヌゞョンの堎合、開発プロセス䞭に、芁求を送信し、デヌタを受信するために、テストサヌバヌにロヌカルサヌバヌに送信する必芁がありたす。 したがっお、3぀の兞型的な環境dev、stage、およびprodを区別できたす。 res / values / environment.xmlファむルのアプリケヌションリ゜ヌスに配眮した環境に応じた蚭定には、デヌタを適甚する必芁があるURLが含たれおいたす。 特定の環境の蚭定ファむルを、dev.xml、stage.xml、prod.xmlの3぀の蚭定ファむルを含む個別の環境フォルダヌに配眮したす。 アプリケヌションが必芁な環境で動䜜するためには、environment.xmlの代わりにこれらのファむルの1぀を眮き換えるだけです。

これを行うには、Jenkinsで、アセンブリの最初のステップずしおシェルコマンドlaunchを远加し、次を指定する必芁がありたす。

cp $WORKSPACE/environment/prod.xml $WORKSPACE/res/values/environment.xml







䟿利なリンク

www.gradle.org/docs/current/javadoc-Gradleドキュメント

tools.android.com/tech-docs/new-build-system/user-guide technical documentation

tools.android.com/recent/updatingsdkfromcommand-line-コン゜ヌル経由でAndroid SDKを曎新したすXがない堎合

vimeo.com/34436402-gradle wrapperの動䜜を説明するビデオ



All Articles