ลดเวลารัน CI ได้ง่ายๆ สำหรับชาว Android Developer

Android Oct 22, 2020

คือถ้าแถวจับมือเมนท้อปๆอ่ะรอเป็นชั่วโมงอ่ะรอกันไหว แต่ถ้างานบิ้วนานมักจะรอกันไม่ไหว ช้านเข้าใจดี และถ้าเวลามีผลกับเงินหล่ะ เราก็ควรจะลดต้นทุนตรงนี้อะเนอะ

Bringing out the Hue
Photo by Rahul Chakraborty / Unsplash

เหตุการณ์ที่เกิดขึ้น

วันนั้นเราไปงานจับมือ หลังจากจับมือเจนในบุแรกเสร็จ เราเลยต่อคิวเพื่อจับมือเฌอปรางในบุสอง ซึ่งคนต่อคิวรอน้องเยอะตั้งแต่บุแรกแล้ว และใช้เวลาประมาณ 2 ชั่วโมงมั้ง เพื่อจะได้เจอน้องเฌอ

ซึ่งแน่นอน ผิดเรื่องโว้ยยยยย แถมเล่าเรื่องอดีตเมื่อสองปีก่อนไปอีกกกกก

เอาใหม่ๆ

เรื่องมีอยู่ว่า ทีมเราเริ่มมีการทำ Code Review กัน โดยแต่ละคนก็แตก branch กันออกไปทำ feature ที่รับผิดชอบ พอเสร็จแล้วจะทำการ Merge Request ที่ branch หลัก

แน่นอนว่าเนื่องจากทำกันคนละ branch ทางเราจึงไม่แน่ใจว่า code ที่น้องๆในทีม push ขึ้นมานั้น มัน run ได้ไหม มี error หรือเปล่า ซึ่งในความเป็นจริงก็มีน้อยมากๆที่ pull มาแล้ว build error เช่น ไม่มีตัวแปรนี้ในโปรเจก อ้าว drawable นี้หายไปไหน อ่ะสีนี้หล่ะ เอ๊ะนี่ class อัลไล ตามหาไม่เจอ เป็นต้น

แน่นอนว่าอีกทีนั้น run CI ทุกครั้งที่มีการ push code ขึ้นไป แน่นอนว่าพอถึงขีดจำกัดแล้ว จากความเดิมที่เคยเล่าไป PM ก็จะมีการทักมาถามว่า ทำไรเหรอ เนื่องจากมันติด limit 2,000 minute/group/month

อันนี้ไปส่องโปรเจกกลุ่มอื่นมา

จากนั้น CI มันจะทำงานไม่ได้หล่ะ เพราะเราไม่ได้จ่ายเงินเพิ่มนี่แหละ มันเลย proceed ให้เลยจ้า ดังภาพ

เราจึงต้องใส่ CI เข้าไปในโปรเจกของเรา โดยเราจะให้มันทำงานก็ต่อเมื่อมีการ merge request เท่านั้น เพื่อลดเวลาในการบิ้วลงเพื่อไม่ให้ติด limit

ผลที่ได้คือ เนื่องจากโปรเจกเราใหญ่มาก ใช้เวลาทั้งสิ้นตีเลขกลมๆไป 45 นาที จ้า คิดคร่าวๆว่าเดือนนึงจะได้กี่รอบ ก็ 2000 / 45 = 44 รอบโดยประมาณ เท่ากับว่าได้แค่วันละรอบนิดๆ หรือถ้าเทียบวันทำงานก็ประมาณ 2 รอบต่อวันแหละ

เท่ากับว่าถึงแม้ว่าเราจะตรวจ Code Review ใน Merge Request นั้นผ่านแล้ว แต่ก็ต้องรอ CI อยู่ดี ซึ่ง โอ้ยยยย นานไป

ดังนั้นจึงต้องหาวิธีใดก็ได้ที่ทำให้ run CI ใช้เวลาน้อยลง

จะอ่านแบบละเอียดๆก็ได้ แต่ Docker พอเข้าใจ concept แต่ให้มานั่งทำแบบ zero to hero ก็ไม่ได้เว้ยย

แต่ก็มีคนใจดีทำ Docker สำหรับ Android ให้ด้วยหล่ะ

ใช้ Docker ที่เป็น Android Image กันเถอะ

แน่นอนว่าเราไปถามอากู๋มาจนแน่ชัดแล้วว่า มีหลายๆบทความนำเสนอการใช้ Docker ที่ทำเพื่อสำหรับ Android เลยจาก Developer หลายๆคน ซึ่งมันจะลดการลงพวก Android SDK ต่างๆลงได้นะ โดยที่เราไม่ต้องไปให้ CI ลงให้ใหม่ทุกครั้งหล่ะ และทำให้ Gradle นั้น run ได้ไวกว่าด้วยหล่ะจ้า

ตัวอย่าง Docker ที่ไปเจอมา

jangrewe/gitlab-ci-android
GitLab CI image for building Android apps. Contribute to jangrewe/gitlab-ci-android development by creating an account on GitHub.
https://github.com/jangrewe/gitlab-ci-android
seanghay/android-ci
Docker Image of Android CI for API 29. Contribute to seanghay/android-ci development by creating an account on GitHub.
https://github.com/seanghay/android-ci

เราลง docker image ที่ชื่อว่า jangrewe/gitlab-ci-android เพราะเจออันแรก เลยขอลองใช้ก่อนเนอะ

มาดูข้างในกันคร่าวๆดีกว่าเนอะ

ไฟล์สำคัญๆที่จะพาไปอยู่ มี 2 files ด้วยกันคือ

  • .gitlab-ci.yml คร่าวๆคือให้ build Docker ขึ้นมาให้เราหน่อย
  • Dockerfile การทำงานจะเหมือนกับการลง image ที่เป็น openjdk แล้ว before_script ก็จะมีการลง Android SDK แล้วก็กด accept รัวๆให้เรา

สรุปไฟล์ .gitlab-ci.yml จะเป็นดังนี้

image: jangrewe/gitlab-ci-android

variables:
  GIT_SUBMODULE_STRATEGY: none

before_script:
  - export GRADLE_USER_HOME=$(pwd)/.gradle
  - chmod +x ./gradlew
  # submodule
  - git submodule sync
  - git submodule update --init

stages:
  - build

build:
  stage: build
  only:
    - merge_requests
  script:
    - ./gradlew assembleDevDebug

ตรงนี้ขอยังไม่แปะใน gist ก่อนน้า เดี๋ยวไปแปะตัว final เลยดีกว่า

พอเราใช้ Docker นั้น ทำให้เราไม่ต้องมานั่งโหลด Android SDK ใหม่หมดหล่ะ ถือว่าประทับใจเลยทีเดียว แต่อย่าลืมแอบไปส่อง Docker บ่อยๆว่าอัพตามยังนะ ฮ่าๆ

ถ้าไปดูความเดิมตอนที่แล้ว คือเรามีเพิ่มใส่ submodule ลงไปด้วย อย่าลืมไป check ใน .gitmodules ด้วยนะว่ามันดึงมาได้ไหม ไม่งั้นมันจะ fail แถวๆนี้แหละไปต่อไม่ได้

อ่ะถ้าใครเพิ่มาใหม่หรือลืมๆไปดูความเดิมตอนที่แล้วก่อนหน้านี้กันได้จ้า

การทดลองทำ CI/CD แบบง่ายๆบน gitlab สำหรับ Android Developer
อยากลองมาทำอะไรสนุกๆ เมื่อเราขี้เกียจมานั่งรัน Unit Test ทุกครั้งหลังเขียนโค้ดเสร็จ ใช้ CI/CD ช่วยกันเถอะ (1) ด้วยความที่ไฟล์ที่มี . ด้านหน้า ใน mac os มันจะไม่เห็นเหมือน windows เราจะต้องแก้ใน…
https://blacklenspub.com/ci-cd-gitlab-for-android-developer-b9425a94bb1
เริ่มทำ Code Review ด้วย ktlint กันเถอะ
เนื่องด้วยทำงานบริษัท startup ที่เปลี่ยนแปลง requirement ได้บ่อย จนเดฟไม่มีเวลาทำ Unit Test แล้วไม่รู้จะทำ Code Review ยังไงอีก อ่ะงั้นเราค่อยๆเริ่มทำสักอย่างก็แล้วกัน แน่นอนว่า Android Kotlin…
https://blacklenspub.com/kotlin-code-review-with-ktlint-bc58656dfac

ผลการรันนั้นมันไม่ได้เร็วขึ้นเลย ใช้เวลาใกล้เคียงจากเดิมมาก แสดงว่าไม่เกี่ยวกันหล่ะ

อีกสิ่งนึงที่ทำให้มันเร็วขึ้นได้ก็คือการ caching ของเก็บไว้ใน Runner นั่นเอง เพื่อสำหรับครั้งต่อไปเราจะได้โหลดมันมาเลยไม่ต้องไปเริ่มต้นใหม่อีกครั้งในทุกๆครั้งนั่นแหละ

ใส่เข้าไปเพิ่มจะเป็นดังนี้

สิ่งที่เพิ่มขึ้นมาก็คือ ส่วน cache นั่นเอง

cache:
  key: ${CI_PROJECT_ID}
  paths:
    - .gradle/wrapper
    - .gradle/caches  

ในที่นี้ทำการ caching gradle folder ให้เรา โดยที่ครั้งต่อไปจะเอา caching ตรงนี้ไปใช้ได้เลยไม่ต้องทำใหม่ มี key เพื่อบอกว่าใช้ cache ตัวไหน เก็บเป็นราย branch และเราเก็บไฟล์ที่ว่านี้ไว้ที่ไหน ในที่นี้จะอยู่ตรงนี้ export GRADLE_USER_HOME=$(pwd)/.gradle

สามารถอ่านเพิ่มเติมเกี่ยวกับ caching ได้ที่นี่เลย

Cache dependencies in GitLab CI/CD | GitLab
Documentation for GitLab Community Edition, GitLab Enterprise Edition, Omnibus GitLab, and GitLab Runner.

ผลในรอบแรก เอ่อออ เวลาที่ใช้ไม่ได้ต่างกันเลย แต่แน่นอนว่ามันเก็บ cache ให้เราหล่ะ

ลอง push code ขึ้นไปเพื่อทดสอบการรัน CI รอบต่อไป ที่น่าสนใจคือมันโหลด cache ที่เก็บมาจากเมื่อกี้มาใช้ รู้สึกได้ว่าเฮ้ยยยย เร็วขึ้นนิดนึงแหะ และสุดท้ายใช้เวลาทั้งสิ้นเป็นตัวเลขกลมๆกลิ้งๆ 30 นาทีจ้า ได้ประมาณ 66 รอบต่อเดือนหล่ะ ถือว่าเราได้รอบเยอะขึ้นเยอะ ผลก็ค่อนข้างเป็นที่น่าพอใจ เพราะคิดไว้ว่าแค่ 30 นาทีก็พอแล้วลู๊ก

ถ้าใครมีวิธีที่ดีกว่านี้ก็วานบอกหลังไมค์หรือ commeny กันได้จ้าทุกคน

ก่อนจบบล็อกนี้กันไป ก็รันไปเยอะแหละ ใกล้หมดเดือนแล้ว ผลที่ได้ก็คือ ...


บทความอ้างอิง

Using Gitlab to set up a CI/CD workflow for an Android App from scratch | Computer Science Blog
Tim Landenberger (tl061) Johannes Mauthe (jm130) Maximilian Narr (mn066) This blog post aims to provide an overview about how to setup a decent CI/CD workflow for an android app with the
https://blog.mi.hdm-stuttgart.de/index.php/2020/02/24/using-gitlab-to-set-up-a-ci-cd-workflow-for-an-android-app-from-scratch/
Android Application GitLab CI and Docker
Recently I started a new project building a new Android application. We used GitLab as git repository for a long time, but only for commit and code review. After merge to the specific branches, it…
https://medium.com/@chiangnan.lin/android-application-gitlab-ci-and-docker-8739d8a11cee
Build Android Apps with GitLab CI/CD
Continuous Integration and Continuous Delivery/Deployment has become one of the most important parts of software development these days. It solved quite a lot of problems that we had run into in the…
https://medium.com/@seanghay/build-android-apps-with-gitlab-ci-cd-5fec4c301a2f

บทความติดดาว สูตรเด็ดเคล็บลับในการบิ้ว CI สำหรับ Android ให้เร็วขึ้น

Android CI/CD with GitLab — Build, Test, Sign, Upload to Dropbox and send an Email
How to prepare full CI/CD process for Android app — build, test, sign, upload to Dropbox and send an email with download link and latest changes.
https://android.jlelse.eu/android-gitlab-ci-cd-sign-deploy-3ad66a8f24bf

เขียนบล็อกเสร็จแล้ว อ่ะฝากร้านหน่อย

อย่าลืมกด like กด share บทความกันด้วยนะคะ :)

Posted by MikkiPastel on Sunday, 10 December 2017

และฝากช่องทางใหม่ ทาง Twitter ฮับ

Tags

Minseo Chayabanjonglerd

I am a full-time Android Developer and part-time contributor with developer community and web3 world, who believe people have hard skills and soft skills to up-skill to da moon.