@@ -2,6 +2,7 @@ package scoverage
2
2
3
3
import sbt .Keys ._
4
4
import sbt ._
5
+ import scoverage .ScoverageKeys ._
5
6
import scoverage .report .{CoverageAggregator , CoberturaXmlWriter , ScoverageHtmlWriter , ScoverageXmlWriter }
6
7
7
8
object ScoverageSbtPlugin extends AutoPlugin {
@@ -42,7 +43,8 @@ object ScoverageSbtPlugin extends AutoPlugin {
42
43
coverageOutputHTML := true ,
43
44
coverageOutputCobertura := true ,
44
45
coverageOutputDebug := false ,
45
- coverageCleanSubprojectFiles := true
46
+ coverageCleanSubprojectFiles := true ,
47
+ coverageOutputTeamCity := false
46
48
)
47
49
48
50
/**
@@ -72,6 +74,7 @@ object ScoverageSbtPlugin extends AutoPlugin {
72
74
coverageOutputXML.value,
73
75
coverageOutputHTML.value,
74
76
coverageOutputDebug.value,
77
+ coverageOutputTeamCity.value,
75
78
log)
76
79
case None => log.warn(" No coverage data, skipping reports" )
77
80
}
@@ -91,6 +94,7 @@ object ScoverageSbtPlugin extends AutoPlugin {
91
94
coverageOutputXML.value,
92
95
coverageOutputHTML.value,
93
96
coverageOutputDebug.value,
97
+ coverageOutputTeamCity.value,
94
98
log)
95
99
val cfmt = cov.statementCoverageFormatted
96
100
log.info(s " Aggregation complete. Coverage was [ $cfmt] " )
@@ -127,6 +131,7 @@ object ScoverageSbtPlugin extends AutoPlugin {
127
131
coverageOutputXML.value,
128
132
coverageOutputHTML.value,
129
133
coverageOutputDebug.value,
134
+ coverageOutputTeamCity.value,
130
135
log
131
136
)
132
137
checkCoverage(c, log, coverageMinimum.value, coverageFailOnMinimum.value)
@@ -163,6 +168,7 @@ object ScoverageSbtPlugin extends AutoPlugin {
163
168
coverageOutputXML : Boolean ,
164
169
coverageOutputHTML : Boolean ,
165
170
coverageDebug : Boolean ,
171
+ coverageOutputTeamCity : Boolean ,
166
172
log : Logger ): Unit = {
167
173
log.info(s " Generating scoverage reports... " )
168
174
@@ -188,10 +194,37 @@ object ScoverageSbtPlugin extends AutoPlugin {
188
194
log.info(s " Written HTML coverage report [ ${reportDir.getAbsolutePath}/index.html] " )
189
195
new ScoverageHtmlWriter (compileSourceDirectories, reportDir).write(coverage)
190
196
}
197
+ if (coverageOutputTeamCity) {
198
+ log.info(" Writing coverage report to teamcity" )
199
+ reportToTeamcity(coverage, coverageOutputHTML, reportDir, crossTarget, log)
200
+ }
191
201
202
+ log.info(s " Statement coverage.: ${coverage.statementCoverageFormatted}% " )
203
+ log.info(s " Branch coverage....: ${coverage.branchCoverageFormatted}}% " )
192
204
log.info(" Coverage reports completed" )
193
205
}
194
206
207
+ private def reportToTeamcity (coverage : Coverage ,
208
+ createCoverageZip : Boolean ,
209
+ reportDir : File ,
210
+ crossTarget : File ,
211
+ log : Logger ) {
212
+
213
+ // Teamcity only have a definition of line/method and class coverage
214
+
215
+ // Log branch coverage as line coverage
216
+ log.info(s " ##teamcity[buildStatisticValue key='CodeCoverageAbsMCovered' value=' ${coverage.invokedStatementCount}'] " )
217
+ log.info(s " ##teamcity[buildStatisticValue key='CodeCoverageAbsMTotal' value=' ${coverage.statementCount}'] " )
218
+
219
+ // Log statement coverage as method coverage
220
+ log.info(s " ##teamcity[buildStatisticValue key='CodeCoverageAbsLCovered' value=' ${coverage.invokedBranchesCount}'] " )
221
+ log.info(s " ##teamcity[buildStatisticValue key='CodeCoverageAbsLTotal' value=' ${coverage.branchCount}'] " )
222
+
223
+ // Create the coverage report for teamcity (HTML files)
224
+ if (createCoverageZip)
225
+ IO .zip(Path .allSubpaths(reportDir), crossTarget / " coverage.zip" )
226
+ }
227
+
195
228
private def loadCoverage (crossTarget : File , log : Logger ): Option [Coverage ] = {
196
229
197
230
val dataDir = crossTarget / " /scoverage-data"
0 commit comments