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>
356 lines
9.1 KiB
Markdown
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()` 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`
|