Skip to content

Commit db21143

Browse files
authored
Merge pull request #437 from codacy/metrics-tools-api
feature: Read metrics tools from codacy-tools
2 parents 4ab10c5 + c360dde commit db21143

10 files changed

Lines changed: 93 additions & 22 deletions

File tree

cli/src/main/scala/com/codacy/analysis/cli/command/AnalyseCommand.scala

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,13 @@ object AnalyseCommand {
8484
ToolsClient(codacyApiUrl)(httpClient = httpClient, ec = actorSystem.dispatcher, mat = materializer)
8585
val toolsDataStorage = FileDataStorage[ToolSpec]("tools")
8686
val duplicationToolsDataStorage = FileDataStorage[DuplicationToolSpec]("duplicationTools")
87-
new ToolRepositoryRemote(toolsClient, toolsDataStorage, duplicationToolsDataStorage, FileDataStorage(_))(
88-
ec = actorSystem.dispatcher,
89-
mat = materializer)
87+
val metricsToolsDataStorage = FileDataStorage[MetricsToolSpec]("metricsTools")
88+
new ToolRepositoryRemote(
89+
toolsClient,
90+
toolsDataStorage,
91+
duplicationToolsDataStorage,
92+
metricsToolsDataStorage,
93+
FileDataStorage(_))(ec = actorSystem.dispatcher, mat = materializer)
9094
}
9195
}
9296

core/src/main/scala/com/codacy/analysis/core/tools/ToolRepository.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
package com.codacy.analysis.core.tools
22

3-
import com.codacy.analysis.core.model.{AnalyserError, DuplicationToolSpec, PatternSpec, ToolSpec}
3+
import com.codacy.analysis.core.model.{AnalyserError, DuplicationToolSpec, MetricsToolSpec, PatternSpec, ToolSpec}
44

55
trait ToolRepository {
66

77
def listTools(): Either[AnalyserError, Seq[ToolSpec]]
88
def listDuplicationTools(): Either[AnalyserError, Seq[DuplicationToolSpec]]
9+
def listMetricsTools(): Either[AnalyserError, Seq[MetricsToolSpec]]
910
def getTool(uuid: String): Either[AnalyserError, ToolSpec]
1011
def listPatterns(tool: ToolSpec): Either[AnalyserError, Seq[PatternSpec]]
1112

core/src/test/scala/com.codacy.analysis.core/ToolRepositoryMock.scala

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import com.codacy.analysis.core.model.{AnalyserError, PatternSpec, ToolSpec}
44
import com.codacy.analysis.core.tools.ToolRepository
55
import com.codacy.plugins.api.languages.Languages
66
import com.codacy.analysis.core.model.DuplicationToolSpec
7+
import com.codacy.analysis.core.model.MetricsToolSpec
78

89
/**
910
* This object can be used to replace calls to codacy API related to tools.
@@ -136,4 +137,22 @@ object ToolRepositoryMock extends ToolRepository {
136137
DuplicationToolSpec("codacy/codacy-duplication-phpcpd:2.1.4", Set(Languages.PHP)),
137138
DuplicationToolSpec("codacy/codacy-duplication-flay:2.1.4", Set(Languages.Ruby)),
138139
DuplicationToolSpec("codacy/codacy-duplication-jscpd:0.1.6", Set(Languages.Kotlin, Languages.TypeScript))))
140+
141+
override def listMetricsTools(): Either[AnalyserError, Seq[MetricsToolSpec]] =
142+
Right(
143+
Seq(
144+
MetricsToolSpec(dockerImage = "codacy/codacy-metrics-pmd:0.2.4", languages = Set(Languages.Java)),
145+
MetricsToolSpec(dockerImage = "codacy/codacy-metrics-gocyclo:0.2.4", languages = Set(Languages.Go)),
146+
MetricsToolSpec(dockerImage = "codacy/codacy-metrics-scalastyle:0.2.4", languages = Set(Languages.Scala)),
147+
MetricsToolSpec(dockerImage = "codacy/codacy-metrics-radon:0.2.4", languages = Set(Languages.Python)),
148+
MetricsToolSpec(
149+
dockerImage = "codacy/codacy-metrics-eslint:1.1.250",
150+
languages = Set(Languages.Javascript, Languages.TypeScript)),
151+
MetricsToolSpec(dockerImage = "codacy/codacy-metrics-pdepend:0.5.0", languages = Set(Languages.PHP)),
152+
MetricsToolSpec(dockerImage = "codacy/codacy-metrics-rubocop:0.4.1", languages = Set(Languages.Ruby)),
153+
MetricsToolSpec(dockerImage = "codacy/codacy-metrics-scala:0.2.4", languages = Set(Languages.Scala)),
154+
MetricsToolSpec(dockerImage = "codacy/codacy-metrics-sonar-csharp:0.1.36", languages = Set(Languages.CSharp)),
155+
MetricsToolSpec(dockerImage = "codacy/codacy-metrics-sonar-csharp:0.1.36", languages = Set(Languages.CSharp)),
156+
MetricsToolSpec(dockerImage = "codacy/codacy-metrics-detekt:0.1.2", languages = Set(Languages.Kotlin)),
157+
MetricsToolSpec(dockerImage = "codacy/codacy-metrics-cloc:0.4.1", languages = Languages.all)))
139158
}

core/src/test/scala/com.codacy.analysis.core/tools/DuplicationToolSpec.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package com.codacy.analysis.core.tools
22

33
import com.codacy.analysis.core.files.FileCollector
44
import com.codacy.analysis.core.model
5+
import com.codacy.analysis.core.ToolRepositoryMock
56
import com.codacy.analysis.core.utils.TestUtils._
67
import com.codacy.plugins.api.languages.{Language, Languages}
78
import com.codacy.plugins.api.duplication.DuplicationCloneFile
@@ -10,7 +11,6 @@ import org.specs2.matcher.MatchResult
1011
import org.specs2.mutable.Specification
1112

1213
import scala.util.Success
13-
import com.codacy.analysis.core.ToolRepositoryMock
1414

1515
class DuplicationToolSpec extends Specification with NoLanguageFeatures {
1616

core/src/test/scala/com.codacy.analysis.core/tools/ToolRepositoryStub.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ class ToolRepositoryStub extends ToolRepository {
77

88
def listTools(): Either[AnalyserError, Seq[ToolSpec]] = ???
99
def listDuplicationTools(): Either[AnalyserError, Seq[model.DuplicationToolSpec]] = ???
10+
def listMetricsTools(): Either[AnalyserError, Seq[model.MetricsToolSpec]] = ???
1011
def getTool(uuid: String): Either[AnalyserError, ToolSpec] = ???
1112
def listPatterns(tool: ToolSpec): Either[AnalyserError, Seq[PatternSpec]] = ???
1213

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package com.codacy.analysis.core.model
2+
3+
import com.codacy.plugins.api.languages.Language
4+
5+
case class MetricsToolSpec(dockerImage: String, languages: Set[Language])

project/Dependencies.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ object Dependencies {
55
val codacyPluginsVersion = "24.4.5_play_2.7"
66
val circeVersion = "0.12.3"
77
val specs2Version = "4.8.1"
8-
val codacyApiVersion = "26.9.0"
8+
val codacyApiVersion = "26.10.0"
99
val silencerVersion = "1.7.0"
1010

1111
lazy val circe = List(

toolRepository-remote/src/main/scala/com/codacy/toolRepository/remote/ToolRepositoryRemote.scala

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,26 @@ import akka.stream.scaladsl.Sink
55
import com.codacy.analysis.clientapi.definitions
66
import com.codacy.analysis.clientapi.definitions.{
77
DuplicationToolListResponse,
8+
MetricsToolListResponse,
89
PaginationInfo,
910
PatternListResponse,
1011
ToolListResponse
1112
}
1213
import com.codacy.analysis.clientapi.tools.{
1314
ListDuplicationToolsResponse,
15+
ListMetricsToolsResponse,
1416
ListPatternsResponse,
1517
ListToolsResponse,
1618
ToolsClient
1719
}
18-
import com.codacy.analysis.core.model.{AnalyserError, DuplicationToolSpec, ParameterSpec, PatternSpec, ToolSpec}
20+
import com.codacy.analysis.core.model.{
21+
AnalyserError,
22+
DuplicationToolSpec,
23+
MetricsToolSpec,
24+
ParameterSpec,
25+
PatternSpec,
26+
ToolSpec
27+
}
1928
import com.codacy.analysis.core.storage.DataStorage
2029
import com.codacy.analysis.core.tools.ToolRepository
2130
import com.codacy.plugins.api.languages.{Language, Languages}
@@ -27,6 +36,7 @@ import scala.concurrent.{Await, ExecutionContext, Future}
2736
class ToolRepositoryRemote(toolsClient: ToolsClient,
2837
toolsDataStorage: DataStorage[ToolSpec],
2938
duplicationToolsDataStorage: DataStorage[DuplicationToolSpec],
39+
metricsToolsDataStorage: DataStorage[MetricsToolSpec],
3040
patternsDataStorageFunc: String => DataStorage[PatternSpec])(
3141
implicit val ec: ExecutionContext,
3242
implicit val mat: Materializer)
@@ -82,6 +92,24 @@ class ToolRepositoryRemote(toolsClient: ToolsClient,
8292
}
8393
}
8494

95+
override lazy val listMetricsTools: Either[AnalyserError, Seq[MetricsToolSpec]] = {
96+
val toolsF = toolsClient.listMetricsTools().value.map {
97+
case Right(ListMetricsToolsResponse.OK(MetricsToolListResponse(data))) =>
98+
Right(data.map(toMetricsToolSpec))
99+
case Right(ListMetricsToolsResponse.InternalServerError(internalServerError)) =>
100+
Left(s"Internal Server Error: ${internalServerError.message}")
101+
case Left(Right(error)) => Left(s"Failed to list tools with ${error.status} status code")
102+
case Left(Left(throwable)) => Left(throwable.getMessage)
103+
}
104+
Await.result(toolsF, 1.minute) match {
105+
case Right(tools) =>
106+
metricsToolsDataStorage.save(tools)
107+
Right(tools)
108+
case Left(err) =>
109+
metricsToolsDataStorage.get().toRight(AnalyserError.FailedToFetchTools(err))
110+
}
111+
}
112+
85113
override def getTool(uuid: String): Either[AnalyserError, ToolSpec] =
86114
listTools.flatMap { toolsSpecs =>
87115
toolsSpecs.find(_.uuid == uuid) match {
@@ -151,6 +179,11 @@ class ToolRepositoryRemote(toolsClient: ToolsClient,
151179
DuplicationToolSpec(tool.dockerImage, languages)
152180
}
153181

182+
private def toMetricsToolSpec(tool: definitions.MetricsTool): MetricsToolSpec = {
183+
val languages = tool.languages.flatMap(Languages.fromName).to[Set]
184+
MetricsToolSpec(tool.dockerImage, languages)
185+
}
186+
154187
private def toToolSpec(tool: definitions.Tool): ToolSpec = {
155188
val languages = tool.languages.flatMap(Languages.fromName).to[Set]
156189
ToolSpec(

toolRepository-remote/src/main/scala/com/codacy/toolRepository/remote/storage/ToolPatternsSpecsEncoders.scala

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package com.codacy.toolRepository.remote.storage
22

3-
import com.codacy.analysis.core.model.{DuplicationToolSpec, ParameterSpec, PatternSpec, ToolSpec}
3+
import com.codacy.analysis.core.model.{DuplicationToolSpec, MetricsToolSpec, ParameterSpec, PatternSpec, ToolSpec}
44
import com.codacy.plugins.api.languages.{Language, Languages}
55
import io.circe.generic.semiauto.{deriveDecoder, deriveEncoder}
66
import io.circe.{Decoder, Encoder, HCursor, Json}
@@ -58,6 +58,14 @@ object ToolPatternsSpecsEncoders {
5858
languages <- c.downField("languages").as[Set[Language]]
5959
} yield DuplicationToolSpec(dockerImage, languages.filter(_ != null))
6060

61+
implicit val metricsToolEncoder: Encoder[MetricsToolSpec] = deriveEncoder[MetricsToolSpec]
62+
63+
implicit val metricsToolDecoder: Decoder[MetricsToolSpec] = (c: HCursor) =>
64+
for {
65+
dockerImage <- c.downField("dockerImage").as[String]
66+
languages <- c.downField("languages").as[Set[Language]]
67+
} yield MetricsToolSpec(dockerImage, languages.filter(_ != null))
68+
6169
implicit val patternParameterDecoder: Decoder[ParameterSpec] = deriveDecoder[ParameterSpec]
6270
implicit val patternParameterEncoder: Encoder[ParameterSpec] = deriveEncoder[ParameterSpec]
6371

toolRepository-remote/src/test/scala/com/codacy/toolRespository/remote/ToolRepositoryRemoteSpec.scala

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ class ToolRepositoryRemoteSpec extends Specification with Mockito with EitherMat
134134
"return the list of tools" in {
135135
val mockedClient = mock[ToolsClient]
136136
val toolRepository =
137-
new ToolRepositoryRemote(mockedClient, emptyStorage, null, _ => emptyStorage)
137+
new ToolRepositoryRemote(mockedClient, emptyStorage, null, null, _ => emptyStorage)
138138

139139
when(mockedClient.listTools(cursor = None)).thenReturn(
140140
toEitherT(ListToolsResponse.OK(ToolListResponse(Vector(toolA), None))),
@@ -151,7 +151,7 @@ class ToolRepositoryRemoteSpec extends Specification with Mockito with EitherMat
151151
"return list with multiple tools" in {
152152
val mockedClient = mock[ToolsClient]
153153
val toolRepository =
154-
new ToolRepositoryRemote(mockedClient, emptyStorage, null, _ => emptyStorage)
154+
new ToolRepositoryRemote(mockedClient, emptyStorage, null, null, _ => emptyStorage)
155155

156156
val paginationInfo = PaginationInfo(Some("cursor"), Some(100), Some(1))
157157

@@ -175,7 +175,7 @@ class ToolRepositoryRemoteSpec extends Specification with Mockito with EitherMat
175175
"return list with stored tools" in {
176176
val mockedClient = mock[ToolsClient]
177177
val toolRepository =
178-
new ToolRepositoryRemote(mockedClient, mockToolsDataWithStorage, null, _ => emptyStorage)
178+
new ToolRepositoryRemote(mockedClient, mockToolsDataWithStorage, null, null, _ => emptyStorage)
179179

180180
mockedClient.listTools(cursor = None).returns(toEitherT(ListToolsResponse.BadRequest(BadRequest("error"))))
181181

@@ -189,7 +189,7 @@ class ToolRepositoryRemoteSpec extends Specification with Mockito with EitherMat
189189
"throw an exception if API returns BadRequest" in {
190190
val mockedClient = mock[ToolsClient]
191191
val toolRepository =
192-
new ToolRepositoryRemote(mockedClient, emptyStorage, null, _ => emptyStorage)
192+
new ToolRepositoryRemote(mockedClient, emptyStorage, null, null, _ => emptyStorage)
193193

194194
mockedClient.listTools(cursor = None).returns(toEitherT(ListToolsResponse.BadRequest(BadRequest("error"))))
195195

@@ -200,7 +200,7 @@ class ToolRepositoryRemoteSpec extends Specification with Mockito with EitherMat
200200
"throw an exception if API returns InternalServerError" in {
201201
val mockedClient = mock[ToolsClient]
202202
val toolRepository =
203-
new ToolRepositoryRemote(mockedClient, emptyStorage, null, _ => emptyStorage)
203+
new ToolRepositoryRemote(mockedClient, emptyStorage, null, null, _ => emptyStorage)
204204

205205
mockedClient
206206
.listTools(cursor = None)
@@ -215,7 +215,7 @@ class ToolRepositoryRemoteSpec extends Specification with Mockito with EitherMat
215215

216216
"return the list of tools" in {
217217
val mockedClient = mock[ToolsClient]
218-
val toolRepository = new ToolRepositoryRemote(mockedClient, null, emptyStorage, null)
218+
val toolRepository = new ToolRepositoryRemote(mockedClient, null, emptyStorage, null, null)
219219

220220
mockedClient
221221
.listDuplicationTools()
@@ -235,7 +235,7 @@ class ToolRepositoryRemoteSpec extends Specification with Mockito with EitherMat
235235
"return list with multiple tools" in {
236236
val mockedClient = mock[ToolsClient]
237237
val toolRepository =
238-
new ToolRepositoryRemote(mockedClient, emptyStorage, null, _ => emptyStorage)
238+
new ToolRepositoryRemote(mockedClient, emptyStorage, null, null, _ => emptyStorage)
239239

240240
val paginationInfo = PaginationInfo(Some("cursor"), Some(100), Some(1))
241241

@@ -262,7 +262,7 @@ class ToolRepositoryRemoteSpec extends Specification with Mockito with EitherMat
262262
"return the list of patterns from API" in {
263263
val mockedClient = mock[ToolsClient]
264264
val toolRepository =
265-
new ToolRepositoryRemote(mockedClient, emptyStorage, null, _ => emptyStorage)
265+
new ToolRepositoryRemote(mockedClient, emptyStorage, null, null, _ => emptyStorage)
266266

267267
when(mockedClient.listTools(cursor = None)).thenReturn(
268268
toEitherT(ListToolsResponse.OK(ToolListResponse(Vector(toolA), None))),
@@ -288,7 +288,7 @@ class ToolRepositoryRemoteSpec extends Specification with Mockito with EitherMat
288288
"return list with multiple patterns from API" in {
289289
val mockedClient = mock[ToolsClient]
290290
val toolRepository =
291-
new ToolRepositoryRemote(mockedClient, emptyStorage, null, _ => emptyStorage)
291+
new ToolRepositoryRemote(mockedClient, emptyStorage, null, null, _ => emptyStorage)
292292

293293
val paginationInfo = PaginationInfo(Some("cursor"), Some(100), Some(1))
294294

@@ -318,7 +318,7 @@ class ToolRepositoryRemoteSpec extends Specification with Mockito with EitherMat
318318
"return list of patterns from storage" in {
319319
val mockedClient = mock[ToolsClient]
320320
val toolRepository =
321-
new ToolRepositoryRemote(mockedClient, mockToolsDataWithStorage, null, mockPatternDataWithStorage)
321+
new ToolRepositoryRemote(mockedClient, mockToolsDataWithStorage, null, null, mockPatternDataWithStorage)
322322

323323
mockedClient
324324
.listTools(cursor = None)
@@ -342,7 +342,7 @@ class ToolRepositoryRemoteSpec extends Specification with Mockito with EitherMat
342342
"return list of patterns first from storage" in {
343343
val mockedClient = mock[ToolsClient]
344344
val toolRepository =
345-
new ToolRepositoryRemote(mockedClient, mockToolsDataWithStorage, null, mockPatternDataWithStorage)
345+
new ToolRepositoryRemote(mockedClient, mockToolsDataWithStorage, null, null, mockPatternDataWithStorage)
346346

347347
mockedClient
348348
.listTools(cursor = None)
@@ -366,7 +366,7 @@ class ToolRepositoryRemoteSpec extends Specification with Mockito with EitherMat
366366
"throw an exception if API returns BadRequest" in {
367367
val mockedClient = mock[ToolsClient]
368368
val toolRepository =
369-
new ToolRepositoryRemote(mockedClient, emptyStorage, null, _ => emptyStorage)
369+
new ToolRepositoryRemote(mockedClient, emptyStorage, null, null, _ => emptyStorage)
370370

371371
mockedClient
372372
.listTools(cursor = None)
@@ -386,7 +386,7 @@ class ToolRepositoryRemoteSpec extends Specification with Mockito with EitherMat
386386

387387
"throw an exception if API returns NotFound" in {
388388
val mockedClient = mock[ToolsClient]
389-
val toolRepository = new ToolRepositoryRemote(mockedClient, emptyStorage, null, _ => emptyStorage)
389+
val toolRepository = new ToolRepositoryRemote(mockedClient, emptyStorage, null, null, _ => emptyStorage)
390390

391391
mockedClient
392392
.listTools(cursor = None)
@@ -407,7 +407,7 @@ class ToolRepositoryRemoteSpec extends Specification with Mockito with EitherMat
407407
"throw an exception if API returns InternalServerError" in {
408408
val mockedClient = mock[ToolsClient]
409409
val toolRepository =
410-
new ToolRepositoryRemote(mockedClient, emptyStorage, null, _ => emptyStorage)
410+
new ToolRepositoryRemote(mockedClient, emptyStorage, null, null, _ => emptyStorage)
411411

412412
mockedClient
413413
.listTools(cursor = None)

0 commit comments

Comments
 (0)