slather 2.4.8 → 2.7.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -1
- data/.travis.yml +4 -2
- data/CHANGELOG.md +100 -0
- data/README.md +26 -3
- data/assets/slather.css +2 -1
- data/lib/slather/command/coverage_command.rb +9 -1
- data/lib/slather/coverage_file.rb +14 -9
- data/lib/slather/coverage_service/coveralls.rb +129 -5
- data/lib/slather/coverage_service/html_output.rb +62 -6
- data/lib/slather/coverage_service/sonarqube_xml_output.rb +61 -0
- data/lib/slather/profdata_coverage_file.rb +42 -2
- data/lib/slather/project.rb +41 -7
- data/lib/slather/version.rb +1 -1
- data/lib/slather.rb +1 -0
- data/slather.gemspec +5 -5
- data/spec/fixtures/FixtureFramework/FixtureFramework.h +19 -0
- data/spec/fixtures/FixtureFramework/FlashExperiment.swift +7 -0
- data/spec/fixtures/FixtureFramework/Info.plist +24 -0
- data/spec/fixtures/FixtureFrameworkTests/FixtureFrameworkTests.swift +34 -0
- data/spec/fixtures/FixtureFrameworkTests/FlashExperimentTests.swift +9 -0
- data/spec/fixtures/FixtureFrameworkTests/Info.plist +22 -0
- data/spec/fixtures/cobertura.xml +157 -37
- data/spec/fixtures/fixtures.xcodeproj/project.pbxproj +222 -0
- data/spec/fixtures/fixtures.xcodeproj/xcshareddata/xcschemes/fixtures.xcscheme +21 -5
- data/spec/fixtures/fixtures.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
- data/spec/fixtures/sonarqube-generic-coverage.xml +93 -0
- data/spec/slather/coverage_service/cobertura_xml_spec.rb +1 -1
- data/spec/slather/coverage_service/coveralls_spec.rb +20 -0
- data/spec/slather/coverage_service/html_output_spec.rb +2 -2
- data/spec/slather/coverage_service/json_spec.rb +1 -1
- data/spec/slather/coverage_service/llvm_cov_spec.rb +1 -1
- data/spec/slather/coverage_service/sonarqube_xml_spec.rb +46 -0
- data/spec/slather/profdata_coverage_spec.rb +16 -0
- data/spec/slather/project_spec.rb +12 -8
- data/spec/spec_helper.rb +1 -0
- metadata +38 -25
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2c4a1059a1eae7156ac2c98e509e9cc267e6dd29fbd18332155e94b81c56c3de
|
4
|
+
data.tar.gz: b4d09bcb4d70d24e482268791c1a86f80f62a5f9206b3188931dabd1e8673b30
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2a526985aec8bbf888ccdf584c3638c97349eddaff3b905df334a88ec42e865f1012c928aa520a3471ad6aadf911e60894576f018230da63aceeb27939a00921
|
7
|
+
data.tar.gz: fa77a74cef513c27b2e09101f20b0357c1cf163c1f94b273137a0738fd163bce9700f4e48b76bdfcd2a12e72ba4c3baaf24f0ce86738143f23f87f5a806fcda5
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
@@ -1,10 +1,12 @@
|
|
1
1
|
language: objective-c
|
2
2
|
script: bundle exec rake
|
3
|
-
osx_image:
|
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 "~>
|
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)
|
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
|
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
|
-
|
47
|
-
|
48
|
-
|
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
|
-
|
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
|
-
|
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 {
|
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
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
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
|