danger-wcc 0.0.2 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.circleci/config.yml +2 -2
- data/.rubocop.yml +24 -17
- data/README.md +2 -0
- data/danger-wcc.gemspec +4 -4
- data/lib/version.rb +1 -1
- data/lib/wcc/commit_lint.rb +2 -1
- data/lib/wcc/commit_lint/commit_check.rb +0 -1
- data/lib/wcc/commit_lint/empty_line_check.rb +0 -1
- data/lib/wcc/commit_lint/subject_cap_check.rb +0 -1
- data/lib/wcc/commit_lint/subject_length_check.rb +0 -1
- data/lib/wcc/commit_lint/subject_period_check.rb +0 -1
- data/lib/wcc/commit_lint/subject_words_check.rb +0 -1
- data/lib/wcc/defaults.reek +8 -8
- data/lib/wcc/dependencies.rb +74 -0
- data/lib/wcc/dependencies/yarn_info.rb +83 -0
- data/lib/wcc/jshint.rb +2 -2
- data/lib/wcc/plugin.rb +21 -11
- data/lib/wcc/reek.rb +2 -2
- data/lib/wcc/rubocop_exceptions.rb +13 -8
- data/lib/wcc/todos.rb +5 -4
- data/lib/wcc/utils.rb +17 -5
- data/spec/fixtures/dependencies/package.json +112 -0
- data/spec/fixtures/dependencies/package.json.diff +28 -0
- data/spec/fixtures/dependencies/package.json_patch_bumps_minor.diff +13 -0
- data/spec/fixtures/dependencies/package.json_patch_bumps_minor.json +112 -0
- data/spec/fixtures/dependencies/yarn.lock +19609 -0
- data/spec/fixtures/dependencies/yarn.lock_patch_bumps_minor.lock +19614 -0
- data/spec/fixtures/dependencies/yarn_minor_version.diff +33 -0
- data/spec/fixtures/dependencies/yarn_minor_version.txt +1151 -0
- data/spec/fixtures/dependencies/yarn_old.txt +1152 -0
- data/spec/fixtures/dependencies/yarn_patch_bumps_minor.diff +28 -0
- data/spec/fixtures/exception_inline_disabled_rule.diff +12 -0
- data/spec/fixtures/rubocop_exception.rb +3 -0
- data/spec/fixtures_helper.rb +0 -1
- data/spec/spec_helper.rb +1 -1
- data/spec/wcc/commit_lint_spec.rb +6 -10
- data/spec/wcc/dependencies_spec.rb +95 -0
- data/spec/wcc/github_spec.rb +13 -7
- data/spec/wcc/jshint_spec.rb +1 -1
- data/spec/wcc/plugin_spec.rb +18 -17
- data/spec/wcc/reek_spec.rb +1 -1
- data/spec/wcc/rubocop_exceptions_spec.rb +34 -15
- data/spec/wcc/todos_spec.rb +10 -10
- data/spec/wcc/utils_spec.rb +2 -2
- data/spec/wcc_spec.rb +1 -1
- metadata +49 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 356af9ca6ebc46af86c402709d820bb30fd94c1e
|
4
|
+
data.tar.gz: 6842e1bc5330f0088b2978c58e9c9e85afab2030
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5c31ffdd4c4cdc7f4a7c8f1631816d6f1452ba31bc0a03d8a5e1c392265ef8b29decd9e644d2f5b437b4ec2d3a282d7973a2f2d81b8fe1c9d02c84e8c3315523
|
7
|
+
data.tar.gz: 9d8fecdeaab1eda89620ac77454c28b9975987fb5a875ce472bae1e8ba2fdac511b54dbfe0647c46ef6c7f3fccdfc9b501a5ca24fbc85c016328e26108445842
|
data/.circleci/config.yml
CHANGED
@@ -9,14 +9,14 @@ jobs:
|
|
9
9
|
- checkout
|
10
10
|
# Restore bundle cache
|
11
11
|
- restore_cache:
|
12
|
-
key: rails-{{ checksum "
|
12
|
+
key: rails-{{ checksum "danger-wcc.gemspec" }}
|
13
13
|
|
14
14
|
# Bundle install dependencies
|
15
15
|
- run: bundle install --path /tmp/vendor/bundle
|
16
16
|
|
17
17
|
# Store bundle cache
|
18
18
|
- save_cache:
|
19
|
-
key: rails-{{ checksum "
|
19
|
+
key: rails-{{ checksum "danger-wcc.gemspec" }}
|
20
20
|
paths:
|
21
21
|
- /tmp/vendor/bundle
|
22
22
|
|
data/.rubocop.yml
CHANGED
@@ -2,6 +2,7 @@ AllCops:
|
|
2
2
|
DisplayCopNames: true
|
3
3
|
TargetRubyVersion: 2.3
|
4
4
|
Exclude:
|
5
|
+
- 'spec/fixtures/**/*'
|
5
6
|
# generated by rails/binstubs
|
6
7
|
- 'bin/**/*'
|
7
8
|
|
@@ -31,7 +32,7 @@ Style/FormatStringToken:
|
|
31
32
|
Metrics/BlockLength:
|
32
33
|
Exclude:
|
33
34
|
# config files where we expect long blocks
|
34
|
-
- 'danger-
|
35
|
+
- 'danger-wcc.gemspec'
|
35
36
|
# spec files that might have a big describe
|
36
37
|
- 'spec/**/*.rb'
|
37
38
|
# dsl files https://stackoverflow.com/a/41187163
|
@@ -43,29 +44,39 @@ Metrics/MethodLength:
|
|
43
44
|
|
44
45
|
Metrics/ModuleLength:
|
45
46
|
Exclude:
|
46
|
-
- 'lib/
|
47
|
+
- 'lib/wcc/utils.rb'
|
47
48
|
- 'spec/**/*.rb'
|
48
49
|
|
49
|
-
|
50
|
-
|
51
|
-
- 'spec/**/*.rb'
|
52
|
-
|
53
|
-
Performance/UnfreezeString:
|
54
|
-
Exclude:
|
55
|
-
- 'spec/**/*.rb'
|
50
|
+
Naming/MethodParameterName:
|
51
|
+
Enabled: false
|
56
52
|
|
57
|
-
|
53
|
+
Naming/MemoizedInstanceVariableName:
|
58
54
|
Enabled: false
|
59
55
|
|
60
56
|
Lint/AssignmentInCondition:
|
61
57
|
Enabled: false
|
62
58
|
|
59
|
+
Lint/RaiseException:
|
60
|
+
Enabled: true
|
61
|
+
|
62
|
+
Lint/StructNewOverride:
|
63
|
+
Enabled: true
|
64
|
+
|
63
65
|
Style/EmptyMethod:
|
64
66
|
EnforcedStyle: expanded
|
65
67
|
|
66
68
|
Style/Alias:
|
67
69
|
EnforcedStyle: prefer_alias_method
|
68
70
|
|
71
|
+
Style/HashEachMethods:
|
72
|
+
Enabled: true
|
73
|
+
|
74
|
+
Style/HashTransformKeys:
|
75
|
+
Enabled: true
|
76
|
+
|
77
|
+
Style/HashTransformValues:
|
78
|
+
Enabled: true
|
79
|
+
|
69
80
|
Style/NumericPredicate:
|
70
81
|
EnforcedStyle: comparison
|
71
82
|
|
@@ -76,13 +87,13 @@ Style/RegexpLiteral:
|
|
76
87
|
Style/SignalException:
|
77
88
|
Enabled: false
|
78
89
|
|
79
|
-
Layout/
|
90
|
+
Layout/ParameterAlignment:
|
80
91
|
EnforcedStyle: with_fixed_indentation
|
81
92
|
|
82
|
-
Layout/
|
93
|
+
Layout/FirstHashElementIndentation:
|
83
94
|
EnforcedStyle: consistent
|
84
95
|
|
85
|
-
Layout/
|
96
|
+
Layout/HashAlignment:
|
86
97
|
# allow coder to get around alignment rules by explicitly defining the hash param
|
87
98
|
EnforcedLastArgumentHashStyle: ignore_explicit
|
88
99
|
|
@@ -124,10 +135,6 @@ Layout/MultilineAssignmentLayout:
|
|
124
135
|
StyleGuide: '#indent-conditional-assignment'
|
125
136
|
Enabled: true
|
126
137
|
|
127
|
-
Lint/UnneededDisable:
|
128
|
-
Exclude:
|
129
|
-
- 'spec/fixtures/**/*'
|
130
|
-
|
131
138
|
Lint/MissingCopEnableDirective:
|
132
139
|
Exclude:
|
133
140
|
- 'spec/fixtures/**/*'
|
data/README.md
CHANGED
data/danger-wcc.gemspec
CHANGED
@@ -1,7 +1,6 @@
|
|
1
|
-
|
2
1
|
# frozen_string_literal: true
|
3
2
|
|
4
|
-
lib = File.expand_path('
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
5
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
6
5
|
require 'version'
|
7
6
|
|
@@ -20,10 +19,11 @@ Gem::Specification.new do |spec|
|
|
20
19
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
21
20
|
spec.require_paths = ['lib']
|
22
21
|
|
22
|
+
spec.add_runtime_dependency 'activesupport', '> 5'
|
23
23
|
spec.add_runtime_dependency 'brakeman'
|
24
24
|
spec.add_runtime_dependency 'danger-plugin-api', '~> 1.0'
|
25
25
|
spec.add_runtime_dependency 'flay'
|
26
|
-
spec.add_runtime_dependency 'git_diff', '~> 0.
|
26
|
+
spec.add_runtime_dependency 'git_diff', '~> 0.4'
|
27
27
|
spec.add_runtime_dependency 'reek'
|
28
28
|
|
29
29
|
# General ruby development
|
@@ -36,7 +36,7 @@ Gem::Specification.new do |spec|
|
|
36
36
|
spec.add_development_dependency 'webmock', '~> 3.1'
|
37
37
|
|
38
38
|
# Linting code and docs
|
39
|
-
spec.add_development_dependency 'rubocop'
|
39
|
+
spec.add_development_dependency 'rubocop', '~> 0.81'
|
40
40
|
spec.add_development_dependency 'yard'
|
41
41
|
|
42
42
|
# Makes testing easy via `bundle exec guard`
|
data/lib/version.rb
CHANGED
data/lib/wcc/commit_lint.rb
CHANGED
@@ -102,7 +102,7 @@ class Danger::DangerWCC < Danger::Plugin
|
|
102
102
|
return unless c.fail?
|
103
103
|
|
104
104
|
messaging.issue([c.message, message[:sha]].join("\n"),
|
105
|
-
|
105
|
+
severity: severity)
|
106
106
|
end
|
107
107
|
|
108
108
|
def checkers
|
@@ -141,6 +141,7 @@ class Danger::DangerWCC < Danger::Plugin
|
|
141
141
|
|
142
142
|
def warning_checks
|
143
143
|
return checks if @config[:warn] == :all
|
144
|
+
|
144
145
|
@config[:warn] || []
|
145
146
|
end
|
146
147
|
|
data/lib/wcc/defaults.reek
CHANGED
@@ -23,10 +23,10 @@ DuplicateMethodCall:
|
|
23
23
|
allow_calls: []
|
24
24
|
FeatureEnvy:
|
25
25
|
enabled: true
|
26
|
-
exclude: []
|
26
|
+
exclude: ["Helper"]
|
27
27
|
InstanceVariableAssumption:
|
28
28
|
enabled: true
|
29
|
-
exclude: []
|
29
|
+
exclude: ["Controller"]
|
30
30
|
IrresponsibleModule:
|
31
31
|
enabled: false
|
32
32
|
exclude: []
|
@@ -54,7 +54,7 @@ NestedIterators:
|
|
54
54
|
ignore_iterators:
|
55
55
|
- tap
|
56
56
|
NilCheck:
|
57
|
-
enabled:
|
57
|
+
enabled: false
|
58
58
|
exclude: []
|
59
59
|
PrimaDonnaMethod:
|
60
60
|
enabled: true
|
@@ -70,15 +70,15 @@ Syntax:
|
|
70
70
|
enabled: true
|
71
71
|
exclude: []
|
72
72
|
TooManyConstants:
|
73
|
-
enabled:
|
73
|
+
enabled: true
|
74
74
|
exclude: []
|
75
75
|
max_constants: 5
|
76
76
|
TooManyInstanceVariables:
|
77
|
-
enabled:
|
77
|
+
enabled: true
|
78
78
|
exclude: []
|
79
79
|
max_instance_variables: 5
|
80
80
|
TooManyMethods:
|
81
|
-
enabled:
|
81
|
+
enabled: true
|
82
82
|
exclude: []
|
83
83
|
max_methods: 15
|
84
84
|
TooManyStatements:
|
@@ -127,5 +127,5 @@ UnusedPrivateMethod:
|
|
127
127
|
exclude: []
|
128
128
|
UtilityFunction:
|
129
129
|
enabled: true
|
130
|
-
exclude: []
|
131
|
-
public_methods_only:
|
130
|
+
exclude: ["Helper", "util"]
|
131
|
+
public_methods_only: true
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_support'
|
4
|
+
require_relative 'utils'
|
5
|
+
|
6
|
+
class Danger::DangerWCC < Danger::Plugin
|
7
|
+
class Dependencies
|
8
|
+
include Utils
|
9
|
+
|
10
|
+
def yarn_info
|
11
|
+
@yarn_info ||= YarnInfo.new(self) if File.exist?('yarn.lock')
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(plugin, options = {})
|
15
|
+
@plugin = plugin
|
16
|
+
@options = options
|
17
|
+
end
|
18
|
+
|
19
|
+
def perform
|
20
|
+
return unless File.exist?('yarn.lock')
|
21
|
+
|
22
|
+
find_yarn_violations
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def issue_yarn_violation(package, versions)
|
28
|
+
line_index = yarn_info.find_index_in_lockfile(package, versions[1])
|
29
|
+
|
30
|
+
plugin.fail "Dangerous change! #{package} was updated "\
|
31
|
+
"from #{versions[0]} to #{versions[1]}"\
|
32
|
+
' without a corresponding change to package.json!',
|
33
|
+
file: 'yarn.lock', line: line_index
|
34
|
+
end
|
35
|
+
|
36
|
+
def find_yarn_violations # rubocop:disable Metrics/AbcSize
|
37
|
+
# if there's a corresponding change in the package.json, ignore
|
38
|
+
mods =
|
39
|
+
yarn_info.modified_yarn_dependencies
|
40
|
+
.except(*yarn_info.package_json_changes)
|
41
|
+
.select { |_, versions| dangerous_change?(versions[0], versions[1]) }
|
42
|
+
|
43
|
+
has_dangerous_top_level_changes = false
|
44
|
+
# issue warnings for top level dependencies
|
45
|
+
mods.slice(*yarn_info.package_json_dependencies)
|
46
|
+
.each do |package, versions|
|
47
|
+
has_dangerous_top_level_changes = true
|
48
|
+
issue_yarn_violation(package, versions)
|
49
|
+
end
|
50
|
+
# issue warnings if a sub-dependency changed without a dangerous change in
|
51
|
+
# a top level dependency
|
52
|
+
return if has_dangerous_top_level_changes
|
53
|
+
|
54
|
+
mods.except(*yarn_info.package_json_dependencies)
|
55
|
+
.each do |package, versions|
|
56
|
+
issue_yarn_violation(package, versions)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def dangerous_change?(old_version, new_version)
|
61
|
+
# the package was deleted
|
62
|
+
return true unless new_version
|
63
|
+
|
64
|
+
old_segments = old_version.segments
|
65
|
+
new_segments = new_version.segments
|
66
|
+
|
67
|
+
# the major or minor version changed.
|
68
|
+
new_segments[0] > old_segments[0] ||
|
69
|
+
new_segments[1] > old_segments[1]
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
require_relative 'dependencies/yarn_info'
|
@@ -0,0 +1,83 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Danger::DangerWCC::Dependencies
|
4
|
+
class YarnInfo
|
5
|
+
def yarn_lock
|
6
|
+
@yarn_lock ||= File.readlines('yarn.lock')
|
7
|
+
end
|
8
|
+
|
9
|
+
def package_json_dependencies
|
10
|
+
@package_json_dependencies ||=
|
11
|
+
JSON.parse(File.read('package.json'))['dependencies']&.keys || []
|
12
|
+
end
|
13
|
+
|
14
|
+
def package_json_changes
|
15
|
+
@package_json_changes ||= find_package_json_changes
|
16
|
+
end
|
17
|
+
|
18
|
+
def modified_yarn_dependencies
|
19
|
+
@modified_yarn_dependencies ||= find_modified_yarn_packages
|
20
|
+
end
|
21
|
+
|
22
|
+
attr_reader :plugin
|
23
|
+
|
24
|
+
def initialize(plugin)
|
25
|
+
@plugin = plugin
|
26
|
+
end
|
27
|
+
|
28
|
+
def find_index_in_lockfile(package, version)
|
29
|
+
return 0 unless version
|
30
|
+
|
31
|
+
re = Regexp.new("^#{Regexp.escape(package)}@", Regexp::IGNORECASE)
|
32
|
+
indexes =
|
33
|
+
yarn_lock.each_with_index
|
34
|
+
.select { |l, _i| re.match(l) }
|
35
|
+
.map { |pair| pair[1] }
|
36
|
+
idx =
|
37
|
+
indexes.find do |i|
|
38
|
+
yarn_lock[i + 1].include?("version \"#{version}\"")
|
39
|
+
end
|
40
|
+
(idx || -1) + 1
|
41
|
+
end
|
42
|
+
|
43
|
+
def parse_yarn_semver(line)
|
44
|
+
match = /(?<package>\S+)\@(?<version>\S+)/.match(line)
|
45
|
+
[match['package'], Gem::Version.new(match['version'])] if match
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def find_package_json_changes
|
51
|
+
return [] unless file = plugin.find_file_in_diff('package.json')
|
52
|
+
|
53
|
+
adds = file.hunks.flat_map { |h| h.lines.select(&:addition?) }
|
54
|
+
adds.map { |l| /\"(?<package>\S+)\"\: \"\S+\"/.match(l.content) }
|
55
|
+
.compact
|
56
|
+
.map { |match| match['package'] }
|
57
|
+
end
|
58
|
+
|
59
|
+
def find_modified_yarn_packages # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
60
|
+
diff = plugin.run_and_diff(
|
61
|
+
'NODE_ENV=production yarn list --depth 0 2>/dev/null'
|
62
|
+
)
|
63
|
+
diff = GitDiff.from_string(diff)
|
64
|
+
|
65
|
+
{}.tap do |modified_packages|
|
66
|
+
plugin.each_file_in_diff(diff) do |file, _diff|
|
67
|
+
file.hunks.each do |hunk|
|
68
|
+
deleted, added =
|
69
|
+
%i[deletion? addition?].map do |type|
|
70
|
+
Hash[hunk.lines.select { |l| l.public_send(type) }
|
71
|
+
.map { |l| parse_yarn_semver(l.content) }
|
72
|
+
.compact]
|
73
|
+
end
|
74
|
+
deleted.each do |(package, version)|
|
75
|
+
modified_packages[package] =
|
76
|
+
[version, added[package]]
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
data/lib/wcc/jshint.rb
CHANGED
data/lib/wcc/plugin.rb
CHANGED
@@ -7,28 +7,33 @@ require_relative 'rubocop_exceptions'
|
|
7
7
|
require_relative 'commit_lint'
|
8
8
|
require_relative 'reek'
|
9
9
|
require_relative 'jshint'
|
10
|
+
require_relative 'dependencies'
|
10
11
|
|
11
12
|
class Danger::DangerWCC < Danger::Plugin
|
12
13
|
include Utils
|
13
14
|
include Github
|
14
15
|
|
15
|
-
|
16
|
-
rubocop_exceptions
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
jshint
|
23
|
-
|
16
|
+
DEFAULT_OPTIONS = {
|
17
|
+
rubocop_exceptions: true,
|
18
|
+
flay: true,
|
19
|
+
todos: true,
|
20
|
+
brakeman: true,
|
21
|
+
commit_lint: false,
|
22
|
+
reek: false,
|
23
|
+
jshint: false,
|
24
|
+
dependencies: true
|
25
|
+
}.freeze
|
24
26
|
|
25
27
|
# Runs all the included checks in the plugin
|
26
28
|
def all(options = {})
|
27
|
-
|
29
|
+
options = DEFAULT_OPTIONS.merge(options)
|
30
|
+
|
31
|
+
to_run = options.keys.reject { |check_name| options[check_name] == false }
|
28
32
|
raise ArgumentError, 'No Enabled Checks' if to_run.empty?
|
29
33
|
|
30
34
|
to_run.each do |check_name|
|
31
|
-
|
35
|
+
check_options = options.fetch(check_name, {})
|
36
|
+
public_send(check_name, check_options == true ? {} : check_options)
|
32
37
|
end
|
33
38
|
end
|
34
39
|
|
@@ -92,6 +97,11 @@ class Danger::DangerWCC < Danger::Plugin
|
|
92
97
|
Jshint.new(self, options).perform
|
93
98
|
end
|
94
99
|
|
100
|
+
def dependencies(options = {})
|
101
|
+
logger.info "dependencies: #{options}"
|
102
|
+
Dependencies.new(self, options).perform
|
103
|
+
end
|
104
|
+
|
95
105
|
private
|
96
106
|
|
97
107
|
def parse_flay_results
|