goodcheck 2.6.1 β 3.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +39 -0
- data/LICENSE +1 -1
- data/README.md +8 -2
- data/lib/goodcheck.rb +6 -3
- data/lib/goodcheck/analyzer.rb +13 -9
- data/lib/goodcheck/buffer.rb +9 -21
- data/lib/goodcheck/cli.rb +6 -8
- data/lib/goodcheck/commands/check.rb +24 -28
- data/lib/goodcheck/commands/config_loading.rb +11 -5
- data/lib/goodcheck/commands/test.rb +35 -28
- data/lib/goodcheck/config.rb +68 -1
- data/lib/goodcheck/config_loader.rb +36 -27
- data/lib/goodcheck/exit_status.rb +2 -0
- data/lib/goodcheck/import_loader.rb +72 -20
- data/lib/goodcheck/issue.rb +3 -3
- data/lib/goodcheck/location.rb +28 -0
- data/lib/goodcheck/logger.rb +4 -4
- data/lib/goodcheck/reporters/json.rb +6 -1
- data/lib/goodcheck/reporters/text.rb +44 -11
- data/lib/goodcheck/rule.rb +3 -1
- data/lib/goodcheck/unarchiver.rb +40 -0
- data/lib/goodcheck/version.rb +1 -1
- metadata +42 -30
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b382336bf78153607e3951bdafe7d819ebac80b080df118fcf3c2b15a25040db
|
4
|
+
data.tar.gz: b17ec056b4d49b70d777a90142b40dd4d17dcb50d9e5861f88cdb37c0eaeff0e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5eaa08336a26a7adb83a0100dd48937395b11a3ee0da758a869940d0e741fa515c5eabc9bef9bf6f6eb1d39d69141014e5c64b0868594fb2bf983ccec7f203c9
|
7
|
+
data.tar.gz: 52a89b2342b9d6785d7ecfb847174d36cccba6bbd33c073520dcc4f65569a2579fb0879e59048aa41de8cd5cd00bc1b07c95784fe53f4b2ed2e1cb05417b4ff8
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,45 @@
|
|
2
2
|
|
3
3
|
## HEAD
|
4
4
|
|
5
|
+
## 3.0.3 (2021-06-25)
|
6
|
+
|
7
|
+
* Fix HTTP GET retrying [#203](https://github.com/sider/goodcheck/pull/203)
|
8
|
+
|
9
|
+
## 3.0.2 (2021-06-23)
|
10
|
+
|
11
|
+
* Retry importing on Net::OpenTimeout [#202](https://github.com/sider/goodcheck/pull/202)
|
12
|
+
|
13
|
+
## 3.0.1 (2021-06-14)
|
14
|
+
|
15
|
+
* Retry HTTP GET request on importing rules [#197](https://github.com/sider/goodcheck/pull/197)
|
16
|
+
|
17
|
+
## 3.0.0 (2021-06-14)
|
18
|
+
|
19
|
+
Breaking changes:
|
20
|
+
|
21
|
+
* Drop support of Ruby 2.4 [#169](https://github.com/sider/goodcheck/pull/169)
|
22
|
+
* `goodcheck test` exit with `3` on tests failed [#168](https://github.com/sider/goodcheck/pull/168)
|
23
|
+
(a potentially breaking change; the command previously exited with `1`)
|
24
|
+
|
25
|
+
Features:
|
26
|
+
|
27
|
+
* Import `.tar.gz` files [#190](https://github.com/sider/goodcheck/pull/190)
|
28
|
+
* Introduce `exclude_binary` option [#195](https://github.com/sider/goodcheck/pull/195)
|
29
|
+
* Add rule severity [#172](https://github.com/sider/goodcheck/pull/172)
|
30
|
+
|
31
|
+
Bugfixes and others:
|
32
|
+
|
33
|
+
* Update gemspec [#176](https://github.com/sider/goodcheck/pull/176)
|
34
|
+
* Update `psych` requirement allowing 4.0 [#183](https://github.com/sider/goodcheck/pull/183)
|
35
|
+
* Improve output error message on `RegexpError` [#188](https://github.com/sider/goodcheck/pull/188)
|
36
|
+
* Fix importing error with extended glob [#194](https://github.com/sider/goodcheck/pull/194)
|
37
|
+
|
38
|
+
## 2.7.0 (2020-12-02)
|
39
|
+
|
40
|
+
* Goodbye ActiveSupport [#155](https://github.com/sider/goodcheck/pull/155)
|
41
|
+
* Fix zero column [#160](https://github.com/sider/goodcheck/pull/160)
|
42
|
+
* Improve text reporter [#161](https://github.com/sider/goodcheck/pull/161)
|
43
|
+
|
5
44
|
## 2.6.1 (2020-11-19)
|
6
45
|
|
7
46
|
* Add missing doc for importing glob feature [#151](https://github.com/sider/goodcheck/pull/151)
|
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -21,7 +21,13 @@ Goodcheck is provided as a Ruby gem. To install it, run:
|
|
21
21
|
$ gem install goodcheck
|
22
22
|
```
|
23
23
|
|
24
|
-
|
24
|
+
If you do not want to install it, you can run it via Docker instead:
|
25
|
+
|
26
|
+
```console
|
27
|
+
$ docker run -t --rm -v "$(pwd):/work" sider/goodcheck
|
28
|
+
```
|
29
|
+
|
30
|
+
Check out the [documentation](docusaurus/docs/getstarted.md) or [website](https://sider.github.io/goodcheck/) for more details.
|
25
31
|
|
26
32
|
## Development
|
27
33
|
|
@@ -36,7 +42,7 @@ To release a new version, follows the steps below:
|
|
36
42
|
3. Update the documentation via `bundle exec rake docs:update_version`.
|
37
43
|
4. Commit the above changes like `git commit -m 'Version 1.2.3'`.
|
38
44
|
5. Run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
39
|
-
6. Publish the updated documentation like `GIT_USER=some_user USE_SSH=true bundle exec rake docs:publish`.
|
45
|
+
6. Publish the updated documentation like `GIT_USER=some_user [USE_SSH=true] bundle exec rake docs:publish`.
|
40
46
|
|
41
47
|
## Contributing
|
42
48
|
|
data/lib/goodcheck.rb
CHANGED
@@ -4,9 +4,7 @@ require "set"
|
|
4
4
|
require "strong_json"
|
5
5
|
require "yaml"
|
6
6
|
require "json"
|
7
|
-
require "
|
8
|
-
require "active_support/core_ext/integer/inflections"
|
9
|
-
require "active_support/tagged_logging"
|
7
|
+
require "logger"
|
10
8
|
require "rainbow"
|
11
9
|
require "digest/sha2"
|
12
10
|
require "net/http"
|
@@ -35,3 +33,8 @@ require "goodcheck/commands/init"
|
|
35
33
|
require "goodcheck/commands/test"
|
36
34
|
require "goodcheck/import_loader"
|
37
35
|
require "goodcheck/commands/pattern"
|
36
|
+
require "goodcheck/unarchiver"
|
37
|
+
|
38
|
+
module Goodcheck
|
39
|
+
DEFAULT_CONFIG_FILE = "goodcheck.yml".freeze
|
40
|
+
end
|
data/lib/goodcheck/analyzer.rb
CHANGED
@@ -13,7 +13,7 @@ module Goodcheck
|
|
13
13
|
def scan(&block)
|
14
14
|
if block_given?
|
15
15
|
if trigger.patterns.empty?
|
16
|
-
yield Issue.new(buffer: buffer,
|
16
|
+
yield Issue.new(buffer: buffer, rule: rule)
|
17
17
|
else
|
18
18
|
var_pats, novar_pats = trigger.patterns.partition {|pat|
|
19
19
|
pat.is_a?(Pattern::Token) && !pat.variables.empty?
|
@@ -44,9 +44,7 @@ module Goodcheck
|
|
44
44
|
while true
|
45
45
|
case
|
46
46
|
when scanner.scan_until(regexp)
|
47
|
-
|
48
|
-
range = (scanner.pos - text.bytesize) .. scanner.pos
|
49
|
-
issues << Issue.new(buffer: buffer, range: range, rule: rule, text: text)
|
47
|
+
issues << new_issue_with_matched(scanner)
|
50
48
|
else
|
51
49
|
break
|
52
50
|
end
|
@@ -55,7 +53,7 @@ module Goodcheck
|
|
55
53
|
issues.each(&block)
|
56
54
|
else
|
57
55
|
unless regexp =~ buffer.content
|
58
|
-
yield Issue.new(buffer: buffer,
|
56
|
+
yield Issue.new(buffer: buffer, rule: rule)
|
59
57
|
end
|
60
58
|
end
|
61
59
|
end
|
@@ -68,9 +66,7 @@ module Goodcheck
|
|
68
66
|
case
|
69
67
|
when scanner.scan_until(pat.regexp)
|
70
68
|
if pat.test_variables(scanner)
|
71
|
-
|
72
|
-
range = (scanner.pos - text.bytesize) .. scanner.pos
|
73
|
-
yield Issue.new(buffer: buffer, range: range, rule: rule, text: text)
|
69
|
+
yield new_issue_with_matched(scanner)
|
74
70
|
end
|
75
71
|
else
|
76
72
|
break
|
@@ -84,11 +80,19 @@ module Goodcheck
|
|
84
80
|
break
|
85
81
|
end
|
86
82
|
else
|
87
|
-
yield Issue.new(buffer: buffer,
|
83
|
+
yield Issue.new(buffer: buffer, rule: rule)
|
88
84
|
break
|
89
85
|
end
|
90
86
|
end
|
91
87
|
end
|
92
88
|
end
|
89
|
+
|
90
|
+
private
|
91
|
+
|
92
|
+
def new_issue_with_matched(scanner)
|
93
|
+
Issue.new(buffer: buffer, rule: rule,
|
94
|
+
text: scanner.matched,
|
95
|
+
text_begin_pos: scanner.pos - scanner.matched_size)
|
96
|
+
end
|
93
97
|
end
|
94
98
|
end
|
data/lib/goodcheck/buffer.rb
CHANGED
@@ -1,8 +1,5 @@
|
|
1
1
|
module Goodcheck
|
2
2
|
class Buffer
|
3
|
-
attr_reader :path
|
4
|
-
attr_reader :content
|
5
|
-
|
6
3
|
DISABLE_LINE_PATTERNS = [
|
7
4
|
/\/\/ goodcheck-disable-line$/, #JS, Java, C, ...
|
8
5
|
/# goodcheck-disable-line$/, # Ruby, Python, PHP, ...
|
@@ -25,10 +22,8 @@ module Goodcheck
|
|
25
22
|
/' goodcheck-disable-next-line$/, # VB
|
26
23
|
].freeze
|
27
24
|
|
28
|
-
|
29
|
-
|
30
|
-
attr_accessor :DISABLE_NEXT_LINE_PATTERNS
|
31
|
-
end
|
25
|
+
attr_reader :path
|
26
|
+
attr_reader :content
|
32
27
|
|
33
28
|
def initialize(path:, content:)
|
34
29
|
@path = path
|
@@ -43,7 +38,7 @@ module Goodcheck
|
|
43
38
|
start_position = 0
|
44
39
|
|
45
40
|
content.split(/\n/, -1).each do |line|
|
46
|
-
range = start_position
|
41
|
+
range = start_position..(start_position + line.bytesize)
|
47
42
|
@line_ranges << range
|
48
43
|
start_position = range.end + 1
|
49
44
|
end
|
@@ -51,10 +46,10 @@ module Goodcheck
|
|
51
46
|
|
52
47
|
@line_ranges
|
53
48
|
end
|
54
|
-
|
49
|
+
|
55
50
|
def line_disabled?(line_number)
|
56
51
|
if line_number > 1
|
57
|
-
return true if DISABLE_NEXT_LINE_PATTERNS.any? { |pattern| line(line_number - 1).match?(pattern) }
|
52
|
+
return true if DISABLE_NEXT_LINE_PATTERNS.any? { |pattern| line(line_number - 1).match?(pattern) }
|
58
53
|
end
|
59
54
|
|
60
55
|
if line_number <= lines.length
|
@@ -70,7 +65,9 @@ module Goodcheck
|
|
70
65
|
end
|
71
66
|
|
72
67
|
if line_index
|
73
|
-
|
68
|
+
line_number = line_index + 1
|
69
|
+
column_number = position - line_ranges[line_index].begin + 1
|
70
|
+
[line_number, column_number]
|
74
71
|
end
|
75
72
|
end
|
76
73
|
|
@@ -79,16 +76,7 @@ module Goodcheck
|
|
79
76
|
end
|
80
77
|
|
81
78
|
def line(line_number)
|
82
|
-
lines[line_number-1]
|
83
|
-
end
|
84
|
-
|
85
|
-
def position_for_location(line, column)
|
86
|
-
if (range = line_ranges[line-1])
|
87
|
-
pos = range.begin + column
|
88
|
-
if pos <= range.end
|
89
|
-
pos
|
90
|
-
end
|
91
|
-
end
|
79
|
+
lines[line_number - 1]
|
92
80
|
end
|
93
81
|
end
|
94
82
|
end
|
data/lib/goodcheck/cli.rb
CHANGED
@@ -21,8 +21,6 @@ module Goodcheck
|
|
21
21
|
help: "Show help and quit"
|
22
22
|
}.freeze
|
23
23
|
|
24
|
-
DEFAULT_CONFIG_FILE = Pathname("goodcheck.yml").freeze
|
25
|
-
|
26
24
|
def run(args)
|
27
25
|
command = args.shift&.to_sym
|
28
26
|
|
@@ -58,12 +56,12 @@ module Goodcheck
|
|
58
56
|
end
|
59
57
|
|
60
58
|
def check(args)
|
61
|
-
config_path = DEFAULT_CONFIG_FILE
|
59
|
+
config_path = Pathname(DEFAULT_CONFIG_FILE)
|
62
60
|
targets = []
|
63
61
|
rules = []
|
64
62
|
formats = [:text, :json]
|
65
63
|
format = :text
|
66
|
-
loglevel =
|
64
|
+
loglevel = nil
|
67
65
|
force_download = false
|
68
66
|
|
69
67
|
OptionParser.new("Usage: goodcheck check [options] paths...") do |opts|
|
@@ -82,7 +80,7 @@ module Goodcheck
|
|
82
80
|
end
|
83
81
|
end.parse!(args)
|
84
82
|
|
85
|
-
Goodcheck.logger.level = loglevel
|
83
|
+
Goodcheck.logger.level = loglevel if loglevel
|
86
84
|
|
87
85
|
if args.empty?
|
88
86
|
targets << Pathname(".")
|
@@ -110,7 +108,7 @@ module Goodcheck
|
|
110
108
|
end
|
111
109
|
|
112
110
|
def test(args)
|
113
|
-
config_path = DEFAULT_CONFIG_FILE
|
111
|
+
config_path = Pathname(DEFAULT_CONFIG_FILE)
|
114
112
|
loglevel = ::Logger::ERROR
|
115
113
|
force_download = false
|
116
114
|
|
@@ -132,7 +130,7 @@ module Goodcheck
|
|
132
130
|
end
|
133
131
|
|
134
132
|
def init(args)
|
135
|
-
config_path = DEFAULT_CONFIG_FILE
|
133
|
+
config_path = Pathname(DEFAULT_CONFIG_FILE)
|
136
134
|
force = false
|
137
135
|
|
138
136
|
OptionParser.new("Usage: goodcheck init [options]") do |opts|
|
@@ -163,7 +161,7 @@ module Goodcheck
|
|
163
161
|
end
|
164
162
|
|
165
163
|
def pattern(args)
|
166
|
-
config_path = DEFAULT_CONFIG_FILE
|
164
|
+
config_path = Pathname(DEFAULT_CONFIG_FILE)
|
167
165
|
|
168
166
|
OptionParser.new do |opts|
|
169
167
|
opts.banner = "Usage: goodcheck pattern [options] ids..."
|
@@ -15,8 +15,6 @@ module Goodcheck
|
|
15
15
|
include HomePath
|
16
16
|
include ExitStatus
|
17
17
|
|
18
|
-
EXIT_MATCH = 2
|
19
|
-
|
20
18
|
def initialize(config_path:, rules:, targets:, reporter:, stderr:, home_path:, force_download:)
|
21
19
|
@config_path = config_path
|
22
20
|
@rules = rules
|
@@ -57,6 +55,8 @@ module Goodcheck
|
|
57
55
|
end
|
58
56
|
end
|
59
57
|
|
58
|
+
reporter.summary
|
59
|
+
|
60
60
|
issue_reported ? EXIT_MATCH : EXIT_SUCCESS
|
61
61
|
end
|
62
62
|
end
|
@@ -71,31 +71,27 @@ module Goodcheck
|
|
71
71
|
def each_check
|
72
72
|
targets.each do |target|
|
73
73
|
Goodcheck.logger.info "Checking target: #{target}"
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
buffer = Buffer.new(path: path, content: content)
|
91
|
-
buffers[encoding] = buffer
|
92
|
-
end
|
93
|
-
|
94
|
-
yield buffer, rule, trigger
|
95
|
-
rescue ArgumentError => exn
|
96
|
-
stderr.puts "#{path}: #{exn.inspect}"
|
97
|
-
end
|
74
|
+
each_file target, immediate: true do |path|
|
75
|
+
Goodcheck.logger.debug "Checking file: #{path}"
|
76
|
+
reporter.file(path) do
|
77
|
+
buffers = {}
|
78
|
+
|
79
|
+
config.rules_for_path(path, rules_filter: rules) do |rule, glob, trigger|
|
80
|
+
Goodcheck.logger.debug "Checking rule: #{rule.id}"
|
81
|
+
begin
|
82
|
+
encoding = glob&.encoding || Encoding.default_external.name
|
83
|
+
|
84
|
+
if buffers[encoding]
|
85
|
+
buffer = buffers[encoding]
|
86
|
+
else
|
87
|
+
content = path.read(encoding: encoding).encode(Encoding.default_internal || Encoding::UTF_8)
|
88
|
+
buffer = Buffer.new(path: path, content: content)
|
89
|
+
buffers[encoding] = buffer
|
98
90
|
end
|
91
|
+
|
92
|
+
yield buffer, rule, trigger
|
93
|
+
rescue ArgumentError => exn
|
94
|
+
stderr.puts "#{path}: #{exn.inspect}"
|
99
95
|
end
|
100
96
|
end
|
101
97
|
end
|
@@ -112,7 +108,7 @@ module Goodcheck
|
|
112
108
|
when DEFAULT_EXCLUSIONS.include?(path.basename.to_s)
|
113
109
|
# noop
|
114
110
|
when immediate || !excluded?(path)
|
115
|
-
path.children.each do |child|
|
111
|
+
path.children.sort.each do |child|
|
116
112
|
each_file(child, &block)
|
117
113
|
end
|
118
114
|
end
|
@@ -131,7 +127,7 @@ module Goodcheck
|
|
131
127
|
end
|
132
128
|
|
133
129
|
def excluded?(path)
|
134
|
-
config.
|
130
|
+
config.exclude_path?(path)
|
135
131
|
end
|
136
132
|
end
|
137
133
|
end
|
@@ -1,10 +1,13 @@
|
|
1
1
|
module Goodcheck
|
2
2
|
module Commands
|
3
3
|
module ConfigLoading
|
4
|
+
include ExitStatus
|
5
|
+
|
4
6
|
class ConfigFileNotFound < Error
|
5
7
|
attr_reader :path
|
6
8
|
|
7
9
|
def initialize(path:)
|
10
|
+
super(path.to_s)
|
8
11
|
@path = path
|
9
12
|
end
|
10
13
|
end
|
@@ -20,7 +23,7 @@ module Goodcheck
|
|
20
23
|
end
|
21
24
|
|
22
25
|
import_loader = ImportLoader.new(cache_path: cache_path, force_download: force_download, config_path: config_path)
|
23
|
-
content = JSON.parse(JSON.dump(YAML.
|
26
|
+
content = JSON.parse(JSON.dump(YAML.safe_load(config_content, filename: config_path.to_s)), symbolize_names: true)
|
24
27
|
loader = ConfigLoader.new(path: config_path, content: content, stderr: stderr, import_loader: import_loader)
|
25
28
|
@config = loader.load
|
26
29
|
end
|
@@ -30,20 +33,23 @@ module Goodcheck
|
|
30
33
|
yield
|
31
34
|
rescue ConfigFileNotFound => exn
|
32
35
|
stderr.puts "Configuration file not found: #{exn.path}"
|
33
|
-
|
36
|
+
EXIT_ERROR
|
37
|
+
rescue ConfigLoader::InvalidPattern => exn
|
38
|
+
stderr.puts exn.message
|
39
|
+
EXIT_ERROR
|
34
40
|
rescue Psych::Exception => exn
|
35
41
|
stderr.puts "Unexpected error happens while loading YAML file: #{exn.inspect}"
|
36
42
|
exn.backtrace.each do |trace_loc|
|
37
43
|
stderr.puts " #{trace_loc}"
|
38
44
|
end
|
39
|
-
|
45
|
+
EXIT_ERROR
|
40
46
|
rescue StrongJSON::Type::TypeError, StrongJSON::Type::UnexpectedAttributeError => exn
|
41
47
|
stderr.puts "Invalid config: #{exn.message}"
|
42
48
|
stderr.puts StrongJSON::ErrorReporter.new(path: exn.path).to_s
|
43
|
-
|
49
|
+
EXIT_ERROR
|
44
50
|
rescue Errno::ENOENT => exn
|
45
51
|
stderr.puts "#{exn}"
|
46
|
-
|
52
|
+
EXIT_ERROR
|
47
53
|
end
|
48
54
|
end
|
49
55
|
end
|
@@ -28,15 +28,15 @@ module Goodcheck
|
|
28
28
|
return EXIT_SUCCESS
|
29
29
|
end
|
30
30
|
|
31
|
-
validate_rule_uniqueness or return
|
32
|
-
validate_rules or return
|
31
|
+
validate_rule_uniqueness or return EXIT_TEST_FAILED
|
32
|
+
validate_rules or return EXIT_TEST_FAILED
|
33
33
|
|
34
34
|
EXIT_SUCCESS
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
38
|
def validate_rule_uniqueness
|
39
|
-
stdout.puts "Validating rule
|
39
|
+
stdout.puts "Validating rule ID uniqueness..."
|
40
40
|
|
41
41
|
duplicated_ids = []
|
42
42
|
|
@@ -47,36 +47,35 @@ module Goodcheck
|
|
47
47
|
end
|
48
48
|
|
49
49
|
if duplicated_ids.empty?
|
50
|
-
stdout.puts " OK
|
50
|
+
stdout.puts Rainbow(" OK! π").green
|
51
51
|
true
|
52
52
|
else
|
53
53
|
count = duplicated_ids.size
|
54
|
-
|
54
|
+
duplication = count == 1 ? 'duplication' : 'duplications'
|
55
|
+
stdout.puts " Found #{Rainbow(count).bold} #{duplication}. π±"
|
55
56
|
duplicated_ids.each do |id|
|
56
|
-
stdout.puts " #{id}"
|
57
|
+
stdout.puts " - #{Rainbow(id).background(:red)}"
|
57
58
|
end
|
58
59
|
false
|
59
60
|
end
|
60
61
|
end
|
61
62
|
|
62
63
|
def validate_rules
|
63
|
-
test_pass = true
|
64
64
|
success_count = 0
|
65
|
-
failure_count = 0
|
66
65
|
failed_rule_ids = Set[]
|
67
66
|
|
68
67
|
config.rules.each do |rule|
|
69
|
-
|
70
|
-
stdout.puts "Testing rule #{Rainbow(rule.id).cyan}..."
|
68
|
+
stdout.puts "Testing rule #{Rainbow(rule.id).cyan}..."
|
71
69
|
|
72
|
-
|
70
|
+
rule_ok = true
|
73
71
|
|
72
|
+
if rule.triggers.any? {|trigger| !trigger.passes.empty? || !trigger.fails.empty?}
|
74
73
|
rule.triggers.each.with_index do |trigger, index|
|
75
74
|
if !trigger.passes.empty? || !trigger.fails.empty?
|
76
75
|
if trigger.by_pattern?
|
77
76
|
stdout.puts " Testing pattern..."
|
78
77
|
else
|
79
|
-
stdout.puts "
|
78
|
+
stdout.puts " #{index + 1}. Testing trigger..."
|
80
79
|
end
|
81
80
|
|
82
81
|
pass_errors = trigger.passes.each.with_index.select do |pass, _|
|
@@ -88,21 +87,19 @@ module Goodcheck
|
|
88
87
|
end
|
89
88
|
|
90
89
|
unless pass_errors.empty?
|
91
|
-
test_pass = false
|
92
90
|
rule_ok = false
|
93
91
|
|
94
92
|
pass_errors.each do |_, index|
|
95
|
-
stdout.puts " #{
|
93
|
+
stdout.puts " #{index + 1}. #{Rainbow('pass').green} example matched. π±"
|
96
94
|
failed_rule_ids << rule.id
|
97
95
|
end
|
98
96
|
end
|
99
97
|
|
100
98
|
unless fail_errors.empty?
|
101
|
-
test_pass = false
|
102
99
|
rule_ok = false
|
103
100
|
|
104
101
|
fail_errors.each do |_, index|
|
105
|
-
stdout.puts " #{
|
102
|
+
stdout.puts " #{index + 1}. #{Rainbow('fail').red} example didnβt match. π±"
|
106
103
|
failed_rule_ids << rule.id
|
107
104
|
end
|
108
105
|
end
|
@@ -110,16 +107,27 @@ module Goodcheck
|
|
110
107
|
end
|
111
108
|
|
112
109
|
if rule.triggers.any?(&:skips_fail_examples?)
|
113
|
-
stdout.puts "
|
110
|
+
stdout.puts " The rule contains a `pattern` with `glob`, which is not supported by the test command. π¨"
|
114
111
|
stdout.puts " Skips testing `fail` examples."
|
115
112
|
end
|
113
|
+
end
|
116
114
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
115
|
+
if rule.severity && !config.severity_allowed?(rule.severity)
|
116
|
+
allowed_severities = config.allowed_severities.map { |s| %("#{s}") }.join(', ')
|
117
|
+
stdout.puts Rainbow(" \"#{rule.severity}\" severity isnβt allowed. Must be one of #{allowed_severities}. π±").red
|
118
|
+
rule_ok = false
|
119
|
+
failed_rule_ids << rule.id
|
120
|
+
end
|
121
|
+
|
122
|
+
if !rule.severity && config.severity_required?
|
123
|
+
stdout.puts Rainbow(" Severity is required. π±").red
|
124
|
+
rule_ok = false
|
125
|
+
failed_rule_ids << rule.id
|
126
|
+
end
|
127
|
+
|
128
|
+
if rule_ok
|
129
|
+
stdout.puts Rainbow(" OK! π").green
|
130
|
+
success_count += 1
|
123
131
|
end
|
124
132
|
end
|
125
133
|
|
@@ -131,13 +139,12 @@ module Goodcheck
|
|
131
139
|
end
|
132
140
|
end
|
133
141
|
|
134
|
-
|
142
|
+
total = success_count + failed_rule_ids.size
|
135
143
|
stdout.puts ""
|
136
|
-
stdout.puts
|
137
|
-
|
138
|
-
Rainbow("#{failure_count} #{'failure'.pluralize(failure_count)}").red].join(", ")
|
144
|
+
stdout.puts "#{Rainbow(total).bold} #{total == 1 ? 'rule' : 'rules'} tested: " \
|
145
|
+
"#{Rainbow(success_count.to_s + ' successful').green.bold}, #{Rainbow(failed_rule_ids.size.to_s + ' failed').red.bold}"
|
139
146
|
|
140
|
-
|
147
|
+
failed_rule_ids.empty?
|
141
148
|
end
|
142
149
|
|
143
150
|
def rule_matches_example?(rule, trigger, example)
|