จากโพสต์ที่แล้วเราได้พูดถึง Git Branching ว่าแตก branch ยังไง merge กลับยังไง แล้วก็มี branching strategy แบบไหนบ้าง แต่พอ merge เสร็จแล้ว... แล้วยังไงต่อ?
ถ้าต้อง build เอง test เอง deploy เอง ทุกครั้งที่มี code ใหม่ มันก็เหนื่อยและเสี่ยงพลาดมาก ยิ่งทีมใหญ่ขึ้น deploy บ่อยขึ้น ยิ่งวุ่น
นี่คือที่มาของ CI/CD Pipeline — ระบบที่จัดการทุกอย่างตั้งแต่ code เข้า repo จนถึง deploy ขึ้น production ให้เราแบบอัตโนมัติ
CI/CD คืออะไร?
CI/CD ย่อมาจาก 2 คำที่ทำงานเสริมกัน — CI ทำให้ทีม integrate code ได้ถี่ขึ้นโดยไม่ "ตีกัน" ส่วน CD ทำให้ code ที่ผ่าน test แล้วถึงมือ user ได้เร็วที่สุด ทั้งสองรวมกันเปลี่ยน deployment จาก "เหตุการณ์ใหญ่น่ากลัว" เป็น "กิจวัตรธรรมดา":
CI — Continuous Integration
"รวม code บ่อยๆ ทดสอบอัตโนมัติทุกครั้ง"
หลักการคือ developer ทุกคนควร merge code เข้า main branch อย่างน้อยวันละครั้ง — ยิ่ง integrate บ่อย ยิ่งเจอ conflict เล็ก แก้ง่าย ถ้าปล่อยให้ branch แยกนานเป็นสัปดาห์ merge ทีเดียว conflict จะใหญ่มาก ทุกครั้งที่ push ระบบจะ:
- ดึง code มา build อัตโนมัติ
- รัน test ทั้งหมด
- แจ้งผลว่า ✅ ผ่าน หรือ ❌ ไม่ผ่าน
ถ้าไม่มี CI → developer push code → ไม่มีใครรู้ว่าพังจนกว่าจะไป deploy จริง 💀
CD — Continuous Delivery / Continuous Deployment
Continuous Delivery: code ที่ผ่าน test แล้ว พร้อม deploy ได้ทันที แต่ยังต้องกดปุ่ม deploy เอง เหมาะกับทีมที่ต้อง compliance review หรือต้องการ manual approval ก่อน release
Continuous Deployment: code ที่ผ่าน test แล้ว deploy ขึ้น production อัตโนมัติเลย ไม่ต้องกดอะไร — ทุก commit ที่ผ่าน pipeline จะถึงมือ user ทันที! Netflix, Facebook, Google ใช้แบบนี้ แต่ต้องมี test coverage สูงมากจึงจะ confident พอ
ทั้งสองแบบมีข้อดี — Delivery ปลอดภัยกว่า (มี human gate) ส่วน Deployment เร็วกว่า (feedback loop สั้นมาก) เลือกตาม risk tolerance ของทีมและ business
Pipeline คืออะไร?
Pipeline คือลำดับขั้นตอนที่ทำงานต่อเนื่องกันอัตโนมัติ ตั้งแต่ code เข้า repo จนถึง deploy ขึ้น production ลองนึกภาพโรงงานผลิตรถยนต์: วัตถุดิบเข้า → ประกอบชิ้นส่วน → ตรวจสอบคุณภาพ → ทาสี → ส่งมอบ ถ้าชิ้นส่วนไม่ผ่านตรวจ สายพานหยุดทันที — ไม่ส่งของเสียถึงลูกค้า CI/CD pipeline ทำเหมือนกัน:
ถ้าขั้นตอนใด fail → pipeline หยุดทันที → แจ้ง developer → ไม่มี code พังหลุดไป production
แต่ละขั้นตอนทำอะไรบ้าง?
Pipeline ทั่วไปมี 5 ขั้นตอน — แต่ละขั้นตอนทำหน้าที่เฉพาะและเป็น "quality gate" ที่ต้องผ่านก่อนไปขั้นถัดไป ยิ่ง pipeline มี gate เยอะ ยิ่งมั่นใจว่า code ที่ถึง production มีคุณภาพ:
1. Source — รับ Code เข้ามา
Pipeline เริ่มทำงานเมื่อมี trigger event — ส่วนใหญ่คือ git push แต่สามารถตั้งได้หลายแบบ ยิ่ง trigger อัตโนมัติมากเท่าไหร่ developer ยิ่งไม่ต้องจำว่า "ต้องทำอะไรก่อน deploy":
- Push code ขึ้น branch
- เปิด Pull Request
- Merge เข้า main
- ตั้งเวลา (cron schedule)
# ตัวอย่าง GitHub Actions trigger
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
2. Build — สร้างโปรเจกต์
ขั้นตอน Build คือการ compile code, ติดตั้ง dependencies, และสร้าง artifacts (เช่น Docker image, JAR file, JS bundle) ที่พร้อม deploy ถ้า build fail แสดงว่า code มีปัญหาพื้นฐาน (syntax error, missing dependency) ต้องแก้ก่อน ตัวอย่างสิ่งที่เกิดขึ้น:
npm install→ ติดตั้ง packagesnpm run build→ compile TypeScript, bundle React, etc.- สร้าง Docker image
- สร้าง artifact (.jar, .whl, binary)
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm ci
- run: npm run build
ถ้า build fail → มักเป็นเพราะ:
- Syntax error
- Missing dependency
- Version conflict
3. Test — ทดสอบ
ขั้นตอนสำคัญที่สุด — ถ้าไม่มี test ก็ไม่ต่างจากการ deploy แบบลุ้นดวง 🎲 automated tests จะรันทุกครั้งที่มี push โดยไม่ต้องพึ่ง "ความขยัน" ของ developer ถ้า test fail → pipeline หยุด → code ไม่หลุดไป production
ระดับของ Test:
| ระดับ | ทดสอบอะไร | ความเร็ว | ตัวอย่าง |
|---|---|---|---|
| Unit Test | ฟังก์ชันเดี่ยวๆ | เร็วมาก (วินาที) | calculate(2,3) ต้องได้ 5 |
| Integration Test | หลายส่วนทำงานร่วมกัน | ปานกลาง | API + Database |
| E2E Test | ทั้งระบบจากมุม user | ช้า (นาที) | กด Login → เห็น Dashboard |
- run: npm test # Unit tests
- run: npm run test:e2e # E2E tests
- run: npm run lint # Code style check
- run: npm audit # Security check
Testing Pyramid:
4. Stage — Preview ก่อน Deploy จริง
Staging คือ environment ที่เหมือน production ทุกอย่าง (same config, same data structure, same infrastructure) แต่ยังไม่ใช่ของจริง — เป็น "ซ้อมรบ" ก่อนรบจริง ช่วยเจอปัญหาที่ test อัตโนมัติจับไม่ได้ เช่น performance issues, UI bugs, integration problems:
ประโยชน์:
- ทดสอบกับ data ที่เหมือนจริง
- ให้ QA team หรือ PM มา review ได้
- ตรวจจับปัญหาที่ test อัตโนมัติจับไม่ได้
5. Deploy — ขึ้น Production
ขั้นตอนสุดท้าย — code ไปถึงมือ user จริงๆ! วิธี deploy มีหลายแบบ แต่ละแบบมี trade-off ด้าน risk, speed, และ complexity การเลือกวิธีที่เหมาะสมขึ้นอยู่กับ business requirements:
วิธี deploy ที่นิยม:
Rolling Update
Blue-Green Deployment
Canary Deployment
ตัวอย่าง Pipeline จริงด้วย GitHub Actions
มาดู pipeline จริงที่ใช้ GitHub Actions — CI/CD tool ที่ built-in มากับ GitHub ฟรี แค่สร้างไฟล์ YAML ใน .github/workflows/ ก็ได้ pipeline อัตโนมัติ ตัวอย่างด้านล่างครอบคลุมทั้ง build, test, deploy:
name: CI/CD Pipeline
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
# ===== CI =====
build-and-test:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Lint
run: npm run lint
- name: Build
run: npm run build
- name: Unit Tests
run: npm test -- --coverage
- name: Upload coverage
uses: actions/upload-artifact@v4
with:
name: coverage
path: coverage/
# ===== CD =====
deploy:
needs: build-and-test # รอ CI ผ่านก่อน
if: github.ref == 'refs/heads/main' # deploy เฉพาะ main
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Deploy to production
run: |
echo "Deploying to production..."
# คำสั่ง deploy จริงๆ เช่น:
# ssh user@server 'cd /app && git pull && npm ci && pm2 restart all'
# หรือ docker push + kubectl apply
เครื่องมือ CI/CD ยอดนิยม
มี CI/CD tools หลายตัว — แต่ละตัวเด่นคนละด้าน GitHub Actions (ง่าย, ฟรีสำหรับ public repos), GitLab CI (ครบจบในที่เดียว), Jenkins (flexible สุด แต่ต้อง maintain เอง), CircleCI (เร็ว, cloud-native) เลือกตามทีมและ ecosystem:
| เครื่องมือ | ประเภท | จุดเด่น | เหมาะกับ |
|---|---|---|---|
| GitHub Actions | Cloud | ใช้ง่าย, ฟรีสำหรับ public repo | โปรเจกต์บน GitHub |
| GitLab CI/CD | Cloud/Self-hosted | Pipeline ดี, มี container registry | องค์กรที่ใช้ GitLab |
| Jenkins | Self-hosted | Plugin เยอะ, ปรับแต่งได้มาก | องค์กรใหญ่ |
| CircleCI | Cloud | เร็ว, config ง่าย | Startup/ทีมเล็ก |
| ArgoCD | Self-hosted | GitOps สำหรับ Kubernetes | ทีมที่ใช้ K8s |
Best Practices
มี pipeline ดีไม่พอ — ต้อง "ดูแล" pipeline ด้วย เหมือนรถยนต์ที่ต้อง service ประจำ ถ้าปล่อยให้ pipeline ช้า, test ไม่ครอบคลุม, หรือ secrets hardcode สุดท้าย pipeline จะกลายเป็นภาระแทนที่จะช่วย:
1. Keep Pipeline Fast ⚡
Pipeline ที่ช้าเกินไป developer จะไม่อยากรอ → เริ่มข้าม CI → ค่อยๆ เลิกใช้ → เสียประโยชน์ทั้งหมด ทำให้เร็วด้วย: parallel jobs, caching dependencies, เลือกรันเฉพาะ test ที่เกี่ยวข้อง, ใช้ incremental builds
เป้าหมาย:
- Build + Unit Test: < 5 นาที
- ทั้ง pipeline: < 15 นาที
2. Test ให้ครอบคลุม 🧪
Test coverage ต่ำ = pipeline ที่ให้ความมั่นใจเทียม — code ผ่าน pipeline แต่พังใน production ตั้งเป้า coverage 80%+ และเขียน tests ตาม Testing Pyramid:
- ตั้งเป้า code coverage > 80%
- มี unit test สำหรับ business logic ที่สำคัญ
- อย่าลืม edge case และ error handling
3. Fail Fast, Fix Fast 🔴
เรียง pipeline จากเร็วไปช้า (lint → unit test → integration → E2E) เพื่อให้ fail เร็วที่สุด ถ้า lint fail ใน 10 วินาทีดีกว่ารอ E2E test 15 นาทีแล้ว fail เมื่อ fail แล้วต้องแก้ทันที — อย่าปล่อยให้ pipeline แดงค้าง:
- ถ้า pipeline fail → แก้เป็นอันดับแรก ก่อนทำอย่างอื่น
- อย่าปล่อยให้ pipeline แดงค้าง → ทีมจะชินกับ "แดงก็แดง"
4. ใช้ Environment Variables สำหรับ Secrets 🔐
อย่า hardcode passwords, API keys, tokens ใน code หรือ pipeline YAML — ใช้ GitHub Secrets, Vault, หรือ environment variables แทน secrets ที่เข้า Git จะอยู่ใน history ตลอดไป:
# ❌ อย่าทำ
- run: mysql -u root -p mypassword123
# ✅ ทำแบบนี้
- run: mysql -u $DB_USER -p $DB_PASSWORD
env:
DB_USER: ${{ secrets.DB_USER }}
DB_PASSWORD: ${{ secrets.DB_PASSWORD }}
5. ทำให้ Pipeline เหมือนกันทุก Environment 🔄
Development → Staging → Production ควรใช้ pipeline เดียวกัน ต่างกันแค่ config (database URL, API keys, feature flags) ถ้าแต่ละ environment ใช้ pipeline ต่างกัน จะเจอปัญหา "staging ผ่านแต่ production พัง" — ใช้ Docker + environment variables ทำให้ environment ต่างกันแค่ config ไม่ใช่ infrastructure
เปรียบเทียบ: ก่อน vs หลังใช้ CI/CD
ตารางด้านล่างแสดงความแตกต่างที่ชัดเจนระหว่าง manual deployment กับ CI/CD — จะเห็นว่า CI/CD ลดทั้ง risk, เวลา, และ human error ได้มหาศาล:
| ก่อน CI/CD | หลัง CI/CD | |
|---|---|---|
| Build | ทำมือ, "ลืม build" | อัตโนมัติทุก push |
| Test | "เดี๋ยว test ทีหลัง" | test ทุกครั้ง ถ้าไม่ผ่านหยุดเลย |
| Deploy | SSH เข้าเซิร์ฟเวอร์ ลาก file ด้วยมือ | กดปุ่มเดียว หรืออัตโนมัติ |
| Bug พบตอนไหน | ตอน user โทรมาด่า | ตอน pipeline fail (ก่อน deploy) |
| ความมั่นใจ | "หวังว่าจะไม่พัง" 🤞 | "test ผ่านแล้ว มั่นใจ" ✅ |
| Deploy frequency | เดือนละครั้ง (กลัวพัง) | วันละหลายครั้ง |
สรุป
- CI (Continuous Integration) = build + test อัตโนมัติทุกครั้งที่ push code
- CD (Continuous Delivery/Deployment) = deploy อัตโนมัติ (หรือกึ่งอัตโนมัติ) ไป production
- Pipeline = ลำดับขั้นตอน: Source → Build → Test → Stage → Deploy
- ถ้าขั้นตอนใด fail → pipeline หยุด → ไม่มี code พังหลุดไป production
- เลือกเครื่องมือตามทีมและโปรเจกต์: GitHub Actions เหมาะสำหรับเริ่มต้น
- Pipeline เร็ว + test ครอบคลุม + fix fast = DevOps ที่ดี
ในโพสต์หน้าเราจะมาพูดถึง Docker — เครื่องมือที่ทำให้ "It works on my machine" กลายเป็นเรื่องในอดีต! 🐳🐕