quality_gate 0.1.0 → 0.1.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b549f0b3f39f5a51bc4c1321a8b0771ae355f4ad1a8da733e6f5cf9c8209a54e
4
- data.tar.gz: a0adfdf9647271909cac928c6056ee59114a5eefee5c8173c4ecf8816bbbb5ba
3
+ metadata.gz: 5c2f18d9b5a74e7d19838e915bb21ab23fe18cb1d2179e0279ec848dec71e9ee
4
+ data.tar.gz: 8f6d82509a688cf01fb92186caca89a4c330470e05b9a5fb3200fa4c28339b55
5
5
  SHA512:
6
- metadata.gz: 6f58b91553cbf70f2224831b4c21f8b2aa279a3e76dba5638445c2d11982363d4820a8d70b54b99fcc83d5b97e1d898292e472c0427b7f2e34c764b2979ab796
7
- data.tar.gz: eb7bbe5a088b832b60f28751f6dfd1009a4d6ed1ce291e42c27dcd2abbbb9ccc1310e4d45992bff589723aaf1dd37c47ff9763f1edb5599aace9fbc730621d0e
6
+ metadata.gz: '0938c529aa703c3e0cdeaad45996e715a58b0554f4b87483d1741816056a10012567ef00410d287d15fe8d39996bf99a7cb750101275ec9b7423a044a2bf5e3d'
7
+ data.tar.gz: 5d822362f3278a6d219401b65379b1d4217e28db160991e7014c25e6a45403c5bd2c1f62df5766d50105d5ae40e80c50c02b5e54619ed0169dc0db723c271d77
data/CHANGELOG.md CHANGED
@@ -1,3 +1,8 @@
1
+ ## [0.1.1] - 2026-09-10
2
+
3
+ - Text gate output now lists each tool that ran with its status, scope, and duration, so a clean run is distinguishable from a run where nothing executed.
4
+ - The installer no longer injects a coverage block into a test helper that already calls `SimpleCov.start`; it reports the skip and names what to confirm.
5
+
1
6
  ## [0.1.0] - 2026-09-08
2
7
 
3
8
  - Layered fast, verify, and audit gates with structured findings for Ruby projects.
data/README.md CHANGED
@@ -45,19 +45,31 @@ The built-in fast path is meant for changed files:
45
45
  bundle exec quality_gate fast --files app/models/user.rb
46
46
  ```
47
47
 
48
- `verify` records coverage while it runs the full test suite, then checks changed code with Undercover. A clean `verify` or `audit` run prints this clean summary:
48
+ `verify` records coverage while it runs the full test suite, then checks changed code with Undercover. A clean `verify` or `audit` run prints this clean summary: one line per tool that ran, naming its status, scope, and duration, then the tally:
49
49
 
50
50
  ```text
51
+ reek clean project 312ms
52
+ test_suite clean test_suite 189137ms
53
+ undercover clean git_diff 619ms
51
54
  0 findings, 0 tool failures
52
55
  ```
53
56
 
57
+ (Durations above are illustrative, not measured figures.) These tool lines make a clean run visible: you see every tool that ran, not just an absence of findings.
58
+
54
59
  Use `--files` to select paths for RuboCop and Reek; the first path follows the option and further paths follow it as separate arguments:
55
60
 
56
61
  ```sh
57
62
  bundle exec quality_gate fast --files lib/quality_gate.rb test/test_quality_gate.rb
58
63
  ```
59
64
 
60
- Paths must exist, including paths from the configuration file. Any missing path returns exit `2` before tools run. A bare `fast` scans the project; it does not discover changed files automatically.
65
+ Paths must exist, including paths from the configuration file. Any missing path returns exit `2` before tools run. A bare `fast` scans the project; it does not discover changed files automatically. RuboCop is the only default fast adapter, so a clean bare `fast` run prints one tool line then the tally:
66
+
67
+ ```text
68
+ rubocop clean project 842ms
69
+ 0 findings, 0 tool failures
70
+ ```
71
+
72
+ (842ms above is illustrative, not a measured figure.)
61
73
 
62
74
  | Adapter | Scope with `--files` |
63
75
  | --- | --- |
@@ -82,13 +94,23 @@ The repository config must also use exactly `text` or `json` for `format`; any o
82
94
 
83
95
  ## Output contract
84
96
 
85
- Gate text output includes tool, severity, location when available, rule, and message:
97
+ Gate text output prints, in order: one line per tool that ran, then findings, then the tally.
98
+
99
+ When at least one tool ran, each gets a line naming the tool, its status, what it inspected, and how long it took:
100
+
101
+ ```text
102
+ <tool> <status> <scope> <duration>ms
103
+ ```
104
+
105
+ `status` is `clean`, `findings`, `tool_failure`, or `skipped`; `scope` describes what the tool inspected, such as `project`, `selected_files`, `git_diff`, `test_suite`, `coverage_summary`, or `lockfile`. These lines distinguish a clean run, which always names its tools, from a run where nothing executed. An empty adapter list runs no tools and prints none of these lines.
106
+
107
+ Findings come next, with tool, severity, location when available, rule, and message:
86
108
 
87
109
  ```text
88
110
  <tool> <severity> <file>:<line> <rule> <message>
89
111
  ```
90
112
 
91
- Multiline messages retain indented detail lines. Findings without a source location omit it rather than printing `:0`. The final gate output line is the summary:
113
+ Multiline messages retain indented detail lines. Findings without a source location omit it rather than printing `:0`. The final gate output line is unchanged, the summary:
92
114
 
93
115
  ```text
94
116
  <n> findings, <m> tool failures
@@ -22,6 +22,7 @@ module QualityGate
22
22
  ].freeze
23
23
  MARKER_START = "# quality_gate coverage — start"
24
24
  MARKER_END = "# quality_gate coverage — end"
25
+ EXISTING_SIMPLECOV_START = /SimpleCov\s*\.\s*start\b/
25
26
  AGENT_CONTRACT_START = "<!-- quality_gate agent contract — start -->"
26
27
  AGENT_CONTRACT_END = "<!-- quality_gate agent contract — end -->"
27
28
  AGENT_TEMPLATE_PATHS = {
@@ -424,6 +425,7 @@ module QualityGate
424
425
  def install_coverage(path, relative_path)
425
426
  original = File.binread(path)
426
427
  return record(:unchanged, relative_path) if original.include?(MARKER_START.b)
428
+ return skip_existing_simplecov(relative_path) if EXISTING_SIMPLECOV_START.match?(original)
427
429
  return record_pretend_skip(relative_path) if options[:pretend]
428
430
 
429
431
  content = content_with_coverage(original)
@@ -659,6 +661,12 @@ module QualityGate
659
661
  record(:skipped, "test/test_helper.rb (missing; Minitest coverage wiring skipped)")
660
662
  end
661
663
 
664
+ def skip_existing_simplecov(relative_path)
665
+ say "Warning: coverage wiring skipped; #{relative_path} already calls SimpleCov.start. " \
666
+ "Confirm it enables branch coverage and loads the Undercover formatter."
667
+ record(:skipped, "#{relative_path} (already starts SimpleCov; coverage wiring skipped)")
668
+ end
669
+
662
670
  def record_pretend_skip(relative_path)
663
671
  record(:skipped, "#{relative_path} (pretend)")
664
672
  end
@@ -9,6 +9,8 @@ module QualityGate
9
9
  end
10
10
 
11
11
  def call(result)
12
+ print_checks(result.checks)
13
+
12
14
  result.findings.each do |finding|
13
15
  io.puts(render_finding(finding))
14
16
  end
@@ -20,6 +22,26 @@ module QualityGate
20
22
 
21
23
  attr_reader :io
22
24
 
25
+ def print_checks(checks)
26
+ return if checks.empty?
27
+
28
+ checks.each { |check| io.puts(render_check(check)) }
29
+ end
30
+
31
+ def render_check(check)
32
+ format(
33
+ "%<tool>-12s %<status>-12s %<scope>-18s %<duration>8dms",
34
+ tool: FieldSanitizer.for_text(check[:tool]),
35
+ status: FieldSanitizer.for_text(check[:status]),
36
+ scope: FieldSanitizer.for_text(check[:scope]),
37
+ duration: duration_ms_for(check)
38
+ )
39
+ end
40
+
41
+ def duration_ms_for(check)
42
+ Integer(check[:duration_ms], exception: false) || 0
43
+ end
44
+
23
45
  def render_finding(finding)
24
46
  lines = FieldSanitizer.for_text_message(finding.message).split("\n", -1)
25
47
  ["#{finding_prefix(finding)} #{lines.first}", *lines.drop(1).map { " #{_1}" }].join("\n")
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module QualityGate
4
- VERSION = "0.1.0"
4
+ VERSION = "0.1.1"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: quality_gate
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lucian Ghinda