AI Code Review 2024-2026

Ollama + GitLab CI/CD

AI Code Review ด้วย Local LLM

ใช้ Ollama + CodeLlama/Llama 3 + GitLab CI/CD สำหรับ Automated Code Review ของ PHP และ Node.js

Ollama
GitLab CI/CD
PHP
Node.js
Python

เนื้อหาในบทความนี้

1 บทนำ: Code Review ด้วย AI คืออะไร?

AI-powered Code Review คือการใช้ Artificial Intelligence โดยเฉพาะ Large Language Models (LLMs) เพื่อวิเคราะห์ ตรวจสอบ และให้ feedback บน source code อัตโนมัติ โดยไม่ต้องให้มนุษย์ review ทุกบรรทัด

ปัญหาของ Manual Code Review

  • ใช้เวลามาก: Reviewer ต้องใช้เวลาหลายชั่วโมงสำหรับ PR ขนาดใหญ่
  • ขาดความสม่ำเสมอ: แต่ละ reviewer มีมาตรฐานและ focus ต่างกัน
  • พลาด security bugs: คน review อาจพลาด issues ที่ subtle หรือซับซ้อน
  • Bottleneck: Review ช้าทำให้ deployment ล่าช้า

วิวัฒนาการของ Code Review

👀

Manual Review

คน review code ทุกบรรทัดด้วยตัวเอง

ก่อนปี 2020
🤖

AI Review (Cloud)

GitHub Copilot, GitLab Duo - ส่ง code ไป cloud

2020-2023
🦙

Local LLM + CI/CD

Ollama + GitLab CI - Private, fast, local

2024-2026

ทำไม Local LLM (Ollama) เป็นทางเลือกที่น่าสนใจในปี 2024-2026?

  • Privacy & Security: Code ไม่ถูกส่งไปที่ cloud เหมาะสำหรับ banking, government, fintech
  • Speed: Local inference เร็วกว่า เพราะไม่ต้องออก internet
  • Cost: ไม่มีค่า API call per token, เหมาะสำหรับ large codebases
  • Customization: เลือก model ที่เหมาะสม (CodeLlama, Llama 3, Mistral)

2 แหล่งข้อมูลหลักจาก US Tech Sources

บทความนี้รวบรวมข้อมูลจากแหล่งข้อมูลแหล่งน่าเชื่อถือจากสหรัฐอเมริกา ปี 2024-2025 ดังนี้:

Ollama - Local LLM Runtime

Ollama คือ framework สำหรับ run LLMs แบบ local บน macOS, Linux, Windows รองรับหลาย models (Llama 3, Mistral, CodeLlama)

https://ollama.ai

GitLab CI/CD Pipeline Automation

GitLab CI มี pipeline orchestration ที่ powerful สามารถใช้ Docker containers เพื่อ run custom tools

GitLab CI Documentation

GitHub Copilot & AI Code Review

GitHub Copilot, GitLab Duo ใช้ LLMs (GPT-4, Claude) สำหรับ code review และ PR suggestions

GitHub Copilot

LLMs for Code Review Research

Research จาก papers: "LLMs for Automated Code Review", "CodeT5", "CodeBERT" - การใช้ models พิเศษสำหรับ code

Note: แหล่งข้อมูลทั้งหมดเป็น US-based tech sources ที่ได้รับการตรวจสอบและเชื่อถือได้

3 การประยุกต์ใช้ในประเทศไทย

E-commerce Companies

บริษัท E-commerce

ใช้ AI code review สำหรับ Laravel/PHP projects ลดเวลา review และค้นหา security issues

Use Case

SQL Injection detection, Authentication bugs, Laravel best practices

Government Systems

หน่วยงานราชการ

Local LLM เหมาะสำหรับ government เพราะ data security, ไม่ต้องส่ง code ไป cloud

Use Case

Compliance checks, Security review, Data protection compliance

Fintech Companies

บริษัท Financial Tech

AI review ก่อน merge production ลดความเสี่ยงของ financial transaction bugs

Use Case

Input validation, Race condition detection, Security patterns

Thai Startups

สตาร์ทอัพไทย

ลดรอบการ review และให้ developers focus บน features มากกว่า manual review

Use Case

Speed up development, Reduce review backlog, Quality assurance

4 สิ่งที่ต้องเตรียม

Software Requirements

  • GitLab.com หรือ GitLab Self-Hosted (with CI/CD enabled)

    ต้องเปิดใช้ GitLab Runner

  • Docker และ Docker Compose

    สำหรับ build containers

  • Ollama (Local LLM runtime)

    ดูวิธีติดตั้งใน Section 5

  • Python 3.9+ สำหรับ script automation

    pip install ollama requests

Hardware Requirements

Minimum (LLM 7B)

  • RAM: 8GB
  • Storage: 20GB (free space)
  • OS: macOS, Linux, Windows
  • CPU: Multi-core (4+ cores recommended)

Recommended (LLM 13B+)

  • RAM: 16GB+
  • GPU: NVIDIA GPU (optional, faster inference)
  • OS: Linux (best for production)
  • CPU: 8+ cores

LLM Models ที่รองรับ (ติดตั้งผ่าน Ollama)

CodeLlama 7B

สาย coding เฉพาะทาง

ollama pull codellama:7b

Llama 3 8B

General purpose, powerful

ollama pull llama3:8b

Mistral 7B

Fast, efficient, good quality

ollama pull mistral:7b

5 ขั้นตอนที่ 1: ติดตั้ง Ollama

Ollama คือ tool สำหรับ run LLMs แบบ local ง่ายและรวดเร็ว รองรับ macOS, Linux, Windows

1 ติดตั้ง Ollama

# macOS (Apple Silicon or Intel)
curl -fsSL https://ollama.ai/install.sh | sh

# Linux (Ubuntu, Debian, etc.)
curl -fsSL https://ollama.ai/install.sh | sh

# Windows (PowerShell as Administrator)
winget install Ollama.Ollama

# หรือ download จาก https://ollama.ai/download

Tip: หลังจากติดตั้ง คุณสามารถเปิด Ollama app แล้ว run ผ่าน command line

2 ติดตั้ง LLM Model

เลือก model ที่เหมาะสำหรับ code review:

# ติดตั้ง CodeLlama 7B (เหมาะสำหรับ coding)
ollama pull codellama:7b

# หรือ Llama 3 8B (General purpose, powerful)
ollama pull llama3:8b

# หรือ Mistral 7B (Fast และ efficient)
ollama pull mistral:7b

Recommendation: เริ่มด้วย codellama:7b สำหรับ code review

3 ทดสอบ Ollama

ทดสอบว่า Ollama และ model ทำงานได้:

# รัน model เพื่อ review code
ollama run codellama:7b "Review this PHP code for security issues:

<?php
$id = $_GET['id'];
$query = "SELECT * FROM users WHERE id = $id";
$result = $db->query($query);
?>"

Expected Output:

Based on the PHP code provided, I've identified several security issues:

1. SQL Injection Vulnerability:

The code constructs a SQL query by directly concatenating user input ($_GET['id']) into the query string. This is a classic SQL injection vulnerability.

Fix:

Use prepared statements with PDO:

```php
$stmt = $db->prepare("SELECT * FROM users WHERE id = :id");
$stmt->bindParam(':id', $id, PDO::PARAM_INT);
$stmt->execute();
```

4 ตรวจสอบ Ollama Server

Ollama จะเริ่ม server ที่ http://localhost:11434 โดยอัตโนมัติ หลังจากติดตั้ง

# ทดสอบ Ollama API
curl http://localhost:11434/api/generate -d '{
"model": "codellama:7b",
"prompt": "Hello"
}'

Success: ถ้าได้ response แสดงว่า Ollama server ทำงานได้ถูกต้อง

6 ขั้นตอนที่ 2: สร้าง GitLab CI Pipeline สำหรับ Code Review

สถาปัตยกรรม AI Code Review

Developer Push Code 👨‍💻 GitLab CI Trigger Pipeline Run Docker Container 🦊 Docker Python Script Fetch Code Send to Ollama Parse Response 🐍 Ollama Local LLM CodeLlama Review Code Generate 🦙 Merge Request Post Comments Show Issues Developer Reviews 📝 Legend: Ollama GitLab CI LLM MR = Auto Code Review Pipeline

เมื่อ developer push code, GitLab CI จะ:

  1. Trigger Pipeline - เมื่อ MR ถูกสร้างหรือ code ถูก push
  2. Run Docker Container - GitLab Runner จะ spin up Docker container พร้อม Python script
  3. Fetch Code - Script จะ fetch code จาก GitLab API
  4. Send to Ollama - Script ส่ง code ไปให้ Ollama review
  5. Parse Response - Script แปลง AI response เป็น format ที่ GitLab รองรับ
  6. Post Comments - Script โพสต์ comments บน MR

.gitlab-ci.yml Configuration

stages:
- code-review

# AI Code Review Stage
ai-code-review:
stage: code-review
image: python:3.11
services:
- docker:dind # Docker-in-Docker
variables:
OLLAMA_BASE_URL: "http://host.docker.internal:11434" # หรือ host.docker.internal
script:
# Install dependencies
- pip install ollama requests

# Run code review script
- python scripts/code_review.py
artifacts:
reports:
codequality: gl-code-quality-report.json # GitLab Code Quality report
only:
- merge_requests # Run ก็ต่อเมื่อมี MR เท่านั้น
allow_failure: true # ไม่ให้ fail ถ้า AI review ไม่สำเร็จ

Important: host.docker.internal ใช้สำหรับเชื่อมต่อจาก Docker container ไป host machine (ที่ Ollama รันอยู่)

ติดตั้ง GitLab Runner (ถ้าจำเป็น)

ถ้าใช้ GitLab.com จะมี shared runners ให้ใช้ แต่ถ้าต้องการ control เอง:

# Register GitLab Runner
curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh | sudo bash
sudo apt-get install gitlab-runner

# Register runner
sudo gitlab-runner register

# ใส่ GitLab instance URL และ registration token

Note: สำหรับ GitLab.com สามารถใช้ shared runners ได้เลย โดยไม่ต้องติดตั้ง runner เอง

7 ขั้นตอนที่ 3: Python Script สำหรับ AI Code Review

Python script นี้จะทำงานใน GitLab CI, fetch code จาก GitLab API, ส่งให้ Ollama review, และโพสต์ comments บน MR

scripts/code_review.py

#!/usr/bin/env python3
""" AI Code Review Script for GitLab CI/CD Uses Ollama Local LLM to review code changes """ import os
import json
import requests
from urllib.parse import urljoin # Configuration OLLAMA_BASE_URL = os.getenv('OLLAMA_BASE_URL', 'http://host.docker.internal:11434') OLLAMA_MODEL = os.getenv('OLLAMA_MODEL', 'codellama:7b') # GitLab Configuration GITLAB_TOKEN = os.getenv('GITLAB_TOKEN') # จาก CI/CD Variables GITLAB_API_URL = os.getenv('CI_API_V4_URL', 'https://gitlab.com/api/v4') PROJECT_ID = os.getenv('CI_PROJECT_ID') MR_IID = os.getenv('CI_MERGE_REQUEST_IID') MR_SOURCE_BRANCH = os.getenv('CI_MERGE_REQUEST_SOURCE_BRANCH') def get_merge_request_diff(): """Get code diff from merge request""" url = f"{GITLAB_API_URL}/projects/{PROJECT_ID}/merge_requests/{MR_IID}/diff" headers = {'PRIVATE-TOKEN': GITLAB_TOKEN} response = requests.get(url, headers=headers) response.raise_for_status() return response.json() def send_to_ollama(code_diff, file_path): """Send code diff to Ollama for review""" url = urljoin(OLLAMA_BASE_URL, '/api/generate') # Build prompt for code review prompt = f"""Review this code diff for security issues, bugs, and best practices: File: {file_path} Diff: {code_diff} Focus on: 1. Security vulnerabilities (SQL injection, XSS, etc.) 2. Code quality issues 3. Best practices 4. Potential bugs Provide your response in JSON format: {{ "issues": [ {{ "severity": "high|medium|low", "line": line_number, "message": "Description of the issue", "suggestion": "Suggested fix" }} ], "summary": "Overall assessment" }}""" payload = { "model": OLLAMA_MODEL, "prompt": prompt, "stream": False, "format": "json" # Try to get JSON response } try: response = requests.post(url, json=payload, timeout=60) response.raise_for_status() return response.json() except requests.exceptions.RequestException as e: print(f"Error calling Ollama: {e}") return None def parse_ai_response(response): """Parse AI response into structured format""" if not response or 'response' not in response: return [] ai_output = response['response'] # Try to parse JSON from AI response try: # AI might output JSON directly or wrapped in text start = ai_output.find('{') end = ai_output.rfind('}') + 1 if start != -1 and end > start: json_str = ai_output[start:end] parsed = json.loads(json_str) return parsed.get('issues', []) except json.JSONDecodeError: pass # Fallback: parse manually issues = [] lines = ai_output.split('\n') for line in lines: if 'security' in line.lower() or 'vulnerability' in line.lower(): issues.append({ 'severity': 'high', 'line': 'unknown', 'message': line.strip(), 'suggestion': '' }) return issues def post_merge_request_comment(issues): """Post code review comments to merge request""" if not issues: print("No issues found by AI review.") return url = f"{GITLAB_API_URL}/projects/{PROJECT_ID}/merge_requests/{MR_IID}/notes" headers = {'PRIVATE-TOKEN': GITLAB_TOKEN} # Build comment body comment = "## 🔍 AI Code Review Results\n\n" severity_emoji = { 'high': '🔴', 'medium': '🟡', 'low': '🟢' } for issue in issues: severity = issue.get('severity', 'medium') emoji = severity_emoji.get(severity, '⚪') message = issue.get('message', 'No message') line = issue.get('line', 'N/A') suggestion = issue.get('suggestion', '') comment += f"{emoji} **{severity.upper()}** (Line {line}): {message}\n" if suggestion: comment += f" 💡 *Suggestion:* {suggestion}\n" comment += "\n" comment += "\n---\n" comment += "*Powered by Ollama (Local LLM)*" payload = {'body': comment} try: response = requests.post(url, headers=headers, data=payload) response.raise_for_status() print("Code review comment posted successfully!") except requests.exceptions.RequestException as e: print(f"Error posting comment: {e}") def generate_code_quality_report(issues): """Generate GitLab Code Quality report""" report = [] for issue in issues: report_item = { "type": issue.get('severity', 'medium'), "check_name": "AI Code Review", "description": issue.get('message', 'No message'), "content": issue.get('suggestion', ''), "severity": issue.get('severity', 'medium'), "location": { "path": issue.get('file_path', 'unknown'), "lines": { "begin": int(issue.get('line', 0)) } } } report.append(report_item) # Save report with open('gl-code-quality-report.json', 'w') as f: json.dump(report, f, indent=2) print(f"Generated code quality report with {len(issues)} issues") def main(): print("Starting AI Code Review...") print(f"Ollama URL: {OLLAMA_BASE_URL}") print(f"Model: {OLLAMA_MODEL}") # Get merge request diff diffs = get_merge_request_diff() print(f"Found {len(diffs)} changed files") all_issues = [] # Review each changed file for diff in diffs: file_path = diff.get('new_path', 'unknown') diff_text = diff.get('diff', '') if not diff_text: continue print(f"Reviewing {file_path}...") # Send to Ollama ai_response = send_to_ollama(diff_text, file_path) # Parse AI response issues = parse_ai_response(ai_response) # Add file path to issues for issue in issues: issue['file_path'] = file_path all_issues.extend(issues) # Post comments to MR if all_issues: print(f"Found {len(all_issues)} issues total") post_merge_request_comment(all_issues) generate_code_quality_report(all_issues) else: print("No issues found!") print("AI Code Review completed!") if __name__ == '__main__': main()

การตั้งค่า Environment Variables ใน GitLab CI

  • OLLAMA_BASE_URL - URL ของ Ollama server
  • OLLAMA_MODEL - Model ที่ต้องการใช้ (codellama:7b)
  • GITLAB_TOKEN - GitLab Personal Access Token (with api scope)

สร้าง GitLab Personal Access Token

  1. 1 ไปที่ Settings > Access Tokens ใน GitLab
  2. 2 คลิก Add new token
  3. 3 เลือก scopes: api (เป็นอย่างน้อย)
  4. 4 Copy token และเพิ่มเป็น CI/CD Variable ใน project

8 ตัวอย่าง PHP

ตัวอย่าง PHP code พร้อมการ review จาก AI และแนวทางการแก้ไข:

ตัวอย่าง 1: SQL Injection Vulnerability

❌ Code ที่มีปัญหา

<?php
function getUserData($userId) { $db = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass'); // ❌ SQL Injection vulnerability! $query = "SELECT * FROM users WHERE id = " . $userId; $result = $db->query($query); return $result->fetchAll(PDO::FETCH_ASSOC); } // Usage $userId = $_GET['id']; // User input $userData = getUserData($userId); print_r($userData); ?>

✅ Code ที่แก้ไขแล้ว

<?php
function getUserData(PDO $db, $userId) { try { // ✅ Use prepared statements $stmt = $db->prepare("SELECT * FROM users WHERE id = :id"); $stmt->bindParam(':id', $userId, PDO::PARAM_INT); $stmt->execute(); return $stmt->fetchAll(PDO::FETCH_ASSOC); } catch (PDOException $e) { error_log("Database error: " . $e->getMessage()); return false; } } // Usage $db = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass'); $userId = filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT); if ($userId === false) { die("Invalid user ID"); } $userData = getUserData($db, $userId); print_r($userData); ?>

AI Code Review Feedback

🔴 HIGH SEVERITY: SQL Injection vulnerability detected.

The code constructs SQL query by directly concatenating user input ($userId). Attacker can inject malicious SQL.

💡 Suggestion:

  • Use PDO prepared statements with parameterized queries
  • Validate input type (ensure $userId is integer)
  • Add error handling with try-catch

ตัวอย่าง 2: Missing Input Validation & XSS

❌ Code ที่มีปัญหา

<?php
// Process user registration
$name = $_POST['name'];
$email = $_POST['email'];
$password = $_POST['password'];

// ❌ No validation!
// ❌ No XSS protection!
if (strlen($password) < 6) {
echo "Password too short";
exit;
}

// Save to database
$query = "INSERT INTO users (name, email, password) VALUES (?, ?, ?)";
$stmt = $db->prepare($query);
$stmt->execute([$name, $email, password_hash($password, PASSWORD_DEFAULT)]);

// ❌ XSS vulnerability when displaying
echo "Welcome, " . $name . "!";
?>

✅ Code ที่แก้ไขแล้ว

<?php
// ✅ Validate and sanitize input
function validateInput($data) {
return htmlspecialchars(strip_tags(trim($data)), ENT_QUOTES, 'UTF-8');
}

function validateEmail($email) {
return filter_var($email, FILTER_VALIDATE_EMAIL);
}

// Process user registration
$name = validateInput($_POST['name']);
$email = validateEmail($_POST['email']);
$password = $_POST['password'];

// ✅ Enhanced validation
if (empty($name) || empty($email) || empty($password)) {
throw new InvalidArgumentException("All fields are required");
}

if (strlen($password) < 8) {
throw new InvalidArgumentException("Password must be at least 8 characters");
}

if ($email === false) {
throw new InvalidArgumentException("Invalid email address");
}

// Save to database
$stmt = $db->prepare("INSERT INTO users (name, email, password) VALUES (?, ?, ?)");
$stmt->execute([$name, $email, password_hash($password, PASSWORD_DEFAULT)]);

// ✅ XSS protected output
echo "Welcome, " . htmlspecialchars($name, ENT_QUOTES, 'UTF-8') . "!";
?>

AI Code Review Feedback

🟡 MEDIUM SEVERITY: Missing input validation.

User inputs ($_POST) are not validated or sanitized, leading to potential security issues.

🔴 HIGH SEVERITY: XSS vulnerability.

Echoing user input ($name) directly to HTML allows attackers to inject malicious scripts.

💡 Suggestions:

  • Validate email format with filter_var()
  • Sanitize HTML output with htmlspecialchars()
  • Use prepared statements for database (already done)
  • Implement proper error handling

ตัวอย่าง 3: Laravel Best Practices

❌ Anti-Pattern

// routes/web.php
Route::get('/users', function () {
// ❌ Business logic in route
$users = DB::table('users')
->where('active', true)
->orderBy('created_at', 'desc')
->get();

return response()->json($users);
});

// app/Http/Controllers/UserController.php
class UserController extends Controller {
// ❌ No type hints
public function store(Request $request) {
$data = $request->all();

// ❌ Mass assignment vulnerability
$user = User::create($data);

return response()->json($user, 201);
}
}

✅ Best Practice

// routes/web.php
Route::apiResource('users', UserController::class);

// app/Http/Controllers/UserController.php
class UserController extends Controller {
// ✅ Type hints
public function index(ShowUsersRequest $request): JsonResponse {
$users = User::active()
->latest()
->paginate($request->get('per_page', 15));

return UserResource::collection($users);
}

// ✅ Form Request validation
public function store(StoreUserRequest $request): JsonResponse {
$validated = $request->validated();

// ✅ Safe mass assignment
$user = User::create($validated);

return new UserResource($user);
}
}

AI Code Review Feedback

🟡 LOW SEVERITY: Business logic in routes.

Routes should be thin. Move database queries to Controllers or Services.

🟡 MEDIUM SEVERITY: Mass assignment vulnerability.

Using $request->all() without validation can expose sensitive fields.

💡 Suggestions:

  • Use Form Request classes for validation (StoreUserRequest)
  • Define $fillable or $guarded in User model
  • Use API Resources for JSON response formatting
  • Add type hints for better IDE support

9 ตัวอย่าง Node.js

ตัวอย่าง Node.js code พร้อมการ review จาก AI และแนวทางการแก้ไข:

ตัวอย่าง 1: Express.js Security Issues

❌ Code ที่มีปัญหา

const express = require('express');
const app = express();
const db = require('./db');

// ❌ No helmet security headers
app.use(express.json());

app.get('/api/users/:id', async (req, res) => {
const userId = req.params.id;

// ❌ SQL Injection!
const query = `SELECT * FROM users WHERE id = ${userId}`;
const result = await db.query(query);

// ❌ No error handling
res.json(result.rows);
});

app.post('/api/users', async (req, res) => {
const { name, email } = req.body;

// ❌ No input validation
const query = `INSERT INTO users (name, email) VALUES ('${name}', '${email}')`;
await db.query(query);

res.status(201).json({ message: 'Created' });
});

app.listen(3000);

✅ Code ที่แก้ไขแล้ว

const express = require('express');
const helmet = require('helmet');
const { body, param, validationResult } = require('express-validator');
const app = express();
const db = require('./db');

// ✅ Security headers
app.use(helmet());
app.use(express.json());

app.get('/api/users/:id',
[param('id').isInt()],
async (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}

const userId = parseInt(req.params.id, 10);

try {
// ✅ Parameterized query
const result = await db.query(
'SELECT id, name, email FROM users WHERE id = $1',
[userId]
);

if (result.rows.length === 0) {
return res.status(404).json({ error: 'User not found' });
}

res.json(result.rows[0]);
} catch (error) {
console.error('Database error:', error);
res.status(500).json({ error: 'Internal server error' });
}
}
);

app.post('/api/users',
[
body('name').trim().notEmpty(),
body('email').isEmail().normalizeEmail()
],
async (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}

const { name, email } = req.body;

try {
const result = await db.query(
'INSERT INTO users (name, email) VALUES ($1, $2) RETURNING *',
[name, email]
);

res.status(201).json(result.rows[0]);
} catch (error) {
console.error('Database error:', error);
res.status(500).json({ error: 'Internal server error' });
}
}
);

app.listen(3000, () => console.log('Server running'));

AI Code Review Feedback

🔴 HIGH SEVERITY: SQL Injection vulnerabilities.

Both GET and POST routes construct SQL queries with user input concatenation.

🟡 MEDIUM SEVERITY: Missing security headers.

No Helmet middleware or CORS configuration, exposing to various attacks.

💡 Suggestions:

  • Use parameterized queries ($1, $2) with pg or mysql2
  • Add Helmet middleware for security headers
  • Implement input validation with express-validator
  • Add proper error handling with try-catch
  • Consider using an ORM like Sequelize or TypeORM

ตัวอย่าง 2: TypeScript Best Practices

❌ Anti-Pattern

// ❌ No types
async function getUserData(id) {
const response = await fetch(`/api/users/${id}`);
const data = await response.json();
return data;
}

// ❌ Callback hell
function processUsers(users, callback) {
const results = [];
users.forEach(user => {
getUserData(user.id).then(data => {
results.push(data);
if (results.length === users.length) {
callback(results);
}
});
});
}

// ❌ No error handling
processUsers(userList, data => {
console.log(data);
});

✅ Best Practice

// ✅ Type definitions
interface User {
id: number;
name: string;
email: string;
}

async function getUserData(id: number): Promise<User> {
const response = await fetch(`/api/users/${id}`);

if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}

const data: User = await response.json();
return data;
}

// ✅ Async/await with Promise.all
async function processUsers(users: User[]): Promise<User[]> {
try {
const userPromises = users.map(user =>
getUserData(user.id)
);

const results = await Promise.all(userPromises);
return results;
} catch (error) {
console.error('Error processing users:', error);
throw error; // Re-throw for caller to handle
}
}

// ✅ Proper error handling
(async () => {
try {
const processedUsers = await processUsers(userList);
console.log('Processed:', processedUsers);
} catch (error) {
console.error('Failed:', error);
// Show error to user
}
})();

AI Code Review Feedback

🟡 LOW SEVERITY: Missing TypeScript types.

Without type definitions, code is harder to maintain and prone to runtime errors.

🟡 MEDIUM SEVERITY: Callback hell pattern.

Using nested callbacks instead of async/await or Promises makes code hard to read and error-prone.

🔴 HIGH SEVERITY: No error handling.

Async operations without try-catch or .catch() will silently fail.

💡 Suggestions:

  • Define TypeScript interfaces for all data structures
  • Use async/await instead of callbacks
  • Use Promise.all() for parallel async operations
  • Add proper error handling with try-catch
  • Consider using a logging library like winston or pino

10 Advanced Features

Multi-File Review

Review หลายไฟล์พร้อมกัน และสรุป issues ระหว่างไฟล์:

# Review multiple files
issues = []
for file in changed_files:
issues += review_file(file)

# Track cross-file issues
summary = analyze_cross_file_relationships(issues)

Custom Review Rules

กำหนด custom rules สำหรับ PHP/Node.js standards:

# Custom PHP rules
rules = [
"PSR-12 coding standards",
"Laravel best practices",
"Company-specific patterns"
]

# Custom Node.js rules
rules = [
"TypeScript strict mode",
"ESLint configuration",
"Security guidelines"
]

Performance Optimization

ปรับปรุง performance:

  • • Cache LLM responses (Redis/File)
  • • Batch processing (parallel reviews)
  • • Use smaller models for quick checks
  • • Limit review to changed files only

Additional Integrations

เชื่อมต่อกับ tools อื่น:

  • • SonarQube (static analysis)
  • • Slack/Discord (notifications)
  • • Jira (bug tracking)
  • • GitHub/GitLab (PR integration)

11 Troubleshooting

ปัญหา: Ollama connection timeout

Docker container ไม่สามารถเชื่อมต่อกับ Ollama server ได้

Solution:

  • • ใช้ host.docker.internal แทน localhost
  • • ตรวจสอบว่า Ollama server กำลังรันอยู่: ollama list
  • • Restart Ollama server: ollama serve

ปัญหา: LLM out of memory

Model 13B+ ใช้ memory เยอะเกินไป

Solution:

  • • ใช้ model เล็กกว่า: codellama:7b แทน codellama:13b
  • • เพิ่ม RAM หรือใช้ GPU
  • • ตั้งค่า Ollama ให้ใช้ memory น้อยลง

ปัญหา: GitLab CI resource limits

Pipeline timeout หรือ out of memory

Solution:

  • • ตั้งค่า timeout: timeout: 5m ใน .gitlab-ci.yml
  • • ใช้ self-hosted runner พร้อม resource เพิ่ม
  • • Split review หลาย stages

ปัญหา: AI response quality poor

AI ให้ feedback ที่ไม่เป็นประโยชน์หรือเข้าใจผิด

Solution:

  • • Tune prompt เพื่อให้เฉพาะเจาะจงมากขึ้น
  • • ใช้ model ที่เหมาะสม: codellama:7b สำหรับ code
  • • เพิ่ม context เช่น language, framework version
  • • Fine-tune model สำหรับ codebase ของคุณ

12 สรุปและขั้นตอนถัดไป

สรุปสิ่งที่ได้เรียนรู้

ข้อดีของ Ollama + GitLab CI

  • ✅ Privacy: Code ไม่ถูกส่งไป cloud
  • ✅ Speed: Local inference เร็วกว่า
  • ✅ Cost: ไม่มี API costs
  • ✅ Customization: เลือก model ได้

สิ่งที่ได้เรียนรู้

  • ✅ ติดตั้งและตั้งค่า Ollama
  • ✅ สร้าง GitLab CI Pipeline
  • ✅ เขียน Python script สำหรับ AI review
  • ✅ Apply กับ PHP และ Node.js

เมื่อไหร่ควรใช้ AI vs Manual Code Review

🤖 ใช้ AI Review เมื่อ:

  • • PR ขนาดเล็กถึงกลาง (< 500 lines)
  • • ตรวจสอบ security issues ทั่วไป
  • • ตรวจสอบ best practices ของ language
  • • เพิ่มความสม่ำเสมอ

👥 ใช้ Manual Review เมื่อ:

  • • PR ขนาดใหญ่หรือ complex
  • • Architecture หรือ design decisions
  • • Business logic ที่ซับซ้อน
  • • Performance considerations

ข้อจำกัดของ AI Code Review

  • Quality depends on model: CodeLlama 7B อาจไม่ถูกต้องสำหรับ complex code
  • Resource usage: LLMs ใช้ memory และ CPU เยอะ
  • False positives: AI อาจแจ้งว่าเป็น issue แต่จริงๆ ไม่ใช่
  • No context awareness: AI ไม่เข้าใจ codebase ของคุณทั้งหมด

ขั้นตอนถัดไป (Next Steps)

1

ทดลองกับ Production Code

Apply AI review กับ MRs จริงใน project ของคุณ

2

ปรับแต่ง Prompts

Tune prompts ให้เฉพาะเจาะจงกับ codebase ของคุณ

3

Monitor Performance

ติดตาม review time, quality, และ developer feedback

4

Learn AI/ML for DevOps

ศึกษา fundamentals ของ LLMs และ integration patterns