blob: a2852fc4b92fb394d8dbd6cee3f161cd365989b3 [file] [log] [blame]
Leonardo Sandoval9dfdd1b2020-08-06 17:08:11 -05001#!/usr/bin/env bash
Zelalem1af7a7b2020-08-04 17:34:32 -05002#
Saul Romerocacda172023-03-10 14:23:41 +00003# Copyright (c) 2019-2023, Arm Limited. All rights reserved.
Zelalem1af7a7b2020-08-04 17:34:32 -05004#
5# SPDX-License-Identifier: BSD-3-Clause
6#
7
Saul Romerocacda172023-03-10 14:23:41 +00008set -x
Zelalem1af7a7b2020-08-04 17:34:32 -05009REPORT_JSON=$1
10REPORT_HTML=$2
Paul Sokolovsky301710a2022-02-21 14:56:33 +030011
Gary Morrison999a9d72022-03-14 18:29:06 -050012if echo "$JENKINS_URL" | grep -q "oss.arm.com"; then
Saul Romerocacda172023-03-10 14:23:41 +000013 ARTIFACT_PATH='artifact/html/qa-code-coverage'
14 INFO_PATH='coverage.info'
15 JSON_PATH='intermediate_layer.json'
Paul Sokolovsky301710a2022-02-21 14:56:33 +030016else
Saul Romerocacda172023-03-10 14:23:41 +000017 ARTIFACT_PATH='artifact'
18 INFO_PATH='trace_report/coverage.info'
19 JSON_PATH='config_file.json'
Paul Sokolovsky301710a2022-02-21 14:56:33 +030020fi
21
Saul Romero072236d2023-12-06 11:57:16 +000022###############################################################################
Zelalem1af7a7b2020-08-04 17:34:32 -050023# Create json file for input to the merge.sh for Code Coverage
24# Globals:
Saul Romero072236d2023-12-06 11:57:16 +000025# REPORT_JSON: Json file with TF ci gateway builder test results
Saul Romerocacda172023-03-10 14:23:41 +000026# MERGE_CONFIGURATION: Json file to be used as input to the merge.sh
Zelalem1af7a7b2020-08-04 17:34:32 -050027# Arguments:
28# None
29# Outputs:
30# Print number of files to be merged
Saul Romero072236d2023-12-06 11:57:16 +000031###############################################################################
Zelalem1af7a7b2020-08-04 17:34:32 -050032create_merge_cfg() {
33python3 - << EOF
34import json
35import os
Saul Romero568f5d72023-11-29 11:58:34 +000036import re
Zelalem1af7a7b2020-08-04 17:34:32 -050037
38server = os.getenv("JENKINS_URL", "https://jenkins.oss.arm.com/")
39merge_json = {} # json object
40_files = []
41with open("$REPORT_JSON") as json_file:
42 data = json.load(json_file)
43merge_number = 0
44test_results = data['test_results']
45test_files = data['test_files']
46for index, build_number in enumerate(test_results):
Saul Romerocacda172023-03-10 14:23:41 +000047 if ("bmcov" in test_files[index] or
48 "code-coverage" in test_files[index]) and test_results[build_number] == "SUCCESS":
Zelalem1af7a7b2020-08-04 17:34:32 -050049 merge_number += 1
Paul Sokolovskydd04dea2022-02-21 13:40:43 +030050 base_url = "{}job/{}/{}/{}".format(
51 server, data['job'], build_number, "$ARTIFACT_PATH")
Saul Romero568f5d72023-11-29 11:58:34 +000052 _group_test_config = re.match(f'^[0-9%]*(?:${TEST_GROUPS}%)?(.+?)\.test', test_files[index])
53 tf_configuration = _group_test_config.groups()[0] if _group_test_config else 'N/A'
Zelalem1af7a7b2020-08-04 17:34:32 -050054 _files.append( {'id': build_number,
55 'config': {
56 'type': 'http',
Paul Sokolovskydd04dea2022-02-21 13:40:43 +030057 'origin': "{}/{}".format(
58 base_url, "$JSON_PATH")
Zelalem1af7a7b2020-08-04 17:34:32 -050059 },
60 'info': {
61 'type': 'http',
Paul Sokolovskydd04dea2022-02-21 13:40:43 +030062 'origin': "{}/{}".format(
63 base_url, "$INFO_PATH")
Saul Romero568f5d72023-11-29 11:58:34 +000064 },
65 'tf-configuration': tf_configuration
Zelalem1af7a7b2020-08-04 17:34:32 -050066 })
67merge_json = { 'files' : _files }
Saul Romerocacda172023-03-10 14:23:41 +000068with open("$MERGE_CONFIGURATION", 'w') as outfile:
69 json.dump(merge_json, outfile, indent=4)
Zelalem1af7a7b2020-08-04 17:34:32 -050070print(merge_number)
71EOF
72}
73
Saul Romero072236d2023-12-06 11:57:16 +000074###############################################################################
75# Append a summary table to an html file (report)that will be interpreted by
76# the Jenkins html plugin
77#
78# If there is more than one code coverage report and is merged successfully,
79# then a summary html/javascript table is created at the end of the
80# html file containing the merged function, line and branch coverage
81# percentages.
82# Globals:
83# OUTDIR: Path where the output folders are
84# COVERAGE_FOLDER: Folder name where the LCOV files are
85# REPORT_JSON: Json file with TF ci gateway builder test results
86# jenkins_archive_folder: Folder name where Jenkins archives files
87# list_of_merged_builds: Array with a list of individual successfully merged
88# jenkins build id's
89# number_of_files_to_merge: Indicates the number of individual jobs that have
90# code coverage and ran successfully
91# Arguments:
92# 1: HTML report to be appended the summary table
93# Outputs:
94# Appended HTML file with the summary table of merged code coverage
95###############################################################################
96generate_code_coverage_summary() {
Saul Romerocacda172023-03-10 14:23:41 +000097 local cov_html=${OUTDIR}/${COVERAGE_FOLDER}/index.html
98 local out_report=$1
Zelalem1af7a7b2020-08-04 17:34:32 -050099python3 - << EOF
100import re
Saul Romerocacda172023-03-10 14:23:41 +0000101import json
Zelalem1af7a7b2020-08-04 17:34:32 -0500102cov_html="$cov_html"
103out_report = "$out_report"
Saul Romerocacda172023-03-10 14:23:41 +0000104confs = ""
105with open("$REPORT_JSON") as json_file:
106 data = json.load(json_file)
Saul Romerocacda172023-03-10 14:23:41 +0000107
Zelalem1af7a7b2020-08-04 17:34:32 -0500108with open(cov_html, "r") as f:
109 html_content = f.read()
110items = ["Lines", "Functions", "Branches"]
111s = """
Saul Romerocacda172023-03-10 14:23:41 +0000112<style>
113.dropbtn {
114 background-color: #04AA6D;
115 color: white;
116 padding: 16px;
117 font-size: 16px;
118 border: none;
119}
120
121/* The container <div> - needed to position the dropdown content */
122.dropdown {
123 position: relative;
124 display: inline-block;
125}
126
127/* Dropdown Content (Hidden by Default) */
128.dropdown-content {
129 display: none;
130 position: absolute;
131 background-color: #f1f1f1;
132 min-width: 160px;
133 box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
134 z-index: 1;
135}
136
137/* Links inside the dropdown */
138.dropdown-content a {
139 color: black;
140 padding: 12px 16px;
141 text-decoration: none;
142 display: block;
143}
144
145/* Change color of dropdown links on hover */
146.dropdown-content a:hover {background-color: #ddd;}
147
148/* Show the dropdown menu on hover */
149.dropdown:hover .dropdown-content {display: block;}
150
151/* Change the background color of the dropdown button when the dropdown content is shown */
152.dropdown:hover .dropbtn {background-color: #3e8e41;}
153</style>
Zelalem1af7a7b2020-08-04 17:34:32 -0500154 <div id="div-cov">
155 <hr>
156 <table id="table-cov">
157 <tbody>
158 <tr>
159 <td>Type</td>
160 <td>Hit</td>
161 <td>Total</td>
162 <td>Coverage</td>
163 </tr>
164"""
165for item in items:
166 data = re.findall(r'<td class="headerItem">{}:</td>\n\s+<td class="headerCovTableEntry">(.+?)</td>\n\s+<td class="headerCovTableEntry">(.+?)</td>\n\s+'.format(item),
167 html_content, re.DOTALL)
168 if data is None:
169 continue
170 hit, total = data[0]
171 cov = round(float(hit)/float(total) * 100.0, 2)
172 color = "success"
173 if cov < 90:
174 color = "unstable"
175 if cov < 75:
176 color = "failure"
177 s = s + """
178 <tr>
179 <td>{}</td>
180 <td>{}</td>
181 <td>{}</td>
182 <td class='{}'>{} %</td>
183 </tr>
184""".format(item, hit, total, color, cov)
185s = s + """
186 </tbody>
187 </table>
188 <p>
Saul Romero568f5d72023-11-29 11:58:34 +0000189 <button onclick="window.open('artifact/${jenkins_archive_folder}/${COVERAGE_FOLDER}/index.html','_blank');">Total Coverage Report (${#list_of_merged_builds[@]} out of ${number_of_files_to_merge})</button>
Zelalem1af7a7b2020-08-04 17:34:32 -0500190 </p>
191 </div>
Saul Romerocacda172023-03-10 14:23:41 +0000192
Zelalem1af7a7b2020-08-04 17:34:32 -0500193<script>
194 document.getElementById('tf-report-main').appendChild(document.getElementById("div-cov"));
195</script>
Saul Romerocacda172023-03-10 14:23:41 +0000196
Zelalem1af7a7b2020-08-04 17:34:32 -0500197"""
198with open(out_report, "a") as f:
199 f.write(s)
200EOF
201}
Saul Romero568f5d72023-11-29 11:58:34 +0000202
Saul Romero072236d2023-12-06 11:57:16 +0000203###############################################################################
204# Append a column for each row corresponding to each build with a successful
205# code coverage report
206#
207# The column contains an html button that links to the individual code coverage
208# html report or 'N/A' if report cannot be found or build was a failure.
209# The column is added to the main table where all the tests configurations
210# status are shown.
211# Globals:
212# list_of_merged_builds: Array with a list of individual successfully merged
213# jenkins build id's
214# Arguments:
215# 1: HTML report to be appended the summary table
216# Outputs:
217# Appended HTML file with the column added to the main hmtl table
218###############################################################################
219generate_code_coverage_column() {
Saul Romero568f5d72023-11-29 11:58:34 +0000220 echo "List of merged build ids:${list_of_merged_builds[@]}"
221python3 - << EOF
222merged_ids=[int(i) for i in "${list_of_merged_builds[@]}".split()]
223s = """
224
225 <script>
226 window.onload = function() {
227 """ + f"const mergedIds={merged_ids}" + """
228 document.querySelector('#tf-report-main table').querySelectorAll("tr").forEach((row,i) => {
229 const cell = document.createElement(i ? "td" : "th")
230 const button = document.createElement("button")
231 button.textContent = "Report"
232 if (i) {
233 merged = false
234 if (q = row.querySelector('td.success a.buildlink')) {
235 href = q.href
236 buildId = href.split("/").at(-2)
237 if (mergedIds.include(buildId)) {
238 cell.classList.add("success")
239 const url = href.replace('console', 'artifact/trace_report/index.html')
240 button.addEventListener('click', () => {
241 window.open(url, "_blank")
242 })
243 cell.appendChild(button)
244 merged = true
245 }
246 }
247 if (!merged) {
248 cell.innerText = "N/A"
249 cell.classList.add("failure")
250 }
251 }
252 else {
253 cell.innerText = "Code Coverage"
254 }
255 row.appendChild(cell)
256 })
257 }
258 </script>
259"""
260with open("$1", "a") as f:
261 f.write(s)
262EOF
263}
264
265
Zelalem1af7a7b2020-08-04 17:34:32 -0500266OUTDIR=""
267index=""
268case "$TEST_GROUPS" in
269 scp*)
270 project="scp"
Saul Romerocacda172023-03-10 14:23:41 +0000271 jenkins_archive_folder=reports;;
Zelalem1af7a7b2020-08-04 17:34:32 -0500272 tf*)
273 project="trusted_firmware"
Saul Romerocacda172023-03-10 14:23:41 +0000274 jenkins_archive_folder=merge/outdir;;
Saul Romero82bcfb02023-06-27 16:24:13 +0100275 spm*)
276 project="hafnium"
277 jenkins_archive_folder=merge/outdir;;
Zelalem1af7a7b2020-08-04 17:34:32 -0500278 *)
279 exit 0;;
280esac
Saul Romerocacda172023-03-10 14:23:41 +0000281OUTDIR=${WORKSPACE}/${jenkins_archive_folder}
282source "$CI_ROOT/script/qa-code-coverage.sh"
283export MERGE_CONFIGURATION="$OUTDIR/merge_configuration.json"
284COVERAGE_FOLDER=lcov
285cd $WORKSPACE
286deploy_qa_tools
287cd -
Zelalem1af7a7b2020-08-04 17:34:32 -0500288mkdir -p $OUTDIR
289pushd $OUTDIR
Saul Romerocacda172023-03-10 14:23:41 +0000290 number_of_files_to_merge=$(create_merge_cfg)
Saul Romero568f5d72023-11-29 11:58:34 +0000291 echo "Merging from $number_of_files_to_merge code coverage reports..."
Zelalem1af7a7b2020-08-04 17:34:32 -0500292 # Only merge when more than 1 test result
Saul Romero072236d2023-12-06 11:57:16 +0000293 if [ "$number_of_files_to_merge" -lt 2 ]; then
Saul Romerocacda172023-03-10 14:23:41 +0000294 echo "Only one file to merge."
Zelalem1af7a7b2020-08-04 17:34:32 -0500295 exit 0
296 fi
Paul Sokolovsky227f2cc2021-12-21 10:58:26 +0300297
Saul Romero568f5d72023-11-29 11:58:34 +0000298 source ${WORKSPACE}/qa-tools/coverage-tool/coverage-reporting/merge.sh \
299 -j $MERGE_CONFIGURATION -l ${OUTDIR}/${COVERAGE_FOLDER} -w $WORKSPACE -c
Saul Romero072236d2023-12-06 11:57:16 +0000300 # backward compatibility with old qa-tools
301 [ $? -eq 0 ] && status=true || status=false
Paul Sokolovsky227f2cc2021-12-21 10:58:26 +0300302
Saul Romero072236d2023-12-06 11:57:16 +0000303 # merged_status is set at 'merge.sh' indicating if merging reports was ok
304 ${merged_status:-$status} && generate_code_coverage_summary "${REPORT_HTML}"
305 generate_code_coverage_column "${REPORT_HTML}"
306 cp "${REPORT_HTML}" "$OUTDIR"
Saul Romero568f5d72023-11-29 11:58:34 +0000307
Zelalem1af7a7b2020-08-04 17:34:32 -0500308popd