Cú điện thoại thức tỉnh trị giá 5.000 USD
Điện thoại của tôi bắt đầu reo inh ỏi vào lúc 2 giờ sáng thứ Ba. Đó không phải là một buổi diễn tập; đó là một tình huống khẩn cấp trên môi trường production. Sau khi loạng choạng đi đến bàn làm việc, tôi đã tìm ra nguyên nhân: một developer mới đã vô tình commit một AWS Secret Access Key lên một kho lưu trữ (repo) công khai. Chỉ trong chưa đầy mười phút, các bot tự động đã quét được khóa này và khởi tạo một loạt các instance EC2 khổng lồ để đào tiền ảo. Hóa đơn AWS của chúng tôi lúc đó đã vượt ngưỡng 4.500 USD.
Chúng tôi đã thu hồi các khóa và xóa sạch lịch sử commit, nhưng bài học rút ra là rất rõ ràng. Bạn không thể dựa vào việc kiểm tra thủ công để phát hiện mọi sai sót. Sự mệt mỏi luôn xảy ra. Sai lầm là không thể tránh khỏi. Bạn cần một người gác cổng ngay trên máy tính của developer — một người từ chối để các thông tin bí mật hoặc mã nguồn cẩu thả rời khỏi máy trạm. Người gác cổng đó chính là pre-commit.
Vấn đề: Vòng lặp commit “Fix Linting” vô tận
Trước khi chúng tôi tiêu chuẩn hóa quy trình làm việc, lịch sử Git của chúng tôi là một “nghĩa địa” đầy xấu hổ. Bạn biết kiểu đó mà: một commit tính năng có ý nghĩa theo sau là bốn tin nhắn kiểu như “fix linting”, “fix formatting again”, và “cái cuối cùng này, hứa đấy”. Nó thật lộn xộn và tốn kém.
Mỗi khi một dev đẩy lên một lỗi cú pháp nhỏ, pipeline CI/CD sẽ được kích hoạt. Nếu bản build GitHub Actions hoặc Jenkins của bạn mất 10 phút để chạy, bạn vừa lãng phí một khoảng thời gian đáng kể và tài nguyên tính toán chỉ vì thiếu một dòng trống. Việc đưa các bước kiểm tra này về phía trước (shift-left) — chạy chúng trước khi mã nguồn rời khỏi máy cục bộ — giúp tiết kiệm hàng giờ làm việc của kỹ sư mỗi tuần.
Chính xác thì Git Hook là gì?
Git có một cơ chế tích hợp sẵn gọi là hooks. Đây là các script tự động thực thi trong các sự kiện cụ thể, chẳng hạn như pre-commit, commit-msg, hoặc pre-push. Tuy nhiên, việc quản lý các hook thô là một cơn ác mộng. Chúng nằm trong thư mục .git/hooks, vốn không được quản lý phiên bản. Điều này khiến việc đồng bộ hóa các quy tắc trong một nhóm gồm hai mươi developer là điều gần như không thể.
Framework pre-commit đã thay đổi điều đó. Đây là một công cụ quản lý dựa trên Python, sử dụng một file cấu hình đơn giản để xử lý mọi thứ. Nó quản lý môi trường cho các công cụ của bạn — cho dù chúng chạy trên Node.js, Go hay Rust — và đảm bảo mọi thành viên trong nhóm đều chạy các bước kiểm tra giống hệt nhau.
Thiết lập: Xây dựng người bảo vệ cho bạn
Chuyển dịch từ tư duy DevOps sơ cấp sang cao cấp bao gồm việc tự động hóa những việc tầm thường. Hãy cùng xây dựng một cấu hình xử lý ba trụ cột của sức khỏe mã nguồn: định dạng (formatting), kiểm tra logic (linting) và bảo mật.
1. Cài đặt
Cài đặt package vào hệ thống của bạn. Mặc dù bạn có thể dùng pip, người dùng macOS thường ưu tiên Homebrew.
pip install pre-commit
# Hoặc dành cho người dùng Mac
brew install pre-commit
2. File cấu hình
Tạo một file .pre-commit-config.yaml trong thư mục gốc của dự án. File này đóng vai trò là nguồn sự thật duy nhất cho các tiêu chuẩn chất lượng của bạn. Đây là cấu hình đã qua thực chiến mà tôi sử dụng cho các microservice dựa trên Python:
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files
- repo: https://github.com/psf/black
rev: 23.11.0
hooks:
- id: black
- repo: https://github.com/pycqa/flake8
rev: 6.1.0
hooks:
- id: flake8
- repo: https://github.com/Yelp/detect-secrets
rev: v1.4.0
hooks:
- id: detect-secrets
args: ['--baseline', '.secrets.baseline']
3. Tại sao lại dùng những hook này?
- Những người dọn dẹp:
trailing-whitespacevàend-of-file-fixergiữ cho các bản so khớp (diff) của bạn sạch sẽ. Sẽ không còn những PR thay đổi 50 dòng mà thực chất chỉ là điều chỉnh khoảng trắng. - Black: Đây là công cụ định dạng “không khoan nhượng”. Nó chấm dứt mọi cuộc tranh luận về việc nên dùng nháy đơn hay nháy kép bằng cách tự đưa ra lựa chọn cho bạn.
- Flake8: Trinh sát logic của chúng ta. Nó gắn cờ các import không sử dụng và các biến chưa được định nghĩa trước khi chúng gây ra lỗi runtime.
- detect-secrets: Đây là công cụ quan trọng nhất trong bộ công cụ của bạn. Nó quét các chuỗi có độ hỗn luận cao (entropy cao) như API key. Nếu phát hiện rò rỉ tiềm ẩn, nó sẽ chặn commit ngay lập tức.
4. Kích hoạt
Chỉ tạo file cấu hình thôi là chưa đủ. Bạn phải đăng ký nó với Git. Hãy chạy lệnh này trong terminal của bạn:
pre-commit install
Giờ đây, khi bạn chạy git commit, các hook sẽ bắt đầu hoạt động. Nếu một bước kiểm tra thất bại, pre-commit sẽ dừng quá trình lại. Nó thường tự động sửa các lỗi định dạng; bạn chỉ cần stage lại các thay đổi và thử lại.
Quy trình phát hiện bí mật (Secret Detection)
Hook detect-secrets sử dụng một file baseline để phân biệt giữa rò rỉ thực sự và một chuỗi “an toàn” đã biết, chẳng hạn như một key giả trong bộ test suite. Khởi tạo nó bằng cách chạy:
detect-secrets scan > .secrets.baseline
Nếu hook nhận diện nhầm (false positive), hãy cập nhật file baseline. Trở ngại nhỏ này là một cái giá quá rẻ để trả cho việc ngăn chặn một vụ vi phạm dữ liệu thảm khốc.
Dọn dẹp mã nguồn cũ (Legacy Code)
Bạn không cần phải đợi đến lúc commit mới biết mã nguồn của mình có đạt yêu cầu hay không. Khi áp dụng pre-commit vào một dự án cũ, hãy chạy nó trên tất cả các file cùng một lúc:
pre-commit run --all-files
Cảnh báo trước: nếu dự án đã vài năm tuổi, bạn có thể thấy hơn 500 lỗi. Đừng nản lòng. Thà đưa những vấn đề này ra ánh sáng ngay bây giờ còn hơn là để chúng ám ảnh môi trường production của bạn.
Tại sao điều này quan trọng với DevOps
Pre-commit xoay quanh vòng lặp phản hồi. Nếu một dev phát hiện ra lỗi sau 10 giây kể từ khi gõ, họ sẽ sửa nó ngay lập tức. Nếu họ biết được sau 20 phút thông qua một bản build CI thất bại, họ đã mất đi mạch làm việc của mình. Chuyển đổi ngữ cảnh (context switching) là kẻ sát nhân thầm lặng đối với năng suất.
Tiêu chuẩn hóa là một thắng lợi lớn khác. Chúng ta không còn phải đối mặt với cái cớ “nó vẫn chạy tốt trên máy của em“. Môi trường linting trên laptop của developer giờ đây giống hệt với môi trường chạy trên build server.
Lời kết
Thiết lập pre-commit là một trong những hành động mang lại hiệu quả cao nhất mà bạn có thể thực hiện. Nó biến chất lượng mã nguồn từ một công việc nhàm chán thành một quy trình chạy ngầm tự động. Những sự cố lúc 2 giờ sáng của tôi giờ đây rất hiếm vì chúng tôi đã tự động hóa để loại bỏ các lỗi phổ biến. Hãy bắt đầu với việc định dạng cơ bản và phát triển từ đó. Bản thân bạn trong tương lai sẽ cảm ơn bạn vì sự an tâm này.

