From 152f58c6ec382b089706629651c63e1844e9dbd7 Mon Sep 17 00:00:00 2001
From: Shnick <1132919+Shnick@users.noreply.github.com>
Date: Mon, 6 Jan 2025 09:43:05 +0000
Subject: [PATCH 1/2] BDOG-3337 add bobby reports page
---
.../BobbyExplorerController.scala | 48 ----
.../bobby/BobbyExplorerController.scala | 90 ++++++++
.../BobbyRulesTrendController.scala | 6 +-
.../{service => bobby}/BobbyService.scala | 6 +-
.../view/BobbyExplorerPage.scala.html | 2 +-
.../bobby/view/BobbyReportsPage.scala.html | 218 ++++++++++++++++++
.../view/BobbyRulesTrendPage.scala.html | 2 +-
.../ServiceDependenciesConnector.scala | 13 +-
.../connector/model/BobbyReport.scala | 66 ++++++
.../connector/model/BobbyRule.scala | 3 +-
.../connector/model/RepoBobbyRules.scala | 38 +++
.../search/SearchIndex.scala | 3 +-
.../view/IndexPage.scala.html | 3 +-
.../bobby_violations_banner.scala.html | 3 +-
.../partials/dependency_section.scala.html | 5 +-
.../view/standard_layout.scala.html | 3 +-
conf/app.routes | 6 +-
.../{service => bobby}/BobbyServiceSpec.scala | 2 +-
.../ServiceDependenciesConnectorSpec.scala | 71 +++++-
19 files changed, 509 insertions(+), 79 deletions(-)
delete mode 100644 app/uk/gov/hmrc/cataloguefrontend/BobbyExplorerController.scala
create mode 100644 app/uk/gov/hmrc/cataloguefrontend/bobby/BobbyExplorerController.scala
rename app/uk/gov/hmrc/cataloguefrontend/{ => bobby}/BobbyRulesTrendController.scala (96%)
rename app/uk/gov/hmrc/cataloguefrontend/{service => bobby}/BobbyService.scala (97%)
rename app/uk/gov/hmrc/cataloguefrontend/{ => bobby}/view/BobbyExplorerPage.scala.html (98%)
create mode 100644 app/uk/gov/hmrc/cataloguefrontend/bobby/view/BobbyReportsPage.scala.html
rename app/uk/gov/hmrc/cataloguefrontend/{ => bobby}/view/BobbyRulesTrendPage.scala.html (97%)
create mode 100644 app/uk/gov/hmrc/cataloguefrontend/connector/model/BobbyReport.scala
create mode 100644 app/uk/gov/hmrc/cataloguefrontend/connector/model/RepoBobbyRules.scala
rename test/uk/gov/hmrc/cataloguefrontend/{service => bobby}/BobbyServiceSpec.scala (99%)
diff --git a/app/uk/gov/hmrc/cataloguefrontend/BobbyExplorerController.scala b/app/uk/gov/hmrc/cataloguefrontend/BobbyExplorerController.scala
deleted file mode 100644
index fb17521de..000000000
--- a/app/uk/gov/hmrc/cataloguefrontend/BobbyExplorerController.scala
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright 2023 HM Revenue & Customs
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package uk.gov.hmrc.cataloguefrontend
-
-import play.api.mvc.{Action, AnyContent, MessagesControllerComponents, RequestHeader}
-import uk.gov.hmrc.cataloguefrontend.auth.CatalogueAuthBuilders
-import uk.gov.hmrc.cataloguefrontend.connector.ServiceDependenciesConnector
-import uk.gov.hmrc.cataloguefrontend.service.BobbyService
-import uk.gov.hmrc.cataloguefrontend.view.html.BobbyExplorerPage
-import uk.gov.hmrc.internalauth.client.FrontendAuthComponents
-import uk.gov.hmrc.play.bootstrap.frontend.controller.FrontendController
-
-import javax.inject.Inject
-import scala.concurrent.ExecutionContext
-
-class BobbyExplorerController @Inject() (
- override val mcc : MessagesControllerComponents,
- page : BobbyExplorerPage,
- bobbyService : BobbyService,
- serviceDeps : ServiceDependenciesConnector,
- override val auth: FrontendAuthComponents
-)(using
- override val ec: ExecutionContext
-) extends FrontendController(mcc)
- with CatalogueAuthBuilders:
-
- def list(selector: Option[String]): Action[AnyContent] =
- BasicAuthAction.async: request =>
- given RequestHeader = request
- for
- rules <- bobbyService.getRules()
- counts <- serviceDeps.getBobbyRuleViolations()
- response = Ok(page(rules, counts))
- yield response
diff --git a/app/uk/gov/hmrc/cataloguefrontend/bobby/BobbyExplorerController.scala b/app/uk/gov/hmrc/cataloguefrontend/bobby/BobbyExplorerController.scala
new file mode 100644
index 000000000..da22ec504
--- /dev/null
+++ b/app/uk/gov/hmrc/cataloguefrontend/bobby/BobbyExplorerController.scala
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2023 HM Revenue & Customs
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package uk.gov.hmrc.cataloguefrontend.bobby
+
+import cats.data.EitherT
+import play.api.data.{Form, Forms}
+import play.api.mvc.{Action, AnyContent, MessagesControllerComponents, MessagesRequest, Result, RequestHeader}
+import uk.gov.hmrc.play.bootstrap.frontend.controller.FrontendController
+import uk.gov.hmrc.internalauth.client.FrontendAuthComponents
+import uk.gov.hmrc.cataloguefrontend.auth.CatalogueAuthBuilders
+import uk.gov.hmrc.cataloguefrontend.bobby.view.html.{BobbyExplorerPage, BobbyReportsPage}
+import uk.gov.hmrc.cataloguefrontend.connector.{RepoType, ServiceDependenciesConnector, TeamsAndRepositoriesConnector}
+import uk.gov.hmrc.cataloguefrontend.model.{DigitalService, SlugInfoFlag, TeamName}
+
+import javax.inject.Inject
+import scala.concurrent.{ExecutionContext, Future}
+
+class BobbyExplorerController @Inject() (
+ teamsAndReposConnector : TeamsAndRepositoriesConnector
+, serviceDeps : ServiceDependenciesConnector
+, bobbyService : BobbyService
+, bobbyReportsPage : BobbyReportsPage
+, bobbyExplorerPage : BobbyExplorerPage
+, override val mcc : MessagesControllerComponents
+, override val auth : FrontendAuthComponents
+)(using
+ override val ec: ExecutionContext
+) extends FrontendController(mcc)
+ with CatalogueAuthBuilders:
+
+ def bobbyReports(team: Option[TeamName], digitalService: Option[DigitalService], flag: Option[String]): Action[AnyContent] =
+ BasicAuthAction.async: request =>
+ given MessagesRequest[AnyContent] = request
+ ( for
+ teams <- EitherT.right[Result](teamsAndReposConnector.allTeams())
+ digitalServices <- EitherT.right[Result](teamsAndReposConnector.allDigitalServices())
+ form = BobbyReportFilter.form.bindFromRequest()
+ filter <- EitherT.fromEither[Future](form.fold(
+ formErrors => Left(BadRequest(bobbyReportsPage(form, teams, digitalServices, results = None)))
+ , formObject => Right(formObject)
+ ))
+ results <- EitherT.right[Result]:
+ serviceDeps.bobbyReports(filter.team, filter.digitalService, filter.repoType, filter.flag)
+ yield
+ Ok(bobbyReportsPage(form, teams, digitalServices, results = Some(results)))
+ ).merge
+
+ def list(selector: Option[String]): Action[AnyContent] =
+ BasicAuthAction.async: request =>
+ given RequestHeader = request
+ for
+ rules <- bobbyService.getRules()
+ counts <- serviceDeps.getBobbyRuleViolations()
+ yield Ok(bobbyExplorerPage(rules, counts))
+
+case class BobbyReportFilter(
+ team : Option[TeamName] = None
+, digitalService: Option[DigitalService] = None
+, repoType : Option[RepoType] = None
+, flag : SlugInfoFlag = SlugInfoFlag.Latest
+, isActive : Option[Boolean] = None
+, exempt : Boolean = false
+)
+
+object BobbyReportFilter:
+ lazy val form: Form[BobbyReportFilter] =
+ Form(
+ Forms.mapping(
+ "team" -> Forms.optional(Forms.of[TeamName])
+ , "digitalService" -> Forms.optional(Forms.of[DigitalService])
+ , "repoType" -> Forms.optional(Forms.of[RepoType])
+ , "flag" -> Forms.optional(Forms.of[SlugInfoFlag]).transform(_.getOrElse(SlugInfoFlag.Latest), Some.apply)
+ , "isActive" -> Forms.optional(Forms.boolean)
+ , "exempt" -> Forms.boolean
+ )(BobbyReportFilter.apply)(f => Some(Tuple.fromProductTyped(f)))
+ )
diff --git a/app/uk/gov/hmrc/cataloguefrontend/BobbyRulesTrendController.scala b/app/uk/gov/hmrc/cataloguefrontend/bobby/BobbyRulesTrendController.scala
similarity index 96%
rename from app/uk/gov/hmrc/cataloguefrontend/BobbyRulesTrendController.scala
rename to app/uk/gov/hmrc/cataloguefrontend/bobby/BobbyRulesTrendController.scala
index 419735d7d..6ed86ae26 100644
--- a/app/uk/gov/hmrc/cataloguefrontend/BobbyRulesTrendController.scala
+++ b/app/uk/gov/hmrc/cataloguefrontend/bobby/BobbyRulesTrendController.scala
@@ -14,16 +14,16 @@
* limitations under the License.
*/
-package uk.gov.hmrc.cataloguefrontend
+package uk.gov.hmrc.cataloguefrontend.bobby
import cats.data.EitherT
import cats.instances.future._
import play.api.mvc.{Action, AnyContent, MessagesControllerComponents, MessagesRequest, Result}
import uk.gov.hmrc.cataloguefrontend.auth.CatalogueAuthBuilders
+import uk.gov.hmrc.cataloguefrontend.bobby.view.html.BobbyRulesTrendPage
import uk.gov.hmrc.cataloguefrontend.connector.ServiceDependenciesConnector
import uk.gov.hmrc.cataloguefrontend.model.{SlugInfoFlag, VersionRange}
import uk.gov.hmrc.cataloguefrontend.serviceconfigs.ServiceConfigsConnector
-import uk.gov.hmrc.cataloguefrontend.view.html.BobbyRulesTrendPage
import uk.gov.hmrc.internalauth.client.FrontendAuthComponents
import uk.gov.hmrc.play.bootstrap.frontend.controller.FrontendController
@@ -134,7 +134,7 @@ class BobbyRulesTrendController @Inject() (
object BobbyRulesTrendController:
def display(group: String, artefact: String, versionRange: VersionRange): String =
- uk.gov.hmrc.cataloguefrontend.routes.BobbyRulesTrendController.display(
+ uk.gov.hmrc.cataloguefrontend.bobby.routes.BobbyRulesTrendController.display(
`rules[]` = Seq(s"$group:$artefact:${versionRange.range}")
).toString
diff --git a/app/uk/gov/hmrc/cataloguefrontend/service/BobbyService.scala b/app/uk/gov/hmrc/cataloguefrontend/bobby/BobbyService.scala
similarity index 97%
rename from app/uk/gov/hmrc/cataloguefrontend/service/BobbyService.scala
rename to app/uk/gov/hmrc/cataloguefrontend/bobby/BobbyService.scala
index fe70e4cfa..585583bae 100644
--- a/app/uk/gov/hmrc/cataloguefrontend/service/BobbyService.scala
+++ b/app/uk/gov/hmrc/cataloguefrontend/bobby/BobbyService.scala
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package uk.gov.hmrc.cataloguefrontend.service
+package uk.gov.hmrc.cataloguefrontend.bobby
import uk.gov.hmrc.cataloguefrontend.connector.model.{BobbyRule, BobbyRuleSet}
import uk.gov.hmrc.cataloguefrontend.serviceconfigs.ServiceConfigsConnector
@@ -33,8 +33,6 @@ class BobbyService @Inject() (
)(using ExecutionContext):
def getRules()(using HeaderCarrier): Future[BobbyRulesView] =
- val today = LocalDate.now(clock)
-
def ordering(dateAscending: Boolean) =
Ordering.by: (br: BobbyRule) =>
( br.from.atStartOfDayInstant.toEpochMilli.pipe(x => if dateAscending then x else -x)
@@ -42,6 +40,7 @@ class BobbyService @Inject() (
, br.artefact
)
+ val today = LocalDate.now(clock)
serviceConfigsConnector
.bobbyRules()
.map: ruleset =>
@@ -55,7 +54,6 @@ class BobbyService @Inject() (
BobbyRuleSet(activeLibraries.sorted, activePlugins.sorted)
}
)
-
end getRules
end BobbyService
diff --git a/app/uk/gov/hmrc/cataloguefrontend/view/BobbyExplorerPage.scala.html b/app/uk/gov/hmrc/cataloguefrontend/bobby/view/BobbyExplorerPage.scala.html
similarity index 98%
rename from app/uk/gov/hmrc/cataloguefrontend/view/BobbyExplorerPage.scala.html
rename to app/uk/gov/hmrc/cataloguefrontend/bobby/view/BobbyExplorerPage.scala.html
index 22e25d867..bf35da4cc 100644
--- a/app/uk/gov/hmrc/cataloguefrontend/view/BobbyExplorerPage.scala.html
+++ b/app/uk/gov/hmrc/cataloguefrontend/bobby/view/BobbyExplorerPage.scala.html
@@ -14,7 +14,7 @@
* limitations under the License.
*@
-@import uk.gov.hmrc.cataloguefrontend.{BobbyRulesTrendController, routes => appRoutes}
+@import uk.gov.hmrc.cataloguefrontend.bobby.{BobbyRulesTrendController, routes => appRoutes}
@import uk.gov.hmrc.cataloguefrontend.connector.RepoType
@import uk.gov.hmrc.cataloguefrontend.connector.model.{BobbyRule, BobbyRuleSet, DependencyScope}
@import uk.gov.hmrc.cataloguefrontend.dependency.DependencyExplorerController
diff --git a/app/uk/gov/hmrc/cataloguefrontend/bobby/view/BobbyReportsPage.scala.html b/app/uk/gov/hmrc/cataloguefrontend/bobby/view/BobbyReportsPage.scala.html
new file mode 100644
index 000000000..7e3ff745c
--- /dev/null
+++ b/app/uk/gov/hmrc/cataloguefrontend/bobby/view/BobbyReportsPage.scala.html
@@ -0,0 +1,218 @@
+@*
+ * Copyright 2023 HM Revenue & Customs
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *@
+
+@import uk.gov.hmrc.cataloguefrontend.{routes => appRoutes}
+@import uk.gov.hmrc.cataloguefrontend.bobby.BobbyReportFilter
+@import uk.gov.hmrc.cataloguefrontend.connector.{GitHubTeam, RepoType}
+@import uk.gov.hmrc.cataloguefrontend.connector.model.BobbyReport
+@import uk.gov.hmrc.cataloguefrontend.util.MarkdownLoader
+@import uk.gov.hmrc.cataloguefrontend.util.DateHelper._
+@import views.html.helper.{FieldConstructor, select}
+
+@this(
+ teamNamesPartial: partials.TeamNamesPartial
+)
+
+@(form : Form[BobbyReportFilter]
+, teams : Seq[GitHubTeam]
+, digitalServices: Seq[DigitalService]
+, results : Option[Seq[BobbyReport]]
+, now : java.time.LocalDate = java.time.LocalDate.now()
+)(implicit
+ messages : Messages
+, request : RequestHeader
+)
+
+@implicitField: FieldConstructor = @{ FieldConstructor(catalogueFieldConstructor.f) }
+
+@standard_layout("Bobby Reports", active = "health") {
+
+
+
+
+
+ @defining(
+ results
+ .getOrElse(Seq.empty[BobbyReport])
+ .flatMap: x =>
+ x.violations.collect:
+ case v
+ if v.exempt == form.get.exempt
+ && ( form.get.isActive.fold(true):
+ case true => now.isAfter(v.from)
+ case false => now.isBefore(v.from) || now.isEqual(v.from)
+ ) => (x.repoName, x.repoVersion, x.repoType, v)
+ ) {
+ case Nil => {
+
This search did not return any results.
+
+ }
+ case items => {
+
Found @items.size results
+
+ }
+ }
+
+}
+
+
diff --git a/app/uk/gov/hmrc/cataloguefrontend/view/BobbyRulesTrendPage.scala.html b/app/uk/gov/hmrc/cataloguefrontend/bobby/view/BobbyRulesTrendPage.scala.html
similarity index 97%
rename from app/uk/gov/hmrc/cataloguefrontend/view/BobbyRulesTrendPage.scala.html
rename to app/uk/gov/hmrc/cataloguefrontend/bobby/view/BobbyRulesTrendPage.scala.html
index 7381e5f56..a27c5ab0c 100644
--- a/app/uk/gov/hmrc/cataloguefrontend/view/BobbyRulesTrendPage.scala.html
+++ b/app/uk/gov/hmrc/cataloguefrontend/bobby/view/BobbyRulesTrendPage.scala.html
@@ -14,7 +14,7 @@
* limitations under the License.
*@
-@import uk.gov.hmrc.cataloguefrontend.{BobbyRulesTrendController, routes => appRoutes }
+@import uk.gov.hmrc.cataloguefrontend.bobby.{BobbyRulesTrendController, routes => appRoutes }
@import uk.gov.hmrc.cataloguefrontend.connector.model.BobbyRule
@import helper._
diff --git a/app/uk/gov/hmrc/cataloguefrontend/connector/ServiceDependenciesConnector.scala b/app/uk/gov/hmrc/cataloguefrontend/connector/ServiceDependenciesConnector.scala
index 00dc691e0..8dbe41999 100644
--- a/app/uk/gov/hmrc/cataloguefrontend/connector/ServiceDependenciesConnector.scala
+++ b/app/uk/gov/hmrc/cataloguefrontend/connector/ServiceDependenciesConnector.scala
@@ -18,7 +18,7 @@ package uk.gov.hmrc.cataloguefrontend.connector
import play.api.libs.json.Reads
import uk.gov.hmrc.cataloguefrontend.connector.model._
-import uk.gov.hmrc.cataloguefrontend.model.{ServiceName, SlugInfoFlag, TeamName, Version, VersionRange}
+import uk.gov.hmrc.cataloguefrontend.model.{DigitalService, ServiceName, SlugInfoFlag, TeamName, Version, VersionRange}
import uk.gov.hmrc.cataloguefrontend.service.{ServiceDependencies, SlugVersionInfo}
import uk.gov.hmrc.http.{HeaderCarrier, HttpReads}
import uk.gov.hmrc.http.client.HttpClientV2
@@ -126,6 +126,17 @@ class ServiceDependenciesConnector @Inject() (
.execute[BobbyRulesSummary]
.map(_.summary)
+ def bobbyReports(
+ teamName : Option[TeamName]
+ , digitalService: Option[DigitalService]
+ , repoType : Option[RepoType]
+ , flag : SlugInfoFlag
+ )(using HeaderCarrier): Future[Seq[BobbyReport]] =
+ given Reads[BobbyReport] = BobbyReport.reads
+ httpClientV2
+ .get(url"$servicesDependenciesBaseUrl/api/bobbyReports?team=${teamName.map(_.asString)}&digitalService=${digitalService.map(_.asString)}&repoType=${repoType.map(_.asString)}&flag=${flag.asString}")
+ .execute[Seq[BobbyReport]]
+
def getHistoricBobbyRuleViolations(query: List[String], from: LocalDate, to: LocalDate)(using HeaderCarrier): Future[HistoricBobbyRulesSummary] =
given Reads[HistoricBobbyRulesSummary] = HistoricBobbyRulesSummary.reads
httpClientV2
diff --git a/app/uk/gov/hmrc/cataloguefrontend/connector/model/BobbyReport.scala b/app/uk/gov/hmrc/cataloguefrontend/connector/model/BobbyReport.scala
new file mode 100644
index 000000000..5ddafb668
--- /dev/null
+++ b/app/uk/gov/hmrc/cataloguefrontend/connector/model/BobbyReport.scala
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2023 HM Revenue & Customs
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package uk.gov.hmrc.cataloguefrontend.connector.model
+
+import play.api.libs.functional.syntax._
+import play.api.libs.json.{Json, Reads, __}
+import uk.gov.hmrc.cataloguefrontend.model.{VersionRange, Version}
+import uk.gov.hmrc.cataloguefrontend.connector.RepoType
+
+import java.time.{Instant, LocalDate}
+
+case class BobbyReport(
+ repoName : String
+, repoVersion : Version
+, repoType : RepoType
+, violations : Seq[BobbyReport.Violation]
+, lastUpdated : Instant
+)
+
+object BobbyReport:
+ val reads: Reads[BobbyReport] =
+ given Reads[Violation] = Violation.reads
+ ( (__ \ "repoName" ).read[String]
+ ~ (__ \ "repoVersion").read[Version](Version.format)
+ ~ (__ \ "repoType" ).read[RepoType]
+ ~ (__ \ "violations" ).read[Seq[Violation]]
+ ~ (__ \ "lastUpdated").read[Instant]
+ )(BobbyReport.apply _)
+
+ case class Violation(
+ depGroup : String
+ , depArtefact: String
+ , depVersion : Version
+ , depScopes : Set[DependencyScope]
+ , range : VersionRange
+ , reason : String
+ , from : LocalDate
+ , exempt : Boolean
+ )
+
+ object Violation:
+ val reads: Reads[Violation] =
+ given Reads[VersionRange] = VersionRange.format
+ ( (__ \ "depGroup" ).read[String]
+ ~ (__ \ "depArtefact").read[String]
+ ~ (__ \ "depVersion" ).read[Version](Version.format)
+ ~ (__ \ "depScopes" ).read[Set[DependencyScope]]
+ ~ (__ \ "range" ).read[VersionRange]
+ ~ (__ \ "reason" ).read[String]
+ ~ (__ \ "from" ).read[LocalDate]
+ ~ (__ \ "exempt" ).read[Boolean]
+ )(Violation.apply _)
diff --git a/app/uk/gov/hmrc/cataloguefrontend/connector/model/BobbyRule.scala b/app/uk/gov/hmrc/cataloguefrontend/connector/model/BobbyRule.scala
index 978f1b4b2..705923680 100644
--- a/app/uk/gov/hmrc/cataloguefrontend/connector/model/BobbyRule.scala
+++ b/app/uk/gov/hmrc/cataloguefrontend/connector/model/BobbyRule.scala
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 HM Revenue & Customs
+ * Copyright 2024 HM Revenue & Customs
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,7 +22,6 @@ import uk.gov.hmrc.cataloguefrontend.model.VersionRange
import java.time.LocalDate
-
case class BobbyRule(
group : String,
artefact : String,
diff --git a/app/uk/gov/hmrc/cataloguefrontend/connector/model/RepoBobbyRules.scala b/app/uk/gov/hmrc/cataloguefrontend/connector/model/RepoBobbyRules.scala
new file mode 100644
index 000000000..6254b0813
--- /dev/null
+++ b/app/uk/gov/hmrc/cataloguefrontend/connector/model/RepoBobbyRules.scala
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2023 HM Revenue & Customs
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package uk.gov.hmrc.cataloguefrontend.connector.model
+
+import play.api.libs.functional.syntax._
+import play.api.libs.json.{Reads, __}
+import uk.gov.hmrc.cataloguefrontend.model.Version
+import uk.gov.hmrc.cataloguefrontend.connector.RepoType
+
+case class RepoBobbyRules(
+ repoName : String
+, repoVersion: Version
+, repoType : RepoType
+, bobbyRules : Seq[BobbyRule]
+)
+
+object RepoBobbyRules:
+ val reads: Reads[RepoBobbyRules] =
+ given Reads[BobbyRule] = BobbyRule.reads
+ ( (__ \ "repoName" ).read[String]
+ ~ (__ \ "repoVersion").read[Version](Version.format)
+ ~ (__ \ "repoType" ).read[RepoType]
+ ~ (__ \ "bobbyRules" ).read[Seq[BobbyRule]]
+ )(RepoBobbyRules.apply)
diff --git a/app/uk/gov/hmrc/cataloguefrontend/search/SearchIndex.scala b/app/uk/gov/hmrc/cataloguefrontend/search/SearchIndex.scala
index 39c14b019..b8e3e46af 100644
--- a/app/uk/gov/hmrc/cataloguefrontend/search/SearchIndex.scala
+++ b/app/uk/gov/hmrc/cataloguefrontend/search/SearchIndex.scala
@@ -20,6 +20,7 @@ package uk.gov.hmrc.cataloguefrontend.search
import play.api.Configuration
import uk.gov.hmrc.cataloguefrontend.routes as catalogueRoutes
import uk.gov.hmrc.cataloguefrontend.connector.{RepoType, TeamsAndRepositoriesConnector, UserManagementConnector}
+import uk.gov.hmrc.cataloguefrontend.bobby.routes as bobbyRoutes
import uk.gov.hmrc.cataloguefrontend.createrepository.routes as createRepoRoutes
import uk.gov.hmrc.cataloguefrontend.dependency.routes as dependencyRoutes
import uk.gov.hmrc.cataloguefrontend.deployments.routes as deployRoutes
@@ -67,7 +68,7 @@ class SearchIndex @Inject()(
private val hardcodedLinks = List(
SearchTerm("explorer", "dependency", dependencyRoutes.DependencyExplorerController.landing.url, 1.0f, Set("depex")),
- SearchTerm("explorer", "bobby", catalogueRoutes.BobbyExplorerController.list().url, 1.0f),
+ SearchTerm("explorer", "bobby", bobbyRoutes.BobbyExplorerController.list().url, 1.0f),
SearchTerm("explorer", "jdk", catalogueRoutes.JdkVersionController.compareAllEnvironments().url, 1.0f, Set("jdk", "jre")),
SearchTerm("explorer", "leaks", leakRoutes.LeakDetectionController.ruleSummaries.url, 1.0f, Set("lds")),
SearchTerm("page", "whats running where (wrw)", wrwRoutes.WhatsRunningWhereController.releases().url, 1.0f, Set("wrw")),
diff --git a/app/uk/gov/hmrc/cataloguefrontend/view/IndexPage.scala.html b/app/uk/gov/hmrc/cataloguefrontend/view/IndexPage.scala.html
index 249e7f29d..79e0c17ed 100644
--- a/app/uk/gov/hmrc/cataloguefrontend/view/IndexPage.scala.html
+++ b/app/uk/gov/hmrc/cataloguefrontend/view/IndexPage.scala.html
@@ -15,6 +15,7 @@
*@
@import uk.gov.hmrc.cataloguefrontend.{routes => appRoutes}
+@import uk.gov.hmrc.cataloguefrontend.bobby.{routes => bobbyRoutes}
@import uk.gov.hmrc.cataloguefrontend.connector.ConfluenceConnector
@import uk.gov.hmrc.cataloguefrontend.deployments.{routes => deployRoutes}
@import uk.gov.hmrc.cataloguefrontend.dependency.{routes => dependencyRoutes}
@@ -45,7 +46,7 @@ Welcome to the MDTP Catalogue
what dependencies
and config they use, and who maintains them.
You can also shutter your service to the outside world,
- view bobby rules, see what
+ view bobby rules, see what
JDK versions are in use, discover
which service corresponds to a given URL, and more to come!
diff --git a/app/uk/gov/hmrc/cataloguefrontend/view/partials/bobby_violations_banner.scala.html b/app/uk/gov/hmrc/cataloguefrontend/view/partials/bobby_violations_banner.scala.html
index b2261e2da..655b8db7f 100644
--- a/app/uk/gov/hmrc/cataloguefrontend/view/partials/bobby_violations_banner.scala.html
+++ b/app/uk/gov/hmrc/cataloguefrontend/view/partials/bobby_violations_banner.scala.html
@@ -16,6 +16,7 @@
@import uk.gov.hmrc.cataloguefrontend.connector.model.Dependency
@import uk.gov.hmrc.cataloguefrontend.{routes => appRoutes}
+@import uk.gov.hmrc.cataloguefrontend.bobby.{routes => bobbyRoutes}
@import uk.gov.hmrc.cataloguefrontend.teams.{routes => teamRoutes}
@(environment : Option[Environment]
@@ -29,7 +30,7 @@
@teamName.map { name =>
s"-${e.asString}")}" href="@teamRoutes.TeamsController.outOfDateTeamDependencies(name)">See Dependencies.
}.getOrElse {
- Please review the lists below, and refer to s"-${e.asString}")}" href="@appRoutes.BobbyExplorerController.list()">Bobby Rules.
+ Please review the lists below, and refer to s"-${e.asString}")}" href="@bobbyRoutes.BobbyExplorerController.list()">Bobby Rules.
}
}
diff --git a/app/uk/gov/hmrc/cataloguefrontend/view/partials/dependency_section.scala.html b/app/uk/gov/hmrc/cataloguefrontend/view/partials/dependency_section.scala.html
index b217bc9e5..f33c568e3 100644
--- a/app/uk/gov/hmrc/cataloguefrontend/view/partials/dependency_section.scala.html
+++ b/app/uk/gov/hmrc/cataloguefrontend/view/partials/dependency_section.scala.html
@@ -15,6 +15,7 @@
*@
@import uk.gov.hmrc.cataloguefrontend.{ routes => appRoutes }
+@import uk.gov.hmrc.cataloguefrontend.bobby.{routes => bobbyRoutes}
@import uk.gov.hmrc.cataloguefrontend.vulnerabilities.{ routes => vulnerabilityRoutes}
@import uk.gov.hmrc.cataloguefrontend.connector.model.{Dependency, ImportedBy, VersionState}
@import uk.gov.hmrc.cataloguefrontend.connector.model.DependencyScope.It
@@ -74,8 +75,8 @@
}
@dependency.versionState match {
- case Some(VersionState.BobbyRulePending (violation)) => {
See rule }
- case Some(VersionState.BobbyRuleViolated(violation)) => {
See rule }
+ case Some(VersionState.BobbyRulePending (violation)) => {
See rule }
+ case Some(VersionState.BobbyRuleViolated(violation)) => {
See rule }
case _ => { }
}
diff --git a/app/uk/gov/hmrc/cataloguefrontend/view/standard_layout.scala.html b/app/uk/gov/hmrc/cataloguefrontend/view/standard_layout.scala.html
index d58474986..9c8ec69fb 100644
--- a/app/uk/gov/hmrc/cataloguefrontend/view/standard_layout.scala.html
+++ b/app/uk/gov/hmrc/cataloguefrontend/view/standard_layout.scala.html
@@ -15,6 +15,7 @@
*@
@import uk.gov.hmrc.cataloguefrontend.{routes => appRoutes }
+@import uk.gov.hmrc.cataloguefrontend.bobby.{routes => bobbyRoutes}
@import uk.gov.hmrc.cataloguefrontend.cost.{routes => costRoutes}
@import uk.gov.hmrc.cataloguefrontend.dependency.{routes => dependencyRoutes}
@import uk.gov.hmrc.cataloguefrontend.prcommenter.{routes => prcommenterRoutes}
@@ -162,7 +163,7 @@
Health-Indicators
Platform Initiatives
- Bobby Explorer
+ Bobby Explorer
Leak Detection - Rules
Leak Detection - Repositories
diff --git a/conf/app.routes b/conf/app.routes
index 86939e914..f534a6527 100644
--- a/conf/app.routes
+++ b/conf/app.routes
@@ -67,8 +67,6 @@ GET /dependencies/:name/:version/graphs uk.gov.hmrc.cataloguefro
GET /dependencyexplorer uk.gov.hmrc.cataloguefrontend.dependency.DependencyExplorerController.landing
GET /dependencyexplorer/results uk.gov.hmrc.cataloguefrontend.dependency.DependencyExplorerController.search(group: String ?= "", artefact: String ?= "", versionRange: Option[String] ?= None, team: Option[TeamName] ?= None, flag: Option[String] ?= None, `scope[]`: Option[Seq[String]] ?= None, `repoType[]`: Option[Seq[String]] ?= None, asCsv: Boolean ?= false)
-GET /bobbyrulestrend uk.gov.hmrc.cataloguefrontend.BobbyRulesTrendController.display(`rules[]`: Seq[String] ?= Seq.empty, from: java.time.LocalDate ?= java.time.LocalDate.now().minusYears(2), to: java.time.LocalDate ?= java.time.LocalDate.now())
-
GET /jdkexplorer/environment uk.gov.hmrc.cataloguefrontend.JdkVersionController.findLatestVersions(env: String, teamName: Option[TeamName] ?= None)
GET /jdkexplorer uk.gov.hmrc.cataloguefrontend.JdkVersionController.compareAllEnvironments(teamName: Option[TeamName] ?= None)
@@ -83,7 +81,9 @@ GET /config/warnings/search/results uk.gov.hmrc.cataloguefro
GET /cost-explorer uk.gov.hmrc.cataloguefrontend.cost.CostController.costExplorer(team: Option[TeamName] ?= None, asCSV: Boolean ?= false)
-GET /bobbyrules uk.gov.hmrc.cataloguefrontend.BobbyExplorerController.list(selector: Option[String] ?= None)
+GET /bobby-reports uk.gov.hmrc.cataloguefrontend.bobby.BobbyExplorerController.bobbyReports(teamName: Option[TeamName] ?= None, digitalService: Option[DigitalService] ?= None, flag: Option[String] ?= None)
+GET /bobbyrules uk.gov.hmrc.cataloguefrontend.bobby.BobbyExplorerController.list(selector: Option[String] ?= None)
+GET /bobbyrulestrend uk.gov.hmrc.cataloguefrontend.bobby.BobbyRulesTrendController.display(`rules[]`: Seq[String] ?= Seq.empty, from: java.time.LocalDate ?= java.time.LocalDate.now().minusYears(2), to: java.time.LocalDate ?= java.time.LocalDate.now())
GET /pr-commenter/recommendations uk.gov.hmrc.cataloguefrontend.prcommenter.PrCommenterController.recommendations(name: Option[String] ?= None, teamName: Option[TeamName] ?= None, commentType: Option[String] ?= None)
diff --git a/test/uk/gov/hmrc/cataloguefrontend/service/BobbyServiceSpec.scala b/test/uk/gov/hmrc/cataloguefrontend/bobby/BobbyServiceSpec.scala
similarity index 99%
rename from test/uk/gov/hmrc/cataloguefrontend/service/BobbyServiceSpec.scala
rename to test/uk/gov/hmrc/cataloguefrontend/bobby/BobbyServiceSpec.scala
index ccc485661..c4c64226b 100644
--- a/test/uk/gov/hmrc/cataloguefrontend/service/BobbyServiceSpec.scala
+++ b/test/uk/gov/hmrc/cataloguefrontend/bobby/BobbyServiceSpec.scala
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package uk.gov.hmrc.cataloguefrontend.service
+package uk.gov.hmrc.cataloguefrontend.bobby
import org.mockito.Mockito.when
import org.scalatestplus.mockito.MockitoSugar
diff --git a/test/uk/gov/hmrc/cataloguefrontend/connector/ServiceDependenciesConnectorSpec.scala b/test/uk/gov/hmrc/cataloguefrontend/connector/ServiceDependenciesConnectorSpec.scala
index 007be3f38..c860543d0 100644
--- a/test/uk/gov/hmrc/cataloguefrontend/connector/ServiceDependenciesConnectorSpec.scala
+++ b/test/uk/gov/hmrc/cataloguefrontend/connector/ServiceDependenciesConnectorSpec.scala
@@ -27,10 +27,12 @@ import play.api.inject.guice.GuiceApplicationBuilder
import play.api.libs.json.{Json, Reads}
import uk.gov.hmrc.http.test.WireMockSupport
import uk.gov.hmrc.cataloguefrontend.connector.model._
-import uk.gov.hmrc.cataloguefrontend.model.{Environment, ServiceName, SlugInfoFlag, Version}
+import uk.gov.hmrc.cataloguefrontend.model.{DigitalService, Environment, ServiceName, SlugInfoFlag, TeamName, Version, VersionRange}
import uk.gov.hmrc.cataloguefrontend.service.ServiceDependencies
import uk.gov.hmrc.http.HeaderCarrier
+import java.time.{Instant, LocalDate}
+
class ServiceDependenciesConnectorSpec
extends AnyWordSpec
with Matchers
@@ -55,8 +57,8 @@ class ServiceDependenciesConnectorSpec
given HeaderCarrier = HeaderCarrier()
- "getJdkVersions" should {
- "returns JDK versions with vendor" in {
+ "getJdkVersions" should:
+ "returns JDK versions with vendor" in:
stubFor(
get(urlEqualTo(s"/api/jdkVersions?flag=${SlugInfoFlag.ForEnvironment(Environment.Production).asString}"))
.willReturn(
@@ -81,11 +83,9 @@ class ServiceDependenciesConnectorSpec
response(1).version shouldBe Version("1.8.0_191")
response(1).vendor shouldBe Vendor.OpenJDK
response(1).kind shouldBe Kind.JRE
- }
- }
- "JSON Reader" should {
- "read json with java section" in {
+ "JSON Reader" should:
+ "read json with java section" in:
given Reads[ServiceDependencies] = ServiceDependencies.reads
val json = """{
@@ -132,6 +132,59 @@ class ServiceDependenciesConnectorSpec
res.java.version shouldBe "1.8.0_191"
res.java.vendor.asString shouldBe "OpenJDK"
res.java.kind.asString shouldBe "JDK"
- }
- }
+
+ "bobbyReports" should:
+ "return bobby reports for a given search" in:
+ stubFor:
+ get(urlEqualTo("/api/bobbyReports?team=some-team&digitalService=some-digital-service&repoType=Service&flag=latest"))
+ .willReturn(aResponse().withBody("""
+ [{
+ "repoName" : "some-repo",
+ "repoVersion": "1.165.0",
+ "repoType" : "Service",
+ "violations" : [{
+ "depGroup" : "uk.gov.hmrc",
+ "depArtefact": "some-library",
+ "depVersion" : "4.0.0",
+ "depScopes" : ["compile","test"],
+ "range" : "[0.0.0,)",
+ "reason" : "Deprecated Library",
+ "from" : "2025-09-30",
+ "exempt" : false
+ }],
+ "lastUpdated" : "2025-01-03T17:37:47.338Z",
+ "latest" : true,
+ "production" : true,
+ "qa" : true,
+ "staging" : true,
+ "development" : true,
+ "externaltest": false,
+ "integration" : false
+ }]
+ """))
+
+ serviceDependenciesConnector
+ .bobbyReports(
+ teamName = Some(TeamName("some-team"))
+ , digitalService = Some(DigitalService("some-digital-service"))
+ , repoType = Some(RepoType.Service)
+ , flag = SlugInfoFlag.Latest)
+ .futureValue shouldBe Seq(
+ BobbyReport(
+ repoName = "some-repo"
+ , repoVersion = Version("1.165.0")
+ , repoType = RepoType.Service
+ , violations = Seq(BobbyReport.Violation(
+ depGroup = "uk.gov.hmrc"
+ , depArtefact = "some-library"
+ , depVersion = Version("4.0.0")
+ , depScopes = Set(DependencyScope.Compile, DependencyScope.Test)
+ , range = VersionRange("[0.0.0,)")
+ , reason = "Deprecated Library"
+ , from = LocalDate.parse("2025-09-30")
+ , exempt = false
+ ))
+ , lastUpdated = Instant.parse("2025-01-03T17:37:47.338Z")
+ )
+ )
}
From ac90baf48f738e53ebb09be5c0c0113d528831b6 Mon Sep 17 00:00:00 2001
From: Shnick <1132919+Shnick@users.noreply.github.com>
Date: Tue, 7 Jan 2025 09:42:24 +0000
Subject: [PATCH 2/2] BDOG-3337 change bobby reports page name to bobby
violations + remove exempt toggle
---
.../bobby/BobbyExplorerController.scala | 24 +++++++++----------
...la.html => BobbyViolationsPage.scala.html} | 21 ++++++----------
conf/app.routes | 2 +-
3 files changed, 19 insertions(+), 28 deletions(-)
rename app/uk/gov/hmrc/cataloguefrontend/bobby/view/{BobbyReportsPage.scala.html => BobbyViolationsPage.scala.html} (92%)
diff --git a/app/uk/gov/hmrc/cataloguefrontend/bobby/BobbyExplorerController.scala b/app/uk/gov/hmrc/cataloguefrontend/bobby/BobbyExplorerController.scala
index da22ec504..999037f01 100644
--- a/app/uk/gov/hmrc/cataloguefrontend/bobby/BobbyExplorerController.scala
+++ b/app/uk/gov/hmrc/cataloguefrontend/bobby/BobbyExplorerController.scala
@@ -22,7 +22,7 @@ import play.api.mvc.{Action, AnyContent, MessagesControllerComponents, MessagesR
import uk.gov.hmrc.play.bootstrap.frontend.controller.FrontendController
import uk.gov.hmrc.internalauth.client.FrontendAuthComponents
import uk.gov.hmrc.cataloguefrontend.auth.CatalogueAuthBuilders
-import uk.gov.hmrc.cataloguefrontend.bobby.view.html.{BobbyExplorerPage, BobbyReportsPage}
+import uk.gov.hmrc.cataloguefrontend.bobby.view.html.{BobbyExplorerPage, BobbyViolationsPage}
import uk.gov.hmrc.cataloguefrontend.connector.{RepoType, ServiceDependenciesConnector, TeamsAndRepositoriesConnector}
import uk.gov.hmrc.cataloguefrontend.model.{DigitalService, SlugInfoFlag, TeamName}
@@ -30,19 +30,19 @@ import javax.inject.Inject
import scala.concurrent.{ExecutionContext, Future}
class BobbyExplorerController @Inject() (
- teamsAndReposConnector : TeamsAndRepositoriesConnector
-, serviceDeps : ServiceDependenciesConnector
-, bobbyService : BobbyService
-, bobbyReportsPage : BobbyReportsPage
-, bobbyExplorerPage : BobbyExplorerPage
-, override val mcc : MessagesControllerComponents
-, override val auth : FrontendAuthComponents
+ teamsAndReposConnector: TeamsAndRepositoriesConnector
+, serviceDeps : ServiceDependenciesConnector
+, bobbyService : BobbyService
+, bobbyViolationsPage : BobbyViolationsPage
+, bobbyExplorerPage : BobbyExplorerPage
+, override val mcc : MessagesControllerComponents
+, override val auth : FrontendAuthComponents
)(using
override val ec: ExecutionContext
) extends FrontendController(mcc)
with CatalogueAuthBuilders:
- def bobbyReports(team: Option[TeamName], digitalService: Option[DigitalService], flag: Option[String]): Action[AnyContent] =
+ def bobbyViolations(team: Option[TeamName], digitalService: Option[DigitalService], flag: Option[String]): Action[AnyContent] =
BasicAuthAction.async: request =>
given MessagesRequest[AnyContent] = request
( for
@@ -50,13 +50,13 @@ class BobbyExplorerController @Inject() (
digitalServices <- EitherT.right[Result](teamsAndReposConnector.allDigitalServices())
form = BobbyReportFilter.form.bindFromRequest()
filter <- EitherT.fromEither[Future](form.fold(
- formErrors => Left(BadRequest(bobbyReportsPage(form, teams, digitalServices, results = None)))
+ formErrors => Left(BadRequest(bobbyViolationsPage(form, teams, digitalServices, results = None)))
, formObject => Right(formObject)
))
results <- EitherT.right[Result]:
serviceDeps.bobbyReports(filter.team, filter.digitalService, filter.repoType, filter.flag)
yield
- Ok(bobbyReportsPage(form, teams, digitalServices, results = Some(results)))
+ Ok(bobbyViolationsPage(form, teams, digitalServices, results = Some(results)))
).merge
def list(selector: Option[String]): Action[AnyContent] =
@@ -73,7 +73,6 @@ case class BobbyReportFilter(
, repoType : Option[RepoType] = None
, flag : SlugInfoFlag = SlugInfoFlag.Latest
, isActive : Option[Boolean] = None
-, exempt : Boolean = false
)
object BobbyReportFilter:
@@ -85,6 +84,5 @@ object BobbyReportFilter:
, "repoType" -> Forms.optional(Forms.of[RepoType])
, "flag" -> Forms.optional(Forms.of[SlugInfoFlag]).transform(_.getOrElse(SlugInfoFlag.Latest), Some.apply)
, "isActive" -> Forms.optional(Forms.boolean)
- , "exempt" -> Forms.boolean
)(BobbyReportFilter.apply)(f => Some(Tuple.fromProductTyped(f)))
)
diff --git a/app/uk/gov/hmrc/cataloguefrontend/bobby/view/BobbyReportsPage.scala.html b/app/uk/gov/hmrc/cataloguefrontend/bobby/view/BobbyViolationsPage.scala.html
similarity index 92%
rename from app/uk/gov/hmrc/cataloguefrontend/bobby/view/BobbyReportsPage.scala.html
rename to app/uk/gov/hmrc/cataloguefrontend/bobby/view/BobbyViolationsPage.scala.html
index 7e3ff745c..4877113c2 100644
--- a/app/uk/gov/hmrc/cataloguefrontend/bobby/view/BobbyReportsPage.scala.html
+++ b/app/uk/gov/hmrc/cataloguefrontend/bobby/view/BobbyViolationsPage.scala.html
@@ -38,10 +38,10 @@
@implicitField: FieldConstructor = @{ FieldConstructor(catalogueFieldConstructor.f) }
-@standard_layout("Bobby Reports", active = "health") {
-
+@standard_layout("Bobby violations", active = "health") {
+
-