src/Pure/Tools/ci_api.scala
changeset 63646 74604a9fc4c8
child 63992 3aa9837d05c7
equal deleted inserted replaced
63645:d7e0004d4321 63646:74604a9fc4c8
       
     1 /*  Title:      Pure/Tools/build.scala
       
     2     Author:     Makarius
       
     3 
       
     4 API for Isabelle Jenkins continuous integration services.
       
     5 */
       
     6 
       
     7 package isabelle
       
     8 
       
     9 
       
    10 import java.net.URL
       
    11 
       
    12 import scala.util.matching.Regex
       
    13 
       
    14 
       
    15 object CI_API
       
    16 {
       
    17   /* CI service */
       
    18 
       
    19   def root(): String =
       
    20     Isabelle_System.getenv_strict("ISABELLE_JENKINS_ROOT")
       
    21 
       
    22   def invoke(url: String, args: String*): Any =
       
    23   {
       
    24     val req = url + "/api/json?" + args.mkString("&")
       
    25     val result = Url.read(req)
       
    26     try { JSON.parse(result) }
       
    27     catch { case ERROR(_) => error("Malformed JSON from " + quote(req)) }
       
    28   }
       
    29 
       
    30 
       
    31   /* build jobs */
       
    32 
       
    33   def build_jobs(): List[String] =
       
    34     for {
       
    35       job <- JSON.array(invoke(root()), "jobs")
       
    36       _class <- JSON.string(job, "_class")
       
    37       if _class == "hudson.model.FreeStyleProject"
       
    38       name <- JSON.string(job, "name")
       
    39     } yield name
       
    40 
       
    41   sealed case class Build_Info(
       
    42     job_name: String,
       
    43     timestamp: Long,
       
    44     output: URL,
       
    45     session_logs: List[(String, URL)])
       
    46   {
       
    47     def read_output(): String = Url.read(output)
       
    48     def read_log(full_stats: Boolean, name: String): Build.Log_Info =
       
    49       Build.parse_log(full_stats,
       
    50         session_logs.collectFirst({ case (a, b) if a == name => Url.read_gzip(b) }) getOrElse "")
       
    51   }
       
    52 
       
    53   def build_job_builds(job_name: String): List[Build_Info] =
       
    54   {
       
    55     val Log_Session = new Regex("""^.*/log/([^/]+)\.gz$""")
       
    56 
       
    57     for {
       
    58       build <- JSON.array(
       
    59         invoke(root() + "/job/" + job_name, "tree=builds[number,timestamp,artifacts[*]]"), "builds")
       
    60       number <- JSON.int(build, "number")
       
    61       timestamp <- JSON.long(build, "timestamp")
       
    62     } yield {
       
    63       val job_prefix = root() + "/job/" + job_name + "/" + number
       
    64       val output = Url(job_prefix + "/consoleText")
       
    65       val session_logs =
       
    66         for {
       
    67           artifact <- JSON.array(build, "artifacts")
       
    68           log_path <- JSON.string(artifact, "relativePath")
       
    69           session <- (log_path match { case Log_Session(name) => Some(name) case _ => None })
       
    70         } yield (session -> Url(job_prefix + "/artifact/" + log_path))
       
    71       Build_Info(job_name, timestamp, output, session_logs)
       
    72     }
       
    73   }
       
    74 }