Files
goodgo-platform/docs/ci-cd.md
Ho Ngoc Hai e798468e4c 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>
2026-04-22 23:29:20 +07:00

356 lines
9.1 KiB
Markdown

# 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()``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`