# บทที่ 10: Demo - Full CI/CD Pipeline ตั้งแต่พัฒนา ถึง Deploy

## สร้าง **Simple Todo App** แบบ Full Stack:

- Backend: Node.js Express API
- Frontend: HTML/CSS/JavaScript (ใน public/ folder)
- Tests: Jest (Backend) + Playwright (Frontend E2E)
- Repository: GitHub
- CI/CD: GitHub Actions
- Deploy: Vercel (ทำได้)

---

## 📑 สารบัญ

1. [ขั้นตอนที่ 1: Setup GitHub Repository](#ขั้นตอนที่-1-setup-github-repository)
2. [ขั้นตอนที่ 2: สร้าง Local Project](#ขั้นตอนที่-2-สร้าง-local-project)
3. [ขั้นตอนที่ 3: Git Workflow - Feature Branch](#ขั้นตอนที่-3-git-workflow---feature-branch)
4. [ขั้นตอนที่ 4: Setup GitHub Actions](#ขั้นตอนที่-4-setup-github-actions)
5. [ขั้นตอนที่ 5: Create Pull Request](#ขั้นตอนที่-5-create-pull-request)
6. [ขั้นตอนที่ 6: Merge & Deploy](#ขั้นตอนที่-6-merge--deploy)
7. [ขั้นตอนที่ 7: Monitor & Rollback](#ขั้นตอนที่-7-monitor--rollback)

---

## ขั้นตอนที่ 1: Setup GitHub Repository

### 1.1 สร้าง Repository บน GitHub

```bash
# 1. ไปที่ https://github.com/new
# 2. Repository name: todo-app
# 3. Add README.md
# 4. Add .gitignore: Node
# 5. Create repository
```

### 1.2 Clone Repository ลงมา

```bash
git clone https://github.com/YOUR_USERNAME/todo-app.git
cd todo-app

# ตรวจสอบ branch
git branch
# Output: * main
```

---

## ขั้นตอนที่ 2: สร้าง Local Project

### 2.1 สร้างโครงสร้าง Project

**Project Structure:**

```
todo-app/
├── public/
│   ├── index.html          ← Web page
│   ├── style.css           ← Styling
│   └── app.js              ← Frontend JavaScript
├── tests/
│   └── e2e/
│       └── todo.spec.js    ← E2E tests (Playwright)
├── __tests__/
│   └── todo.test.js        ← API tests (Jest + Supertest)
├── .github/
│   └── workflows/
│       └── ci.yml          ← CI Pipeline
├── .env.example            ← Environment variables template
├── .eslintrc.json          ← ESLint config
├── .gitignore              ← Git ignore list
├── .prettierrc.json        ← Prettier formatter config
├── jest.config.js          ← Jest test config
├── playwright.config.js    ← Playwright config
├── package.json            ← Dependencies & scripts
├── index.js                ← Backend Express API
├── README.md               ← Project overview
├── SETUP.md                ← Setup instructions
├── COMMANDS.md             ← Quick command reference
├── FRONTEND.md             ← Frontend documentation
├── E2E_TESTS.md            ← Playwright E2E tests guide
├── API_TESTS.md            ← Supertest API tests guide
└── node_modules/           ← Dependencies (auto-generated)
```

**Commands:**

```bash
# สร้าง package.json
npm init -y

# Install dependencies
npm install express cors dotenv
npm install --save-dev jest nodemon eslint prettier @playwright/test
```

### 2.2 สร้าง Basic App

**package.json scripts:**

```json
{
  "name": "todo-app",
  "version": "1.0.0",
  "scripts": {
    "start": "node index.js",
    "dev": "nodemon index.js",
    "test": "jest",
    "test:e2e": "playwright test",
    "test:e2e:ui": "playwright test --ui",
    "test:e2e:headed": "playwright test --headed",
    "lint": "eslint .",
    "lint:fix": "eslint . --fix",
    "build": "echo 'Building app...'"
  },
  "dependencies": {
    "express": "^4.18.2",
    "cors": "^2.8.5",
    "dotenv": "^16.0.3"
  },
  "devDependencies": {
    "jest": "^29.5.0",
    "nodemon": "^2.0.20",
    "eslint": "^8.40.0",
    "prettier": "^2.8.8",
    "supertest": "^6.3.3",
    "@playwright/test": "^1.40.0"
  }
}
```

**index.js:**

```javascript
const express = require("express");
const cors = require("cors");
require("dotenv").config();

const app = express();
app.use(cors());
app.use(express.json());

// Serve static files (HTML, CSS, JS)
app.use(express.static("public"));

// Sample data
let todos = [
  { id: 1, title: "Learn Git", completed: false },
  { id: 2, title: "Learn CI/CD", completed: false },
];

// GET all todos
app.get("/api/todos", (req, res) => {
  res.json(todos);
});

// GET single todo
app.get("/api/todos/:id", (req, res) => {
  const todo = todos.find((t) => t.id === parseInt(req.params.id));
  if (!todo) return res.status(404).json({ error: "Todo not found" });
  res.json(todo);
});

// POST new todo
app.post("/api/todos", (req, res) => {
  const { title } = req.body;
  if (!title) return res.status(400).json({ error: "Title required" });

  const newTodo = {
    id: Math.max(...todos.map((t) => t.id), 0) + 1,
    title,
    completed: false,
  };
  todos.push(newTodo);
  res.status(201).json(newTodo);
});

// DELETE todo
app.delete("/api/todos/:id", (req, res) => {
  const index = todos.findIndex((t) => t.id === parseInt(req.params.id));
  if (index === -1) return res.status(404).json({ error: "Todo not found" });

  const deletedTodo = todos.splice(index, 1);
  res.json(deletedTodo[0]);
});

// UPDATE todo
app.put("/api/todos/:id", (req, res) => {
  const todo = todos.find((t) => t.id === parseInt(req.params.id));
  if (!todo) return res.status(404).json({ error: "Todo not found" });

  if (req.body.title) todo.title = req.body.title;
  if (req.body.completed !== undefined) todo.completed = req.body.completed;

  res.json(todo);
});

// Health check
app.get("/health", (req, res) => {
  res.json({ status: "ok", timestamp: new Date().toISOString() });
});

const PORT = process.env.PORT || 3000;
if (require.main === module) {
  app.listen(PORT, () => {
    console.log(`🚀 Server running on http://localhost:${PORT}`);
    console.log(`🌐 Frontend: http://localhost:${PORT}`);
    console.log(`📝 API: http://localhost:${PORT}/api/todos`);
    console.log(`❤️  Health: http://localhost:${PORT}/health`);
  });
}

module.exports = app;
```

**`.eslintrc.json`:**

```json
{
  "env": {
    "node": true,
    "es2021": true
  },
  "extends": "eslint:recommended",
  "parserOptions": {
    "ecmaVersion": "latest"
  },
  "rules": {
    "indent": ["error", 2],
    "linebreak-style": ["error", "unix"],
    "quotes": ["error", "single"],
    "semi": ["error", "always"],
    "no-unused-vars": ["warn"],
    "no-console": "off"
  }
}
```

**`jest.config.js`:**

```javascript
module.exports = {
  testEnvironment: "node",
  collectCoverageFrom: ["index.js"],
  testMatch: ["**/__tests__/**/*.test.js"],
  verbose: true,
};
```

**`.env.example`:**

```
PORT=3000
NODE_ENV=development
```

**`__tests__/todo.test.js`:**

```javascript
describe("Todo API", () => {
  it("should have correct structure", () => {
    expect([1, 2]).toHaveLength(2);
  });

  it("should have a title property", () => {
    const todo = { id: 1, title: "Learn Git", completed: false };
    expect(todo).toHaveProperty("title");
  });
});
```

**`.gitignore` (เลือก Node.js template):**

```
node_modules/
dist/
.env
.env.local
.env*.local
.DS_Store
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.vercel
.next
build/
coverage/
.idea/
.vscode/
# Playwright artifacts
test-results/
playwright-report/
.auth/
```

### 2.2 ไฟล์เอกสาร

**SETUP.md** - ขั้นตอนการตั้งค่า

- สร้าง Repository บน GitHub
- Clone และ Setup Local
- การทำ Feature Branch Workflow
- ตรวจสอบรายการเรียนรู้
- สิ่งที่ได้เรียนรู้

**COMMANDS.md** - คำสั่งอ้างอิงด่วน

- คำสั่ง Development
- คำสั่ง Testing (Jest, Supertest, Playwright)
- คำสั่ง Build & Deploy
- คำสั่ง Git

**README.md** - รายละเอียดโปรเจค

- ภาพรวมโปรเจค
- API Endpoints
- โครงสร้างโปรเจค
- ขั้นตอน Setup
- Scripts ที่มี
- การทดสอบคุณภาพ

**FRONTEND.md** - เอกสารส่วนหน้า

- หน้าปัจจุบัน (index.html)
- ฟังก์ชันการทำงาน
- API Integration
- Error Handling
- Mobile Responsive

**E2E_TESTS.md** - E2E Testing Guide

- บทนำ Playwright
- Test Cases ที่ 11 tests
- วิธีการรัน Playwright
- การอ่านผลลัพธ์
- Debugging Tests

**API_TESTS.md** - API Testing Guide

- บทนำ Supertest
- Test Cases ที่ 13 tests
- วิธีการรัน Jest + Supertest
- Response Format Validation
- Error Handling Tests

---

### 2.3 Local Testing ก่อน Commit

**ทดสอบ Lint:**

```bash
npm run lint
# Output:
# ✅ Linting completed (no errors)
```

**ทดสอบ Jest + Supertest Unit Tests:**

```bash
npm test
# Output:
# PASS  __tests__/todo.test.js
#   Todo API - Endpoints
#     GET /api/todos
#       ✓ should return all todos (45ms)
#       ✓ should return todos with correct structure (12ms)
#     GET /api/todos/:id
#       ✓ should return single todo by id (8ms)
#       ✓ should return 404 for non-existent todo (5ms)
#     POST /api/todos
#       ✓ should create new todo (22ms)
#       ✓ should return 400 if title is missing (8ms)
#     PUT /api/todos/:id
#       ✓ should update todo completion status (15ms)
#       ✓ should update todo title (12ms)
#       ✓ should return 404 for non-existent todo (6ms)
#     DELETE /api/todos/:id
#       ✓ should delete todo (18ms)
#       ✓ should return 404 for non-existent todo (5ms)
#     GET /health
#       ✓ should return health status (3ms)
#
# Test Suites: 1 passed, 1 total
# Tests:       13 passed, 13 total
# Time:        2.456s
```

**ทดสอบ Development Server:**

```bash
npm run dev
# Output:
# 🚀 Server running on http://localhost:3000
# 🌐 Frontend: http://localhost:3000
# 📝 API: http://localhost:3000/api/todos
# ❤️  Health: http://localhost:3000/health

# ทดสอบ API ใน terminal อื่น:
curl http://localhost:3000/api/todos
# Output:
# [{"id":1,"title":"Learn Git","completed":false}, ...]

# ทดสอบ Frontend ที่ http://localhost:3000 ใน browser
# - ดู Todo list
# - เพิ่ม todo ใหม่
# - ลบ todo
```

**ทดสอบ E2E Tests (Playwright):**

```bash
# Terminal 1: ตรวจสอบ backend รันอยู่
npm run dev

# Terminal 2: รัน E2E tests
npx playwright install  # ครั้งแรกเท่านั้น
npm run test:e2e

# Output:
# ✓ should display home page
# ✓ should load todos from API
# ✓ should display API status
# ✓ should add new todo
# ✓ should add todo with Enter key
# ✓ should mark todo as completed
# ✓ should delete todo
# ✓ should show error when adding empty todo
# ✓ should display todo count
# ✓ should have API endpoints info section
# ✓ should be responsive on mobile
#
# 11 passed (5.2s)
```

**ดู E2E Test Report:**

```bash
npx playwright show-report
# Opens browser with interactive test report
```

### 2.4 Commit ขึ้น Repository

```bash
# ตรวจสอบ status
git status
# Output:
# On branch main
# Untracked files:
#   .eslintrc.json
#   .env.example
#   .gitignore
#   __tests__/
#   index.js
#   jest.config.js
#   package.json

# Add all files
git add .

# Commit
git commit -m "chore: Initial project setup with API and tests"

# Push
git push origin main

# Verify on GitHub (refresh page) - should see all files
```

---

## ขั้นตอนที่ 3: Git Workflow - Feature Branch

### 3.1 สร้าง Feature Branch

```bash
# สร้าง feature branch สำหรับ "Add delete todos"
git checkout -b feature/delete-todos

# ตรวจสอบว่าอยู่บน branch ใหม่
git branch
# Output:
# * feature/delete-todos
#   main
```

### 3.2 ทำการพัฒนา Feature

**เพิ่ม DELETE endpoint ใน index.js:**

```javascript
// DELETE todo
app.delete("/api/todos/:id", (req, res) => {
  const index = todos.findIndex((t) => t.id === parseInt(req.params.id));
  if (index === -1) return res.status(404).json({ error: "Todo not found" });

  const deletedTodo = todos.splice(index, 1);
  res.json(deletedTodo[0]);
});
```

### 3.3 Commit Changes

```bash
# ดู changes
git diff

# Add changes
git add index.js

# Commit
git commit -m "feat: Add DELETE /api/todos/:id endpoint"

# Push feature branch
git push origin feature/delete-todos
```

### 3.4 ตรวจสอบบน GitHub

สังเกตว่า GitHub จะแสดงข้อความ:

```
Compare & pull request
```

---

## ขั้นตอนที่ 4: Setup GitHub Actions

### 4.1 สร้าง CI Pipeline

**`.github/workflows/ci.yml`:**

```yaml
name: CI Pipeline

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main, develop]

jobs:
  build:
    runs-on: ubuntu-latest
    timeout-minutes: 10

    strategy:
      matrix:
        node-version: [18.x]

    steps:
      # 1. Checkout code
      - name: Checkout code
        uses: actions/checkout@v3

      # 2. Setup Node.js
      - name: Setup Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v3
        with:
          node-version: ${{ matrix.node-version }}
          cache: "npm"

      # 3. Install dependencies
      - name: Install dependencies
        run: npm ci

      # 4. Lint
      - name: Run linter
        run: npm run lint

      # 5. Test
      - name: Run tests
        run: npm test

      # 6. Build
      - name: Build
        run: npm run build

      # 7. Success message
      - name: ✅ All checks passed!
        run: echo "Pipeline completed successfully"
```

### 4.2 Setup GitHub Secrets (สำหรับ Vercel Deploy)

1. ไปที่ GitHub Repository
2. Settings → Secrets and variables → Actions
3. กด "New repository secret"
4. ชื่อ: `VERCEL_TOKEN`
5. ค่า: [หาจาก Vercel Dashboard]
   - ไปที่ vercel.com
   - Settings → Tokens
   - Create New Token
   - Copy and paste ลงใน GitHub

### 4.3 Commit CI Configuration

```bash
# สร้าง folder (ถ้ายังไม่มี)
mkdir -p .github/workflows

# Add CI file
git add .github/workflows/ci.yml
git commit -m "chore: Add GitHub Actions CI pipeline"
git push origin main
```

### 4.4 ดู CI Pipeline Run

**ตรวจสอบ Pipeline:**

1. ไปที่ GitHub Repository → **Actions** tab
2. ดู workflow status:
   - 🟠 **In Progress** (รันอยู่)
   - ✅ **Success** (ผ่านทั้งหมด)
   - ❌ **Failed** (มีบางขั้นตอนล้มเหลว)

**ตัวอย่าง Success Output:**

```
CI Pipeline (4 minutes took)
✓ Checkout code
✓ Setup Node.js 18
✓ Install dependencies
✓ Run linter
✓ Run tests
✓ Build
✓ Build successful

✅ All checks passed!
```

**ถ้า Failed:**

- คลิก workflow เพื่อดูรายละเอียด
- ดูว่า step ไหนล้มเหลว
- ดู error message
- แก้ไขในเครื่องแล้ว push ใหม่

---

## ขั้นตอนที่ 5: Create Pull Request

### 5.1 สร้าง PR บน GitHub Web

**ขั้นตอน:**

```
1. ไปที่ GitHub Repository
2. หา "Compare & pull request" button
   (หรือไป Pull requests tab → New pull request)
3. เลือก:
   - Base branch: main
   - Compare branch: feature/delete-todos
4. กรอก PR Details แล้ว Click "Create pull request"
```

**ตัวแบบ:**

**PR Title:**

```
feat: Add DELETE endpoint to remove todos
```

**PR Description:**

````markdown
## Description

This PR adds the ability to delete todos via DELETE /api/todos/:id endpoint

## Type of change

- [x] New feature
- [ ] Bug fix

## Testing

```bash
curl -X DELETE http://localhost:3000/api/todos/1
```
````

## Checklist

- [x] Code follows style guidelines
- [x] I have performed a self-review of my code
- [x] I have tested the changes locally

```

### 5.2 GitHub Actions จะ Trigger

GitHub Actions จะอัตโนมัติเมื่อสร้าง PR:
1. ✅ Checkout code
2. ✅ Setup Node.js 18
3. ✅ Install dependencies (npm ci)
4. ✅ Run linter (npm run lint)
5. ✅ Run tests (npm test)
6. ✅ Build (npm run build)
7. ✅ Build successful

**ผลลัพธ์:**

- ✅ **All checks passed** → สามารถ merge ได้
```

Conversation
✓ All checks have passed
You can now merge this pull request

```

- ❌ **Some checks failed** → ต้องแก้ไขก่อน
```

Conversation
✗ Some checks were not successful
Fix the issues then push again

```

**ดู Error Details:**
- ใน PR page → "Checks" tab
- คลิก "CI Pipeline"
- ดู "Run linter" หรือ "Run tests" ว่าผิดตรงไหน

---

## ขั้นตอนที่ 6: Merge & Deploy

### 6.1 Code Review & Approval

```

GitHub Flow:

1. Create PR ✅
2. CI Pipeline run ✅
3. Developer review code
4. Approve PR
5. Merge to main

```

### 6.2 Merge PR

**เมื่อ CI Pipeline ✅ PASS:**

**Option 1: Merge บน GitHub Web (แนะนำ)**

```

1. ไปที่ PR page
2. สังเกตว่า "Merge pull request" button ขึ้นมา
3. กดปุ่มสีเขียว (อาทิ "Merge pull request")
4. เลือก merge strategy:
   - Create a merge commit (default)
   - Squash and merge
   - Rebase and merge
5. Confirm merge
6. Delete branch (ถ้าต้องการ)

````

**Option 2: Local Merge**

```bash
git checkout main
git pull origin main
git merge --ff feature/delete-todos
git push origin main

# ลบ local feature branch
git branch -d feature/delete-todos

# ลบ remote feature branch
git push origin --delete feature/delete-todos
````

### 6.3 Auto-Deploy (สำหรับ Production)

**Setup Vercel Deployment** (เพิ่มเข้า CI):

```yaml
# เพิ่มใน .github/workflows/ci.yml

# 8. Deploy to Vercel (optional)
- name: Deploy to Vercel
  if: github.ref == 'refs/heads/main'
  run: |
    npm install -g vercel
    vercel --prod --token ${{ secrets.VERCEL_TOKEN }}
```

**ผลลัพธ์:**

```
main branch updated
  ↓ (GitHub Actions trigger)
CI Pipeline run (lint, test, build)
  ↓ (All passed)
Deploy to Vercel Production
  ↓
Live at: https://todo-app.vercel.app
```

---

## ขั้นตอนที่ 7: Monitor & Rollback

### 7.1 Monitor Production

**ตรวจสอบ Deployment Status:**

```bash
# Check deployed version
curl https://todo-app.vercel.app/api/todos

# Response (Success - 200):
# [
#   { "id": 1, "title": "Learn Git", "completed": false },
#   { "id": 2, "title": "Learn CI/CD", "completed": false }
# ]

# Test DELETE endpoint
curl -X DELETE https://todo-app.vercel.app/api/todos/1

# Response:
# { "id": 1, "title": "Learn Git", "completed": false }
```

**ตรวจสอบ Vercel Dashboard:**

```
1. ไปที่ vercel.com → todo-app project
2. ดู Deployments tab
3. เลือก latest deployment
4. ดู logs และ status:
   ✅ Ready (deployed สำเร็จ)
   🟠 Building (รอสักครู่)
   ❌ Error/Failed (มีปัญหา)
```

### 7.2 Troubleshooting Deployment

**ถ้า Deploy or CI ล้มเหลว:**

```
ขั้นที่ 1: ตรวจสอบ Error Logs
  - GitHub Actions tab → ดู failed step
  - Vercel Dashboard → Deployment logs
  - ดู error message ที่ชัดเจน

ขั้นที่ 2: ระบุปัญหา
  - npm ci failed? → package.json มีปัญหา
  - Lint failed? → Code style ผิด
  - Test failed? → Test case ผิด
  - Build failed? → Build script มีปัญหา

ขั้นที่ 3: แก้ไขในเครื่อง
  git checkout main
  git pull origin main
  # แก้ไขไฟล์ที่มีปัญหา
  npm run lint:fix  # Fix lint errors auto
  npm test          # Verify tests pass
  npm run build     # Verify build passes

ขั้นที่ 4: Push ใหม่
  git add .
  git commit -m "fix: Fix deployment issue"
  git push origin main

ขั้นที่ 5: ตรวจสอบ CI Pipeline
  - ไปที่ GitHub Actions tab
  - รอให้ workflow complete
  - ตรวจสอบว่า ✅ All checks passed
```

**Common Issues & Solutions:**

| ปัญหา                          | เหตุผล                        | วิธีแก้ไข                             |
| ------------------------------ | ----------------------------- | ------------------------------------- |
| `npm ci failed`                | Dependencies version mismatch | ลบ `node_modules`, `npm install` ใหม่ |
| `Lint error: quotes`           | ใช้ double quotes แทน single  | `npm run lint:fix`                    |
| `Test failed`                  | Test case ล้มเหลว             | ตรวจสอบ `__tests__/` files            |
| `Port already in use`          | Port 3000 ถูกใช้อยู่          | เปลี่ยน PORT ใน .env                  |
| `Cannot find module 'express'` | dependencies ยังไม่ install   | รัน `npm install`                     |
| `VERCEL_TOKEN not found`       | GitHub Secrets ยังไม่ setup   | ตั้งค่า VERCEL_TOKEN ใน Settings      |
| `Build error on Vercel`        | Environment variable ขาด      | เพิ่ม .env vars ใน Vercel Dashboard   |

### 7.3 Rollback (ถ้าจำเป็น)

**วิธีที่ 1: Vercel Rollback (เร็วที่สุด)**

```
1. ไป vercel.com → todo-app
2. Deployments tab
3. หาเวอร์ชัน "Stable" ก่อนหน้า
4. กด "..." → "Promote to Production"
5. ระบบจะเปลี่ยนไป production เดิม

ผลลัพธ์: Production rollback ลำเพังใน 10 วินาที
```

**วิธีที่ 2: Git Rollback (ถ้าต้องแก้ code)**

```bash
# ดูประวัติ commit
git log --oneline
# Output:
# abc1234 feat: Add DELETE endpoint
# def5678 chore: Initial setup

# Revert last commit
git revert HEAD
# แล้ว push
git push origin main

# GitHub Actions จะ trigger CI อีกครั้ง
# หลังจาก CI pass → auto-deploy rollback version
```

\*\*วิธีที่ 3: Reset to Previous Version (ถ้า code เสีย)

```bash
# ระบุตำแหน่งที่ต้องการ rollback
git reset --hard def5678

# Force push (⚠️ ระวัง!)
git push origin main --force
```

---

## 📊 สรุป: Workflow ทั้งหมด

```
┌──────────────────────────────────────┐
│ 1. สร้าง Feature Branch              │
│    git checkout -b feature/..        │
└──────────┬───────────────────────────┘
           ↓
┌──────────────────────────────────────┐
│ 2. Local Development                 │
│    npm run dev                       │
│    git commit + git push             │
└──────────┬───────────────────────────┘
           ↓
┌──────────────────────────────────────┐
│ 3. Create Pull Request               │
│    (GitHub Web)                      │
└──────────┬───────────────────────────┘
           ↓
┌──────────────────────────────────────┐
│ 4. GitHub Actions CI Pipeline        │
│    ✅ Lint, Test, Build              │
└──────────┬───────────────────────────┘
           ↓
┌──────────────────────────────────────┐
│ 5. Code Review                       │
│    (Developer review)                │
└──────────┬───────────────────────────┘
           ↓
┌──────────────────────────────────────┐
│ 6. Merge to Main                     │
│    (Approve + Merge)                 │
└──────────┬───────────────────────────┘
           ↓
┌──────────────────────────────────────┐
│ 7. Auto-Deploy to Production         │
│    (Vercel)                          │
└──────────┬───────────────────────────┘
           ↓
┌──────────────────────────────────────┐
│ 8. Monitor                           │
│    ✅ Live in Production             │
│    ❌ Rollback if needed             │
└──────────────────────────────────────┘
```

---

---

## 📋 Quick Checklist: ก่อนสร้าง PR

```bash
# 1. ตรวจสอบ branch ว่าถูก feature branch
git branch
# Output: * feature/delete-todos

# 2. Run lint
npm run lint
# ✅ ต้องไม่มี error

# 3. Run API tests (Jest + Supertest)
npm test
# ✅ ต้องผ่าน 13 tests (GET, POST, PUT, DELETE endpoints + health check)

# 4. Run E2E tests (Playwright - ต้อง npm run dev ใน terminal อื่น)
npm run test:e2e
# ✅ ต้องผ่าน 11 tests (user workflows, mobile responsive, error handling)

# 5. Auto-fix lint issues
npm run lint:fix
# ✅ Fix formatting issues

# 6. Run build
npm run build
# ✅ ต้องสำเร็จ

# 6. ตรวจสอบ git status
git status
# ✅ ต้องเป็น "nothing to commit"

# 7. ตรวจสอบ git log
git log --oneline -5
# ✅ ต้องเห็น commit ใหม่ที่ push ไปแล้ว

# ✅ พร้อม! สร้าง PR ได้เลย
```

---

## 🎯 Key Takeaways

✅ **Git Workflow:**

- Feature branch สำหรับ feature ใหม่ ๆ
- Commit message ชัดเจน → ดูประวัติง่าย
- Push ขึ้น GitHub ก่อน PR

✅ **Build Automation:**

- npm scripts ทำให้ build process ระบบอัตโนมัติ
- eslint, jest ตรวจสอบ code quality
- ทดสอบ locally ก่อน push

✅ **Frontend:**

- HTML/CSS/JavaScript ใน public/ folder
- ทำงานได้โดยไม่ต้อง build (static files)
- Express serve ได้ผ่าน app.use(express.static('public'))

✅ **Testing Strategy:**

- Jest: Unit tests สำหรับ API logic
- Playwright: E2E tests สำหรับ frontend interaction
- ทดสอบทั้ง 2 แบบก่อนสร้าง PR

✅ **CI Pipeline:**

- GitHub Actions ทำให้ทุก PR ผ่าน test ก่อน
- ป้องกัน bad code เข้า production
- Workflow จะตรวจ lint, test, test:e2e อัตโนมัติ

✅ **Pull Request & Code Review:**

- PR แสดงให้เห็นว่าจะเปลี่ยนแปลงอะไร
- CI Pipeline ต้องผ่านก่อน merge
- Code review โดย team members

✅ **Deployment:**

- Auto-deploy เมื่อ merge ไป main
- Deploy ไป production ได้ทันใจ
- GitHub Actions + Vercel integration

✅ **Monitoring:**

- ตรวจสอบ deployed version ทันที
- ดู logs ถ้า error
- Rollback ได้ในไม่กี่วินาที

✅ **Complete Workflow:**

```
Local Branch → Git Push → PR → CI Checks ✅ (Lint + Unit + E2E) → Merge → Auto Deploy → Production ✅
```
