Various CI fixes

* Output CSV on build stage
* Check more failure states in pipeline
* Allow configs.py to use multiple groups
* Add build log as artifact
* Add links to particular build configs
* Host CMSIS_5 pack file internally
* Adding mbedcrypto url as a param
* Move the LAVA job generation into a new jenkins job
* Make job_ids strings for adding to job description

Change-Id: I801a1a5d15a7f55e25477ad371e8ec59eb14fd7f
Signed-off-by: Dean Birch <dean.birch@arm.com>
diff --git a/jenkins/build-config.jpl b/jenkins/build-config.jpl
index d258dbd..aea0266 100644
--- a/jenkins/build-config.jpl
+++ b/jenkins/build-config.jpl
@@ -34,21 +34,23 @@
           branches: [[name: 'FETCH_HEAD']], 
           userRemoteConfigs: [[
             refspec: 'refs/tags/$MBEDCRYPTO_VERSION',
-            url: 'https://github.com/ARMmbed/mbed-crypto.git'
+            url: params.MBEDCRYPTO_URL
           ]]
         ]
       )
     }
     sh """
-wget -O cmsis.pack -q https://github.com/ARM-software/CMSIS_5/releases/download/${CMSIS_VERSION}/ARM.CMSIS.${CMSIS_VERSION}.pack
+# Host https://github.com/Arm-software/CMSIS_5/releases/download/5.5.0/ARM.CMSIS.5.5.0.pack
+# under \$JENKINS_HOME/userContent
+wget -O cmsis.pack -q \${JENKINS_URL}/userContent/ARM.CMSIS.${CMSIS_VERSION}.pack
 unzip -o -d CMSIS_5 cmsis.pack
 """
   }
   stage("Build") {
-    sh "tf-m-ci-scripts/run-build.sh"
+    sh "tf-m-ci-scripts/run-build.sh 2>&1 | tee build.log"
   }
   stage("Post") {
-    archiveArtifacts 'trusted-firmware-m/build/install/**'
+    archiveArtifacts 'trusted-firmware-m/build/install/**,build.log'
     cleanWs()
   }
 }
diff --git a/jenkins/build-docs.jpl b/jenkins/build-docs.jpl
index 8c967fd..ba5e1e1 100644
--- a/jenkins/build-docs.jpl
+++ b/jenkins/build-docs.jpl
@@ -34,13 +34,15 @@
           branches: [[name: 'FETCH_HEAD']], 
           userRemoteConfigs: [[
             refspec: 'refs/tags/$MBEDCRYPTO_VERSION',
-            url: 'https://github.com/ARMmbed/mbed-crypto.git'
+            url: params.MBEDCRYPTO_URL
           ]]
         ]
       )
     }
     sh """
-wget -O cmsis.pack -q https://github.com/ARM-software/CMSIS_5/releases/download/${CMSIS_VERSION}/ARM.CMSIS.${CMSIS_VERSION}.pack
+# Host https://github.com/Arm-software/CMSIS_5/releases/download/5.5.0/ARM.CMSIS.5.5.0.pack
+# under \$JENKINS_HOME/userContent
+wget -O cmsis.pack -q \${JENKINS_URL}/userContent/ARM.CMSIS.${CMSIS_VERSION}.pack
 unzip -o -d CMSIS_5 cmsis.pack
 """
   }
diff --git a/jenkins/checkpatch.jpl b/jenkins/checkpatch.jpl
index f43ef58..5a447b5 100644
--- a/jenkins/checkpatch.jpl
+++ b/jenkins/checkpatch.jpl
@@ -51,13 +51,15 @@
           branches: [[name: 'FETCH_HEAD']], 
           userRemoteConfigs: [[
             refspec: 'refs/tags/$MBEDCRYPTO_VERSION',
-            url: 'https://github.com/ARMmbed/mbed-crypto.git'
+            url: params.MBEDCRYPTO_URL
           ]]
         ]
       )
     }
     sh """
-wget -O cmsis.pack -q https://github.com/ARM-software/CMSIS_5/releases/download/${CMSIS_VERSION}/ARM.CMSIS.${CMSIS_VERSION}.pack
+# Host https://github.com/Arm-software/CMSIS_5/releases/download/5.5.0/ARM.CMSIS.5.5.0.pack
+# under \$JENKINS_HOME/userContent
+wget -O cmsis.pack -q \${JENKINS_URL}/userContent/ARM.CMSIS.${CMSIS_VERSION}.pack
 unzip -o -d CMSIS_5 cmsis.pack
 """
   }
diff --git a/jenkins/ci.jpl b/jenkins/ci.jpl
index 9f52c62..743d6c5 100644
--- a/jenkins/ci.jpl
+++ b/jenkins/ci.jpl
@@ -6,6 +6,8 @@
 //
 //-------------------------------------------------------------------------------
 
+library identifier: 'local-lib@master', retriever: legacySCM(scm)
+
 def listConfigs(ci_scripts_dir, config_list, filter_group) {
   dir(ci_scripts_dir) {
     echo "Obtaining list of configs."
@@ -39,11 +41,22 @@
   params += string(name: 'CMSIS_VERSION', value: env.CMSIS_VERSION)
   params += string(name: 'MBEDCRYPTO_VERSION', value: env.MBEDCRYPTO_VERSION)
   params += string(name: 'CODE_REPO', value: env.CODE_REPO)
-  return {
-    def res = build(job: 'tf-m-build-config', parameters: params, propagate: false)
-    print("${res.number}: ${config} ${res.result} ${res.getAbsoluteUrl()}")
-    if (res.result == "FAILURE") {
-      error("Build failed at ${res.getAbsoluteUrl()}")
+  return { -> results
+    def build_res = build(job: 'tf-m-build-config', parameters: params, propagate: false)
+    def build_info = [build_res, config, params_collection]
+    results['builds'][build_res.number] = build_info
+    def build_url = build_res.getAbsoluteUrl()
+    print("${build_res.number}: ${config} ${build_res.result} ${build_url}")
+    failure_states = ["FAILURE", "ABORTED", "UNSTABLE", "NOT_BUILT"]
+    if (build_res.result in failure_states) {
+      error("Build failed at ${build_url}")
+    }
+    else {
+      print("Doing LAVA stuff for ${build_url}")
+      params += string(name: 'BUILD_NUMBER', value: "${build_res.number}")
+      params += string(name: 'BUILD_URL', value: build_url)
+      def lava_res = build(job: 'tf-m-lava-submit', parameters: params, propagate: false)
+      results['lava_jobs'] += lava_res.getDescription()
     }
   }
 }
@@ -58,12 +71,29 @@
   return {
     def res = build(job: 'tf-m-build-docs', parameters: params, propagate:false)
     print("${res.number}: Docs ${res.result} ${res.getAbsoluteUrl()}")
-    if (res.result == "FAILURE") {
+    if (res.result in ["FAILURE", "ABORTED", "UNSTABLE", "NOT_BUILT"]) {
       error("Build failed at ${res.getAbsoluteUrl()}")
     }
   }
 }
 
+
+def buildCsv(results) {
+  def csvContent = summary.getBuildCsv(results)
+  node("master") {
+    writeCSV file: 'build_results.csv', records: csvContent, format: CSVFormat.EXCEL
+    archiveArtifacts 'build_results.csv'
+  }
+}
+
+def writeSummary(results) {
+  def buildLinks = summary.getLinks(results)
+  node("master") {
+    writeFile file: "build_links.html", text: buildLinks
+    archiveArtifacts 'build_links.html'
+  }
+}
+
 def verifyStatus(value, stage_name) {
   node("docker-amd64-xenial") {
     cleanWs()
@@ -100,6 +130,8 @@
   stage("Configs") {
     // Populate configs
     listConfigs('tf-m-ci-scripts', configs, env.FILTER_GROUP)
+    results['builds'] = [:]
+    results['lava_jobs'] = []
     for (config in configs) {
       builds[config] = buildConfig("tf-m-ci-scripts", config, env.FILTER_GROUP)
     }
@@ -111,10 +143,26 @@
   try {
     parallel(builds)
   } catch (Exception e) {
+    print(e)
     manager.buildFailure()
     verify = -1
   } finally {
+    print("Verifying status")
     verifyStatus(verify, 'build')
+    print("Building CSV")
+    buildCsv(results['builds'])
+    writeSummary(results['builds'])
   }
 }
-// TODO Test phase
+node("docker-amd64-xenial") {
+  stage("Tests") {
+    dir("tf-m-ci-scripts") {
+      git url: '$CI_SCRIPTS_REPO', branch: 'master', credentialsId: 'GIT_SSH_KEY'
+    }
+    print("Wait for LAVA results here...")
+    results['lava_jobs'].each { result ->
+      print(result)
+    }
+  }
+  cleanWs()
+}
diff --git a/jenkins/cppcheck.jpl b/jenkins/cppcheck.jpl
index eacdc3a..6ce22b4 100644
--- a/jenkins/cppcheck.jpl
+++ b/jenkins/cppcheck.jpl
@@ -51,13 +51,15 @@
           branches: [[name: 'FETCH_HEAD']], 
           userRemoteConfigs: [[
             refspec: 'refs/tags/$MBEDCRYPTO_VERSION',
-            url: 'https://github.com/ARMmbed/mbed-crypto.git'
+            url: params.MBEDCRYPTO_URL
           ]]
         ]
       )
     }
     sh """
-wget -O cmsis.pack -q https://github.com/ARM-software/CMSIS_5/releases/download/${CMSIS_VERSION}/ARM.CMSIS.${CMSIS_VERSION}.pack
+# Host https://github.com/Arm-software/CMSIS_5/releases/download/5.5.0/ARM.CMSIS.5.5.0.pack
+# under \$JENKINS_HOME/userContent
+wget -O cmsis.pack -q \${JENKINS_URL}/userContent/ARM.CMSIS.${CMSIS_VERSION}.pack
 unzip -o -d CMSIS_5 cmsis.pack
 """
   }
diff --git a/jenkins/lava-submit.jpl b/jenkins/lava-submit.jpl
new file mode 100644
index 0000000..fbb8611
--- /dev/null
+++ b/jenkins/lava-submit.jpl
@@ -0,0 +1,43 @@
+#!/usr/bin/env groovy
+//-------------------------------------------------------------------------------
+// Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+//
+// SPDX-License-Identifier: BSD-3-Clause
+//
+//-------------------------------------------------------------------------------
+
+node("docker-amd64-xenial") {
+  stage("Init") {
+    cleanWs()
+    dir("tf-m-ci-scripts") {
+      git url: '$CI_SCRIPTS_REPO', branch: 'master', credentialsId: 'GIT_SSH_KEY'
+    }
+  }
+  stage("LAVA") {
+    withCredentials([usernamePassword(credentialsId: 'LAVA_CREDENTIALS', passwordVariable: 'LAVA_TOKEN', usernameVariable: 'LAVA_USER')]) {
+      print("Generating LAVA jobs...")
+      def bl2_string = ""
+      if (env.BL2.equals("True")) {
+        bl2_string = "--bl2"
+      }
+      dir("tf-m-ci-scripts") {
+        def res = sh(script: """./lava_helper/lava_create_jobs.py \
+--build-number ${env.BUILD_NUMBER} --output-dir lava_jobs \
+--compiler ${env.COMPILER} --platform ${env.TARGET_PLATFORM} \
+${bl2_string} --build-type ${env.CMAKE_BUILD_TYPE} \
+--jenkins-build-url ${env.BUILD_URL} --proj-config ${env.PROJ_CONFIG}
+""", returnStdout: true).trim()
+        print(res)
+        job_ids = sh(script: """./lava_helper/lava_submit_jobs.py \
+  --lava-url https://tf.validation.linaro.org --job-dir lava_jobs \
+  --lava-user ${LAVA_USER} --lava-token ${LAVA_TOKEN}
+  """, returnStdout: true).trim()
+        currentBuild.setDescription(job_ids)
+      }
+    }
+  }
+  stage("Post") {
+    archiveArtifacts artifacts: 'tf-m-ci-scripts/lava_jobs/**', allowEmptyArchive: true
+    cleanWs()
+  }
+}