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.
- checksums.yaml +7 -0
- data/bin/check +18 -0
- data/bin/codeclimate +21 -0
- data/bin/prep-release +45 -0
- data/bin/publish +47 -0
- data/bin/release +41 -0
- data/bin/validate-release +18 -0
- data/config/engines.yml +322 -0
- data/lib/cc/analyzer/bridge.rb +106 -0
- data/lib/cc/analyzer/composite_container_listener.rb +21 -0
- data/lib/cc/analyzer/container/result.rb +74 -0
- data/lib/cc/analyzer/container.rb +208 -0
- data/lib/cc/analyzer/container_listener.rb +9 -0
- data/lib/cc/analyzer/engine.rb +125 -0
- data/lib/cc/analyzer/engine_output.rb +74 -0
- data/lib/cc/analyzer/engine_output_filter.rb +36 -0
- data/lib/cc/analyzer/engine_output_overrider.rb +31 -0
- data/lib/cc/analyzer/filesystem.rb +50 -0
- data/lib/cc/analyzer/formatters/formatter.rb +53 -0
- data/lib/cc/analyzer/formatters/html_formatter.rb +415 -0
- data/lib/cc/analyzer/formatters/json_formatter.rb +38 -0
- data/lib/cc/analyzer/formatters/plain_text_formatter.rb +101 -0
- data/lib/cc/analyzer/formatters/spinner.rb +35 -0
- data/lib/cc/analyzer/formatters.rb +21 -0
- data/lib/cc/analyzer/issue.rb +69 -0
- data/lib/cc/analyzer/issue_sorter.rb +30 -0
- data/lib/cc/analyzer/issue_validations/category_validation.rb +32 -0
- data/lib/cc/analyzer/issue_validations/check_name_presence_validation.rb +15 -0
- data/lib/cc/analyzer/issue_validations/content_validation.rb +21 -0
- data/lib/cc/analyzer/issue_validations/description_presence_validation.rb +15 -0
- data/lib/cc/analyzer/issue_validations/location_format_validation.rb +72 -0
- data/lib/cc/analyzer/issue_validations/other_locations_format_validation.rb +41 -0
- data/lib/cc/analyzer/issue_validations/path_existence_validation.rb +15 -0
- data/lib/cc/analyzer/issue_validations/path_is_file_validation.rb +15 -0
- data/lib/cc/analyzer/issue_validations/path_presence_validation.rb +15 -0
- data/lib/cc/analyzer/issue_validations/relative_path_validation.rb +32 -0
- data/lib/cc/analyzer/issue_validations/remediation_points_validation.rb +25 -0
- data/lib/cc/analyzer/issue_validations/severity_validation.rb +39 -0
- data/lib/cc/analyzer/issue_validations/type_validation.rb +15 -0
- data/lib/cc/analyzer/issue_validations/validation.rb +35 -0
- data/lib/cc/analyzer/issue_validations.rb +26 -0
- data/lib/cc/analyzer/issue_validator.rb +11 -0
- data/lib/cc/analyzer/location_description.rb +45 -0
- data/lib/cc/analyzer/logging_container_listener.rb +24 -0
- data/lib/cc/analyzer/measurement.rb +22 -0
- data/lib/cc/analyzer/measurement_validations/name_validation.rb +23 -0
- data/lib/cc/analyzer/measurement_validations/type_validation.rb +15 -0
- data/lib/cc/analyzer/measurement_validations/validation.rb +27 -0
- data/lib/cc/analyzer/measurement_validations/value_validation.rb +21 -0
- data/lib/cc/analyzer/measurement_validations.rb +16 -0
- data/lib/cc/analyzer/measurement_validator.rb +11 -0
- data/lib/cc/analyzer/mounted_path.rb +80 -0
- data/lib/cc/analyzer/raising_container_listener.rb +32 -0
- data/lib/cc/analyzer/source_buffer.rb +47 -0
- data/lib/cc/analyzer/source_extractor.rb +79 -0
- data/lib/cc/analyzer/source_fingerprint.rb +40 -0
- data/lib/cc/analyzer/statsd_container_listener.rb +51 -0
- data/lib/cc/analyzer/validator.rb +38 -0
- data/lib/cc/analyzer.rb +50 -0
- data/lib/cc/cli/analyze/engine_failure.rb +11 -0
- data/lib/cc/cli/analyze.rb +90 -0
- data/lib/cc/cli/command.rb +85 -0
- data/lib/cc/cli/console.rb +12 -0
- data/lib/cc/cli/engines/engine_command.rb +15 -0
- data/lib/cc/cli/engines/install.rb +35 -0
- data/lib/cc/cli/engines/list.rb +18 -0
- data/lib/cc/cli/engines.rb +5 -0
- data/lib/cc/cli/file_store.rb +42 -0
- data/lib/cc/cli/global_cache.rb +47 -0
- data/lib/cc/cli/global_config.rb +35 -0
- data/lib/cc/cli/help.rb +51 -0
- data/lib/cc/cli/output.rb +34 -0
- data/lib/cc/cli/prepare.rb +98 -0
- data/lib/cc/cli/runner.rb +75 -0
- data/lib/cc/cli/validate_config.rb +84 -0
- data/lib/cc/cli/version.rb +16 -0
- data/lib/cc/cli/version_checker.rb +107 -0
- data/lib/cc/cli.rb +39 -0
- data/lib/cc/config/checks_adapter.rb +40 -0
- data/lib/cc/config/default_adapter.rb +54 -0
- data/lib/cc/config/engine.rb +41 -0
- data/lib/cc/config/engine_set.rb +47 -0
- data/lib/cc/config/json_adapter.rb +17 -0
- data/lib/cc/config/prepare.rb +92 -0
- data/lib/cc/config/validation/check_validator.rb +34 -0
- data/lib/cc/config/validation/engine_validator.rb +93 -0
- data/lib/cc/config/validation/fetch_validator.rb +78 -0
- data/lib/cc/config/validation/file_validator.rb +112 -0
- data/lib/cc/config/validation/hash_validations.rb +52 -0
- data/lib/cc/config/validation/json.rb +31 -0
- data/lib/cc/config/validation/prepare_validator.rb +40 -0
- data/lib/cc/config/validation/yaml.rb +66 -0
- data/lib/cc/config/yaml_adapter.rb +73 -0
- data/lib/cc/config.rb +70 -0
- data/lib/cc/engine_registry.rb +74 -0
- data/lib/cc/resolv.rb +39 -0
- data/lib/cc/workspace/exclusion.rb +34 -0
- data/lib/cc/workspace/path_tree/dir_node.rb +67 -0
- data/lib/cc/workspace/path_tree/file_node.rb +31 -0
- data/lib/cc/workspace/path_tree.rb +49 -0
- data/lib/cc/workspace.rb +39 -0
- metadata +279 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
module CC
|
|
2
|
+
module Analyzer
|
|
3
|
+
class IssueSorter
|
|
4
|
+
def initialize(issues)
|
|
5
|
+
@issues = issues
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def by_location
|
|
9
|
+
@issues.sort_by { |i| line_or_offset(i) }
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
private
|
|
13
|
+
|
|
14
|
+
def line_or_offset(issue)
|
|
15
|
+
location = issue["location"]
|
|
16
|
+
|
|
17
|
+
case
|
|
18
|
+
when location["lines"]
|
|
19
|
+
[location["lines"]["begin"].to_i]
|
|
20
|
+
when location["positions"] && location["positions"]["begin"]["line"]
|
|
21
|
+
[location["positions"]["begin"]["line"].to_i, location["positions"]["begin"]["column"].to_i]
|
|
22
|
+
when location["positions"] && location["positions"]["begin"]["offset"]
|
|
23
|
+
[1_000_000_000] # push offsets to end of list
|
|
24
|
+
else
|
|
25
|
+
[0] # whole-file issues are first
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
module CC
|
|
2
|
+
module Analyzer
|
|
3
|
+
module IssueValidations
|
|
4
|
+
class CategoryValidation < Validation
|
|
5
|
+
CATEGORIES = [
|
|
6
|
+
"Bug Risk".freeze,
|
|
7
|
+
"Clarity".freeze,
|
|
8
|
+
"Compatibility".freeze,
|
|
9
|
+
"Complexity".freeze,
|
|
10
|
+
"Duplication".freeze,
|
|
11
|
+
"Performance".freeze,
|
|
12
|
+
"Security".freeze,
|
|
13
|
+
"Style".freeze,
|
|
14
|
+
].freeze
|
|
15
|
+
|
|
16
|
+
def valid?
|
|
17
|
+
object["categories"].present? && no_invalid_categories?
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def message
|
|
21
|
+
"Category must be at least one of #{CATEGORIES.join(", ")}"
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
def no_invalid_categories?
|
|
27
|
+
(CATEGORIES | object["categories"]) == CATEGORIES
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
module CC
|
|
2
|
+
module Analyzer
|
|
3
|
+
module IssueValidations
|
|
4
|
+
class ContentValidation < Validation
|
|
5
|
+
def valid?
|
|
6
|
+
!has_content? || (content.is_a?(Hash) && content["body"].is_a?(String))
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def message
|
|
10
|
+
"Content must be a hash containing a 'body' key with string contents"
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
private
|
|
14
|
+
|
|
15
|
+
def has_content?
|
|
16
|
+
object.key?("content")
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
module CC
|
|
2
|
+
module Analyzer
|
|
3
|
+
module IssueValidations
|
|
4
|
+
class LocationFormatValidation < Validation
|
|
5
|
+
class Validator
|
|
6
|
+
def initialize(location)
|
|
7
|
+
@location = location
|
|
8
|
+
check_validity
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def valid?
|
|
12
|
+
error.nil?
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def message
|
|
16
|
+
if error
|
|
17
|
+
"Location is not formatted correctly: #{error}"
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
attr_accessor :error
|
|
24
|
+
|
|
25
|
+
attr_reader :location
|
|
26
|
+
|
|
27
|
+
def check_validity
|
|
28
|
+
if location["lines"]
|
|
29
|
+
self.error = "location.lines is not valid: #{JSON.dump(location["lines"])}" unless valid_lines?(location["lines"])
|
|
30
|
+
elsif location["positions"]
|
|
31
|
+
self.error = "location.positions is not valid: #{JSON.dump(location["positions"])}" unless valid_positions?(location["positions"])
|
|
32
|
+
else
|
|
33
|
+
self.error = "location.lines or location.positions must be present"
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def valid_positions?(positions)
|
|
38
|
+
positions.is_a?(Hash) &&
|
|
39
|
+
valid_position?(positions["begin"]) &&
|
|
40
|
+
valid_position?(positions["end"])
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def valid_position?(position)
|
|
44
|
+
position &&
|
|
45
|
+
(
|
|
46
|
+
[position["line"], position["column"]].all? { |value| value.is_a?(Integer) } ||
|
|
47
|
+
position["offset"].is_a?(Integer)
|
|
48
|
+
)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def valid_lines?(lines)
|
|
52
|
+
lines.is_a?(Hash) && [lines["begin"], lines["end"]].all? { |value| value.is_a?(Integer) }
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def valid?
|
|
57
|
+
validation.valid?
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def message
|
|
61
|
+
validation.message
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
private
|
|
65
|
+
|
|
66
|
+
def validation
|
|
67
|
+
@validation ||= Validator.new(object.fetch("location", {}))
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
module CC
|
|
2
|
+
module Analyzer
|
|
3
|
+
module IssueValidations
|
|
4
|
+
class OtherLocationsFormatValidation < Validation
|
|
5
|
+
CHECKS = [
|
|
6
|
+
LocationFormatValidation,
|
|
7
|
+
PathExistenceValidation,
|
|
8
|
+
PathPresenceValidation,
|
|
9
|
+
RelativePathValidation,
|
|
10
|
+
].freeze
|
|
11
|
+
|
|
12
|
+
def initialize(object)
|
|
13
|
+
super
|
|
14
|
+
@other_location_valid = {}
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def valid?
|
|
18
|
+
if object["other_locations"]
|
|
19
|
+
object["other_locations"].is_a?(Array) &&
|
|
20
|
+
object["other_locations"].all?(&method(:other_location_valid?))
|
|
21
|
+
else
|
|
22
|
+
true
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def message
|
|
27
|
+
"Other locations are not formatted correctly"
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
private
|
|
31
|
+
|
|
32
|
+
def other_location_valid?(location)
|
|
33
|
+
path = location && location["path"]
|
|
34
|
+
@other_location_valid[path] ||= CHECKS.all? do |klass|
|
|
35
|
+
klass.new("location" => location).valid?
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
require "pathname"
|
|
2
|
+
|
|
3
|
+
module CC
|
|
4
|
+
module Analyzer
|
|
5
|
+
module IssueValidations
|
|
6
|
+
class RelativePathValidation < Validation
|
|
7
|
+
BUILDER_CODE_PATH = "/tmp/workspace/code".freeze
|
|
8
|
+
|
|
9
|
+
def valid?
|
|
10
|
+
path &&
|
|
11
|
+
!path.start_with?("/") && (
|
|
12
|
+
relative_to?(MountedPath.code.container_path) ||
|
|
13
|
+
relative_to?(BUILDER_CODE_PATH)
|
|
14
|
+
)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def message
|
|
18
|
+
"Path must be relative to the project directory"
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
def relative_to?(directory)
|
|
24
|
+
expanded_base = Pathname.new(directory).expand_path.to_s
|
|
25
|
+
expanded_path = Pathname.new(path).expand_path.to_s
|
|
26
|
+
|
|
27
|
+
expanded_path.start_with?(expanded_base)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module CC
|
|
2
|
+
module Analyzer
|
|
3
|
+
module IssueValidations
|
|
4
|
+
class RemediationPointsValidation < Validation
|
|
5
|
+
def valid?
|
|
6
|
+
remediation_points.nil? || positive_integer?(remediation_points)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def message
|
|
10
|
+
"Remediation points must be a non-negative integer"
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
private
|
|
14
|
+
|
|
15
|
+
def remediation_points
|
|
16
|
+
@remediation_points ||= object["remediation_points"]
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def positive_integer?(x)
|
|
20
|
+
x.is_a?(Integer) && x >= 0
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
module CC
|
|
2
|
+
module Analyzer
|
|
3
|
+
module IssueValidations
|
|
4
|
+
class SeverityValidation < Validation
|
|
5
|
+
INFO = "info".freeze
|
|
6
|
+
MINOR = "minor".freeze
|
|
7
|
+
MAJOR = "major".freeze
|
|
8
|
+
CRITICAL = "critical".freeze
|
|
9
|
+
BLOCKER = "blocker".freeze
|
|
10
|
+
|
|
11
|
+
DEPRECATED_SEVERITIES = [
|
|
12
|
+
NORMAL = "normal".freeze,
|
|
13
|
+
].freeze
|
|
14
|
+
|
|
15
|
+
VALID_SEVERITIES = ([
|
|
16
|
+
INFO,
|
|
17
|
+
MINOR,
|
|
18
|
+
MAJOR,
|
|
19
|
+
CRITICAL,
|
|
20
|
+
BLOCKER,
|
|
21
|
+
] + DEPRECATED_SEVERITIES).freeze
|
|
22
|
+
|
|
23
|
+
def valid?
|
|
24
|
+
severity.nil? || VALID_SEVERITIES.include?(severity)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def message
|
|
28
|
+
"Permitted severities include #{VALID_SEVERITIES.join(", ")}"
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
def severity
|
|
34
|
+
@severity ||= object["severity"]
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
module CC
|
|
2
|
+
module Analyzer
|
|
3
|
+
module IssueValidations
|
|
4
|
+
class Validation
|
|
5
|
+
def initialize(object)
|
|
6
|
+
@object = object
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def valid?
|
|
10
|
+
raise NotImplementedError
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def message
|
|
14
|
+
raise NotImplementedError
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
private
|
|
18
|
+
|
|
19
|
+
attr_reader :object
|
|
20
|
+
|
|
21
|
+
def path
|
|
22
|
+
object.fetch("location", {})["path"]
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def type
|
|
26
|
+
object["type"]
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def content
|
|
30
|
+
object["content"]
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
module CC
|
|
2
|
+
module Analyzer
|
|
3
|
+
module IssueValidations
|
|
4
|
+
autoload :CategoryValidation, "cc/analyzer/issue_validations/category_validation"
|
|
5
|
+
autoload :CheckNamePresenceValidation, "cc/analyzer/issue_validations/check_name_presence_validation"
|
|
6
|
+
autoload :ContentValidation, "cc/analyzer/issue_validations/content_validation"
|
|
7
|
+
autoload :DescriptionPresenceValidation, "cc/analyzer/issue_validations/description_presence_validation"
|
|
8
|
+
autoload :LocationFormatValidation, "cc/analyzer/issue_validations/location_format_validation"
|
|
9
|
+
autoload :OtherLocationsFormatValidation, "cc/analyzer/issue_validations/other_locations_format_validation"
|
|
10
|
+
autoload :PathExistenceValidation, "cc/analyzer/issue_validations/path_existence_validation"
|
|
11
|
+
autoload :PathIsFileValidation, "cc/analyzer/issue_validations/path_is_file_validation"
|
|
12
|
+
autoload :PathPresenceValidation, "cc/analyzer/issue_validations/path_presence_validation"
|
|
13
|
+
autoload :RelativePathValidation, "cc/analyzer/issue_validations/relative_path_validation"
|
|
14
|
+
autoload :RemediationPointsValidation, "cc/analyzer/issue_validations/remediation_points_validation"
|
|
15
|
+
autoload :SeverityValidation, "cc/analyzer/issue_validations/severity_validation"
|
|
16
|
+
autoload :TypeValidation, "cc/analyzer/issue_validations/type_validation"
|
|
17
|
+
autoload :Validation, "cc/analyzer/issue_validations/validation"
|
|
18
|
+
|
|
19
|
+
def self.validations
|
|
20
|
+
constants.sort.map(&method(:const_get)).select do |klass|
|
|
21
|
+
klass.is_a?(Class) && klass.superclass == Validation
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
module CC
|
|
2
|
+
module Analyzer
|
|
3
|
+
class LocationDescription
|
|
4
|
+
def initialize(source_buffer, location, suffix = "")
|
|
5
|
+
@source_buffer = source_buffer
|
|
6
|
+
@location = location
|
|
7
|
+
@suffix = suffix
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def to_s
|
|
11
|
+
if location["lines"]
|
|
12
|
+
begin_line = location["lines"]["begin"]
|
|
13
|
+
end_line = location["lines"]["end"]
|
|
14
|
+
elsif location["positions"]
|
|
15
|
+
begin_line = position_to_line(location["positions"]["begin"])
|
|
16
|
+
end_line = position_to_line(location["positions"]["end"])
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
str = render_lines(begin_line, end_line)
|
|
20
|
+
str << suffix unless str.blank?
|
|
21
|
+
str
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
attr_reader :location, :suffix
|
|
27
|
+
|
|
28
|
+
def render_lines(begin_line, end_line)
|
|
29
|
+
if end_line == begin_line
|
|
30
|
+
begin_line.to_s
|
|
31
|
+
else
|
|
32
|
+
"#{begin_line}-#{end_line}"
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def position_to_line(position)
|
|
37
|
+
if position["line"]
|
|
38
|
+
position["line"]
|
|
39
|
+
else
|
|
40
|
+
@source_buffer.decompose_position(position["offset"]).first
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
module CC
|
|
2
|
+
module Analyzer
|
|
3
|
+
class LoggingContainerListener < ContainerListener
|
|
4
|
+
def initialize(logger)
|
|
5
|
+
@logger = logger
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def started(engine, _details)
|
|
9
|
+
logger.info("starting engine #{engine.name}")
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def finished(engine, _details, result)
|
|
13
|
+
logger.info("finished engine #{engine.name}")
|
|
14
|
+
if result.skipped?
|
|
15
|
+
logger.warn("skipped engine #{engine.name}: #{result.stderr}")
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
attr_reader :logger
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
module CC
|
|
2
|
+
module Analyzer
|
|
3
|
+
class Measurement
|
|
4
|
+
def initialize(engine_name, output)
|
|
5
|
+
@engine_name = engine_name
|
|
6
|
+
@output = output
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def as_json(*)
|
|
10
|
+
parsed_output.merge("engine_name" => engine_name)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
private
|
|
14
|
+
|
|
15
|
+
attr_reader :engine_name, :output
|
|
16
|
+
|
|
17
|
+
def parsed_output
|
|
18
|
+
@parsed_output ||= JSON.parse(output)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module CC
|
|
2
|
+
module Analyzer
|
|
3
|
+
module MeasurementValidations
|
|
4
|
+
class NameValidation < Validation
|
|
5
|
+
REGEX = /^[A-Za-z0-9_\.\-]+$/
|
|
6
|
+
|
|
7
|
+
def valid?
|
|
8
|
+
name&.is_a?(String) && REGEX.match?(name)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def message
|
|
12
|
+
"Name must be present and contain only letters, numbers, periods, hyphens, and underscores"
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
private
|
|
16
|
+
|
|
17
|
+
def name
|
|
18
|
+
object["name"]
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module CC
|
|
2
|
+
module Analyzer
|
|
3
|
+
module MeasurementValidations
|
|
4
|
+
class TypeValidation < Validation
|
|
5
|
+
def valid?
|
|
6
|
+
type&.casecmp("measurement")&.zero?
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def message
|
|
10
|
+
"Type must be 'measurement' but was '#{type}'"
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
module CC
|
|
2
|
+
module Analyzer
|
|
3
|
+
module MeasurementValidations
|
|
4
|
+
class Validation
|
|
5
|
+
def initialize(object)
|
|
6
|
+
@object = object
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def valid?
|
|
10
|
+
raise NotImplementedError
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def message
|
|
14
|
+
raise NotImplementedError
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
private
|
|
18
|
+
|
|
19
|
+
attr_reader :object
|
|
20
|
+
|
|
21
|
+
def type
|
|
22
|
+
object["type"]
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
module CC
|
|
2
|
+
module Analyzer
|
|
3
|
+
module MeasurementValidations
|
|
4
|
+
class ValueValidation < Validation
|
|
5
|
+
def valid?
|
|
6
|
+
value&.is_a?(Numeric)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def message
|
|
10
|
+
"Value must be present and numeric"
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
private
|
|
14
|
+
|
|
15
|
+
def value
|
|
16
|
+
object["value"]
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
module CC
|
|
2
|
+
module Analyzer
|
|
3
|
+
module MeasurementValidations
|
|
4
|
+
autoload :NameValidation, "cc/analyzer/measurement_validations/name_validation"
|
|
5
|
+
autoload :TypeValidation, "cc/analyzer/measurement_validations/type_validation"
|
|
6
|
+
autoload :ValueValidation, "cc/analyzer/measurement_validations/value_validation"
|
|
7
|
+
autoload :Validation, "cc/analyzer/measurement_validations/validation"
|
|
8
|
+
|
|
9
|
+
def self.validations
|
|
10
|
+
constants.sort.map(&method(:const_get)).select do |klass|
|
|
11
|
+
klass.is_a?(Class) && klass.superclass == Validation
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|