diff --git a/app/uk/gov/hmrc/teamsandrepositories/connectors/JenkinsConnector.scala b/app/uk/gov/hmrc/teamsandrepositories/connectors/JenkinsConnector.scala index 0c0960e8..6af468e2 100644 --- a/app/uk/gov/hmrc/teamsandrepositories/connectors/JenkinsConnector.scala +++ b/app/uk/gov/hmrc/teamsandrepositories/connectors/JenkinsConnector.scala @@ -127,29 +127,22 @@ class JenkinsConnector @Inject()( .execute[LatestBuild] .recoverWithLogging(url) - def getBuildTestJobResults(jenkinsUrl: String)(using ExecutionContext): Future[Option[LatestBuild.TestJobResults]] = + def getTestJobResults(jenkinsUrl: String)(using ExecutionContext): Future[Option[LatestBuild.TestJobResults]] = // Prevents Server-Side Request Forgery - assert(jenkinsUrl.startsWith(config.BuildJobs.baseUrl), s"$jenkinsUrl was requested for invalid host") - - given HeaderCarrier = HeaderCarrier() - val url = url"${jenkinsUrl}lastBuild/artifact/test-results.json" - - httpClientV2 - .get(url) - .setHeader("Authorization" -> config.BuildJobs.authorizationHeader) - .execute[Option[LatestBuild.TestJobResults]] - .recoverWithLogging(url) - - def getPerformanceTestJobResults(jenkinsUrl: String)(using ExecutionContext): Future[Option[LatestBuild.TestJobResults]] = - // Prevents Server-Side Request Forgery - assert(jenkinsUrl.startsWith(config.PerformanceJobs.baseUrl), s"$jenkinsUrl was requested for invalid host") + assert( + List(config.BuildJobs.baseUrl, config.PerformanceJobs.baseUrl).exists(jenkinsUrl.startsWith), + s"$jenkinsUrl was requested for invalid host" + ) given HeaderCarrier = HeaderCarrier() - val url = url"${jenkinsUrl}lastBuild/artifact/test-results.json" + + val url = url"${jenkinsUrl}lastBuild/artifact/test-results.json" + val authHeader = if url.toString.startsWith("https://build.tax.service.gov.uk") then config.BuildJobs.authorizationHeader + else config.PerformanceJobs.authorizationHeader httpClientV2 .get(url) - .setHeader("Authorization" -> config.PerformanceJobs.authorizationHeader) + .setHeader("Authorization" -> authHeader) .execute[Option[LatestBuild.TestJobResults]] .recoverWithLogging(url) @@ -267,19 +260,19 @@ object JenkinsConnector: Format.of[String].inmap(parse, _.asString) case class TestJobResults( - securityAlerts : String, - accessibilityViolations: Option[String] + numAccessibilityViolations: Option[Int], + numSecurityAlerts : Option[Int] ) object TestJobResults: val apiWrites: Writes[TestJobResults] = - ( (__ \ "securityAlerts" ).write[String] - ~ (__ \ "accessibilityViolations").writeNullable[String] + ( (__ \ "numAccessibilityViolations").writeNullable[Int] + ~ (__ \ "numSecurityAlerts" ).writeNullable[Int] )(t => Tuple.fromProductTyped(t)) - + val jenkinsReads: Reads[TestJobResults] = - ( (__ \ "securityAlerts" ).read[String] - ~ (__ \ "accessibilityViolations").readNullable[String] + ( (__ \ "accessibilityViolations").readNullable[String].map(_.flatMap(_.toIntOption)) + ~ (__ \ "securityAlerts" ).readNullable[String].map(_.flatMap(_.toIntOption)) )(TestJobResults.apply _) val apiWrites: Writes[LatestBuild] = diff --git a/app/uk/gov/hmrc/teamsandrepositories/persistence/JenkinsJobsPersistence.scala b/app/uk/gov/hmrc/teamsandrepositories/persistence/JenkinsJobsPersistence.scala index 3cbe2bd3..440aea34 100644 --- a/app/uk/gov/hmrc/teamsandrepositories/persistence/JenkinsJobsPersistence.scala +++ b/app/uk/gov/hmrc/teamsandrepositories/persistence/JenkinsJobsPersistence.scala @@ -104,8 +104,8 @@ object JenkinsJobsPersistence: val mongoFormat: Format[Job] = given OFormat[JenkinsConnector.LatestBuild.TestJobResults] = - ( (__ \ "securityAlerts" ).format[String] - ~ (__ \ "accessibilityViolations").formatNullable[String] + ( (__ \ "numAccessibilityViolations").formatNullable[Int] + ~ (__ \ "numSecurityAlerts" ).formatNullable[Int] )(JenkinsConnector.LatestBuild.TestJobResults.apply, t => Tuple.fromProductTyped(t)) given OFormat[JenkinsConnector.LatestBuild] = diff --git a/app/uk/gov/hmrc/teamsandrepositories/services/JenkinsReloadService.scala b/app/uk/gov/hmrc/teamsandrepositories/services/JenkinsReloadService.scala index 2bfa32b0..1b0f189c 100644 --- a/app/uk/gov/hmrc/teamsandrepositories/services/JenkinsReloadService.scala +++ b/app/uk/gov/hmrc/teamsandrepositories/services/JenkinsReloadService.scala @@ -34,19 +34,13 @@ class JenkinsReloadService @Inject()( ): private val RepoNameRegex = """.*hmrc/([^/]+)\.git""".r - - private def getTestJobResults(url: String)(using ExecutionContext): Future[Option[TestJobResults]] = - if url.contains("https://build.tax.service.gov.uk") then jenkinsConnector.getBuildTestJobResults(url) - else jenkinsConnector.getPerformanceTestJobResults(url) - + private def extractTestJobResults(description: String): Option[TestJobResults] = - val securityAlerts = """Security alerts: (\d+)""" .r.findFirstMatchIn(description).map(_.group(1)) - val accessibilityIssues = """Accessibility issues: (\d+)""".r.findFirstMatchIn(description).map(_.group(1)) + val securityAlerts = """Security alerts: (\d+)""" .r.findFirstMatchIn(description).map(_.group(1).toInt) + val accessibilityIssues = """Accessibility issues: (\d+)""".r.findFirstMatchIn(description).map(_.group(1).toInt) - if securityAlerts.isEmpty && accessibilityIssues.isEmpty then - None - else - Some(TestJobResults(securityAlerts.getOrElse(""), accessibilityIssues)) + if securityAlerts.isEmpty && accessibilityIssues.isEmpty then None + else Some(TestJobResults(numAccessibilityViolations = accessibilityIssues, numSecurityAlerts = securityAlerts)) def updateBuildAndPerformanceJobs()(using ExecutionContext): Future[Unit] = for @@ -73,12 +67,12 @@ class JenkinsReloadService @Inject()( updatedJobs <- jobs.foldLeftM[Future, List[JenkinsJobsPersistence.Job]](List.empty): (acc, job) => job.jobType match case JenkinsJobsPersistence.JobType.Test => - // used for old builds that publish test results in the description instead of as json - val extractedResults = job.latestBuild.flatMap(_.description).flatMap(extractTestJobResults) - getTestJobResults(job.jenkinsUrl).map: + jenkinsConnector.getTestJobResults(job.jenkinsUrl).map: case Some(results) => acc :+ job.copy(latestBuild = job.latestBuild.map(_.copy(testJobResults = Some(results)))) - case None => acc :+ job.copy(latestBuild = job.latestBuild.map(_.copy(testJobResults = extractedResults))) - case _ => + case None => // used for old builds that publish test results in the description instead of as json + val extractedResults = job.latestBuild.flatMap(_.description).flatMap(extractTestJobResults) + acc :+ job.copy(latestBuild = job.latestBuild.map(_.copy(testJobResults = extractedResults))) + case _ => Future.successful(acc :+ job) pipelineDetails <- buildDeployApiConnector .getBuildJobsDetails()