From 808b2e7c0e26c6a91d03ee4649e0f13d6b1eb210 Mon Sep 17 00:00:00 2001 From: codex Date: Mon, 11 May 2026 17:39:53 -0300 Subject: [PATCH] ci: publish LOC source file totals --- scripts/publish_quality_metrics.py | 27 +++++++++++++++++++------ scripts/publish_quality_metrics_test.py | 2 ++ 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/scripts/publish_quality_metrics.py b/scripts/publish_quality_metrics.py index d4121fd..718f670 100755 --- a/scripts/publish_quality_metrics.py +++ b/scripts/publish_quality_metrics.py @@ -100,6 +100,7 @@ def _build_payload( tests_skipped: int, test_cases: list[tuple[str, str]], coverage_percent: float, + source_files_total: int, source_lines_over_500: int, branch: str, build_number: str, @@ -131,6 +132,8 @@ def _build_payload( f'ananke_quality_gate_coverage_percent{{suite="{suite}"}} {coverage_percent:.3f}', "# TYPE platform_quality_gate_workspace_line_coverage_percent gauge", f'platform_quality_gate_workspace_line_coverage_percent{{suite="{suite}"}} {coverage_percent:.3f}', + "# TYPE platform_quality_gate_source_files_total gauge", + f'platform_quality_gate_source_files_total{{suite="{suite}"}} {source_files_total}', "# TYPE platform_quality_gate_source_lines_over_500_total gauge", f'platform_quality_gate_source_lines_over_500_total{{suite="{suite}"}} {source_lines_over_500}', "# TYPE platform_quality_gate_build_info gauge", @@ -169,8 +172,7 @@ def _read_coverage_percent(path: str) -> float: return 0.0 -def _count_source_files_over_limit(repo_root: Path, max_lines: int = 500) -> int: - count = 0 +def _iter_source_files(repo_root: Path): for rel_root in SOURCE_SCAN_ROOTS: base = repo_root / rel_root if not base.exists(): @@ -182,9 +184,19 @@ def _count_source_files_over_limit(repo_root: Path, max_lines: int = 500) -> int continue if path.name.endswith("_test.go") or path.name.endswith(".test.py"): continue - lines = len(path.read_text(encoding="utf-8", errors="ignore").splitlines()) - if lines > max_lines: - count += 1 + yield path + + +def _count_source_files(repo_root: Path) -> int: + return sum(1 for _ in _iter_source_files(repo_root)) + + +def _count_source_files_over_limit(repo_root: Path, max_lines: int = 500) -> int: + count = 0 + for path in _iter_source_files(repo_root): + lines = len(path.read_text(encoding="utf-8", errors="ignore").splitlines()) + if lines > max_lines: + count += 1 return count @@ -409,6 +421,7 @@ def main(argv: list[str] | None = None) -> int: resolved_ok += current_ok resolved_failed += current_failed coverage_percent = _read_coverage_percent(args.coverage_percent_file) + source_files_total = _count_source_files(repo_root) source_lines_over_500 = _count_source_files_over_limit(repo_root, max_lines=500) quality_output = Path(os.getenv("ANANKE_QUALITY_OUTPUT_FILE", str(build_dir / "quality-gate.out"))) tests = _parse_go_test_counts(quality_output) @@ -435,6 +448,7 @@ def main(argv: list[str] | None = None) -> int: tests_skipped=tests["skipped"], test_cases=test_cases, coverage_percent=coverage_percent, + source_files_total=source_files_total, source_lines_over_500=source_lines_over_500, branch=branch, build_number=build_number, @@ -451,7 +465,8 @@ def main(argv: list[str] | None = None) -> int: summary = ( f"[quality] published Pushgateway metrics suite={args.suite} job={args.job_name} ok={resolved_ok} " - f"failed={resolved_failed} coverage={coverage_percent:.3f} source_lines_over_500={source_lines_over_500}" + f"failed={resolved_failed} coverage={coverage_percent:.3f} source_files_total={source_files_total} " + f"source_lines_over_500={source_lines_over_500}" ) if remote_error: summary += f" remote_read_error={remote_error}" diff --git a/scripts/publish_quality_metrics_test.py b/scripts/publish_quality_metrics_test.py index 2a88af8..945f9eb 100755 --- a/scripts/publish_quality_metrics_test.py +++ b/scripts/publish_quality_metrics_test.py @@ -109,6 +109,7 @@ class PublishQualityMetricsTest(unittest.TestCase): self.assertIn('ananke_quality_gate_publish_info{suite="ananke",trigger="host"} 1', body) self.assertIn('ananke_quality_gate_coverage_percent{suite="ananke"}', body) self.assertIn('platform_quality_gate_workspace_line_coverage_percent{suite="ananke"}', body) + self.assertIn('platform_quality_gate_source_files_total{suite="ananke"}', body) self.assertIn('platform_quality_gate_source_lines_over_500_total{suite="ananke"}', body) def test_publish_does_not_double_count_same_build(self) -> None: @@ -175,6 +176,7 @@ class PublishQualityMetricsTest(unittest.TestCase): self.assertIn('platform_quality_gate_runs_total{suite="ananke",status="ok"} 11', body) self.assertIn('platform_quality_gate_runs_total{suite="ananke",status="failed"} 3', body) self.assertIn('platform_quality_gate_workspace_line_coverage_percent{suite="ananke"}', body) + self.assertIn('platform_quality_gate_source_files_total{suite="ananke"}', body) self.assertIn('platform_quality_gate_source_lines_over_500_total{suite="ananke"}', body)