codecov 0.2.12 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 98728653c21cce7decd7a9b031e54e950da789d70c464bb61e53e1964372ac1d
4
- data.tar.gz: 8d45300d929ff5bd39cb5cfb562960ef1bf3b36b1f51754376f25c8ac8ae3a31
3
+ metadata.gz: 28cb9ca7e98d8d586f0c8118cc099def187c61c2cd1bc36882dd835959030404
4
+ data.tar.gz: 2ae5223947def7a015e0b92fb591f1090cb086406d7f44e284a241a022a54fa4
5
5
  SHA512:
6
- metadata.gz: bdd1f35739f17cc5110ea0c2fa51bf4939812b96ff96009311dfb52ea67b63107cdbfbb8ad6e9b76f1cdc1104a136407bf1f9e89d1509c717131d9b03e62a986
7
- data.tar.gz: 84673f1a411a1b7746b04448a79aa9a84b3e5606d14f7c70b6adee66be765f66ba2caed073cda2dc837788b7a67cc3a0c6c232655533e1170ea0865b30f77c93
6
+ metadata.gz: f43851f9d6c5b8603bea783df5f52dfc40cc5290dfeb741cee23639bd00a60ab1916b73001f7b17652b11839f995b8bc963b151a71e4a7615510f1f129fe6d28
7
+ data.tar.gz: '082f364e342d308a06b25c7955949e225bc8c93d730cbb86d1542c881175441740ffd802e070c071a65f45a8e5df4a536fd4811ef0fc18d732d9e04a8dc046bb'
@@ -6,617 +6,12 @@ require 'net/http'
6
6
  require 'simplecov'
7
7
  require 'zlib'
8
8
 
9
- class SimpleCov::Formatter::Codecov
10
- VERSION = '0.2.12'
11
-
12
- ### CIs
13
- RECOGNIZED_CIS = [
14
- APPVEYOR = 'Appveyor CI',
15
- AZUREPIPELINES = 'Azure Pipelines',
16
- BITBUCKET = 'Bitbucket',
17
- BITRISE = 'Bitrise CI',
18
- BUILDKITE = 'Buildkite CI',
19
- CIRCLE = 'Circle CI',
20
- CODEBUILD = 'Codebuild CI',
21
- CODESHIP = 'Codeship CI',
22
- DRONEIO = 'Drone CI',
23
- GITHUB = 'GitHub Actions',
24
- GITLAB = 'GitLab CI',
25
- HEROKU = 'Heroku CI',
26
- JENKINS = 'Jenkins CI',
27
- SEMAPHORE = 'Semaphore CI',
28
- SHIPPABLE = 'Shippable',
29
- SOLANO = 'Solano CI',
30
- TEAMCITY = 'TeamCity CI',
31
- TRAVIS = 'Travis CI',
32
- WERCKER = 'Wercker CI'
33
- ].freeze
34
-
35
- def display_header
36
- puts [
37
- '',
38
- ' _____ _',
39
- ' / ____| | |',
40
- '| | ___ __| | ___ ___ _____ __',
41
- '| | / _ \ / _\`|/ _ \/ __/ _ \ \ / /',
42
- '| |___| (_) | (_| | __/ (_| (_) \ V /',
43
- ' \_____\___/ \__,_|\___|\___\___/ \_/',
44
- " Ruby-#{VERSION}",
45
- ''
46
- ].join("\n")
47
- end
48
-
49
- def detect_ci
50
- ci = if (ENV['CI'] == 'True') && (ENV['APPVEYOR'] == 'True')
51
- APPVEYOR
52
- elsif !ENV['TF_BUILD'].nil?
53
- AZUREPIPELINES
54
- elsif (ENV['CI'] == 'true') && !ENV['BITBUCKET_BRANCH'].nil?
55
- BITBUCKET
56
- elsif (ENV['CI'] == 'true') && (ENV['BITRISE_IO'] == 'true')
57
- BITRISE
58
- elsif (ENV['CI'] == 'true') && (ENV['BUILDKITE'] == 'true')
59
- BUILDKITE
60
- elsif (ENV['CI'] == 'true') && (ENV['CIRCLECI'] == 'true')
61
- CIRCLE
62
- elsif ENV['CODEBUILD_CI'] == 'true'
63
- CODEBUILD
64
- elsif (ENV['CI'] == 'true') && (ENV['CI_NAME'] == 'codeship')
65
- CODESHIP
66
- elsif ((ENV['CI'] == 'true') || (ENV['CI'] == 'drone')) && (ENV['DRONE'] == 'true')
67
- DRONEIO
68
- elsif (ENV['CI'] == 'true') && (ENV['GITHUB_ACTIONS'] == 'true')
69
- GITHUB
70
- elsif !ENV['GITLAB_CI'].nil?
71
- GITLAB
72
- elsif ENV['HEROKU_TEST_RUN_ID']
73
- HEROKU
74
- elsif !ENV['JENKINS_URL'].nil?
75
- JENKINS
76
- elsif (ENV['CI'] == 'true') && (ENV['SEMAPHORE'] == 'true')
77
- SEMAPHORE
78
- elsif (ENV['CI'] == 'true') && (ENV['SHIPPABLE'] == 'true')
79
- SHIPPABLE
80
- elsif ENV['TDDIUM'] == 'true'
81
- SOLANO
82
- elsif ENV['CI_SERVER_NAME'] == 'TeamCity'
83
- TEAMCITY
84
- elsif (ENV['CI'] == 'true') && (ENV['TRAVIS'] == 'true')
85
- TRAVIS
86
- elsif (ENV['CI'] == 'true') && !ENV['WERCKER_GIT_BRANCH'].nil?
87
- WERCKER
88
- end
89
-
90
- if !RECOGNIZED_CIS.include?(ci)
91
- puts [red('x>'), 'No CI provider detected.'].join(' ')
92
- else
93
- puts "==> #{ci} detected"
94
- end
95
-
96
- ci
97
- end
98
-
99
- def build_params(ci)
100
- params = {
101
- 'token' => ENV['CODECOV_TOKEN'],
102
- 'flags' => ENV['CODECOV_FLAG'] || ENV['CODECOV_FLAGS'],
103
- 'package' => "ruby-#{VERSION}"
104
- }
105
-
106
- case ci
107
- when APPVEYOR
108
- # http://www.appveyor.com/docs/environment-variables
109
- params[:service] = 'appveyor'
110
- params[:branch] = ENV['APPVEYOR_REPO_BRANCH']
111
- params[:build] = ENV['APPVEYOR_JOB_ID']
112
- params[:pr] = ENV['APPVEYOR_PULL_REQUEST_NUMBER']
113
- params[:job] = ENV['APPVEYOR_ACCOUNT_NAME'] + '/' + ENV['APPVEYOR_PROJECT_SLUG'] + '/' + ENV['APPVEYOR_BUILD_VERSION']
114
- params[:slug] = ENV['APPVEYOR_REPO_NAME']
115
- params[:commit] = ENV['APPVEYOR_REPO_COMMIT']
116
- when AZUREPIPELINES
117
- params[:service] = 'azure_pipelines'
118
- params[:branch] = ENV['BUILD_SOURCEBRANCH']
119
- params[:pull_request] = ENV['SYSTEM_PULLREQUEST_PULLREQUESTNUMBER']
120
- params[:job] = ENV['SYSTEM_JOBID']
121
- params[:build] = ENV['BUILD_BUILDID']
122
- params[:build_url] = "#{ENV['SYSTEM_TEAMFOUNDATIONSERVERURI']}/#{ENV['SYSTEM_TEAMPROJECT']}/_build/results?buildId=#{ENV['BUILD_BUILDID']}"
123
- params[:commit] = ENV['BUILD_SOURCEVERSION']
124
- params[:slug] = ENV['BUILD_REPOSITORY_ID']
125
- when BITBUCKET
126
- # https://confluence.atlassian.com/bitbucket/variables-in-pipelines-794502608.html
127
- params[:service] = 'bitbucket'
128
- params[:branch] = ENV['BITBUCKET_BRANCH']
129
- # BITBUCKET_COMMIT does not always provide full commit sha due to a bug https://jira.atlassian.com/browse/BCLOUD-19393#
130
- params[:commit] = (ENV['BITBUCKET_COMMIT'].length < 40 ? nil : ENV['BITBUCKET_COMMIT'])
131
- params[:build] = ENV['BITBUCKET_BUILD_NUMBER']
132
- when BITRISE
133
- # http://devcenter.bitrise.io/faq/available-environment-variables/
134
- params[:service] = 'bitrise'
135
- params[:branch] = ENV['BITRISE_GIT_BRANCH']
136
- params[:pr] = ENV['BITRISE_PULL_REQUEST']
137
- params[:build] = ENV['BITRISE_BUILD_NUMBER']
138
- params[:build_url] = ENV['BITRISE_BUILD_URL']
139
- params[:commit] = ENV['BITRISE_GIT_COMMIT']
140
- params[:slug] = ENV['BITRISEIO_GIT_REPOSITORY_OWNER'] + '/' + ENV['BITRISEIO_GIT_REPOSITORY_SLUG']
141
- when BUILDKITE
142
- # https://buildkite.com/docs/guides/environment-variables
143
- params[:service] = 'buildkite'
144
- params[:branch] = ENV['BUILDKITE_BRANCH']
145
- params[:build] = ENV['BUILDKITE_BUILD_NUMBER']
146
- params[:job] = ENV['BUILDKITE_JOB_ID']
147
- params[:build_url] = ENV['BUILDKITE_BUILD_URL']
148
- params[:slug] = ENV['BUILDKITE_PROJECT_SLUG']
149
- params[:commit] = ENV['BUILDKITE_COMMIT']
150
- when CIRCLE
151
- # https://circleci.com/docs/environment-variables
152
- params[:service] = 'circleci'
153
- params[:build] = ENV['CIRCLE_BUILD_NUM']
154
- params[:job] = ENV['CIRCLE_NODE_INDEX']
155
- params[:slug] = if !ENV['CIRCLE_PROJECT_REPONAME'].nil?
156
- ENV['CIRCLE_PROJECT_USERNAME'] + '/' + ENV['CIRCLE_PROJECT_REPONAME']
157
- else
158
- ENV['CIRCLE_REPOSITORY_URL'].gsub(/^.*:/, '').gsub(/\.git$/, '')
159
- end
160
- params[:pr] = ENV['CIRCLE_PR_NUMBER']
161
- params[:branch] = ENV['CIRCLE_BRANCH']
162
- params[:commit] = ENV['CIRCLE_SHA1']
163
- when CODEBUILD
164
- # https://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref-env-vars.html
165
- params[:service] = 'codebuild'
166
- params[:branch] = ENV['CODEBUILD_WEBHOOK_HEAD_REF'].split('/')[2]
167
- params[:build] = ENV['CODEBUILD_BUILD_ID']
168
- params[:commit] = ENV['CODEBUILD_RESOLVED_SOURCE_VERSION']
169
- params[:job] = ENV['CODEBUILD_BUILD_ID']
170
- params[:slug] = ENV['CODEBUILD_SOURCE_REPO_URL'].match(/.*github.com\/(?<slug>.*).git/)['slug']
171
- params[:pr] = if ENV['CODEBUILD_SOURCE_VERSION']
172
- matched = ENV['CODEBUILD_SOURCE_VERSION'].match(%r{pr/(?<pr>.*)})
173
- matched.nil? ? ENV['CODEBUILD_SOURCE_VERSION'] : matched['pr']
174
- end
175
- when CODESHIP
176
- # https://www.codeship.io/documentation/continuous-integration/set-environment-variables/
177
- params[:service] = 'codeship'
178
- params[:branch] = ENV['CI_BRANCH']
179
- params[:commit] = ENV['CI_COMMIT_ID']
180
- params[:build] = ENV['CI_BUILD_NUMBER']
181
- params[:build_url] = ENV['CI_BUILD_URL']
182
- when DRONEIO
183
- # https://semaphoreapp.com/docs/available-environment-variables.html
184
- params[:service] = 'drone.io'
185
- params[:branch] = ENV['DRONE_BRANCH']
186
- params[:commit] = ENV['DRONE_COMMIT_SHA']
187
- params[:job] = ENV['DRONE_JOB_NUMBER']
188
- params[:build] = ENV['DRONE_BUILD_NUMBER']
189
- params[:build_url] = ENV['DRONE_BUILD_LINK'] || ENV['DRONE_BUILD_URL'] || ENV['CI_BUILD_URL']
190
- params[:pr] = ENV['DRONE_PULL_REQUEST']
191
- params[:tag] = ENV['DRONE_TAG']
192
- when GITHUB
193
- # https://help.github.com/en/actions/configuring-and-managing-workflows/using-environment-variables#default-environment-variables
194
- params[:service] = 'github-actions'
195
- params[:branch] = ENV['GITHUB_HEAD_REF'] || ENV['GITHUB_REF'].sub('refs/head/', '')
196
- # PR refs are in the format: refs/pull/7/merge for pull_request events
197
- params[:pr] = ENV['GITHUB_REF'].split('/')[2] unless ENV['GITHUB_HEAD_REF'].nil? || ENV['GITHUB_HEAD_REF'].empty?
198
- params[:slug] = ENV['GITHUB_REPOSITORY']
199
- params[:build] = ENV['GITHUB_RUN_ID']
200
- params[:commit] = ENV['GITHUB_SHA']
201
- when GITLAB
202
- # http://doc.gitlab.com/ci/examples/README.html#environmental-variables
203
- # https://gitlab.com/gitlab-org/gitlab-ci-runner/blob/master/lib/build.rb#L96
204
- # GitLab Runner v9 renamed some environment variables, so we check both old and new variable names.
205
- params[:service] = 'gitlab'
206
- params[:branch] = ENV['CI_BUILD_REF_NAME'] || ENV['CI_COMMIT_REF_NAME']
207
- params[:build] = ENV['CI_BUILD_ID'] || ENV['CI_JOB_ID']
208
- slug = ENV['CI_BUILD_REPO'] || ENV['CI_REPOSITORY_URL']
209
- params[:slug] = slug.split('/', 4)[-1].sub('.git', '') if slug
210
- params[:commit] = ENV['CI_BUILD_REF'] || ENV['CI_COMMIT_SHA']
211
- when HEROKU
212
- params[:service] = 'heroku'
213
- params[:branch] = ENV['HEROKU_TEST_RUN_BRANCH']
214
- params[:build] = ENV['HEROKU_TEST_RUN_ID']
215
- params[:commit] = ENV['HEROKU_TEST_RUN_COMMIT_VERSION']
216
- when JENKINS
217
- # https://wiki.jenkins-ci.org/display/JENKINS/Building+a+software+project
218
- # https://wiki.jenkins-ci.org/display/JENKINS/GitHub+pull+request+builder+plugin#GitHubpullrequestbuilderplugin-EnvironmentVariables
219
- params[:service] = 'jenkins'
220
- params[:branch] = ENV['ghprbSourceBranch'] || ENV['GIT_BRANCH']
221
- params[:commit] = ENV['ghprbActualCommit'] || ENV['GIT_COMMIT']
222
- params[:pr] = ENV['ghprbPullId']
223
- params[:build] = ENV['BUILD_NUMBER']
224
- params[:root] = ENV['WORKSPACE']
225
- params[:build_url] = ENV['BUILD_URL']
226
- when SEMAPHORE
227
- # https://semaphoreapp.com/docs/available-environment-variables.html
228
- params[:service] = 'semaphore'
229
- params[:branch] = ENV['BRANCH_NAME']
230
- params[:commit] = ENV['REVISION']
231
- params[:build] = ENV['SEMAPHORE_BUILD_NUMBER']
232
- params[:job] = ENV['SEMAPHORE_CURRENT_THREAD']
233
- params[:slug] = ENV['SEMAPHORE_REPO_SLUG']
234
- when SHIPPABLE
235
- # http://docs.shippable.com/en/latest/config.html#common-environment-variables
236
- params[:service] = 'shippable'
237
- params[:branch] = ENV['BRANCH']
238
- params[:build] = ENV['BUILD_NUMBER']
239
- params[:build_url] = ENV['BUILD_URL']
240
- params[:pull_request] = ENV['PULL_REQUEST']
241
- params[:slug] = ENV['REPO_NAME']
242
- params[:commit] = ENV['COMMIT']
243
- when SOLANO
244
- # http://docs.solanolabs.com/Setup/tddium-set-environment-variables/
245
- params[:service] = 'solano'
246
- params[:branch] = ENV['TDDIUM_CURRENT_BRANCH']
247
- params[:commit] = ENV['TDDIUM_CURRENT_COMMIT']
248
- params[:build] = ENV['TDDIUM_TID']
249
- params[:pr] = ENV['TDDIUM_PR_ID']
250
- when TEAMCITY
251
- # https://confluence.jetbrains.com/display/TCD8/Predefined+Build+Parameters
252
- # Teamcity does not automatically make build parameters available as environment variables.
253
- # Add the following environment parameters to the build configuration
254
- # env.TEAMCITY_BUILD_BRANCH = %teamcity.build.branch%
255
- # env.TEAMCITY_BUILD_ID = %teamcity.build.id%
256
- # env.TEAMCITY_BUILD_URL = %teamcity.serverUrl%/viewLog.html?buildId=%teamcity.build.id%
257
- # env.TEAMCITY_BUILD_COMMIT = %system.build.vcs.number%
258
- # env.TEAMCITY_BUILD_REPOSITORY = %vcsroot.<YOUR TEAMCITY VCS NAME>.url%
259
- params[:service] = 'teamcity'
260
- params[:branch] = ENV['TEAMCITY_BUILD_BRANCH']
261
- params[:build] = ENV['TEAMCITY_BUILD_ID']
262
- params[:build_url] = ENV['TEAMCITY_BUILD_URL']
263
- params[:commit] = ENV['TEAMCITY_BUILD_COMMIT']
264
- params[:slug] = ENV['TEAMCITY_BUILD_REPOSITORY'].split('/', 4)[-1].sub('.git', '')
265
- when TRAVIS
266
- # http://docs.travis-ci.com/user/ci-environment/#Environment-variables
267
- params[:service] = 'travis'
268
- params[:branch] = ENV['TRAVIS_BRANCH']
269
- params[:pull_request] = ENV['TRAVIS_PULL_REQUEST']
270
- params[:job] = ENV['TRAVIS_JOB_ID']
271
- params[:slug] = ENV['TRAVIS_REPO_SLUG']
272
- params[:build] = ENV['TRAVIS_JOB_NUMBER']
273
- params[:commit] = ENV['TRAVIS_COMMIT']
274
- params[:env] = ENV['TRAVIS_RUBY_VERSION']
275
- when WERCKER
276
- # http://devcenter.wercker.com/articles/steps/variables.html
277
- params[:service] = 'wercker'
278
- params[:branch] = ENV['WERCKER_GIT_BRANCH']
279
- params[:build] = ENV['WERCKER_MAIN_PIPELINE_STARTED']
280
- params[:slug] = ENV['WERCKER_GIT_OWNER'] + '/' + ENV['WERCKER_GIT_REPOSITORY']
281
- params[:commit] = ENV['WERCKER_GIT_COMMIT']
282
- end
283
-
284
- if params[:branch].nil?
285
- # find branch, commit, repo from git command
286
- branch = `git rev-parse --abbrev-ref HEAD`.strip
287
- params[:branch] = branch != 'HEAD' ? branch : 'master'
288
- end
289
-
290
- if !ENV['VCS_COMMIT_ID'].nil?
291
- params[:commit] = ENV['VCS_COMMIT_ID']
292
-
293
- elsif params[:commit].nil?
294
- params[:commit] = `git rev-parse HEAD`.strip
295
- end
296
-
297
- slug = ENV['CODECOV_SLUG']
298
- params[:slug] = slug unless slug.nil?
299
-
300
- params[:pr] = params[:pr].sub('#', '') unless params[:pr].nil?
301
-
302
- params
303
- end
304
-
305
- def retry_request(req, https)
306
- retries = 3
307
- begin
308
- response = https.request(req)
309
- rescue Timeout::Error, SocketError => e
310
- retries -= 1
311
-
312
- if retries.zero?
313
- puts 'Timeout or connection error uploading coverage reports to Codecov. Out of retries.'
314
- puts e
315
- return response
316
- end
317
-
318
- puts 'Timeout or connection error uploading coverage reports to Codecov. Retrying...'
319
- puts e
320
- retry
321
- rescue StandardError => e
322
- puts 'Error uploading coverage reports to Codecov. Sorry'
323
- puts e.class.name
324
- puts e
325
- puts "Backtrace:\n\t#{e.backtrace}"
326
- return response
327
- end
328
-
329
- response
330
- end
331
-
332
- def create_report(report)
333
- result = {
334
- 'meta' => {
335
- 'version' => 'codecov-ruby/v' + VERSION
336
- }
337
- }
338
- result.update(result_to_codecov(report))
339
- result
340
- end
341
-
342
- def gzip_report(report)
343
- puts [green('==>'), 'Gzipping contents'].join(' ')
344
-
345
- io = StringIO.new
346
- gzip = Zlib::GzipWriter.new(io)
347
- gzip << report
348
- gzip.close
349
-
350
- io.string
351
- end
352
-
353
- def upload_to_codecov(ci, report)
354
- url = ENV['CODECOV_URL'] || 'https://codecov.io'
355
- is_enterprise = url != 'https://codecov.io'
356
-
357
- params = build_params(ci)
358
- params_secret_token = params.clone
359
- params_secret_token['token'] = 'secret'
360
-
361
- query = URI.encode_www_form(params)
362
- query_without_token = URI.encode_www_form(params_secret_token)
363
-
364
- gzipped_report = gzip_report(report['codecov'])
365
-
366
- report['params'] = params
367
- report['query'] = query
368
-
369
- puts [green('==>'), 'Uploading reports'].join(' ')
370
- puts " url: #{url}"
371
- puts " query: #{query_without_token}"
372
-
373
- response = false
374
- unless is_enterprise
375
- response = upload_to_v4(url, gzipped_report, query, query_without_token)
376
- return false if response == false
377
- end
378
-
379
- response || upload_to_v2(url, gzipped_report, query, query_without_token)
380
- end
381
-
382
- def upload_to_v4(url, report, query, query_without_token)
383
- uri = URI.parse(url.chomp('/') + '/upload/v4')
384
- https = Net::HTTP.new(uri.host, uri.port)
385
- https.use_ssl = !url.match(/^https/).nil?
386
-
387
- puts [green('-> '), 'Pinging Codecov'].join(' ')
388
- puts "#{url}#{uri.path}?#{query_without_token}"
389
-
390
- req = Net::HTTP::Post.new(
391
- "#{uri.path}?#{query}",
392
- {
393
- 'X-Reduced-Redundancy' => 'false',
394
- 'X-Content-Encoding' => 'application/x-gzip',
395
- 'Content-Type' => 'text/plain'
396
- }
397
- )
398
- response = retry_request(req, https)
399
- if !response&.code || response.code == '400'
400
- puts red(response&.body)
401
- return false
402
- end
403
-
404
- reports_url = response.body.lines[0]
405
- s3target = response.body.lines[1]
406
- puts [green('-> '), 'Uploading to'].join(' ')
407
- puts s3target
408
-
409
- uri = URI(s3target)
410
- https = Net::HTTP.new(uri.host, uri.port)
411
- https.use_ssl = true
412
- req = Net::HTTP::Put.new(
413
- s3target,
414
- {
415
- 'Content-Encoding' => 'gzip',
416
- 'Content-Type' => 'text/plain'
417
- }
418
- )
419
- req.body = report
420
- res = retry_request(req, https)
421
- if res&.body == ''
422
- {
423
- 'uploaded' => true,
424
- 'url' => reports_url,
425
- 'meta' => {
426
- 'status' => res.code
427
- },
428
- 'message' => 'Coverage reports upload successfully'
429
- }.to_json
430
- else
431
- puts [black('-> '), 'Could not upload reports via v4 API, defaulting to v2'].join(' ')
432
- puts red(res&.body || 'nil')
433
- nil
434
- end
435
- end
436
-
437
- def upload_to_v2(url, report, query, query_without_token)
438
- uri = URI.parse(url.chomp('/') + '/upload/v2')
439
- https = Net::HTTP.new(uri.host, uri.port)
440
- https.use_ssl = !url.match(/^https/).nil?
441
-
442
- puts [green('-> '), 'Uploading to Codecov'].join(' ')
443
- puts "#{url}#{uri.path}?#{query_without_token}"
444
-
445
- req = Net::HTTP::Post.new(
446
- "#{uri.path}?#{query}",
447
- {
448
- 'Accept' => 'application/json',
449
- 'Content-Encoding' => 'gzip',
450
- 'Content-Type' => 'text/plain',
451
- 'X-Content-Encoding' => 'gzip'
452
- }
453
- )
454
- req.body = report
455
- res = retry_request(req, https)
456
- res&.body
457
- end
458
-
459
- def handle_report_response(report)
460
- if report['result']['uploaded']
461
- puts " View reports at #{report['result']['url']}"
462
- else
463
- puts red(' X> Failed to upload coverage reports')
464
- end
465
- end
9
+ require_relative 'codecov/formatter'
10
+ require_relative 'codecov/uploader'
466
11
 
12
+ class SimpleCov::Formatter::Codecov
467
13
  def format(result, disable_net_blockers = true)
468
- net_blockers(:off) if disable_net_blockers
469
-
470
- display_header
471
- ci = detect_ci
472
- report = create_report(result)
473
- response = upload_to_codecov(ci, report)
474
- if response == false
475
- report['result'] = { 'uploaded' => false }
476
- return report
477
- end
478
-
479
- report['result'] = JSON.parse(response)
480
- handle_report_response(report)
481
-
482
- net_blockers(:on) if disable_net_blockers
483
- report
484
- end
485
-
486
- private
487
-
488
- # Format SimpleCov coverage data for the Codecov.io API.
489
- #
490
- # @param result [SimpleCov::Result] The coverage data to process.
491
- # @return [Hash]
492
- def result_to_codecov(result)
493
- {
494
- 'codecov' => result_to_codecov_report(result),
495
- 'coverage' => result_to_codecov_coverage(result),
496
- 'messages' => result_to_codecov_messages(result)
497
- }
498
- end
499
-
500
- def result_to_codecov_report(result)
501
- report = file_network.join("\n").concat("\n")
502
- report = report.concat({ 'coverage' => result_to_codecov_coverage(result) }.to_json)
503
- report
504
- end
505
-
506
- def file_network
507
- invalid_file_types = [
508
- 'woff', 'eot', 'otf', # fonts
509
- 'gif', 'png', 'jpg', 'jpeg', 'psd', # images
510
- 'ptt', 'pptx', 'numbers', 'pages', 'md', 'txt', 'xlsx', 'docx', 'doc', 'pdf', 'csv', # docs
511
- 'yml', 'yaml', '.gitignore'
512
- ].freeze
513
-
514
- invalid_directories = [
515
- 'node_modules/',
516
- 'public/',
517
- 'storage/',
518
- 'tmp/',
519
- 'vendor/'
520
- ]
521
-
522
- puts [green('==>'), 'Appending file network'].join(' ')
523
- network = []
524
- Dir['**/*'].keep_if do |file|
525
- if File.file?(file) && !file.end_with?(*invalid_file_types) && invalid_directories.none? { |dir| file.include?(dir) }
526
- network.push(file)
527
- end
528
- end
529
-
530
- network.push('<<<<<< network')
531
- network
532
- end
533
-
534
- # Format SimpleCov coverage data for the Codecov.io coverage API.
535
- #
536
- # @param result [SimpleCov::Result] The coverage data to process.
537
- # @return [Hash<String, Array>]
538
- def result_to_codecov_coverage(result)
539
- result.files.each_with_object({}) do |file, memo|
540
- memo[shortened_filename(file)] = file_to_codecov(file)
541
- end
542
- end
543
-
544
- # Format SimpleCov coverage data for the Codecov.io messages API.
545
- #
546
- # @param result [SimpleCov::Result] The coverage data to process.
547
- # @return [Hash<String, Hash>]
548
- def result_to_codecov_messages(result)
549
- result.files.each_with_object({}) do |file, memo|
550
- memo[shortened_filename(file)] = file.lines.each_with_object({}) do |line, lines_memo|
551
- lines_memo[line.line_number.to_s] = 'skipped' if line.skipped?
552
- end
553
- end
554
- end
555
-
556
- # Format coverage data for a single file for the Codecov.io API.
557
- #
558
- # @param file [SimpleCov::SourceFile] The file to process.
559
- # @return [Array<nil, Integer>]
560
- def file_to_codecov(file)
561
- # Initial nil is required to offset line numbers.
562
- [nil] + file.lines.map do |line|
563
- if line.skipped?
564
- nil
565
- else
566
- line.coverage
567
- end
568
- end
569
- end
570
-
571
- # Get a filename relative to the project root. Based on
572
- # https://github.com/colszowka/simplecov-html, copyright Christoph Olszowka.
573
- #
574
- # @param file [SimeplCov::SourceFile] The file to use.
575
- # @return [String]
576
- def shortened_filename(file)
577
- file.filename.gsub(/^#{SimpleCov.root}/, '.').gsub(%r{^\./}, '')
578
- end
579
-
580
- # Toggle VCR and WebMock on or off
581
- #
582
- # @param switch Toggle switch for Net Blockers.
583
- # @return [Boolean]
584
- def net_blockers(switch)
585
- throw 'Only :on or :off' unless %i[on off].include? switch
586
-
587
- if defined?(VCR)
588
- case switch
589
- when :on
590
- VCR.turn_on!
591
- when :off
592
- VCR.turn_off!(ignore_cassettes: true)
593
- end
594
- end
595
-
596
- if defined?(WebMock)
597
- # WebMock on by default
598
- # VCR depends on WebMock 1.8.11; no method to check whether enabled.
599
- case switch
600
- when :on
601
- WebMock.enable!
602
- when :off
603
- WebMock.disable!
604
- end
605
- end
606
-
607
- true
608
- end
609
-
610
- # Convenience color methods
611
- def black(str)
612
- str.nil? ? '' : "\e[30m#{str}\e[0m"
613
- end
614
-
615
- def red(str)
616
- str.nil? ? '' : "\e[31m#{str}\e[0m"
617
- end
618
-
619
- def green(str)
620
- str.nil? ? '' : "\e[32m#{str}\e[0m"
14
+ report = Codecov::SimpleCov::Formatter.format(result)
15
+ Codecov::Uploader.upload(report, disable_net_blockers)
621
16
  end
622
17
  end