module
Noir::SkippedFiles
Overview
Every path by which a scan can quietly lose coverage, funnelled into one place.
AnalyzerFailure covers the case where a whole analyzer raised: coverage
lost by the tech. The other half of the same problem is a single file
raising inside an analyzer that otherwise completed — the per-file rescues in
Analyzer#parallel_analyze and Analyzer#scan_files exist precisely so one
unreadable or unparsable file costs only itself. That is the right
behaviour, but until now the only trace was a --debug line, so the result
of a scan that silently dropped a file was byte-identical to one that read
everything.
#2612 made that gap wider by adding a ceiling on parse time: a pathologically malformed file now raises and is skipped where it used to take the process down. Loud-and-fatal became quiet-and-partial, which is the better failure mode only if the "partial" part is visible somewhere.
The analysis pass was only ever half the story, though. A scan drops
coverage in six other places — an unlistable directory takes its whole
subtree, an oversize or unreadable or binary-looking file is filtered out, a
symlinked tree is never walked, an export never lands, -P runs with zero
rules loaded — and each of those had its own local counter, its own log
line, and no route into errors at all. So --strict (documented as "exit
2 if any analyzer failed or skipped a file") reported green on a scan that
had lost most of a codebase.
Rather than six more counters, they all record here. #failures is the one
list, errors in the output is that list, and degraded in the CLI is
"that list is not empty". Adding a seventh drop path is a #record call.
Tallied rather than listed one entry per file: a repository that trips this
usually trips it in bulk (a vendored minified bundle, a generated tree), and
errors is part of the JSON/YAML/TOML output — one entry per tech with a
count and a few example paths says the same thing without letting a broken
checkout print thousands of lines.
Extended Modules
Defined in:
models/skipped_files.crConstant Summary
-
DELIVER_SCOPE =
"deliver" -
DETECT_SCOPE =
"detect" -
Labels for the drop paths that belong to no analyzer. They land in the same
errors[].techfield a real tech name would, because the field answers the same question either way: which part of the scan came up short. -
MAX_PATHS_PER_TECH =
5 -
Example paths kept per tech. Beyond this only the count grows.
-
PASSIVE_SCAN_SCOPE =
"passive-scan"
Instance Method Summary
- #clear(phase : Phase) : Nil
-
#clear : Nil
Drops everything, both phases.
-
#count : Int32
Total files (and directories, and symlinks) skipped since the last
#clear, across every scope. - #failures(phase : Phase) : Array(AnalyzerFailure)
-
#failures : Array(AnalyzerFailure)
One
AnalyzerFailureper tally plus one per recorded gap, so a dropped file, an unwalked directory and an undelivered export all land in the sameerrorsarray — and the same--strictexit code — as a dropped analyzer. -
#record(tech : String, path : String, reason : String, noun : String = "file", phase : Phase = Phase::Analysis) : Nil
techmay be empty —Analyzer's owntechreturns""and onlyanalyzer_forfills it in, so a base-class caller is still recorded, just unattributed. -
#record_gap(scope : String, message : String, phase : Phase = Phase::Scan) : Nil
One-off coverage gap, reported as written.
Instance Method Detail
Drops everything, both phases. Used by specs and by library callers that want a clean slate; production code clears one phase at a time.
Total files (and directories, and symlinks) skipped since the last
#clear, across every scope. Excludes #record_gap entries, which count
no items.
One AnalyzerFailure per tally plus one per recorded gap, so a dropped
file, an unwalked directory and an undelivered export all land in the
same errors array — and the same --strict exit code — as a dropped
analyzer.
tech may be empty — Analyzer's own tech returns "" and only
analyzer_for fills it in, so a base-class caller is still recorded,
just unattributed.
noun names what was dropped so the message reads true for callers that
skip something other than a file — a directory that would not list, a
symlink that is not followed.