construi 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +14 -0
  3. data/.rspec +2 -0
  4. data/Gemfile +5 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +4 -0
  7. data/Rakefile +7 -0
  8. data/VERSION +1 -0
  9. data/bin/construi +6 -0
  10. data/construi.gemspec +29 -0
  11. data/lib/construi.rb +36 -0
  12. data/lib/construi/config.rb +36 -0
  13. data/lib/construi/container.rb +69 -0
  14. data/lib/construi/image.rb +74 -0
  15. data/lib/construi/version.rb +3 -0
  16. data/spec/sanity_spec.rb +7 -0
  17. data/spec/spec_helper.rb +78 -0
  18. data/vendor/bundle/ruby/1.9.1/build_info/codeclimate-test-reporter-0.4.6.info +1 -0
  19. data/vendor/bundle/ruby/1.9.1/cache/codeclimate-test-reporter-0.4.6.gem +0 -0
  20. data/vendor/bundle/ruby/1.9.1/gems/codeclimate-test-reporter-0.4.6/.gitignore +18 -0
  21. data/vendor/bundle/ruby/1.9.1/gems/codeclimate-test-reporter-0.4.6/.rspec +2 -0
  22. data/vendor/bundle/ruby/1.9.1/gems/codeclimate-test-reporter-0.4.6/.travis.yml +8 -0
  23. data/vendor/bundle/ruby/1.9.1/gems/codeclimate-test-reporter-0.4.6/Gemfile +12 -0
  24. data/vendor/bundle/ruby/1.9.1/gems/codeclimate-test-reporter-0.4.6/LICENSE.txt +40 -0
  25. data/vendor/bundle/ruby/1.9.1/gems/codeclimate-test-reporter-0.4.6/README.md +131 -0
  26. data/vendor/bundle/ruby/1.9.1/gems/codeclimate-test-reporter-0.4.6/Rakefile +6 -0
  27. data/vendor/bundle/ruby/1.9.1/gems/codeclimate-test-reporter-0.4.6/bin/cc-tddium-post-worker +24 -0
  28. data/vendor/bundle/ruby/1.9.1/gems/codeclimate-test-reporter-0.4.6/codeclimate-test-reporter.gemspec +29 -0
  29. data/vendor/bundle/ruby/1.9.1/gems/codeclimate-test-reporter-0.4.6/config/cacert.pem +3895 -0
  30. data/vendor/bundle/ruby/1.9.1/gems/codeclimate-test-reporter-0.4.6/lib/code_climate/test_reporter.rb +56 -0
  31. data/vendor/bundle/ruby/1.9.1/gems/codeclimate-test-reporter-0.4.6/lib/code_climate/test_reporter/calculate_blob.rb +39 -0
  32. data/vendor/bundle/ruby/1.9.1/gems/codeclimate-test-reporter-0.4.6/lib/code_climate/test_reporter/ci.rb +89 -0
  33. data/vendor/bundle/ruby/1.9.1/gems/codeclimate-test-reporter-0.4.6/lib/code_climate/test_reporter/client.rb +99 -0
  34. data/vendor/bundle/ruby/1.9.1/gems/codeclimate-test-reporter-0.4.6/lib/code_climate/test_reporter/configuration.rb +57 -0
  35. data/vendor/bundle/ruby/1.9.1/gems/codeclimate-test-reporter-0.4.6/lib/code_climate/test_reporter/exception_message.rb +74 -0
  36. data/vendor/bundle/ruby/1.9.1/gems/codeclimate-test-reporter-0.4.6/lib/code_climate/test_reporter/formatter.rb +114 -0
  37. data/vendor/bundle/ruby/1.9.1/gems/codeclimate-test-reporter-0.4.6/lib/code_climate/test_reporter/git.rb +68 -0
  38. data/vendor/bundle/ruby/1.9.1/gems/codeclimate-test-reporter-0.4.6/lib/code_climate/test_reporter/payload_validator.rb +59 -0
  39. data/vendor/bundle/ruby/1.9.1/gems/codeclimate-test-reporter-0.4.6/lib/code_climate/test_reporter/version.rb +5 -0
  40. data/vendor/bundle/ruby/1.9.1/gems/codeclimate-test-reporter-0.4.6/lib/codeclimate-test-reporter.rb +8 -0
  41. data/vendor/bundle/ruby/1.9.1/gems/codeclimate-test-reporter-0.4.6/spec/fixtures/encoding_test.rb +6 -0
  42. data/vendor/bundle/ruby/1.9.1/gems/codeclimate-test-reporter-0.4.6/spec/fixtures/encoding_test_iso.rb +6 -0
  43. data/vendor/bundle/ruby/1.9.1/gems/codeclimate-test-reporter-0.4.6/spec/lib/calculate_blob_spec.rb +27 -0
  44. data/vendor/bundle/ruby/1.9.1/gems/codeclimate-test-reporter-0.4.6/spec/lib/ci_spec.rb +26 -0
  45. data/vendor/bundle/ruby/1.9.1/gems/codeclimate-test-reporter-0.4.6/spec/lib/client_spec.rb +24 -0
  46. data/vendor/bundle/ruby/1.9.1/gems/codeclimate-test-reporter-0.4.6/spec/lib/configuration_spec.rb +75 -0
  47. data/vendor/bundle/ruby/1.9.1/gems/codeclimate-test-reporter-0.4.6/spec/lib/formatter_spec.rb +141 -0
  48. data/vendor/bundle/ruby/1.9.1/gems/codeclimate-test-reporter-0.4.6/spec/lib/git_spec.rb +39 -0
  49. data/vendor/bundle/ruby/1.9.1/gems/codeclimate-test-reporter-0.4.6/spec/lib/payload_validator_spec.rb +89 -0
  50. data/vendor/bundle/ruby/1.9.1/gems/codeclimate-test-reporter-0.4.6/spec/lib/test_reporter_spec.rb +36 -0
  51. data/vendor/bundle/ruby/1.9.1/gems/codeclimate-test-reporter-0.4.6/spec/spec_helper.rb +46 -0
  52. data/vendor/bundle/ruby/1.9.1/gems/json-1.8.2/ext/json/Makefile +174 -0
  53. data/vendor/bundle/ruby/1.9.1/gems/json-1.8.2/ext/json/ext/generator/Makefile +221 -0
  54. data/vendor/bundle/ruby/1.9.1/gems/json-1.8.2/ext/json/ext/parser/Makefile +221 -0
  55. data/vendor/bundle/ruby/1.9.1/specifications/codeclimate-test-reporter-0.4.6.gemspec +50 -0
  56. metadata +199 -0
@@ -0,0 +1,56 @@
1
+ module CodeClimate
2
+ module TestReporter
3
+
4
+ def self.start
5
+ if run?
6
+ require "simplecov"
7
+ ::SimpleCov.add_filter 'vendor'
8
+ ::SimpleCov.formatter = Formatter
9
+ ::SimpleCov.start(configuration.profile) do
10
+ skip_token CodeClimate::TestReporter.configuration.skip_token
11
+ end
12
+ end
13
+ end
14
+
15
+ def self.run?
16
+ environment_variable_set? && run_on_current_branch?
17
+ end
18
+
19
+ def self.environment_variable_set?
20
+ return @environment_variable_set if defined?(@environment_variable_set)
21
+
22
+ @environment_variable_set = !!ENV["CODECLIMATE_REPO_TOKEN"]
23
+ unless @environment_variable_set
24
+ logger.info("Not reporting to Code Climate because ENV['CODECLIMATE_REPO_TOKEN'] is not set.")
25
+ end
26
+
27
+ @environment_variable_set
28
+ end
29
+
30
+ def self.run_on_current_branch?
31
+ return @run_on_current_branch if defined?(@run_on_current_branch)
32
+
33
+ @run_on_current_branch = true if configured_branch.nil?
34
+ @run_on_current_branch ||= !!(current_branch =~ /#{configured_branch}/i)
35
+
36
+ unless @run_on_current_branch
37
+ logger.info("Not reporting to Code Climate because #{configured_branch} is set as the reporting branch.")
38
+ end
39
+
40
+ @run_on_current_branch
41
+ end
42
+
43
+ def self.configured_branch
44
+ configuration.branch
45
+ end
46
+
47
+ def self.current_branch
48
+ Git.branch_from_git_or_ci
49
+ end
50
+
51
+ def self.logger
52
+ CodeClimate::TestReporter.configuration.logger
53
+ end
54
+
55
+ end
56
+ end
@@ -0,0 +1,39 @@
1
+ module CodeClimate
2
+ module TestReporter
3
+
4
+ class CalculateBlob
5
+
6
+ def initialize(file_path)
7
+ @file_path = file_path
8
+ end
9
+
10
+ def blob_id
11
+ calculate_with_file or calculate_with_git
12
+ end
13
+
14
+ private
15
+
16
+ def calculate_with_file
17
+ File.open(@file_path, "rb") do |file|
18
+ header = "blob #{file.size}\0"
19
+ content = file.read
20
+ store = header + content
21
+
22
+ return Digest::SHA1.hexdigest(store)
23
+ end
24
+ rescue EncodingError
25
+ puts "WARNING: Unable to read #{@file_path}\nUsing git for blob calculation"
26
+ nil
27
+ end
28
+
29
+ def calculate_with_git
30
+ output = `git hash-object -t blob #{@file_path}`.chomp
31
+ raise 'ERROR: Failed to calculate blob with git' unless $?.success?
32
+
33
+ output
34
+ end
35
+
36
+ end
37
+
38
+ end
39
+ end
@@ -0,0 +1,89 @@
1
+ module CodeClimate
2
+ module TestReporter
3
+ class Ci
4
+
5
+ def self.service_data(env = ENV)
6
+ if env['TRAVIS']
7
+ {
8
+ name: "travis-ci",
9
+ branch: env['TRAVIS_BRANCH'],
10
+ build_identifier: env['TRAVIS_JOB_ID'],
11
+ pull_request: env['TRAVIS_PULL_REQUEST']
12
+ }
13
+ elsif env['CIRCLECI']
14
+ {
15
+ name: "circlci",
16
+ build_identifier: env['CIRCLE_BUILD_NUM'],
17
+ branch: env['CIRCLE_BRANCH'],
18
+ commit_sha: env['CIRCLE_SHA1']
19
+ }
20
+ elsif env['SEMAPHORE']
21
+ {
22
+ name: "semaphore",
23
+ branch: env['BRANCH_NAME'],
24
+ build_identifier: env['SEMAPHORE_BUILD_NUMBER']
25
+ }
26
+ elsif env['JENKINS_URL']
27
+ {
28
+ name: "jenkins",
29
+ build_identifier: env['BUILD_NUMBER'],
30
+ build_url: env['BUILD_URL'],
31
+ branch: env['GIT_BRANCH'],
32
+ commit_sha: env['GIT_COMMIT']
33
+ }
34
+ elsif env['TDDIUM']
35
+ {
36
+ name: "tddium",
37
+ build_identifier: env['TDDIUM_SESSION_ID'],
38
+ worker_id: env['TDDIUM_TID']
39
+ }
40
+ elsif env['WERCKER']
41
+ {
42
+ name: "wercker",
43
+ build_identifier: env['WERCKER_BUILD_ID'],
44
+ build_url: env['WERCKER_BUILD_URL'],
45
+ branch: env['WERCKER_GIT_BRANCH'],
46
+ commit_sha: env['WERCKER_GIT_COMMIT']
47
+ }
48
+ elsif env['APPVEYOR']
49
+ {
50
+ name: "appveyor",
51
+ build_identifier: env['APPVEYOR_BUILD_ID'],
52
+ build_url: env['APPVEYOR_API_URL'],
53
+ branch: env['APPVEYOR_REPO_BRANCH'],
54
+ commit_sha: env['APPVEYOR_REPO_COMMIT'],
55
+ pull_request: env['APPVEYOR_PULL_REQUEST_NUMBER']
56
+ }
57
+ elsif env['CI_NAME'] =~ /DRONE/i
58
+ {
59
+ name: "drone",
60
+ build_identifier: env['CI_BUILD_NUMBER'],
61
+ build_url: env['CI_BUILD_URL'],
62
+ branch: env['CI_BRANCH'],
63
+ commit_sha: env['CI_BUILD_NUMBER'],
64
+ pull_request: env['CI_PULL_REQUEST']
65
+ }
66
+ elsif env['CI_NAME'] =~ /codeship/i
67
+ {
68
+ name: "codeship",
69
+ build_identifier: env['CI_BUILD_NUMBER'],
70
+ build_url: env['CI_BUILD_URL'],
71
+ branch: env['CI_BRANCH'],
72
+ commit_sha: env['CI_COMMIT_ID'],
73
+ }
74
+ elsif env['BUILDBOX']
75
+ {
76
+ name: "buildbox",
77
+ build_identifier: env['BUILDBOX_JOB_ID'],
78
+ build_url: env['BUILDBOX_BUILD_URL'],
79
+ branch: env['BUILDBOX_BRANCH'],
80
+ commit_sha: env['BUILDBOX_COMMIT']
81
+ }
82
+ else
83
+ {}
84
+ end
85
+ end
86
+
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,99 @@
1
+ require "json"
2
+ require "uri"
3
+ require "net/https"
4
+
5
+ module CodeClimate
6
+ module TestReporter
7
+
8
+ class Client
9
+
10
+ DEFAULT_TIMEOUT = 5 # in seconds
11
+ USER_AGENT = "Code Climate (Ruby Test Reporter v#{VERSION})"
12
+
13
+ def host
14
+ ENV["CODECLIMATE_API_HOST"] ||
15
+ "https://codeclimate.com"
16
+ end
17
+
18
+ def batch_post_results(files)
19
+ uri = URI.parse("#{host}/test_reports/batch")
20
+ http = http_client(uri)
21
+
22
+ boundary = SecureRandom.uuid
23
+ post_body = []
24
+ post_body << "--#{boundary}\r\n"
25
+ post_body << "Content-Disposition: form-data; name=\"repo_token\"\r\n"
26
+ post_body << "\r\n"
27
+ post_body << ENV["CODECLIMATE_REPO_TOKEN"]
28
+ files.each_with_index do |file, index|
29
+ post_body << "\r\n--#{boundary}\r\n"
30
+ post_body << "Content-Disposition: form-data; name=\"coverage_reports[#{index}]\"; filename=\"#{File.basename(file)}\"\r\n"
31
+ post_body << "Content-Type: application/json\r\n"
32
+ post_body << "\r\n"
33
+ post_body << File.read(file)
34
+ end
35
+ post_body << "\r\n--#{boundary}--\r\n"
36
+ request = Net::HTTP::Post.new(uri.request_uri)
37
+ request["User-Agent"] = USER_AGENT
38
+ request.body = post_body.join
39
+ request["Content-Type"] = "multipart/form-data, boundary=#{boundary}"
40
+ response = http.request(request)
41
+
42
+ if response.code.to_i >= 200 && response.code.to_i < 300
43
+ response
44
+ else
45
+ raise "HTTP Error: #{response.code}"
46
+ end
47
+ end
48
+
49
+ def post_results(result)
50
+ uri = URI.parse("#{host}/test_reports")
51
+ http = http_client(uri)
52
+
53
+ request = Net::HTTP::Post.new(uri.path)
54
+ request["User-Agent"] = USER_AGENT
55
+ request["Content-Type"] = "application/json"
56
+
57
+ if CodeClimate::TestReporter.configuration.gzip_request
58
+ request["Content-Encoding"] = "gzip"
59
+ request.body = compress(result.to_json)
60
+ else
61
+ request.body = result.to_json
62
+ end
63
+
64
+ response = http.request(request)
65
+
66
+ if response.code.to_i >= 200 && response.code.to_i < 300
67
+ response
68
+ else
69
+ raise "HTTP Error: #{response.code}"
70
+ end
71
+ end
72
+
73
+ private
74
+
75
+ def http_client(uri)
76
+ Net::HTTP.new(uri.host, uri.port).tap do |http|
77
+ if uri.scheme == "https"
78
+ http.use_ssl = true
79
+ http.verify_mode = OpenSSL::SSL::VERIFY_PEER
80
+ http.ca_file = File.expand_path('../../../../config/cacert.pem', __FILE__)
81
+ http.verify_depth = 5
82
+ end
83
+ http.open_timeout = CodeClimate::TestReporter.configuration.timeout
84
+ http.read_timeout = CodeClimate::TestReporter.configuration.timeout
85
+ end
86
+ end
87
+
88
+ def compress(str)
89
+ sio = StringIO.new("w")
90
+ gz = Zlib::GzipWriter.new(sio)
91
+ gz.write(str)
92
+ gz.close
93
+ sio.string
94
+ end
95
+
96
+ end
97
+
98
+ end
99
+ end
@@ -0,0 +1,57 @@
1
+ require 'logger'
2
+
3
+ module CodeClimate
4
+ module TestReporter
5
+ @@configuration = nil
6
+
7
+ def self.configure
8
+ @@configuration = Configuration.new
9
+
10
+ if block_given?
11
+ yield configuration
12
+ end
13
+
14
+ configuration
15
+ end
16
+
17
+ def self.configuration
18
+ @@configuration || configure
19
+ end
20
+
21
+ class Configuration
22
+ attr_accessor :branch, :path_prefix, :gzip_request, :git_dir
23
+
24
+ attr_writer :logger, :profile, :timeout
25
+
26
+ def initialize
27
+ @gzip_request = true
28
+ end
29
+
30
+ def logger
31
+ @logger ||= default_logger
32
+ end
33
+
34
+ def profile
35
+ @profile ||= "test_frameworks"
36
+ end
37
+
38
+ def skip_token
39
+ @skip_token ||= "nocov"
40
+ end
41
+
42
+ def timeout
43
+ @timeout ||= Client::DEFAULT_TIMEOUT
44
+ end
45
+
46
+ private
47
+
48
+ def default_logger
49
+ log = Logger.new($stderr)
50
+ log.level = Logger::INFO
51
+
52
+ log
53
+ end
54
+ end
55
+
56
+ end
57
+ end
@@ -0,0 +1,74 @@
1
+ module CodeClimate
2
+ module TestReporter
3
+
4
+ class WebMockMessage
5
+ def library_name
6
+ "WebMock"
7
+ end
8
+
9
+ def instructions
10
+ <<-STR
11
+ WebMock.disable_net_connect!(:allow => "codeclimate.com")
12
+ STR
13
+ end
14
+ end
15
+
16
+ class VCRMessage
17
+ def library_name
18
+ "VCR"
19
+ end
20
+
21
+ def instructions
22
+ <<-STR
23
+ VCR.configure do |config|
24
+ # your existing configuration
25
+ config.ignore_hosts 'codeclimate.com'
26
+ end
27
+ STR
28
+ end
29
+ end
30
+
31
+ class ExceptionMessage
32
+
33
+ HTTP_STUBBING_MESSAGES = {
34
+ "VCR::Errors::UnhandledHTTPRequestError" => VCRMessage,
35
+ "WebMock::NetConnectNotAllowedError" => WebMockMessage
36
+ }
37
+
38
+ def initialize(exception)
39
+ @exception = exception
40
+ end
41
+
42
+ def message
43
+ parts = []
44
+ parts << "Code Climate encountered an exception: #{exception_class}"
45
+ if http_stubbing_exception
46
+ message = http_stubbing_exception.new
47
+ parts << "======"
48
+ parts << "Hey! Looks like you are using #{message.library_name}, which will prevent the codeclimate-test-reporter from reporting results to codeclimate.com.
49
+ Add the following to your spec or test helper to ensure codeclimate-test-reporter can post coverage results:"
50
+ parts << "\n" + message.instructions + "\n"
51
+ parts << "======"
52
+ parts << "If this doesn't work, please consult https://codeclimate.com/docs#test-coverage-troubleshooting"
53
+ parts << "======"
54
+ else
55
+ parts << @exception.message
56
+ @exception.backtrace.each do |line|
57
+ parts << line
58
+ end
59
+ end
60
+ parts.join("\n")
61
+ end
62
+
63
+ private
64
+
65
+ def exception_class
66
+ @exception.class.to_s
67
+ end
68
+
69
+ def http_stubbing_exception
70
+ HTTP_STUBBING_MESSAGES[exception_class]
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,114 @@
1
+ # encoding: utf-8
2
+
3
+ require "tmpdir"
4
+ require "securerandom"
5
+ require "json"
6
+ require "digest/sha1"
7
+ require "simplecov"
8
+
9
+ require "code_climate/test_reporter/exception_message"
10
+ require "code_climate/test_reporter/payload_validator"
11
+
12
+ module CodeClimate
13
+ module TestReporter
14
+ class Formatter
15
+ def format(result)
16
+ return true unless CodeClimate::TestReporter.run?
17
+
18
+ print "Coverage = #{result.source_files.covered_percent.round(2)}%. "
19
+
20
+ payload = to_payload(result)
21
+ PayloadValidator.validate(payload)
22
+ if tddium? || ENV["TO_FILE"]
23
+ file_path = File.join(Dir.tmpdir, "codeclimate-test-coverage-#{SecureRandom.uuid}.json")
24
+ print "Coverage results saved to #{file_path}... "
25
+ File.open(file_path, "w") { |file| file.write(payload.to_json) }
26
+ else
27
+ client = Client.new
28
+ print "Sending report to #{client.host} for branch #{Git.branch_from_git_or_ci}... "
29
+ client.post_results(payload)
30
+ end
31
+
32
+ puts "done."
33
+ true
34
+ rescue => ex
35
+ puts ExceptionMessage.new(ex).message
36
+ false
37
+ end
38
+
39
+ def partial?
40
+ tddium?
41
+ end
42
+
43
+ def to_payload(result)
44
+ totals = Hash.new(0)
45
+ source_files = result.files.map do |file|
46
+ totals[:total] += file.lines.count
47
+ totals[:covered] += file.covered_lines.count
48
+ totals[:missed] += file.missed_lines.count
49
+
50
+ {
51
+ name: short_filename(file.filename),
52
+ blob_id: CalculateBlob.new(file.filename).blob_id,
53
+ coverage: file.coverage.to_json,
54
+ covered_percent: round(file.covered_percent, 2),
55
+ covered_strength: round(file.covered_strength, 2),
56
+ line_counts: {
57
+ total: file.lines.count,
58
+ covered: file.covered_lines.count,
59
+ missed: file.missed_lines.count
60
+ }
61
+ }
62
+ end
63
+
64
+ {
65
+ repo_token: ENV["CODECLIMATE_REPO_TOKEN"],
66
+ source_files: source_files,
67
+ run_at: result.created_at.to_i,
68
+ covered_percent: result.source_files.covered_percent.round(2),
69
+ covered_strength: result.source_files.covered_strength.round(2),
70
+ line_counts: totals,
71
+ partial: partial?,
72
+ git: Git.info,
73
+ environment: {
74
+ test_framework: result.command_name.downcase,
75
+ pwd: Dir.pwd,
76
+ rails_root: (Rails.root.to_s rescue nil),
77
+ simplecov_root: ::SimpleCov.root,
78
+ gem_version: VERSION
79
+ },
80
+ ci_service: ci_service_data
81
+ }
82
+ end
83
+
84
+
85
+ def short_filename(filename)
86
+ return filename unless ::SimpleCov.root
87
+ filename = filename.gsub(::SimpleCov.root, '.').gsub(/^\.\//, '')
88
+ apply_prefix filename
89
+ end
90
+
91
+ def tddium?
92
+ ci_service_data && ci_service_data[:name] == "tddium"
93
+ end
94
+
95
+ # Convert to Float before rounding.
96
+ # Fixes [#7] possible segmentation fault when calling #round on a Rational
97
+ def round(numeric, precision)
98
+ Float(numeric).round(precision)
99
+ end
100
+
101
+ private
102
+
103
+ def apply_prefix filename
104
+ prefix = CodeClimate::TestReporter.configuration.path_prefix
105
+ return filename if prefix.nil?
106
+ "#{prefix}/#{filename}"
107
+ end
108
+
109
+ def ci_service_data
110
+ @ci_service_data ||= Ci.service_data
111
+ end
112
+ end
113
+ end
114
+ end