specguard-ruby 0.3.10 → 0.3.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/specguard/rspec/cli.rb +72 -11
- data/lib/specguard/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a48430615dad6103c9c66ef9a7e78d5f4fabdcf460a2321d4f3b03bb0d096fe5
|
|
4
|
+
data.tar.gz: 68100f41f50db5a7bc0067a6afb79823498aeae6bf6ef0fff0b5d04ff4b3b672
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ffeaa97c7b965463b5efd30a3273101f029dca4a0de18d2af6dbcd6664dacdc42e49bda907ae02d8d33c3a7bd3b5c9716c47c1a0469122c438dd751f146ba6b0
|
|
7
|
+
data.tar.gz: 8745018c339d7073e30e720771a9e4cea8df251a9681e35d536c3015e9e0b5990c55ccba7b9807cb156fd2b69d13834cf62ef9899c9f5740629ee360445df92d
|
data/lib/specguard/rspec/cli.rb
CHANGED
|
@@ -156,7 +156,11 @@ module SpecGuard
|
|
|
156
156
|
# `ok` is derived FROM it rather than recomputed from the findings, so
|
|
157
157
|
# the two renderers cannot disagree about whether the run passed.
|
|
158
158
|
code = results.any?(&:failed?) ? EXIT_MALFORMED : EXIT_OK
|
|
159
|
-
|
|
159
|
+
# The selection's file LIST rides along (the `files:` count stays what
|
|
160
|
+
# the document's summary consumes) because the coverage note is about
|
|
161
|
+
# which files were checked, not how many.
|
|
162
|
+
report_results(results, files: selection.count, selected_files: selection.files,
|
|
163
|
+
json: options[:json], ok: code == EXIT_OK)
|
|
160
164
|
|
|
161
165
|
code
|
|
162
166
|
rescue UsageError, ValidatorError => e
|
|
@@ -225,9 +229,18 @@ module SpecGuard
|
|
|
225
229
|
#
|
|
226
230
|
# Under `--json` the count is not dropped, it MOVES: stdout carries one
|
|
227
231
|
# document and nothing else, and this line's number is that document's
|
|
228
|
-
# `summary.files`. The
|
|
229
|
-
#
|
|
230
|
-
#
|
|
232
|
+
# `summary.files`. The sentence branches by STREAM, not by content: the
|
|
233
|
+
# human renderer reads it on stdout, the json renderer on stderr, where
|
|
234
|
+
# diagnostics about the linter already live — the empty-selection
|
|
235
|
+
# warning is the precedent, SPGD-247 the doctrine. (SPGD-1134: this was
|
|
236
|
+
# an `elsif !json` suppression, which left a json run's selection
|
|
237
|
+
# unverifiable — the machine channel named neither its resolved base nor
|
|
238
|
+
# its untracked leg, so the bridge, which passes `--json`
|
|
239
|
+
# unconditionally, could only verify the diff ∪ untracked union by
|
|
240
|
+
# arithmetic on `summary.files`.) The warnings below are diagnostics
|
|
241
|
+
# about the linter rather than findings, so they stay on stderr exactly
|
|
242
|
+
# as they are — a run that selected nothing is still loud, in both
|
|
243
|
+
# renderers.
|
|
231
244
|
#
|
|
232
245
|
# The `--changed` count names its provenance: files can reach the
|
|
233
246
|
# selection through the untracked leg (`file_selector.rb`), and "changed
|
|
@@ -239,15 +252,24 @@ module SpecGuard
|
|
|
239
252
|
if selection.empty?
|
|
240
253
|
@stderr.puts "specguard-lint: warning: selected 0 spec files — #{empty_reason(selection)}"
|
|
241
254
|
@stderr.puts "specguard-lint: warning: #{selection.note}" if selection.note
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
@stdout.puts "specguard-lint: checked #{selection.count} spec file#{'s' unless selection.count == 1}" \
|
|
245
|
-
"#{" changed since #{selection.base}" if selection.mode == :changed}" \
|
|
246
|
-
"#{" under #{Dir.pwd}" if selection.mode == :all}" \
|
|
247
|
-
"#{" including #{untracked} untracked" if untracked.positive?}"
|
|
255
|
+
else
|
|
256
|
+
json ? @stderr.puts(selection_line(selection)) : @stdout.puts(selection_line(selection))
|
|
248
257
|
end
|
|
249
258
|
end
|
|
250
259
|
|
|
260
|
+
# The selection sentence, built at exactly one site and written by both
|
|
261
|
+
# renderers — only the stream differs. The human line is the contract
|
|
262
|
+
# of record; the json renderer printing the SAME bytes is what makes
|
|
263
|
+
# "the machine reads the provenance the human does" a property of the
|
|
264
|
+
# code rather than a promise two copies could drift apart on.
|
|
265
|
+
def selection_line(selection)
|
|
266
|
+
untracked = selection.mode == :changed ? selection.stats&.untracked.to_i : 0
|
|
267
|
+
"specguard-lint: checked #{selection.count} spec file#{'s' unless selection.count == 1}" \
|
|
268
|
+
"#{" changed since #{selection.base}" if selection.mode == :changed}" \
|
|
269
|
+
"#{" under #{Dir.pwd}" if selection.mode == :all}" \
|
|
270
|
+
"#{" including #{untracked} untracked" if untracked.positive?}"
|
|
271
|
+
end
|
|
272
|
+
|
|
251
273
|
# `:explicit` is absent by construction — an explicit Selection is only
|
|
252
274
|
# built from a non-empty file list, so it can never be empty.
|
|
253
275
|
def empty_reason(selection)
|
|
@@ -337,9 +359,11 @@ module SpecGuard
|
|
|
337
359
|
# statements about the same numbers, and a linter whose two renderers can
|
|
338
360
|
# disagree about how much it checked is worse than one that only prints
|
|
339
361
|
# prose: the disagreement is unfalsifiable from outside the process.
|
|
340
|
-
def report_results(results, files:, json:, ok:)
|
|
362
|
+
def report_results(results, files:, selected_files:, json:, ok:)
|
|
341
363
|
annotations, unread = results.partition(&:line_scoped?)
|
|
342
364
|
|
|
365
|
+
report_zero_annotation_files(selected_files, annotations, unread)
|
|
366
|
+
|
|
343
367
|
if json
|
|
344
368
|
@stdout.puts JSONReporter.render(results, files: files, annotations: annotations.length, ok: ok)
|
|
345
369
|
return
|
|
@@ -350,6 +374,43 @@ module SpecGuard
|
|
|
350
374
|
@stdout.puts summary_line(annotations, unread)
|
|
351
375
|
end
|
|
352
376
|
|
|
377
|
+
# The coverage note: which of the checked files were read and yielded no
|
|
378
|
+
# `@intent` annotation at all. Zero findings on stdout (or an empty
|
|
379
|
+
# `findings` list in the document) is otherwise ambiguous between
|
|
380
|
+
# "every checked file was annotated and valid" and "half the checked
|
|
381
|
+
# files carry nothing" — and the missing-annotation question is the most
|
|
382
|
+
# actionable one this tool touches, because the bridge agent reading
|
|
383
|
+
# `linter_stderr` has no other view into the repository's spec files.
|
|
384
|
+
#
|
|
385
|
+
# The boundary is the set-difference the partition above already
|
|
386
|
+
# supports: a file counts as covered when it yielded any line-scoped
|
|
387
|
+
# result (an annotation, valid or not — the SPGD-900 unreachable findings
|
|
388
|
+
# are line-scoped too and require an annotation to exist, so they cover
|
|
389
|
+
# their file) or when it could not be read at all (KIND_READ → `unread`).
|
|
390
|
+
# An unread file is NOT a zero-annotation file: it already gets its own
|
|
391
|
+
# summary clause and FAIL line, and calling it annotation-free would be
|
|
392
|
+
# the same overstatement `summary_line` refuses to make. Unreachable
|
|
393
|
+
# findings need a stacked annotation — impossible in a file with none —
|
|
394
|
+
# so `annotations ∪ unread` already covers every non-bare file and no
|
|
395
|
+
# third subtraction is needed.
|
|
396
|
+
#
|
|
397
|
+
# It is a NOTE on stderr, never a warning and never an exit code: "lint,
|
|
398
|
+
# don't require" (SPGD-12 §1) keeps a missing annotation a non-error.
|
|
399
|
+
# It is emitted before the json early-return so both renderers get it —
|
|
400
|
+
# stderr is renderer-indifferent (SPGD-247; the SPGD-1134 selection
|
|
401
|
+
# sentence is the landed precedent, and the bridge forwards stderr
|
|
402
|
+
# verbatim as `linter_stderr`). The prefix is deliberately not
|
|
403
|
+
# `specguard-lint: checked`, which the selection-sentence pin counts.
|
|
404
|
+
def report_zero_annotation_files(selected_files, annotations, unread)
|
|
405
|
+
bare = selected_files - annotations.map(&:file) - unread.map(&:file)
|
|
406
|
+
return if bare.empty?
|
|
407
|
+
|
|
408
|
+
verb = bare.length == 1 ? "carries" : "carry"
|
|
409
|
+
@stderr.puts "specguard-lint: note: #{bare.length} of #{selected_files.length} checked " \
|
|
410
|
+
"spec file#{'s' unless selected_files.length == 1} #{verb} no @intent " \
|
|
411
|
+
"annotations: #{bare.join(', ')}"
|
|
412
|
+
end
|
|
413
|
+
|
|
353
414
|
# The summary line exists for one reason — so "checked nothing" can never
|
|
354
415
|
# read as "all clean" — which makes overstating what was inspected its
|
|
355
416
|
# own kind of lie. A file that could not be opened contributed no
|
data/lib/specguard/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: specguard-ruby
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.3.
|
|
4
|
+
version: 0.3.12
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- specguard Agent
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-09-
|
|
11
|
+
date: 2026-09-16 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: json
|