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 +4 -4
- data/CHANGELOG.md +5 -0
- data/README.md +26 -4
- data/lib/quality_gate/installation.rb +8 -0
- data/lib/quality_gate/reporters/text.rb +22 -0
- data/lib/quality_gate/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5c2f18d9b5a74e7d19838e915bb21ab23fe18cb1d2179e0279ec848dec71e9ee
|
|
4
|
+
data.tar.gz: 8f6d82509a688cf01fb92186caca89a4c330470e05b9a5fb3200fa4c28339b55
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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
|
|
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")
|
data/lib/quality_gate/version.rb
CHANGED