codeclimate 0.14.0 → 0.14.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d13448b3cac119e109b7c8803f6a9ad3d40c7cfc
4
- data.tar.gz: ca2b0a4d9ce066010654c5c4b33f648e671c80f1
3
+ metadata.gz: f7d10a3e340b114a674a576928f4fcfecf003804
4
+ data.tar.gz: f457eb3fc54b3e7e63aeb3d64010b57736c4165d
5
5
  SHA512:
6
- metadata.gz: af40f37bcad31b287e4e89cd903a327381c435d9925343aff88a05d3c15816e4f99a4c8cceb2de1f635bedbfc11544375fbabf662436473eb818069d3a6e43e1
7
- data.tar.gz: 0ebed34277ebffadb88133ffc92a61ec07c14f732ae3c67bb9d6e496cdf40590d40219d53d8f2c919cc4d5d79315b2110d7abf69bc2ed529e742936959698174
6
+ metadata.gz: 7abfdf98943e97e6a5c43cb5a63f767e15b98a5b2b67ad2353ed417e3ce2835f8478dbe7b38f7de025128c5f79245db70c67e2faacbff2538e7a237cb0e00265
7
+ data.tar.gz: f97c25a43e0e1b44b1f05c6e5bbff19fbbbe5a018bd4008dcadadf28ff233c9951c981c6c7a556cae2ef23a540792854afc22ef74a3f0c8c147b045e724c09e0
data/bin/codeclimate CHANGED
@@ -4,5 +4,6 @@ $LOAD_PATH.unshift(File.expand_path(File.join(File.dirname(__FILE__), "../lib"))
4
4
  require "cc/cli"
5
5
 
6
6
  ENV["FILESYSTEM_DIR"] ||= "."
7
+ ENV["CODE_PATH"] ||= ENV["PWD"]
7
8
 
8
9
  CC::CLI::Runner.run(ARGV)
@@ -0,0 +1,129 @@
1
+ {
2
+ "arrow_spacing": {
3
+ "level": "ignore"
4
+ },
5
+ "braces_spacing": {
6
+ "level": "ignore",
7
+ "spaces": 0,
8
+ "empty_object_spaces": 0
9
+ },
10
+ "camel_case_classes": {
11
+ "level": "error"
12
+ },
13
+ "coffeescript_error": {
14
+ "level": "error"
15
+ },
16
+ "colon_assignment_spacing": {
17
+ "level": "ignore",
18
+ "spacing": {
19
+ "left": 0,
20
+ "right": 0
21
+ }
22
+ },
23
+ "cyclomatic_complexity": {
24
+ "value": 10,
25
+ "level": "ignore"
26
+ },
27
+ "duplicate_key": {
28
+ "level": "error"
29
+ },
30
+ "empty_constructor_needs_parens": {
31
+ "level": "ignore"
32
+ },
33
+ "ensure_comprehensions": {
34
+ "level": "warn"
35
+ },
36
+ "eol_last": {
37
+ "level": "ignore"
38
+ },
39
+ "indentation": {
40
+ "value": 2,
41
+ "level": "error"
42
+ },
43
+ "line_endings": {
44
+ "level": "ignore",
45
+ "value": "unix"
46
+ },
47
+ "max_line_length": {
48
+ "value": 80,
49
+ "level": "error",
50
+ "limitComments": true
51
+ },
52
+ "missing_fat_arrows": {
53
+ "level": "ignore",
54
+ "is_strict": false
55
+ },
56
+ "newlines_after_classes": {
57
+ "value": 3,
58
+ "level": "ignore"
59
+ },
60
+ "no_backticks": {
61
+ "level": "error"
62
+ },
63
+ "no_debugger": {
64
+ "level": "warn",
65
+ "console": false
66
+ },
67
+ "no_empty_functions": {
68
+ "level": "ignore"
69
+ },
70
+ "no_empty_param_list": {
71
+ "level": "ignore"
72
+ },
73
+ "no_implicit_braces": {
74
+ "level": "ignore",
75
+ "strict": true
76
+ },
77
+ "no_implicit_parens": {
78
+ "strict": true,
79
+ "level": "ignore"
80
+ },
81
+ "no_interpolation_in_single_quotes": {
82
+ "level": "ignore"
83
+ },
84
+ "no_plusplus": {
85
+ "level": "ignore"
86
+ },
87
+ "no_stand_alone_at": {
88
+ "level": "ignore"
89
+ },
90
+ "no_tabs": {
91
+ "level": "error"
92
+ },
93
+ "no_this": {
94
+ "level": "ignore"
95
+ },
96
+ "no_throwing_strings": {
97
+ "level": "error"
98
+ },
99
+ "no_trailing_semicolons": {
100
+ "level": "error"
101
+ },
102
+ "no_trailing_whitespace": {
103
+ "level": "error",
104
+ "allowed_in_comments": false,
105
+ "allowed_in_empty_lines": true
106
+ },
107
+ "no_unnecessary_double_quotes": {
108
+ "level": "ignore"
109
+ },
110
+ "no_unnecessary_fat_arrows": {
111
+ "level": "warn"
112
+ },
113
+ "non_empty_constructor_needs_parens": {
114
+ "level": "ignore"
115
+ },
116
+ "prefer_english_operator": {
117
+ "level": "ignore",
118
+ "doubleNotLevel": "ignore"
119
+ },
120
+ "space_operators": {
121
+ "level": "ignore"
122
+ },
123
+ "spacing_after_comma": {
124
+ "level": "ignore"
125
+ },
126
+ "transform_messes_up_line_numbers": {
127
+ "level": "warn"
128
+ }
129
+ }
@@ -63,6 +63,7 @@ module CC
63
63
 
64
64
  def config_file
65
65
  path = File.join("/tmp/cc", SecureRandom.uuid)
66
+ FileUtils.mkdir_p("/tmp/cc")
66
67
  File.write(path, @config.to_json)
67
68
  path
68
69
  end
data/lib/cc/cli.rb CHANGED
@@ -12,6 +12,7 @@ module CC
12
12
  autoload :Help, "cc/cli/help"
13
13
  autoload :Init, "cc/cli/init"
14
14
  autoload :Runner, "cc/cli/runner"
15
+ autoload :Test, "cc/cli/test"
15
16
  autoload :ValidateConfig, "cc/cli/validate_config"
16
17
  autoload :Version, "cc/cli/version"
17
18
  end
@@ -0,0 +1,270 @@
1
+ require "shellwords"
2
+ require "cc/yaml"
3
+
4
+ module CC
5
+ module CLI
6
+ class Marker
7
+ def self.from_text(engine_name, test_file, line_number, text)
8
+ marker = Marker.new(line_number, text)
9
+ attrs = attrs_from_marker(text.sub(/^.*\[issue\] ?/, ""))
10
+
11
+ marker.issue = attrs.merge(
12
+ "engine_name" => engine_name,
13
+ "location" => {
14
+ "path" => test_file,
15
+ "lines" => {
16
+ "begin" => line_number + 1,
17
+ "end" => line_number + 1,
18
+ },
19
+ },
20
+ )
21
+
22
+ if marker.issue["category"]
23
+ marker.issue["categories"] = Array.wrap(marker.issue["category"])
24
+ marker.issue.delete("category")
25
+ end
26
+
27
+ marker
28
+ end
29
+
30
+ def self.attrs_from_marker(text)
31
+ if text.blank?
32
+ {}
33
+ else
34
+ matches = text.scan(/([a-z\._-]+)=(?:(")((?:\\.|[^"])*)"|([^\s]*))/).map(&:compact)
35
+
36
+ key_values = matches.map do |match|
37
+ munge_match(match)
38
+ end
39
+
40
+ Hash[key_values]
41
+ end
42
+ end
43
+
44
+ def self.munge_match(match)
45
+ if match.size == 3 # Quoted
46
+ key, _, value = match
47
+ value = '"' + value + '"'
48
+ else
49
+ key, value = match
50
+ end
51
+
52
+ [key, munge_value(value)]
53
+ end
54
+
55
+ def self.munge_value(value)
56
+ JSON.load(value)
57
+ rescue JSON::ParserError
58
+ value
59
+ end
60
+
61
+ attr_reader :line, :line_text
62
+ attr_accessor :issue
63
+
64
+ def initialize(line, line_text)
65
+ @line = line
66
+ @line_text = line_text
67
+ @issue = issue
68
+ end
69
+ end
70
+
71
+ class Test < Command
72
+ def run
73
+ @engine_name = @args.first
74
+
75
+ if @engine_name.blank?
76
+ fatal "Usage: codeclimate test #{rainbow.wrap('engine_name').underline}"
77
+ end
78
+
79
+ test_engine
80
+ end
81
+
82
+ def test_engine
83
+ within_tempdir do
84
+ prepare_working_dir
85
+ unpack_tests
86
+ run_tests
87
+ end
88
+ ensure
89
+ remove_null_container
90
+ end
91
+
92
+ def within_tempdir
93
+ tmpdir = create_tmpdir
94
+
95
+ Dir.chdir(tmpdir) do
96
+ yield
97
+ end
98
+ ensure
99
+ FileUtils.rm_rf(tmpdir)
100
+ end
101
+
102
+ def unpack_tests
103
+ test_paths.each do |test_path|
104
+ unpack(test_path)
105
+ end
106
+ end
107
+
108
+ def run_tests
109
+ Dir["**/*"].each do |test_file|
110
+ next unless File.file?(test_file)
111
+ process_file(test_file)
112
+ end
113
+ end
114
+
115
+ def process_file(test_file)
116
+ markers = markers_in(test_file)
117
+
118
+ actual_issues = issues_in(test_file)
119
+ compare_issues(actual_issues, markers)
120
+ end
121
+
122
+ def compare_issues(actual_issues, markers)
123
+ markers.each do |marker|
124
+ validate_issue(marker, actual_issues)
125
+ end
126
+
127
+ validate_unexpected_issues(actual_issues)
128
+ end
129
+
130
+ def validate_issue(marker, actual_issues)
131
+ if (index = locate_match(actual_issues, marker))
132
+ announce_pass(marker)
133
+ actual_issues.delete_at(index)
134
+ else
135
+ announce_fail(marker, actual_issues)
136
+ fatal "Expected issue not found."
137
+ end
138
+ end
139
+
140
+ def locate_match(actual_issues, marker)
141
+ actual_issues.each_with_index do |actual, index|
142
+ if fuzzy_match(marker.issue, actual)
143
+ return index
144
+ end
145
+ end
146
+
147
+ nil
148
+ end
149
+
150
+ def announce_pass(marker)
151
+ say format("PASS %3d: %s", marker.line, marker.line_text)
152
+ end
153
+
154
+ def announce_fail(marker, actual_issues)
155
+ say colorize(format("FAIL %3d: %s", marker.line, marker.line_text), :red)
156
+ say colorize("Expected:", :yellow)
157
+ say colorize(JSON.pretty_generate(marker.issue), :yellow)
158
+ say "\n"
159
+ say colorize("Actual:", :yellow)
160
+ say colorize(JSON.pretty_generate(actual_issues), :yellow)
161
+ end
162
+
163
+ def validate_unexpected_issues(actual_issues)
164
+ if actual_issues.any?
165
+ say colorize("Actuals not empty after matching.", :red)
166
+ say
167
+ say colorize("#{actual_issues.size} remaining:", :yellow)
168
+ say colorize(JSON.pretty_generate(actual_issues), :yellow)
169
+ fatal "Unexpected issue found."
170
+ end
171
+ end
172
+
173
+ def fuzzy_match(expected, actual)
174
+ expected.all? do |key, value|
175
+ actual[key] == value
176
+ end
177
+ end
178
+
179
+ def issues_in(test_file)
180
+ issue_docs = capture_stdout do
181
+ codeclimate_analyze(test_file)
182
+ end
183
+
184
+ JSON.parse(issue_docs)
185
+ end
186
+
187
+ def codeclimate_analyze(relative_path)
188
+ codeclimate_path = File.expand_path(File.join(File.dirname(__FILE__), "../../../bin/codeclimate"))
189
+
190
+ system([
191
+ "unset CODE_PATH &&",
192
+ "unset FILESYSTEM_DIR &&",
193
+ Shellwords.escape(codeclimate_path),
194
+ "analyze",
195
+ "--engine", Shellwords.escape(@engine_name),
196
+ "-f", "json",
197
+ Shellwords.escape(relative_path)
198
+ ].join(" "))
199
+ end
200
+
201
+ def prepare_working_dir
202
+ `git init`
203
+
204
+ File.open(".codeclimate.yml", "w") do |config|
205
+ config.write("engines:\n #{@engine_name}:\n enabled: true")
206
+ end
207
+ end
208
+
209
+ def markers_in(test_file)
210
+ lines = File.readlines(test_file)
211
+
212
+ [].tap do |markers|
213
+ lines.each_with_index do |line, index|
214
+ if line =~ /\[issue\].*/
215
+ markers << Marker.from_text(@engine_name, test_file, index + 1, line)
216
+ end
217
+ end
218
+ end
219
+ end
220
+
221
+ def create_tmpdir
222
+ tmpdir = File.join("/tmp/cc", SecureRandom.uuid)
223
+ FileUtils.mkdir_p(tmpdir)
224
+ tmpdir
225
+ end
226
+
227
+ def unpack(path)
228
+ system("docker cp #{null_container_id}:#{path} .")
229
+ end
230
+
231
+ def null_container_id
232
+ # docker cp only works with containers, not images so
233
+ # workaround it by creating a throwaway container
234
+ @null_container_id = `docker run -d #{engine_image} false`.chomp
235
+ end
236
+
237
+ def remove_null_container
238
+ `docker rm -f #{null_container_id}` if null_container_id
239
+ end
240
+
241
+ def test_paths
242
+ Array.wrap(engine_spec["test_paths"])
243
+ end
244
+
245
+ def engine_spec
246
+ @engine_spec ||= JSON.parse(`docker run --rm #{engine_image} cat /engine.json`)
247
+ end
248
+
249
+ def engine_image
250
+ engine_registry[@engine_name]["image"]
251
+ end
252
+
253
+ # Stolen from ActiveSupport (where it was deprecated)
254
+ def capture_stdout
255
+ captured_stream = Tempfile.new("stdout")
256
+ origin_stream = $stdout.dup
257
+ $stdout.reopen(captured_stream)
258
+
259
+ yield
260
+
261
+ $stdout.rewind
262
+ return captured_stream.read
263
+ ensure
264
+ captured_stream.close
265
+ captured_stream.unlink
266
+ $stdout.reopen(origin_stream)
267
+ end
268
+ end
269
+ end
270
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: codeclimate
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.14.0
4
+ version: 0.14.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Code Climate
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-11-05 00:00:00.000000000 Z
11
+ date: 2015-11-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -50,14 +50,14 @@ dependencies:
50
50
  requirements:
51
51
  - - "~>"
52
52
  - !ruby/object:Gem::Version
53
- version: 0.4.0
53
+ version: 0.5.0
54
54
  type: :runtime
55
55
  prerelease: false
56
56
  version_requirements: !ruby/object:Gem::Requirement
57
57
  requirements:
58
58
  - - "~>"
59
59
  - !ruby/object:Gem::Version
60
- version: 0.4.0
60
+ version: 0.5.0
61
61
  - !ruby/object:Gem::Dependency
62
62
  name: faraday
63
63
  requirement: !ruby/object:Gem::Requirement
@@ -193,6 +193,7 @@ files:
193
193
  - bin/codeclimate-init
194
194
  - bin/prep-release
195
195
  - bin/release
196
+ - config/coffeelint/coffeelint.json
196
197
  - config/csslint/.csslintrc
197
198
  - config/engines.yml
198
199
  - config/eslint/.eslintrc
@@ -237,6 +238,7 @@ files:
237
238
  - lib/cc/cli/help.rb
238
239
  - lib/cc/cli/init.rb
239
240
  - lib/cc/cli/runner.rb
241
+ - lib/cc/cli/test.rb
240
242
  - lib/cc/cli/upgrade_config_generator.rb
241
243
  - lib/cc/cli/validate_config.rb
242
244
  - lib/cc/cli/version.rb
@@ -261,7 +263,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
261
263
  version: '0'
262
264
  requirements: []
263
265
  rubyforge_project:
264
- rubygems_version: 2.4.8
266
+ rubygems_version: 2.4.5
265
267
  signing_key:
266
268
  specification_version: 4
267
269
  summary: Code Climate CLI