docs(GOO-33): comprehensive documentation sprint
Create/update all Sprint 6 documentation: - CHANGELOG.md: document GOO-33 and recent audit findings - CONTRIBUTING.md: add branching, PR, commit conventions - docs/ci-cd.md: GitHub Actions pipeline documentation - docs/onboarding.md: developer setup & onboarding guide - docs/mcp-servers.md: MCP servers API documentation - docs/PROJECT_TRACKER.md: mark GOO-33 as in_progress - docs/QA_TRACKER.md: test status and verification plans Curate audit reports (reduce ~103 → 12 canonical files): - Keep canonical audit reports with descriptive index - Archive obsolete/duplicate audit exploration files Acceptance Criteria: - [x] QA_TRACKER.md exists with current test status - [x] CHANGELOG.md updated to today - [x] PROJECT_TRACKER.md reflects current sprint status - [x] CI/CD pipeline documented - [x] CONTRIBUTING.md has branching, PR, commit conventions - [x] docs/audits/ reduced to canonical reports Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
355
docs/ci-cd.md
Normal file
355
docs/ci-cd.md
Normal file
@@ -0,0 +1,355 @@
|
||||
# CI/CD Pipeline
|
||||
|
||||
GoodGo Platform sử dụng **GitHub Actions** để tự động hóa build, test, và deployment. Pipeline tuân theo quy tắc _"build once, deploy anywhere"_ — một lần build, deploy tới nhiều môi trường.
|
||||
|
||||
## Pipeline Overview
|
||||
|
||||
Pipeline bao gồm **4 bước chính**:
|
||||
|
||||
```
|
||||
1. Lint (ESLint)
|
||||
↓
|
||||
2. TypeScript Check (tsc)
|
||||
↓
|
||||
3. Unit Tests (Jest/Vitest)
|
||||
↓
|
||||
4. Build (Turborepo)
|
||||
```
|
||||
|
||||
Mỗi bước phải **pass** trước khi tiếp tục bước tiếp theo. Nếu bất kỳ bước nào thất bại, workflow dừng ngay.
|
||||
|
||||
---
|
||||
|
||||
## Trigger Events
|
||||
|
||||
Pipeline **tự động chạy** khi:
|
||||
|
||||
| Event | Branches | Hành động |
|
||||
|-------|----------|----------|
|
||||
| **Push** | `main`, `master`, `develop` | Chạy đầy đủ pipeline (lint → typecheck → test → build) |
|
||||
| **Pull Request** | Bất kỳ branch | Chạy đầy đủ pipeline trước khi merge |
|
||||
| **Manual** (workflow_dispatch) | Bất kỳ branch | Cho phép chạy thủ công từ GitHub UI |
|
||||
|
||||
---
|
||||
|
||||
## Step 1: Lint (ESLint)
|
||||
|
||||
**File:** `.github/workflows/ci.yml` → job `lint`
|
||||
|
||||
**Mục đích:** Kiểm tra style code, conventions, và phát hiện anti-patterns.
|
||||
|
||||
**Command:**
|
||||
```bash
|
||||
pnpm lint
|
||||
```
|
||||
|
||||
**Chi tiết:**
|
||||
- ESLint config: `.eslintrc.json` (root)
|
||||
- Rules: import order, naming, unused variables, etc.
|
||||
- Auto-fixable issues: `pnpm lint --fix`
|
||||
- **Non-auto-fixable issues:** workflow fails, developer phải fix thủ công
|
||||
|
||||
**Quy tắc chính:**
|
||||
- ✅ Imports ordered: `external` → `internal` (path alias) → `relative`
|
||||
- ✅ Không dùng `any` type (TypeScript strict)
|
||||
- ✅ Không có unused variables hoặc imports
|
||||
- ❌ Không mix `require()` và `import` (dùng `import` for ES6)
|
||||
|
||||
**Thời gian:** ~30 giây
|
||||
|
||||
---
|
||||
|
||||
## Step 2: TypeScript Check (tsc)
|
||||
|
||||
**File:** `.github/workflows/ci.yml` → job `typecheck`
|
||||
|
||||
**Mục đích:** Kiểm tra type safety toàn codebase mà không compile.
|
||||
|
||||
**Command:**
|
||||
```bash
|
||||
pnpm typecheck
|
||||
```
|
||||
|
||||
**Chi tiết:**
|
||||
- Chạy `tsc --noEmit` trên mỗi package (API, Web, etc.)
|
||||
- **TypeScript config:** `tsconfig.json` (per-package)
|
||||
- **Strict mode:** `strict: true`
|
||||
- Path aliases: `@modules/*` (API), `@/*` (Web)
|
||||
|
||||
**Quy tắc chính:**
|
||||
- ✅ Mọi function phải có explicit return types
|
||||
- ✅ Mọi parameter phải có type annotation (strict)
|
||||
- ✅ Generic types phải đủ specificity (không `Promise<any>`)
|
||||
- ❌ Không dùng `any` ngoại lệ (có comment `@ts-expect-error`)
|
||||
|
||||
**Thời gian:** ~45 giây
|
||||
|
||||
---
|
||||
|
||||
## Step 3: Unit Tests (Jest/Vitest)
|
||||
|
||||
**File:** `.github/workflows/ci.yml` → job `test`
|
||||
|
||||
**Mục đích:** Chạy suite kiểm thử đơn vị, đảm bảo logic ngữ nghĩa đúng.
|
||||
|
||||
**Command:**
|
||||
```bash
|
||||
pnpm test
|
||||
```
|
||||
|
||||
**Chi tiết:**
|
||||
- **API (NestJS):** Jest + `@nestjs/testing`
|
||||
- **Web (Next.js):** Vitest + `@testing-library/react`
|
||||
- Coverage threshold: API ≥ 60%, Web ≥ 50%
|
||||
- Snapshot tests: must commit `.snap` file changes
|
||||
|
||||
**Test Locations:**
|
||||
| Package | Pattern | Runner |
|
||||
|---------|---------|--------|
|
||||
| API | `apps/api/src/**/*.spec.ts` | Jest |
|
||||
| Web | `apps/web/src/**/*.spec.ts` | Vitest |
|
||||
| Libs | `libs/**/*.spec.ts` | Jest (libs) / Vitest (web libs) |
|
||||
|
||||
**Quy tắc viết Test:**
|
||||
- ✅ Test AAA pattern: **A**rrange → **A**ct → **A**ssert
|
||||
- ✅ Describe blocks: `[Unit/Integration] ClassName.method()`
|
||||
- ✅ Mock external dependencies (database, HTTP, etc.)
|
||||
- ✅ Test happy path + error cases + edge cases
|
||||
- ❌ Không mock internal logic
|
||||
- ❌ Không snapshot-test component trees (snapshot brittle)
|
||||
|
||||
**Thời gian:** ~60 giây (API), ~30 giây (Web)
|
||||
|
||||
**Xem coverage:**
|
||||
```bash
|
||||
pnpm test -- --coverage
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Step 4: Build (Turborepo)
|
||||
|
||||
**File:** `.github/workflows/ci.yml` → job `build`
|
||||
|
||||
**Mục đích:** Production build tất cả packages, detect breaking changes.
|
||||
|
||||
**Command:**
|
||||
```bash
|
||||
pnpm build
|
||||
```
|
||||
|
||||
**Chi tiết:**
|
||||
- **Turborepo caching:** Bỏ qua build lại nếu code không thay đổi
|
||||
- **Targets:** `apps/api`, `apps/web`, `libs/ai-services`, `libs/mcp-servers`
|
||||
- **Output:** `dist/` per-package
|
||||
- Vô hiệu hóa cache: `--no-cache`
|
||||
|
||||
**Per-Package Build:**
|
||||
| Package | Command | Output | Notes |
|
||||
|---------|---------|--------|-------|
|
||||
| API | `nest build` | `dist/` | Production NestJS app |
|
||||
| Web | `next build` | `.next/` | Optimized Next.js app |
|
||||
| AI Services | `docker build` | `Dockerfile` | Python FastAPI image (không build trong CI, chỉ lint + test) |
|
||||
| MCP Servers | Bundled vào API | N/A | TypeScript → JS |
|
||||
|
||||
**Thời gian:** ~120 giây (with Turborepo cache)
|
||||
|
||||
---
|
||||
|
||||
## Error Handling & Retry
|
||||
|
||||
### CI Pipeline Retry Policy
|
||||
|
||||
| Failure | Action | Retry |
|
||||
|---------|--------|-------|
|
||||
| Network timeout | Auto-retry (3x) | Yes, within same run |
|
||||
| Out of disk space | Fail + notify | Manual re-run |
|
||||
| Flaky test | Fail (capture logs) | Manual re-run w/ `--seed` |
|
||||
| Git checkout error | Fail + notify | Manual re-run |
|
||||
|
||||
### Local Debugging
|
||||
|
||||
```bash
|
||||
# Replicate exact CI environment locally
|
||||
docker pull ghcr.io/actions/runner:latest
|
||||
|
||||
# Or run pnpm commands locally
|
||||
pnpm install
|
||||
pnpm lint --debug
|
||||
pnpm typecheck
|
||||
pnpm test -- --bail # stop on first failure
|
||||
pnpm build
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## GitHub Status Checks
|
||||
|
||||
Pull requests require **all 4 checks to pass** before merging:
|
||||
|
||||
```
|
||||
✅ lint
|
||||
✅ typecheck
|
||||
✅ test
|
||||
✅ build
|
||||
```
|
||||
|
||||
**Branch Protection Rules:**
|
||||
|
||||
- ✅ Require PR reviews: 1 approval minimum (code owner)
|
||||
- ✅ Dismiss stale PR approvals
|
||||
- ✅ Require status checks to pass
|
||||
- ✅ Require branches to be up to date before merging
|
||||
- ✅ Restrict who can push to matching branches (admin only)
|
||||
|
||||
---
|
||||
|
||||
## Secrets & Environment Variables
|
||||
|
||||
### CI-Only Secrets (`.github/secrets/`)
|
||||
|
||||
| Secret | Used In | Purpose |
|
||||
|--------|---------|---------|
|
||||
| `DATABASE_URL_TEST` | Step 3 (test) | Test database (PostgreSQL) |
|
||||
| `REDIS_URL_TEST` | Step 3 (test) | Test Redis cache |
|
||||
| `OPENAI_API_KEY` | Step 3 (test) | Claude API (if needed) |
|
||||
|
||||
### Build-Time Env (`.env.ci`)
|
||||
|
||||
```bash
|
||||
# .env.ci (git-tracked)
|
||||
NODE_ENV=test
|
||||
LOG_LEVEL=warn
|
||||
DATABASE_POOL_MIN=2
|
||||
DATABASE_POOL_MAX=5
|
||||
REDIS_TIMEOUT=5000
|
||||
```
|
||||
|
||||
### Deploy-Only Secrets (`.github/secrets/` for Production)
|
||||
|
||||
| Secret | Deploy Target | Used In |
|
||||
|--------|---------------|---------|
|
||||
| `DOCKER_REGISTRY_TOKEN` | Docker Hub / GitHub Container Registry | Push image after build success |
|
||||
| `DEPLOY_SSH_KEY` | Production VPS | SSH into server + restart service |
|
||||
| `SENTRY_AUTH_TOKEN` | Sentry.io | Release tracking |
|
||||
|
||||
---
|
||||
|
||||
## Deployment Strategy
|
||||
|
||||
### Auto-Deploy Trigger
|
||||
|
||||
Push to `main` → All checks pass → Auto-deploy to **Staging**
|
||||
|
||||
```
|
||||
main branch
|
||||
↓ (all checks pass)
|
||||
↓
|
||||
Auto-build Docker image
|
||||
↓
|
||||
Push to GitHub Container Registry (ghcr.io)
|
||||
↓
|
||||
SSH into staging server
|
||||
↓
|
||||
docker pull + docker-compose up -d
|
||||
↓
|
||||
Health checks (/health/ready) → smoke tests
|
||||
↓
|
||||
✅ Deployed to staging
|
||||
```
|
||||
|
||||
### Manual Deploy to Production
|
||||
|
||||
**Only via GitHub Release tag:**
|
||||
|
||||
```bash
|
||||
git tag -a v1.5.0 -m "Release 1.5.0"
|
||||
git push origin v1.5.0
|
||||
```
|
||||
|
||||
Tag push triggers **manual approval** in GitHub → Deploy to Production.
|
||||
|
||||
---
|
||||
|
||||
## Monitoring & Logs
|
||||
|
||||
### CI Logs
|
||||
|
||||
- **GitHub:** https://github.com/hongochai10/goodgo-bds-platform-ai/actions
|
||||
- **Per-job logs:** Click workflow run → view step output
|
||||
- **Artifact download:** Logs, coverage reports, etc.
|
||||
|
||||
### Production Deployment Logs
|
||||
|
||||
```bash
|
||||
# SSH into production server
|
||||
ssh deploy@prod.goodgo.app
|
||||
|
||||
# View Docker Compose logs
|
||||
docker-compose -f docker-compose.prod.yml logs -f
|
||||
```
|
||||
|
||||
### Error Alerts
|
||||
|
||||
- **Slack:** Integration notify `#deployments` on failure
|
||||
- **Email:** GitHub notifications to team@goodgo.app
|
||||
- **Sentry:** Auto-capture runtime errors after deploy
|
||||
|
||||
---
|
||||
|
||||
## Performance Tips
|
||||
|
||||
### Faster Local Development
|
||||
|
||||
```bash
|
||||
# Lint & typecheck only (skip test & build for quick feedback)
|
||||
pnpm lint && pnpm typecheck
|
||||
|
||||
# Test only changed files
|
||||
pnpm test -- --onlyChanged
|
||||
|
||||
# Build only specific package
|
||||
pnpm --filter api build
|
||||
```
|
||||
|
||||
### Faster CI (reduce time)
|
||||
|
||||
1. **Cache optimization:** Turborepo already caches built packages
|
||||
2. **Parallel jobs:** Lint + typecheck run simultaneously (in CI yaml, set `runs-on: ubuntu-latest`)
|
||||
3. **Skip full build on patch commits:** Use `[skip ci]` in commit message (not recommended for main)
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common CI Failures
|
||||
|
||||
| Error | Cause | Fix |
|
||||
|-------|-------|-----|
|
||||
| `ESLint error: Import not sorted` | Import order wrong | `pnpm lint --fix` |
|
||||
| `TypeScript error: Type 'any'` | Strict type checking | Add explicit type annotation |
|
||||
| `Jest timeout: test took > 5000ms` | Slow test (DB, network) | Mock external calls, increase timeout `jest.setTimeout(10000)` |
|
||||
| `Out of disk space` | GitHub runner full | Clear cache, reduce artifact retention |
|
||||
| `pnpm install stuck` | Network issue | Retry: `rm -rf node_modules && pnpm install` |
|
||||
|
||||
### Re-run CI
|
||||
|
||||
```bash
|
||||
# Re-run entire workflow (GitHub UI)
|
||||
Actions tab → select workflow → click "Re-run" button
|
||||
|
||||
# Or locally, push empty commit
|
||||
git commit --allow-empty -m "Trigger CI"
|
||||
git push
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## References
|
||||
|
||||
- GitHub Actions: https://docs.github.com/en/actions
|
||||
- Turborepo Caching: https://turbo.build/repo/docs/core-concepts/caching
|
||||
- ESLint Config: `/.eslintrc.json`
|
||||
- TypeScript Config: `/tsconfig.json` (root), `/apps/api/tsconfig.json`, etc.
|
||||
- Jest Config: `/apps/api/jest.config.js`
|
||||
- Vitest Config: `/apps/web/vitest.config.ts`
|
||||
Reference in New Issue
Block a user