coveralls-ruby 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,69 @@
1
+ require "thor"
2
+
3
+ module Coveralls
4
+ class CommandLine < Thor
5
+
6
+ desc "push", "Runs your test suite and pushes the coverage results to Coveralls."
7
+ def push
8
+ return unless ensure_can_run_locally!
9
+ ENV["COVERALLS_RUN_LOCALLY"] = "true"
10
+ cmds = "bundle exec rake"
11
+ if File.exist?('.travis.yml')
12
+ cmds = YAML.load_file('.travis.yml')["script"] || cmds rescue cmds
13
+ end
14
+ cmds.each { |cmd| system cmd }
15
+ ENV["COVERALLS_RUN_LOCALLY"] = nil
16
+ end
17
+
18
+ desc "report", "Runs your test suite locally and displays coverage statistics."
19
+ def report
20
+ ENV["COVERALLS_NOISY"] = "true"
21
+ exec "bundle exec rake"
22
+ ENV["COVERALLS_NOISY"] = nil
23
+ end
24
+
25
+ desc "open", "View this repository on Coveralls."
26
+ def open
27
+ open_token_based_url "https://coveralls.io/repos/%@"
28
+ end
29
+
30
+ desc "service", "View this repository on your CI service's website."
31
+ def service
32
+ open_token_based_url "https://coveralls.io/repos/%@/service"
33
+ end
34
+
35
+ desc "last", "View the last build for this repository on Coveralls."
36
+ def last
37
+ open_token_based_url "https://coveralls.io/repos/%@/last_build"
38
+ end
39
+
40
+ desc "version", "See version"
41
+ def version
42
+ Coveralls::Output.puts Coveralls::VERSION
43
+ end
44
+
45
+ private
46
+
47
+ def open_token_based_url url
48
+ config = Coveralls::Configuration.configuration
49
+ if config[:repo_token]
50
+ url = url.gsub("%@", config[:repo_token])
51
+ `open #{url}`
52
+ else
53
+ Coveralls::Output.puts "No repo_token configured."
54
+ end
55
+ end
56
+
57
+ def ensure_can_run_locally!
58
+ config = Coveralls::Configuration.configuration
59
+ if config[:repo_token].nil?
60
+ Coveralls::Output.puts "Coveralls cannot run locally because no repo_secret_token is set in .coveralls.yml", :color => "red"
61
+ Coveralls::Output.puts "Please try again when you get your act together.", :color => "red"
62
+
63
+ return false
64
+ end
65
+ true
66
+ end
67
+
68
+ end
69
+ end
@@ -0,0 +1,234 @@
1
+ require 'yaml'
2
+ require 'securerandom'
3
+
4
+ module Coveralls
5
+ module Configuration
6
+
7
+ def self.configuration
8
+ config = {
9
+ :environment => self.relevant_env,
10
+ :git => git
11
+ }
12
+ yml = self.yaml_config
13
+ if yml
14
+ config[:configuration] = yml
15
+ config[:repo_token] = yml['repo_token'] || yml['repo_secret_token']
16
+ end
17
+ if ENV['COVERALLS_REPO_TOKEN']
18
+ config[:repo_token] = ENV['COVERALLS_REPO_TOKEN']
19
+ end
20
+ if ENV['COVERALLS_PARALLEL'] && ENV['COVERALLS_PARALLEL'] != "false"
21
+ config[:parallel] = true
22
+ end
23
+ if ENV['COVERALLS_FLAG_NAME']
24
+ config[:flag_name] = ENV['COVERALLS_FLAG_NAME']
25
+ end
26
+ if ENV['TRAVIS']
27
+ set_service_params_for_travis(config, yml ? yml['service_name'] : nil)
28
+ elsif ENV['CIRCLECI']
29
+ set_service_params_for_circleci(config)
30
+ elsif ENV['SEMAPHORE']
31
+ set_service_params_for_semaphore(config)
32
+ elsif ENV['JENKINS_URL'] || ENV['JENKINS_HOME']
33
+ set_service_params_for_jenkins(config)
34
+ elsif ENV['APPVEYOR']
35
+ set_service_params_for_appveyor(config)
36
+ elsif ENV['TDDIUM']
37
+ set_service_params_for_tddium(config)
38
+ elsif ENV['GITLAB_CI']
39
+ set_service_params_for_gitlab(config)
40
+ elsif ENV['COVERALLS_RUN_LOCALLY'] || Coveralls.testing
41
+ set_service_params_for_coveralls_local(config)
42
+ end
43
+
44
+ # standardized env vars
45
+ set_standard_service_params_for_generic_ci(config)
46
+
47
+ if service_name = ENV['COVERALLS_SERVICE_NAME']
48
+ config[:service_name] = service_name
49
+ end
50
+
51
+ config
52
+ end
53
+
54
+ def self.set_service_params_for_travis(config, service_name)
55
+ config[:service_job_id] = ENV['TRAVIS_JOB_ID']
56
+ config[:service_pull_request] = ENV['TRAVIS_PULL_REQUEST'] unless ENV['TRAVIS_PULL_REQUEST'] == 'false'
57
+ config[:service_name] = service_name || 'travis-ci'
58
+ config[:service_branch] = ENV['TRAVIS_BRANCH']
59
+ end
60
+
61
+ def self.set_service_params_for_circleci(config)
62
+ config[:service_name] = 'circleci'
63
+ config[:service_number] = ENV['CIRCLE_BUILD_NUM']
64
+ config[:service_pull_request] = (ENV['CI_PULL_REQUEST'] || "")[/(\d+)$/,1]
65
+ config[:parallel] = ENV['CIRCLE_NODE_TOTAL'].to_i > 1
66
+ config[:service_job_number] = ENV['CIRCLE_NODE_INDEX']
67
+ end
68
+
69
+ def self.set_service_params_for_semaphore(config)
70
+ config[:service_name] = 'semaphore'
71
+ config[:service_number] = ENV['SEMAPHORE_BUILD_NUMBER']
72
+ config[:service_pull_request] = ENV['PULL_REQUEST_NUMBER']
73
+ end
74
+
75
+ def self.set_service_params_for_jenkins(config)
76
+ config[:service_name] = 'jenkins'
77
+ config[:service_number] = ENV['BUILD_NUMBER']
78
+ config[:service_branch] = ENV['BRANCH_NAME']
79
+ config[:service_pull_request] = ENV['ghprbPullId']
80
+ end
81
+
82
+ def self.set_service_params_for_appveyor(config)
83
+ config[:service_name] = 'appveyor'
84
+ config[:service_number] = ENV['APPVEYOR_BUILD_VERSION']
85
+ config[:service_branch] = ENV['APPVEYOR_REPO_BRANCH']
86
+ config[:commit_sha] = ENV['APPVEYOR_REPO_COMMIT']
87
+ repo_name = ENV['APPVEYOR_REPO_NAME']
88
+ config[:service_build_url] = 'https://ci.appveyor.com/project/%s/build/%s' % [repo_name, config[:service_number]]
89
+ end
90
+
91
+ def self.set_service_params_for_tddium(config)
92
+ config[:service_name] = 'tddium'
93
+ config[:service_number] = ENV['TDDIUM_SESSION_ID']
94
+ config[:service_job_number] = ENV['TDDIUM_TID']
95
+ config[:service_pull_request] = ENV['TDDIUM_PR_ID']
96
+ config[:service_branch] = ENV['TDDIUM_CURRENT_BRANCH']
97
+ config[:service_build_url] = "https://ci.solanolabs.com/reports/#{ENV['TDDIUM_SESSION_ID']}"
98
+ end
99
+
100
+ def self.set_service_params_for_gitlab(config)
101
+ config[:service_name] = 'gitlab-ci'
102
+ config[:service_number] = ENV['CI_PIPELINE_ID']
103
+ config[:service_job_number] = ENV['CI_BUILD_NAME']
104
+ config[:service_job_id] = ENV['CI_BUILD_ID']
105
+ config[:service_branch] = ENV['CI_BUILD_REF_NAME']
106
+ config[:commit_sha] = ENV['CI_BUILD_REF']
107
+ end
108
+
109
+ def self.set_service_params_for_coveralls_local(config)
110
+ config[:service_job_id] = nil
111
+ config[:service_name] = 'coveralls-ruby'
112
+ config[:service_event_type] = 'manual'
113
+ end
114
+
115
+ def self.set_standard_service_params_for_generic_ci(config)
116
+ config[:service_name] ||= ENV['CI_NAME']
117
+ config[:service_number] ||= ENV['CI_BUILD_NUMBER']
118
+ config[:service_job_id] ||= ENV['CI_JOB_ID']
119
+ config[:service_build_url] ||= ENV['CI_BUILD_URL']
120
+ config[:service_branch] ||= ENV['CI_BRANCH']
121
+ config[:service_pull_request] ||= (ENV['CI_PULL_REQUEST'] || "")[/(\d+)$/,1]
122
+ end
123
+
124
+ def self.yaml_config
125
+ if self.configuration_path && File.exist?(self.configuration_path)
126
+ YAML::load_file(self.configuration_path)
127
+ end
128
+ end
129
+
130
+ def self.configuration_path
131
+ File.expand_path(File.join(self.root, ".coveralls.yml")) if self.root
132
+ end
133
+
134
+ def self.root
135
+ pwd
136
+ end
137
+
138
+ def self.pwd
139
+ Dir.pwd
140
+ end
141
+
142
+ def self.simplecov_root
143
+ if defined?(::SimpleCov)
144
+ ::SimpleCov.root
145
+ end
146
+ end
147
+
148
+ def self.rails_root
149
+ Rails.root.to_s
150
+ rescue
151
+ nil
152
+ end
153
+
154
+ def self.git
155
+ hash = {}
156
+
157
+ Dir.chdir(root) do
158
+
159
+ hash[:head] = {
160
+ :id => ENV.fetch("GIT_ID", `git log -1 --pretty=format:'%H'`),
161
+ :author_name => ENV.fetch("GIT_AUTHOR_NAME", `git log -1 --pretty=format:'%aN'`),
162
+ :author_email => ENV.fetch("GIT_AUTHOR_EMAIL", `git log -1 --pretty=format:'%ae'`),
163
+ :committer_name => ENV.fetch("GIT_COMMITTER_NAME", `git log -1 --pretty=format:'%cN'`),
164
+ :committer_email => ENV.fetch("GIT_COMMITTER_EMAIL", `git log -1 --pretty=format:'%ce'`),
165
+ :message => ENV.fetch("GIT_MESSAGE", `git log -1 --pretty=format:'%s'`)
166
+ }
167
+
168
+ # Branch
169
+ hash[:branch] = ENV.fetch("GIT_BRANCH", `git rev-parse --abbrev-ref HEAD`)
170
+
171
+ # Remotes
172
+ remotes = nil
173
+ begin
174
+ remotes = `git remote -v`.split(/\n/).map do |remote|
175
+ splits = remote.split(" ").compact
176
+ {:name => splits[0], :url => splits[1]}
177
+ end.uniq
178
+ rescue
179
+ end
180
+ hash[:remotes] = remotes
181
+
182
+ end
183
+
184
+ hash
185
+
186
+ rescue Exception => e
187
+ Coveralls::Output.puts "Coveralls git error:", :color => "red"
188
+ Coveralls::Output.puts e.to_s, :color => "red"
189
+ nil
190
+ end
191
+
192
+ def self.relevant_env
193
+ hash = {
194
+ :pwd => self.pwd,
195
+ :rails_root => self.rails_root,
196
+ :simplecov_root => simplecov_root,
197
+ :gem_version => VERSION
198
+ }
199
+
200
+ hash.merge! begin
201
+ if ENV['TRAVIS']
202
+ {
203
+ :travis_job_id => ENV['TRAVIS_JOB_ID'],
204
+ :travis_pull_request => ENV['TRAVIS_PULL_REQUEST'],
205
+ :branch => ENV['TRAVIS_BRANCH']
206
+ }
207
+ elsif ENV['CIRCLECI']
208
+ {
209
+ :circleci_build_num => ENV['CIRCLE_BUILD_NUM'],
210
+ :branch => ENV['CIRCLE_BRANCH'],
211
+ :commit_sha => ENV['CIRCLE_SHA1']
212
+ }
213
+ elsif ENV['JENKINS_URL']
214
+ {
215
+ :jenkins_build_num => ENV['BUILD_NUMBER'],
216
+ :jenkins_build_url => ENV['BUILD_URL'],
217
+ :branch => ENV['GIT_BRANCH'],
218
+ :commit_sha => ENV['GIT_COMMIT']
219
+ }
220
+ elsif ENV['SEMAPHORE']
221
+ {
222
+ :branch => ENV['BRANCH_NAME'],
223
+ :commit_sha => ENV['REVISION']
224
+ }
225
+ else
226
+ {}
227
+ end
228
+ end
229
+
230
+ hash
231
+ end
232
+
233
+ end
234
+ end
@@ -0,0 +1,114 @@
1
+ module Coveralls
2
+ #
3
+ # Public: Methods for formatting strings with Term::ANSIColor.
4
+ # Does not utilize monkey-patching and should play nicely when
5
+ # included with other libraries.
6
+ #
7
+ # All methods are module methods and should be called on
8
+ # the Coveralls::Output module.
9
+ #
10
+ # Examples
11
+ #
12
+ # Coveralls::Output.format("Hello World", :color => "cyan")
13
+ # # => "\e[36mHello World\e[0m"
14
+ #
15
+ # Coveralls::Output.print("Hello World")
16
+ # # Hello World => nil
17
+ #
18
+ # Coveralls::Output.puts("Hello World", :color => "underline")
19
+ # # Hello World
20
+ # # => nil
21
+ #
22
+ # To silence output completely:
23
+ #
24
+ # Coveralls::Output.silent = true
25
+ #
26
+ # or set this environment variable:
27
+ #
28
+ # COVERALLS_SILENT
29
+ #
30
+ # To disable color completely:
31
+ #
32
+ # Coveralls::Output.no_color = true
33
+
34
+ module Output
35
+ attr_accessor :silent, :no_color
36
+ attr_writer :output
37
+ extend self
38
+
39
+ def output
40
+ (defined?(@output) && @output) || $stdout
41
+ end
42
+
43
+ def no_color?
44
+ (defined?(@no_color)) && @no_color
45
+ end
46
+
47
+ # Public: Formats the given string with the specified color
48
+ # through Term::ANSIColor
49
+ #
50
+ # string - the text to be formatted
51
+ # options - The hash of options used for formatting the text:
52
+ # :color - The color to be passed as a method to
53
+ # Term::ANSIColor
54
+ #
55
+ # Examples
56
+ #
57
+ # Coveralls::Output.format("Hello World!", :color => "cyan")
58
+ # # => "\e[36mHello World\e[0m"
59
+ #
60
+ # Returns the formatted string.
61
+ def format(string, options = {})
62
+ unless no_color?
63
+ require 'term/ansicolor'
64
+ if options[:color]
65
+ options[:color].split(/\s/).reverse_each do |color|
66
+ if Term::ANSIColor.respond_to?(color.to_sym)
67
+ string = Term::ANSIColor.send(color.to_sym, string)
68
+ end
69
+ end
70
+ end
71
+ end
72
+ string
73
+ end
74
+
75
+ # Public: Passes .format to Kernel#puts
76
+ #
77
+ # string - the text to be formatted
78
+ # options - The hash of options used for formatting the text:
79
+ # :color - The color to be passed as a method to
80
+ # Term::ANSIColor
81
+ #
82
+ #
83
+ # Example
84
+ #
85
+ # Coveralls::Output.puts("Hello World", :color => "cyan")
86
+ #
87
+ # Returns nil.
88
+ def puts(string, options = {})
89
+ return if silent?
90
+ (options[:output] || output).puts self.format(string, options)
91
+ end
92
+
93
+ # Public: Passes .format to Kernel#print
94
+ #
95
+ # string - the text to be formatted
96
+ # options - The hash of options used for formatting the text:
97
+ # :color - The color to be passed as a method to
98
+ # Term::ANSIColor
99
+ #
100
+ # Example
101
+ #
102
+ # Coveralls::Output.print("Hello World!", :color => "underline")
103
+ #
104
+ # Returns nil.
105
+ def print(string, options = {})
106
+ return if silent?
107
+ (options[:output] || output).print self.format(string, options)
108
+ end
109
+
110
+ def silent?
111
+ ENV["COVERALLS_SILENT"] || (defined?(@silent) && @silent)
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,19 @@
1
+ require 'rake'
2
+ require 'rake/tasklib'
3
+
4
+ module Coveralls
5
+ class RakeTask < ::Rake::TaskLib
6
+ include ::Rake::DSL if defined?(::Rake::DSL)
7
+
8
+ def initialize(*args, &task_block)
9
+ namespace :coveralls do
10
+ desc "Push latest coverage results to Coveralls.io"
11
+ task :push do
12
+ require 'coveralls'
13
+ Coveralls.push!
14
+ end
15
+ end
16
+ end # initialize
17
+
18
+ end # class
19
+ end # module
@@ -0,0 +1,101 @@
1
+ module Coveralls
2
+ module SimpleCov
3
+ class Formatter
4
+
5
+ def display_result(result)
6
+ # Log which files would be submitted.
7
+ if result.files.length > 0
8
+ Coveralls::Output.puts "[Coveralls] Some handy coverage stats:"
9
+ else
10
+ Coveralls::Output.puts "[Coveralls] There are no covered files.", :color => "yellow"
11
+ end
12
+ result.files.each do |f|
13
+ Coveralls::Output.print " * "
14
+ Coveralls::Output.print short_filename(f.filename).to_s, :color => "cyan"
15
+ Coveralls::Output.print " => ", :color => "white"
16
+ cov = "#{f.covered_percent.round}%"
17
+ if f.covered_percent > 90
18
+ Coveralls::Output.print cov, :color => "green"
19
+ elsif f.covered_percent > 80
20
+ Coveralls::Output.print cov, :color => "yellow"
21
+ else
22
+ Coveralls::Output.print cov, :color => "red"
23
+ end
24
+ Coveralls::Output.puts ""
25
+ end
26
+ true
27
+ end
28
+
29
+ def get_source_files(result)
30
+ # Gather the source files.
31
+ source_files = []
32
+ result.files.each do |file|
33
+ properties = {}
34
+
35
+ # Get Source
36
+ properties[:source] = File.open(file.filename, "rb:utf-8").read
37
+
38
+ # Get the root-relative filename
39
+ properties[:name] = short_filename(file.filename)
40
+
41
+ # Get the coverage
42
+ properties[:coverage] = file.coverage.dup
43
+
44
+ # Skip nocov lines
45
+ file.lines.each_with_index do |line, i|
46
+ properties[:coverage][i] = nil if line.skipped?
47
+ end
48
+
49
+ source_files << properties
50
+ end
51
+ source_files
52
+ end
53
+
54
+ def format(result)
55
+
56
+ unless Coveralls.should_run?
57
+ if Coveralls.noisy?
58
+ display_result result
59
+ end
60
+ return
61
+ end
62
+
63
+ # Post to Coveralls.
64
+ API.post_json "jobs",
65
+ :source_files => get_source_files(result),
66
+ :test_framework => result.command_name.downcase,
67
+ :run_at => result.created_at
68
+
69
+ Coveralls::Output.puts output_message result
70
+
71
+ true
72
+
73
+ rescue Exception => e
74
+ display_error e
75
+ end
76
+
77
+ def display_error(e)
78
+ Coveralls::Output.puts "Coveralls encountered an exception:", :color => "red"
79
+ Coveralls::Output.puts e.class.to_s, :color => "red"
80
+ Coveralls::Output.puts e.message, :color => "red"
81
+ e.backtrace.each do |line|
82
+ Coveralls::Output.puts line, :color => "red"
83
+ end if e.backtrace
84
+ if e.respond_to?(:response) && e.response
85
+ Coveralls::Output.puts e.response.to_s, :color => "red"
86
+ end
87
+ false
88
+ end
89
+
90
+ def output_message(result)
91
+ "Coverage is at #{result.covered_percent.round(2) rescue result.covered_percent.round}%.\nCoverage report sent to Coveralls."
92
+ end
93
+
94
+ def short_filename(filename)
95
+ filename = filename.gsub(::SimpleCov.root, '.').gsub(/^\.\//, '') if ::SimpleCov.root
96
+ filename
97
+ end
98
+
99
+ end
100
+ end
101
+ end