Declarative Syntax & Post Actions
เปลี่ยนความยุ่งเหยิงของการเขียนสคริปต์ตามใจชอบ ให้เป็นโครงสร้างมาตรฐานสากล: ลำดับชั้น pipeline, stages, steps และการจัดการวงจรชีวิตด้วย post conditions พร้อมรับประกันความสะอาดด้วย cleanWs()
"Never Leave a Workspace Dirty After Build."
ไปป์ไลน์ที่ดีไม่ได้วัดแค่ว่าบิลด์ผ่านหรือไม่ แต่วัดที่ว่าเมื่อบิลด์พัง มันยังสามารถกวาดล้างขยะ แจ้งเตือนทีม และคืนสถานะเครื่องให้พร้อมสำหรับงานถัดไปได้อย่างปลอดภัย 100%
ควิซวันนี้มี 15 ข้อ ประกอบด้วยเนื้อหาใหม่ของ Day 2 จำนวน 10 ข้อ และดึงเนื้อหา Controller/Agent ของ Day 1 มาทดสอบสะสม 5 ข้อ
Introduced Topic & The Big Picture
Declarative Pipeline คืออะไร และวงจร Post Action คืออะไร?
Declarative Pipeline คือ "แบบฟอร์มบันทึกขั้นตอนทำงานมาตรฐาน" ของ Jenkins ที่บังคับให้ทุกคนเขียนในโครงสร้างเดียวกันชัดเจน โดยไม่อนุญาตให้เขียนโค้ดสคริปต์ Groovy อิสระจนเละเทะ และมีระบบ Post Actions ซึ่งเปรียบเหมือน "ข้อตกลงปิดกะการทำงาน" ที่กำหนดไว้ล่วงหน้าว่า เมื่อทำงานเสร็จ (ไม่ว่าจะสำเร็จหรือล้มเหลว) จะต้องเก็บกวาดขยะและแจ้งเตือนใครบ้างเสมอ
- คลิกตั้งค่าผ่านหน้าเว็บ (Freestyle): ไม่มีใครจำได้ว่าตั้งค่าอะไรไว้ในช่องไหน เมื่อเซิร์ฟเวอร์พังต้องมานั่งกดใหม่จากศูนย์
- Scripted Pipeline สับสน: แต่ละคนเขียนโค้ด Groovy แบบไม่มีกรอบ ตรวจสอบโครงสร้างยาก และไม่มีบล็อกมาตรฐานรองรับ
- ขยะค้างเติ่งเมื่อพัง: ถ้าบิลด์ล้มเหลวกลางคัน ไฟล์บิลด์ชั่วคราวจะตกค้างบนเครื่อง Agent จนดิสก์เต็มเงียบๆ
- เก็บไว้ใน Git (Jenkinsfile): มีประวัติ Version Control ทุกคนในทีมเห็นขั้นตอนการส่งมอบโค้ดตรงกัน
- ไวยากรณ์เข้มงวด อ่านง่าย: แยกชัดเจนระหว่างใครรัน (
agent), ขั้นตอนอะไร (stages), คำสั่งอะไร (steps) - วงจรปิดท้ายที่ไว้ใจได้: ไม่ว่าบิลด์จะพังอย่างไร บล็อก
post { always }จะถูกสั่งให้ทำงานเพื่อล้างดิสก์และส่ง Alert เสมอ
pipeline { }
บล็อกครอบนอกสุดระดับ Root ตัวเดียวของไฟล์ บ่งบอกให้ Jenkins ทราบว่าต้องใช้ Declarative Parser ตรวจสอบไวยากรณ์
agent
ระบุผู้ลงมือปฏิบัติงาน ว่าจะให้รันบนเครื่องใด (any, none, หรือเจาะจง label)
stages & steps
stages คือรายการของขั้นตอนย่อย โดยในแต่ละ stage จะมีกล่อง steps เก็บคำสั่งรันจริง
post { }
วงจรปิดท้าย ทำงานอัตโนมัติตามสถานะผลลัพธ์ เช่น always, success, failure, unstable
Everyday Mental Model & Intuition
หากคุณต้องการเข้าใจว่าทำไม Declarative Pipeline จึงต้องมีโครงสร้างแบบนี้ ให้มองเหมือนคู่มือมาตรฐานการประกอบเฟอร์นิเจอร์:
โครงสร้างขั้นตอนตายตัว (stages/steps)
ในคู่มือ IKEA จะแบ่งเป็นขั้นตอนชัดเจน: ขั้นที่ 1 ต่อโครงตู้ -> ขั้นที่ 2 ติดบานพับประตู -> ขั้นที่ 3 วางชั้นไม้ ห้ามกระโดดข้ามขั้นตอน ถ้าขั้นตอนไหนติดขัดก็หยุดทันที
ข้อกำหนดปิดกะ (post { always })
ไม่ว่าโต๊ะตัวนั้นจะประกอบเสร็จสมบูรณ์หรือช่างทำไม้หักกลางทาง ช่างทุกคนมีกฎเหล็กเหมือนกันคือ: ต้องกวาดขี้เลื่อยและเก็บเครื่องมือเข้ากล่องก่อนออกจากห้องเสมอ
ปุ่มโทรแจ้งผู้จัดการ (post { failure })
ถ้าขั้นตอนใดเกิดข้อผิดพลาดจนไม่สามารถดำเนินต่อได้ ให้โทรศัพท์แจ้งหัวหน้าฝ่ายผลิตทันที เพื่อส่งชิ้นส่วนใหม่มาเปลี่ยน ไม่ปล่อยให้งานค้างคาเงียบๆ
Real-World Engineering Context & War Story
จุดเริ่มต้น: ทีมโมบายล์แอปพลิเคชันสร้าง Pipeline บิลด์ไฟล์ APK และไฟล์ทดสอบขนาด 8GB ต่อรอบ โดยในตอนแรกเขียนสคริปต์ลบไฟล์ไว้ที่บรรทัดสุดท้ายของ Stage ทดสอบ: sh 'rm -rf ./build'
วันที่พังยับเยิน: เมื่อมีการแก้โค้ดแล้วชุด Unit Test รันพังกลางทาง ตัว Jenkins หยุดการทำงานของ Stage นั้นทันที ส่งผลให้บรรทัด sh 'rm -rf ./build' ที่อยู่ท้าย Stage ไม่ถูกเรียกใช้งานเลยแม้แต่ครั้งเดียว
สิ่งที่เกิดขึ้น: นักพัฒนาพยายามแก้โค้ดแล้วกดบิลด์ซ้ำอีก 35 ครั้ง ทุกครั้งที่เทสต์พัง ไฟล์ขยะ 8GB ตกค้างสะสมบนดิสก์ จนพื้นที่ขนาด 300GB ของ Agent เต็มสนิท (ENOSPC: no space left on device) คิวงานของทั้งทีม iOS, Android, และ Backend ที่ใช้ Agent ชุดนี้ถูกดีดล้มเหลวระนาวเป็นลูกโซ่
ห้ามเขียนคำสั่งล้างพื้นที่ไว้ใน steps เด็ดขาด ให้ย้ายไปไว้ในบล็อก post { always { cleanWs() } } เพราะ Jenkins การันตีว่าคำสั่งภายใต้ always จะถูกเรียกใช้งาน 100% แม้ว่าสเตจก่อนหน้าจะ Error, Fail, หรือถูกสั่ง Abort ก็ตาม
Hands-on Syntax Breakdown (ลงมือทำทีละก้าว 3 ระดับ)
โครงสร้างหลัก 4 บล็อกแรกที่ขาดไม่ได้
pipeline { agent any // 1. กำหนด Worker ที่จะใช้ทำงาน stages { // 2. กล่องรวม Stages ทั้งหมด stage('Compile') { // 3. Stage ย่อยลำดับแรก steps { // 4. กล่องเก็บคำสั่งรันจริง echo 'Compiling source code files...' } } } }
คำอธิบาย: นี่คือโครงสร้างขั้นต่ำที่สุด หากขาด agent หรือ stages ตัว Jenkinsfile Linter จะตีว่า Syntax ผิดพลาดทันทีตั้งแต่ก่อนเริ่มรัน
แยกขั้นตอน Build, Test, และเริ่มใส่ Post Actions พื้นฐาน
pipeline { agent { node { label 'linux-runner' } } stages { stage('Build') { steps { sh 'echo "Compiling code binaries..."' } } stage('Test') { steps { sh 'echo "Running automated unit tests..."' } } } post { success { echo 'All stages completed smoothly!' } failure { echo 'Build or Test failed. Please inspect logs.' } } }
คำอธิบาย: บล็อก post จะรอประเมินสถานะเมื่อทุก Stage ทำงานจบ หาก Stage ใดล้มเหลว จะกระโดดมาทำงานในเงื่อนไข failure ทันที
วงจร Post เต็มรูปแบบ: always, success, failure, changed, cleanWs()
pipeline { agent { node { label 'k8s-maven-worker' } } stages { stage('Unit & Integration Tests') { steps { sh 'mvn test' } } } post { always { // รัน 100% เสมอ ไม่ว่าบิลด์จะผ่าน ตก หรือถูกกดยกเลิก cleanWs() echo 'Workspace cleaned safely. Disk usage preserved.' } success { echo 'Pipeline succeeded. Ready for staging deployment.' } failure { echo 'Pipeline failed. Triggering incident notification...' } changed { // ทำงานเฉพาะเมื่อสถานะเปลี่ยนไปจากรอบก่อนหน้า (เช่น จาก Fail กลับมา Pass) echo 'Status state changed from previous build!' } } }
คำอธิบาย: สภาวะ changed มีประโยชน์อย่างยิ่งในการลดการแจ้งเตือนที่ไม่จำเป็น (Alert Fatigue) โดยจะยิงข้อความเฉพาะตอนที่สถานะบิลด์พลิกกลับมาผ่าน หรือเพิ่งพังเป็นครั้งแรกเท่านั้น
Interactive Simulator: Pipeline Stage & Post Condition Engine
จำลองสถานการณ์: พิสูจน์พฤติกรรมของ Post Actions เมื่อ Stage ทำงานสำเร็จหรือล้มเหลว
เลือกผลลัพธ์ของ Stage ทดสอบ (Pass หรือ Fail) และเปิด/ปิดคำสั่ง cleanWs() แล้วคลิก "Run Pipeline Simulation" เพื่อดูผลกระทบต่อดิสก์และลำดับการทำงานของ Post Block
หากปิดใช้งาน สังเกตว่าไฟล์ขยะ Workspace จะค้างอยู่บนดิสก์แม้บิลด์จะจบลงแล้ว