codeclimate-fede 0.85.21

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.
Files changed (102) hide show
  1. checksums.yaml +7 -0
  2. data/bin/check +18 -0
  3. data/bin/codeclimate +21 -0
  4. data/bin/prep-release +45 -0
  5. data/bin/publish +47 -0
  6. data/bin/release +41 -0
  7. data/bin/validate-release +18 -0
  8. data/config/engines.yml +322 -0
  9. data/lib/cc/analyzer/bridge.rb +106 -0
  10. data/lib/cc/analyzer/composite_container_listener.rb +21 -0
  11. data/lib/cc/analyzer/container/result.rb +74 -0
  12. data/lib/cc/analyzer/container.rb +208 -0
  13. data/lib/cc/analyzer/container_listener.rb +9 -0
  14. data/lib/cc/analyzer/engine.rb +125 -0
  15. data/lib/cc/analyzer/engine_output.rb +74 -0
  16. data/lib/cc/analyzer/engine_output_filter.rb +36 -0
  17. data/lib/cc/analyzer/engine_output_overrider.rb +31 -0
  18. data/lib/cc/analyzer/filesystem.rb +50 -0
  19. data/lib/cc/analyzer/formatters/formatter.rb +53 -0
  20. data/lib/cc/analyzer/formatters/html_formatter.rb +415 -0
  21. data/lib/cc/analyzer/formatters/json_formatter.rb +38 -0
  22. data/lib/cc/analyzer/formatters/plain_text_formatter.rb +101 -0
  23. data/lib/cc/analyzer/formatters/spinner.rb +35 -0
  24. data/lib/cc/analyzer/formatters.rb +21 -0
  25. data/lib/cc/analyzer/issue.rb +69 -0
  26. data/lib/cc/analyzer/issue_sorter.rb +30 -0
  27. data/lib/cc/analyzer/issue_validations/category_validation.rb +32 -0
  28. data/lib/cc/analyzer/issue_validations/check_name_presence_validation.rb +15 -0
  29. data/lib/cc/analyzer/issue_validations/content_validation.rb +21 -0
  30. data/lib/cc/analyzer/issue_validations/description_presence_validation.rb +15 -0
  31. data/lib/cc/analyzer/issue_validations/location_format_validation.rb +72 -0
  32. data/lib/cc/analyzer/issue_validations/other_locations_format_validation.rb +41 -0
  33. data/lib/cc/analyzer/issue_validations/path_existence_validation.rb +15 -0
  34. data/lib/cc/analyzer/issue_validations/path_is_file_validation.rb +15 -0
  35. data/lib/cc/analyzer/issue_validations/path_presence_validation.rb +15 -0
  36. data/lib/cc/analyzer/issue_validations/relative_path_validation.rb +32 -0
  37. data/lib/cc/analyzer/issue_validations/remediation_points_validation.rb +25 -0
  38. data/lib/cc/analyzer/issue_validations/severity_validation.rb +39 -0
  39. data/lib/cc/analyzer/issue_validations/type_validation.rb +15 -0
  40. data/lib/cc/analyzer/issue_validations/validation.rb +35 -0
  41. data/lib/cc/analyzer/issue_validations.rb +26 -0
  42. data/lib/cc/analyzer/issue_validator.rb +11 -0
  43. data/lib/cc/analyzer/location_description.rb +45 -0
  44. data/lib/cc/analyzer/logging_container_listener.rb +24 -0
  45. data/lib/cc/analyzer/measurement.rb +22 -0
  46. data/lib/cc/analyzer/measurement_validations/name_validation.rb +23 -0
  47. data/lib/cc/analyzer/measurement_validations/type_validation.rb +15 -0
  48. data/lib/cc/analyzer/measurement_validations/validation.rb +27 -0
  49. data/lib/cc/analyzer/measurement_validations/value_validation.rb +21 -0
  50. data/lib/cc/analyzer/measurement_validations.rb +16 -0
  51. data/lib/cc/analyzer/measurement_validator.rb +11 -0
  52. data/lib/cc/analyzer/mounted_path.rb +80 -0
  53. data/lib/cc/analyzer/raising_container_listener.rb +32 -0
  54. data/lib/cc/analyzer/source_buffer.rb +47 -0
  55. data/lib/cc/analyzer/source_extractor.rb +79 -0
  56. data/lib/cc/analyzer/source_fingerprint.rb +40 -0
  57. data/lib/cc/analyzer/statsd_container_listener.rb +51 -0
  58. data/lib/cc/analyzer/validator.rb +38 -0
  59. data/lib/cc/analyzer.rb +50 -0
  60. data/lib/cc/cli/analyze/engine_failure.rb +11 -0
  61. data/lib/cc/cli/analyze.rb +90 -0
  62. data/lib/cc/cli/command.rb +85 -0
  63. data/lib/cc/cli/console.rb +12 -0
  64. data/lib/cc/cli/engines/engine_command.rb +15 -0
  65. data/lib/cc/cli/engines/install.rb +35 -0
  66. data/lib/cc/cli/engines/list.rb +18 -0
  67. data/lib/cc/cli/engines.rb +5 -0
  68. data/lib/cc/cli/file_store.rb +42 -0
  69. data/lib/cc/cli/global_cache.rb +47 -0
  70. data/lib/cc/cli/global_config.rb +35 -0
  71. data/lib/cc/cli/help.rb +51 -0
  72. data/lib/cc/cli/output.rb +34 -0
  73. data/lib/cc/cli/prepare.rb +98 -0
  74. data/lib/cc/cli/runner.rb +75 -0
  75. data/lib/cc/cli/validate_config.rb +84 -0
  76. data/lib/cc/cli/version.rb +16 -0
  77. data/lib/cc/cli/version_checker.rb +107 -0
  78. data/lib/cc/cli.rb +39 -0
  79. data/lib/cc/config/checks_adapter.rb +40 -0
  80. data/lib/cc/config/default_adapter.rb +54 -0
  81. data/lib/cc/config/engine.rb +41 -0
  82. data/lib/cc/config/engine_set.rb +47 -0
  83. data/lib/cc/config/json_adapter.rb +17 -0
  84. data/lib/cc/config/prepare.rb +92 -0
  85. data/lib/cc/config/validation/check_validator.rb +34 -0
  86. data/lib/cc/config/validation/engine_validator.rb +93 -0
  87. data/lib/cc/config/validation/fetch_validator.rb +78 -0
  88. data/lib/cc/config/validation/file_validator.rb +112 -0
  89. data/lib/cc/config/validation/hash_validations.rb +52 -0
  90. data/lib/cc/config/validation/json.rb +31 -0
  91. data/lib/cc/config/validation/prepare_validator.rb +40 -0
  92. data/lib/cc/config/validation/yaml.rb +66 -0
  93. data/lib/cc/config/yaml_adapter.rb +73 -0
  94. data/lib/cc/config.rb +70 -0
  95. data/lib/cc/engine_registry.rb +74 -0
  96. data/lib/cc/resolv.rb +39 -0
  97. data/lib/cc/workspace/exclusion.rb +34 -0
  98. data/lib/cc/workspace/path_tree/dir_node.rb +67 -0
  99. data/lib/cc/workspace/path_tree/file_node.rb +31 -0
  100. data/lib/cc/workspace/path_tree.rb +49 -0
  101. data/lib/cc/workspace.rb +39 -0
  102. metadata +279 -0
@@ -0,0 +1,54 @@
1
+ module CC
2
+ class Config
3
+ class DefaultAdapter
4
+ # intentionally not sorted: we want them in a particular order
5
+ ENGINES = {
6
+ "structure".freeze => "stable".freeze,
7
+ "duplication".freeze => "stable".freeze,
8
+ }.freeze
9
+
10
+ EXCLUDE_PATTERNS = %w[
11
+ config/
12
+ db/
13
+ dist/
14
+ features/
15
+ **/node_modules/
16
+ script/
17
+ **/spec/
18
+ **/test/
19
+ **/tests/
20
+ Tests/
21
+ **/vendor/
22
+ **/*_test.go
23
+ **/*.d.ts
24
+ ].freeze
25
+
26
+ attr_reader :config
27
+
28
+ def initialize(data = {})
29
+ @config = data
30
+
31
+ apply_default_excludes
32
+ apply_default_engines
33
+ end
34
+
35
+ private
36
+
37
+ def apply_default_engines
38
+ config["plugins"] ||= {}
39
+
40
+ ENGINES.each do |name, channel|
41
+ config["plugins"][name] ||= {}
42
+ unless [true, false].include?(config["plugins"][name]["enabled"])
43
+ config["plugins"][name]["enabled"] = true
44
+ end
45
+ config["plugins"][name]["channel"] ||= channel
46
+ end
47
+ end
48
+
49
+ def apply_default_excludes
50
+ config["exclude_patterns"] ||= EXCLUDE_PATTERNS
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,41 @@
1
+ module CC
2
+ class Config
3
+ class Engine
4
+ DEFAULT_CHANNEL = "stable".freeze
5
+
6
+ attr_accessor :channel
7
+ attr_reader :name, :config, :exclude_patterns
8
+ attr_writer :enabled
9
+
10
+ def initialize(name, enabled: false, channel: nil, config: nil, exclude_patterns: [])
11
+ @name = name
12
+ @enabled = enabled
13
+ @channel = channel || DEFAULT_CHANNEL
14
+ @config = config || {}
15
+ @exclude_patterns = exclude_patterns
16
+ end
17
+
18
+ def enabled?
19
+ @enabled
20
+ end
21
+
22
+ def plugin?
23
+ !DefaultAdapter::ENGINES.keys.include?(name)
24
+ end
25
+
26
+ def container_label
27
+ @container_label ||= SecureRandom.uuid
28
+ end
29
+
30
+ def hash
31
+ name.hash
32
+ end
33
+
34
+ def eql?(other)
35
+ other.is_a?(self.class) && name.eql?(other.name)
36
+ end
37
+ alias_method :==, :eql?
38
+ alias_method :equal?, :eql?
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,47 @@
1
+ module CC
2
+ class Config
3
+ class EngineSet
4
+ attr_reader :engines
5
+
6
+ def initialize(data)
7
+ @data = data
8
+ @engines = []
9
+
10
+ build_set
11
+ end
12
+
13
+ private
14
+
15
+ attr_reader :data
16
+
17
+ def build_set
18
+ DefaultAdapter::ENGINES.keys.each do |name|
19
+ if (engine = extract_engine(name))
20
+ engines << engine
21
+ end
22
+ end
23
+
24
+ data.each do |name, engine_data|
25
+ engines << build_engine(name, engine_data)
26
+ end
27
+ end
28
+
29
+ def extract_engine(name)
30
+ if data[name]
31
+ engine_data = data.delete(name)
32
+ build_engine(name, engine_data)
33
+ end
34
+ end
35
+
36
+ def build_engine(name, data)
37
+ Config::Engine.new(
38
+ name,
39
+ enabled: data.fetch("enabled", true),
40
+ channel: data["channel"],
41
+ config: data,
42
+ exclude_patterns: data.fetch("exclude_patterns", []),
43
+ )
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,17 @@
1
+ module CC
2
+ class Config
3
+ class JSONAdapter < Config
4
+ DEFAULT_PATH = ".codeclimate.json".freeze
5
+
6
+ attr_reader :config
7
+
8
+ def self.load(path = DEFAULT_PATH)
9
+ new(::JSON.parse(File.open(path).read))
10
+ end
11
+
12
+ def initialize(json = {})
13
+ @config = json
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,92 @@
1
+ module CC
2
+ class Config
3
+ class Prepare
4
+ attr_reader :fetch
5
+
6
+ def self.from_data(data)
7
+ if data.present?
8
+ fetch = Fetch.from_data(data.fetch("fetch", []))
9
+
10
+ new(fetch: fetch)
11
+ else
12
+ new
13
+ end
14
+ end
15
+
16
+ def initialize(fetch: Fetch.new)
17
+ @fetch = fetch
18
+ end
19
+
20
+ def merge(other)
21
+ Prepare.new(fetch: fetch.merge(other.fetch))
22
+ end
23
+
24
+ class Fetch
25
+ def self.from_data(data)
26
+ new(data.map { |d| Entry.from_data(d) })
27
+ end
28
+
29
+ def initialize(entries = [])
30
+ @entries = Set.new(entries)
31
+ end
32
+
33
+ def each(&block)
34
+ entries.each(&block)
35
+ end
36
+
37
+ def merge(other)
38
+ Fetch.new(each.to_a | other.each.to_a)
39
+ end
40
+
41
+ private
42
+
43
+ attr_reader :entries
44
+
45
+ class Entry
46
+ attr_reader :url, :path
47
+
48
+ def self.from_data(data)
49
+ case data
50
+ when String then new(data)
51
+ when Hash then new(data.fetch("url"), data["path"])
52
+ end
53
+ end
54
+
55
+ def initialize(url, path = nil)
56
+ @url = url
57
+ @path = path || url.split("/").last
58
+
59
+ validate_path!
60
+ end
61
+
62
+ # Useful in specs
63
+ def ==(other)
64
+ other.is_a?(self.class) &&
65
+ other.url == url &&
66
+ other.path == path
67
+ end
68
+
69
+ private
70
+
71
+ # Duplicate a validation which has security implication. This should
72
+ # always be caught upstream, so raising loudly is fine.
73
+ def validate_path!
74
+ if path.blank?
75
+ raise ArgumentError, "path cannot be be blank"
76
+ end
77
+
78
+ pathname = Pathname.new(path)
79
+
80
+ if pathname.absolute?
81
+ raise ArgumentError, "path cannot be absolute: #{path}"
82
+ end
83
+
84
+ if pathname.cleanpath.to_s != pathname.to_s || path.include?("..")
85
+ raise ArgumentError, "path cannot point outside the current directory: #{path}"
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,34 @@
1
+ module CC
2
+ class Config
3
+ module Validation
4
+ class CheckValidator
5
+ include HashValidations
6
+
7
+ attr_reader :errors, :warnings
8
+
9
+ def initialize(data)
10
+ @data = data
11
+
12
+ @errors = []
13
+ @warnings = []
14
+
15
+ validate
16
+ end
17
+
18
+ private
19
+
20
+ attr_reader :data
21
+
22
+ def validate
23
+ unless data.is_a?(Hash)
24
+ errors << "must be a hash"
25
+ return
26
+ end
27
+
28
+ validate_key_type("enabled", [TrueClass, FalseClass])
29
+ validate_key_type("config", Hash)
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,93 @@
1
+ module CC
2
+ class Config
3
+ module Validation
4
+ class EngineValidator
5
+ include HashValidations
6
+
7
+ RECOGNIZED_KEYS = %w[
8
+ enabled
9
+ channel
10
+ checks
11
+ config
12
+ exclude_fingerprints
13
+ exclude_patterns
14
+ ].freeze
15
+
16
+ attr_reader :errors, :warnings
17
+
18
+ def initialize(data, legacy: false)
19
+ @data = data
20
+ @legacy = legacy
21
+
22
+ @errors = []
23
+ @warnings = []
24
+
25
+ validate
26
+ end
27
+
28
+ def valid?
29
+ errors.none?
30
+ end
31
+
32
+ private
33
+
34
+ attr_reader :data
35
+
36
+ def legacy?
37
+ @legacy
38
+ end
39
+
40
+ def validate
41
+ validate_root
42
+ return unless data.is_a?(Hash)
43
+
44
+ validate_key_type("enabled", [TrueClass, FalseClass])
45
+ validate_key_type("channel", String)
46
+ validate_key_type("config", [String, Hash])
47
+ validate_key_type("exclude_patterns", Array)
48
+ if legacy?
49
+ validate_exclude_paths
50
+ end
51
+
52
+ validate_checks
53
+ validate_exclude_fingerprints
54
+
55
+ if legacy?
56
+ warn_unrecognized_keys(RECOGNIZED_KEYS + %w[exclude_paths])
57
+ else
58
+ warn_unrecognized_keys(RECOGNIZED_KEYS)
59
+ end
60
+ end
61
+
62
+ def validate_root
63
+ if !data.is_a?(Hash) && ![true, false].include?(data)
64
+ errors << "section must be a boolean or a hash"
65
+ return false
66
+ end
67
+ true
68
+ end
69
+
70
+ def validate_checks
71
+ return unless validate_key_type("checks", Hash)
72
+
73
+ data.fetch("checks", {}).each do |_check_name, check_data|
74
+ validator = CheckValidator.new(check_data)
75
+ errors.push(*validator.errors)
76
+ warnings.push(*validator.warnings)
77
+ end
78
+ end
79
+
80
+ def validate_exclude_paths
81
+ validate_key_type("exclude_paths", [Array, String])
82
+ if data.key?("exclude_paths")
83
+ warnings << "'exclude_paths' has been deprecated, please use 'exclude_patterns' instead"
84
+ end
85
+ end
86
+
87
+ def validate_exclude_fingerprints
88
+ validate_key_type("exclude_fingerprints", Array)
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,78 @@
1
+ require "uri"
2
+ require "pathname"
3
+
4
+ module CC
5
+ class Config
6
+ module Validation
7
+ class FetchValidator
8
+ include HashValidations
9
+
10
+ attr_reader :errors, :warnings
11
+
12
+ def initialize(data)
13
+ @data = data
14
+
15
+ @errors = []
16
+ @warnings = []
17
+
18
+ validate
19
+ end
20
+
21
+ private
22
+
23
+ attr_reader :data
24
+
25
+ def validate
26
+ if data.is_a?(String)
27
+ validate_url(data)
28
+ elsif data.is_a?(Hash)
29
+ validate_fetch_hash
30
+ else
31
+ errors << "fetch section should be a string or a hash"
32
+ end
33
+ end
34
+
35
+ def validate_url(url)
36
+ unless valid_url?(url)
37
+ errors << "fetch section: invalid URL '#{url}'"
38
+ end
39
+ end
40
+
41
+ def valid_url?(url)
42
+ uri = URI.parse(url)
43
+ uri.is_a?(URI::HTTP) || uri.is_a?(URI::HTTPS)
44
+ rescue URI::InvalidURIError
45
+ false
46
+ end
47
+
48
+ def validate_fetch_hash
49
+ if !data.key?("path") || !data.key?("url")
50
+ errors << "fetch section must include 'url' & 'path'"
51
+ end
52
+
53
+ validate_key_type("path", String)
54
+ validate_key_type("url", String)
55
+
56
+ validate_path(data["path"])
57
+ validate_url(data["url"])
58
+
59
+ warn_unrecognized_keys(%w[path url])
60
+ end
61
+
62
+ def validate_path(path)
63
+ if path.nil? || path.length.zero?
64
+ errors << "fetch section's 'path' cannot be empty"
65
+ else
66
+ pathname = Pathname.new(path)
67
+ if pathname.absolute?
68
+ errors << "fetch section: absolute path '#{path}' is invalid"
69
+ end
70
+ if pathname.cleanpath.to_s != pathname.to_s || path.include?("..")
71
+ errors << "fetch section: relative path elements in '#{path}' are invalid"
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,112 @@
1
+ module CC
2
+ class Config
3
+ module Validation
4
+ class FileValidator
5
+ include HashValidations
6
+
7
+ attr_reader :errors, :path, :warnings
8
+
9
+ def initialize(path, registry)
10
+ @path = path
11
+ @registry = registry
12
+
13
+ @errors = []
14
+ @warnings = []
15
+
16
+ validate
17
+ end
18
+
19
+ def valid?
20
+ errors.none?
21
+ end
22
+
23
+ private
24
+
25
+ attr_reader :data, :registry
26
+
27
+ def validate
28
+ raise NotImplementedError, "use a subclass"
29
+ end
30
+
31
+ def denormalize_subvalidator(validator, prefix)
32
+ validator.errors.each do |msg|
33
+ errors << "#{prefix}: #{msg}"
34
+ end
35
+ validator.warnings.each do |msg|
36
+ warnings << "#{prefix}: #{msg}"
37
+ end
38
+ end
39
+
40
+ def validate_prepare
41
+ return unless validate_key_type("prepare", Hash)
42
+
43
+ validator = PrepareValidator.new(data.fetch("prepare", {}))
44
+ denormalize_subvalidator(validator, "prepare section")
45
+ end
46
+
47
+ def validate_engines(key, legacy: false)
48
+ return unless validate_key_type(key, Hash)
49
+
50
+ data.fetch(key, {}).each do |engine_name, engine_data|
51
+ engine_validator = EngineValidator.new(engine_data, legacy: legacy)
52
+ denormalize_subvalidator(engine_validator, "engine #{engine_name}")
53
+
54
+ if engine_validator.valid?
55
+ validate_engine_existence(engine_name, engine_data)
56
+ end
57
+ end
58
+ end
59
+
60
+ def validate_engine_existence(engine_name, engine_data)
61
+ if [true, false].include?(engine_data)
62
+ engine_data = {
63
+ "enabled" => true,
64
+ "channel" => Engine::DEFAULT_CHANNEL,
65
+ }
66
+ end
67
+
68
+ engine = Engine.new(
69
+ engine_name,
70
+ enabled: engine_data.fetch("enabled", true),
71
+ channel: engine_data["channel"],
72
+ config: engine_data["config"],
73
+ )
74
+ unless engine_exists?(engine)
75
+ warnings << "unknown engine or channel <#{engine.name}:#{engine.channel}>"
76
+ end
77
+ end
78
+
79
+ def engine_exists?(engine)
80
+ !registry.fetch_engine_details(engine).nil?
81
+ rescue CC::EngineRegistry::EngineDetailsNotFoundError
82
+ false
83
+ end
84
+
85
+ def validate_checks
86
+ return unless validate_key_type("checks", Hash)
87
+
88
+ data.fetch("checks", {}).each do |check_name, check_data|
89
+ validator = CheckValidator.new(check_data)
90
+ denormalize_subvalidator(validator, "check #{check_name}")
91
+ end
92
+ end
93
+
94
+ def validate_exclude_pattern(key, legacy: false)
95
+ types =
96
+ if legacy
97
+ [Array, String]
98
+ else
99
+ Array
100
+ end
101
+ return unless validate_key_type(key, types)
102
+
103
+ Array(data.fetch(key, [])).each do |pattern|
104
+ unless pattern.is_a?(String)
105
+ errors << "each exclude pattern should be a string, but '#{pattern.inspect}' is a #{pattern.class.to_s.downcase}"
106
+ end
107
+ end
108
+ end
109
+ end
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,52 @@
1
+ module CC
2
+ class Config
3
+ module Validation
4
+ module HashValidations
5
+ def validate_hash_data
6
+ unless data.is_a?(Hash)
7
+ errors << "Config file should contain a hash, not a #{data.class.to_s.downcase}"
8
+ return false
9
+ end
10
+ true
11
+ end
12
+
13
+ def validate_key_type(key, types)
14
+ if types.is_a?(Class)
15
+ return validate_key_type(key, [types])
16
+ elsif data.key?(key)
17
+ unless types.include?(data[key].class)
18
+ errors << key_type_error_message(key, types)
19
+ return false
20
+ end
21
+ end
22
+ true
23
+ end
24
+
25
+ def key_type_error_message(key, types)
26
+ if types.one?
27
+ klass_name = types[0].to_s.downcase
28
+ article =
29
+ if klass_name[0] == "a"
30
+ "an"
31
+ else
32
+ "a"
33
+ end
34
+ "'#{key}' must be #{article} #{klass_name}"
35
+ elsif types == [TrueClass, FalseClass]
36
+ "'#{key}' must be a boolean"
37
+ else
38
+ type_names = types.map(&:to_s).map(&:downcase)
39
+ "'#{key}' must be one of #{type_names.join(", ")}"
40
+ end
41
+ end
42
+
43
+ def warn_unrecognized_keys(recognized_keys)
44
+ unknown_keys = data.keys.reject { |k| recognized_keys.include?(k) }
45
+ unknown_keys.each do |key|
46
+ warnings << "unrecognized key '#{key}'"
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,31 @@
1
+ module CC
2
+ class Config
3
+ module Validation
4
+ class JSON < FileValidator
5
+ private
6
+
7
+ def validate
8
+ @data = ::JSON.parse(File.read(path))
9
+
10
+ return unless validate_hash_data
11
+
12
+ validate_version
13
+ validate_prepare
14
+ validate_engines("plugins")
15
+ validate_checks
16
+ validate_exclude_pattern("exclude_patterns")
17
+
18
+ warn_unrecognized_keys(%w[checks prepare plugins exclude_patterns version])
19
+ rescue ::JSON::ParserError => ex
20
+ errors << "Unable to parse: #{ex.message}"
21
+ end
22
+
23
+ def validate_version
24
+ unless data.key?("version")
25
+ warnings << %(missing 'version' key. Please add `"version": "2"`)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,40 @@
1
+ module CC
2
+ class Config
3
+ module Validation
4
+ class PrepareValidator
5
+ include HashValidations
6
+
7
+ attr_reader :errors, :warnings
8
+
9
+ def initialize(data)
10
+ @data = data
11
+
12
+ @errors = []
13
+ @warnings = []
14
+
15
+ validate
16
+ end
17
+
18
+ private
19
+
20
+ attr_reader :data
21
+
22
+ def validate
23
+ return unless validate_key_type("fetch", Array)
24
+
25
+ data.fetch("fetch", []).each do |fetch_data|
26
+ validator = FetchValidator.new(fetch_data)
27
+ validator.errors.each do |msg|
28
+ errors << msg
29
+ end
30
+ validator.warnings.each do |msg|
31
+ warnings << msg
32
+ end
33
+ end
34
+
35
+ warn_unrecognized_keys(%w[fetch])
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end