ci(ariadne): restore LOC checker with tracked waivers
This commit is contained in:
parent
a57577e2a5
commit
26cc9333c7
2
Jenkinsfile
vendored
2
Jenkinsfile
vendored
@ -173,7 +173,7 @@ mkdir -p build
|
|||||||
set +e
|
set +e
|
||||||
python -m pip install --no-cache-dir -r requirements.txt -r requirements-dev.txt \
|
python -m pip install --no-cache-dir -r requirements.txt -r requirements-dev.txt \
|
||||||
&& python -m ruff check ariadne scripts --select PLR \
|
&& python -m ruff check ariadne scripts --select PLR \
|
||||||
&& python scripts/check_file_sizes.py --roots ariadne scripts testing --max-lines 500 --waivers ci/loc_hygiene_waivers.tsv \
|
&& python scripts/check_file_sizes.py --roots ariadne scripts tests --max-lines 500 --waivers ci/loc_hygiene_waivers.tsv \
|
||||||
&& python -m slipcover \
|
&& python -m slipcover \
|
||||||
--json \
|
--json \
|
||||||
--out "${COVERAGE_JSON}" \
|
--out "${COVERAGE_JSON}" \
|
||||||
|
|||||||
15
ci/loc_hygiene_waivers.tsv
Normal file
15
ci/loc_hygiene_waivers.tsv
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# path reason
|
||||||
|
ariadne/services/cluster_state.py split planned; service orchestration decomposition tracked in hygiene backlog
|
||||||
|
ariadne/app.py split planned; Flask app bootstrap/routes currently co-located
|
||||||
|
ariadne/services/comms.py split planned; comms adapters still consolidated
|
||||||
|
ariadne/manager/provisioning.py split planned; provisioning flow modules pending extraction
|
||||||
|
ariadne/services/nextcloud.py split planned; provider methods pending partition
|
||||||
|
ariadne/services/firefly.py split planned; provider methods pending partition
|
||||||
|
ariadne/settings.py split planned; settings schema + helpers pending split
|
||||||
|
ariadne/services/jenkins_workspace_cleanup.py split planned; job orchestration pending extraction
|
||||||
|
ariadne/services/wger.py split planned; provider methods pending partition
|
||||||
|
ariadne/services/vault.py split planned; auth + data access helpers pending split
|
||||||
|
tests/test_provisioning.py test module split planned; broad provisioning coverage retained meanwhile
|
||||||
|
tests/test_services.py test module split planned; broad service contract coverage retained meanwhile
|
||||||
|
tests/test_app.py test module split planned; API coverage retained meanwhile
|
||||||
|
tests/test_keycloak_admin.py test module split planned; identity admin coverage retained meanwhile
|
||||||
|
85
scripts/check_file_sizes.py
Normal file
85
scripts/check_file_sizes.py
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Fail when source files exceed a configured line-count threshold."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
DEFAULT_SKIP_PARTS = {
|
||||||
|
".git",
|
||||||
|
".venv",
|
||||||
|
"venv",
|
||||||
|
"build",
|
||||||
|
"dist",
|
||||||
|
"node_modules",
|
||||||
|
"__pycache__",
|
||||||
|
".pytest_cache",
|
||||||
|
}
|
||||||
|
SOURCE_SUFFIXES = {".py", ".sh", ".json", ".yaml", ".yml"}
|
||||||
|
|
||||||
|
|
||||||
|
def _read_waivers(path: Path) -> set[str]:
|
||||||
|
if not path.exists():
|
||||||
|
return set()
|
||||||
|
waived: set[str] = set()
|
||||||
|
for line in path.read_text(encoding="utf-8").splitlines():
|
||||||
|
row = line.strip()
|
||||||
|
if not row or row.startswith("#"):
|
||||||
|
continue
|
||||||
|
waived.add(row.split("\t", 1)[0].strip())
|
||||||
|
return waived
|
||||||
|
|
||||||
|
|
||||||
|
def _iter_files(root: Path) -> list[Path]:
|
||||||
|
if not root.exists():
|
||||||
|
return []
|
||||||
|
files: list[Path] = []
|
||||||
|
for path in root.rglob("*"):
|
||||||
|
if not path.is_file():
|
||||||
|
continue
|
||||||
|
if any(part in DEFAULT_SKIP_PARTS for part in path.parts):
|
||||||
|
continue
|
||||||
|
if path.suffix.lower() not in SOURCE_SUFFIXES and path.name != "Jenkinsfile":
|
||||||
|
continue
|
||||||
|
files.append(path)
|
||||||
|
return files
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> int:
|
||||||
|
parser = argparse.ArgumentParser(description=__doc__)
|
||||||
|
parser.add_argument("--roots", nargs="+", required=True)
|
||||||
|
parser.add_argument("--max-lines", type=int, default=500)
|
||||||
|
parser.add_argument("--waivers", default="ci/loc_hygiene_waivers.tsv")
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
repo_root = Path.cwd().resolve()
|
||||||
|
waived = _read_waivers(repo_root / args.waivers)
|
||||||
|
|
||||||
|
offenders: list[tuple[int, str]] = []
|
||||||
|
for root_name in args.roots:
|
||||||
|
for path in _iter_files(repo_root / root_name):
|
||||||
|
rel = path.relative_to(repo_root).as_posix()
|
||||||
|
if rel in waived:
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
line_count = sum(1 for _ in path.open("r", encoding="utf-8", errors="ignore"))
|
||||||
|
except OSError:
|
||||||
|
continue
|
||||||
|
if line_count > args.max_lines:
|
||||||
|
offenders.append((line_count, rel))
|
||||||
|
|
||||||
|
if not offenders:
|
||||||
|
print(f"[loc] ok: no files exceed {args.max_lines} lines")
|
||||||
|
return 0
|
||||||
|
|
||||||
|
offenders.sort(reverse=True)
|
||||||
|
print(f"[loc] failed: {len(offenders)} file(s) exceed {args.max_lines} lines")
|
||||||
|
for lines, rel in offenders:
|
||||||
|
print(f" - {rel}: {lines} lines")
|
||||||
|
return 1
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
raise SystemExit(main())
|
||||||
Loading…
x
Reference in New Issue
Block a user