Skip to content

Commit

Permalink
Merge pull request #913 from hmrc/BDOG-3170-derives
Browse files Browse the repository at this point in the history
BDOG-3170 Use of derives
  • Loading branch information
colin-lamed committed Jul 2, 2024
2 parents b24fe88 + 3d2d504 commit 00caefc
Show file tree
Hide file tree
Showing 105 changed files with 946 additions and 878 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ class BobbyRulesTrendController @Inject() (
page(
form.fill(SearchForm(rules = Seq.empty, from = LocalDate.now().minusYears(2) , to = LocalDate.now())),
allRules,
flags = SlugInfoFlag.values,
flags = SlugInfoFlag.values.toSeq,
data = None
)
)
Expand All @@ -68,17 +68,18 @@ class BobbyRulesTrendController @Inject() (
allRules <- configConnector.bobbyRules()
.map(_.libraries)
.map(_.sortBy(-_.from.toEpochDay))
flags = SlugInfoFlag.values.toSeq
pageWithError = (msg: String) =>
page(
form.bindFromRequest().withGlobalError(msg),
allRules,
flags = SlugInfoFlag.values,
flags,
data = None
)
res <- form
.bindFromRequest()
.fold(
hasErrors = formWithErrors => Future.successful(BadRequest(page(formWithErrors, allRules, flags = SlugInfoFlag.values, data = None))),
hasErrors = formWithErrors => Future.successful(BadRequest(page(formWithErrors, allRules, flags, data = None))),
success = query =>
(for
violations <- EitherT.right[Result](serviceDeps.getHistoricBobbyRuleViolations(query.rules.toList, query.from, query.to))
Expand All @@ -87,7 +88,7 @@ class BobbyRulesTrendController @Inject() (
Ok(page(
form.bindFromRequest(),
allRules,
flags = SlugInfoFlag.values,
flags,
Some(
countData
.groupBy { case ((_, e), _) => e }
Expand Down Expand Up @@ -120,14 +121,13 @@ class BobbyRulesTrendController @Inject() (
)

val form =
import uk.gov.hmrc.cataloguefrontend.util.FormUtils._
import play.api.data._
import play.api.data.Forms._
import uk.gov.hmrc.cataloguefrontend.util.FormUtils.notEmptySeq
import play.api.data.{Form, Forms}
Form(
Forms.mapping(
"rules" -> Forms.seq(Forms.text).verifying(notEmptySeq),
"from" -> default(Forms.localDate, LocalDate.now().minusYears(2)),
"to" -> default(Forms.localDate, LocalDate.now())
"from" -> Forms.default(Forms.localDate, LocalDate.now().minusYears(2)),
"to" -> Forms.default(Forms.localDate, LocalDate.now())
)(SearchForm.apply)(sf => Some(Tuple.fromProductTyped(sf)))
)
}
Expand Down
21 changes: 10 additions & 11 deletions app/uk/gov/hmrc/cataloguefrontend/CatalogueController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ package uk.gov.hmrc.cataloguefrontend
import cats.data.{EitherT, OptionT}
import cats.implicits._
import play.api.data.{Form, Forms}
import play.api.data.Forms._
import play.api.i18n.I18nSupport
import play.api.mvc._
import play.api.{Configuration, Logger}
Expand Down Expand Up @@ -161,7 +160,7 @@ class CatalogueController @Inject() (
serviceMetricsConnector.nonPerformantQueriesForService(serviceName)
else
Future.successful(Seq.empty)
envDatas <- Environment.valuesAsSeq
envDatas <- Environment.values.toSeq
.traverse: env =>
val deployedVersions = deployments.filter(_.environment == env).map(_.version)
// a single environment may have multiple versions during a deployment
Expand All @@ -170,7 +169,7 @@ class CatalogueController @Inject() (
case Some(version) =>
for
repoModules <- serviceDependenciesConnector.getRepositoryModules(repositoryName, version)
shutterStates <- ShutterType.valuesAsSeq.foldLeftM[Future, Seq[ShutterState]](Seq.empty): (acc, shutterType) =>
shutterStates <- ShutterType.values.toSeq.foldLeftM[Future, Seq[ShutterState]](Seq.empty): (acc, shutterType) =>
shutterService
.getShutterStates(shutterType, env, Some(serviceName))
.map(acc ++ _)
Expand All @@ -182,8 +181,8 @@ class CatalogueController @Inject() (
telemetryLinks.grafanaDashboard(env, serviceName),
telemetryLinks.kibanaDashboard(env, serviceName)
),
nonPerformantQueryLinks = database.fold(Seq[uk.gov.hmrc.cataloguefrontend.connector.Link]()): d =>
telemetryLinks.kibanaNonPerformantQueries(env, ServiceName(d), nonPerformantQueries) // TODO should this really be Database rather than ServiceName?
nonPerformantQueryLinks = database.fold(Seq[uk.gov.hmrc.cataloguefrontend.connector.Link]()): databaseName =>
telemetryLinks.kibanaNonPerformantQueries(env, serviceName, databaseName, nonPerformantQueries)
)
yield Some((SlugInfoFlag.ForEnvironment(env): SlugInfoFlag) -> data)
case None =>
Expand Down Expand Up @@ -477,8 +476,8 @@ case class TeamFilter(

object TeamFilter:
lazy val form = Form(
mapping(
"name" -> optional(text).transform[Option[String]](_.filter(_.trim.nonEmpty), identity)
Forms.mapping(
"name" -> Forms.optional(Forms.text).transform[Option[String]](_.filter(_.trim.nonEmpty), identity)
)(TeamFilter.apply)(f => Some.apply(f.name))
)

Expand Down Expand Up @@ -540,10 +539,10 @@ case class DefaultBranchesFilter(
object DefaultBranchesFilter {
lazy val form: Form[DefaultBranchesFilter] =
Form(
mapping(
"name" -> optional(text).transform[Option[String]](_.filter(_.trim.nonEmpty), identity),
"teamNames" -> optional(Forms.of[TeamName](TeamName.formFormat)),
"defaultBranch" -> optional(text).transform[Option[String]](_.filter(_.trim.nonEmpty), identity)
Forms.mapping(
"name" -> Forms.optional(Forms.text).transform[Option[String]](_.filter(_.trim.nonEmpty), identity),
"teamNames" -> Forms.optional(Forms.of[TeamName](TeamName.formFormat)),
"defaultBranch" -> Forms.optional(Forms.text).transform[Option[String]](_.filter(_.trim.nonEmpty), identity)
)(DefaultBranchesFilter.apply)(f => Some(Tuple.fromProductTyped(f)))
)
}
9 changes: 5 additions & 4 deletions app/uk/gov/hmrc/cataloguefrontend/JdkVersionController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ import cats.implicits._
import play.api.mvc.MessagesControllerComponents
import uk.gov.hmrc.cataloguefrontend.auth.CatalogueAuthBuilders
import uk.gov.hmrc.cataloguefrontend.connector.TeamsAndRepositoriesConnector
import uk.gov.hmrc.cataloguefrontend.model.{SlugInfoFlag, TeamName}
import uk.gov.hmrc.cataloguefrontend.model.{SlugInfoFlag, TeamName, given}
import uk.gov.hmrc.cataloguefrontend.service.DependenciesService
import uk.gov.hmrc.cataloguefrontend.util.Parser
import uk.gov.hmrc.cataloguefrontend.view.html.{JdkAcrossEnvironmentsPage, JdkVersionPage}
import uk.gov.hmrc.internalauth.client.FrontendAuthComponents
import uk.gov.hmrc.play.bootstrap.frontend.controller.FrontendController
Expand All @@ -46,18 +47,18 @@ class JdkVersionController @Inject() (
BasicAuthAction.async { implicit request =>
for
teams <- teamsAndRepositoriesConnector.allTeams()
selectedFlag = SlugInfoFlag.parse(flag.toLowerCase).getOrElse(SlugInfoFlag.Latest)
selectedFlag = Parser[SlugInfoFlag].parse(flag.toLowerCase).getOrElse(SlugInfoFlag.Latest)
selectedTeamName = teamName.flatMap(n => teams.find(_.name == n)).map(_.name)
jdkVersions <- dependenciesService.getJdkVersions(selectedFlag, selectedTeamName)
yield Ok(jdkVersionPage(jdkVersions.sortBy(j => (j.version, j.serviceName)), SlugInfoFlag.values, teams, selectedFlag, selectedTeamName))
yield Ok(jdkVersionPage(jdkVersions.sortBy(j => (j.version, j.serviceName)), SlugInfoFlag.values.toSeq, teams, selectedFlag, selectedTeamName))
}

def compareAllEnvironments(teamName: Option[TeamName]) =
BasicAuthAction.async { implicit request =>
for
teams <- teamsAndRepositoriesConnector.allTeams()
selectedTeamName = teamName.flatMap(n => teams.find(_.name == n)).map(_.name)
envs <- SlugInfoFlag.values.traverse(env => dependenciesService.getJdkCountsForEnv(env, selectedTeamName))
envs <- SlugInfoFlag.values.toSeq.traverse(env => dependenciesService.getJdkCountsForEnv(env, selectedTeamName))
jdks = envs.flatMap(_.usage.keys).distinct.sortBy(_._1)
yield Ok(jdkAcrossEnvironmentsPage(envs, jdks, teams, selectedTeamName))
}
Expand Down
9 changes: 5 additions & 4 deletions app/uk/gov/hmrc/cataloguefrontend/SbtVersionController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ import cats.implicits._
import play.api.mvc.MessagesControllerComponents
import uk.gov.hmrc.cataloguefrontend.auth.CatalogueAuthBuilders
import uk.gov.hmrc.cataloguefrontend.connector.TeamsAndRepositoriesConnector
import uk.gov.hmrc.cataloguefrontend.model.{SlugInfoFlag, TeamName}
import uk.gov.hmrc.cataloguefrontend.model.{SlugInfoFlag, TeamName, given}
import uk.gov.hmrc.cataloguefrontend.service.DependenciesService
import uk.gov.hmrc.cataloguefrontend.util.Parser
import uk.gov.hmrc.cataloguefrontend.view.html.{SbtVersionPage, SbtAcrossEnvironmentsPage}
import uk.gov.hmrc.internalauth.client.FrontendAuthComponents
import uk.gov.hmrc.play.bootstrap.frontend.controller.FrontendController
Expand All @@ -46,18 +47,18 @@ class SbtVersionController @Inject()(
BasicAuthAction.async { implicit request =>
for
teams <- teamsAndRepositoriesConnector.allTeams()
selectedFlag = SlugInfoFlag.parse(flag.toLowerCase).getOrElse(SlugInfoFlag.Latest)
selectedFlag = Parser[SlugInfoFlag].parse(flag.toLowerCase).getOrElse(SlugInfoFlag.Latest)
selectedTeam = teamName.flatMap(n => teams.find(_.name == n))
sbtVersions <- dependenciesService.getSbtVersions(selectedFlag, selectedTeam.map(_.name))
yield Ok(sbtVersionPage(sbtVersions.sortBy(s => (s.version, s.serviceName)), SlugInfoFlag.values, teams, selectedFlag, selectedTeam))
yield Ok(sbtVersionPage(sbtVersions.sortBy(s => (s.version, s.serviceName)), SlugInfoFlag.values.toSeq, teams, selectedFlag, selectedTeam))
}

def compareAllEnvironments(teamName: Option[TeamName]) =
BasicAuthAction.async { implicit request =>
for
teams <- teamsAndRepositoriesConnector.allTeams()
selectedTeam = teamName.flatMap(n => teams.find(_.name == n))
envs <- SlugInfoFlag.values.traverse(env => dependenciesService.getSbtCountsForEnv(env, selectedTeam.map(_.name)))
envs <- SlugInfoFlag.values.toSeq.traverse(env => dependenciesService.getSbtCountsForEnv(env, selectedTeam.map(_.name)))
sbts = envs.flatMap(_.usage.keys).distinct.sorted
yield Ok(sbtAcrossEnvironmentsPage(envs, sbts, teams, selectedTeam))
}
Expand Down
7 changes: 3 additions & 4 deletions app/uk/gov/hmrc/cataloguefrontend/SearchByUrlController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@
package uk.gov.hmrc.cataloguefrontend

import javax.inject.{Inject, Singleton}
import play.api.data.Form
import play.api.data.Forms.{mapping, optional, text}
import play.api.data.{Form, Forms}
import play.api.mvc.{Action, AnyContent, MessagesControllerComponents}
import uk.gov.hmrc.cataloguefrontend.auth.CatalogueAuthBuilders
import uk.gov.hmrc.cataloguefrontend.service.SearchByUrlService
Expand Down Expand Up @@ -65,8 +64,8 @@ class SearchByUrlController @Inject() (

object UrlSearchFilter:
lazy val form = Form(
mapping(
"name" -> optional(text).transform[Option[String]](x => if (x.exists(_.trim.isEmpty)) None else x, identity)
Forms.mapping(
"name" -> Forms.optional(Forms.text).transform[Option[String]](x => if x.exists(_.trim.isEmpty) then None else x, identity)
)(UrlSearchFilter.apply)(f => Some(f.name))
)

Expand Down
28 changes: 16 additions & 12 deletions app/uk/gov/hmrc/cataloguefrontend/binders/Binders.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@

package uk.gov.hmrc.cataloguefrontend.binders

import cats.implicits._
import play.api.data.FormError
import play.api.data.format.Formatter
import play.api.mvc.{PathBindable, QueryStringBindable}
import uk.gov.hmrc.cataloguefrontend.connector.ServiceType

import java.time.{Instant, LocalDate}
import scala.util.Try
Expand All @@ -36,15 +38,6 @@ object Binders:
_.toString
)

implicit val serviceTypeQueryStringBindable: QueryStringBindable[ServiceType] =
queryStringBindableFromString[ServiceType](
{
case s if s.nonEmpty => Some(ServiceType.parse(s))
case _ => None
},
_.asString
)

/** `summon[QueryStringBindable[String]].transform` doesn't allow us to provide failures.
* This function provides `andThen` semantics
*/
Expand All @@ -62,10 +55,21 @@ object Binders:
* This function provides `andThen` semantics
*/
def pathBindableFromString[T](parse: String => Either[String, T], asString: T => String)(using strBinder: PathBindable[String]): PathBindable[T] =
new PathBindable[T] {
new PathBindable[T]:
override def bind(key: String, value: String): Either[String, T] =
parse(value)

override def unbind(key: String, value: T): String =
asString(value)
}

def formFormatFromString[T](parse: String => Either[String, T], asString: T => String): Formatter[T] =
new Formatter[T]:
override def bind(key: String, data: Map[String, String]): Either[Seq[FormError], T] =
data
.get(key)
.map(_.trim) match
case Some(s) if s.nonEmpty => parse(s).leftMap(err => Seq(FormError(key, err)))
case _ => Left(Seq(FormError(key, s"$key is missing")))

override def unbind(key: String, value: T): Map[String, String] =
Map(key -> asString(value))
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,14 @@ import play.api.Logging
import play.api.libs.functional.syntax._
import play.api.libs.json._
import play.api.libs.ws.writeableOf_JsValue
import play.api.mvc.PathBindable
import uk.gov.hmrc.cataloguefrontend.ChangePrototypePassword.PrototypePassword
import uk.gov.hmrc.cataloguefrontend.config.BuildDeployApiConfig
import uk.gov.hmrc.cataloguefrontend.connector.BuildDeployApiConnector._
import uk.gov.hmrc.cataloguefrontend.createappconfigs.CreateAppConfigsForm
import uk.gov.hmrc.cataloguefrontend.createrepository.{CreatePrototypeRepoForm, CreateServiceRepoForm}
import uk.gov.hmrc.cataloguefrontend.model.{Environment, ServiceName, TeamName}
import uk.gov.hmrc.cataloguefrontend.util.{FromString, FromStringEnum}
import uk.gov.hmrc.cataloguefrontend.util.{FromString, FromStringEnum, Parser}
import uk.gov.hmrc.http.HttpReads.Implicits._
import uk.gov.hmrc.http.client.HttpClientV2
import uk.gov.hmrc.http.{HeaderCarrier, HttpReads, StringContextOps, UpstreamErrorResponse}
Expand Down Expand Up @@ -251,13 +252,19 @@ object BuildDeployApiConnector:

case class AsyncRequestId(request: JsValue)

enum PrototypeStatus(val asString: String, val displayString: String) extends FromString:
import FromStringEnum._

given Parser[PrototypeStatus] = Parser.parser(PrototypeStatus.values)

enum PrototypeStatus(
override val asString: String,
val displayString : String
) extends FromString
derives Ordering, Reads, PathBindable:
case Running extends PrototypeStatus(asString = "running" , displayString = "Running" )
case Stopped extends PrototypeStatus(asString = "stopped" , displayString = "Stopped" )
case Undetermined extends PrototypeStatus(asString = "undetermined", displayString = "Undetermined")

object PrototypeStatus extends FromStringEnum[PrototypeStatus]

case class PrototypeDetails(
url : Option[String],
status: PrototypeStatus
Expand All @@ -266,7 +273,7 @@ object BuildDeployApiConnector:
object PrototypeDetails:
val reads: Reads[PrototypeDetails] =
( (__ \ "prototypeUrl").readNullable[String]
~ (__ \ "status").read[PrototypeStatus](PrototypeStatus.reads)
~ (__ \ "status" ).read[PrototypeStatus]
)(PrototypeDetails.apply)

case class ChangePrototypePasswordRequest(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,15 @@ class ResourceUsageConnector @Inject() (
acc.lastOption match
case Some(previous) =>
Environment
.valuesAsSeq.map: env =>
.values.map: env =>
env -> resourceUsages
.find(_.environment == env).map(_.deploymentSize)
.orElse(previous.values.get(env))
.getOrElse(DeploymentSize.empty)
.toMap
case None =>
Environment
.valuesAsSeq.map: env =>
.values.map: env =>
env -> resourceUsages
.find(_.environment == env).map(_.deploymentSize)
.getOrElse(DeploymentSize.empty)
Expand Down Expand Up @@ -102,7 +102,7 @@ object ResourceUsageConnector:
val format: Format[RawResourceUsage] =
( (__ \ "date" ).format[Instant]
~ (__ \ "serviceName" ).format[ServiceName](ServiceName.format)
~ (__ \ "environment" ).format[Environment](Environment.format)
~ (__ \ "environment" ).format[Environment]
~ (__ \ "slots" ).format[Int]
~ (__ \ "instances" ).format[Int]
)((d, sn, e, s, i) => RawResourceUsage(d, sn, e, DeploymentSize(s, i))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ object RouteRulesConnector:
~ (__ \"isRegex" ).read[Boolean]
)(Route.apply)

( (__ \"environment").read[Environment](Environment.format)
( (__ \"environment").read[Environment]
~ (__ \"routes" ).read[Seq[Route]]
~ Reads.pure(false)
)(EnvironmentRoute.apply)
Expand All @@ -122,7 +122,6 @@ object RouteRulesConnector:

object AdminFrontendRoute:
val reads: Reads[AdminFrontendRoute] =
given Reads[Environment] = Environment.format
( (__ \"service" ).read[ServiceName](ServiceName.format)
~ (__ \"route" ).read[String]
~ (__ \"allow" ).read[Map[Environment, List[String]]]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ class SearchByUrlConnector @Inject() (

private given Reads[FrontendRoutes] =
( (__ \ "service" ).read[ServiceName](ServiceName.format)
~ (__ \ "environment").read[Environment](Environment.format)
~ (__ \ "environment").read[Environment]
~ (__ \ "routes" ).read[Seq[FrontendRoute]]
)(FrontendRoutes.apply)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ object ServiceMetricsConnector:
object NonPerformantQueries:
val reads: Reads[NonPerformantQueries] =
( (__ \ "service" ).read[ServiceName](ServiceName.format)
~ (__ \ "environment").read[Environment](Environment.format)
~ (__ \ "environment").read[Environment]
~ (__ \ "queryTypes" ).read[Seq[String]]
)(NonPerformantQueries.apply)

Expand All @@ -82,6 +82,6 @@ object ServiceMetricsConnector:
~ (__ \ "collection" ).read[String]
~ (__ \ "sizeBytes" ).read[BigDecimal]
~ (__ \ "date" ).read[LocalDate]
~ (__ \ "environment").read[Environment](Environment.format)
~ (__ \ "environment").read[Environment]
~ (__ \ "service" ).readNullable[String]
)(apply)
Loading

0 comments on commit 00caefc

Please sign in to comment.