Tối thứ Sáu, tôi từng merge một change nhỏ: đổi logic hiển thị trạng thái thanh toán trong dashboard. Diff không lớn, test pass, AI assistant giải thích khá tự tin rằng chỉ đụng UI. Deploy xong mười phút, support báo khách không thấy invoice đã paid. Không phải backend hỏng. Không phải database hỏng. Pipeline của tôi hỏng theo nghĩa nguy hiểm hơn: nó không bắt buộc ai phải nhìn vào đúng màn hình trước khi đưa code ra production.
Từ đó tôi không coi deploy pipeline là vài lệnh CI nữa. Khi có AI coding trong team, pipeline phải là một đường ray có bằng chứng. AI có thể sửa nhanh, đọc nhanh, generate nhanh, nhưng nó cũng rất giỏi làm bạn tin rằng “change này nhỏ”. Deploy pipeline phải chống lại cảm giác đó.
Pipeline tốt bắt đầu trước khi merge
Một deploy pipeline thực dụng có ba lớp: build được, chạy được, và đúng việc người dùng cần. Nhiều team dừng ở lớp một: CI pass, unit test pass, lint pass, vậy là merge. Với AI coding, lớp đó quá mỏng.
AI thường tạo ra code syntactically đúng nhưng lệch ngữ cảnh. Nó gọi nhầm hook đã tồn tại, reuse endpoint sai payload, hoặc sửa một condition làm case khác đổi nghĩa. Những lỗi này không phải lúc nào unit test cũng bắt. Vì vậy pipeline nên ép mỗi task có một preview URL hoặc ít nhất một local verification path rõ ràng trước khi merge.
Với web app, mỗi PR nên có:
- Preview URL gắn với commit hoặc branch.
- Một smoke test checklist ngắn theo feature.
- Một rollback point cụ thể: commit trước deploy, artifact version, hoặc image tag.
- Một người chịu trách nhiệm nhìn production sau deploy.
Không cần phức tạp. Nhưng phải ghi lại. Nếu chỉ nằm trong đầu người deploy, đến lúc incident xảy ra không ai biết quay lại đâu.
Preview URL là nơi bắt lỗi rẻ nhất
Preview URL không phải “nice to have”. Nó là staging mini cho từng change. Với AI coding, tôi xem nó là checkpoint bắt buộc vì nó trả lời câu hỏi mà diff không trả lời được: người dùng thật sẽ thấy gì?
Một preview tốt cần gần giống production ở bốn điểm: routing, auth, API environment, và asset loading. Nếu preview chỉ render static page với mock data thì gần như vô dụng cho feature nghiệp vụ. User đã dặn trong repo này là không dùng mock data, và đó là một rule đúng cho deploy. Mock data làm preview nhìn đẹp nhưng không chứng minh gì về contract thật.
Tôi thường viết smoke checklist ngay trong PR hoặc ticket, dạng rất cụ thể:
Preview smoke test
- Login bằng account staging có invoice paid và unpaid.
- Mở /billing/invoices.
- Filter status = Paid.
- Confirm invoice INV-2026-041 hiện badge Paid.
- Click invoice detail, confirm payment date vẫn hiển thị.
- Refresh page, confirm filter state không crash.
Checklist này có thể do AI draft, nhưng người deploy phải sửa lại theo domain. Đừng để AI viết checklist kiểu “verify the page works as expected”. Câu đó không có giá trị vận hành. “INV-2026-041 hiện badge Paid” thì có.
Deploy window không chỉ dành cho enterprise
Nhiều người nghe “deploy window” là nghĩ tới ngân hàng, telecom, hệ thống lớn. Tôi nghĩ app nhỏ càng cần deploy window, vì app nhỏ thường không có SRE, không có on-call rotation, không có alert đầy đủ. Nếu deploy lúc người phụ trách chuẩn bị đi ngủ, rollback sẽ chậm.
Deploy window của một blog, SaaS nhỏ, dashboard nội bộ có thể rất nhẹ:
- Không deploy feature mới trong 30 phút trước khi người phụ trách offline.
- Không deploy change risk cao ngay trước campaign, demo, webinar, hoặc billing cycle.
- Deploy vào khung có thể nhìn log và user flow sau đó ít nhất 15 phút.
- Nếu phải deploy ngoài window, ghi rõ lý do và rollback owner.
AI coding làm tốc độ change tăng lên. Tốc độ đó dễ kéo deploy sang kiểu “xong rồi bấm luôn”. Pipeline phải đặt một nhịp chậm có chủ ý ở cuối. Không phải để bureaucracy, mà để giữ quyền quan sát sau khi code chạm người dùng thật.
Artifact phải trace được
Khi incident xảy ra, câu hỏi đầu tiên không phải “AI đã sửa gì”. Câu hỏi đầu tiên là “production đang chạy artifact nào”. Nếu không trả lời trong một phút, pipeline thiếu traceability.
Với frontend static deploy, artifact có thể là commit SHA trong build metadata hoặc tên folder deploy. Với container, là image digest hoặc tag immutable. Với serverless, là deployment ID. Dù dùng gì, đừng dựa vào tag mơ hồ như latest.
Tôi thích một rule đơn giản:
Every deploy log must contain:
- branch
- commit SHA
- build command
- artifact ID
- target environment
- deploy start/end time
- rollback command or previous artifact ID
AI có thể giúp generate deploy note từ git state, nhưng pipeline phải lấy dữ liệu từ command thật. Đừng để AI đoán branch hoặc commit. Với repo có nhiều worker song song, đoán sai là chuyện rất dễ xảy ra.
Smoke test sau deploy phải nhỏ nhưng thật
Smoke test không phải regression suite. Nó là một đường đi ngắn nhất chứng minh production còn sống ở những điểm change vừa đụng. Nếu deploy change billing, smoke billing. Nếu deploy search, smoke search. Nếu deploy content blog, smoke trang bài viết, series page, RSS hoặc sitemap nếu có.
Một smoke test tốt có ba tầng:
- Technical health: page trả HTTP 200, asset load, API không 500.
- User path: thao tác chính chạy được từ đầu tới cuối.
- Data sanity: dữ liệu thật hoặc staging-realistic hiển thị đúng.
Ví dụ deploy bài blog mới:
Post-deploy smoke
- curl production URL, confirm HTTP 200.
- Open article URL, title matches frontmatter.
- Open /series/ai-coding-thuc-chien/, confirm order includes bài 12.
- Search "deploy pipeline", confirm article appears.
- Check browser console has no obvious runtime error.
Smoke test phải gắn với change. Checklist global dài 40 dòng sẽ bị bỏ qua. Checklist 5 dòng đúng chỗ thì được chạy thật.
Rollback point phải được chọn trước deploy
Rollback không nên bắt đầu bằng “để tôi xem lại CI”. Trước khi deploy, bạn phải biết rollback về đâu. Đây là điểm AI coding hay làm team chủ quan: change nhỏ, assistant confident, test pass. Nhưng rollback luôn phải tồn tại cho cả change nhỏ.
Có vài kiểu rollback point:
- Static site: previous deploy ID hoặc previous build folder.
- Container: previous image digest.
- Database-free backend: previous release version.
- Database migration: rollback plan riêng, thường không chỉ là revert code.
- Feature flag: disable flag, nếu change đã được bọc đúng.
Nếu task có migration, pipeline phải tách deploy code và migration thinking. AI rất dễ viết migration nhìn hợp lý nhưng rollback khó. Một migration đổi schema destructive, drop column, backfill sai, hoặc mutate data không idempotent thì rollback code không cứu được data.
Rule cá nhân: nếu rollback cần nhiều hơn một command, ghi runbook ngắn trước deploy. Nếu không ghi được runbook, chưa deploy.
AI nên làm gì trong pipeline
AI rất hữu ích ở pipeline, nhưng nên dùng đúng việc.
Nên giao AI:
- Đọc diff và đề xuất smoke checklist.
- So sánh changed files với route/user flow bị ảnh hưởng.
- Tóm tắt deploy note từ git state thật.
- Viết script kiểm tra endpoint hoặc page status.
- Đọc log sau deploy và nhóm lỗi theo pattern.
Không nên giao AI:
- Tự quyết định production deploy khi chưa có owner.
- Tự bỏ qua failed check vì “likely flaky”.
- Tự sửa production config trong lúc incident nếu chưa có confirmation.
- Tự chọn rollback target nếu pipeline không trace artifact.
AI có thể là copilot của deploy, không phải người ký deploy. Người ký deploy là người chịu trách nhiệm khi support gọi.
Pipeline tối thiểu tôi chấp nhận
Nếu một team nhỏ hỏi tôi setup tối thiểu, tôi sẽ không bắt đầu bằng Kubernetes hay GitOps. Tôi bắt đầu bằng một checklist ít nhưng đủ:
Before merge
- CI pass.
- Preview URL available.
- Smoke checklist written with real route/data.
- Risk level: low / medium / high.
Before deploy
- Current branch and commit confirmed.
- Target environment confirmed.
- Rollback point known.
- Deploy owner online for 15 minutes after deploy.
After deploy
- Production smoke test run.
- Error logs checked.
- Deploy note recorded.
- Incident channel watched for 15 minutes.
Pipeline này không sang. Nhưng nó bắt được phần lớn lỗi do AI coding gây ra: đúng code sai context, UI pass local nhưng fail production data, deploy nhầm branch, không biết rollback về đâu.
Chỗ tradeoff thật
Pipeline càng nhiều gate càng chậm. Nếu mỗi typo fix cũng phải qua preview, checklist, approval, deploy window, team sẽ bypass. Vì vậy nên phân loại risk.
Low risk: content typo, CSS spacing nhỏ, copy change không động logic. Có thể deploy nhanh, smoke nhẹ.
Medium risk: UI logic, API payload, auth state, payment display, search, routing. Cần preview và smoke thật.
High risk: migration, permission, billing, background job, data deletion, external integration. Cần rollback runbook, feature flag nếu có thể, deploy window rõ, và người thứ hai review.
AI coding không làm mọi change thành high risk. Nó làm risk khó cảm nhận hơn vì code xuất hiện nhanh và trông sạch. Pipeline tốt không chống AI. Nó chống cảm giác dễ dãi sau khi AI làm việc quá nhanh.
Tôi vẫn thích deploy nhanh. Nhưng nhanh không có nghĩa là mù. Một pipeline thực dụng phải trả lời được bốn câu trước khi bấm nút: đang deploy artifact nào, ai đã nhìn preview, smoke production bằng gì, và quay lại đâu nếu sai. Thiếu một trong bốn câu đó, deploy chưa sẵn sàng.