(SecDevOps/Automation) — “Build Tests: Linting trong CI/CD — đừng để bug lọt qua vì khoảng trắng!”
Anh em DevOps/NetDev/Automation đều biết: bug “khó” thì ít, bug “đáng tiếc” mới nhiều—kiểu như biến khai báo xong quên dùng, import thừa, hay style chỗ thụt đầu dòng. Tin vui: những thứ này xử lý cực nhanh nếu ta lint sớm ngay trong pipeline CI. Vì sao Linting phải chạy sớm trong CI?
.flake8
[flake8] max-line-length = 100 extend-ignore = E203,W503 per-file-ignores = tests/*: D, S
pyproject.toml (Black)
[tool.black] line-length = 100 target-version = ["py311"] extend-exclude = ["migrations"]
.pylintrc (trích)
[MASTER] ignore=migrations [MESSAGES CONTROL] disable=C0114,C0115,C0116 ; tắt tạm docstring nếu đội chưa sẵn sàng [FORMAT] max-line-length=100
bandit.yaml (trích)
skips: - B101 # assert used Tích hợp vào quy trình làm việc
1) Pre-commit hook (giữ repo luôn sạch)
.pre-commit-config.yaml
repos: - repo: https://github.com/psf/black rev: 24.3.0 hooks: - id: black args: ["--check"] - repo: https://github.com/pycqa/flake8 rev: 7.1.0 hooks: - id: flake8 - repo: https://github.com/PyCQA/pylint rev: v3.2.6 hooks: - id: pylint additional_dependencies: ["pylint-django==2.6.0"] - repo: https://github.com/PyCQA/bandit rev: 1.7.9 hooks: - id: bandit args: ["-c", "bandit.yaml", "-r", "."]
Cài đặt:
pip install pre-commit pre-commit install
.github/workflows/lint.yml
name: Lint on: pull_request: branches: ["main", "develop"] jobs: lint: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: "3.11" - name: Install deps run: | python -m pip install --upgrade pip pip install black flake8 pylint bandit - name: Black (check) run: black --check . - name: Flake8 run: flake8 . - name: Pylint (fail soft ban đầu) run: | pylint $(git ls-files '*.py') || true - name: Bandit run: bandit -c bandit.yaml -r .
format: \tblack . lint: \tflake8 . \tpylint $$(git ls-files '*.py') || true \tbandit -c bandit.yaml -r . ci: \tblack --check . \tflake8 . \tbandit -c bandit.yaml -r . Nguyên tắc triển khai theo giai đoạn (CALMS-ready)
# Kiểm format mà không sửa black --check . # Tự định dạng toàn bộ black . # Kiểm tra style nhanh flake8 . # Phân tích sâu (đỏ nhiều thì nới lỏng dần) pylint $(git ls-files '*.py') # Quét bảo mật bandit -c bandit.yaml -r .
Thông điệp chốt
CI/CD muốn “khỏe” thì lint sớm – lint luôn. Đừng để những lỗi lặt vặt làm nghẽn pipeline hay tệ hơn, chui vào production. Từ Black để thống nhất format, flake8/Pylint để giữ kỷ luật code, đến Bandit để khóa rủi ro bảo mật—hãy coi linting là build test bắt buộc trong mọi PR của bạn.
Anh em DevOps/NetDev/Automation đều biết: bug “khó” thì ít, bug “đáng tiếc” mới nhiều—kiểu như biến khai báo xong quên dùng, import thừa, hay style chỗ thụt đầu dòng. Tin vui: những thứ này xử lý cực nhanh nếu ta lint sớm ngay trong pipeline CI. Vì sao Linting phải chạy sớm trong CI?
- Nhanh & rẻ: phát hiện lỗi style/logic trước khi vào test phức tạp.
- Đồng nhất codebase: cả team một chuẩn (PEP8, docstring, naming…), review nhẹ đầu hơn.
- Giảm nợ kỹ thuật: loại bỏ unused imports/vars, tránh bloat và side-effect.
- Nâng bảo mật: kiểm soát rủi ro sớm với static analysis (ví dụ Bandit).
- Pylint: già rơ, báo lỗi theo mã (Wxxx cảnh báo, Exxxx lỗi). Phù hợp kiểm chuẩn sâu.
- Pyflakes: tập trung lỗi cú pháp & logic cơ bản, nhanh gọn.
- flake8: wrapper gọn kết hợp Pyflakes + pycodestyle, dễ mở rộng plugin.
- pycodestyle: kiểm PEP8; pydocstyle: ép docstring chuẩn.
- Black: auto-format “ý chí mạnh”—giúp code thống nhất, review nhàn (dùng --check trong CI).
- Bandit: quét bảo mật tĩnh (mật khẩu cứng, call nguy hiểm, module lỗi thời…).
Lưu ý: Python, Ruby là ngôn ngữ thông dịch—không có compiler “đỡ hộ” cú pháp như C/Go—nên linter là lớp phòng tuyến bắt buộc.
Cấu hình tối thiểu (để team bớt cãi nhau 😅)- Black làm “single source of truth” về format.
- flake8 kiểm chuẩn + plugin (mypy, bugbear…) nếu cần.
- Bandit cho bảo mật.
- Pylint cho kiểm tra sâu—bật dần theo maturity.
.flake8
[flake8] max-line-length = 100 extend-ignore = E203,W503 per-file-ignores = tests/*: D, S
pyproject.toml (Black)
[tool.black] line-length = 100 target-version = ["py311"] extend-exclude = ["migrations"]
.pylintrc (trích)
[MASTER] ignore=migrations [MESSAGES CONTROL] disable=C0114,C0115,C0116 ; tắt tạm docstring nếu đội chưa sẵn sàng [FORMAT] max-line-length=100
bandit.yaml (trích)
skips: - B101 # assert used Tích hợp vào quy trình làm việc
1) Pre-commit hook (giữ repo luôn sạch)
.pre-commit-config.yaml
repos: - repo: https://github.com/psf/black rev: 24.3.0 hooks: - id: black args: ["--check"] - repo: https://github.com/pycqa/flake8 rev: 7.1.0 hooks: - id: flake8 - repo: https://github.com/PyCQA/pylint rev: v3.2.6 hooks: - id: pylint additional_dependencies: ["pylint-django==2.6.0"] - repo: https://github.com/PyCQA/bandit rev: 1.7.9 hooks: - id: bandit args: ["-c", "bandit.yaml", "-r", "."]
Cài đặt:
pip install pre-commit pre-commit install
Từ nay commit nào cũng bị lint trước khi vào repo.
2) GitHub Actions (chặn lỗi ngay từ PR).github/workflows/lint.yml
name: Lint on: pull_request: branches: ["main", "develop"] jobs: lint: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: "3.11" - name: Install deps run: | python -m pip install --upgrade pip pip install black flake8 pylint bandit - name: Black (check) run: black --check . - name: Flake8 run: flake8 . - name: Pylint (fail soft ban đầu) run: | pylint $(git ls-files '*.py') || true - name: Bandit run: bandit -c bandit.yaml -r .
Mẹo: cho Pylint || true thời gian đầu để đội dần siết rule—tránh “đỏ cả rừng” làm tắc pipeline.
3) Makefile (dev chạy cho tiện)format: \tblack . lint: \tflake8 . \tpylint $$(git ls-files '*.py') || true \tbandit -c bandit.yaml -r . ci: \tblack --check . \tflake8 . \tbandit -c bandit.yaml -r . Nguyên tắc triển khai theo giai đoạn (CALMS-ready)
- Phase 1 – Format-first: bật Black + flake8 cơ bản (E/W tối thiểu), Bandit “informational”.
- Phase 2 – Scale up rules: siết flake8 (bugbear, complexity), bật một phần Pylint.
- Phase 3 – Security baseline: Bandit thành “blocking” cho hạng mục critical/high.
- Phase 4 – Policy-as-code: lưu rule vào repo, review rule-change như code.
# Kiểm format mà không sửa black --check . # Tự định dạng toàn bộ black . # Kiểm tra style nhanh flake8 . # Phân tích sâu (đỏ nhiều thì nới lỏng dần) pylint $(git ls-files '*.py') # Quét bảo mật bandit -c bandit.yaml -r .
Thông điệp chốt
CI/CD muốn “khỏe” thì lint sớm – lint luôn. Đừng để những lỗi lặt vặt làm nghẽn pipeline hay tệ hơn, chui vào production. Từ Black để thống nhất format, flake8/Pylint để giữ kỷ luật code, đến Bandit để khóa rủi ro bảo mật—hãy coi linting là build test bắt buộc trong mọi PR của bạn.