coveralls-ruby 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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