Skip to content

fix(detect): gate coverage/ pruning on report artefacts (#2339) - #2351

Closed
MANOJ21K wants to merge 1 commit into
Graphify-Labs:v8from
MANOJ21K:fix/2339-gate-coverage-skip-dir
Closed

fix(detect): gate coverage/ pruning on report artefacts (#2339)#2351
MANOJ21K wants to merge 1 commit into
Graphify-Labs:v8from
MANOJ21K:fix/2339-gate-coverage-skip-dir

Conversation

@MANOJ21K

Copy link
Copy Markdown
Contributor

Fixes #2339.

Problem

"coverage" is an unconditional entry in detect.py::_SKIP_DIRS, and _is_noise_dir
matches directory names at any depth. In a repo where coverage is a legitimate package
name, the whole package is dropped from the graph — no warning, no skipped_sensitive
entry, nothing in the report.

The failure is quiet in the worst way: the package's dependents are still there, so
queries return plausible neighbours while the package itself simply doesn't exist as
nodes. The reporter only found it by diffing git ls-files against the distinct
source_file values in graph.json.

Same bug class as #1666 and #2058

The comment on the entry is # Vitest/Istanbul/nyc HTML reports (#870) — a JS-ecosystem
artefact directory — but the pruning is unconditional and language-agnostic.

detect.py has already been fixed twice for exactly this shape:

coverage hadn't been given the same treatment. This PR applies the existing pattern
rather than inventing a new mechanism.

Fix

  • coverage moves out of the unconditional _SKIP_DIRS set into an evidence-gated
    branch in _is_noise_dir, backed by a new _has_coverage_artifacts() helper written
    to match _has_venv_markers() (same OSError guard, same "cannot verify → keep a
    possibly-real code dir" contract when no parent is passed).
  • Evidence is a file a coverage tool actually writes: lcov.info, coverage-final.json,
    coverage-summary.json, clover.xml, coverage.xml, cobertura-coverage.xml,
    jacoco.xml, .coverage, index.html — or an lcov-report/ / html-report/
    subtree. That covers lcov, nyc/Istanbul, coverage.py, JaCoCo and Cobertura.
  • lcov-report stays unconditional. It has no false-positive class — no package is
    ever named that — so gating it would only add filesystem probes for no benefit. Only
    the ambiguous bare name is gated, mirroring how __snapshots__ stayed unconditional
    in Ruby: stable subset of files yields zero nodes in full-repo runs (0.9.6) — each extracts fine in isolation #1666 while snapshots was gated.

Reproduction

The reporter's repro, before and after (auditor_toolkit/assurance/coverage/ holding
__init__.py, impact.py, inventory.py, mapping.py, summary.py, with a genuine
Istanbul report at webapp/coverage/ in the same tree):

# before
direct target : []
via repo walk : []

# after
direct target : ['__init__.py', 'impact.py', 'inventory.py', 'mapping.py', 'summary.py']
via repo walk : ['auditor_toolkit/assurance/coverage/__init__.py', ... 'summary.py']

The generated webapp/coverage/ report is still pruned in the "after" walk — its
prettify.js never enters the corpus — so #870 is not regressed.

Tests

tests/test_detect.py, following the test_detect_keeps_snapshots_code_namespace
precedent. Three of them fail on clean v8:

  • test_detect_keeps_coverage_code_namespace — a coverage/ package with real modules
    survives a detect() scan.
  • test_collect_files_keeps_coverage_code_namespace — the issue as reported, via
    collect_files, both as the walk target and through the repo root, with a real report
    dir alongside that must still be skipped.
  • test_is_noise_dir_coverage_is_evidence_gated — the gate directly: name alone isn't
    enough, artefact evidence prunes, no-parent keeps, lcov-report still unconditional.
  • test_detect_skips_coverage_dir_by_lcov_info — guard: a single artefact file with no
    lcov-report/ subtree is still enough to prune.

The existing test_detect_skips_coverage_dir (#870) passes unchanged.

uv run pytest tests/ -q → 3903 passed, 3 skipped (baseline on v8 is 3899 passed,
3 skipped — the delta is exactly these four tests, no regressions).

Noted but not fixed here

The reporter also flagged that _parse_gitignore_line strips inline # comments while
git only treats # as a comment at line start, so *_backup_*.py # temp scripts
excludes real files for graphify but matches nothing for git. That's a separate
divergence in a different function and belongs in its own issue/PR.

…s#2339)

"coverage" was an unconditional _SKIP_DIRS entry and _is_noise_dir matches
directory names at any depth, so a repo where coverage is a legitimate
package name lost the whole package from the graph — no warning, no
skipped_sensitive entry, nothing in the report. The failure is quiet in
the worst way: the package's dependents survive, so queries keep
returning plausible neighbours while the package itself has no nodes.

The entry's comment cites Vitest/Istanbul/nyc HTML reports (Graphify-Labs#870), but
the pruning is language-agnostic, so it also removes Python/Go/Rust
packages that happen to be called coverage.

detect.py has been fixed twice for this exact shape — Graphify-Labs#1666 gated a bare
snapshots/ on real .snap evidence, Graphify-Labs#2058 gated env/.env/*_env on real
virtualenv markers — so this applies the established pattern rather than
a new mechanism. _has_coverage_artifacts() mirrors _has_venv_markers():
same OSError guard, same "cannot verify, keep a possibly-real code dir"
contract when no parent is available. Evidence is a file a coverage tool
actually writes (lcov.info, coverage-final.json, clover.xml,
coverage.xml, cobertura-coverage.xml, jacoco.xml, .coverage, index.html)
or an lcov-report/ / html-report/ subtree, covering lcov, nyc/Istanbul,
coverage.py, JaCoCo and Cobertura.

lcov-report stays unconditional: it has no false-positive class, so
gating it would add filesystem probes for no benefit — the same split
Graphify-Labs#1666 made between the unambiguous __snapshots__ and the bare snapshots.
@safishamsi

Copy link
Copy Markdown
Collaborator

Shipped in v0.9.32: the coverage/ prune is now gated on coverage-report artefacts, so a real package named coverage/ is kept (#2339). Thanks @MANOJ21K!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

coverage/ in _SKIP_DIRS silently drops real Python packages named 'coverage' (same class as #1666 snapshots / #2058 env)

2 participants