Skip to content

Commit

Permalink
Merge pull request #213 from hmrc/BDOG-2315
Browse files Browse the repository at this point in the history
BDOG-2315: adds test job results to latest build
  • Loading branch information
Tyrpix authored Nov 19, 2024
2 parents ae1e377 + 8f66389 commit 4d4a26c
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,9 @@ class JenkinsConnector @Inject()(
import HttpReads.Implicits._
import JenkinsConnector._

private given Reads[LatestBuild] = LatestBuild.jenkinsReads
private given Reads[Seq[JenkinsObject]] = JenkinsObjects.jenkinsReads
private given Reads[LatestBuild] = LatestBuild.jenkinsReads
private given Reads[LatestBuild.TestJobResults] = LatestBuild.TestJobResults.jenkinsReads
private given Reads[Seq[JenkinsObject]] = JenkinsObjects.jenkinsReads

def triggerBuildJob(baseUrl: String)(using ExecutionContext): Future[String] =
// Prevents Server-Side Request Forgery
Expand Down Expand Up @@ -126,6 +127,20 @@ class JenkinsConnector @Inject()(
.execute[LatestBuild]
.recoverWithLogging(url)

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)

extension [T](future: Future[T])
private def recoverWithLogging(url: URL)(using ExecutionContext): Future[T] =
future.recoverWith:
Expand Down Expand Up @@ -216,11 +231,12 @@ object JenkinsConnector:
(__ \ "jobs").read(Reads.seq[JenkinsObject])

case class LatestBuild(
number : Int,
url : String,
timestamp : Instant,
result : Option[LatestBuild.BuildResult],
description: Option[String]
number : Int,
url : String,
timestamp : Instant,
result : Option[LatestBuild.BuildResult],
description : Option[String],
testJobResults: Option[LatestBuild.TestJobResults] = None
)
object LatestBuild:
enum BuildResult(val asString: String):
Expand All @@ -238,18 +254,36 @@ object JenkinsConnector:
given Format[BuildResult] =
Format.of[String].inmap(parse, _.asString)

case class TestJobResults(
securityAlerts : String,
accessibilityViolations: Option[String]
)

object TestJobResults:
val apiWrites: Writes[TestJobResults] =
( (__ \ "securityAlerts" ).write[String]
~ (__ \ "accessibilityViolations").writeNullable[String]
)(t => Tuple.fromProductTyped(t))

val jenkinsReads: Reads[TestJobResults] =
( (__ \ "securityAlerts" ).read[String]
~ (__ \ "accessibilityViolations").readNullable[String]
)(TestJobResults.apply _)

val apiWrites: Writes[LatestBuild] =
( (__ \ "number" ).write[Int]
~ (__ \ "url" ).write[String]
~ (__ \ "timestamp" ).write[Instant]
~ (__ \ "result" ).writeNullable[BuildResult]
~ (__ \ "description").writeNullable[String]
( (__ \ "number" ).write[Int]
~ (__ \ "url" ).write[String]
~ (__ \ "timestamp" ).write[Instant]
~ (__ \ "result" ).writeNullable[BuildResult]
~ (__ \ "description" ).writeNullable[String]
~ (__ \ "testJobResults").writeNullable[TestJobResults](TestJobResults.apiWrites)
)(a => Tuple.fromProductTyped(a))

val jenkinsReads: Reads[LatestBuild] =
( (__ \ "number" ).read[Int]
~ (__ \ "url" ).read[String]
~ (__ \ "timestamp" ).read[Instant]
~ (__ \ "result" ).readNullable[BuildResult]
~ (__ \ "description").readNullable[String]
( (__ \ "number" ).read[Int]
~ (__ \ "url" ).read[String]
~ (__ \ "timestamp" ).read[Instant]
~ (__ \ "result" ).readNullable[BuildResult]
~ (__ \ "description" ).readNullable[String]
~ (__ \ "testJobResults").readNullable[TestJobResults](TestJobResults.jenkinsReads)
)(apply _)
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,13 @@ object JenkinsController:

val apiJobWrites: Writes[JenkinsJobsPersistence.Job] =
given Writes[JenkinsConnector.LatestBuild] =
( (__ \ "number" ).write[Int]
~ (__ \ "url" ).write[String]
~ (__ \ "timestamp" ).write[Instant]
~ (__ \ "result" ).writeNullable[JenkinsConnector.LatestBuild.BuildResult]
~ (__ \ "description").writeNullable[String]
( (__ \ "number" ).write[Int]
~ (__ \ "url" ).write[String]
~ (__ \ "timestamp" ).write[Instant]
~ (__ \ "result" ).writeNullable[JenkinsConnector.LatestBuild.BuildResult]
~ (__ \ "description" ).writeNullable[String]
~ (__ \ "testJobResults").writeNullable[JenkinsConnector.LatestBuild.TestJobResults]
(JenkinsConnector.LatestBuild.TestJobResults.apiWrites)
)(l => Tuple.fromProductTyped(l))

( (__ \ "repoName" ).write[String]
Expand All @@ -67,5 +69,5 @@ object JenkinsController:
~ (__ \ "jobType" ).write[JenkinsJobsPersistence.JobType](JenkinsJobsPersistence.JobType.format)
~ (__ \ "repoType" ).writeNullable[RepoType](RepoType.format)
~ (__ \ "testType" ).writeNullable[TestType](TestType.format)
~ (__ \ "latestBuild").writeNullable[JenkinsConnector.LatestBuild]
~ (__ \ "latestBuild").writeNullable[JenkinsConnector.LatestBuild](JenkinsConnector.LatestBuild.apiWrites)
)(j => Tuple.fromProductTyped(j))
Original file line number Diff line number Diff line change
Expand Up @@ -102,12 +102,19 @@ object JenkinsJobsPersistence:

object Job:
val mongoFormat: Format[Job] =

given OFormat[JenkinsConnector.LatestBuild.TestJobResults] =
( (__ \ "securityAlerts" ).format[String]
~ (__ \ "accessibilityViolations").formatNullable[String]
)(JenkinsConnector.LatestBuild.TestJobResults.apply, t => Tuple.fromProductTyped(t))

given OFormat[JenkinsConnector.LatestBuild] =
( (__ \ "number" ).format[Int]
~ (__ \ "url" ).format[String]
~ (__ \ "timestamp" ).format(MongoJavatimeFormats.instantFormat)
~ (__ \ "result" ).formatNullable[JenkinsConnector.LatestBuild.BuildResult]
~ (__ \ "description").formatNullable[String]
( (__ \ "number" ).format[Int]
~ (__ \ "url" ).format[String]
~ (__ \ "timestamp" ).format(MongoJavatimeFormats.instantFormat)
~ (__ \ "result" ).formatNullable[JenkinsConnector.LatestBuild.BuildResult]
~ (__ \ "description" ).formatNullable[String]
~ (__ \ "testJobResults").formatNullable[JenkinsConnector.LatestBuild.TestJobResults]
)(JenkinsConnector.LatestBuild.apply, l => Tuple.fromProductTyped(l))

( (__ \ "repoName" ).format[String]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,23 +56,28 @@ class JenkinsReloadService @Inject()(
) :: acc
))
}
updatedJobs <- jobs.foldLeftM[Future, List[JenkinsJobsPersistence.Job]](List.empty): (acc, job) =>
if job.jobType == JenkinsJobsPersistence.JobType.Test then
jenkinsConnector.getTestJobResults(job.jenkinsUrl).map: testJobResults =>
acc :+ job.copy(latestBuild = job.latestBuild.map(_.copy(testJobResults = testJobResults)))
else Future.successful(acc :+ job)
pipelineDetails <- buildDeployApiConnector
.getBuildJobsDetails()
.map(_.map(x => (x.repoName, x.buildJobs.find(_.jobType == BuildDeployApiConnector.JobType.Pipeline))))
.map(_.collect { case (a, Some(b)) => (a, b) })
pipelineJobs <- pipelineDetails.foldLeftM[Future, List[JenkinsJobsPersistence.Job]](List.empty) { case (acc, (repoName, pipelineDatail)) =>
pipelineJobs <- pipelineDetails.foldLeftM[Future, List[JenkinsJobsPersistence.Job]](List.empty) { case (acc, (repoName, pipelineDetail)) =>
jenkinsConnector
.getLatestBuildData(pipelineDatail.jenkinsUrl)
.getLatestBuildData(pipelineDetail.jenkinsUrl)
.map(latestBuild =>
JenkinsJobsPersistence.Job(
repoName = repoName
, jobName = pipelineDatail.jobName
, jobName = pipelineDetail.jobName
, jobType = JenkinsJobsPersistence.JobType.Pipeline
, repoType = None
, testType = None
, jenkinsUrl = pipelineDatail.jenkinsUrl
, jenkinsUrl = pipelineDetail.jenkinsUrl
, latestBuild = latestBuild
) :: acc)
}
_ <- jenkinsJobsPersistence.putAll(jobs ++ pipelineJobs)
_ <- jenkinsJobsPersistence.putAll(updatedJobs ++ pipelineJobs)
yield ()

0 comments on commit 4d4a26c

Please sign in to comment.