# Cách deploy và rollback production ## Phân loại **Loại tài liệu:** How-to. **Reader job:** phát hành một thay đổi lên EC2 Compose và khôi phục commit trước nếu verification thất bại. ## Khi nào dùng hướng dẫn này Production hiện tại là một EC2 host chạy Docker Compose. Đây không phải quy trình Kubernetes/ArgoCD. Deploy bình thường chạy bằng `deploy.yml`; rollback có workflow manual riêng. ## Điều kiện tiên quyết - Thay đổi đã được review. - CI của commit đã xanh; lưu ý deploy workflow chưa phụ thuộc CI bằng `needs`. - GitHub secrets `EC2_HOST`, `EC2_SSH_KEY` và `GRAFANA_ADMIN_PASSWORD` hợp lệ. - Biết last-known-good SHA trước khi deploy. - Thay đổi migration đã được đánh giá vì migrations chỉ đi tới, không có down. ## Bước 1 — Xác định deploy có được trigger không Push lên `master` chỉ trigger deploy khi thay đổi nằm trong path filter: - `apps/ai-service/**`; - `apps/web/**`; - `packages/**`; - drug entity artifact; - `infra/docker/**`; - chính `deploy.yml`. Docs-only change không deploy production. Có thể dùng `workflow_dispatch` khi cần chạy chủ động. ## Bước 2 — Ghi release context Trước khi chạy, lưu: ```text target SHA last-known-good SHA CI run URL deploy run URL thay đổi config/migration người theo dõi rollout ``` Không deploy đồng thời với một corpus switch nếu chưa có kế hoạch rollback riêng cho collection. ## Bước 3 — Chạy deploy workflow Workflow thực hiện trên host: 1. fetch và reset checkout về `origin/master`; 2. build/start app + observability services; 3. validate/reload Caddy; 4. apply migrations; 5. kiểm tra health/readiness/web; 6. smoke một condition→drug response; 7. kiểm tra Prometheus, Tempo, Grafana và một trace cụ thể. Theo dõi log đến khi tất cả assertion pass. Job fail không đồng nghĩa host đã tự rollback; workflow deploy không có automatic rollback. ## Bước 4 — Verify sau deploy Kiểm tra tối thiểu: - `/health` và `/ready` trả 200; - web tải được; - query smoke trả `answerable` và citation `chi_dinh`; - trace ID có trong Tempo; - `duocthu_requests_total` query được; - dashboard Grafana được provision; - không có spike mới ở abstain/provider failure. Giữ một cửa sổ quan sát trước khi tuyên bố rollout hoàn tất. ## Rollback bằng workflow Mở workflow **Rollback production**, chọn `workflow_dispatch`, nhập `target_sha` là last-known-good commit. Workflow: 1. verify SHA tồn tại; 2. reset checkout về SHA đó; 3. rebuild app/observability tier; 4. chạy migrations idempotent; 5. chạy health checks. Rollback không đảo schema database. Nếu release chứa migration không tương thích ngược, dừng và lập kế hoạch phục hồi dữ liệu/schema thay vì chạy workflow mù. ## Rollback corpus Code rollback và corpus rollback là hai thao tác khác nhau. Nếu vừa switch Qdrant collection: 1. đặt lại `QDRANT_COLLECTION` về collection cũ; 2. restart `ai-service`; 3. xác nhận manifest check và smoke query; 4. không xóa collection mới cho đến khi điều tra xong. ## Troubleshooting | Triệu chứng | Kiểm tra đầu tiên | Recovery | |---|---|---| | Build fail sau reset | GitHub log và Docker build log trên host | Rollback workflow về SHA cũ | | `ai-service` restart loop | `ManifestMismatch` trong container log | Sửa collection/model binding | | Smoke answer fail | Response + 200 dòng ai-service log | Rollback nếu ảnh hưởng live path | | Tempo chưa ready | Retry/log Tempo | Không coi rollout complete | | Migration fail | Migration output và DB state | Dừng; không chạy reset schema tùy tiện | ## Liên quan - [Deployment architecture](../20-deployment.md) - [CI/CD](../22-ci-cd.md) - [Production operations](../24-production-operations.md) - [Troubleshooting](../25-troubleshooting.md)