quanbi.dev
Khoá cài trên cần gạt, chặn đúng thao tác gây mất code khi deploy

Hướng dẫn thực hànhCâu chuyện thật

Mất code khi deploy: bốn lần, và cái khoá mình gắn sau đó

Quân BiCập nhật 8 phút đọc7 lượt xem

Bốn lần mình mất code, và cả bốn lần đều xoay quanh cùng một thứ: phần việc mà git chưa nhìn thấy. Mất code khi deploy nghe như lỗi của công cụ deploy. Thực ra công cụ làm đúng việc của nó, còn thứ mình đưa cho nó là một thư mục có phần chưa được ghi vào git.

Vì sao mình mất code khi deploy

Git chỉ biết những gì đã commit. Phần bạn vừa sửa mà chưa commit thì với git nó không tồn tại.

Lệnh build thì lấy nguồn từ git. Vậy nên mọi thứ chưa commit không đi vào bản build, hoặc tệ hơn, đi vào đúng một bản build rồi biến mất ở bản sau.

Câu đó nghe hiển nhiên. Mình vẫn dính bốn lần, vì lúc gấp thì mình không nghĩ tới nó.

Bài deploy Next.js lên VPS cũng đếm bốn cái bẫy. Đó là bốn cái bẫy của quy trình deploy, và một trong số đó chỉ chặn mình lại chứ không lấy mất gì. Bốn lần dưới đây là bốn lần mất chữ thật.

Lần một: đêm chạy một mạch

Agent chạy suốt đêm, sáng ra site đúng như mình đặt, chiều đó mình bảo nó build bản mới. Bản build lấy nguồn từ git, và cả đêm sửa chưa commit lần nào, nên nó bốc hơi. Bài Claude Code là gì kể kỹ lần đó, nên ở đây mình chỉ nói phần rút ra.

Cái mất không phải một đêm máy chạy. Cái mất là mình thôi tin vào thứ mình nhìn thấy trên màn hình sáng hôm đó. Từ hôm ấy, mỗi lần agent báo xong mình đều phải hỏi thêm một câu.

Lần hai: hai phiên một branch

Hai phiên mở cùng một thư mục, cùng một branch. Phiên bên này pull bản mới về, và mọi thứ phiên bên kia chưa commit bị xoá trắng trong đúng một lệnh. Bài deploy ở trên kể lần đó.

Phần đáng nói là nó chưa hết. Đúng lúc mình viết bài này, thư mục repo đang có một phiên khác mở, nên mọi lệnh đổi branch ở đây bị chặn từ đầu. Đường đi thay thế là push thẳng lên nhánh chính mà không đụng vào branch đang mở tại máy.

Nói cách khác, cái luật này không phải kỷ niệm. Nó vẫn đang đổi cách mình gõ lệnh trong lúc viết chính bài viết bạn đang đọc.

Lần ba: build từ thư mục đang dở

Thư mục làm việc lúc nào cũng có thứ chưa commit. Build thẳng từ đó thì bản chạy ngoài kia khác bản trên remote.

Lúc yên thì không sao. Lúc có sự cố, thứ mình mở ra đọc trên GitHub không phải thứ đang chạy, nên mình đi tìm lỗi ở đúng chỗ không có lỗi.

Lần bốn: bản đang chạy là bản duy nhất

Lần này đau nhất về nguyên tắc. Mình sửa, build thẳng trên máy chủ, thấy chạy đúng thì để đó.

Bản sửa ấy chỉ tồn tại bên trong một bản build đang chạy. Không có trên remote, không có trong lịch sử git. Lần build kế tiếp lấy nguồn từ git, và bản duy nhất đó bị ghi đè bởi chính quy trình lẽ ra để bảo vệ nó.

Từ đây mình rút ra luật ngắn nhất trong cả bài: xong nghĩa là đã commit và đã push. Chạy được trên màn hình không tính là xong.

Vì sao viết luật ra giấy không đủ

Ban đầu mình tưởng viết luật ra là xong. Mình viết hẳn ba dòng luật, để trong tài liệu, và đọc lại mỗi lần bắt đầu việc mới.

Hoá ra mình vẫn phá luật. Không phải vì mình quên nó, mà vì lúc gấp thì mình không đọc lại nó. Luật nằm trong tài liệu là một thoả thuận với chính mình, và mình là bên hay xin ngoại lệ nhất.

Nên mình chuyển luật vào máy. Bây giờ nó không nhắc, nó chặn.

Cái khoá gắn vào máy

Cái khoá này nằm ở máy mình, không nằm trong repo của site. Nó đứng trước mọi lệnh mình gõ, ở mọi dự án, chứ không riêng blog này. Nó chặn hai nhóm lệnh:

  • Lệnh git có thể xoá việc chưa commit. Cụ thể: reset --hard, checkout, switch, pull, clean -f, restore, stash drop. Chặn khi thư mục còn thay đổi chưa commit ở file git đang theo dõi.
  • Lệnh deploy lên bản thật, khi thư mục còn bẩn hoặc đang đi trước remote. Đây đúng là cái làm nên lần thứ bốn.

Việc an toàn thì không bao giờ bị chặn: tạo branch mới, cất tạm, commit, push, hoặc bất cứ lệnh gì trong một thư mục đã sạch. File mới chưa được git theo dõi cũng không làm nó kêu, trừ đúng lệnh dọn file rác vì lệnh đó nhắm thẳng vào chúng.

Cái khoá này biến chuyện mất code khi deploy thành chuyện vô hại. Xấu nhất thì mình deploy một bản đã commit hơi cũ, và sửa bằng cách deploy lại. Nguồn luôn lấy lại được từ git.

Một việc một thư mục riêng

Luật thứ hai đi kèm: một việc là một branch, và branch đó có thư mục riêng của nó.

Hai phiên chung một thư mục là chuyện lần hai. Git có sẵn cách tách ra, mỗi việc một bản làm việc riêng trên cùng một repo, xem tài liệu git worktree. Mình chỉ chạm tới nó sau khi mất việc một lần.

Mỗi lần deploy xong mình còn gắn một tag, bằng tay, ở bước cuối cùng của chuỗi. Bài deploy ở trên gọi mấy cái mốc đó là thứ rẻ nhất mà cứu mình nhiều nhất, và mình giữ nguyên câu đó. Ở đây mình nói rõ thêm nó cứu bằng cách nào.

Tới giờ nó cứu ở chỗ mình luôn biết chính xác bản nào đang chạy ngoài kia. Mỗi lần lên bản mới đẻ ra một mốc, nên câu hỏi "cái đang chạy là cái nào" lúc nào cũng có câu trả lời trong một giây.

Còn động tác deploy ngược lại một mốc cũ thì trên site này mình chưa phải làm lần nào. Nó vẫn là đường thoát trên giấy, chưa phải kinh nghiệm, và mình nói ra để bạn đừng tin nó nhiều hơn mình.

Chỗ cái khoá này không cứu được

Nó chặn theo trạng thái thư mục, nên nó không biết gì về ý định của mình. Có lúc mình thật sự muốn xoá phần đang sửa, và lúc đó nó vẫn chặn.

Vì vậy có một cửa tắt, dùng bằng cách nói thẳng ra trong chính câu lệnh. Mỗi lần tắt đều bị ghi lại. Mình để cửa đó vì một cái khoá không có cửa tắt là cái khoá người ta sẽ tháo hẳn ra.

Nó cũng không cứu được file chưa bao giờ nằm trong git: file cấu hình chứa khoá, file mình cố ý để git bỏ qua. Mấy thứ đó vẫn phải sao lưu bằng cách khác, và mình vẫn chưa làm phần đó tử tế.

Và nó không thay được thói quen commit. Nó chỉ làm cái giá của việc không commit hiện ra ngay lúc bạn định làm điều nguy hiểm, thay vì hiện ra ba ngày sau.

Ai không cần tới mức này

Bạn làm một mình, một branch, một máy, không có agent nào chạy song song. Vậy thì ba dòng luật viết ra giấy là đủ.

Mình cần tới cái khoá vì hoàn cảnh khác: có nhiều phiên agent chạy cùng lúc, và người bấm nút không đọc code. Với mình thì mọi lệnh git đều là lệnh mình không tự đọc được hậu quả, nên mình cần một lớp đứng chặn phía trước.

Bốn việc làm ngay hôm nay

  • Đặt luật xong nghĩa là đã push, rồi bỏ hẳn cách nói xong khi code còn nằm trên máy.
  • Đừng bao giờ build từ thư mục đang mở. Lấy một bản sạch từ branch chính.
  • Gắn tag mỗi lần deploy, để lần sau có chỗ quay về.
  • Thử đúng một lần quay về tag cũ, lúc đang rảnh. Mình chưa làm, và đó là chỗ yếu nhất trong cả bài này.

Quy trình deploy sáu bước mình mô tả riêng ở bài deploy Next.js lên VPS. Còn phần tiền thuê máy và công cụ, mình để ở bài chi phí chạy website một tháng. Thứ tự nên giao việc gì cho máy trước thì ở bài nên tự động hoá việc gì trước.

Sau bốn lần đó mình không cẩn thận hơn. Chỉ là bây giờ có máy nhớ hộ, và nó không nể mình. Các ghi chép cùng loại nằm ở chủ đề Vận hành.

Bài này thế nào?

Chia sẻ

XFacebook

Ảnh đại diện của chủ trang quanbi.dev

Về mình

Quân Bi · Người viết

Xem thêm →

Bình luận (0)

Chưa có bình luận nào. Bạn mở hàng nhé.

Viết bình luận