Skip to content
Snippets Groups Projects
Commit 6904c68d authored by Raphael Defosseux's avatar Raphael Defosseux
Browse files

CI: generate HTML report for DS Tester

parent 1b826ea8
No related branches found
No related tags found
No related merge requests found
...@@ -4,3 +4,5 @@ ci-scripts/mysql-complete.cmd ...@@ -4,3 +4,5 @@ ci-scripts/mysql-complete.cmd
ci-scripts/temp/ci-*.sh ci-scripts/temp/ci-*.sh
spgw_u.conf spgw_u.conf
deploy_results_oai_cn5g.html deploy_results_oai_cn5g.html
test_results_oai_cn5g_ds_tester.html
cn5g_fed_docker_logs.zip
...@@ -225,6 +225,7 @@ pipeline { ...@@ -225,6 +225,7 @@ pipeline {
myShCmdWithLog('cd /home/oaici/CI-dev-ops-cn5g/scripts && CI_ENV=True SRC_BASE_DIR=/tmp/CI-CN5G-FED ./run-5gc.bash -pt --shark --detach --get-results --5g', 'archives/run-5g-dstester.log', new_host_flag, new_host_user, new_host) myShCmdWithLog('cd /home/oaici/CI-dev-ops-cn5g/scripts && CI_ENV=True SRC_BASE_DIR=/tmp/CI-CN5G-FED ./run-5gc.bash -pt --shark --detach --get-results --5g', 'archives/run-5g-dstester.log', new_host_flag, new_host_user, new_host)
copyFrom2ndServer('DS-TEST-RESULTS/status.txt', 'DS-TEST-RESULTS', new_host_flag, new_host_user, new_host) copyFrom2ndServer('DS-TEST-RESULTS/status.txt', 'DS-TEST-RESULTS', new_host_flag, new_host_user, new_host)
copyFrom2ndServer('DS-TEST-RESULTS/*.tar', 'DS-TEST-RESULTS', new_host_flag, new_host_user, new_host) copyFrom2ndServer('DS-TEST-RESULTS/*.tar', 'DS-TEST-RESULTS', new_host_flag, new_host_user, new_host)
sh 'python3 ./ci-scripts/dsTestGenerateHTMLReport.py --job_name=' + JOB_NAME + ' --job_id=' + BUILD_ID + ' --job_url=' + BUILD_URL
} }
} }
} }
...@@ -264,6 +265,9 @@ pipeline { ...@@ -264,6 +265,9 @@ pipeline {
if (fileExists('deploy_results_oai_cn5g.html')) { if (fileExists('deploy_results_oai_cn5g.html')) {
archiveArtifacts artifacts: 'deploy_results_oai_cn5g.html' archiveArtifacts artifacts: 'deploy_results_oai_cn5g.html'
} }
if (fileExists('test_results_oai_cn5g_ds_tester.html')) {
archiveArtifacts artifacts: 'test_results_oai_cn5g_ds_tester.html'
}
} }
} }
} }
......
#/*
# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
# * contributor license agreements. See the NOTICE file distributed with
# * this work for additional information regarding copyright ownership.
# * The OpenAirInterface Software Alliance licenses this file to You under
# * the OAI Public License, Version 1.1 (the "License"); you may not use this file
# * except in compliance with the License.
# * You may obtain a copy of the License at
# *
# * http://www.openairinterface.org/?page_id=698
# *
# * Unless required by applicable law or agreed to in writing, software
# * distributed under the License is distributed on an "AS IS" BASIS,
# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# * See the License for the specific language governing permissions and
# * limitations under the License.
# *-------------------------------------------------------------------------------
# * For more information about the OpenAirInterface (OAI) Software Alliance:
# * contact@openairinterface.org
# */
#---------------------------------------------------------------------
import os
import re
import sys
import subprocess
class HtmlReport():
def __init__(self):
self.job_name = ''
self.job_id = ''
self.job_url = ''
self.job_start_time = 'TEMPLATE_TIME'
def generate(self):
cwd = os.getcwd()
self.file = open(cwd + '/test_results_oai_cn5g_ds_tester.html', 'w')
self.generateHeader()
finalStatus = self.testSummaryHeader()
self.testSummaryDetails()
self.testSummaryFooter()
self.generateFooter()
self.file.close()
if finalStatus:
sys.exit(0)
else:
sys.exit(-1)
def generateHeader(self):
# HTML Header
self.file.write('<!DOCTYPE html>\n')
self.file.write('<html class="no-js" lang="en-US">\n')
self.file.write('<head>\n')
self.file.write(' <meta name="viewport" content="width=device-width, initial-scale=1">\n')
self.file.write(' <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">\n')
self.file.write(' <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>\n')
self.file.write(' <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>\n')
self.file.write(' <title>OAI 5G Core Network Test Results for ' + self.job_name + ' job build #' + self.job_id + '</title>\n')
self.file.write('</head>\n')
self.file.write('<body><div class="container">\n')
self.file.write(' <table width = "100%" style="border-collapse: collapse; border: none;">\n')
self.file.write(' <tr style="border-collapse: collapse; border: none;">\n')
self.file.write(' <td style="border-collapse: collapse; border: none;">\n')
self.file.write(' <a href="http://www.openairinterface.org/">\n')
self.file.write(' <img src="http://www.openairinterface.org/wp-content/uploads/2016/03/cropped-oai_final_logo2.png" alt="" border="none" height=50 width=150>\n')
self.file.write(' </img>\n')
self.file.write(' </a>\n')
self.file.write(' </td>\n')
self.file.write(' <td style="border-collapse: collapse; border: none; vertical-align: center;">\n')
self.file.write(' <b><font size = "6">Job Summary -- Job: ' + self.job_name + ' -- Build-ID: <a href="' + self.job_url + '">' + self.job_id + '</a></font></b>\n')
self.file.write(' </td>\n')
self.file.write(' </tr>\n')
self.file.write(' </table>\n')
self.file.write(' <br>\n')
def generateFooter(self):
self.file.write(' <div class="well well-lg">End of Test Report -- Copyright <span class="glyphicon glyphicon-copyright-mark"></span> 2020 <a href="http://www.openairinterface.org/">OpenAirInterface</a>. All Rights Reserved.</div>\n')
self.file.write('</div></body>\n')
self.file.write('</html>\n')
def testSummaryHeader(self):
self.file.write(' <h2>DS Tester Summary</h2>\n')
finalDsTesterSummaryFile = 'DS-TEST-RESULTS/status.txt'
cwd = os.getcwd()
if os.path.isfile(cwd + '/' + finalDsTesterSummaryFile):
finalStatusOK = True
with open(cwd + '/' + finalDsTesterSummaryFile, 'r') as finalLog:
for line in finalLog:
line = line.strip()
result = re.search('FAILED', line)
if result is not None:
finalStatusOK = False
finalLog.close()
if finalStatusOK:
self.file.write(' <div class="alert alert-success">\n')
self.file.write(' <strong>Successful DsTester suite! <span class="glyphicon glyphicon-warning-sign"></span></strong>\n')
self.file.write(' </div>\n')
else:
self.file.write(' <div class="alert alert-danger">\n')
self.file.write(' <strong>Failed DsTester suite! <span class="glyphicon glyphicon-warning-sign"></span></strong>\n')
self.file.write(' </div>\n')
else:
self.file.write(' <div class="alert alert-warning">\n')
self.file.write(' <strong>LogFile not available! <span class="glyphicon glyphicon-warning-sign"></span></strong>\n')
self.file.write(' </div>\n')
return finalStatusOK
def testSummaryFooter(self):
self.file.write(' <br>\n')
def testSummaryDetails(self):
self.file.write(' <br>\n')
self.file.write(' <button data-toggle="collapse" data-target="#ds-tester-details">More details on DsTester results</button>\n')
self.file.write(' <div id="ds-tester-details" class="collapse">\n')
self.file.write(' <table class="table-bordered" width = "60%" align = "center" border = 1>\n')
self.file.write(' <tr bgcolor = "#33CCFF" >\n')
self.file.write(' <th>Test Name</th>\n')
self.file.write(' <th>Test Status</th>\n')
self.file.write(' <th>Test Details</th>\n')
self.file.write(' </tr>\n')
dsTesterDetailsLog = 'archives/run-5g-dstester.log'
cwd = os.getcwd()
if os.path.isfile(cwd + '/' + dsTesterDetailsLog):
testName = ''
testDetails = '<pre style="background-color:white">\n'
with open(cwd + '/' + dsTesterDetailsLog) as detailsLog:
for line in detailsLog:
line = line.strip()
result = re.search('CHECKED condition|FAILED condition', line)
if result is not None:
details = line.replace('Result String: ', '')
details = details.replace('CHECKED condition ', '')
details = details.replace('FAILED condition ', '')
result = re.search('FAILED condition', line)
if result is not None:
testDetails += '<b>' + details + '</b>\n'
else:
testDetails += details + '\n'
result = re.search('Running ', line)
if result is not None:
testName = line.replace('Running ', '')
result = re.search('status:', line)
if result is not None:
self.file.write(' <tr>\n')
self.file.write(' <td>' + testName + '</td>\n')
result = re.search('FAILED', line)
if result is not None:
self.file.write(' <td bgcolor = "Red"><b><font color="white">KO</font></b></td>\n')
else:
self.file.write(' <td bgcolor = "DarkGreen"><b><font color="white">OK</font></b></td>\n')
testDetails += '</pre>\n'
self.file.write(' <td>' + testDetails + '</td>\n')
self.file.write(' </tr>\n')
testDetails = '<pre style="background-color:white">\n'
detailsLog.close()
else:
print ('no details???')
self.file.write(' </table>\n')
self.file.write(' </div>\n')
def Usage():
print('----------------------------------------------------------------------------------------------------------------------')
print('dsTestGenerateHTMLReport.py')
print(' Generate an HTML report for the Jenkins pipeline on oai-cn5g-fed.')
print('----------------------------------------------------------------------------------------------------------------------')
print('Usage: python3 generateHtmlReport.py [options]')
print(' --help Show this help.')
print('---------------------------------------------------------------------------------------------- Mandatory Options -----')
print(' --job_name=[Jenkins Job name]')
print(' --job_id=[Jenkins Job Build ID]')
print(' --job_url=[Jenkins Job Build URL]')
#--------------------------------------------------------------------------------------------------------
#
# Start of main
#
#--------------------------------------------------------------------------------------------------------
argvs = sys.argv
argc = len(argvs)
HTML = HtmlReport()
while len(argvs) > 1:
myArgv = argvs.pop(1)
if re.match('^\-\-help$', myArgv, re.IGNORECASE):
Usage()
sys.exit(0)
elif re.match('^\-\-job_name=(.+)$', myArgv, re.IGNORECASE):
matchReg = re.match('^\-\-job_name=(.+)$', myArgv, re.IGNORECASE)
HTML.job_name = matchReg.group(1)
elif re.match('^\-\-job_id=(.+)$', myArgv, re.IGNORECASE):
matchReg = re.match('^\-\-job_id=(.+)$', myArgv, re.IGNORECASE)
HTML.job_id = matchReg.group(1)
elif re.match('^\-\-job_url=(.+)$', myArgv, re.IGNORECASE):
matchReg = re.match('^\-\-job_url=(.+)$', myArgv, re.IGNORECASE)
HTML.job_url = matchReg.group(1)
else:
sys.exit('Invalid Parameter: ' + myArgv)
if HTML.job_name == '' or HTML.job_id == '' or HTML.job_url == '':
sys.exit('Missing Parameter in job description')
HTML.generate()
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment