codeclimate-test-reporter 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'codeclimate-test-reporter'
5
+ require 'tmpdir'
6
+
7
+ if ENV["CODECLIMATE_REPO_TOKEN"]
8
+ tmpdir = Dir.tmpdir
9
+ puts "Searching #{tmpdir} for files to POST."
10
+ coverage_report_files = Dir.glob("#{tmpdir}/codeclimate-test-coverage-*")
11
+ if coverage_report_files.size > 0
12
+ puts "Found: "
13
+ puts coverage_report_files.join("\n")
14
+ client = CodeClimate::TestReporter::Client.new
15
+ print "Sending reports to #{client.host}..."
16
+ client.batch_post_results(coverage_report_files)
17
+ puts "done."
18
+ else
19
+ puts "No files found to POST."
20
+ end
21
+ else
22
+ $stderr.puts "Cannot batch post - environment variable CODECLIMATE_REPO_TOKEN must be set."
23
+ exit(1)
24
+ end
@@ -0,0 +1,20 @@
1
+ module CodeClimate
2
+ module TestReporter
3
+ VERSION = "0.0.6"
4
+
5
+ def self.start
6
+ if run?
7
+ require "simplecov"
8
+ ::SimpleCov.add_filter 'vendor'
9
+ ::SimpleCov.formatter = Formatter
10
+ ::SimpleCov.start("test_frameworks")
11
+ else
12
+ puts("Not reporting to Code Climate because ENV['CODECLIMATE_REPO_TOKEN'] is not set.")
13
+ end
14
+ end
15
+
16
+ def self.run?
17
+ !!ENV["CODECLIMATE_REPO_TOKEN"]
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,80 @@
1
+ require "json"
2
+ require "uri"
3
+ require "net/https"
4
+
5
+ module CodeClimate
6
+ module TestReporter
7
+
8
+ class Client
9
+
10
+ def host
11
+ ENV["CODECLIMATE_API_HOST"] ||
12
+ "https://codeclimate.com"
13
+ end
14
+
15
+ def batch_post_results(files)
16
+ uri = URI.parse("#{host}/test_reports/batch")
17
+ http = http_client(uri)
18
+
19
+ boundary = SecureRandom.uuid
20
+ post_body = []
21
+ post_body << "--#{boundary}\r\n"
22
+ post_body << "Content-Disposition: form-data; name=\"repo_token\"\r\n"
23
+ post_body << "\r\n"
24
+ post_body << ENV["CODECLIMATE_REPO_TOKEN"]
25
+ files.each_with_index do |file, index|
26
+ post_body << "\r\n--#{boundary}\r\n"
27
+ post_body << "Content-Disposition: form-data; name=\"coverage_reports[#{index}]\"; filename=\"#{File.basename(file)}\"\r\n"
28
+ post_body << "Content-Type: application/json\r\n"
29
+ post_body << "\r\n"
30
+ post_body << File.read(file)
31
+ end
32
+ post_body << "\r\n--#{boundary}--\r\n"
33
+ request = Net::HTTP::Post.new(uri.request_uri)
34
+ request.body = post_body.join
35
+ request["Content-Type"] = "multipart/form-data, boundary=#{boundary}"
36
+ response = http.request(request)
37
+
38
+ if response.code.to_i >= 200 && response.code.to_i < 300
39
+ response
40
+ else
41
+ raise "HTTP Error: #{response.code}"
42
+ end
43
+ end
44
+
45
+ def post_results(result)
46
+ uri = URI.parse("#{host}/test_reports")
47
+ http = http_client(uri)
48
+
49
+ request = Net::HTTP::Post.new(uri.path)
50
+ request["Content-Type"] = "application/json"
51
+ request.body = result.to_json
52
+
53
+ response = http.request(request)
54
+
55
+ if response.code.to_i >= 200 && response.code.to_i < 300
56
+ response
57
+ else
58
+ raise "HTTP Error: #{response.code}"
59
+ end
60
+ end
61
+
62
+ private
63
+
64
+ def http_client(uri)
65
+ Net::HTTP.new(uri.host, uri.port).tap do |http|
66
+ if uri.scheme == "https"
67
+ http.use_ssl = true
68
+ http.verify_mode = OpenSSL::SSL::VERIFY_PEER
69
+ http.ca_file = File.expand_path('../../config/cacert.pem', __FILE__)
70
+ http.verify_depth = 5
71
+ end
72
+ http.open_timeout = 5 # in seconds
73
+ http.read_timeout = 5 # in seconds
74
+ end
75
+ end
76
+
77
+ end
78
+
79
+ end
80
+ end
@@ -0,0 +1,151 @@
1
+ require "tmpdir"
2
+ require "securerandom"
3
+ require "json"
4
+ require "digest/sha1"
5
+
6
+ module CodeClimate
7
+ module TestReporter
8
+ class Formatter
9
+ def format(result)
10
+ print "Coverage = #{result.covered_percent.round(2)}%."
11
+
12
+ payload = to_payload(result)
13
+ if tddium? || ENV["TO_FILE"]
14
+ file_path = File.join(Dir.tmpdir, "codeclimate-test-coverage-#{SecureRandom.uuid}.json")
15
+ print "Coverage results saved to #{file_path}..."
16
+ File.open(file_path, "w") { |file| file.write(payload.to_json) }
17
+ else
18
+ client = Client.new
19
+ print "Sending report to #{client.host}... "
20
+ client.post_results(payload)
21
+ end
22
+
23
+ puts "done."
24
+ true
25
+ rescue => ex
26
+ puts "\nCode Climate encountered an exception: #{ex.class}"
27
+ puts ex.message
28
+ ex.backtrace.each do |line|
29
+ puts line
30
+ end
31
+ false
32
+ end
33
+
34
+ def partial?
35
+ tddium?
36
+ end
37
+
38
+ def to_payload(result)
39
+ totals = Hash.new(0)
40
+ source_files = result.files.map do |file|
41
+ totals[:total] += file.lines.count
42
+ totals[:covered] += file.covered_lines.count
43
+ totals[:missed] += file.missed_lines.count
44
+
45
+ {
46
+ name: short_filename(file.filename),
47
+ blob_id: calculate_blob_id(file.filename),
48
+ coverage: file.coverage.to_json,
49
+ covered_percent: file.covered_percent.round(2),
50
+ covered_strength: file.covered_strength.round(2),
51
+ line_counts: {
52
+ total: file.lines.count,
53
+ covered: file.covered_lines.count,
54
+ missed: file.missed_lines.count
55
+ }
56
+ }
57
+ end
58
+
59
+ {
60
+ repo_token: ENV["CODECLIMATE_REPO_TOKEN"],
61
+ source_files: source_files,
62
+ run_at: result.created_at,
63
+ covered_percent: result.covered_percent.round(2),
64
+ covered_strength: result.covered_strength.round(2),
65
+ line_counts: totals,
66
+ partial: partial?,
67
+ git: {
68
+ head: `git log -1 --pretty=format:'%H'`,
69
+ committed_at: committed_at,
70
+ branch: git_branch,
71
+ },
72
+ environment: {
73
+ test_framework: result.command_name.downcase,
74
+ pwd: Dir.pwd,
75
+ rails_root: (Rails.root.to_s rescue nil),
76
+ simplecov_root: ::SimpleCov.root,
77
+ gem_version: VERSION
78
+ },
79
+ ci_service: ci_service_data
80
+ }
81
+ end
82
+
83
+ def ci_service_data
84
+ if ENV['TRAVIS']
85
+ {
86
+ name: "travis-ci",
87
+ branch: ENV['TRAVIS_BRANCH'],
88
+ build_identifier: ENV['TRAVIS_JOB_ID'],
89
+ pull_request: ENV['TRAVIS_PULL_REQUEST']
90
+ }
91
+ elsif ENV['CIRCLECI']
92
+ {
93
+ name: "circlci",
94
+ build_identifier: ENV['CIRCLE_BUILD_NUM'],
95
+ branch: ENV['CIRCLE_BRANCH'],
96
+ commit_sha: ENV['CIRCLE_SHA1']
97
+ }
98
+ elsif ENV['SEMAPHORE']
99
+ {
100
+ name: "semaphore",
101
+ branch: ENV['BRANCH_NAME'],
102
+ build_identifier: ENV['SEMAPHORE_BUILD_NUMBER']
103
+ }
104
+ elsif ENV['JENKINS_URL']
105
+ {
106
+ name: "jenkins",
107
+ build_identifier: ENV['BUILD_NUMBER'],
108
+ build_url: ENV['BUILD_URL'],
109
+ branch: ENV['GIT_BRANCH'],
110
+ commit_sha: ENV['GIT_COMMIT']
111
+ }
112
+ elsif ENV['TDDIUM']
113
+ {
114
+ name: "tddium",
115
+ build_identifier: ENV['TDDIUM_SESSION_ID'],
116
+ worker_id: ENV['TDDIUM_TID']
117
+ }
118
+ else
119
+ {}
120
+ end
121
+ end
122
+
123
+ def calculate_blob_id(path)
124
+ content = File.open(path, "rb").read
125
+ header = "blob #{content.length}\0"
126
+ store = header + content
127
+ Digest::SHA1.hexdigest(store)
128
+ end
129
+
130
+ def short_filename(filename)
131
+ return filename unless ::SimpleCov.root
132
+ filename.gsub(::SimpleCov.root, '.').gsub(/^\.\//, '')
133
+ end
134
+
135
+ def committed_at
136
+ committed_at = `git log -1 --pretty=format:'%ct'`
137
+ committed_at.to_i.zero? ? nil : committed_at.to_i
138
+ end
139
+
140
+ def git_branch
141
+ branch = `git branch`.split("\n").delete_if { |i| i[0] != "*" }
142
+ branch = [branch].flatten.first
143
+ branch ? branch.gsub("* ","") : nil
144
+ end
145
+
146
+ def tddium?
147
+ ci_service_data && ci_service_data[:name] == "tddium"
148
+ end
149
+ end
150
+ end
151
+ end
@@ -1,175 +1,3 @@
1
- require "json"
2
- require "digest/sha1"
3
- require "net/https"
4
- require "uri"
5
-
6
- module CodeClimate
7
- class TestReporter
8
- VERSION = "0.0.5"
9
-
10
- class API
11
- def self.host
12
- ENV["CODECLIMATE_API_HOST"] ||
13
- "https://codeclimate.com"
14
- end
15
-
16
- def self.post_results(result)
17
- uri = URI.parse("#{host}/test_reports")
18
- http = Net::HTTP.new(uri.host, uri.port)
19
-
20
- if uri.scheme == "https"
21
- http.use_ssl = true
22
- http.verify_mode = OpenSSL::SSL::VERIFY_PEER
23
- http.ca_file = File.expand_path('../../config/cacert.pem', __FILE__)
24
- http.verify_depth = 5
25
- end
26
-
27
- http.open_timeout = 5 # in seconds
28
- http.read_timeout = 5 # in seconds
29
-
30
- request = Net::HTTP::Post.new(uri.path)
31
- request["Content-Type"] = "application/json"
32
- request.body = result.to_json
33
-
34
- response = http.request(request)
35
-
36
- if response.code.to_i >= 200 && response.code.to_i < 300
37
- response
38
- else
39
- raise "HTTP Error: #{response.code}"
40
- end
41
- end
42
- end
43
-
44
- class Formatter
45
- def format(result)
46
- totals = Hash.new(0)
47
-
48
- source_files = result.files.map do |file|
49
- totals[:total] += file.lines.count
50
- totals[:covered] += file.covered_lines.count
51
- totals[:missed] += file.missed_lines.count
52
-
53
- {
54
- name: short_filename(file.filename),
55
- blob_id: calculate_blob_id(file.filename),
56
- coverage: file.coverage.to_json,
57
- covered_percent: file.covered_percent.round(2),
58
- covered_strength: file.covered_strength.round(2),
59
- line_counts: {
60
- total: file.lines.count,
61
- covered: file.covered_lines.count,
62
- missed: file.missed_lines.count
63
- }
64
- }
65
- end
66
-
67
- print "Coverage = #{result.covered_percent.round(2)}%. Sending report to #{API.host}... "
68
-
69
- API.post_results({
70
- repo_token: ENV["CODECLIMATE_REPO_TOKEN"],
71
- source_files: source_files,
72
- run_at: result.created_at,
73
- covered_percent: result.covered_percent.round(2),
74
- covered_strength: result.covered_strength.round(2),
75
- line_counts: totals,
76
- git: {
77
- head: `git log -1 --pretty=format:'%H'`,
78
- committed_at: committed_at,
79
- branch: git_branch,
80
- },
81
- environment: {
82
- test_framework: result.command_name.downcase,
83
- pwd: Dir.pwd,
84
- rails_root: (Rails.root.to_s rescue nil),
85
- simplecov_root: ::SimpleCov.root,
86
- gem_version: VERSION
87
- },
88
- ci_service: ci_service_data
89
- })
90
-
91
- puts "done."
92
- true
93
- rescue => ex
94
- puts "\nCode Climate encountered an exception: #{ex.class}"
95
- puts ex.message
96
- ex.backtrace.each do |line|
97
- puts line
98
- end
99
- false
100
- end
101
-
102
- def ci_service_data
103
- if ENV['TRAVIS']
104
- {
105
- name: "travis-ci",
106
- branch: ENV['TRAVIS_BRANCH'],
107
- build_identifier: ENV['TRAVIS_JOB_ID'],
108
- pull_request: ENV['TRAVIS_PULL_REQUEST']
109
- }
110
- elsif ENV['CIRCLECI']
111
- {
112
- name: "circlci",
113
- build_identifier: ENV['CIRCLE_BUILD_NUM'],
114
- branch: ENV['CIRCLE_BRANCH'],
115
- commit_sha: ENV['CIRCLE_SHA1']
116
- }
117
- elsif ENV['SEMAPHORE']
118
- {
119
- name: "semaphore",
120
- branch: ENV['BRANCH_NAME'],
121
- build_identifier: ENV['SEMAPHORE_BUILD_NUMBER']
122
- }
123
- elsif ENV['JENKINS_URL']
124
- {
125
- name: "jenkins",
126
- build_identifier: ENV['BUILD_NUMBER'],
127
- build_url: ENV['BUILD_URL'],
128
- branch: ENV['GIT_BRANCH'],
129
- commit_sha: ENV['GIT_COMMIT']
130
- }
131
- else
132
- {}
133
- end
134
- end
135
-
136
- def calculate_blob_id(path)
137
- content = File.open(path, "rb").read
138
- header = "blob #{content.length}\0"
139
- store = header + content
140
- Digest::SHA1.hexdigest(store)
141
- end
142
-
143
- def short_filename(filename)
144
- return filename unless ::SimpleCov.root
145
- filename.gsub(::SimpleCov.root, '.').gsub(/^\.\//, '')
146
- end
147
-
148
- def committed_at
149
- committed_at = `git log -1 --pretty=format:'%ct'`
150
- committed_at.to_i.zero? ? nil : committed_at.to_i
151
- end
152
-
153
- def git_branch
154
- branch = `git branch`.split("\n").delete_if { |i| i[0] != "*" }
155
- branch = [branch].flatten.first
156
- branch ? branch.gsub("* ","") : nil
157
- end
158
- end
159
-
160
- def self.start
161
- if run?
162
- require "simplecov"
163
- ::SimpleCov.add_filter 'vendor'
164
- ::SimpleCov.formatter = Formatter
165
- ::SimpleCov.start("test_frameworks")
166
- else
167
- puts("Not reporting to Code Climate because ENV['CODECLIMATE_REPO_TOKEN'] is not set.")
168
- end
169
- end
170
-
171
- def self.run?
172
- !!ENV["CODECLIMATE_REPO_TOKEN"]
173
- end
174
- end
175
- end
1
+ require 'code_climate/test_reporter'
2
+ require "code_climate/test_reporter/client"
3
+ require "code_climate/test_reporter/formatter"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: codeclimate-test-reporter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-07-28 00:00:00.000000000 Z
12
+ date: 2013-09-09 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: simplecov
@@ -69,7 +69,8 @@ description: Collects test coverage data from your Ruby test suite and sends it
69
69
  Code Climate's hosted, automated code review service. Based on SimpleCov.
70
70
  email:
71
71
  - bryan@brynary.com
72
- executables: []
72
+ executables:
73
+ - cc-tddium-post-worker
73
74
  extensions: []
74
75
  extra_rdoc_files: []
75
76
  files:
@@ -78,8 +79,12 @@ files:
78
79
  - LICENSE.txt
79
80
  - README.md
80
81
  - Rakefile
82
+ - bin/cc-tddium-post-worker
81
83
  - codeclimate-test-reporter.gemspec
82
84
  - config/cacert.pem
85
+ - lib/code_climate/test_reporter.rb
86
+ - lib/code_climate/test_reporter/client.rb
87
+ - lib/code_climate/test_reporter/formatter.rb
83
88
  - lib/codeclimate-test-reporter.rb
84
89
  - spec/spec_helper.rb
85
90
  homepage: ''
@@ -108,3 +113,4 @@ specification_version: 3
108
113
  summary: Uploads Ruby test coverage data to Code Climate.
109
114
  test_files:
110
115
  - spec/spec_helper.rb
116
+ has_rdoc: