ลดเวลารัน CI ได้ง่ายๆ สำหรับชาว Android Developer
คือถ้าแถวจับมือเมนท้อปๆอ่ะรอเป็นชั่วโมงอ่ะรอกันไหว แต่ถ้างานบิ้วนานมักจะรอกันไม่ไหว ช้านเข้าใจดี และถ้าเวลามีผลกับเงินหล่ะ เราก็ควรจะลดต้นทุนตรงนี้อะเนอะ
เหตุการณ์ที่เกิดขึ้น
วันนั้นเราไปงานจับมือ หลังจากจับมือเจนในบุแรกเสร็จ เราเลยต่อคิวเพื่อจับมือเฌอปรางในบุสอง ซึ่งคนต่อคิวรอน้องเยอะตั้งแต่บุแรกแล้ว และใช้เวลาประมาณ 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 ที่ไปเจอมา
เราลง 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 แถวๆนี้แหละไปต่อไม่ได้
อ่ะถ้าใครเพิ่มาใหม่หรือลืมๆไปดูความเดิมตอนที่แล้วก่อนหน้านี้กันได้จ้า
ผลการรันนั้นมันไม่ได้เร็วขึ้นเลย ใช้เวลาใกล้เคียงจากเดิมมาก แสดงว่าไม่เกี่ยวกันหล่ะ
อีกสิ่งนึงที่ทำให้มันเร็วขึ้นได้ก็คือการ 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 ให้เราหล่ะ
ลอง push code ขึ้นไปเพื่อทดสอบการรัน CI รอบต่อไป ที่น่าสนใจคือมันโหลด cache ที่เก็บมาจากเมื่อกี้มาใช้ รู้สึกได้ว่าเฮ้ยยยย เร็วขึ้นนิดนึงแหะ และสุดท้ายใช้เวลาทั้งสิ้นเป็นตัวเลขกลมๆกลิ้งๆ 30 นาทีจ้า ได้ประมาณ 66 รอบต่อเดือนหล่ะ ถือว่าเราได้รอบเยอะขึ้นเยอะ ผลก็ค่อนข้างเป็นที่น่าพอใจ เพราะคิดไว้ว่าแค่ 30 นาทีก็พอแล้วลู๊ก
ถ้าใครมีวิธีที่ดีกว่านี้ก็วานบอกหลังไมค์หรือ commeny กันได้จ้าทุกคน
ก่อนจบบล็อกนี้กันไป ก็รันไปเยอะแหละ ใกล้หมดเดือนแล้ว ผลที่ได้ก็คือ ...
บทความอ้างอิง
บทความติดดาว สูตรเด็ดเคล็บลับในการบิ้ว CI สำหรับ Android ให้เร็วขึ้น
เขียนบล็อกเสร็จแล้ว อ่ะฝากร้านหน่อย
และฝากช่องทางใหม่ ทาง Twitter ฮับ