goodcheck 2.5.2 → 3.0.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 +49 -3
- data/LICENSE +1 -1
- data/README.md +8 -445
- data/lib/goodcheck.rb +9 -4
- data/lib/goodcheck/analyzer.rb +13 -9
- data/lib/goodcheck/buffer.rb +9 -21
- data/lib/goodcheck/cli.rb +79 -57
- data/lib/goodcheck/commands/check.rb +41 -27
- data/lib/goodcheck/commands/config_loading.rb +28 -5
- data/lib/goodcheck/commands/init.rb +4 -2
- data/lib/goodcheck/commands/pattern.rb +2 -1
- data/lib/goodcheck/commands/test.rb +38 -30
- data/lib/goodcheck/config.rb +68 -1
- data/lib/goodcheck/config_loader.rb +41 -31
- data/lib/goodcheck/error.rb +3 -0
- data/lib/goodcheck/exit_status.rb +8 -0
- data/lib/goodcheck/glob.rb +14 -3
- data/lib/goodcheck/import_loader.rb +96 -26
- 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 +44 -82
- data/.github/dependabot.yml +0 -18
- data/.github/workflows/release.yml +0 -16
- data/.github/workflows/test.yml +0 -46
- data/.gitignore +0 -13
- data/.rubocop.yml +0 -5
- data/Dockerfile +0 -13
- data/Gemfile +0 -6
- data/Rakefile +0 -75
- data/bin/console +0 -14
- data/bin/setup +0 -8
- data/cheatsheet.pdf +0 -0
- data/docusaurus/.dockerignore +0 -2
- data/docusaurus/.gitignore +0 -12
- data/docusaurus/Dockerfile +0 -10
- data/docusaurus/docker-compose.yml +0 -18
- data/docusaurus/docs/commands.md +0 -69
- data/docusaurus/docs/configuration.md +0 -300
- data/docusaurus/docs/development.md +0 -15
- data/docusaurus/docs/getstarted.md +0 -46
- data/docusaurus/docs/rules.md +0 -79
- data/docusaurus/website/README.md +0 -193
- data/docusaurus/website/core/Footer.js +0 -100
- data/docusaurus/website/package.json +0 -14
- data/docusaurus/website/pages/en/index.js +0 -207
- data/docusaurus/website/pages/en/versions.js +0 -118
- data/docusaurus/website/sidebars.json +0 -11
- data/docusaurus/website/siteConfig.js +0 -171
- data/docusaurus/website/static/css/code-block-buttons.css +0 -39
- data/docusaurus/website/static/css/custom.css +0 -245
- data/docusaurus/website/static/img/favicon.ico +0 -0
- data/docusaurus/website/static/js/code-block-buttons.js +0 -47
- data/docusaurus/website/versioned_docs/version-1.0.0/commands.md +0 -70
- data/docusaurus/website/versioned_docs/version-1.0.0/configuration.md +0 -296
- data/docusaurus/website/versioned_docs/version-1.0.0/development.md +0 -16
- data/docusaurus/website/versioned_docs/version-1.0.0/getstarted.md +0 -47
- data/docusaurus/website/versioned_docs/version-1.0.0/rules.md +0 -81
- data/docusaurus/website/versioned_docs/version-1.0.2/rules.md +0 -79
- data/docusaurus/website/versioned_docs/version-2.4.0/configuration.md +0 -301
- data/docusaurus/website/versioned_docs/version-2.4.3/rules.md +0 -80
- data/docusaurus/website/versioned_sidebars/version-1.0.0-sidebars.json +0 -11
- data/docusaurus/website/versioned_sidebars/version-1.0.2-sidebars.json +0 -11
- data/docusaurus/website/versioned_sidebars/version-2.4.0-sidebars.json +0 -11
- data/docusaurus/website/versions.json +0 -12
- data/docusaurus/website/yarn.lock +0 -6604
- data/goodcheck.gemspec +0 -35
- data/goodcheck.yml +0 -10
- data/logo/GoodCheck Horizontal.pdf +0 -899
- data/logo/GoodCheck Horizontal.png +0 -0
- data/logo/GoodCheck Horizontal.svg +0 -55
- data/logo/GoodCheck logo.png +0 -0
- data/logo/GoodCheck vertical.png +0 -0
- data/sample.yml +0 -57
@@ -1,11 +1,29 @@
|
|
1
1
|
module Goodcheck
|
2
2
|
module Commands
|
3
3
|
module ConfigLoading
|
4
|
+
include ExitStatus
|
5
|
+
|
6
|
+
class ConfigFileNotFound < Error
|
7
|
+
attr_reader :path
|
8
|
+
|
9
|
+
def initialize(path:)
|
10
|
+
super(path.to_s)
|
11
|
+
@path = path
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
4
15
|
attr_reader :config
|
5
16
|
|
6
17
|
def load_config!(force_download:, cache_path:)
|
18
|
+
config_content =
|
19
|
+
begin
|
20
|
+
config_path.read
|
21
|
+
rescue Errno::ENOENT
|
22
|
+
raise ConfigFileNotFound.new(path: config_path)
|
23
|
+
end
|
24
|
+
|
7
25
|
import_loader = ImportLoader.new(cache_path: cache_path, force_download: force_download, config_path: config_path)
|
8
|
-
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)
|
9
27
|
loader = ConfigLoader.new(path: config_path, content: content, stderr: stderr, import_loader: import_loader)
|
10
28
|
@config = loader.load
|
11
29
|
end
|
@@ -13,20 +31,25 @@ module Goodcheck
|
|
13
31
|
def handle_config_errors(stderr)
|
14
32
|
begin
|
15
33
|
yield
|
16
|
-
|
34
|
+
rescue ConfigFileNotFound => exn
|
35
|
+
stderr.puts "Configuration file not found: #{exn.path}"
|
36
|
+
EXIT_ERROR
|
37
|
+
rescue ConfigLoader::InvalidPattern => exn
|
38
|
+
stderr.puts exn.message
|
39
|
+
EXIT_ERROR
|
17
40
|
rescue Psych::Exception => exn
|
18
41
|
stderr.puts "Unexpected error happens while loading YAML file: #{exn.inspect}"
|
19
42
|
exn.backtrace.each do |trace_loc|
|
20
43
|
stderr.puts " #{trace_loc}"
|
21
44
|
end
|
22
|
-
|
45
|
+
EXIT_ERROR
|
23
46
|
rescue StrongJSON::Type::TypeError, StrongJSON::Type::UnexpectedAttributeError => exn
|
24
47
|
stderr.puts "Invalid config: #{exn.message}"
|
25
48
|
stderr.puts StrongJSON::ErrorReporter.new(path: exn.path).to_s
|
26
|
-
|
49
|
+
EXIT_ERROR
|
27
50
|
rescue Errno::ENOENT => exn
|
28
51
|
stderr.puts "#{exn}"
|
29
|
-
|
52
|
+
EXIT_ERROR
|
30
53
|
end
|
31
54
|
end
|
32
55
|
end
|
@@ -58,6 +58,8 @@ rules:
|
|
58
58
|
# - vendor
|
59
59
|
EOC
|
60
60
|
|
61
|
+
include ExitStatus
|
62
|
+
|
61
63
|
attr_reader :stdout
|
62
64
|
attr_reader :stderr
|
63
65
|
attr_reader :path
|
@@ -73,7 +75,7 @@ rules:
|
|
73
75
|
def run
|
74
76
|
if path.file? && !force
|
75
77
|
stderr.puts "#{path} already exists. Try --force option to overwrite the file."
|
76
|
-
return
|
78
|
+
return EXIT_ERROR
|
77
79
|
end
|
78
80
|
|
79
81
|
path.open("w") do |io|
|
@@ -82,7 +84,7 @@ rules:
|
|
82
84
|
|
83
85
|
stdout.puts "Wrote #{path}. ✍️"
|
84
86
|
|
85
|
-
|
87
|
+
EXIT_SUCCESS
|
86
88
|
end
|
87
89
|
end
|
88
90
|
end
|
@@ -9,6 +9,7 @@ module Goodcheck
|
|
9
9
|
|
10
10
|
include ConfigLoading
|
11
11
|
include HomePath
|
12
|
+
include ExitStatus
|
12
13
|
|
13
14
|
def initialize(stdout:, stderr:, path:, ids:, home_path:)
|
14
15
|
@stdout = stdout
|
@@ -34,7 +35,7 @@ module Goodcheck
|
|
34
35
|
end
|
35
36
|
end
|
36
37
|
|
37
|
-
|
38
|
+
EXIT_SUCCESS
|
38
39
|
end
|
39
40
|
end
|
40
41
|
end
|
@@ -3,6 +3,7 @@ module Goodcheck
|
|
3
3
|
class Test
|
4
4
|
include ConfigLoading
|
5
5
|
include HomePath
|
6
|
+
include ExitStatus
|
6
7
|
|
7
8
|
attr_reader :stdout
|
8
9
|
attr_reader :stderr
|
@@ -24,18 +25,18 @@ module Goodcheck
|
|
24
25
|
|
25
26
|
if config.rules.empty?
|
26
27
|
stdout.puts "No rules."
|
27
|
-
return
|
28
|
+
return EXIT_SUCCESS
|
28
29
|
end
|
29
30
|
|
30
|
-
validate_rule_uniqueness or return
|
31
|
-
validate_rules or return
|
31
|
+
validate_rule_uniqueness or return EXIT_TEST_FAILED
|
32
|
+
validate_rules or return EXIT_TEST_FAILED
|
32
33
|
|
33
|
-
|
34
|
+
EXIT_SUCCESS
|
34
35
|
end
|
35
36
|
end
|
36
37
|
|
37
38
|
def validate_rule_uniqueness
|
38
|
-
stdout.puts "Validating rule
|
39
|
+
stdout.puts "Validating rule ID uniqueness..."
|
39
40
|
|
40
41
|
duplicated_ids = []
|
41
42
|
|
@@ -46,36 +47,35 @@ module Goodcheck
|
|
46
47
|
end
|
47
48
|
|
48
49
|
if duplicated_ids.empty?
|
49
|
-
stdout.puts " OK
|
50
|
+
stdout.puts Rainbow(" OK! 👍").green
|
50
51
|
true
|
51
52
|
else
|
52
53
|
count = duplicated_ids.size
|
53
|
-
|
54
|
+
duplication = count == 1 ? 'duplication' : 'duplications'
|
55
|
+
stdout.puts " Found #{Rainbow(count).bold} #{duplication}. 😱"
|
54
56
|
duplicated_ids.each do |id|
|
55
|
-
stdout.puts " #{id}"
|
57
|
+
stdout.puts " - #{Rainbow(id).background(:red)}"
|
56
58
|
end
|
57
59
|
false
|
58
60
|
end
|
59
61
|
end
|
60
62
|
|
61
63
|
def validate_rules
|
62
|
-
test_pass = true
|
63
64
|
success_count = 0
|
64
|
-
failure_count = 0
|
65
65
|
failed_rule_ids = Set[]
|
66
66
|
|
67
67
|
config.rules.each do |rule|
|
68
|
-
|
69
|
-
stdout.puts "Testing rule #{Rainbow(rule.id).cyan}..."
|
68
|
+
stdout.puts "Testing rule #{Rainbow(rule.id).cyan}..."
|
70
69
|
|
71
|
-
|
70
|
+
rule_ok = true
|
72
71
|
|
72
|
+
if rule.triggers.any? {|trigger| !trigger.passes.empty? || !trigger.fails.empty?}
|
73
73
|
rule.triggers.each.with_index do |trigger, index|
|
74
74
|
if !trigger.passes.empty? || !trigger.fails.empty?
|
75
75
|
if trigger.by_pattern?
|
76
76
|
stdout.puts " Testing pattern..."
|
77
77
|
else
|
78
|
-
stdout.puts "
|
78
|
+
stdout.puts " #{index + 1}. Testing trigger..."
|
79
79
|
end
|
80
80
|
|
81
81
|
pass_errors = trigger.passes.each.with_index.select do |pass, _|
|
@@ -87,21 +87,19 @@ module Goodcheck
|
|
87
87
|
end
|
88
88
|
|
89
89
|
unless pass_errors.empty?
|
90
|
-
test_pass = false
|
91
90
|
rule_ok = false
|
92
91
|
|
93
92
|
pass_errors.each do |_, index|
|
94
|
-
stdout.puts " #{
|
93
|
+
stdout.puts " #{index + 1}. #{Rainbow('pass').green} example matched. 😱"
|
95
94
|
failed_rule_ids << rule.id
|
96
95
|
end
|
97
96
|
end
|
98
97
|
|
99
98
|
unless fail_errors.empty?
|
100
|
-
test_pass = false
|
101
99
|
rule_ok = false
|
102
100
|
|
103
101
|
fail_errors.each do |_, index|
|
104
|
-
stdout.puts " #{
|
102
|
+
stdout.puts " #{index + 1}. #{Rainbow('fail').red} example didn’t match. 😱"
|
105
103
|
failed_rule_ids << rule.id
|
106
104
|
end
|
107
105
|
end
|
@@ -109,16 +107,27 @@ module Goodcheck
|
|
109
107
|
end
|
110
108
|
|
111
109
|
if rule.triggers.any?(&:skips_fail_examples?)
|
112
|
-
stdout.puts "
|
110
|
+
stdout.puts " The rule contains a `pattern` with `glob`, which is not supported by the test command. 🚨"
|
113
111
|
stdout.puts " Skips testing `fail` examples."
|
114
112
|
end
|
113
|
+
end
|
115
114
|
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
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
|
122
131
|
end
|
123
132
|
end
|
124
133
|
|
@@ -130,13 +139,12 @@ module Goodcheck
|
|
130
139
|
end
|
131
140
|
end
|
132
141
|
|
133
|
-
|
142
|
+
total = success_count + failed_rule_ids.size
|
134
143
|
stdout.puts ""
|
135
|
-
stdout.puts
|
136
|
-
|
137
|
-
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}"
|
138
146
|
|
139
|
-
|
147
|
+
failed_rule_ids.empty?
|
140
148
|
end
|
141
149
|
|
142
150
|
def rule_matches_example?(rule, trigger, example)
|
data/lib/goodcheck/config.rb
CHANGED
@@ -1,11 +1,43 @@
|
|
1
1
|
module Goodcheck
|
2
2
|
class Config
|
3
|
+
DEFAULT_EXCLUDE_BINARY = false
|
4
|
+
|
5
|
+
# https://www.iana.org/assignments/media-types/media-types.xhtml
|
6
|
+
BINARY_MIME_TYPES = %w[
|
7
|
+
audio
|
8
|
+
font
|
9
|
+
image
|
10
|
+
model
|
11
|
+
multipart
|
12
|
+
video
|
13
|
+
].to_set.freeze
|
14
|
+
BINARY_MIME_FULLTYPES = %w[
|
15
|
+
application/gzip
|
16
|
+
application/illustrator
|
17
|
+
application/pdf
|
18
|
+
application/zip
|
19
|
+
].to_set.freeze
|
20
|
+
|
3
21
|
attr_reader :rules
|
4
22
|
attr_reader :exclude_paths
|
23
|
+
attr_reader :exclude_binary
|
24
|
+
alias exclude_binary? exclude_binary
|
25
|
+
attr_reader :allowed_severities
|
26
|
+
attr_reader :severity_required
|
27
|
+
alias severity_required? severity_required
|
5
28
|
|
6
|
-
def initialize(rules:, exclude_paths:)
|
29
|
+
def initialize(rules:, exclude_paths:, exclude_binary: DEFAULT_EXCLUDE_BINARY, severity: nil)
|
7
30
|
@rules = rules
|
8
31
|
@exclude_paths = exclude_paths
|
32
|
+
@exclude_binary = exclude_binary || DEFAULT_EXCLUDE_BINARY
|
33
|
+
severity ||= {}
|
34
|
+
@allowed_severities = Set.new(severity.fetch(:allow, []))
|
35
|
+
@severity_required = severity.fetch(:required, false)
|
36
|
+
end
|
37
|
+
|
38
|
+
def severity_allowed?(severity)
|
39
|
+
return true if allowed_severities.empty?
|
40
|
+
allowed_severities.include?(severity)
|
9
41
|
end
|
10
42
|
|
11
43
|
def each_rule(filter:, &block)
|
@@ -44,5 +76,40 @@ module Goodcheck
|
|
44
76
|
enum_for(:rules_for_path, path, rules_filter: rules_filter)
|
45
77
|
end
|
46
78
|
end
|
79
|
+
|
80
|
+
def exclude_path?(path)
|
81
|
+
excluded = exclude_paths.any? do |pattern|
|
82
|
+
path.fnmatch?(pattern, File::FNM_PATHNAME | File::FNM_EXTGLOB)
|
83
|
+
end
|
84
|
+
|
85
|
+
return true if excluded
|
86
|
+
return excluded unless exclude_binary?
|
87
|
+
return excluded unless path.file?
|
88
|
+
|
89
|
+
exclude_file_by_mime_type?(path)
|
90
|
+
end
|
91
|
+
|
92
|
+
private
|
93
|
+
|
94
|
+
def exclude_file_by_mime_type?(file)
|
95
|
+
# NOTE: Lazy load to save memory
|
96
|
+
require "marcel"
|
97
|
+
|
98
|
+
fulltype = Marcel::MimeType.for(file)
|
99
|
+
type, subtype = fulltype.split("/")
|
100
|
+
|
101
|
+
case
|
102
|
+
when subtype.end_with?("+xml") # e.g. "image/svg+xml"
|
103
|
+
false
|
104
|
+
when BINARY_MIME_TYPES.include?(type)
|
105
|
+
Goodcheck.logger.debug "Exclude file: #{file} (#{fulltype})"
|
106
|
+
true
|
107
|
+
when BINARY_MIME_FULLTYPES.include?(fulltype)
|
108
|
+
Goodcheck.logger.debug "Exclude file: #{file} (#{fulltype})"
|
109
|
+
true
|
110
|
+
else
|
111
|
+
false
|
112
|
+
end
|
113
|
+
end
|
47
114
|
end
|
48
115
|
end
|
@@ -2,7 +2,7 @@ module Goodcheck
|
|
2
2
|
class ConfigLoader
|
3
3
|
include ArrayHelper
|
4
4
|
|
5
|
-
class InvalidPattern <
|
5
|
+
class InvalidPattern < Error; end
|
6
6
|
|
7
7
|
Schema = StrongJSON.new do
|
8
8
|
def self.array_or(type)
|
@@ -22,7 +22,8 @@ module Goodcheck
|
|
22
22
|
let :deprecated_token_pattern, object(token: string, case_insensitive: boolean?)
|
23
23
|
|
24
24
|
let :encoding, enum(*Encoding.name_list.map {|name| literal(name) })
|
25
|
-
let :glob_obj, object(pattern: string, encoding: optional(encoding)
|
25
|
+
let :glob_obj, object(pattern: string, encoding: optional(encoding),
|
26
|
+
exclude: enum?(string, array(string)))
|
26
27
|
let :one_glob, enum(glob_obj,
|
27
28
|
string,
|
28
29
|
detector: -> (value) {
|
@@ -102,7 +103,8 @@ module Goodcheck
|
|
102
103
|
justification: optional(array_or(string)),
|
103
104
|
glob: optional(glob),
|
104
105
|
pass: optional(array_or(string)),
|
105
|
-
fail: optional(array_or(string))
|
106
|
+
fail: optional(array_or(string)),
|
107
|
+
severity: optional(string)
|
106
108
|
)
|
107
109
|
|
108
110
|
let :negative_rule, object(
|
@@ -112,14 +114,16 @@ module Goodcheck
|
|
112
114
|
justification: optional(array_or(string)),
|
113
115
|
glob: optional(glob),
|
114
116
|
pass: optional(array_or(string)),
|
115
|
-
fail: optional(array_or(string))
|
117
|
+
fail: optional(array_or(string)),
|
118
|
+
severity: optional(string)
|
116
119
|
)
|
117
120
|
|
118
121
|
let :nopattern_rule, object(
|
119
122
|
id: string,
|
120
123
|
message: string,
|
121
124
|
justification: optional(array_or(string)),
|
122
|
-
glob: glob
|
125
|
+
glob: glob,
|
126
|
+
severity: optional(string)
|
123
127
|
)
|
124
128
|
|
125
129
|
let :positive_trigger, object(
|
@@ -162,7 +166,8 @@ module Goodcheck
|
|
162
166
|
id: string,
|
163
167
|
message: string,
|
164
168
|
justification: optional(array_or(string)),
|
165
|
-
trigger: array_or(trigger)
|
169
|
+
trigger: array_or(trigger),
|
170
|
+
severity: optional(string)
|
166
171
|
)
|
167
172
|
|
168
173
|
let :rule, enum(positive_rule,
|
@@ -186,14 +191,17 @@ module Goodcheck
|
|
186
191
|
|
187
192
|
let :rules, array(rule)
|
188
193
|
|
189
|
-
let :
|
190
|
-
|
191
|
-
|
194
|
+
let :severity, object(
|
195
|
+
allow: optional(array(string)),
|
196
|
+
required: boolean?
|
197
|
+
)
|
192
198
|
|
193
199
|
let :config, object(
|
194
200
|
rules: optional(rules),
|
195
|
-
import: optional(
|
196
|
-
exclude: optional(
|
201
|
+
import: optional(array(string)),
|
202
|
+
exclude: optional(array_or(string)),
|
203
|
+
exclude_binary: boolean?,
|
204
|
+
severity: optional(severity)
|
197
205
|
)
|
198
206
|
end
|
199
207
|
|
@@ -213,39 +221,40 @@ module Goodcheck
|
|
213
221
|
|
214
222
|
def load
|
215
223
|
Goodcheck.logger.info "Loading configuration: #{path}"
|
216
|
-
|
217
|
-
Schema.config.coerce(content)
|
224
|
+
Schema.config.coerce(content)
|
218
225
|
|
219
|
-
|
226
|
+
rules = []
|
220
227
|
|
221
|
-
|
222
|
-
|
223
|
-
Array(content[:import]).each do |import|
|
224
|
-
load_import rules, import
|
225
|
-
end
|
228
|
+
load_rules(rules, array(content[:rules]))
|
226
229
|
|
227
|
-
|
228
|
-
|
229
|
-
Config.new(rules: rules, exclude_paths: exclude_paths)
|
230
|
+
Array(content[:import]).each do |import|
|
231
|
+
load_import rules, import
|
230
232
|
end
|
233
|
+
|
234
|
+
Config.new(
|
235
|
+
rules: rules,
|
236
|
+
exclude_paths: Array(content[:exclude]),
|
237
|
+
exclude_binary: content[:exclude_binary],
|
238
|
+
severity: content[:severity]
|
239
|
+
)
|
231
240
|
end
|
232
241
|
|
233
242
|
def load_rules(rules, array)
|
234
243
|
array.each do |hash|
|
235
244
|
rules << load_rule(hash)
|
245
|
+
rescue RegexpError => exn
|
246
|
+
raise InvalidPattern, "Invalid pattern of the `#{hash.fetch(:id)}` rule in `#{path}`: #{exn.message}"
|
236
247
|
end
|
237
248
|
end
|
238
249
|
|
239
250
|
def load_import(rules, import)
|
240
251
|
Goodcheck.logger.info "Importing rules from #{import}"
|
241
252
|
|
242
|
-
|
243
|
-
|
244
|
-
json = JSON.parse(JSON.dump(YAML.load(content, filename: import)), symbolize_names: true)
|
253
|
+
import_loader.load(import) do |content, filename|
|
254
|
+
json = JSON.parse(JSON.dump(YAML.safe_load(content, filename: filename)), symbolize_names: true)
|
245
255
|
|
246
|
-
|
247
|
-
|
248
|
-
end
|
256
|
+
Schema.rules.coerce json
|
257
|
+
load_rules(rules, json)
|
249
258
|
end
|
250
259
|
end
|
251
260
|
|
@@ -256,8 +265,9 @@ module Goodcheck
|
|
256
265
|
triggers = retrieve_triggers(hash)
|
257
266
|
justifications = array(hash[:justification])
|
258
267
|
message = hash[:message].chomp
|
268
|
+
severity = hash[:severity]
|
259
269
|
|
260
|
-
Rule.new(id: id, message: message, justifications: justifications, triggers: triggers)
|
270
|
+
Rule.new(id: id, message: message, justifications: justifications, triggers: triggers, severity: severity)
|
261
271
|
end
|
262
272
|
|
263
273
|
def retrieve_triggers(hash)
|
@@ -344,9 +354,9 @@ module Goodcheck
|
|
344
354
|
globs.map do |glob|
|
345
355
|
case glob
|
346
356
|
when String
|
347
|
-
Glob.new(pattern: glob, encoding: nil)
|
357
|
+
Glob.new(pattern: glob, encoding: nil, exclude: nil)
|
348
358
|
when Hash
|
349
|
-
Glob.new(pattern: glob[:pattern], encoding: glob[:encoding])
|
359
|
+
Glob.new(pattern: glob[:pattern], encoding: glob[:encoding], exclude: glob[:exclude])
|
350
360
|
end
|
351
361
|
end
|
352
362
|
end
|