Files
cowork-local/tests/test_no_ignored_source.py
f9f6bc01fd
CI / test (push) Canceled after 0s
Feature/delta team/epic r04 (#7)
## Summary

epic r04 - begin refactor

## Change Type

- [x] Cowork feature
- [ ] Bug fix
- [ ] Core AI contribution
- [ ] Test / hardening
- [ ] Performance
- [ ] Documentation

## Related Work

Cowork Task:

Core Repo: http://34.143.229.138/gitea-admin/fsg-ai-core-assets

Core AI Issue:

Core Task:

Related PR:

## Scope

What is intentionally included?

What is intentionally NOT included?

## Validation

- [ ] Unit tests
- [ ] Integration tests
- [ ] Manual verification
- [ ] Regression check

Commands / evidence:

## Security Impact

Permission / credential / network / customer data impact:

## Compatibility

- [ ] No breaking change
- [ ] Breaking change documented

## Reviewer Notes

Anything Cowork reviewers should pay attention to.

---------

Co-authored-by: Anh Tran Nguyen Minh <anhtnm1@fpt.com>
Co-authored-by: Huong Le Thi Thien <huongltt35@fpt.com>
Co-authored-by: Nam Pham Dinh Thanh <nampdt@fpt.com>
Co-authored-by: Vu Dam Tuan <vudt15@fpt.com>
Co-authored-by: Hiep Ha Van <hiephv3@fpt.com>
Co-authored-by: Lam Hoang Van <lamhv7@fpt.com>
Reviewed-on: #7
Co-authored-by: Duy Le Huu <duylh19@fpt.com>
2026-08-31 05:15:13 +00:00

92 lines
3.5 KiB
Python

"""Không file mã nguồn nào được nằm ngoài repo vì `.gitignore`.
Bài này sinh ra từ một lỗi thật, mất hai ngày mới lộ:
``.gitignore`` dòng 31 ghi ``secrets/`` — mẫu **không neo**, nên git bỏ qua
mọi thư mục tên ``secrets`` ở mọi độ sâu, kể cả ``infrastructure/secrets/``
vốn là **mã nguồn**. Ba file trong đó chưa bao giờ lên repo. Máy người viết
vẫn chạy 150 test xanh, nhưng ai clone sạch về thì 4 file test đỏ ngay lúc
thu thập.
Trên máy đã có file thì không cách nào nhận ra: ``pytest`` đọc đĩa, không đọc
git. Nên phải hỏi thẳng git.
"""
from __future__ import annotations
import subprocess
import sys
from pathlib import Path
REPO = Path(__file__).resolve().parent.parent
#: Thư mục chứa mã nguồn của ứng dụng — file .py ở đây bắt buộc phải vào repo.
SOURCE_DIRS = ["domain", "application", "infrastructure", "presentation",
"adapters", "core", "ui", "providers", "scripts", "tools", "tests"]
def _git(*args: str) -> str:
out = subprocess.run(["git", *args], cwd=REPO, capture_output=True,
text=True, encoding="utf-8", errors="replace")
return out.stdout
def test_khong_file_py_nao_bi_gitignore_nuot():
"""File .py có trên đĩa nhưng git không thấy — vừa chưa theo dõi, vừa bị
bỏ qua. Đó chính là hình dạng của lỗi ``secrets/``."""
existing = []
for d in SOURCE_DIRS:
root = REPO / d
if root.is_dir():
existing.append(d)
assert existing, "không thấy thư mục mã nguồn nào — kiểm lại SOURCE_DIRS"
ignored = _git("ls-files", "--others", "--ignored", "--exclude-standard",
"--", *existing).splitlines()
ignored_py = [p for p in ignored
if p.endswith(".py") and "__pycache__" not in p]
assert not ignored_py, (
"File mã nguồn bị .gitignore nuốt — clone sạch sẽ thiếu:\n "
+ "\n ".join(ignored_py)
+ "\nChạy `git check-ignore -v <file>` để biết dòng nào gây ra."
)
def test_khong_file_py_nao_bi_bo_quen_chua_theo_doi():
"""Chưa bị ignore nhưng cũng chưa `git add` — quên, không phải cố ý."""
untracked = _git("ls-files", "--others", "--exclude-standard").splitlines()
forgotten = [p for p in untracked
if p.endswith(".py")
and p.split("/")[0] in SOURCE_DIRS
and "__pycache__" not in p]
assert not forgotten, (
"File mã nguồn chưa được git add — clone sạch sẽ thiếu:\n "
+ "\n ".join(forgotten)
)
def test_moi_module_duoc_import_deu_co_trong_repo():
"""Bắt theo hướng ngược: đi từ những gì code THỰC SỰ import.
Hai bài trên quét theo thư mục; bài này bắt cả trường hợp file nằm ngoài
danh sách đó mà vẫn được import.
"""
tracked = set(_git("ls-files").splitlines())
missing = []
for d in ("domain", "application", "infrastructure", "adapters"):
root = REPO / d
if not root.is_dir():
continue
for f in root.rglob("*.py"):
rel = f.relative_to(REPO).as_posix()
if "__pycache__" in rel:
continue
if rel not in tracked:
missing.append(rel)
assert not missing, (
"Module thuộc kiến trúc mới nhưng không có trong repo:\n "
+ "\n ".join(missing)
)