Screen Shot 2557-05-18 at 11.29.34 PM
กำลังจะต้องไปสอนเรื่อง Continuous Integration with Jenkins

เลยถือโอกาสเอาบทความที่เคยแปลไว้มาเขียนอีกครั้ง

เป็นบทความของ Martin Fowler เรื่อง Continuous Integration

ในบทความนี้ได้พูดถึงแนวปฏิบัติ 10 ข้อของ Continuous Integration
ซึ่งน่าสนใจมากๆ เลยสรุปตามความเข้าใจของตัวเอง
แนวคิดอาจจะเก่าหน่อย แต่ยังคงความเก๋าและสำคัญอย่างมาก
ประกอบไปด้วยแนวปฏิบัติต่างๆ ดังนี้

1. Maintain a single source repository
ทุกๆ อย่างที่จำเป็นต่อการ build ระบบ ควรอยู่ใน repository เดียวกัน
จำไว้ว่า สามารถทำการ build บนเครื่องเปล่าๆ ได้เลย
เรื่องการใช้พวก version control นั้น
แนะนำให้มี main branch ในการพัฒนาระบบเพียง branch เดียว
เนื่องจากยิ่งมีมาก ยิ่งเกิดปัญหามาก
ดังนั้นถ้าคุณมี branch หลักในการทำงานเพียง branch เดียวแล้ว
คุณจะมั่นใจได้ว่า มันยังคงทำงานได้อยู่เสมอ
อาจจะมี branch อื่นๆ ขึ้นมาเช่น  fix bug สำหรับการแก้ไขข้อผิดพลาดบน production
หรือ branch ชั่วคราวสำหรับการทดลองอะไรบางอย่าง

2. Automate the build
การ deploy หรือ run ระบบนั้นมักจะมีกระบวนการที่ซับซ้อน
เช่นการ compile การ copy หรือย้ายไฟล์ การสร้างหรือแก้ไข schema database
รวมทั้งอาจจะมีกระบวนการอื่นๆ อีกมากมาย
ส่วนใหญ่มักจะทำกระบวนการดังกล่าวแบบ manual
ซึ่งสูญเสียเวลาอันมีค่าไปอย่างมาก
ดังนั้น ควรเปลี่ยนไปเป็น automated ให้หมด

โดยในการ build สามารถใช้เครื่องมือมาช่วยได้ เช่น
ภาษา Java สามารถใช้พวก Maven, Gradle ช่วย
ซึ่งสั่งให้ build ได้ด้วยชุดคำสั่งเดียว มันสะดวกสบายมาก

Automated build ที่ดี
สามารถที่จะ build และ run บนเครื่องเปล่าๆ ได้เลย
ดังนั้นเราควรทำตามแนวคิดที่ 1 มาก่อนนะ

บางคนอาจจะบอกว่า ระบบที่พัฒนาอยู่มันใหญ่มากๆ
การ build แบบนี้ทุกๆ ครั้งที่มีการเปลี่ยนแปลง ใช้เวลามากเกินไป
การแก้ไขก็ง่ายนิดเดียว ก็ทำการ build เฉพาะส่วนที่แก้ไขสิ
โดยใช้เรื่องของวันที่ของการแก้ไขล่าสุดมาใช้ รวมทั้งสิ่งที่เกี่ยวข้องมาใช้

บางคนบอกว่าฉันมี IDE มาช่วยในการ build ทุกๆ อย่างนะ
คำถามคือ เครื่องของคนอื่นสามารถใช้งานได้ไหม ด้วย configuration เหมือนกันทั้งหมด ???
ถ้าได้ล่ะก็ แนะนำให้มี build server ตรงกลาง เพื่อตรวจสอบการ build อีกครั้ง

3. Make your build self-testing
ในเครื่องคุณต้องมีชุดของการทดสอบที่ทำงานอบบอัตโนมัติ
เพื่อใช้ตรวจสอบระบบของคุณ
เพื่อหาข้อผิดพลาดต่างๆของระบบ
สามารถตรวจสอบด้วยชุดคำสั่งที่สั้นและง่าย
ผลการทดสอบควรที่จะบอกด้วยว่าผ่านและไม่ผ่านเพราะว่าอะไร
ดังนั้น คุณจะทำได้อย่างไร ถ้าไม่ทำตามแนวคิด TDD (Test-Driven Developement)

จงจำไว้ว่า
การทดสอบตามแนวคิด TDD ไม่ได้หาข้อผิดพลาดในทุกๆ อย่าง
หรือทำแล้วจำนวนข้อผิดพลาดจะเป็นศูนย์
เพราะว่าไม่มีอะไรที่ perfect ไปหมดทุกอย่างหรอกนะ
แต่ถ้าเรา run การทดสอบบ่อย เพื่อหาข้อผิดพลาด
มากกว่า perfect test ที่ไม่เคยถูกเขียนหรือสร้างเลย อย่างไหนจะดีกว่ากัน
ตรงนี้ลองคิดดูเอาเอง !!!

4. Everyone Commits To the Mainline Every Day
Integration คือ การพูดคุยและการติดต่อสื่อสาร
Integration อนุญาตให้แต่ละคนในทีมบอกหรือคุยกันว่า มีอะไรเปลี่ยนแปลงบ้าง
ดังนั้น ยิ่งถ้าคุณพูดคุยกันมากและบ่อยขึ้น ก็จะทำให้แต่ละคนในทีมรู้การเปลี่ยนแปลงต่างๆ ได้อย่างรวดเร็ว

ดังนั้น วันนี้คุณ commit การเปลี่ยนแปลงต่างๆ ไปยัง repository กลางบ่อยเพียงใด ?

โดยการ commit ควรที่จะไป branch หลักที่ทำการ build เสมอ
เพื่อจะไม่เสียเวลาในการ merge ไปมา ( สามารถใช้แนวคิด Branch by abstract และ Feature Toggle )

การ commit บ่อยๆ ทำให้เห็นปัญหาอย่างรวดเร็ว
ทำให้แก้ไขได้อย่างรวดเร็วตามมา

มาดูขั้นตอนการ commit การเปลี่ยนแปลง ที่ควรจะทำเป็นดังนี้

  • ดึงการเปลี่ยนแปลงล่าสุดจาก repository กลางมาที่เครื่องก่อน
  • ทำการ run ชุดทดสอบว่าผ่านทั้งหมด
  • ทำการแก้ไขตามความต้องการ
  • เมื่อทำการแก้ไขเสร็จ ให้ทำการ run ชุดทดสอบให้ผ่าน
  • ทำการดึงการเปลี่ยนแปลงล่าสุดจาก repository กลาง
  • ถ้ามีการเปลี่ยนแปลงและ conflict กันก็แก้ไขซะ
  • ทำการ run ชุดทดสอบให้ผ่านอีกรอบ
  • เมื่อทุกอย่างเรียบร้อย จึงทำการ commit ไปยัง repository กลาง

ถ้าคุณทำตามแนวทางนี้แล้ว จะไม่เกิดปัญหาในการทำงาน

บางคน บางทีม บอกว่าเราทำการ commit ทุกๆ วัน
แนวทางนี้ก็ถือว่าเริ่มต้นได้ดี
แต่ 1 วันมันนานไปไหม เราควรที่จะ commit ทุกๆ ครึ่งวัน หรือ ทุกๆ ชั่วโมง
จะได้รับ feedback การทำงาน
หรือพูดคุยกัยบ่อยขึ้น มันจะดีกว่านะครับ
ลองปรัปรุงกันดูนะ

5. Every Commit Should Build the Mainline on an Integration Machine
ทุกๆ commit จะต้องถูก build จาก server อยู่เสมอ
เพื่อให้รู้สุขภาพของระบบงาน
ถ้าการ build มัน fail มันบ่งบอกถึงวินัยในการทำงาน เช่น
คุณทำการ update การเปลี่ยนแปลงล่าสุดมาหรือเปล่า
คุณมี environment ที่แตกต่างหรือเปล่า
มันทำให้คุณเห็นข้อผิดพลาด เพื่อปรับปรุงให้ดีขึ้น

การมี build server หรือ integration server อยู่ตรงกลาง
เพื่อทำให้มั่นใจว่า ระบบคุณยังทำงานหรือมีสุขภาพที่ดี
การเปลี่ยนแปลงต่างๆ ไม่ทำให้ระบบมันพัง หรือ build ไม่ได้
ดังนั้น ทีมควรที่จะมีข้อตกลงกันไว้ว่า
ถ้า build server ยังไม่ผ่านหรือเป็นสีแดง แล้วห้ามกลับบ้าน
จะต้องช่วยกันแก้ไขให้ผ่านก่อนเสมอ
ทำแบบนี้ไปทุกๆ วันจนเกิดเป็นนิสัย
มันจะทำให้คุณไม่ผลัดวันประกันพรุ่ง

ส่วน build server ตรงกลางนั้น สามารถจัดการได้ 2 แบบตามความชอบ คือ
แบบ manual และ แบบ automated หรือ continuous integration server

บางที่อาจจะบอกว่า เรามี nightly build นะ แต่จริงๆ แล้วมันไม่ใช่ Continuous Integration นะ
เพราะว่ามันยังทำงานน้อยไป รู้ช้าไป
เราต้องการ feedback หรือผลการทำงานที่รวดเร็ว
เพื่อแก้ไขปัญหาได้อย่างทันท่วงที

ดังนั้น การ commit ไป แล้ว build server มัน fail นั้นเป็นสิ่งที่ไม่ได้แย่
แต่มันบอกสิ่งที่เรายังต้องปรับปรุง เพื่อให้มันผ่านอยู่เสมอ
ทำให้เราพัฒนาระบบอยู่บนสิ่งที่มันยังทำงานได้ มีสุขถาพที่ดีอยู่เสมอ

6. Keep the Build Fast
หัวใจของ Continuous Integration คือ fast feedback
ดังนั้นถ้าคุณทำการสร้างระบบ Continuous Integration แล้วมันช้า
นั่นแสดงว่าคุณมาผิดทางแล้วนะ

ในแนวปฎิบัติของ XP programming บอกว่าคำว่า fast feedback คือเวลาไม่เกิน 10 นาที
ดังนั้นยิ่งเวลาน้อย คุณสามารถไปทำงานอื่นได้เพิ่มอีกมาก

แต่ในหลายๆ ระบบ อาจจะบอกว่า มันไปช้าที่พวก testing นะ ที่มีหลากหลายเหลือเกิน
เช่น BDD, ATDD, UI, Performance
แล้วจะทำอย่างไรดีล่ะ ?

คำตอบก็คือ นำ Build pipeline มาใช้สิ
แยกการทดสอบส่วนต่างๆ ออกจากกันเป็นงานย่อยๆ แยกทำงานไป
ทำให้เราสนใจเฉพาะ build process ก่อน เนื่องจากมีความสำคัญสูงสุด
เนื่องจากเป็น code หลักของระบบ ถ้ามันยังมีสุขภาพที่ดี หรือ build ได้ก็ยังดีอยู่
ส่วนอื่นๆ มันจะทำงานช้า ซึ่งเราสามารถรอคอยได้

7. Test in a Clone of the Production Environment
ควรที่จะต้องทดสอบอยู่บน environment เหมือนกับ server
เน้นย้ำว่าควรเหมือนกันให้มากที่สุดเท่าที่จะทำได้
เช่น Hardware, Software, IP, port ต่างๆ เป็นต้น
เนื่องจากมันทำให้เรามั่นใจได้ว่า จะไม่เกิดความผิดพลาดแปลกๆ เมื่อ deploy ขึ้น production server
แน่นอนว่าเจอกันบ่อยๆ แน่นอน เพราะว่าละเลยเรื่องนี้ไปเยอะมากๆ ถึงมากที่สุด

ในปัจจุบันเทคโนโลยีด้วย Virtualization มีให้เลือกใช้เยอะ สะดวกสบายมากๆ
ดังนั้น เราสามารถสร้าง test server ให้ใกล้เคียงกับ production server
ด้วยค่าใช้จ่ายที่ต่ำ และพลังงานที่น้อยลง

8. Make it Easy for Anyone to Get the Latest Executable
ใครๆ ก็ตามในทีมหรือคนที่เกี่ยวข้องสามารถเข้าถึงระบบงานล่าสุดได้เสมอ
ตัวอย่างเช่นใน java project เราจะต้องสามารถนำพวก WAR, EAR ล่าสุดที่ build ผ่าน
มาใช้งานได้ทันทีเมื่อต้องการ
ไม่ใช่ว่าต้องการเมื่อไร จะทำการ build เมื่อนั้น ซึ่งผิดมากๆ

9. Everyone can see what’s happening
แนวปฏิบัตินี้สำคัญมากๆ ถ้าคุณทำ Continuous Integration แล้วคุณต้องโชว์
เพื่อแสดงให้เห็นสิ่งที่คุณกำลังทำอยู่ว่า มันเป็นอย่างไร
เนื่องจาก Continuous Integration มันคือการพูดคุย ติดต่อสื่อสาร
ดังนั้นคุณต้องมั่นใจว่าทุกๆ คนต้องเห็นสิ่งที่คุณทำได้
สิ่งที่นำมาใช้บ่อยๆ คือ ฉายขึ้น projector มันเลย
ใครเดินผ่านไปมารู้หมด

การโชว์ไม่เพียงแต่ผ่านจาก computer เท่านั้น
ยังสามารถทำเป็น physical board ได้
เช่นการนำปฏิทินกระดาษมาแปะไว้
แล้วทำกระดาษมาแปะในแต่ละวัน เพื่อบอกสถานะการทดสอบก็ได้
ทำให้การทำงานสนุกมากยิ่งขึ้น

แนะนำว่า ทำ Continuous Integration แล้ว มันต้องโชว์ชาวบ้านครับ

10. Automate Deployment
ในระบบ Continuous Integration นั้นควรที่จะมีมากกว่า 1 เครื่องหรือมากกว่า 1 VM
เนื่องจากทำให้สามารถขั้นตอนการ build ออกจากส่วนการทดสอบแบบต่างๆ ได้ง่าย
ดังนั้นสิ่งที่คุณต้องการก็คือ การ deploy ระบบงานลงในเครื่องต่างๆ เช่น

  • dev server
  • test server
  • SIT server
  • SUT server
  • Staging server
  • Production server

ทำงานแบบอัตโนมัติด้วยนะ
ลองคิดดูถ้าทำแบบ manual จะนรกขนาดไหน (จะกลัวอะไร ปัจจุบันเราก็ทำกันอยู่ … แต่ไม่คิดจะปรับปรุงให้ดีขึ้นบ้างหรือ ??)

ดังนั้นถ้าพูดถึงคำว่า Continuous Integration แล้ว
ลองนำเอาแนวปฏิบัตินี้มาเป็น check list ดูว่า
คุณทำข้อไหนไปบ้าง

อย่าลืมว่า Continuous Integration คือระบบเพื่อใช้ในการพัฒนาและปรับปรุงนะครับ !!!