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.
- 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
|