blob: d25ebed17020145f8be23326c704d810e987ba70 [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
Arthur Shea813bdf2025-02-03 21:39:57 -080012if echo "$JENKINS_PUBLIC_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
Arthur Shea813bdf2025-02-03 21:39:57 -080038server = os.getenv("JENKINS_PUBLIC_URL", "https://jenkins.oss.arm.com/")
Zelalem1af7a7b2020-08-04 17:34:32 -050039merge_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
Saul Romero95e8d4e2023-12-11 10:03:55 +0000214# individual_report_folder: Location within the jenkins job worker where
215# resides the code coverage html report.
Saul Romero072236d2023-12-06 11:57:16 +0000216# Arguments:
217# 1: HTML report to be appended the summary table
218# Outputs:
219# Appended HTML file with the column added to the main hmtl table
220###############################################################################
221generate_code_coverage_column() {
Saul Romero568f5d72023-11-29 11:58:34 +0000222 echo "List of merged build ids:${list_of_merged_builds[@]}"
223python3 - << EOF
224merged_ids=[int(i) for i in "${list_of_merged_builds[@]}".split()]
225s = """
226
227 <script>
228 window.onload = function() {
229 """ + f"const mergedIds={merged_ids}" + """
230 document.querySelector('#tf-report-main table').querySelectorAll("tr").forEach((row,i) => {
231 const cell = document.createElement(i ? "td" : "th")
232 const button = document.createElement("button")
233 button.textContent = "Report"
234 if (i) {
235 merged = false
236 if (q = row.querySelector('td.success a.buildlink')) {
237 href = q.href
Saul Romero690348e2024-08-20 16:05:40 +0100238 buildId = Number(href.split("/").at(-2))
239 if (mergedIds.includes(buildId)) {
Saul Romero568f5d72023-11-29 11:58:34 +0000240 cell.classList.add("success")
Saul Romero95e8d4e2023-12-11 10:03:55 +0000241 const url = href.replace('console', 'artifact/${individual_report_folder}')
Saul Romero568f5d72023-11-29 11:58:34 +0000242 button.addEventListener('click', () => {
243 window.open(url, "_blank")
244 })
245 cell.appendChild(button)
246 merged = true
247 }
248 }
249 if (!merged) {
250 cell.innerText = "N/A"
251 cell.classList.add("failure")
252 }
253 }
254 else {
255 cell.innerText = "Code Coverage"
256 }
257 row.appendChild(cell)
258 })
259 }
260 </script>
261"""
262with open("$1", "a") as f:
263 f.write(s)
264EOF
265}
266
267
Zelalem1af7a7b2020-08-04 17:34:32 -0500268OUTDIR=""
269index=""
270case "$TEST_GROUPS" in
271 scp*)
272 project="scp"
Saul Romero95e8d4e2023-12-11 10:03:55 +0000273 jenkins_archive_folder=reports
274 individual_report_folder=html/qa-code-coverage/lcov/index.html
275 ;;
Zelalem1af7a7b2020-08-04 17:34:32 -0500276 tf*)
277 project="trusted_firmware"
Saul Romero95e8d4e2023-12-11 10:03:55 +0000278 jenkins_archive_folder=merge/outdir
279 individual_report_folder=trace_report/index.html
280 ;;
Saul Romero82bcfb02023-06-27 16:24:13 +0100281 spm*)
282 project="hafnium"
Saul Romero95e8d4e2023-12-11 10:03:55 +0000283 jenkins_archive_folder=merge/outdir
284 individual_report_folder=trace_report/index.html
285 ;;
Zelalem1af7a7b2020-08-04 17:34:32 -0500286 *)
287 exit 0;;
288esac
Saul Romerocacda172023-03-10 14:23:41 +0000289OUTDIR=${WORKSPACE}/${jenkins_archive_folder}
290source "$CI_ROOT/script/qa-code-coverage.sh"
291export MERGE_CONFIGURATION="$OUTDIR/merge_configuration.json"
292COVERAGE_FOLDER=lcov
293cd $WORKSPACE
294deploy_qa_tools
295cd -
Zelalem1af7a7b2020-08-04 17:34:32 -0500296mkdir -p $OUTDIR
297pushd $OUTDIR
Saul Romerocacda172023-03-10 14:23:41 +0000298 number_of_files_to_merge=$(create_merge_cfg)
Saul Romero568f5d72023-11-29 11:58:34 +0000299 echo "Merging from $number_of_files_to_merge code coverage reports..."
Zelalem1af7a7b2020-08-04 17:34:32 -0500300 # Only merge when more than 1 test result
Saul Romero072236d2023-12-06 11:57:16 +0000301 if [ "$number_of_files_to_merge" -lt 2 ]; then
Saul Romerocacda172023-03-10 14:23:41 +0000302 echo "Only one file to merge."
Zelalem1af7a7b2020-08-04 17:34:32 -0500303 exit 0
304 fi
Paul Sokolovsky227f2cc2021-12-21 10:58:26 +0300305
Saul Romero568f5d72023-11-29 11:58:34 +0000306 source ${WORKSPACE}/qa-tools/coverage-tool/coverage-reporting/merge.sh \
Saul Romero690348e2024-08-20 16:05:40 +0100307 -j $MERGE_CONFIGURATION -l ${OUTDIR}/${COVERAGE_FOLDER} \
308 -w $WORKSPACE -c -i -d
Saul Romero072236d2023-12-06 11:57:16 +0000309 # backward compatibility with old qa-tools
310 [ $? -eq 0 ] && status=true || status=false
Paul Sokolovsky227f2cc2021-12-21 10:58:26 +0300311
Saul Romero072236d2023-12-06 11:57:16 +0000312 # merged_status is set at 'merge.sh' indicating if merging reports was ok
313 ${merged_status:-$status} && generate_code_coverage_summary "${REPORT_HTML}"
Saul Romero690348e2024-08-20 16:05:40 +0100314 generate_code_coverage_column "${REPORT_HTML}" || true
Saul Romero072236d2023-12-06 11:57:16 +0000315 cp "${REPORT_HTML}" "$OUTDIR"
Zelalem1af7a7b2020-08-04 17:34:32 -0500316popd