44require 'json'
55require 'net/http'
66require 'simplecov'
7+ require 'colorize'
8+ require 'tempfile'
9+ require 'zlib'
710
811class SimpleCov ::Formatter ::Codecov
912 VERSION = '0.1.17'
@@ -27,64 +30,69 @@ class SimpleCov::Formatter::Codecov
2730 TEAMCITY = 'TeamCity CI' ,
2831 TRAVIS = 'Travis CI' ,
2932 WERCKER = 'Wercker CI'
30- ]
33+ ] . freeze
3134
3235 def display_header
3336 puts [
3437 '' ,
3538 ' _____ _' ,
3639 ' / ____| | |' ,
3740 '| | ___ __| | ___ ___ _____ __' ,
38- '| | / _ \\ / _\` |/ _ \\ / __/ _ \\ \ \ / /' ,
39- '| |___| (_) | (_| | __/ (_| (_) \\ V /' ,
40- ' \\ _____\\ ___/ \\ __,_|\\ ___|\\ ___\\ ___/ \ \_/' ,
41+ '| | / _ \ / _\`|/ _ \/ __/ _ \ \ / /' ,
42+ '| |___| (_) | (_| | __/ (_| (_) \ V /' ,
43+ ' \_____\___/ \__,_|\___|\___\___/ \_/' ,
4144 " Ruby-#{ VERSION } " ,
4245 ''
4346 ] . join ( "\n " )
4447 end
4548
4649 def detect_ci
47- case
48- when ( ENV [ 'CI' ] == 'True' ) && ( ENV [ 'APPVEYOR' ] == 'True' )
49- return APPVEYOR
50- when !ENV [ 'TF_BUILD' ] . nil?
51- return AZUREPIPELINES
52- when ( ENV [ 'CI' ] == 'true' ) && !ENV [ 'BITBUCKET_BRANCH' ] . nil?
53- return BITBUCKET
54- when ( ENV [ 'CI' ] == 'true' ) && ( ENV [ 'BITRISE_IO' ] == 'true' )
55- return BITRISE
56- when ( ENV [ 'CI' ] == 'true' ) && ( ENV [ 'BUILDKITE' ] == 'true' )
57- return BUILDKITE
58- when ( ENV [ 'CI' ] == 'true' ) && ( ENV [ 'CIRCLECI' ] == 'true' )
59- return CIRCLE
60- when ( ENV [ 'CI' ] == 'true' ) && ( ENV [ 'CI_NAME' ] == 'codeship' )
61- return CODESHIP
62- when ( ( ENV [ 'CI' ] == 'true' ) || ( ENV [ 'CI' ] == 'drone' ) ) && ( ENV [ 'DRONE' ] == 'true' )
63- return DRONEIO
64- when !ENV [ 'GITLAB_CI' ] . nil?
65- return GITLAB
66- when ENV [ 'HEROKU_TEST_RUN_ID' ]
67- return HEROKU
68- when !ENV [ 'JENKINS_URL' ] . nil?
69- return JENKINS
70- when ( ENV [ 'CI' ] == 'true' ) && ( ENV [ 'SEMAPHORE' ] == 'true' )
71- return SEMAPHORE
72- when ( ENV [ 'CI' ] == 'true' ) && ( ENV [ 'SHIPPABLE' ] == 'true' )
73- return SHIPPABLE
74- when ENV [ 'TDDIUM' ] == 'true'
75- return SOLANO
76- when ENV [ 'CI_SERVER_NAME' ] == 'TeamCity'
77- return TEAMCITY
78- when ( ENV [ 'CI' ] == 'true' ) && ( ENV [ 'TRAVIS' ] == 'true' )
79- return TRAVIS
80- when ( ENV [ 'CI' ] == 'true' ) && !ENV [ 'WERCKER_GIT_BRANCH' ] . nil?
81- return WERCKER
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 [ 'CI' ] == 'true' ) && ( ENV [ 'CI_NAME' ] == 'codeship' )
63+ CODESHIP
64+ elsif ( ( ENV [ 'CI' ] == 'true' ) || ( ENV [ 'CI' ] == 'drone' ) ) && ( ENV [ 'DRONE' ] == 'true' )
65+ DRONEIO
66+ elsif !ENV [ 'GITLAB_CI' ] . nil?
67+ GITLAB
68+ elsif ENV [ 'HEROKU_TEST_RUN_ID' ]
69+ HEROKU
70+ elsif !ENV [ 'JENKINS_URL' ] . nil?
71+ JENKINS
72+ elsif ( ENV [ 'CI' ] == 'true' ) && ( ENV [ 'SEMAPHORE' ] == 'true' )
73+ SEMAPHORE
74+ elsif ( ENV [ 'CI' ] == 'true' ) && ( ENV [ 'SHIPPABLE' ] == 'true' )
75+ SHIPPABLE
76+ elsif ENV [ 'TDDIUM' ] == 'true'
77+ SOLANO
78+ elsif ENV [ 'CI_SERVER_NAME' ] == 'TeamCity'
79+ TEAMCITY
80+ elsif ( ENV [ 'CI' ] == 'true' ) && ( ENV [ 'TRAVIS' ] == 'true' )
81+ TRAVIS
82+ elsif ( ENV [ 'CI' ] == 'true' ) && !ENV [ 'WERCKER_GIT_BRANCH' ] . nil?
83+ WERCKER
84+ end
85+
86+ if !RECOGNIZED_CIS . include? ( ci )
87+ puts [ 'x>' . red , 'No CI provider detected.' ] . join ( ' ' )
88+ else
89+ puts "==> #{ ci } detected"
8290 end
91+
92+ ci
8393 end
8494
8595 def build_params ( ci )
86- puts 'x> No CI provider detected.' if RECOGNIZED_CIS . include? ( ci )
87-
8896 params = {
8997 'token' => ENV [ 'CODECOV_TOKEN' ] ,
9098 'flags' => ENV [ 'CODECOV_FLAG' ] || ENV [ 'CODECOV_FLAGS' ]
@@ -268,8 +276,7 @@ def build_params(ci)
268276 params
269277 end
270278
271- def upload_to_codecov ( req , https )
272- puts ' -> Pinging Codecov'
279+ def retry_request ( req , https )
273280 retries = 3
274281 begin
275282 response = https . request ( req )
@@ -294,52 +301,89 @@ def upload_to_codecov(req, https)
294301 response
295302 end
296303
297- def format ( result )
298- net_blockers ( :off )
299-
300- display_header
301- ci = detect_ci
302- puts "==> #{ ci } detected"
303-
304- report = {
304+ def create_report ( report )
305+ result = {
305306 'meta' => {
306307 'version' => 'codecov-ruby/v' + SimpleCov ::Formatter ::Codecov ::VERSION
307308 }
308309 }
309- report . update ( result_to_codecov ( result ) )
310- json = report . to_json
310+ result . update ( result_to_codecov ( report ) )
311+ result
312+ end
311313
312- # Build URL Request
314+ def gzip_report ( report )
315+ puts [ '==>' . green , 'Gzipping contents' ] . join ( ' ' )
316+
317+ file = Tempfile . new
318+ Zlib ::GzipWriter . open ( file . path ) do |gz |
319+ gz . write report
320+ end
321+ file . rewind
322+ gzipped_report = file . read
323+ file . close
324+
325+ gzipped_report
326+ end
327+
328+ def upload_to_codecov ( ci , report )
313329 url = ENV [ 'CODECOV_URL' ] || 'https://codecov.io'
314- uri = URI . parse ( url . chomp ( '/' ) + '/upload/v1' )
315330
316331 params = build_params ( ci )
317332 params_secret_token = params . clone
318333 params_secret_token [ 'token' ] = 'secret'
319- uri . query = URI . encode_www_form ( params )
320- req = Net ::HTTP ::Post . new ( uri . path + '?' + uri . query ,
321- {
322- 'Content-Type' => 'application/json' ,
323- 'Accept' => 'application/json'
324- } )
325- req . body = json
326334
335+ query = URI . encode_www_form ( params )
336+ query_without_token = URI . encode_www_form ( params_secret_token )
337+
338+ gzipped_report = gzip_report ( report )
339+
340+ report [ 'params' ] = params
341+ report [ 'query' ] = query
342+
343+ puts [ '==>' . green , 'Uploading reports' ] . join ( ' ' )
344+ puts " url: #{ url } "
345+ puts " query: #{ query_without_token } "
346+
347+ upload_to_v2 ( url , gzipped_report , query , query_without_token )
348+ end
349+
350+ def upload_to_v2 ( url , report , query , query_without_token )
351+ uri = URI . parse ( url . chomp ( '/' ) + '/upload/v2' )
327352 https = Net ::HTTP . new ( uri . host , uri . port )
328353 https . use_ssl = !url . match ( /^https/ ) . nil?
329354
330- # make request
331- puts "#{ uri . path } ?#{ URI . encode_www_form ( params_secret_token ) } "
332- response = upload_to_codecov ( req , https )
333- puts response . body
355+ puts [ '-> ' . green , 'Uploading to Codecov' ] . join ( ' ' )
356+ puts "#{ url } /#{ uri . path } ?#{ query_without_token } "
334357
335- # join the response to report
336- report [ 'result' ] = JSON . parse ( response . body )
337- report [ 'params' ] = params
338- report [ 'query' ] = uri . query
358+ req = Net ::HTTP ::Post . new (
359+ "#{ uri . path } ?#{ query } " ,
360+ {
361+ 'X-Reduced-Redundancy' => 'false' ,
362+ 'Content-Type' => 'text/plain'
363+ }
364+ )
365+ req . body = report
366+ retry_request ( req , https )
367+ end
339368
340- net_blockers ( :on )
369+ def handle_report_response ( report )
370+ if report [ 'result' ] [ 'uploaded' ]
371+ puts " View reports at #{ report [ 'result' ] [ 'url' ] } "
372+ else
373+ puts ' X> Failed to upload coverage reports' . red
374+ end
375+ end
376+
377+ def format ( result )
378+ net_blockers ( :off )
341379
342- # return json data
380+ display_header
381+ ci = detect_ci
382+ report = create_report ( result )
383+ response = upload_to_codecov ( ci , report )
384+ report [ 'result' ] = JSON . parse ( response . body )
385+ handle_report_response ( report )
386+ net_blockers ( :on )
343387 report
344388 end
345389
0 commit comments