เปลี่ยนการรวมโค้ดที่ยุ่งยากให้เป็นเรื่องอัตโนมัติ เพื่อคุณภาพซอฟต์แวร์ที่ดียิ่งขึ้น
เมื่อ Developer หลายคนทำงานแยกกันเป็นเวลานาน แล้วมา "รวมร่าง" กันทีเดียวตอนจบ
แนวปฏิบัติในการพัฒนาซอฟต์แวร์ที่นักพัฒนาจะทำการ รวมโค้ด (Merge) เข้าสู่ Shared Repository บ่อยๆ (อย่างน้อยวันละครั้ง)
Dev commits code to Git
CI Server compiles code
Run automated tests & Static Analysis
Pass/Fail Notification
เจอ Bug ทันทีที่ commit ไม่ต้องรอไปเจอตอน production
การรวมโค้ดทีละนิดบ่อยๆ ง่ายกว่าการรวมก้อนใหญ่ทีเดียว
เมื่อกระบวนการทดสอบเป็นอัตโนมัติ เราก็ปล่อยของได้เร็วขึ้น
ทีมสื่อสารกันผ่านโค้ดและการแจ้งเตือน ลดความสับสน
การทำ CI ไม่ใช่แค่การลงเครื่องมือ แต่ต้องมีองค์ประกอบเหล่านี้
ต้องมีศูนย์กลางเก็บโค้ด เช่น Git (GitHub, GitLab, Bitbucket) เพื่อจัดการ Source Code
สคริปต์ที่สามารถ Compile, Link, หรือ Package โค้ดได้ด้วยคำสั่งเดียว (เช่น npm build, docker build)
สิ่งที่ขาดไม่ได้! ถ้าไม่มี Test ก็ไม่ใช่ CI (Unit Test, Integration Test)
เป้าหมาย: เปลี่ยน Source Code ให้เป็น Executable Artifact ที่พร้อมรัน
$ npm install
$ npm run build
... Creating optimized production build ...
$ docker build -t my-app:v1 .
กระดูกสันหลังของ CI คือการทดสอบอัตโนมัติ เพื่อรับประกันคุณภาพ
Unit Tests: ทดสอบฟังก์ชันย่อยๆ แยกกัน (ควรมีเยอะที่สุด)
Integration Tests: ทดสอบการทำงานร่วมกันระหว่าง Module/Database
*CI Server จะรัน Test เหล่านี้ทุกครั้ง ถ้า Test ไม่ผ่าน = Build Failed (ห้าม Merge!)
การตรวจสอบโค้ดโดยไม่ต้องรันโปรแกรม (Code Quality & Security)
ตรวจสอบรูปแบบการเขียนโค้ดให้เป็นมาตรฐานเดียวกัน (เช่น ESLint, Pylint)
ค้นหาจุดที่อาจก่อให้เกิด Bug เช่น ตัวแปรที่ไม่ได้ใช้, Infinite Loop
ค้นหาช่องโหว่ความปลอดภัยเบื้องต้นในโค้ด (เช่น Hardcoded Password)
CI ที่ดีต้องแจ้งผลเร็วและชัดเจน เพื่อให้ Developer แก้ไขได้ทันที
ถัดไปเราจะมาดู "เครื่องมือ" ที่ทำให้กระบวนการเหล่านี้เป็นจริง
รุ่นเก๋า, Open Source, ปรับแต่งได้สูงมาก แต่ดูแลยาก
มาแรง, Integrate กับ GitHub แน่นปึ้ก, ฟรีสำหรับ Public Repo
All-in-one platform, ดีเยี่ยมสำหรับองค์กรที่ใช้ GitLab, มี Auto DevOps
เป็นส่วนหนึ่งของ GitLab ทำให้ Code และ Pipeline อยู่ที่เดียวกัน ไม่ต้อง setup แยก
Automation Tool ที่มาพร้อมกับ GitHub ที่เราจะเน้นใน Lab นี้
push, pull_request)# .github/workflows/ci.yml
name:
CI Pipelineon:
[push]jobs:
build-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: npm install
- run: npm test
| Feature | Jenkins | GitLab CI | GitHub Actions |
|---|---|---|---|
| Hosting | Self-hosted | Cloud / Self-hosted | Cloud / Self-hosted |
| Configuration | Jenkinsfile (Groovy) | YAML (.gitlab-ci.yml) | YAML (Workflows) |
| Difficulty | High (Setup/Plugins) | Medium | Low (Easy to start) |
| Ecosystem | Massive Plugin Library | Integrated in GitLab | Huge Marketplace |
Git Hooks คือสคริปต์ที่ Git จะเรียกใช้งาน (Fire) เมื่อมีเหตุการณ์สำคัญเกิดขึ้น เช่น ก่อน Commit หรือหลัง Push
ป้องกัน "Bad Code" ไม่ให้เข้าสู่ Repo ตั้งแต่เครื่อง Developer
# .git/hooks/pre-commit
#!/bin/sh
echo "Running pre-commit checks..."
# Run Linter
npm run lint
if
[ $? -ne 0 ];then
echo "Lint failed! Commit rejected."
exit 1 # Non-zero exit blocks the commit
fi
Tip: ใช้ framework อย่าง pre-commit หรือ husky (สำหรับ JS) จะจัดการง่ายกว่าเขียน shell script เอง
Git Server (GitHub/GitLab) ส่งสัญญาณบอก CI Server ว่า "มีโค้ดใหม่มาแล้วนะ!"
Event: Push
Action: Start Build
เราจะสร้าง Automated Pipeline ให้กับโปรเจกต์ Resume Hub ที่มีทั้ง Backend (Django) และ Frontend (React)
เตรียม Source Code จาก GitHub (Branch wk05)
# 1. ไปที่ GitHub และ Fork Repository นี้:
https://github.com/wichitpaulsombat/djrepo
# 2. Clone Repository ของคุณลงเครื่อง (เปลี่ยน YOUR_USER)
$ git clone -b wk05 https://github.com/YOUR_USER/djrepo.git
$ cd djrepo
# 3. ตรวจสอบโครงสร้างไฟล์ (ควรเจอ folder backend/ และ frontend/)
$ ls -F
backend/ frontend/ docker-compose.yaml ...
เนื่องจากเราเก็บโค้ดทั้ง 2 ส่วนไว้ใน Repo เดียว เราควรกำหนด Paths Filter เพื่อประหยัดทรัพยากร
ทำงานเมื่อมีการแก้ไขไฟล์ในโฟลเดอร์ backend/** เท่านั้น
ทำงานเมื่อมีการแก้ไขไฟล์ในโฟลเดอร์ frontend/** เท่านั้น
👉 เราจะสร้างไฟล์ Workflow แยกกัน 2 ไฟล์: django.yml และ react.yml
สร้างไฟล์ .github/workflows/django.yml
name: Django CI
on:
push:
branches: [ "wk05" ]
paths:
- "backend/**" # ทำงานเฉพาะเมื่อแก้ backend
pull_request:
branches: [ "wk05" ]
paths:
- "backend/**"
jobs:
build-test:
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./backend # เข้าไปใน folder backend เสมอ
ต่อจากไฟล์เดิม เพิ่มขั้นตอนการติดตั้งและทดสอบ
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Install Dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: Run Tests
run: |
python manage.py test
defaults.run.working-directory ไว้แล้ว คำสั่ง pip และ manage.py จะรันในโฟลเดอร์ backend โดยอัตโนมัติ
สร้างไฟล์ .github/workflows/react.yml
name: React CI
on:
push:
branches: [ "wk05" ]
paths:
- "frontend/**" # เฉพาะไฟล์ Frontend
pull_request:
branches: [ "wk05" ]
paths:
- "frontend/**"
jobs:
build:
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./frontend
steps:
- uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: "18"
cache: "npm"
cache-dependency-path: frontend/package-lock.json
- name: Install Dependencies
run: npm ci
- name: Build
run: npm run build
env:
CI: false # ป้องกัน build fail จาก warning เล็กน้อย (Optional)
cache: "npm" จะช่วยให้การติดตั้ง dependencies ในรอบถัดไปเร็วขึ้นมาก
เมื่อสร้างไฟล์ Workflow ทั้งสองเสร็จแล้ว ให้ส่งขึ้น GitHub
# ตรวจสอบสถานะ
$ git status
# Add files
$ git add .github/workflows/
# Commit
$ git commit -m "Add CI pipelines for Backend and Frontend"
# Push to wk05 branch
$ git push origin wk05
1. เปิด GitHub Repository ของคุณ
2. ไปที่แท็บ Actions
3. คุณควรเห็น Workflows ทั้ง Django CI และ React CI กำลังทำงาน (หรือทำงานเสร็จแล้ว)
ถ้าโค้ดไม่มี Error ไฟจะเขียว
ถ้า Build พัง หรือ Test ไม่ผ่าน
ลองแก้ไขไฟล์เฉพาะส่วน Frontend เพื่อดูว่า Backend CI จะไม่ทำงาน
# แก้ไขไฟล์ Frontend เล็กน้อย
แก้ไข frontend/src/App.jsx (เช่นเปลี่ยนข้อความ)
$ git add frontend/src/App.jsx
$ git commit -m "Update frontend text"
$ git push origin wk05
👀 สังเกตที่แท็บ Actions: ควรจะมีแค่ React CI เท่านั้นที่ทำงาน ส่วน Django CI จะนิ่งสนิท (Skipped) นี่คือข้อดีของการทำ Path Filtering!
เพิ่มคุณภาพโค้ดด้วยการตรวจจับ Syntax Error อัตโนมัติ
เพิ่มใน django.yml:
- name: Lint with flake8
run: |
pip install flake8
# stop the build if there are Python syntax errors
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
เพิ่มใน react.yml (ก่อน build):
- name: Lint
run: npm run lint
บังคับให้ CI ผ่านก่อน Merge (Best Practice)
1. ไปที่ Settings ของ Repository > Branches
2. คลิก Add branch protection rule
3. Branch name pattern: wk05 (หรือ main)
4. ติคถูกที่ Require status checks to pass before merging
5. ค้นหาและเลือก build-test (จาก Django) และ build (จาก React)
6. กด Create
ผลลัพธ์: ถ้าใครเปิด Pull Request เข้ามาแล้ว Test พัง ปุ่ม Merge จะกดไม่ได้! 🛡️
สาเหตุ: ไม่ได้ตั้ง working-directory หรือ path ผิด
แก้: เช็ค defaults.run.working-directory: ./backend
สาเหตุ: ไม่มี package-lock.json ใน repo
แก้: รัน npm install ในเครื่องแล้ว push ไฟล์ lock ขึ้นไปก่อน
สาเหตุ: React Treat Warnings as Errors ใน CI
แก้: เพิ่ม env CI: false ใน step build
คุณได้สร้างระบบ CI เต็มรูปแบบสำหรับ Modern Web Application แล้ว