Build dan test aplikasi Android secara otomatis dengan Gitlab Continuous Integration

in #firebase6 years ago (edited)

Dennis got wicked design skillz

Pada artikel ini, saya akan menjelaskan bagaimana kami di Oddbit, membangun Continuous Integration untuk aplikasi Android yang memungkinkan kita untuk mem-build, test, dan menyiapkan package yang siap dikirim ke client.

Diakhir artikel ini, anda akan menemukan konfigurasi Gitlab CI secara lengkap dan siap digunakan.


Click here to read the article in English

Gitlab

Gitlab mungkin tidak mendapatkan penghasilan sebanding dengan apa yang seharusnya mereka dapat. Tapi saya akan membagi keuntungan saya jika saya mendapatkan kesempatan nanti.

GitHub sangat bagus untuk komunitas open source. Tapi Gitlab adalah solusi one-stop-shop untuk tim developer seperti kita. Saya telah menulis beberapa artikel khusus tentang Gitlab CI, karena ini adalah salah satu hal yang paling saya sukai dengan platform ini.

Dalam contoh artikel ini, Anda dapat melihat bahwa saya telah mengonfigurasi script dengan "anchors" yang memungkinkan kami menggunakan kembali specs pekerjaan dengan cara modul DNRY. Baca lebih lanjut tentang itu di dokumentasi Gitlab jika Anda belum yakin tentang hal itu.

Step 1: Build

Untuk men-develop aplikasi Android di Gitlab CI, kita perlu men-setup enviroment, men-download dan menginstal beberapa paket terlebih dahulu.

.build_template: &build_template_def
  stage: build
  artifacts:
    expire_in: 4 hours
    paths:
    - app/build/outputs/
    - .android/

  before_script:
    # Extract the SDK version that we're building against
    - export ANDROID_COMPILE_SDK=`egrep '^[[:blank:]]+compileSdkVersion'  app/build.gradle | awk '{print $2}'`

    # Explict output for logging purpose only
    - echo $ANDROID_SDK_TOOLS
    - echo $ANDROID_COMPILE_SDK

    # Fetch the specified SDK tools version to build with
    - wget --quiet --output-document=/tmp/sdk-tools-linux.zip https://dl.google.com/android/repository/sdk-tools-linux-${ANDROID_SDK_TOOLS}.zip
    - unzip /tmp/sdk-tools-linux.zip -d .android

    # Set up environment variables
    - export ANDROID_HOME=$PWD/.android
    - export PATH=$PATH:$PWD/.android/platform-tools/

    # Install platform tools and Android SDK for the compile target
    - echo y | .android/tools/bin/sdkmanager "platforms;android-${ANDROID_COMPILE_SDK}"

    - chmod +x ./gradlew

build_debug:
  <<: *build_template_def
  only:
    - develop

  script:
    - ./gradlew assembleDebug

build_release:
  <<: *build_template_def
  only:
    - master
  script:
    - ./gradlew assembleRelease

Mari kita breakdown kasus ini menjadi beberapa bagian!

Pertama dimulai dengan mendownload SDK Tools versi terbaru, untuk melakukannya kita harus secara eksplisit menentukan versi yang ingin kita gunakan. Demi kenyamanan, saya menyimpan versi ANDROID_SDK_TOOLS ke dalam build environment variable, yang ditetapkan ke "3859397" (versi terbaru saat artikel ini ditulis).

tps://dl.google.com/android/repository/sdk-tools-linux-${ANDROID_SDK_TOOLS}.zip


Selanjutnya extract package tersebut ke dalam folder bernama .android di dalam folder project karena kita akan menyimpan file tersebut sebagai artefak ke pekerjaan berikutnya. Artifak ini dikonfigurasi agar expired setelah 4 jam, yang rasanya sangat cukup untuk menjalankan long running test. Untuk sementara hanya ini yang kita butuhkan, sedangkan untuk membuat package aplikasi yang siap dikirim ke client akan dibahas pada akhir artikel.

Setelah kita mengekstrak paket tersebut, kita dapat menggunakan sdkmanager CLI tool untuk melakukan semua pekerjaan yang sama seperti yang dilakukan Android Studio. Pada baris pertama, kita mengekstrak konfigurasi build target SDK dari app/build.gradle, kita akan menggunakannya untuk menginstall platform tool dan target SDK yang ingin kita kompile.

$ sdkmanager "platforms;android-${ANDROID_COMPILE_SDK}"



Yapss itu dia, commit, push, dan tunggu… atau langsung ke langkah berikutnya!

Step 2: Test

Dalam contoh ini, testing hanya menjalankan unit testing. Tapi seperti yang akan kita lihat di artikel berikutnya “Mendeploy aplikasi ke Firebase Test Lab dengan Gitlab CI”, kita dapat mengeksekusi CI Jobs secara paralel sebelum mengemasnya jika semua test berhasil.
unit_test:
  stage: test
  only:
    - develop
    - master

  before_script:
    - export ANDROID_HOME=$PWD/.android
    - export PATH=$PATH:$PWD/.android/platform-tools/

  script:
    - ./gradlew test



Seperti yang bisa kita lihat, tidak banyak yang bisa dijelaskan dalam langkah ini. Library yang telah didownload dan hasil generate dari build step dapat kita akses kembali, thanks to the artifacts configuration.

Step 3: Package


Akhirnya, jika semua proses berjalan dengan benar kita akan membuat sebuah file zip file yang dapat didownload dan dikirim ke project manager, client, atau siapapun yang ingin kita inginkan.

.package_template: &package_template_def
  before_script:
    - export VERSION_NAME=`egrep '^[[:blank:]]+versionName[[:blank:]]'  app/build.gradle | awk '{print $2}' | sed s/\"//g`
    - export VERSION_CODE=`egrep '^[[:blank:]]+versionCode[[:blank:]]'  app/build.gradle | awk '{print $2}'`
    - mkdir -p deliverables

    # Store some information about the build
    - touch ./deliverables/info.txt
    - echo "Build date          $(date)"                >> ./deliverables/info.txt
    - echo "App version name    ${VERSION_NAME}"        >> ./deliverables/info.txt
    - echo "App version code    ${VERSION_CODE}"        >> ./deliverables/info.txt
    - echo "Git branch          ${CI_COMMIT_REF_NAME}"  >> ./deliverables/info.txt
    - echo "Git commit          ${CI_COMMIT_SHA}"       >> ./deliverables/info.txt
    - echo "Gitlab pipeline     ${CI_PIPELINE_ID}"      >> ./deliverables/info.txt

package_develop:
  <<: *package_template_def
  stage: package
  environment: Development
  only:
    - develop
  script:
    - mv app/build/outputs/apk/app-debug.apk ./deliverables/NameOfTheApp-v$VERSION_NAME-$VERSION_CODE-debug.apk
  artifacts:
    expire_in: 3 days
    paths:
    - deliverables

package_release:
  <<: *package_template_def
  stage: package
  environment: Release
  only:
    - master
  script:
    - mv app/build/outputs/apk/app-release.apk ./deliverables/NameOfTheApp-v$VERSION_NAME-$VERSION_CODE-release.apk
  artifacts:
    expire_in: 4 weeks
    paths:
    - deliverables


Sederhananya script ini melakukan 2 hal yaitu:

  1. Me-rename file APK sesuai dengan nama aplikasi dan menambahkan informasi versi dari aplikasi.
  2. Menambahkan file keterangan tambahan mengenai build dari aplikasi kita berupa: tanggal, commit hash, pipeline id, dan lain-lain.

Package yang dihasiilkan akan disimpan dalam jangka waktu tertentu, yang dapat kita konfigurasi sesuai dengan kebutuhan kita (bahkan kita dapat menghapus expired datenya).

Disini saya memutuskan untuk menghapus hasil “development build” setelah 3 hari. Karena branch ini adalah branch yang sibuk jadi saya ingin memastikan hanya hasil build terbaru yang ada pada branch ini.

Sedangkan pada release branch kita akan membiarkan hasil build tersimpan lebih lama dan mungkin akan ada beberapa hasil build dari periode sprint yang berbeda. Hal ini untuk menjamin jika repository kita memiliki hasil build terbaru yang dapat didownload setiap saat.

Jika pengembangan project Anda dalam kondisi vacum selama beberapa waktu, Anda dapat meningkatkan (atau menghapus) expired date. Atau mengkonfigurasi penjadwalan build otomatis setiap beberapa minggu di master branch. Hanya untuk memastikan semuanya masih ok :-)

Script Lengkap


Inilah konfigurasi lengkap, siap copy / paste ke proyek Android anda. Tapi ... Anda tidak langsung menuju script ini tanpa membaca artikel ini sampai akhir, bukan? :-) Jika Anda melakukannya: jangan tanya, baca dulu.

Klik sini untuk download dari github

image: openjdk:8-jdk

stages:
  - build
  - test
  - package


####################################################################################################
# BUILD
#
.build_template: &build_template_def
  stage: build
  artifacts:
    expire_in: 4 hours
    paths:
    - app/build/outputs/
    - .android/

  before_script:
    # Extract the SDK version that we're building against
    - export ANDROID_COMPILE_SDK=`egrep '^[[:blank:]]+compileSdkVersion'  app/build.gradle | awk '{print $2}'`

    # Explict output for logging purpose only
    - echo $ANDROID_SDK_TOOLS
    - echo $ANDROID_COMPILE_SDK

    # Fetch the specified SDK tools version to build with
    - wget --quiet --output-document=/tmp/sdk-tools-linux.zip https://dl.google.com/android/repository/sdk-tools-linux-${ANDROID_SDK_TOOLS}.zip
    - unzip /tmp/sdk-tools-linux.zip -d .android

    # Set up environment variables
    - export ANDROID_HOME=$PWD/.android
    - export PATH=$PATH:$PWD/.android/platform-tools/

    # Install platform tools and Android SDK for the compile target
    - echo y | .android/tools/bin/sdkmanager "platforms;android-${ANDROID_COMPILE_SDK}"

    - chmod +x ./gradlew

build_debug:
  <<: *build_template_def
  only:
    - develop

  script:
    - ./gradlew assembleDebug

build_release:
  <<: *build_template_def
  only:
    - master
  script:
    - ./gradlew assembleRelease

####################################################################################################
# UNIT TESTING
#

unit_test:
  stage: test
  only:
    - master
    - develop

  before_script:
    - export ANDROID_HOME=$PWD/.android
    - export PATH=$PATH:$PWD/.android/platform-tools/

  script:
    - ./gradlew test


####################################################################################################
# PACKAGE APK FOR DOWNLOADING
#

.package_template: &package_template_def
  before_script:
    - export VERSION_NAME=`egrep '^[[:blank:]]+versionName[[:blank:]]'  app/build.gradle | awk '{print $2}' | sed s/\"//g`
    - export VERSION_CODE=`egrep '^[[:blank:]]+versionCode[[:blank:]]'  app/build.gradle | awk '{print $2}'`
    - mkdir -p deliverables

    # Store some information about the build
    - touch ./deliverables/info.txt
    - echo "Build date          $(date)"                >> ./deliverables/info.txt
    - echo "App version name    ${VERSION_NAME}"        >> ./deliverables/info.txt
    - echo "App version code    ${VERSION_CODE}"        >> ./deliverables/info.txt
    - echo "Git branch          ${CI_COMMIT_REF_NAME}"  >> ./deliverables/info.txt
    - echo "Git commit          ${CI_COMMIT_SHA}"       >> ./deliverables/info.txt
    - echo "Gitlab pipeline     ${CI_PIPELINE_ID}"      >> ./deliverables/info.txt


package_develop:
  <<: *package_template_def
  stage: package
  environment: Development
  only:
    - develop
  script:
    - mv app/build/outputs/apk/app-debug.apk ./deliverables/NameOfTheApp-v$VERSION_NAME-$VERSION_CODE-debug.apk
  artifacts:
    expire_in: 3 days
    paths:
    - deliverables

package_release:
  <<: *package_template_def
  stage: package
  environment: Release
  only:
    - master
  script:
    - mv app/build/outputs/apk/app-release.apk ./deliverables/NameOfTheApp-v$VERSION_NAME-$VERSION_CODE-release.apk
  artifacts:
    expire_in: 4 weeks
    paths:
    - deliverables
Sort:  

artikel yang sangat keren @dennisalund !

sekedar ingin menambahkan tips, kita bisa menggunakan custom image docker yang sudah ada pre-installed SDK android, salah satunya adalah docker dari jangrewe yang memang dibuat khusus untuk CI android di Gitlab: https://github.com/jangrewe/gitlab-ci-android

lumayan bikin code CI jadi pendek :D

give it a try :)

Ya, itu sebenarnya jauh lebih bagus dan efektif. Coba saya update artikelnya dengan saran itu. Terima kasih ya!

hai kawan @dennisalund, salam...

saya ada bikin aplikasi Steem Autovote. Bila kamu jain dan tergabung dalam aplikasi ini, maka tiap artikel kamu akan mendapatkan upvote dari member lain. Besaran upvote yang diberikan akan tergantung dengan Steem Power kamu.

yuk join ya, gabung dengan teman-teman lainnya. kita cara nafkah bersama di steem :)
untuk info lebih lanjut bisa dibaca disini: https://steemit.com/steem/@lopezdacruz/tentang-steem-indovoter-aplikasi-otomatis-vote-antar-member

terima kasih ya

Hai, selamat ketemu. Jujur dikit ya, saya gak terlalu setuju kalo ada auto-upvoting. Mungkin orang bisa dapat banyak STEEM, tapi itu tidak akan bantu untuk naikin artikel dengan kualitas, karena semua artikel dapat banyak upvote. Lama-lama, kalo bots jadi lebih penting untuk dapat STEEM, daripada feedback beneran dari orang, jadinya orang mungkin mulai posting banyak dengan kualitas rendah, malah lebih jarang tapi dengan kualitas tinggi.

Congratulations @dennisalund! You have completed some achievement on Steemit and have been rewarded with new badge(s) :

Award for the number of upvotes

Click on any badge to view your own Board of Honor on SteemitBoard.
For more information about SteemitBoard, click here

If you no longer want to receive notifications, reply to this comment with the word STOP

By upvoting this notification, you can help all Steemit users. Learn how here!