diff --git a/app/uk/gov/hmrc/cataloguefrontend/FeatureSwitch.scala b/app/uk/gov/hmrc/cataloguefrontend/FeatureSwitch.scala index 5a93276e9..303f59b98 100644 --- a/app/uk/gov/hmrc/cataloguefrontend/FeatureSwitch.scala +++ b/app/uk/gov/hmrc/cataloguefrontend/FeatureSwitch.scala @@ -32,3 +32,6 @@ object CatalogueFrontendSwitches: def showTestRepoRelationships: FeatureSwitch = FeatureSwitch.forName("show-test-repo-relationships") + + def showNewTeamPage: FeatureSwitch = + FeatureSwitch.forName("show-new-team-page") diff --git a/app/uk/gov/hmrc/cataloguefrontend/bobby/BobbyExplorerController.scala b/app/uk/gov/hmrc/cataloguefrontend/bobby/BobbyExplorerController.scala index 999037f01..3a4bb4f77 100644 --- a/app/uk/gov/hmrc/cataloguefrontend/bobby/BobbyExplorerController.scala +++ b/app/uk/gov/hmrc/cataloguefrontend/bobby/BobbyExplorerController.scala @@ -42,7 +42,13 @@ class BobbyExplorerController @Inject() ( ) extends FrontendController(mcc) with CatalogueAuthBuilders: - def bobbyViolations(team: Option[TeamName], digitalService: Option[DigitalService], flag: Option[String]): Action[AnyContent] = + /** + * @param teamName for reverse routing + * @param digitalService for reverse routing + * @param flag for reverse routing + * @param isActive for reverse routing + */ + def bobbyViolations(teamName: Option[TeamName], digitalService: Option[DigitalService], flag: Option[String], isActive: Option[Boolean]): Action[AnyContent] = BasicAuthAction.async: request => given MessagesRequest[AnyContent] = request ( for @@ -54,11 +60,14 @@ class BobbyExplorerController @Inject() ( , formObject => Right(formObject) )) results <- EitherT.right[Result]: - serviceDeps.bobbyReports(filter.team, filter.digitalService, filter.repoType, filter.flag) + serviceDeps.bobbyReports(filter.teamName, filter.digitalService, filter.repoType, filter.flag) yield Ok(bobbyViolationsPage(form, teams, digitalServices, results = Some(results))) ).merge + /** + * @param selector for reverse routing + */ def list(selector: Option[String]): Action[AnyContent] = BasicAuthAction.async: request => given RequestHeader = request @@ -68,7 +77,7 @@ class BobbyExplorerController @Inject() ( yield Ok(bobbyExplorerPage(rules, counts)) case class BobbyReportFilter( - team : Option[TeamName] = None + teamName : Option[TeamName] = None , digitalService: Option[DigitalService] = None , repoType : Option[RepoType] = None , flag : SlugInfoFlag = SlugInfoFlag.Latest @@ -79,7 +88,7 @@ object BobbyReportFilter: lazy val form: Form[BobbyReportFilter] = Form( Forms.mapping( - "team" -> Forms.optional(Forms.of[TeamName]) + "teamName" -> 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) diff --git a/app/uk/gov/hmrc/cataloguefrontend/bobby/BobbyRulesTrendController.scala b/app/uk/gov/hmrc/cataloguefrontend/bobby/BobbyRulesTrendController.scala index 6ed86ae26..75c746a65 100644 --- a/app/uk/gov/hmrc/cataloguefrontend/bobby/BobbyRulesTrendController.scala +++ b/app/uk/gov/hmrc/cataloguefrontend/bobby/BobbyRulesTrendController.scala @@ -58,6 +58,11 @@ class BobbyRulesTrendController @Inject() ( ) ) + /** + * @param rules for reverse routing + * @param from for reverse routing + * @param to for reverse routing + */ def display( rules: Seq[String], from : LocalDate, diff --git a/app/uk/gov/hmrc/cataloguefrontend/bobby/view/BobbyViolationsPage.scala.html b/app/uk/gov/hmrc/cataloguefrontend/bobby/view/BobbyViolationsPage.scala.html index 4877113c2..6c3aef628 100644 --- a/app/uk/gov/hmrc/cataloguefrontend/bobby/view/BobbyViolationsPage.scala.html +++ b/app/uk/gov/hmrc/cataloguefrontend/bobby/view/BobbyViolationsPage.scala.html @@ -22,9 +22,7 @@ @import uk.gov.hmrc.cataloguefrontend.util.DateHelper._ @import views.html.helper.{FieldConstructor, select} -@this( - teamNamesPartial: partials.TeamNamesPartial -) +@this() @(form : Form[BobbyReportFilter] , teams : Seq[GitHubTeam] @@ -53,7 +51,7 @@

Bobby Violations

@select( field = form("repoType") - , options = RepoType.values.filterNot(_ == RepoType.Prototype).map(ds => ds.asString -> ds.asString) + , options = RepoType.values.filterNot(_ == RepoType.Prototype).map(ds => ds.asString -> ds.asString).toSeq , Symbol("_default") -> "All" , Symbol("_label") -> "Repository Type" , Symbol("_labelClass") -> "form-label" @@ -63,12 +61,12 @@

Bobby Violations

@select( - field = form("team") + field = form("teamName") , options = teams.map(t => t.name.asString -> t.name.asString) , Symbol("_default") -> "All" , Symbol("_label") -> "Team" , Symbol("_labelClass") -> "form-label" - , Symbol("id") -> "select-team" + , Symbol("id") -> "select-team-name" , Symbol("class") -> "form-select" )
@@ -185,7 +183,7 @@

Bobby Violations

} + + @partials.team_leak_detection_banner(leaksFoundForTeam) + @partials.bobby_violations_banner(environment = None , dependencies = masterTeamDependencies.flatMap(_.dependencies.toDependencySeq), pending = false, team = true, teamName = Option(teamName)) + @partials.bobby_violations_banner(environment = Some(Environment.Production), dependencies = masterTeamDependencies.flatMap(_.dependencies.toDependencySeq), pending = false, team = true, teamName = Option(teamName)) + @partials.bobby_violations_banner(environment = None , dependencies = masterTeamDependencies.flatMap(_.dependencies.toDependencySeq), pending = true , team = true, teamName = Option(teamName)) + @partials.bobby_violations_banner(environment = Some(Environment.Production), dependencies = masterTeamDependencies.flatMap(_.dependencies.toDependencySeq), pending = true , team = true, teamName = Option(teamName)) + +
+ +
+ +
+
+
+
Details
+
+
+
+
Description:
+
@umpTeam.description.getOrElse("")
+
+
+
Documentation:
+
+ @umpTeam.documentation.map { docs => + Go to Confluence space + } +
+
+
+
Slack:
+
+
+ @umpTeam.slack.map(addSlackInfo("Team", _)) + @umpTeam.slackNotification.map(addSlackInfo("Notification", _)) + @umpUpdateLink(isMemberBox = false) + +
+
GitHub:
+
+ @gitHubUrl.map { url => + Link to Github @umpTeam.teamName.asString + } +
+
+
+
+
+ +
+
+
+
Team Members
+
+
+ @if(umpTeam.members.isEmpty){ +

+ @teamName.asString has no members. +

+ } else { +
    + @for(teamMember <- umpTeam.members) { +
  • + + @teamMember.displayName + + @if(!teamMember.role.isUser) { + @teamMember.role.displayName + } +
  • + } +
+ } + @umpUpdateLink(isMemberBox = true) +
+
+
+
+ + @if(gitHubUrl.isDefined){ +
+
+
+
+
+
Team Service & Dependency Status
+
+ +
+
+
+
+
+ @showRepositories(repos.getOrElse(RepoType.Service , Seq.empty), "Services" , "service") + @showRepositories(repos.getOrElse(RepoType.Library , Seq.empty), "Libraries" , "library") + @showRepositories(repos.getOrElse(RepoType.Prototype, Seq.empty), "Prototypes" , "prototype") + @showRepositories(repos.getOrElse(RepoType.Test , Seq.empty), "Tests" , "test") + @showRepositories(repos.getOrElse(RepoType.Other , Seq.empty), "Repositories", "repository") +
+ } +
+} + +@addSlackInfo(label: String, slackInfo: SlackInfo) = { + @if(!slackInfo.hasValidUrl) { +
+
@label:
+
+

@slackInfo.url

+

Please change to a URL via UMP

+
+
+ } else if (!slackInfo.hasValidName) { +
+
@label:
+
+ Go to @label.toLowerCase channel +
+
+ } else { +
+
@label:
+
+ #@slackInfo.name +
+
+ } +} + +@umpUpdateLink(isMemberBox: Boolean) = { + +} + +@showRepositories(repos: Seq[GitRepository], headerName: String, typeName: String) = { +
+
+
+
@headerName
+
+
+ @if(repos.isEmpty) { +

+ @Html(viewMessages.noRepoOfTypeForTeam(typeName)) +

+ } else { +
    + @defining(repos.partition(_.isShared)) { case (shared, nonShared) => + @repoListFor(nonShared) + @if(shared.nonEmpty){ +
  • Shared
  • + @repoListFor(shared) + } + } +
+ } +
+
+
+} + +@repoListFor(repos: Seq[GitRepository]) = { + @for(repo <- repos.sortBy(_.name.toLowerCase)) { +
  • +
    + + @repo.name + @if(hasLeaks(repo.name)) {} + @if(repo.isDeprecated){ deprecated } + +
    +
  • + } +} diff --git a/app/uk/gov/hmrc/cataloguefrontend/teams/view/TeamInfoPage.scala.html b/app/uk/gov/hmrc/cataloguefrontend/teams/view/TeamInfoPage.scala.html index 83ec45209..0c05f6412 100644 --- a/app/uk/gov/hmrc/cataloguefrontend/teams/view/TeamInfoPage.scala.html +++ b/app/uk/gov/hmrc/cataloguefrontend/teams/view/TeamInfoPage.scala.html @@ -15,203 +15,185 @@ *@ @import uk.gov.hmrc.cataloguefrontend.{routes => appRoutes} -@import uk.gov.hmrc.cataloguefrontend.connector.{GitRepository, RepoType} -@import uk.gov.hmrc.cataloguefrontend.connector.model.Dependency -@import uk.gov.hmrc.cataloguefrontend.teams.RepoAndDependencies +@import uk.gov.hmrc.cataloguefrontend.connector.{GitRepository, JenkinsJob, RepoType} +@import uk.gov.hmrc.cataloguefrontend.connector.model.{BobbyReport, Dependency} +@import uk.gov.hmrc.cataloguefrontend.teams.{RepoAndDependencies, routes => teamRoutes} @import uk.gov.hmrc.cataloguefrontend.users.{UmpTeam, SlackInfo, routes => userRoutes} @import uk.gov.hmrc.cataloguefrontend.view.ViewMessages +@import uk.gov.hmrc.cataloguefrontend.leakdetection.LeakDetectionRepositorySummary +@import uk.gov.hmrc.cataloguefrontend.platforminitiatives.PlatformInitiative +@import uk.gov.hmrc.cataloguefrontend.prcommenter.PrCommenterComment +@import uk.gov.hmrc.cataloguefrontend.servicecommissioningstatus.CachedServiceCheck +@import uk.gov.hmrc.cataloguefrontend.vulnerabilities.TotalVulnerabilityCount +@import uk.gov.hmrc.cataloguefrontend.whatsrunningwhere.WhatsRunningWhere @this( - viewMessages: ViewMessages +viewMessages: ViewMessages ) -@(teamName : TeamName, - repos : Map[RepoType, Seq[GitRepository]], - umpTeam : UmpTeam, - umpMyTeamsUrl : String, - leaksFoundForTeam : Boolean, - hasLeaks : String => Boolean, - masterTeamDependencies: Seq[RepoAndDependencies], - prodDependencies : Map[String, Seq[Dependency]], - gitHubUrl : Option[String] +@( + teamName : TeamName +, umpMyTeamsUrl : String +, results : ( Option[String] + , Seq[GitRepository] + , UmpTeam + , Option[String] + , Seq[LeakDetectionRepositorySummary] + , Seq[BobbyReport] // Production + , Seq[BobbyReport] // Latest + , Seq[PlatformInitiative] + , Seq[TotalVulnerabilityCount] + , Seq[CachedServiceCheck] + , Seq[WhatsRunningWhere] + , Seq[JenkinsJob] + ) )(implicit - request : RequestHeader + request: RequestHeader ) @standard_layout(teamName.asString, active = "teams") { -

    @teamName.asString

    - - - @partials.team_leak_detection_banner(leaksFoundForTeam) - @partials.bobby_violations_banner(environment = None , dependencies = masterTeamDependencies.flatMap(_.dependencies.toDependencySeq), pending = false, team = true, teamName = Option(teamName)) - @partials.bobby_violations_banner(environment = Some(Environment.Production), dependencies = masterTeamDependencies.flatMap(_.dependencies.toDependencySeq), pending = false, team = true, teamName = Option(teamName)) - @partials.bobby_violations_banner(environment = None , dependencies = masterTeamDependencies.flatMap(_.dependencies.toDependencySeq), pending = true , team = true, teamName = Option(teamName)) - @partials.bobby_violations_banner(environment = Some(Environment.Production), dependencies = masterTeamDependencies.flatMap(_.dependencies.toDependencySeq), pending = true , team = true, teamName = Option(teamName)) - +

    @teamName.asString

    + @defining(results) { case (gitHubUrl, repos, umpTeam, openPrsUrl, leaks, latestBobbyReports, productionBobbyReports, platformInitiatives, vulnerabilities, commissioningChecks, whatsRunningWhere, testJobs) =>
    +
    +
    +
    +
    +
    Details
    +
    +
    +
    +
    Description:
    +
    @umpTeam.description.getOrElse("")
    +
    +
    +
    Documentation:
    +
    + @umpTeam.documentation.map { docs => + Go to Confluence space + } +
    +
    +
    +
    Slack:
    +
    +
    -
    - -
    -
    -
    -
    Details
    -
    -
    -
    -
    Description:
    -
    @umpTeam.description.getOrElse("")
    -
    -
    -
    Documentation:
    -
    - @umpTeam.documentation.map { docs => - Go to Confluence space - } -
    -
    -
    -
    Slack:
    -
    -
    - @umpTeam.slack.map(addSlackInfo("Team", _)) - @umpTeam.slackNotification.map(addSlackInfo("Notification", _)) - @umpUpdateLink(isMemberBox = false) + @umpTeam.slack.map(addSlackInfo("Team", _)) + @umpTeam.slackNotification.map(addSlackInfo("Notification", _)) + @umpUpdateLink(isMemberBox = false) -
    -
    GitHub:
    -
    - @gitHubUrl.map { url => - Link to Github @umpTeam.teamName.asString - } -
    -
    -
    -
    +
    +
    GitHub:
    +
    + @gitHubUrl.map { url => + Link to Github @umpTeam.teamName.asString + } +
    +
    +
    +
    -
    -
    -
    -
    Team Members
    -
    -
    - @if(umpTeam.members.isEmpty){ -

    - @teamName.asString has no members. -

    - } else { -
      - @for(teamMember <- umpTeam.members) { -
    • - - @teamMember.displayName - - @if(!teamMember.role.isUser) { - @teamMember.role.displayName - } -
    • - } -
    +
    + @defining(umpTeam.members.size > 8) { displayGrow => +
    +
    +
    Members
    +
    +
    +
    + @if(umpTeam.members.isEmpty){ +

    @teamName.asString has no members.

    + } else { +
      + @for(teamMember <- umpTeam.members) { +
    • + @teamMember.displayName + @if(!teamMember.role.isUser) { + @teamMember.role.displayName + } +
    • } - @umpUpdateLink(isMemberBox = true) -
    + + }
    +
    + @if(displayGrow) { +
    + +
    + }
    + }
    +
    @if(gitHubUrl.isDefined){
    -
    -
    - @partials.servicesAndDependencies(masterTeamDependencies, teamName) +
    +
    +
    +
    Digital Services
    +
    + @defining(repos.flatMap(_.digitalServiceName).distinct.sorted) { digitalServices => +
    + @if(digitalServices.isEmpty) { +

    @teamName.asString has no Digital Services.

    + } else { +
      + @for(digitalService <- digitalServices) { +
    • @digitalService.asString
    • + } +
    + }
    + }
    +
    +
    + @healthPartial(teamName = Some(teamName), leaks, latestBobbyReports, productionBobbyReports, platformInitiatives, vulnerabilities, commissioningChecks, whatsRunningWhere, testJobs) +
    +
    + @explorePartial(teamName = Some(teamName), openPrsUrl) +
    -
    - @showRepositories(repos.getOrElse(RepoType.Service , Seq.empty), "Services" , "service") - @showRepositories(repos.getOrElse(RepoType.Library , Seq.empty), "Libraries" , "library") - @showRepositories(repos.getOrElse(RepoType.Prototype, Seq.empty), "Prototypes" , "prototype") - @showRepositories(repos.getOrElse(RepoType.Test , Seq.empty), "Tests" , "test") - @showRepositories(repos.getOrElse(RepoType.Other , Seq.empty), "Repositories", "repository") -
    + @repositoriesPartial(repos, viewMessages) }
    + } } @addSlackInfo(label: String, slackInfo: SlackInfo) = { @if(!slackInfo.hasValidUrl) {
    -
    @label:
    -
    -

    @slackInfo.url

    -

    Please change to a URL via UMP

    -
    +
    @label:
    +
    +

    @slackInfo.url

    +

    Please change to a URL via UMP

    +
    } else if (!slackInfo.hasValidName) {
    -
    @label:
    -
    - Go to @label.toLowerCase channel -
    +
    @label:
    +
    + Go to @label.toLowerCase channel +
    } else {
    -
    @label:
    -
    - #@slackInfo.name -
    +
    @label:
    +
    + #@slackInfo.name +
    } } @umpUpdateLink(isMemberBox: Boolean) = { - -} - -@showRepositories(repos: Seq[GitRepository], headerName: String, typeName: String) = { -
    -
    -
    -
    @headerName
    -
    -
    - @if(repos.isEmpty) { -

    - @Html(viewMessages.noRepoOfTypeForTeam(typeName)) -

    - } else { -
      - @defining(repos.partition(_.isShared)) { case (shared, nonShared) => - @repoListFor(nonShared) - @if(shared.nonEmpty){ -
    • Shared
    • - @repoListFor(shared) - } - } -
    - } -
    -
    -
    -} - -@repoListFor(repos: Seq[GitRepository]) = { - @for(repo <- repos.sortBy(_.name.toLowerCase)) { -
  • -
    - - @repo.name - @if(hasLeaks(repo.name)) {} - @if(repo.isDeprecated){ deprecated } - -
    -
  • - } + } diff --git a/app/uk/gov/hmrc/cataloguefrontend/teams/view/explorePartial.scala.html b/app/uk/gov/hmrc/cataloguefrontend/teams/view/explorePartial.scala.html new file mode 100644 index 000000000..647de686d --- /dev/null +++ b/app/uk/gov/hmrc/cataloguefrontend/teams/view/explorePartial.scala.html @@ -0,0 +1,56 @@ +@* + * 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.teams.{routes => teamRoutes} +@import uk.gov.hmrc.cataloguefrontend.leakdetection.{LeakDetectionRepositorySummary, routes => leakDetectionRoutes} +@import uk.gov.hmrc.cataloguefrontend.servicecommissioningstatus.{CachedServiceCheck, routes => serviceCommissioningStatusRoutes} +@import uk.gov.hmrc.cataloguefrontend.platforminitiatives.{PlatformInitiative, routes => platforminitiativesRoutes} +@import uk.gov.hmrc.cataloguefrontend.vulnerabilities.{TotalVulnerabilityCount, routes => vulnerabilityRoutes} +@import uk.gov.hmrc.cataloguefrontend.prcommenter.{PrCommenterComment, routes => prcommenterRoutes} + +@( + teamName : Option[TeamName] +, openPrsUrl: Option[String] +)(implicit + request: RequestHeader +) + +
    +
    +
    Explore
    +
    +
    + +
    +
    diff --git a/app/uk/gov/hmrc/cataloguefrontend/teams/view/healthPartial.scala.html b/app/uk/gov/hmrc/cataloguefrontend/teams/view/healthPartial.scala.html new file mode 100644 index 000000000..6b20b362f --- /dev/null +++ b/app/uk/gov/hmrc/cataloguefrontend/teams/view/healthPartial.scala.html @@ -0,0 +1,182 @@ +@* + * 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.connector.JenkinsJob +@import uk.gov.hmrc.cataloguefrontend.connector.model.BobbyReport +@import uk.gov.hmrc.cataloguefrontend.teams.{routes => teamRoutes} +@import uk.gov.hmrc.cataloguefrontend.bobby.{routes => bobbyRoutes} +@import uk.gov.hmrc.cataloguefrontend.leakdetection.{LeakDetectionRepositorySummary, routes => leakDetectionRoutes} +@import uk.gov.hmrc.cataloguefrontend.platforminitiatives.{PlatformInitiative, routes => platforminitiativesRoutes} +@import uk.gov.hmrc.cataloguefrontend.servicecommissioningstatus.{CachedServiceCheck, routes => serviceCommissioningStatusRoutes} +@import uk.gov.hmrc.cataloguefrontend.test.{routes => testJobRoutes} +@import uk.gov.hmrc.cataloguefrontend.vulnerabilities.{TotalVulnerabilityCount, routes => vulnerabilityRoutes} +@import uk.gov.hmrc.cataloguefrontend.whatsrunningwhere.{WhatsRunningWhere, Profile, ProfileType, routes => whatsRunningWhereRoutes} + +@( + teamName : Option[TeamName] +, leaks : Seq[LeakDetectionRepositorySummary] +, productionBobbyReports: Seq[BobbyReport] +, latestBobbyReports : Seq[BobbyReport] +, platformInitiatives : Seq[PlatformInitiative] +, vulnerabilities : Seq[TotalVulnerabilityCount] +, commissioningChecks : Seq[CachedServiceCheck] +, whatsRunningWhere : Seq[WhatsRunningWhere] +, testJobs : Seq[JenkinsJob] +, now : java.time.LocalDate = java.time.LocalDate.now() +)(implicit + request: RequestHeader +) + +
    +
    +
    Health
    +
    +
    + + + + @defining(leaks.map(_.unresolvedCount).sum) { count => + + } + + + + @defining(productionBobbyReports.flatMap(_.violations.filter(v => !v.exempt && now.isAfter(v.from))).size) { count => + + } + + + + @defining(latestBobbyReports.flatMap(_.violations.filter(v => !v.exempt && now.isAfter(v.from))).size) { count => + + } + + + + @defining(vulnerabilities.map(_.actionRequired).sum) { count => + + } + + + + + + + @defining(-1) { count => + + } + + + + @defining(-1) { count => + + } + + + + + + + @defining(productionBobbyReports.flatMap(_.violations.filter(v => !v.exempt && (now.isBefore(v.from) || now.isEqual(v.from)))).size) { count => + + } + + + + @defining(latestBobbyReports.flatMap(_.violations.filter(v => !v.exempt && (now.isBefore(v.from) || now.isEqual(v.from)))).size) { count => + + } + + + + @defining(platformInitiatives.filter(_.progress.percent < 100).size) { count => + + } + + + + @defining(commissioningChecks.filter(_.warnings).size) { count => + + } + + + + @defining( + whatsRunningWhere.map { wrw => + ( wrw.versions.maxBy(_.version) + , wrw.versions.find(_.environment == Environment.Production) + ) match { + case (v1, Some(v2)) + if v2.version.patch > 0 + || v2.version.major < v1.version.major + || v2.version.minor <= v1.version.minor - 1 + => { 1 } + case _ => { 0 } + } + } + ) { counts => + + } + @* TODO whatsRunningWhere should use standard Catalogue form params and reverse routes *@ + + + + + + + @defining(testJobs.flatMap(_.latestBuild).filter(_.result == Some("FAILURE")).size) { count => + + } + + + + @defining(testJobs.flatMap(_.latestBuild).flatMap(_.testJobResults).flatMap(_.numAccessibilityViolations).sum) { count => + + } + + + + + @defining(testJobs.flatMap(_.latestBuild).flatMap(_.testJobResults).flatMap(_.numSecurityAlerts).sum) { count => + + } + + + + + + + @defining(-1) { count => + + } + + + + @defining(-1) { count => + + } + + + + @defining(-1) { count => + + } + + + +
    @countLeaks
    @countBobby Errors - Production
    @countBobby Errors - Latest
    @count Service Vulnerabilities

    @countShuttered Frontend
    @countShuttered Api

    @countBobby Warnings - Production
    @countBobby Warnings - Latest
    @countPlatform Initiatives
    @countService Commissioning State Warnings
    @counts.sumOutdated or Hotfixed Production Deployments

    @countTest Failures
    @countAccessibility Issues
    @countSecurity Alerts

    @countSlow Running Queries
    @countNon Indexed Queries
    @countContainer Kills
    +
    +
    diff --git a/app/uk/gov/hmrc/cataloguefrontend/teams/view/repositoriesPartial.scala.html b/app/uk/gov/hmrc/cataloguefrontend/teams/view/repositoriesPartial.scala.html new file mode 100644 index 000000000..c548c1f3b --- /dev/null +++ b/app/uk/gov/hmrc/cataloguefrontend/teams/view/repositoriesPartial.scala.html @@ -0,0 +1,75 @@ +@* + * 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.connector.{GitRepository, RepoType} +@import uk.gov.hmrc.cataloguefrontend.view.ViewMessages + +@( + repos : Seq[GitRepository] +, viewMessages: ViewMessages +)(implicit + request: RequestHeader +) + +
    + @defining(repos.groupBy(_.repoType)) { repoMap => + @showRepositories(repoMap, RepoType.Service , "Services" ) + @showRepositories(repoMap, RepoType.Library , "Libraries" ) + @showRepositories(repoMap, RepoType.Prototype, "Prototypes" ) + @showRepositories(repoMap, RepoType.Test , "Tests" ) + @showRepositories(repoMap, RepoType.Other , "Repositories") + } +
    + +@showRepositories(repoMap: Map[RepoType, Seq[GitRepository]], repoType: RepoType, headerName: String) = { +
    +
    +
    +
    @headerName
    +
    +
    + @if(repoMap.get(repoType).isEmpty) { +

    @Html(viewMessages.noRepoOfTypeForTeam(repoType.asString))

    + } else { +
      + @defining(repoMap(repoType).partition(_.isShared)) { case (shared, nonShared) => + @repoListFor(nonShared) + @if(shared.nonEmpty){ +
    • Shared
    • + @repoListFor(shared) + } + } +
    + } +
    +
    +
    +} + +@repoListFor(filteredRepos: Seq[GitRepository]) = { + @for(repo <- filteredRepos.sortBy(_.name.toLowerCase)) { +
  • +
    + + @repo.name + @if(repo.isDeprecated){ deprecated } + +
    +
  • + } +} diff --git a/app/uk/gov/hmrc/cataloguefrontend/view/partials/servicesAndDependencies.scala.html b/app/uk/gov/hmrc/cataloguefrontend/view/partials/servicesAndDependencies.scala.html deleted file mode 100644 index ba1c0e7c8..000000000 --- a/app/uk/gov/hmrc/cataloguefrontend/view/partials/servicesAndDependencies.scala.html +++ /dev/null @@ -1,36 +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. - *@ - -@import uk.gov.hmrc.cataloguefrontend.servicecommissioningstatus.{routes => serviceCommissioningStatusRoutes} -@import uk.gov.hmrc.cataloguefrontend.teams.{RepoAndDependencies, routes => teamRoutes} -@import uk.gov.hmrc.cataloguefrontend.vulnerabilities.{routes => vulnerabilityRoutes} - -@(masterTeamDependencies: Seq[RepoAndDependencies], - teamName : TeamName -) - -
    -
    -
    Team Service & Dependency Status
    -
    -
    - -
    -
    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 9c8ec69fb..081f83218 100644 --- a/app/uk/gov/hmrc/cataloguefrontend/view/standard_layout.scala.html +++ b/app/uk/gov/hmrc/cataloguefrontend/view/standard_layout.scala.html @@ -166,7 +166,7 @@
  • Bobby Explorer
  • Leak Detection - Rules
  • -
  • Leak Detection - Repositories
  • +
  • Leak Detection - Repositories
  • Vulnerabilities
  • Vulnerabilities - Services
  • diff --git a/app/uk/gov/hmrc/cataloguefrontend/vulnerabilities/VulnerabilitiesController.scala b/app/uk/gov/hmrc/cataloguefrontend/vulnerabilities/VulnerabilitiesController.scala index 17f7a4996..af404d66d 100644 --- a/app/uk/gov/hmrc/cataloguefrontend/vulnerabilities/VulnerabilitiesController.scala +++ b/app/uk/gov/hmrc/cataloguefrontend/vulnerabilities/VulnerabilitiesController.scala @@ -44,6 +44,13 @@ class VulnerabilitiesController @Inject() ( ) extends FrontendController(mcc) with CatalogueAuthBuilders: + /** + * @param vulnerability for reverse routing + * @param curationStatus for reverse routing + * @param service for reverse routing + * @param team for reverse routing + * @param flag for reverse routing + */ def vulnerabilitiesList( vulnerability : Option[String], curationStatus: Option[String], @@ -90,6 +97,14 @@ class VulnerabilitiesController @Inject() ( ) } + /** + * @param service for reverse routing + * @param team for reverse routing + * @param vulnerability for reverse routing + * @param curationStatus for reverse routing + * @param from for reverse routing + * @param from for reverse routing + */ def vulnerabilitiesTimeline( service : Option[ServiceName], team : Option[TeamName], diff --git a/conf/app.routes b/conf/app.routes index e3f0cb013..8bb09af80 100644 --- a/conf/app.routes +++ b/conf/app.routes @@ -40,7 +40,7 @@ GET /service/:name/costs uk.gov.hmrc.cataloguefro GET /service/:name/commissioning-state uk.gov.hmrc.cataloguefrontend.servicecommissioningstatus.ServiceCommissioningStatusController.getCommissioningState(name: ServiceName) GET /commissioning-state/search uk.gov.hmrc.cataloguefrontend.servicecommissioningstatus.ServiceCommissioningStatusController.searchLanding() -GET /commissioning-state/search/results uk.gov.hmrc.cataloguefrontend.servicecommissioningstatus.ServiceCommissioningStatusController.searchResults(team: Option[TeamName] ?= None) +GET /commissioning-state/search/results uk.gov.hmrc.cataloguefrontend.servicecommissioningstatus.ServiceCommissioningStatusController.searchResults(team: Option[TeamName] ?= None, warningFilter: Option[Boolean] ?= None) GET /library/:name uk.gov.hmrc.cataloguefrontend.CatalogueController.library(name) @@ -81,7 +81,7 @@ 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 /bobby-violations uk.gov.hmrc.cataloguefrontend.bobby.BobbyExplorerController.bobbyViolations(teamName: Option[TeamName] ?= None, digitalService: Option[DigitalService] ?= None, flag: Option[String] ?= None) +GET /bobby-violations uk.gov.hmrc.cataloguefrontend.bobby.BobbyExplorerController.bobbyViolations(teamName: Option[TeamName] ?= None, digitalService: Option[DigitalService] ?= None, flag: Option[String] ?= None, isActive: Option[Boolean] ?= 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()) @@ -116,7 +116,7 @@ GET /platform-initiatives uk.gov.hmrc.cataloguefro GET /leak-detection uk.gov.hmrc.cataloguefrontend.leakdetection.LeakDetectionController.ruleSummaries GET /leak-detection/drafts uk.gov.hmrc.cataloguefrontend.leakdetection.LeakDetectionController.draftReports -GET /leak-detection/repositories uk.gov.hmrc.cataloguefrontend.leakdetection.LeakDetectionController.repoSummaries(includeWarnings: Boolean ?= false, includeExemptions: Boolean ?= false, includeViolations: Boolean ?= false, includeNonIssues: Boolean ?= false) +GET /leak-detection/repositories uk.gov.hmrc.cataloguefrontend.leakdetection.LeakDetectionController.repoSummaries(team: Option[TeamName] ?= None, includeWarnings: Boolean ?= false, includeExemptions: Boolean ?= false, includeViolations: Boolean ?= false, includeNonIssues: Boolean ?= false) GET /leak-detection/repositories/:repository uk.gov.hmrc.cataloguefrontend.leakdetection.LeakDetectionController.branchSummaries(repository: String, includeNonIssues: Boolean ?= false) GET /leak-detection/repositories/:repository/:branch uk.gov.hmrc.cataloguefrontend.leakdetection.LeakDetectionController.report(repository: String, branch: String) POST /leak-detection/repositories/:repository/:branch uk.gov.hmrc.cataloguefrontend.leakdetection.LeakDetectionController.rescan(repository: String, branch: String) @@ -141,4 +141,4 @@ GET /users/edit-user/access uk.gov.hmrc.cataloguefr POST /users/edit-user/access uk.gov.hmrc.cataloguefrontend.users.EditUserController.editUserAccess(username: UserName, organisation: Option[String] ?= None) GET /users/edit-user/access/2 uk.gov.hmrc.cataloguefrontend.users.EditUserController.requestSent(username: UserName) -GET /tests uk.gov.hmrc.cataloguefrontend.test.TestJobController.allTests(teamName: Option[TeamName], digitalService: Option[DigitalService]) +GET /tests uk.gov.hmrc.cataloguefrontend.test.TestJobController.allTests(teamName: Option[TeamName] ?= None, digitalService: Option[DigitalService] ?= None) diff --git a/conf/application.conf b/conf/application.conf index 99dcd9a40..814199ea2 100644 --- a/conf/application.conf +++ b/conf/application.conf @@ -255,7 +255,3 @@ bootstrap.auditfilter.maskedFormFields = [ "password" ] # B&D api for create app configs does not support externaltest environmentsToHideByDefault = ["integration", "development", "externaltest"] - -feature { - show-decommission-button = false -} diff --git a/test/uk/gov/hmrc/cataloguefrontend/cost/CostControllerSpec.scala b/test/uk/gov/hmrc/cataloguefrontend/cost/CostControllerSpec.scala index 542af8423..cdb45565c 100644 --- a/test/uk/gov/hmrc/cataloguefrontend/cost/CostControllerSpec.scala +++ b/test/uk/gov/hmrc/cataloguefrontend/cost/CostControllerSpec.scala @@ -57,7 +57,7 @@ class CostControllerSpec when(mockAuthStubBehaviour.stubAuth(None, Retrieval.EmptyRetrieval)) .thenReturn(Future.unit) - when(mockTeamsAndRepositoriesConnector.allTeams()(using any[HeaderCarrier])) + when(mockTeamsAndRepositoriesConnector.allTeams(any)(using any[HeaderCarrier])) .thenReturn(Future.successful(Seq.empty)) when(mockServiceConfigConnector.deploymentConfig(any, any, any, any)(using any[HeaderCarrier])) diff --git a/test/uk/gov/hmrc/cataloguefrontend/createrepository/CreateRepositoryControllerSpec.scala b/test/uk/gov/hmrc/cataloguefrontend/createrepository/CreateRepositoryControllerSpec.scala index 769b201b4..95bc85873 100644 --- a/test/uk/gov/hmrc/cataloguefrontend/createrepository/CreateRepositoryControllerSpec.scala +++ b/test/uk/gov/hmrc/cataloguefrontend/createrepository/CreateRepositoryControllerSpec.scala @@ -128,7 +128,7 @@ class CreateRepositoryControllerSpec when(mockCacheRepo.deleteFromSession[RepoTypeOut](any())(any())) .thenReturn(Future.successful(())) - when(mockTeamsAndReposConnector.allTeams()(using any[HeaderCarrier])) + when(mockTeamsAndReposConnector.allTeams(any())(using any[HeaderCarrier])) .thenReturn(Future.successful(Seq(GitHubTeam(TeamName("TestTeam"), None, Seq.empty)))) val fakeRequest: FakeRequest[AnyContent] = @@ -154,7 +154,7 @@ class CreateRepositoryControllerSpec when(mockCacheRepo.deleteFromSession[RepoTypeOut](any())(any())) .thenReturn(Future.successful(())) - when(mockTeamsAndReposConnector.allTeams()(using any[HeaderCarrier])) + when(mockTeamsAndReposConnector.allTeams(any())(using any[HeaderCarrier])) .thenReturn(Future.successful(Seq(GitHubTeam(TeamName("TestTeam"), None, Seq.empty)))) when(mockBuildDeployApiConnector.createTestRepository(any())(using any[HeaderCarrier])) @@ -175,16 +175,16 @@ class CreateRepositoryControllerSpec val mockBuildDeployApiConnector: BuildDeployApiConnector = mock[BuildDeployApiConnector] - + val mockTeamsAndReposConnector: TeamsAndRepositoriesConnector = mock[TeamsAndRepositoriesConnector] - + val mockCacheRepo: SessionCacheRepository = mock[SessionCacheRepository] - + val authStubBehaviour: StubBehaviour = mock[StubBehaviour] - + val authComponent: FrontendAuthComponents = FrontendAuthComponentsStub(authStubBehaviour) diff --git a/test/uk/gov/hmrc/cataloguefrontend/deployments/DeploymentEventsControllerSpec.scala b/test/uk/gov/hmrc/cataloguefrontend/deployments/DeploymentEventsControllerSpec.scala index 6802e4604..c96ce9554 100644 --- a/test/uk/gov/hmrc/cataloguefrontend/deployments/DeploymentEventsControllerSpec.scala +++ b/test/uk/gov/hmrc/cataloguefrontend/deployments/DeploymentEventsControllerSpec.scala @@ -74,7 +74,7 @@ class DeploymentEventsControllerSpec .thenReturn(Future.unit) when(mockedReleasesConnector.deploymentHistory(environment = any, from = any, to = any, team = any, service = any, skip = any, limit = any)(using any[HeaderCarrier])) .thenReturn(Future.successful(PaginatedDeploymentHistory(history = Seq.empty, 0))) - when(mockedTeamsAndRepositoriesConnector.allTeams()(using any[HeaderCarrier])) + when(mockedTeamsAndRepositoriesConnector.allTeams(any)(using any[HeaderCarrier])) .thenReturn(Future.successful(Seq.empty)) val response = controller.deploymentEvents()(FakeRequest(GET, "/deployments/production").withSession(SessionKeys.authToken -> "Token token")) status(response) shouldBe 200 @@ -100,7 +100,7 @@ class DeploymentEventsControllerSpec .thenReturn(Future.unit) when(mockedReleasesConnector.deploymentHistory(environment = any, from = any, to = any, team = any, service = any, skip = any, limit = any)(using any[HeaderCarrier])) .thenReturn(Future.successful(PaginatedDeploymentHistory(deps, deps.length))) - when(mockedTeamsAndRepositoriesConnector.allTeams()(using any[HeaderCarrier])) + when(mockedTeamsAndRepositoriesConnector.allTeams(any)(using any[HeaderCarrier])) .thenReturn(Future.successful(Seq.empty)) val response = controller.deploymentEvents()(FakeRequest(GET, "/deployments/production?from=2020-01-01&to=2020-02-01").withSession(SessionKeys.authToken -> "Token token")) @@ -134,7 +134,7 @@ class DeploymentEventsControllerSpec using any[HeaderCarrier])) .thenReturn(Future.successful(PaginatedDeploymentHistory(deps, deps.length))) - when(mockedTeamsAndRepositoriesConnector.allTeams()(using any[HeaderCarrier])) + when(mockedTeamsAndRepositoriesConnector.allTeams(any)(using any[HeaderCarrier])) .thenReturn(Future.successful(Seq.empty)) val response = controller.deploymentEvents()(FakeRequest(GET, "/deployments/production?service=s1").withSession(SessionKeys.authToken -> "Token token")) @@ -160,7 +160,7 @@ class DeploymentEventsControllerSpec when(authStubBehaviour.stubAuth(None, Retrieval.EmptyRetrieval)) .thenReturn(Future.unit) - when(mockedTeamsAndRepositoriesConnector.allTeams()(using any[HeaderCarrier])) + when(mockedTeamsAndRepositoriesConnector.allTeams(any)(using any[HeaderCarrier])) .thenReturn(Future.successful(Seq.empty)) val response = controller.deploymentEvents()(FakeRequest(GET, "/deployments/production?page=2").withSession(SessionKeys.authToken -> "Token token")) diff --git a/test/uk/gov/hmrc/cataloguefrontend/platforminitiatives/PlatformInitiativesControllerSpec.scala b/test/uk/gov/hmrc/cataloguefrontend/platforminitiatives/PlatformInitiativesControllerSpec.scala index b0fff1710..303d91802 100644 --- a/test/uk/gov/hmrc/cataloguefrontend/platforminitiatives/PlatformInitiativesControllerSpec.scala +++ b/test/uk/gov/hmrc/cataloguefrontend/platforminitiatives/PlatformInitiativesControllerSpec.scala @@ -83,7 +83,7 @@ class PlatformInitiativesControllerSpec when(authStubBehaviour.stubAuth(None, Retrieval.EmptyRetrieval)) .thenReturn(Future.unit) - when(mockTRConnector.allTeams()(using any[HeaderCarrier])) + when(mockTRConnector.allTeams(any)(using any[HeaderCarrier])) .thenReturn(Future.successful(Seq())) when(mockPIConnector.getInitiatives(any[Option[TeamName]])(using any[HeaderCarrier])) diff --git a/test/uk/gov/hmrc/cataloguefrontend/teams/TeamServicesSpec.scala b/test/uk/gov/hmrc/cataloguefrontend/teams/TeamsControllerSpec.scala similarity index 98% rename from test/uk/gov/hmrc/cataloguefrontend/teams/TeamServicesSpec.scala rename to test/uk/gov/hmrc/cataloguefrontend/teams/TeamsControllerSpec.scala index 4fe83f2c8..348130ba9 100644 --- a/test/uk/gov/hmrc/cataloguefrontend/teams/TeamServicesSpec.scala +++ b/test/uk/gov/hmrc/cataloguefrontend/teams/TeamsControllerSpec.scala @@ -28,7 +28,7 @@ import uk.gov.hmrc.cataloguefrontend.view.ViewMessages import scala.io.Source import scala.jdk.CollectionConverters._ -class TeamServicesSpec extends UnitSpec with BeforeAndAfter with FakeApplicationBuilder { +class TeamsControllerSpec extends UnitSpec with BeforeAndAfter with FakeApplicationBuilder { def asDocument(html: String): Document = Jsoup.parse(html)