slather 2.4.8 → 2.7.5

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.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -1
  3. data/.travis.yml +4 -2
  4. data/CHANGELOG.md +100 -0
  5. data/README.md +26 -3
  6. data/assets/slather.css +2 -1
  7. data/lib/slather/command/coverage_command.rb +9 -1
  8. data/lib/slather/coverage_file.rb +14 -9
  9. data/lib/slather/coverage_service/coveralls.rb +129 -5
  10. data/lib/slather/coverage_service/html_output.rb +62 -6
  11. data/lib/slather/coverage_service/sonarqube_xml_output.rb +61 -0
  12. data/lib/slather/profdata_coverage_file.rb +42 -2
  13. data/lib/slather/project.rb +41 -7
  14. data/lib/slather/version.rb +1 -1
  15. data/lib/slather.rb +1 -0
  16. data/slather.gemspec +5 -5
  17. data/spec/fixtures/FixtureFramework/FixtureFramework.h +19 -0
  18. data/spec/fixtures/FixtureFramework/FlashExperiment.swift +7 -0
  19. data/spec/fixtures/FixtureFramework/Info.plist +24 -0
  20. data/spec/fixtures/FixtureFrameworkTests/FixtureFrameworkTests.swift +34 -0
  21. data/spec/fixtures/FixtureFrameworkTests/FlashExperimentTests.swift +9 -0
  22. data/spec/fixtures/FixtureFrameworkTests/Info.plist +22 -0
  23. data/spec/fixtures/cobertura.xml +157 -37
  24. data/spec/fixtures/fixtures.xcodeproj/project.pbxproj +222 -0
  25. data/spec/fixtures/fixtures.xcodeproj/xcshareddata/xcschemes/fixtures.xcscheme +21 -5
  26. data/spec/fixtures/fixtures.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
  27. data/spec/fixtures/sonarqube-generic-coverage.xml +93 -0
  28. data/spec/slather/coverage_service/cobertura_xml_spec.rb +1 -1
  29. data/spec/slather/coverage_service/coveralls_spec.rb +20 -0
  30. data/spec/slather/coverage_service/html_output_spec.rb +2 -2
  31. data/spec/slather/coverage_service/json_spec.rb +1 -1
  32. data/spec/slather/coverage_service/llvm_cov_spec.rb +1 -1
  33. data/spec/slather/coverage_service/sonarqube_xml_spec.rb +46 -0
  34. data/spec/slather/profdata_coverage_spec.rb +16 -0
  35. data/spec/slather/project_spec.rb +12 -8
  36. data/spec/spec_helper.rb +1 -0
  37. metadata +38 -25
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 24ee530494c9f131751a85dba16a4bc09292c187d045be17b1212d9cf4038378
4
- data.tar.gz: 4c5dabc3de752ebb88998ca29d87d6f072e4477a909926d4237078a2a9f73bc2
3
+ metadata.gz: 2c4a1059a1eae7156ac2c98e509e9cc267e6dd29fbd18332155e94b81c56c3de
4
+ data.tar.gz: b4d09bcb4d70d24e482268791c1a86f80f62a5f9206b3188931dabd1e8673b30
5
5
  SHA512:
6
- metadata.gz: b7d4a1db210237adec6b9c03634774991a209c4aa64c10dea0a73208642298082b9a76f9c0e979b68a4601c6c9ff37f92d6f05bfd3c8a35429bd78cc8ac9549c
7
- data.tar.gz: 9bf87cccabbd4b243e8ba9c519d491818a38924125694ca8701b3b34764a8c9ae167919b764638fa0af27b137dbbf10d9188b3e6297f93f3d1673ec07566d817
6
+ metadata.gz: 2a526985aec8bbf888ccdf584c3638c97349eddaff3b905df334a88ec42e865f1012c928aa520a3471ad6aadf911e60894576f018230da63aceeb27939a00921
7
+ data.tar.gz: fa77a74cef513c27b2e09101f20b0357c1cf163c1f94b273137a0738fd163bce9700f4e48b76bdfcd2a12e72ba4c3baaf24f0ce86738143f23f87f5a806fcda5
data/.gitignore CHANGED
@@ -20,7 +20,7 @@ tmp
20
20
  *.o
21
21
  *.a
22
22
  mkmf.log
23
-
23
+ .vendor
24
24
  # Xcode
25
25
  #
26
26
  *.pbxuser
data/.travis.yml CHANGED
@@ -1,10 +1,12 @@
1
1
  language: objective-c
2
2
  script: bundle exec rake
3
- osx_image: xcode9.2
3
+ osx_image: xcode12.2
4
+
5
+ cache: bundler
4
6
 
5
7
  before_install:
6
8
  - curl http://curl.haxx.se/ca/cacert.pem -o /usr/local/share/cacert.pem
7
- - gem install bundler -v "~> 1.0" --no-ri --no-rdoc
9
+ - gem install bundler -v "~> 2.0" --no-document
8
10
 
9
11
  install:
10
12
  - bundle install --without=documentation
data/CHANGELOG.md CHANGED
@@ -1,5 +1,105 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## v2.7.5
4
+
5
+ * Add `--cdn-assets` flag
6
+ [sushant-here](https://github.com/sushant-here)
7
+ [#537](https://github.com/SlatherOrg/slather/pull/537)
8
+
9
+ * Update nokogiri version
10
+
11
+ ## v2.7.4
12
+
13
+ * Support Ruby 3.2.0
14
+ [crazymanish](https://github.com/crazymanish)
15
+ [#532](https://github.com/SlatherOrg/slather/pull/532)
16
+
17
+ ## v2.7.3
18
+
19
+ * Support Coveralls parallel runs
20
+ [paulz](https://github.com/paulz)
21
+ [#523](https://github.com/SlatherOrg/slather/pull/523)
22
+
23
+ * Update nokogiri version
24
+ [anil291987](https://github.com/anil291987)
25
+ [#518](https://github.com/SlatherOrg/slather/pull/518)
26
+ [#524](https://github.com/SlatherOrg/slather/pull/524)
27
+
28
+ ## v2.7.2
29
+
30
+ * Update xcodeproj version
31
+ [adamyanalunas](https://github.com/adamyanalunas)
32
+ [#502](https://github.com/SlatherOrg/slather/pull/502)
33
+
34
+ * Update nokogiri version
35
+ [jwelton](https://github.com/jwelton)
36
+ [#503](https://github.com/SlatherOrg/slather/pull/503)
37
+
38
+ * Support alternate CI systems in coveralls output
39
+ [fermoyadrop](https://github.com/fermoyadrop)
40
+ [#504](https://github.com/SlatherOrg/slather/pull/504)
41
+
42
+ * Add Bitrise support to coveralls output
43
+ [fermoyadrop](https://github.com/fermoyadrop)
44
+ [#504](https://github.com/SlatherOrg/slather/pull/505)
45
+
46
+ ## v2.7.1
47
+
48
+ * Support generating coverage for framework targets
49
+ [onato](https://github.com/onato)
50
+ [#482](https://github.com/SlatherOrg/slather/pull/482)
51
+
52
+ * Show number of lines in HTML report
53
+ [SiemianHS](https://github.com/SiemianHS)
54
+ [#494](https://github.com/SlatherOrg/slather/pull/494)
55
+
56
+ * Fixed issues with HTML report generation
57
+ [fchiba](https://github.com/fchiba)
58
+ [#483](https://github.com/SlatherOrg/slather/pull/483)
59
+ [#484](https://github.com/SlatherOrg/slather/pull/484)
60
+
61
+ * Don't fail if a source file doesn't exist
62
+ [chillpop](https://github.com/chillpop)
63
+ [#492](https://github.com/SlatherOrg/slather/pull/492)
64
+
65
+ ## v2.7.0
66
+
67
+ * Add Branch Coverage data for ProfData coverage files
68
+ [hborawski](https://github.com/hborawski)
69
+ [#477](https://github.com/SlatherOrg/slather/pull/477)
70
+
71
+ * Fixed 'Argument list too long' when running 'xcrun llvm-cov'
72
+ [samuelsainz](https://github.com/samuelsainz)
73
+ [#476](https://github.com/SlatherOrg/slather/pull/476)
74
+
75
+ ## v2.6.1
76
+
77
+ * Update nokogiri to 1.11
78
+ [ashin-omg](https://github.com/ashin-omg)
79
+ [#473](https://github.com/SlatherOrg/slather/pull/473)
80
+
81
+ ## v2.6.0
82
+
83
+ * Added GitHub actions support
84
+ [martin-key](https://github.com/martin-key), [troyfontaine](https://github.com/troyfontaine)
85
+ [#468](https://github.com/SlatherOrg/slather/pull/468)
86
+
87
+ ## v2.5.0
88
+
89
+ * Fixed activesupport and cocoapods dependencies
90
+ [daneov](https://github.com/daneov)
91
+ [#456](https://github.com/SlatherOrg/slather/pull/467)
92
+
93
+ * Fixed typo in documentation
94
+ [descorp](https://github.com/descorp)
95
+ [#456](https://github.com/SlatherOrg/slather/pull/463)
96
+
97
+ ## v2.4.9
98
+
99
+ * Added support for Sonarqube output
100
+ [adellibovi](https://github.com/adellibovi)
101
+ [#456](https://github.com/SlatherOrg/slather/pull/456)
102
+
3
103
  ## v2.4.8
4
104
 
5
105
  * Optimize performance for many binaries
data/README.md CHANGED
@@ -134,13 +134,14 @@ test:
134
134
 
135
135
  ### Usage with Coveralls
136
136
 
137
- Login to [Coveralls](https://coveralls.io/) and enable your repository. Right now, `slather` supports Coveralls via [Travis CI](https://travis-ci.org) and [CircleCI](https://circleci.com).
137
+ Login to [Coveralls](https://coveralls.io/) and enable your repository. Right now, `slather` supports Coveralls via [Travis CI](https://travis-ci.org), [CircleCI](https://circleci.com), [Jenkins](https://www.jenkins.io/), [Teamcity](https://www.jetbrains.com/teamcity/), [Buildkite](https://buildkite.com/), and [Bitrise](https://bitrise.io/).
138
138
 
139
- Make a `.slather.yml` file:
139
+ Make a `.slather.yml` file and specify the CI Service you're using:
140
140
 
141
141
  ```yml
142
142
  # .slather.yml
143
143
 
144
+ ci_service: circleci | travis_ci | travis_pro | jenkins | buildkite | teamcity
144
145
  coverage_service: coveralls
145
146
  xcodeproj: path/to/project.xcodeproj
146
147
  scheme: YourXcodeSchemeName
@@ -149,7 +150,7 @@ ignore:
149
150
  - ProjectTestsGroup/*
150
151
  ```
151
152
 
152
- And then in your `.travis.yml` or `circle.yml`, call `slather` after a successful build:
153
+ And then in your `.travis.yml` or `circle.yml` or `github-action.yml`, call `slather` after a successful build:
153
154
 
154
155
  ```yml
155
156
  # .travis.yml
@@ -168,6 +169,25 @@ test:
168
169
 
169
170
  ```
170
171
 
172
+ ```yml
173
+ # github-action.yml
174
+ myjob:
175
+ steps:
176
+ - run: |
177
+ bundle config path vendor/bundle
178
+ bundle install --without=documentation --jobs 4 --retry 3
179
+ - name: Extract branch name
180
+ shell: bash
181
+ run: echo "##[set-output name=branch;]$(echo ${GITHUB_REF#refs/heads/})"
182
+ id: get_branch
183
+ - run: bundle exec slather
184
+ env:
185
+ GIT_BRANCH: ${{ steps.get_branch.outputs.branch }}
186
+ CI_PULL_REQUEST: ${{ github.event.number }}
187
+ COVERAGE_ACCESS_TOKEN: ${{ secrets.GITHUB_TOKEN }}
188
+
189
+ ```
190
+
171
191
  #### Usage with Travis CI Pro
172
192
 
173
193
  To use Coveralls with Travis CI Pro (for private repos), add following lines along with other settings to `.slather.yml`:
@@ -214,6 +234,8 @@ $ slather coverage --html --scheme YourXcodeSchemeName path/to/project.xcodeproj
214
234
 
215
235
  This will make a directory named `html` in your root directory (unless `--output-directory` is specified) and will generate all the reports as static html pages inside the directory. It will print out the report's path by default, but you can also specify `--show` flag to open it in your browser automatically.
216
236
 
237
+ By default, the generated HTML will reference locally hosted assets (js, css). You can specify the `--cdn-assets` to specify that you prefer for the generated HTML to use externally hosted assets. This can be useful if publishing the HTML file as a build artifact.
238
+
217
239
  ### TeamCity Reporting
218
240
 
219
241
  To report the coverage statistics to TeamCity:
@@ -265,3 +287,4 @@ Please make sure to follow our general coding style and add test coverage for ne
265
287
  * [@jhersh](https://github.com/jhersh), CircleCI support.
266
288
  * [@tarbrain](https://github.com/tarbrain), Cobertura support and bugfixing.
267
289
  * [@ikhsan](https://github.com/ikhsan), html support.
290
+ * [@martin-key](https://github.com/martin-key) and [@troyfontaine](https://github.com/troyfontaine), Github Actions support.
data/assets/slather.css CHANGED
@@ -74,6 +74,7 @@ table.source_code {
74
74
  table.source_code td {
75
75
  padding-bottom: 0.3em;
76
76
  }
77
+ code.missed { background-color: rgba(255, 73, 76, 0.3); }
77
78
  table.source_code tr.missed td { background-color: rgba(248, 103, 105, 0.2); }
78
79
  table.source_code tr.covered td { background-color: rgba(103, 207, 124, 0.2); }
79
80
  table.source_code td.num {
@@ -124,7 +125,7 @@ footer p, footer a {
124
125
  Syntax Highlighting using highlight.js (https://highlightjs.org)
125
126
  ------------------------------------------------------------- */
126
127
  .hljs {
127
- display: block;
128
+ display: inline-block;
128
129
  overflow-x: auto;
129
130
  -webkit-text-size-adjust: none;
130
131
  }
@@ -8,15 +8,18 @@ class CoverageCommand < Clamp::Command
8
8
  option ["--jenkins"], :flag, "Indicate that the builds are running on Jenkins"
9
9
  option ["--buildkite"], :flag, "Indicate that the builds are running on Buildkite"
10
10
  option ["--teamcity"], :flag, "Indicate that the builds are running on TeamCity"
11
+ option ["--github"], :flag, "Indicate that the builds are running on Github Actions"
11
12
 
12
13
  option ["--coveralls", "-c"], :flag, "Post coverage results to coveralls"
13
14
  option ["--simple-output", "-s"], :flag, "Output coverage results to the terminal"
14
15
  option ["--gutter-json", "-g"], :flag, "Output coverage results as Gutter JSON format"
15
16
  option ["--cobertura-xml", "-x"], :flag, "Output coverage results as Cobertura XML format"
17
+ option ["--sonarqube-xml", "-sq"], :flag, "Output coverage results as SonarQube XML format"
16
18
  option ["--llvm-cov", "-r"], :flag, "Output coverage as llvm-cov format"
17
19
  option ["--json"], :flag, "Output coverage results as simple JSON"
18
20
  option ["--html"], :flag, "Output coverage results as static html pages"
19
21
  option ["--show"], :flag, "Indicate that the static html pages will open automatically"
22
+ option ["--cdn-assets"], :flag, "Indicate that the static html pages will load assets from a CDN"
20
23
 
21
24
  option ["--build-directory", "-b"], "BUILD_DIRECTORY", "The directory where gcno files will be written to. Defaults to derived data."
22
25
  option ["--source-directory"], "SOURCE_DIRECTORY", "The directory where your source files are located."
@@ -28,7 +31,7 @@ class CoverageCommand < Clamp::Command
28
31
  option ["--scheme"], "SCHEME", "The scheme for which the coverage was generated"
29
32
  option ["--configuration"], "CONFIGURATION", "The configuration for test that the project was set"
30
33
  option ["--workspace"], "WORKSPACE", "The workspace that the project was built in"
31
- option ["--binary-file"], "BINARY_FILE", "The binary file against the which the coverage will be run", :multivalued => true
34
+ option ["--binary-file"], "BINARY_FILE", "The binary file against which the coverage will be run", :multivalued => true
32
35
  option ["--binary-basename"], "BINARY_BASENAME", "Basename of the file against which the coverage will be run", :multivalued => true
33
36
  option ["--arch"], "ARCH", "Architecture to use from universal binaries"
34
37
  option ["--source-files"], "SOURCE_FILES", "A Dir.glob compatible pattern used to limit the lookup to specific source files. Ignored in gcov mode.", :multivalued => true
@@ -90,6 +93,8 @@ class CoverageCommand < Clamp::Command
90
93
  project.ci_service = :buildkite
91
94
  elsif teamcity?
92
95
  project.ci_service = :teamcity
96
+ elsif github?
97
+ project.ci_service = :github
93
98
  end
94
99
  end
95
100
 
@@ -122,8 +127,11 @@ class CoverageCommand < Clamp::Command
122
127
  elsif html?
123
128
  project.coverage_service = :html
124
129
  project.show_html = show?
130
+ project.cdn_assets = cdn_assets?
125
131
  elsif json?
126
132
  project.coverage_service = :json
133
+ elsif sonarqube_xml?
134
+ project.coverage_service = :sonarqube_xml
127
135
  end
128
136
  end
129
137
 
@@ -43,18 +43,23 @@ module Slather
43
43
 
44
44
  def gcov_data
45
45
  @gcov_data ||= begin
46
- gcov_output = `gcov "#{source_file_pathname}" --object-directory "#{gcno_file_pathname.parent}" --branch-probabilities --branch-counts`
47
- # Sometimes gcov makes gcov files for Cocoa Touch classes, like NSRange. Ignore and delete later.
48
- gcov_files_created = gcov_output.scan(/creating '(.+\..+\.gcov)'/)
46
+ gcov_data = ""
47
+
48
+ Dir.chdir(project.project_dir) do
49
+ gcov_output = `gcov "#{source_file_pathname}" --object-directory "#{gcno_file_pathname.parent}" --branch-probabilities --branch-counts`
50
+ # Sometimes gcov makes gcov files for Cocoa Touch classes, like NSRange. Ignore and delete later.
51
+ gcov_files_created = gcov_output.scan(/creating '(.+\..+\.gcov)'/)
52
+
53
+ gcov_file_name = "./#{source_file_pathname.basename}.gcov"
54
+ if File.exist?(gcov_file_name)
55
+ gcov_data = File.new(gcov_file_name).read
56
+ else
57
+ gcov_data = ""
58
+ end
49
59
 
50
- gcov_file_name = "./#{source_file_pathname.basename}.gcov"
51
- if File.exists?(gcov_file_name)
52
- gcov_data = File.new(gcov_file_name).read
53
- else
54
- gcov_data = ""
60
+ gcov_files_created.each { |file| FileUtils.rm_f(file) }
55
61
  end
56
62
 
57
- gcov_files_created.each { |file| FileUtils.rm_f(file) }
58
63
  gcov_data
59
64
  end
60
65
  end
@@ -36,6 +36,31 @@ module Slather
36
36
  end
37
37
  private :jenkins_job_id
38
38
 
39
+ def github_job_id
40
+ ENV['GITHUB_RUN_ID']
41
+ end
42
+ private :github_job_id
43
+
44
+ def bitrise_job_id
45
+ ENV['BITRISE_BUILD_NUMBER']
46
+ end
47
+ private :bitrise_job_id
48
+
49
+ def bitrise_pull_request
50
+ ENV['BITRISE_PULL_REQUEST']
51
+ end
52
+ private :bitrise_pull_request
53
+
54
+ def github_pull_request
55
+ ENV['CI_PULL_REQUEST'] || ""
56
+ end
57
+ private :github_pull_request
58
+
59
+ def github_repo_name
60
+ ENV['GITHUB_REPOSITORY'] || ""
61
+ end
62
+ private :github_repo_name
63
+
39
64
  def jenkins_branch_name
40
65
  branch_name = ENV['GIT_BRANCH'] || ENV['BRANCH_NAME']
41
66
  if branch_name.include? 'origin/'
@@ -51,6 +76,16 @@ module Slather
51
76
  end
52
77
  private :teamcity_branch_name
53
78
 
79
+ def github_branch_name
80
+ ENV['GIT_BRANCH'] || `git ls-remote --heads origin | grep $(git rev-parse HEAD) | cut -d / -f 3-`.chomp
81
+ end
82
+ private :github_branch_name
83
+
84
+ def bitrise_branch_name
85
+ ENV['BITRISE_GIT_BRANCH'] || `git ls-remote --heads origin | grep $(git rev-parse HEAD) | cut -d / -f 3-`.chomp
86
+ end
87
+ private :bitrise_branch_name
88
+
54
89
  def buildkite_job_id
55
90
  ENV['BUILDKITE_BUILD_NUMBER']
56
91
  end
@@ -119,11 +154,51 @@ module Slather
119
154
  "https://buildkite.com/" + ENV['BUILDKITE_PROJECT_SLUG'] + "/builds/" + ENV['BUILDKITE_BUILD_NUMBER'] + "#"
120
155
  end
121
156
 
157
+ def github_git_info
158
+ {
159
+ :head => {
160
+ :id => ENV['GITHUB_SHA'],
161
+ :author_name => ENV['GITHUB_ACTOR'],
162
+ :message => (`git log --format=%s -n 1 HEAD`.chomp || "")
163
+ },
164
+ :branch => github_branch_name
165
+ }
166
+ end
167
+ private :github_git_info
168
+
169
+ def bitrise_git_info
170
+ {
171
+ :head => {
172
+ :id => ENV['BITRISE_GIT_COMMIT'],
173
+ :committer_name => (ENV['GIT_CLONE_COMMIT_AUTHOR_NAME'] || `git log --format=%an -n 1 HEAD`.chomp || ""),
174
+ :committer_email => (ENV['GIT_CLONE_COMMIT_AUTHOR_EMAIL'] || `git log --format=%ae -n 1 HEAD`.chomp || ""),
175
+ :message => (ENV['BITRISE_GIT_MESSAGE'] || `git log --format=%s -n 1 HEAD`.chomp || "")
176
+ },
177
+ :branch => bitrise_branch_name
178
+ }
179
+ end
180
+ private :bitrise_git_info
181
+
182
+ def github_build_url
183
+ "https://github.com/" + ENV['GITHUB_REPOSITORY'] + "/actions/runs/" + ENV['GITHUB_RUN_ID']
184
+ end
185
+ private :github_build_url
186
+
187
+ def is_parallel
188
+ ENV['IS_PARALLEL'] != nil
189
+ end
190
+ private :is_parallel
191
+
192
+ def github_job_name
193
+ ENV['GITHUB_JOB']
194
+ end
195
+ private :github_job_name
196
+
122
197
  def coveralls_coverage_data
123
198
  if ci_service == :travis_ci || ci_service == :travis_pro
124
199
  if travis_job_id
125
200
  if ci_service == :travis_ci
126
-
201
+
127
202
  if coverage_access_token.to_s.strip.length > 0
128
203
  raise StandardError, "Access token is set. Uploading coverage data for public repositories doesn't require an access token."
129
204
  end
@@ -133,7 +208,7 @@ module Slather
133
208
  :service_name => "travis-ci",
134
209
  :source_files => coverage_files.map(&:as_json)
135
210
  }.to_json
136
- elsif ci_service == :travis_pro
211
+ elsif ci_service == :travis_pro
137
212
 
138
213
  if coverage_access_token.to_s.strip.length == 0
139
214
  raise StandardError, "Access token is not set. Uploading coverage data for private repositories requires an access token."
@@ -206,8 +281,57 @@ module Slather
206
281
  else
207
282
  raise StandardError, "Environment variable `TC_BUILD_NUMBER` not set. Is this running on a teamcity build?"
208
283
  end
284
+ elsif ci_service == :github
285
+
286
+ if coverage_access_token.to_s.strip.length == 0
287
+ raise StandardError, "Access token is not set. Uploading coverage data for private repositories requires an access token."
288
+ end
289
+
290
+ if github_job_id
291
+ {
292
+ :service_job_id => github_job_id,
293
+ :service_name => "github",
294
+ :repo_token => coverage_access_token,
295
+ :repo_name => github_repo_name,
296
+ :source_files => coverage_files.map(&:as_json),
297
+ :service_build_url => github_build_url,
298
+ :service_pull_request => github_pull_request,
299
+ :git => github_git_info,
300
+ :parallel => is_parallel,
301
+ :flag_name => github_job_name
302
+ }.to_json
303
+ else
304
+ raise StandardError, "Environment variable `GITHUB_RUN_ID` not set. Is this running on github build?"
305
+ end
306
+ elsif ci_service == :bitrise
307
+ {
308
+ :service_job_id => bitrise_job_id,
309
+ :service_name => 'bitrise',
310
+ :repo_token => coverage_access_token,
311
+ :source_files => coverage_files.map(&:as_json),
312
+ :service_pull_request => bitrise_pull_request,
313
+ :service_branch => bitrise_branch_name,
314
+ :git => bitrise_git_info
315
+ }.to_json
209
316
  else
210
- raise StandardError, "No support for ci named #{ci_service}"
317
+ {
318
+ :service_job_id => ENV['CI_BUILD_NUMBER'],
319
+ :service_name => ENV['CI_NAME'] || ci_service,
320
+ :repo_token => coverage_access_token,
321
+ :source_files => coverage_files.map(&:as_json),
322
+ :service_build_url => ENV['CI_BUILD_URL'],
323
+ :service_pull_request => ENV['CI_PULL_REQUEST'],
324
+ :service_branch => ENV['CI_BRANCH'],
325
+ :git => {
326
+ :head => {
327
+ :id => ENV['CI_COMMIT'],
328
+ :committer_name => (`git log --format=%an -n 1 HEAD`.chomp || ""),
329
+ :committer_email => (`git log --format=%ae -n 1 HEAD`.chomp || ""),
330
+ :message => (`git log --format=%s -n 1 HEAD`.chomp || "")
331
+ },
332
+ :branch => ENV['CI_BRANCH']
333
+ }
334
+ }.to_json
211
335
  end
212
336
  end
213
337
  private :coveralls_coverage_data
@@ -220,8 +344,8 @@ module Slather
220
344
 
221
345
  curl_result = `curl -s --form json_file=@#{f.path} #{coveralls_api_jobs_path}`
222
346
 
223
- if curl_result.is_a? String
224
- curl_result_json = JSON.parse(curl_result)
347
+ if curl_result.is_a? String
348
+ curl_result_json = JSON.parse(curl_result)
225
349
 
226
350
  if curl_result_json["error"]
227
351
  error_message = curl_result_json["message"]
@@ -70,9 +70,14 @@ module Slather
70
70
 
71
71
  total_relevant_lines = 0
72
72
  total_tested_lines = 0
73
+ total_relevant_branches = 0
74
+ total_branches_tested = 0
73
75
  coverage_files.each { |coverage_file|
74
76
  total_tested_lines += coverage_file.num_lines_tested
75
77
  total_relevant_lines += coverage_file.num_lines_testable
78
+
79
+ total_relevant_branches += coverage_file.num_branches_testable
80
+ total_branches_tested += coverage_file.num_branches_tested
76
81
  }
77
82
 
78
83
  builder = Nokogiri::HTML::Builder.with(template.at('#reports')) { |cov|
@@ -82,6 +87,22 @@ module Slather
82
87
  percentage = (total_tested_lines / total_relevant_lines.to_f) * 100.0
83
88
  cov.span "Total Coverage : "
84
89
  cov.span decimal_f(percentage) + '%', :class => class_for_coverage_percentage(percentage), :id => "total_coverage"
90
+ cov.span " ("
91
+ cov.span total_tested_lines, :id => "total_tested_lines"
92
+ cov.span " of "
93
+ cov.span total_relevant_lines, :id => "total_relevant_lines"
94
+ cov.span " lines)"
95
+ }
96
+
97
+ cov.h4 {
98
+ percentage = (total_branches_tested / total_relevant_branches.to_f) * 100.0
99
+ cov.span "Total Branch Coverage : "
100
+ cov.span decimal_f(percentage) + '%', :class => class_for_coverage_percentage(percentage), :id => "total_coverage"
101
+ cov.span " ("
102
+ cov.span total_branches_tested, :id => "total_branches_tested"
103
+ cov.span " of "
104
+ cov.span total_relevant_branches, :id => "total_relevant_branches"
105
+ cov.span " lines)"
85
106
  }
86
107
 
87
108
  cov.input(:class => "search", :placeholder => "Search")
@@ -133,6 +154,7 @@ module Slather
133
154
  filepath = coverage_file.source_file_pathname_relative_to_repo_root
134
155
  filename = File.basename(filepath)
135
156
  percentage = coverage_file.percentage_lines_tested
157
+ branch_percentage = coverage_file.rate_branches_tested * 100
136
158
 
137
159
  cleaned_gcov_lines = coverage_file.cleaned_gcov_data.split("\n")
138
160
  is_file_empty = (cleaned_gcov_lines.count <= 0)
@@ -142,7 +164,10 @@ module Slather
142
164
  builder = Nokogiri::HTML::Builder.with(template.at('#reports')) { |cov|
143
165
  cov.h2(:class => "cov_title") {
144
166
  cov.span("Coverage for \"#{filename}\"" + (!is_file_empty ? " : " : ""))
167
+ cov.span("Lines: ") unless is_file_empty
145
168
  cov.span("#{decimal_f(percentage)}%", :class => class_for_coverage_percentage(percentage)) unless is_file_empty
169
+ cov.span(" Branches: ") unless is_file_empty
170
+ cov.span("#{decimal_f(branch_percentage)}%", :class => class_for_coverage_percentage(branch_percentage)) unless is_file_empty
146
171
  }
147
172
 
148
173
  cov.h4("(#{coverage_file.num_lines_tested} of #{coverage_file.num_lines_testable} relevant lines covered)", :class => "cov_subtitle")
@@ -157,8 +182,9 @@ module Slather
157
182
 
158
183
  cov.table(:class => "source_code") {
159
184
  cleaned_gcov_lines.each do |line|
160
-
161
185
  line_number = coverage_file.line_number_in_line(line)
186
+ missed_regions = coverage_file.branch_region_data[line_number]
187
+ hits = coverage_file.coverage_for_line(line)
162
188
  next unless line_number > 0
163
189
 
164
190
  line_source = line.split(line_number_separator, 3)[2]
@@ -171,7 +197,30 @@ module Slather
171
197
  cov.td(line, :class => classes[idx])
172
198
  else
173
199
  cov.td(:class => classes[idx]) {
174
- cov.pre { cov.code(line, :class => "objc") }
200
+ cov.pre {
201
+ # If the line has coverage and missed regions, split up
202
+ # the line to show regions that weren't covered
203
+ if missed_regions != nil && hits != nil && hits > 0
204
+ regions = missed_regions.map do |region|
205
+ region_start, region_length = region
206
+ if region_length != nil
207
+ line[region_start, region_length]
208
+ else
209
+ line[region_start, line.length - region_start]
210
+ end
211
+ end
212
+ current_line = line
213
+ regions.each do |region|
214
+ covered, remainder = current_line.split(region, 2)
215
+ cov.code(covered, :class => "objc")
216
+ cov.code(region, :class => "objc missed")
217
+ current_line = remainder
218
+ end
219
+ cov.code(current_line, :class => "objc")
220
+ else
221
+ cov.code(line, :class => "objc")
222
+ end
223
+ }
175
224
  }
176
225
  end
177
226
  }
@@ -184,10 +233,17 @@ module Slather
184
233
  end
185
234
 
186
235
  def generate_html_template(title, is_index, is_file_empty)
187
- logo_path = "logo.jpg"
188
- css_path = "slather.css"
189
- highlight_js_path = "highlight.pack.js"
190
- list_js_path = "list.min.js"
236
+ if cdn_assets
237
+ logo_path = "https://cdn.jsdelivr.net/gh/SlatherOrg/slather/docs/logo.jpg"
238
+ css_path = "https://cdn.jsdelivr.net/gh/SlatherOrg/slather/assets/slather.css"
239
+ highlight_js_path = "https://cdn.jsdelivr.net/gh/SlatherOrg/slather/assets/highlight.pack.js"
240
+ list_js_path = "https://cdn.jsdelivr.net/gh/SlatherOrg/slather/assets/list.min.js"
241
+ else
242
+ logo_path = "logo.jpg"
243
+ css_path = "slather.css"
244
+ highlight_js_path = "highlight.pack.js"
245
+ list_js_path = "list.min.js"
246
+ end
191
247
 
192
248
  builder = Nokogiri::HTML::Builder.new do |doc|
193
249
  doc.html {
@@ -0,0 +1,61 @@
1
+ require 'nokogiri'
2
+ require 'date'
3
+
4
+ module Slather
5
+ module CoverageService
6
+ module SonarqubeXmlOutput
7
+
8
+ def coverage_file_class
9
+ if input_format == "profdata"
10
+ Slather::ProfdataCoverageFile
11
+ else
12
+ Slather::CoverageFile
13
+ end
14
+ end
15
+ private :coverage_file_class
16
+
17
+ def post
18
+ cobertura_xml_report = create_xml_report(coverage_files)
19
+ store_report(cobertura_xml_report)
20
+ end
21
+
22
+ def store_report(report)
23
+ output_file = 'sonarqube-generic-coverage.xml'
24
+ if output_directory
25
+ FileUtils.mkdir_p(output_directory)
26
+ output_file = File.join(output_directory, output_file)
27
+ end
28
+ File.write(output_file, report.to_s)
29
+ end
30
+
31
+ def create_xml_report(coverage_files)
32
+ create_empty_xml_report
33
+ coverage_node = @doc.root
34
+ coverage_node['version'] = "1"
35
+
36
+ coverage_files.each do |coverage_file|
37
+ file_node = Nokogiri::XML::Node.new "file", @doc
38
+ file_node.parent = coverage_node
39
+ file_node['path'] = coverage_file.source_file_pathname_relative_to_repo_root.to_s
40
+ coverage_file.all_lines.each do |line|
41
+ if coverage_file.coverage_for_line(line)
42
+ line_node = Nokogiri::XML::Node.new "lineToCover", @doc
43
+ line_node['lineNumber'] = coverage_file.line_number_in_line(line)
44
+ line_node['covered'] = coverage_file.coverage_for_line(line) == 0 ? "false" : "true"
45
+ line_node.parent = file_node
46
+ end
47
+ end
48
+ end
49
+ @doc.to_xml
50
+ end
51
+
52
+ def create_empty_xml_report
53
+ builder = Nokogiri::XML::Builder.new do |xml|
54
+ xml.coverage
55
+ end
56
+ @doc = builder.doc
57
+ end
58
+
59
+ end
60
+ end
61
+ end