From dda1044cf9df72ccd463eb01f63b67a2be3a66b4 Mon Sep 17 00:00:00 2001 From: TimSVector Date: Mon, 20 May 2024 15:00:05 -0400 Subject: [PATCH 001/112] Updates --- src/main/resources/scripts/generate_xml.py | 78 ++++++++++++++++------ 1 file changed, 58 insertions(+), 20 deletions(-) diff --git a/src/main/resources/scripts/generate_xml.py b/src/main/resources/scripts/generate_xml.py index de1373c5..301670bc 100644 --- a/src/main/resources/scripts/generate_xml.py +++ b/src/main/resources/scripts/generate_xml.py @@ -761,7 +761,6 @@ def generate_local_results(self, results, key): print(" {}/{}/{}".format(comp, ts, env_name)) return - xmlUnitReportName = os.getcwd() + os.sep + "xml_data" + os.sep + "test_results_" + key.replace("/","_") + ".xml" localXML = GenerateXml(self.FullManageProjectName, build_dir, env_name, comp, ts, @@ -1002,7 +1001,7 @@ def generate_unit(self): vctMap = False if not tc.is_csv_map and not vctMap: if not tc.for_compound_only or tc.testcase_status == "TCR_STRICT_IMPORT_FAILED": - self.write_testcase(tc, tc.function.unit.name, tc.function.display_name) + self.write_testcase(tc, tc.function.unit.name, tc.function.display_name, unit = unit) except AttributeError as e: parse_traceback.parse(traceback.format_exc(), self.verbose, self.compiler, self.testsuite, self.env, self.build_dir) @@ -1110,12 +1109,63 @@ def testcase_failed(self, tc): return True return False + + def get_xml_string(self, fpath = None): + + if fpath: + testcaseStringExtraStatus=""" + + %s + +%s + + +""" + testcaseString =""" + + %s + +""" + + else: + testcaseStringExtraStatus=""" + + %s + +%s + + +""" + testcaseString =""" + + %s + +""" + return testcaseString, testcaseStringExtraStatus # # GenerateXml - write a testcase to the jUnit XML file # - def write_testcase(self, tc, unit_name, func_name, st_is_monitored = False): + def write_testcase(self, tc, unit_name, func_name, st_is_monitored = False, unit = None): + fpath = "" + startLine = "" + unitName = "" + + if unit: + filePath = unit.sourcefile.normalized_path(normcase=False) + + try: + prj_dir = os.environ['WORKSPACE'].replace("\\","/") + "/" + except: + prj_dir = os.getcwd().replace("\\","/") + "/" + + fpath = os.path.relpath(filePath,prj_dir).replace("\\","/") + + startLine = str(tc.function.start_line) + + unitName = unit.name + if self.noResults: return @@ -1229,6 +1279,8 @@ def write_testcase(self, tc, unit_name, func_name, st_is_monitored = False): status = "PASS" extraStatus = "" + testcaseString, testcaseStringExtraStatus = self.get_xml_string(fpath) + if status != "": msg = "{} {} / {} \n\nExecution Report:\n {}".format(status, exp_pass, exp_total, result) msg = escape(msg, quote=False) @@ -1236,25 +1288,11 @@ def write_testcase(self, tc, unit_name, func_name, st_is_monitored = False): msg = msg.replace("\n"," ") msg = msg.replace("\r","") - testcaseStringExtraStatus=""" - - %s - -%s - - -""" - testcaseString =""" - - %s - -""" - if status != "": testcaseString = testcaseStringExtraStatus - self.fh_data += (testcaseString % (tc_name_full, classname, deltaTimeStr, extraStatus, msg)) + self.fh_data += (testcaseString % (tc_name_full, unitName, deltaTimeStr, fpath, startLine, extraStatus, msg)) else: - self.fh_data += (testcaseString % (tc_name_full, classname, deltaTimeStr, extraStatus)) - + self.fh_data += (testcaseString % (tc_name_full, unitName, deltaTimeStr, fpath, startLine, extraStatus)) + ## GenerateXml def was_test_case_skipped(self, tc, searchName, isSystemTest): From 28f163a32d57bbd55cc09e4ca3e8b357dec0b423 Mon Sep 17 00:00:00 2001 From: TimSVector Date: Mon, 3 Jun 2024 09:31:33 -0400 Subject: [PATCH 002/112] Adding new files --- src/main/resources/scripts/cobertura.py | 732 ++++++++++++++++++ .../resources/scripts/create_index_html.py | 181 +++++ 2 files changed, 913 insertions(+) create mode 100644 src/main/resources/scripts/cobertura.py create mode 100644 src/main/resources/scripts/create_index_html.py diff --git a/src/main/resources/scripts/cobertura.py b/src/main/resources/scripts/cobertura.py new file mode 100644 index 00000000..0e77f499 --- /dev/null +++ b/src/main/resources/scripts/cobertura.py @@ -0,0 +1,732 @@ +# +# The MIT License +# +# Copyright 2020 Vector Informatik, GmbH. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# + +from lxml import etree +from vector.apps.DataAPI.vcproject_api import VCProjectApi +from vector.apps.DataAPI.vcproject_models import VCProject +from vector.apps.DataAPI.cover_api import CoverApi +from vector.apps.DataAPI.unit_test_api import UnitTestApi +import sys, os +from collections import defaultdict +from pprint import pprint + + +fileList = [] + +def dump(obj): + if hasattr(obj, '__dict__'): + return vars(obj) + else: + try: + return {attr: getattr(obj, attr, None) for attr in obj.__slots__} + except: + return str(obj) + +def write_xml(x, name, verbose = False): + + if verbose: + print(etree.tostring(x,pretty_print=True)) + + xml_str = "\n" + xml_str += "\n" + + xml_str += etree.tostring(x,pretty_print=True).decode() + + open(name + ".xml", "w").write(xml_str) + +def getCoveredFunctionCount(source): + if len(source.functions) == 0: + return 0,0 + + funcTotal = 0 + funcCovTotal = 0 + for funcApi in source.functions: + func_cov = False + funcTotal += 1 + for instFunc in funcApi.instrumented_functions: + if instFunc.covered(True): + func_cov = True + if func_cov: + funcCovTotal += 1 + # print(source.name,"::",funcApi.name, func_cov) + + # print(funcCovTotal, funcTotal) + + return funcCovTotal, funcTotal + +def getFileXML(testXml, coverAPI, verbose = False): + + try: + prj_dir = os.environ['CI_PROJECT_DIR'].replace("\\","/") + "/" + except: + try: + prj_dir = os.environ['WORKSPACE'].replace("\\","/") + "/" + except: + prj_dir = os.getcwd().replace("\\","/") + "/" + + fname = coverAPI.display_name + fpath = os.path.relpath(coverAPI.display_path,prj_dir).replace("\\","/") + + branch_totals = float(coverAPI.metrics.branches + coverAPI.metrics.mcdc_branches) + branch_covered = float(coverAPI.metrics.covered_branches + coverAPI.metrics.covered_mcdc_branches) + + if branch_totals > 0: + branch_pct = branch_covered / branch_totals + else: + branch_pct = 0.0 + + statement_pct = coverAPI.metrics.covered_statements_pct / 100.0 + mcdcpair_pct = coverAPI.metrics.covered_mcdc_pairs_pct / 100.0 + funccall_pct = coverAPI.metrics.covered_function_calls_pct / 100.0 + func_pct = coverAPI.metrics.covered_functions_pct / 100.0 + + file = None + + if verbose: + print (" fname = ", fname) + print (" fpath = ", fpath) + + for element in testXml.iter(): + if element.tag == "class" and element.attrib['filename'] == fpath: + file = element + lines = file[0] + + if file == None: + file = etree.SubElement(testXml, "class") + if ".c" in fname: + fname = fname.split(".c")[0] + file.attrib['name'] = fname.replace(".","_") + file.attrib['filename'] = fpath + + if coverAPI.metrics.statements > 0: + file.attrib['line-rate'] = str(statement_pct) + # statementPercentStr = "{:.2f}".format(coverAPI.metrics.covered_statements_pct) + "% (" + str(coverAPI.metrics.covered_statements) + "/" + str(coverAPI.metrics.statements) + ")" + # file.attrib['statement'] = statementPercentStr + + if coverAPI.metrics.branches or coverAPI.metrics.mcdc_branches: + file.attrib['branch-rate'] = str(branch_pct) + if coverAPI.metrics.function_calls > 0: + funcCallPercentStr = "{:.2f}".format(coverAPI.metrics.covered_function_calls_pct) + "% (" + str(coverAPI.metrics.covered_function_calls) + "/" + str(coverAPI.metrics.function_calls) + ")" + file.attrib['functioncall-coverage'] = funcCallPercentStr + if coverAPI.metrics.mcdc_pairs > 0: + mcdcPairPercentStr = "{:.2f}".format(coverAPI.metrics.covered_mcdc_pairs_pct) + "% (" + str(coverAPI.metrics.covered_mcdc_pairs) + "/" + str(coverAPI.metrics.mcdc_pairs) + ")" + file.attrib['mcdcpair-coverage'] = mcdcPairPercentStr + + funcCovTotal, funcTotal = getCoveredFunctionCount(coverAPI) + + if funcTotal > 0: + file.attrib['function-coverage'] = "{:.2f}".format(100.0 *funcCovTotal/funcTotal) + "% (" + str(funcCovTotal) + "/" + str(funcTotal) + ")" + else: + file.attrib['function-coverage'] = "0.00% (0/0)" + + file.attrib['complexity'] = str(coverAPI.metrics.complexity) + + methods = etree.SubElement(file, "methods") + lines = etree.SubElement(file, "lines") + path = os.path.dirname(fname) + if path not in fileList: + fileList.append(path) + + return methods, lines + +def getLineCoverageElementXML(lines, lineno): + + covEle = None + + for element in lines.iter(): + if element.tag == "line" and element.attrib['number'] == str(lineno): + covEle = element + + if covEle == None: + covEle = etree.SubElement(lines, "line") + covEle.attrib['number'] = str(lineno) + covEle.attrib['hits'] = "0" + covEle.attrib['branch'] = "false" + + return covEle + +def getBranchMcdcPairFcCoverageElementXML(lines, line, branchPercent = None, mcdcPercent = None, functionCallPercent = None): + + lineno = line.line_number + covEle = None + condition = None + #print(etree.tostring(lines,pretty_print=True).decode()) + for element in lines.iter(): + if element.tag == "line" and element.attrib['number'] == str(lineno): + covEle = element + if branchPercent: + if covEle.attrib['branch'] == 'false': + covEle.attrib['branch'] = 'true' + covEle.attrib['number'] = str(lineno) + covEle.attrib['condition-coverage'] = branchPercent + conditions = etree.SubElement(covEle, "conditions") + condition = etree.SubElement(conditions, "condition") + else: + condition = covEle[0][0] + if mcdcPercent: + covEle.attrib['mcdcpair-coverage'] = mcdcPercent + if functionCallPercent: + covEle.attrib['functioncall-coverage'] = functionCallPercent + + + if covEle == None: + covEle = etree.SubElement(lines, "line") + covEle.attrib['number'] = str(lineno) + covEle.attrib['hits'] = "0" + if branchPercent: + covEle.attrib['condition-coverage'] = branchPercent + covEle.attrib['branch'] = "true" + conditions = etree.SubElement(covEle, "conditions") + condition = etree.SubElement(conditions, "condition") + if mcdcPercent: + covEle.attrib['mcdcpair-coverage'] = mcdcPercent + if functionCallPercent: + covEle.attrib['functioncall-coverage'] = functionCallPercent + + if condition is not None: + condition.attrib['number'] = "0" + condition.attrib['type'] = "jump" + condition.attrib['coverage'] = branchPercent.split()[0] + + return covEle + +def has_any_coverage(line): + + return (line.metrics.statements + + line.metrics.branches + + line.metrics.mcdc_branches + + line.metrics.mcdc_pairs + + line.metrics.functions + + line.metrics.function_calls) + +def has_anything_covered(line): + + return (line.metrics.covered_statements + + line.metrics.covered_branches + + line.metrics.covered_mcdc_branches + + line.metrics.covered_mcdc_pairs + + line.metrics.covered_functions + + line.metrics.covered_function_calls + + line.metrics.max_covered_statements + + line.metrics.max_covered_branches + + line.metrics.max_covered_mcdc_branches + + line.metrics.max_covered_mcdc_pairs + + line.metrics.max_covered_functions + + line.metrics.max_covered_function_calls) + +def processStatementBranchMCDC(fileApi, lines): + + linesTotal = 0 + linesCovered = 0 + + for line in fileApi.iterate_coverage(): + if not has_any_coverage(line): + continue + + linesTotal += 1 + + covEle = getLineCoverageElementXML(lines,line.line_number) + + if has_anything_covered(line): + linesCovered += 1 + covEle.attrib['hits'] = "1" + + # multi-line statement + # if line.start_line != line.end_line: + # lines.remove(covEle) + # # if its part of a multi-line statement, save the range for use later + # for num in range(line.start_line,line.end_line+1): + # covEle = getLineCoverageElementXML(lines,num) + # if covEle.attrib['hits'] != "0" or covered == "true": + # covEle.attrib['hits'] = "1" + + ## branches + branchPct = -1.0 + totalBr = 0 + coverBr = 0 + + if line.metrics.branches + line.metrics.mcdc_branches: + totalBr = line.metrics.branches + line.metrics.mcdc_branches + if (line.metrics.covered_branches + line.metrics.covered_mcdc_branches) > 0: + coverBr = line.metrics.covered_branches + line.metrics.covered_mcdc_branches + elif (line.metrics.max_covered_branches + line.metrics.max_covered_mcdc_branches) > 0: + coverBr = line.metrics.max_covered_branches + line.metrics.max_covered_mcdc_branches + else: + coverBr = 0 + + branchPct = (coverBr * 100 ) / totalBr + + ## mcdc pair + pairPct = -1.0 + totalPr = 0 + coverPr = 0 + if line.metrics.mcdc_pairs: + totalPr = line.metrics.mcdc_pairs + coverPr = line.metrics.covered_mcdc_pairs + pairPct = (coverPr * 100 ) / totalPr + + ## function call + totalFc = -1.0 + coverFc = 0 + fcPct = 0 + hasFc = False + fcPctString = None + + if line.metrics.function_calls: + hasFc = True + totalFc = line.metrics.function_calls + coverFc = line.metrics.covered_function_calls + fcPct = (coverFc * 100 ) / totalFc + fcPctString = str(fcPct) + "% (" + str(coverFc) + "/" + str(totalFc) + ")" + + ## has branches + hasBranches = False + pairPctString = None + branchPctString = None + if line.metrics.branches + line.metrics.mcdc_branches + line.metrics.mcdc_pairs: + hasBranches = True + if branchPct == -1: + branchPctString = "0.0% (0/0)" + else: + branchPctString = str(branchPct) + "% (" + str(coverBr) + "/" + str(totalBr) + ")" + if pairPct == -1: + pairPctString = None + else: + pairPctString = str(pairPct) + "% (" + str(coverPr) + "/" + str(totalPr) + ")" + + if hasBranches or hasFc: + covEle = getBranchMcdcPairFcCoverageElementXML(lines, line, branchPctString, pairPctString, fcPctString) + + return linesCovered, linesTotal + + +def procesCoverage(coverXML, coverApi): + + methods, lines = getFileXML(coverXML, coverApi) + + for func in coverApi.functions: + + method = etree.SubElement(methods, "method") + + method.attrib['name'] = func.name + method.attrib['signature'] = func.instrumented_functions[0].parameterized_name.replace(func.name,"",1) + method.attrib['line-rate'] = str(func.metrics.covered_statements_pct/100.0) + + statementPercentStr = "{:.2f}".format(func.metrics.covered_statements_pct) + "% (" + str(func.metrics.covered_statements) + "/" + str(func.metrics.statements) + ")" + #method.attrib['statements'] = statementPercentStr + + func_total_br = func.metrics.branches + func.metrics.mcdc_branches + func_cov_br = func.metrics.covered_branches + func.metrics.covered_mcdc_branches + + func_branch_rate = 0.0 + if func_total_br > 0: + func_branch_rate = float(func_cov_br) / float(func_total_br) + + method.attrib['branch-rate'] = str(func_branch_rate) + method.attrib['complexity'] = str(func.complexity) + + if func.metrics.function_calls > 0: + funcCallPercentStr = "{:.2f}".format(func.metrics.covered_function_calls_pct) + "% (" + str(func.metrics.covered_function_calls) + "/" + str(func.metrics.function_calls) + ")" + method.attrib['functioncall-coverage'] = funcCallPercentStr + if func.metrics.mcdc_pairs > 0: + mcdcPairPercentStr = "{:.2f}".format(func.metrics.covered_mcdc_pairs_pct) + "% (" + str(func.metrics.covered_mcdc_pairs) + "/" + str(func.metrics.mcdc_pairs) + ")" + method.attrib['mcdcpair-coverage'] = mcdcPairPercentStr + + if (func.metrics.aggregate_covered_functions_pct + + func.metrics.aggregate_covered_statements_pct + + func.metrics.aggregate_covered_branches_pct + + func.metrics.aggregate_covered_mcdc_branches_pct + + func.metrics.aggregate_covered_mcdc_pairs + + func.metrics.aggregate_covered_function_calls_pct) > 0: + method.attrib['function-coverage'] = "100% (1/1)" + else: + method.attrib['function-coverage'] = "0% (0/1)" + + # if lines under methods are required + # func_lines = etree.SubElement(method, "lines") + # processStatementBranchMCDC(func, func_lines) + + + return processStatementBranchMCDC(coverApi, lines) + +def runCoverageResultsMP(packages, mpFile, verbose = False): + + vcproj = VCProjectApi(mpFile) + api = vcproj.project.cover_api + + return runCoberturaResults(packages, api) + +def runCoberturaResults(packages, api, verbose = False): + + total_br = 0 + total_st = 0 + total_func = 0 + total_fc = 0 + total_mcdc = 0 + + total_lines = 0 + + cov_br = 0 + cov_st = 0 + cov_func = 0 + cov_fc = 0 + cov_mcdc = 0 + + cov_lines = 0 + + vg = 0 + + pkg_total_br = 0 + pkg_total_st = 0 + pkg_total_func = 0 + pkg_total_fc = 0 + pkg_total_mcdc = 0 + + pkg_total_lines = 0 + + pkg_cov_br = 0 + pkg_cov_st = 0 + pkg_cov_func = 0 + pkg_cov_fc = 0 + pkg_cov_mcdc = 0 + pkg_vg = 0 + + pkg_cov_lines = 0 + + path_name = "@@@@" + + package = None + + hasStatementCov = False + hasBranchCov = False + hasMcdcCov = False + hasFunctionCov = False + hasFunctionCallCov = False + + fileDict = {} + try: + prj_dir = os.environ['CI_PROJECT_DIR'].replace("\\","/") + "/" + except: + try: + prj_dir = os.environ['WORKSPACE'].replace("\\","/") + "/" + except: + prj_dir = os.getcwd().replace("\\","/") + "/" + + # get a sorted listed of all the files with the proj directory stripped off + + for file in api.SourceFile.all(): + if file.display_name == "": + continue + + fname = file.display_name + fpath = file.display_path.rsplit('.',1)[0] + fpath = os.path.relpath(fpath,prj_dir).replace("\\","/") + + # print("*", file.name, file.display_name, fpath) + + fileDict[fpath] = file + + for path in sorted(fileDict.keys()): + file = fileDict[path] + new_path = path.rsplit('/',1)[0] + + # when we switch paths + if new_path != path_name: + + # If we have data to save... + if package != None: + + if verbose: + print("saving data for package: " + path_name ) + + # calculate stats for package + branch_rate = 0.0 + statement_rate = 0.0 + line_rate = 0.0 + MCDC_rate = 0.0 + FC_rate = 0.0 + func_rate = 0.0 + + if pkg_total_st > 0: + statement_rate = float(pkg_cov_st) / float(pkg_total_st) + + if pkg_total_lines > 0: + line_rate = float(pkg_cov_lines) / float(pkg_total_lines) + + if pkg_total_br > 0: + branch_rate = float(pkg_cov_br) / float(pkg_total_br) + + if pkg_total_mcdc > 0: + MCDC_rate = float(pkg_cov_mcdc) / float(pkg_total_mcdc) + + if pkg_total_func > 0: + func_rate = float(pkg_cov_func) / float(pkg_total_func) + + if pkg_total_fc > 0: + FC_rate = float(pkg_cov_fc) / float(pkg_total_fc) + + # store the stats + # remove trailing . if present + package_name = path_name.replace("/",".") + if package_name.endswith("."): + package_name = package_name[:-1] + + package.attrib['name'] = package_name + + + package.attrib['complexity'] = str(pkg_vg) + + if file.has_statement_coverage: + package.attrib['line-rate'] = str(line_rate) + if file.has_branch_coverage or file.has_mcdc_coverage: + package.attrib['branch-rate'] = str(branch_rate) + if file.has_mcdc_coverage: + mcdcPairPercentStr = "{:.2f}".format(MCDC_rate * 100.0) + "% (" + str(pkg_cov_mcdc) + "/" + str(pkg_total_mcdc) + ")" + package.attrib['mcdcpair-coverage'] = mcdcPairPercentStr + if file.has_function_call_coverage: + funcCallPercentStr = "{:.2f}".format(FC_rate * 100.0) + "% (" + str(pkg_cov_fc) + "/" + str(pkg_total_fc) + ")" + package.attrib['functioncall-coverage'] = funcCallPercentStr + + funcCovTotal, funcTotal = getCoveredFunctionCount(file) + if funcTotal > 0: + func_rate = funcCovTotal / funcTotal + funcPercentStr = "{:.2f}".format(func_rate * 100.0) + "% (" + str(pkg_cov_func) + "/" + str(pkg_total_func) + ")" + package.attrib['function-coverage'] = funcPercentStr + + path_name = new_path + + if verbose: + # create a new package and zero out the stats + print("creating blank package for: " + path_name + "/") + + package = etree.SubElement(packages, "package") + classes = etree.SubElement(package, "classes") + pkg_total_br = 0 + pkg_total_lines = 0 + pkg_total_st = 0 + pkg_total_func = 0 + pkg_total_fc = 0 + pkg_total_mcdc = 0 + + pkg_cov_br = 0 + pkg_cov_st = 0 + pkg_cov_lines = 0 + pkg_cov_func = 0 + pkg_cov_fc = 0 + pkg_cov_mcdc = 0 + pkg_vg = 0 + + + if verbose: + print ("adding data for " + path) + + total_br += file.metrics.branches + file.metrics.mcdc_branches + total_st += file.metrics.statements + total_fc += file.metrics.function_calls + total_mcdc += file.metrics.mcdc_pairs + + cov_br += file.metrics.covered_branches + file.metrics.covered_mcdc_branches + cov_st += file.metrics.covered_statements + cov_fc += file.metrics.covered_function_calls + cov_mcdc += file.metrics.covered_mcdc_pairs + vg += file.metrics.complexity + + pkg_total_br += file.metrics.branches + file.metrics.mcdc_branches + pkg_total_st += file.metrics.statements + pkg_total_fc += file.metrics.function_calls + pkg_total_mcdc += file.metrics.mcdc_pairs + + + pkg_cov_br += file.metrics.covered_branches + file.metrics.covered_mcdc_branches + pkg_cov_st += file.metrics.covered_statements + pkg_cov_fc += file.metrics.covered_function_calls + pkg_cov_mcdc += file.metrics.covered_mcdc_pairs + pkg_vg += file.metrics.complexity + + funcCovTotal, funcTotal = getCoveredFunctionCount(file) + pkg_total_func += funcTotal + pkg_cov_func += funcCovTotal + total_func += funcTotal + cov_func += funcCovTotal + + linesCovered, linesTotal = procesCoverage(classes, file) + + total_lines += linesTotal + cov_lines += linesCovered + pkg_total_lines += linesTotal + pkg_cov_lines += linesCovered + + + if package != None: + if verbose: + print("saving data for package: " + path_name ) + + # calculate stats for package + line_rate = 0.0 + branch_rate = 0.0 + func_rate = 0.0 + FC_rate = 0.0 + MCDC_rate = 0.0 + + if pkg_total_st > 0: + statement_rate = float(pkg_cov_st) / float(pkg_total_st) + if pkg_total_lines > 0: + line_rate = float(pkg_cov_lines) / float(pkg_total_lines) + if pkg_total_br > 0: + branch_rate = float(pkg_cov_br) / float(pkg_total_br) + if pkg_total_func > 0: + func_rate = float(pkg_cov_func) / float(pkg_total_func) + if pkg_total_fc > 0: + FC_rate = float(pkg_cov_fc) / float(pkg_total_fc) + if pkg_total_mcdc > 0: + MCDC_rate = float(pkg_cov_mcdc) / float(pkg_total_mcdc) + + # store the stats + package_name = path_name.replace("/",".") + if package_name.endswith("."): + package_name = package_name[:-1] + + package.attrib['name'] = package_name + if file.has_statement_coverage: + package.attrib['line-rate'] = str(line_rate) + package.attrib['statement-rate'] = str(statement_rate) + if file.has_branch_coverage or file.has_mcdc_coverage: + package.attrib['branch-rate'] = str(branch_rate) + if file.has_mcdc_coverage: + mcdcPairPercentStr = "{:.2f}".format(MCDC_rate * 100.0) + "% (" + str(pkg_cov_mcdc) + "/" + str(pkg_total_mcdc) + ")" + package.attrib['mcdcpair-coverage'] = mcdcPairPercentStr + if file.has_function_call_coverage: + funcCallPercentStr = "{:.2f}".format(FC_rate * 100.0) + "% (" + str(pkg_cov_fc) + "/" + str(pkg_total_fc) + ")" + package.attrib['functioncall-coverage'] = funcCallPercentStr + + if pkg_total_func > 0: + funcPercentStr = "{:.2f}".format(func_rate * 100.0) + "% (" + str(pkg_cov_func) + "/" + str(pkg_total_func) + ")" + package.attrib['function-coverage'] = funcPercentStr + package.attrib['complexity'] = str(pkg_vg) + + branch_rate = -1.0 + statement_rate = -1.0 + line_rate = -1.0 + func_rate = -1.0 + FC_rate = -1.0 + MCDC_rate = -1.0 + + if total_st > 0: + statement_rate = float(cov_st) / float(total_st) + + if total_lines > 0: + line_rate = float(cov_lines) / float(total_lines) + + if total_br > 0: + branch_rate = float(cov_br) / float(total_br) + + if total_mcdc > 0: + MCDC_rate = float(cov_mcdc) / float(total_mcdc) + + if total_func > 0: + func_rate = float(cov_func) / float(total_func) + + if total_fc > 0: + FC_rate = float(cov_fc) / float(total_fc) + + + return total_st, cov_st, total_lines, cov_lines, total_br, cov_br, total_func, cov_func, total_fc, cov_fc, total_mcdc, cov_mcdc, branch_rate, statement_rate, line_rate, func_rate, FC_rate, MCDC_rate, vg + + +def generateCoverageResults(inFile, azure, xml_data_dir = "xml_data"): + + #coverage results + coverages=etree.Element("coverage") + + sources = etree.SubElement(coverages, "sources") + packages = etree.SubElement(coverages, "packages") + name = os.path.splitext(os.path.basename(inFile))[0] + + complexity = 0 + branch_rate, line_rate, func_rate, FC_rate, MCDC_rate = 0.0, 0.0, 0.0, 0.0, 0.0 + total_br, total_st, total_func, total_fc, total_mcdc = 0, 0, 0, 0, 0 + + if inFile.endswith(".vce"): + api=UnitTestApi(inFile) + cdb = api.environment.get_coverdb_api() + total_st, cov_st, total_lines, cov_lines, total_br, cov_br, total_func, cov_func, total_fc, cov_fc, total_mcdc, cov_mcdc, branch_rate, statement_rate, line_rate, func_rate, FC_rate, MCDC_rate, complexity = runCoberturaResults(packages, cdb, False) + elif inFile.endswith(".vcp"): + api=CoverAPI(inFile) + else: + total_st, cov_st, total_lines, cov_lines, total_br, cov_br, total_func, cov_func, total_fc, cov_fc, total_mcdc, cov_mcdc, branch_rate, statement_rate, line_rate, func_rate, FC_rate, MCDC_rate, complexity = runCoverageResultsMP(packages, inFile) + + if line_rate != -1.0: coverages.attrib['line-rate'] = str(line_rate) + if statement_rate != -1.0: coverages.attrib['statement-rate'] = str(statement_rate) + if branch_rate != -1.0: coverages.attrib['branch-rate'] = str(branch_rate) + if MCDC_rate != -1.0: coverages.attrib['mcdcpair-coverage-rate'] = str(MCDC_rate) + if func_rate != -1.0: coverages.attrib['function-coverage-rate'] = str(func_rate) + if FC_rate != -1.0: coverages.attrib['functioncall-coverage-rate'] = str(FC_rate) + from datetime import datetime + coverages.attrib['timestamp'] = str(datetime.now()) + + tool_version = os.path.join(os.environ['VECTORCAST_DIR'], "DATA", "tool_version.txt") + with open(tool_version,"r") as fd: + ver = fd.read() + + coverages.attrib['version'] = "VectorCAST " + ver.rstrip() + + if azure: + if line_rate != -1.0: coverages.attrib['lines-covered'] = str(cov_st) + if line_rate != -1.0: coverages.attrib['lines-valid'] = str(total_st) + if branch_rate != -1.0: coverages.attrib['branches-covered'] = str(cov_br) + if branch_rate != -1.0: coverages.attrib['branches-valid'] = str(total_br) + + if line_rate != -1.0: print ("lines: {:.2f}% ({:d} out of {:d})".format(line_rate*100.0, cov_lines, total_lines)) + if statement_rate != -1.0: print ("statements: {:.2f}% ({:d} out of {:d})".format(statement_rate*100.0, cov_st, total_st)) + if branch_rate != -1.0: print ("branches: {:.2f}% ({:d} out of {:d})".format(branch_rate*100.0, cov_br, total_br)) + if func_rate != -1.0: print ("functions: {:.2f}% ({:d} out of {:d})".format(func_rate*100.0, cov_func, total_func)) + if FC_rate != -1.0: print ("function calls: {:.2f}% ({:d} out of {:d})".format(FC_rate*100.0, cov_fc, total_fc)) + if MCDC_rate != -1.0: print ("mcdc pairs: {:.2f}% ({:d} out of {:d})".format(MCDC_rate*100.0, cov_mcdc, total_mcdc)) + + if statement_rate != -1.0: print ("coverage: {:.2f}% of statements".format(statement_rate*100.0)) + print ("complexity: {:d}".format(complexity)) + source = etree.SubElement(sources, "source") + source.text = "./" + + cob_data_dir = os.path.join(xml_data_dir,"cobertura") + if not os.path.exists(cob_data_dir): + os.makedirs(cob_data_dir) + + write_xml(coverages, os.path.join(cob_data_dir,"coverage_results_" + name)) + +if __name__ == '__main__': + + inFile = sys.argv[1] + try: + if "--azure" == sys.argv[2]: + azure = True + print ("using azure mode") + else: + azure = False + except Exception as e: + azure = False + + generateCoverageResults(inFile, azure, "cov_plugin") + + diff --git a/src/main/resources/scripts/create_index_html.py b/src/main/resources/scripts/create_index_html.py new file mode 100644 index 00000000..843a1f23 --- /dev/null +++ b/src/main/resources/scripts/create_index_html.py @@ -0,0 +1,181 @@ +import os +import sys +import argparse +import glob + +report_style="html{line-height:1.15;-webkit-text-size-adjust:100%}\n" \ +"body{margin:0}\n" \ +"h1{font-size:2em;margin:.67em 0}\n" \ +"hr{box-sizing:content-box;height:0;overflow:visible}\n" \ +"pre{font-family:monospace,monospace;font-size:1em}\n" \ +"a{background-color:transparent}\n" \ +"abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}\n" \ +"b,strong{font-weight:bolder}\n" \ +"code,kbd,samp{font-family:monospace,monospace;font-size:1em}\n" \ +"small{font-size:80%}\n" \ +"sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\n" \ +"sub{bottom:-.25em}\n" \ +"sup{top:-.5em}\n" \ +"img{border-style:none}\n" \ +" html {box-sizing:border-box;position:relative;height:100%;width:100%;}\n" \ +"*, *:before, *:after {box-sizing:inherit;}\n" \ +"body {position:relative;height:100%;width:100%;font-size:10pt;font-family:helvetica, Arial, sans-serif;color:#3a3e3f;}\n" \ +".alternate-font {font-family:Arial Unicode MS, Arial, sans-serif;}\n" \ +"#page {position:relative;width:100%;height:100%;overflow:hidden;}\n" \ +"#title-bar {position:absolute;top:0px;left:0em;right:0px;height:1.8em;background-color:#B1B6BA;white-space:nowrap;box-shadow:1px 1px 5px black;z-index:100;}\n" \ +"#report-title {font-size:3em;text-align:center;font-weight:bold;background-color:white;padding:0.5em;margin-bottom:0.75em;border:1px solid #e5e5e5;}\n" \ +".contents-block {position:absolute;top:1.8em;left:0em;width:XXem;bottom:0em;overflow:auto;background-color:#DADEE1;border-right:1px solid silver;padding-left:0.75em;padding-right:0.5em;}\n" \ +".report-body {position:absolute;top:1.8em;left:22em;right:0em;bottom:0em;padding-left:2em;padding-right:2em;overflow:auto;padding-bottom:1.5em;background-color:#DADEE1;}\n" \ +".report-body.no-toc {left:0em;}\n" \ +".report-body > .report-block, .report-body > .report-block-coverage, .report-body > .report-block-scroll, .report-body > .testcase {border:1px solid #e5e5e5;margin-bottom:2em;padding-bottom:1em;padding-right:2em;background-color:white;padding-left:2em;padding-top:0.1em;margin-top:1em;}\n" \ +".report-body > .report-block-scroll {overflow-x:visible;background-color:inherit;}\n" \ +".title-bar-heading {display:none;position:absolute;text-align:center;width:100%;color:white;font-size:3em;bottom:0px;margin-bottom:0.3em;}\n" \ +".title-bar-logo {display:inline-block;height:100%;}\n" \ +".title-bar-logo img {width:120px;margin-left:0.5em;margin-top:-16px;}\n" \ +".contents-block ul {padding-left:1.5em;list-style-type:none;line-height:1.5;}\n" + +report_title=" \n" \ +'
\n' \ +' \n' \ +'
\n' + +class cd: + """Context manager for changing the current working directory""" + def __init__(self, newPath): + self.newPath = os.path.expanduser(newPath) + + def __enter__(self): + self.savedPath = os.getcwd() + os.chdir(self.newPath) + + def __exit__(self, etype, value, traceback): + os.chdir(self.savedPath) + +def getReportName(filename): + + reportName = filename + + if "aggregate" in filename: + manageProject = filename.split("_aggregate",1)[0] + reportName = " Aggregate Coverage Report" + + elif "environment" in filename: + manageProject = filename.split("_environment",1)[0] + reportName = " Environment Report" + + elif "manage_incremental_rebuild_report" in filename: + manageProject = filename.split("_manage_incremental_rebuild_report",1)[0] + reportName = "Incremental Report Report" + + elif "metrics" in filename: + manageProject = filename.split("_metrics",1)[0] + reportName = " Metrics Report" + + elif "html_reports" in filename: + ## html_reports/VectorCAST_MinGW_C++_UnitTesting_ENV_LINKED_LIST.html + comp_ts_env = filename.replace("html_reports/","").replace(".html","") + reportName = "Full Report: "+ comp_ts_env + + return reportName + +def create_index_html (html_file_list): + + ## No idea what this is for + global report_style + global report_title + maxlen = 1 + for html_file_name in html_file_list : + if len(html_file_name) > maxlen : + maxlen = len(html_file_name) + # somewhat ad-hoc calculation + maxlen /= 2 + maxlen += 4 + + indexHtmlText = "" + + indexHtmlText += "\n" + indexHtmlText += "\n" + indexHtmlText += '\n' + indexHtmlText += " \n" + indexHtmlText += " Index\n" + indexHtmlText += ' \n' + indexHtmlText += " \n" + indexHtmlText += " \n" + indexHtmlText += " \n" + + indexHtmlText += report_title + + indexHtmlText += " \n" + indexHtmlText += "
\n" +# indexHtmlText += ' ' + indexHtmlText += "

VectorCAST HTML Reports

\n" + + indexHtmlText += " \n" + indexHtmlText += " \n" + + for html_file_name in html_file_list: + reportName = getReportName(html_file_name) + line = ' \n'.format(html_file_name, reportName) + indexHtmlText += line + + indexHtmlText += " \n" + indexHtmlText += "
{}
\n" + indexHtmlText += "
\n" + + indexHtmlText += " \n" + + indexHtmlText += " \n" + indexHtmlText += "\n" + + return indexHtmlText + +def run(html_file_list): + + print("Creating index.html for VectorCAST Project Reports") + + if len(html_file_list) > 0: + indexHtmlText = create_index_html (html_file_list) + + else: + print("No HTML reports found") + return 1 + + try: + with open("index.html", 'w') as fd: + fd.write(indexHtmlText) + except: + print("Unable to write to index.html") + return 1 + + return 0 + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("--html_base_dir", help='Set the base directory of the html_reports directory. The default is the workspace directory', default = "html_reports") + args = parser.parse_args() + + try: + prj_dir = os.environ['CI_PROJECT_DIR'].replace("\\","/") + "/" + except: + prj_dir = os.getcwd().replace("\\","/") + "/" + + tempHtmlReportList = glob.glob("*.html") + tempHtmlReportList += glob.glob(os.path.join(args.html_base_dir, "*.html")) + htmlReportList = [] + + for report in tempHtmlReportList: + if "index.html" not in report: + report = report.replace("\\","/") + report = report.replace(prj_dir,"") + htmlReportList.append(report) + + return run(htmlReportList) + +if __name__ == "__main__" : + ret = main() + sys.exit (ret) \ No newline at end of file From d4242cf563a003d1ff0c7b5308903408fffe0fed Mon Sep 17 00:00:00 2001 From: TimSVector Date: Mon, 3 Jun 2024 09:32:59 -0400 Subject: [PATCH 003/112] adding new sonarqube script --- .../scripts/generate_sonarqube_testresults.py | 853 ++++++++++++++++++ 1 file changed, 853 insertions(+) create mode 100644 src/main/resources/scripts/generate_sonarqube_testresults.py diff --git a/src/main/resources/scripts/generate_sonarqube_testresults.py b/src/main/resources/scripts/generate_sonarqube_testresults.py new file mode 100644 index 00000000..2ee3ae71 --- /dev/null +++ b/src/main/resources/scripts/generate_sonarqube_testresults.py @@ -0,0 +1,853 @@ +# +# The MIT License +# +# Copyright 2016 Vector Software, East Greenwich, Rhode Island USA +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# + +from __future__ import print_function + +import os +from datetime import datetime +try: + from html import escape +except ImportError: + # html not standard module in Python 2. + from cgi import escape +import sys +# Later version of VectorCAST have renamed to Unit Test API +# Try loading the newer (renamed) version first and fall back +# to the older. +try: + from vector.apps.DataAPI.unit_test_api import UnitTestApi + from vector.apps.DataAPI.unit_test_models import TestCase +except: + from vector.apps.DataAPI.api import Api as UnitTestApi + from vector.apps.DataAPI.models import TestCase + +try: + from vector.apps.DataAPI.vcproject_api import VCProjectApi +except: + pass + +from vector.enums import ENVIRONMENT_STATUS_TYPE_T + +from vector.apps.DataAPI.cover_api import CoverApi +from vector.apps.ReportBuilder.custom_report import fmt_percent +from operator import attrgetter +import hashlib +import traceback +from pprint import pprint +try: + from vector.apps.ReportBuilder.custom_report import CustomReport +except: + pass + +import re +from enum import Enum + +def dummy(*args, **kwargs): + return None + +class TC_STATUS(Enum): + NONE = 0 + PASS = 1 + FAIL = 2 + ERROR = 3 + SKIPPED = 4 + NOT_APPLICABLE = 5 + +xml_status = ["N/A","PASS","FAIL","ERROR","N/A","N/A"] + +########################################################################## +# This class generates the XML (JUnit based) report for the overall +# +class BaseGenerateXml(object): + def __init__(self, FullManageProjectName, verbose, xml_data_dir = "xml_data"): + projectName = os.path.splitext(os.path.basename(FullManageProjectName))[0] + self.manageProjectName = projectName + self.xml_data_dir = xml_data_dir + self.unit_report_name = os.path.join(self.xml_data_dir,"sonarqube","test_results_"+ self.manageProjectName + ".xml") + self.verbose = verbose + self.print_exc = False + + self.test_id = 1 + + # get the VC langaguge and encoding + self.encFmt = 'utf-8' + from vector.apps.DataAPI.configuration import vcastqt_global_options + self.lang = vcastqt_global_options.get('Translator','english') + if self.lang == "english": + self.encFmt = "utf-8" + if self.lang == "japanese": + self.encFmt = "shift-jis" + if self.lang == "chinese": + self.encFmt = "GBK" + + self.failDict = {} + self.passDict = {} + self.api = None + + try: + prj_dir = os.environ['CI_PROJECT_DIR'].replace("\\","/") + "/" + except: + prj_dir = os.getcwd().replace("\\","/") + "/" + + self.workspace = prj_dir + + def dump(self,obj): + if hasattr(obj, '__dict__'): + return vars(obj) + else: + try: + return {attr: getattr(obj, attr, None) for attr in obj.__slots__} + except: + return str(obj) + + def convertTHStatus(self, status): + + convertDict = {'TEST_HISTORY_FAILURE_REASON_DATA_SKEW_UNDERFLOW': 'Data Skew Underflow', + 'TEST_HISTORY_FAILURE_REASON_DATA_SKEW_OVERFLOW': 'Data Skew Overflow', + 'TEST_HISTORY_FAILURE_REASON_HARNESS_FAILURE': 'Harness Failure', + 'TEST_HISTORY_FAILURE_REASON_THISTORY_FILE_DOES_NOT_EXIST': 'Thistory File Does Not Exist', + 'TEST_HISTORY_FAILURE_REASON_INSUFFICIENT_HEAP_SIZE': 'Insufficient Heap Size', + 'TEST_HISTORY_FAILURE_REASON_LIBRARY_MALLOC_FAILED': 'Library Malloc Failed', + 'TEST_HISTORY_FAILURE_REASON_THISTORY_LINE_INVALID': 'Thistory Line Invalid', + 'TEST_HISTORY_FAILURE_REASON_THISTORY_ENDED_PREMATURELY': 'Thistory Ended Prematurely', + 'TEST_HISTORY_FAILURE_REASON_EXPECTED_ENDED_PREMATURELY': 'Expected Ended Prematurely', + 'TEST_HISTORY_FAILURE_REASON_HARNESS_COMMNAD_INVALID': 'Harness Commnad Invalid', + 'TEST_HISTORY_FAILURE_REASON_TEST_HISTORY_OUTPUT_FILES_CONTAIN_ERROR':'Test History Output Files Contain Error', + 'TEST_HISTORY_FAILURE_REASON_STRICT_IMPORT_FAILED': 'Strict Import Failed', + 'TEST_HISTORY_FAILURE_REASON_MACRO_NOT_FOUND': 'Macro Not Found', + 'TEST_HISTORY_FAILURE_REASON_SYMBOL_OR_MACRO_NOT_FOUND': 'Symbol Or Macro Not Found', + 'TEST_HISTORY_FAILURE_REASON_SYMBOL_OR_MACRO_TYPE_MISMATCH': 'Symbol Or Macro Type Mismatch', + 'TEST_HISTORY_FAILURE_REASON_EMPTY_TESTCASES': 'Empty Testcases', + 'TEST_HISTORY_FAILURE_REASON_NO_EXPECTED_RETURN': 'No Expected Return', + 'TEST_HISTORY_FAILURE_REASON_NO_EXPECTED_VALUES': 'No Expected Values', + 'TEST_HISTORY_FAILURE_REASON_EXECUTABLE_MISSING': 'Executable Missing', + 'TEST_HISTORY_FAILURE_REASON_MAX_VARY_EXCEEDED': 'Max Vary Exceeded', + 'TEST_HISTORY_FAILURE_REASON_TRUNCATED_HARNESS_DATA': 'Truncated Harness Data', + 'TEST_HISTORY_FAILURE_REASON_HARNESS_STDOUT_DATA_UNDERFLOW': 'Harness Stdout Data Underflow', + 'TEST_HISTORY_FAILURE_REASON_MAX_STRING_LENGTH_EXCEEDED': 'Max String Length Exceeded', + 'TEST_HISTORY_FAILURE_REASON_MAX_TARGET_FILES_EXCEEDED': 'Max Target Files Exceeded', + 'TEST_HISTORY_FAILURE_TIMEOUT_EXCEEDED': 'Timeout Exceeded' + } + + try: + s = convertDict[str(status)] + except: + s = convertDict[status] + return s + + def convertExecStatusToEnum(self, status): + convertDict = { 'EXEC_SUCCESS_PASS' : TC_STATUS.PASS, + 'EXEC_SUCCESS_FAIL' : TC_STATUS.FAIL, + 'EXEC_SUCCESS_NONE' : TC_STATUS.PASS, + 'EXEC_EXECUTION_FAILED' : TC_STATUS.FAIL, + 'EXEC_ABORTED' : TC_STATUS.FAIL, + 'EXEC_TIMEOUT_EXCEEDED' : TC_STATUS.FAIL, + 'EXEC_VXWORKS_LOAD_ERROR' : TC_STATUS.ERROR, + 'EXEC_USER_CODE_COMPILE_FAILED' : TC_STATUS.ERROR, + 'EXEC_COMPOUND_ONLY' : TC_STATUS.ERROR, + 'EXEC_STRICT_IMPORT_FAILED' : TC_STATUS.ERROR, + 'EXEC_MACRO_NOT_FOUND' : TC_STATUS.ERROR, + 'EXEC_SYMBOL_OR_MACRO_NOT_FOUND' : TC_STATUS.ERROR, + 'EXEC_SYMBOL_OR_MACRO_TYPE_MISMATCH' : TC_STATUS.ERROR, + 'EXEC_MAX_VARY_EXCEEDED' : TC_STATUS.ERROR, + 'EXEC_COMPOUND_WITH_NO_SLOTS' : TC_STATUS.ERROR, + 'EXEC_COMPOUND_WITH_ZERO_ITERATIONS' : TC_STATUS.ERROR, + 'EXEC_STRING_LENGTH_EXCEEDED' : TC_STATUS.ERROR, + 'EXEC_FILE_COUNT_EXCEEDED' : TC_STATUS.ERROR, + 'EXEC_EMPTY_TESTCASE' : TC_STATUS.ERROR, + 'EXEC_NO_EXPECTED_RETURN' : TC_STATUS.FAIL, + 'EXEC_NO_EXPECTED_VALUES' : TC_STATUS.FAIL, + 'EXEC_CSV_MAP' : TC_STATUS.NOT_APPLICABLE, + 'EXEC_DRIVER_DATA_COMPILE_FAILED' : TC_STATUS.ERROR, + 'EXEC_RECURSIVE_COMPOUND' : TC_STATUS.ERROR, + 'EXEC_SPECIALIZED_COMPOUND_CONTAINING_COMMON' : TC_STATUS.ERROR, + 'EXEC_COMMON_COMPOUND_CONTAINING_SPECIALIZED' : TC_STATUS.ERROR, + 'EXEC_HIDING_EXPECTED_RESULTS' : TC_STATUS.ERROR, + 'INVALID_TEST_CASE' : TC_STATUS.ERROR, + } + try: + s = convertDict[str(status)] + except: + s = convertDict[status] + return s + + def convertExecStatusToStr(self, status): + convertDict = { 'EXEC_SUCCESS_PASS':'Testcase passed', + 'EXEC_SUCCESS_FAIL':'Testcase failed on expected values', + 'EXEC_SUCCESS_NONE':'No expected results', + 'EXEC_EXECUTION_FAILED':'Testcase failed to run to completion (possible testcase timeout)', + 'EXEC_ABORTED':'User aborted testcase', + 'EXEC_TIMEOUT_EXCEEDED':'Testcase timeout', + 'EXEC_VXWORKS_LOAD_ERROR':'VxWorks load error', + 'EXEC_USER_CODE_COMPILE_FAILED':'User code failed to compile', + 'EXEC_COMPOUND_ONLY':'Compound only test case', + 'EXEC_STRICT_IMPORT_FAILED':'Strict Testcase Import Failure', + 'EXEC_MACRO_NOT_FOUND':'Macro not found', + 'EXEC_SYMBOL_OR_MACRO_NOT_FOUND':'Symbol or macro not found', + 'EXEC_SYMBOL_OR_MACRO_TYPE_MISMATCH':'Symbol or macro type mismatch', + 'EXEC_MAX_VARY_EXCEEDED':'Maximum varied parameters exceeded', + 'EXEC_COMPOUND_WITH_NO_SLOTS':'Compound with no slot', + 'EXEC_COMPOUND_WITH_ZERO_ITERATIONS':'Compound with zero slot', + 'EXEC_STRING_LENGTH_EXCEEDED':'Maximum string length exceeded', + 'EXEC_FILE_COUNT_EXCEEDED':'Maximum file count exceeded', + 'EXEC_EMPTY_TESTCASE':'Empty testcase', + 'EXEC_NO_EXPECTED_RETURN':'No expected return value', + 'EXEC_NO_EXPECTED_VALUES':'No expected values', + 'EXEC_CSV_MAP':'CSV Map', + 'EXEC_DRIVER_DATA_COMPILE_FAILED':'Driver data failed to compile', + 'EXEC_RECURSIVE_COMPOUND':'Recursive Compound Test', + 'EXEC_SPECIALIZED_COMPOUND_CONTAINING_COMMON':'Specialized compound containing non-specialized testcases', + 'EXEC_COMMON_COMPOUND_CONTAINING_SPECIALIZED':'Non-specialized compound containing specialized testcases', + 'EXEC_HIDING_EXPECTED_RESULTS':'Hiding expected results', + 'INVALID_TEST_CASE':'Invalid Test Case' + } + try: + s = convertDict[str(status)] + except: + s = convertDict[status] + return s + +# +# BaseGenerateXml - generate the formatted timestamp to write to the coverage file +# + def get_timestamp(self): + dt = datetime.now() + hour = dt.hour + if hour > 12: + hour -= 12 + return dt.strftime('%d %b %Y @HR@:%M:%S %p').upper().replace('@HR@', str(hour)) + + + +########################################################################## +# This class generates the XML (JUnit based) report for the overall +# +class GenerateManageXml (BaseGenerateXml): + +# GenerateManageXml + + def __init__(self, FullManageProjectName, verbose = False, + cbtDict = None, + generate_exec_rpt_each_testcase = True, + skipReportsForSkippedEnvs = False, + report_failed_only = False, + no_full_reports = False, + print_exc = False, + xml_data_dir = "xml_data"): + + super(GenerateManageXml, self).__init__(FullManageProjectName, verbose, xml_data_dir) + + self.api = VCProjectApi(FullManageProjectName) + + self.FullManageProjectName = FullManageProjectName + self.generate_exec_rpt_each_testcase = generate_exec_rpt_each_testcase + self.skipReportsForSkippedEnvs = skipReportsForSkippedEnvs + self.report_failed_only = report_failed_only + self.cbtDict = cbtDict + self.no_full_reports = no_full_reports + self.error_count = 0 + self.failed_count = 0 + self.error_count = 0 + self.passed_count = 0 + self.print_exc = print_exc + + self.fh_data = "" + + self.cleanupXmlDataDir() + + def cleanupXmlDataDir(self): + path=os.path.join(self.xml_data_dir,"sonarqube") + import glob + # if the path exists, try to delete all file in it + if os.path.isdir(path): + for file in glob.glob(path + "/*.*"): + try: + os.remove(file); + except: + print(" *INFO: File System Error removing file after failed to remove directory: " + path + "/" + file + ". Check console for environment build/execution errors") + if print_exc: traceback.print_exc() + + # we should either have an empty directory or no directory + else: + try: + os.makedirs(path) + except: + print("failed making path: " + path) + print(" *INFO: File System Error creating directory: " + path + ". Check console for environment build/execution errors") + if print_exc: traceback.print_exc() + + def __del__(self): + try: + self.api.close() + except: + pass + + def generate_local_results(self, results, key): + # get the level from the name + + if len(key.split("/")) != 3: + comp, ts, group, env_name = key.split("/") + else: + comp, ts, env_name = key.split("/") + + env_key = comp + "/" + ts + "/" + env_name + + env = self.api.project.environments[env_key] + env_def = self.api.project.environments[env_key].definition + + build_dir = os.path.join(self.api.project.workspace,env.relative_working_directory) + vceFile = os.path.join(build_dir, env.name+".vce") + + xmlUnitReportName = os.path.join(self.xml_data_dir, "sonarqube", "test_results_" + key.replace("/","_") + ".xml") + + localXML = GenerateXml(self.FullManageProjectName, build_dir, env_name, comp, ts, + key, xmlUnitReportName, None, None, False, + self.cbtDict, + self.generate_exec_rpt_each_testcase, + self.skipReportsForSkippedEnvs, + self.report_failed_only, + self.print_exc, + xml_data_dir = self.xml_data_dir) + + localXML.topLevelAPI = self.api + localXML.failDict = self.failDict + localXML.passDict = self.passDict + localXML.failed_count = self.failed_count + localXML.error_count = self.error_count + localXML.passed_count = self.passed_count + localXML.test_id = self.test_id + localXML.generate_unit() + self.failDict = localXML.failDict + self.passDict = localXML.passDict + self.failed_count = localXML.failed_count + self.error_count = localXML.error_count + self.passed_count = localXML.passed_count + self.test_id = localXML.test_id + del localXML + + +# GenerateManageXml + def generate_testresults(self): + results = self.api.project.repository.get_full_status([]) + all_envs = [] + for env in self.api.Environment.all(): + all_envs.append(env.level._full_path) + + if results['ALL']['testcase_results'] == {}: + return + + self.localDataOnly = True + for result in results: + if result in all_envs: + if len(result.split("/")) != 3: + comp, ts, group, env_name = result.split("/") + else: + comp, ts, env_name = result.split("/") + env.level._full_path + + env_to_investigate = self.api.Environment.filter(level___full_path__equals=result) + + try: + testPath = env_to_investigate[0].build_directory + "/" + env_to_investigate[0].name + if not os.path.exists(testPath): + print("SQ: Skipping environment: "+ env_to_investigate[0].name) + print("SQ: *Missing path for environment: " + env_to_investigate[0].name) + print("SQ: Expected Path: " + testPath) + continue + if env_to_investigate[0].api.environment.status != ENVIRONMENT_STATUS_TYPE_T.NORMAL: + print("SQ: Skipping environment: "+ env_to_investigate[0].name) + print("SQ: *" + env_to_investigate[0].name + " status is not NORMAL") + continue + except: + print(" Skipping environment: "+ env_to_investigate[0].name) + print(" *Unable to open DataAPI") + continue + + + if isinstance(env_to_investigate[0].api, UnitTestApi): + uname = (env_to_investigate[0].api.TestCase.first().unit_display_name) + fname = (env_to_investigate[0].api.TestCase.first().function_display_name) + + if results[result]['local'] != {}: + self.generate_local_results(results,result) + else: + for key in results[result]['imported'].keys(): + self.localDataOnly = False + importedResult = results[result]['imported'][key] + total = importedResult['testcase_results']['total_count'] + success = importedResult['testcase_results']['success_count'] + failed = total - success + importName = importedResult['name'] + classname = "ImportedResults." + importName + "." + comp + "." + ts + "." + env_name + classname = comp + "." + ts + "." + env_name + for idx in range(1,success+1): + tc_name_full = "ImportedResults." + importName + ".TestCase.PASS.%03d" % idx + + p1 = " \n" % (self.test_id) + p2 = " %s\n" % (tc_name_full) + p3 = " \n" + p4 = " \n" + + self.passDict[tc_name_full] = p1 + p2 + p3 + p4 + self.passed_count += 1 + self.test_id += 1 + + for idx in range(1,failed+1): + tc_name_full = "ImportedResults." + importName + ".TestCase.FAIL.%03d" % idx + + f1 = " \n" % (self.test_id) + f2 = " %sn" % (tc_name_full) + f3 = " Failure\n" + f4 = " \n" + f5 = " \n" + + self.failDict[tc_name_full] = f1 + f2 + f4 + f4 + f5 + self.failed_count += 1 + self.test_id += 1 + + self.write_cppunit_data() + + + + def write_cppunit_data(self): + + ### sort and output the fhdata here + + self.fh_data = "\n" + self.fh_data += "\n" + + self.fh_data += " \n" + for key in self.failDict: + self.fh_data += self.failDict[key] + self.fh_data += " \n" + + self.fh_data += " \n" + for key in self.passDict: + self.fh_data += self.passDict[key] + self.fh_data += " \n" + + self.fh_data += " \n" + self.fh_data += " %d\n" % (self.passed_count + self.failed_count + self.error_count) + self.fh_data += " %d\n" % (self.error_count + self.failed_count) + self.fh_data += " %d\n" % (self.error_count ) + self.fh_data += " %d\n" % (self.failed_count) + self.fh_data += " \n" + + self.fh_data += "\n" + + with open(self.unit_report_name, "w") as fd: + fd.write(self.fh_data) + + + +########################################################################## +# This class generates the XML (Junit based) report for dynamic tests and +# +# In both cases these are for a single environment +# +class GenerateXml(BaseGenerateXml): + + def __init__(self, FullManageProjectName, build_dir, env, compiler, testsuite, jenkins_name, unit_report_name, jenkins_link, jobNameDotted, verbose = False, cbtDict= None, generate_exec_rpt_each_testcase = True, skipReportsForSkippedEnvs = False, report_failed_only = False, print_exc = False, xml_data_dir = "xml_data"): + super(GenerateXml, self).__init__(FullManageProjectName, verbose, xml_data_dir = xml_data_dir) + + self.cbtDict = cbtDict + self.FullManageProjectName = FullManageProjectName + self.generate_exec_rpt_each_testcase = generate_exec_rpt_each_testcase + self.skipReportsForSkippedEnvs = skipReportsForSkippedEnvs + self.report_failed_only = report_failed_only + self.print_exc = print_exc + self.topLevelAPI = None + + ## use hash code instead of final directory name as regression scripts can have overlapping final directory names + + build_dir_4hash = build_dir.upper() + build_dir_4hash = "/".join(build_dir_4hash.split("/")[-2:]) + + # Unicode-objects must be encoded before hashing in Python 3 + if sys.version_info[0] >= 3: + build_dir_4hash = build_dir_4hash.encode(self.encFmt) + + self.hashCode = hashlib.md5(build_dir_4hash).hexdigest() + + if verbose: + print ("gen Dir: " + str(build_dir_4hash)+ " Hash: " +self.hashCode) + + #self.hashCode = build_dir.split("/")[-1].upper() + self.build_dir = build_dir + self.env = env + self.compiler = compiler + self.testsuite = testsuite + self.jenkins_name = jenkins_name + self.unit_report_name = os.path.join(self.xml_data_dir,"sonarqube","test_results_"+ self.manageProjectName + ".xml") + self.jenkins_link = jenkins_link + self.jobNameDotted = jobNameDotted + cov_path = os.path.join(build_dir,env + '.vcp') + unit_path = os.path.join(build_dir,env + '.vce') + if os.path.exists(cov_path): + self.api = CoverApi(cov_path) + elif os.path.exists(unit_path): + self.api = UnitTestApi(unit_path) + else: + self.api = None + if verbose: + print("Error: Could not determine project type for {}/{}".format(build_dir, env)) + print(" {}/{}/{}".format(compiler, testsuite, env)) + return + + self.api.commit = dummy + self.failed_count = 0 + self.passed_count = 0 + self.test_id = 0 + + +# +# GenerateXml - add any compound tests to the unit report +# + def add_compound_tests(self): + for tc in self.api.TestCase.all(): + if tc.kind == TestCase.KINDS['compound']: + if not tc.for_compound_only: + self.write_testcase(tc, "<>", "<>") + +# +# GenerateXml - add any intialisation tests to the unit report +# + def add_init_tests(self): + for tc in self.api.TestCase.all(): + if tc.kind == TestCase.KINDS['init']: + if not tc.for_compound_only: + self.write_testcase(tc, "<>", "<>") + +# +# GenerateXml - Find the test case file +# + def generate_unit(self): + + if self.topLevelAPI == None: + self.start_test_results_file() + + if isinstance(self.api, CoverApi): + try: + if self.topLevelAPI == None: + api = VCProjectApi(self.FullManageProjectName) + else: + api = self.topLevelAPI + + for env in api.Environment.all(): + if env.compiler.name == self.compiler and env.testsuite.name == self.testsuite and env.name == self.env and env.system_tests: + for st in env.system_tests: + pass_fail_rerun = "" + if st.run_needed and st.type == 2: #SystemTestType.MANUAL: + pass_fail_rerun = ": Manual system tests can't be run in Jenkins" + elif st.run_needed: + pass_fail_rerun = ": Needs to be executed" + elif st.passed: + pass_fail_rerun = ": Passed" + else: + pass_fail_rerun = ": Failed" + + level = env.compiler.name + "/" + env.testsuite.name + "/" + env.name + if self.verbose: + print (level, st.name, pass_fail_rerun) + self.write_testcase(st, level, st.name, env.definition.is_monitored) + + # callStr = os.getenv('VECTORCAST_DIR') + os.sep + "manage -p " + self.FullManageProjectName + " --system-tests-status=" + self.manageProjectName + "_system_tests_status.html" + # p = subprocess.Popen(callStr, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) + # out, err = p.communicate() + + if self.topLevelAPI == None: + api.close() + + except ImportError as e: + from generate_qa_results_xml import genQATestResults + pc,fc = genQATestResults(self.FullManageProjectName, self.compiler+ "/" + self.testsuite, self.env, True, self.encFmt) + self.failed_count += fc + self.passed_count += pc + self.test_id += pc + fc + return + + else: + try: + self.add_compound_tests() + self.add_init_tests() + for unit in self.api.Unit.all(): + if unit.is_uut: + for func in unit.functions: + if not func.is_non_testable_stub: + for tc in func.testcases: + try: + vctMap = tc.is_vct_map + except: + vctMap = False + if not tc.is_csv_map and not vctMap: + if not tc.for_compound_only or tc.testcase_status == "TCR_STRICT_IMPORT_FAILED": + self.write_testcase(tc, tc.function.unit.name, tc.function.display_name) + + except AttributeError as e: + traceback.print_exc() + + if self.topLevelAPI == None: + self.end_test_results_file() +# +# GenerateXml - write the end of the jUnit XML file and close it +# + def start_test_results_file(self): + self.fh_data = "\n" + self.fh_data += "\n" + + def end_test_results_file(self): + self.fh_data += "\n" + + with open(self.unit_report_name, "w") as fd: + fd.write(self.fh_data) + +# +# GenerateXml - start the JUnit XML file +# + + def testcase_failed(self, tc): + + try: + from vector.apps.DataAPI.manage_models import SystemTest + if (isinstance(tc, SystemTest)): + if tc.run_needed and tc.type == 2: + return False + elif tc.run_needed: + return False + elif tc.passed == tc.total: + return False + else: + return True + except: + pass + + if not tc.passed: + return True + + return False + +# +# GenerateXml - write a testcase to the jUnit XML file +# + def write_testcase(self, tc, unit_name, func_name, st_is_monitored = False): + + ## + ## + ## + ## + ## + ## + ## + ## + ## + ## + ## + ## + ## + ## + + + isSystemTest = False + + try: + from vector.apps.DataAPI.manage_models import SystemTest + if (isinstance(tc, SystemTest)): + isSystemTest = True + except: + pass + + tc_time = "0" + + if not isSystemTest and tc.function: + if tc.end_time and tc.start_time: + tc_time = str(int((tc.end_time - tc.start_time).total_seconds())) + + failure_message = "" + + if self.report_failed_only and not self.testcase_failed(tc): + return + + unit_name = escape(unit_name, quote=False) + func_name = escape(func_name, quote=True) + tc_name = escape(tc.name, quote=False) + compiler = escape(self.compiler, quote=False).replace(".","") + testsuite = escape(self.testsuite, quote=False).replace(".","") + envName = escape(self.env, quote=False).replace(".","") + + tc_name_full = unit_name + "." + func_name + "." + tc_name + + classname = compiler + "." + testsuite + "." + envName + + + tcStatus = TC_STATUS.NONE + + idx = 1 + + if isSystemTest: + if tc.run_needed and tc.type == 2: #SystemTestType.MANUAL: + tcStatus = TC_STATUS.SKIPPED + elif tc.run_needed: + tcStatus = TC_STATUS.SKIPPED + elif tc.passed == tc.total: + tcStatus = TC_STATUS.PASS + else: + tcStatus = TC_STATUS.FAIL + else: + + if tc.testcase_status != 'TCR_STATUS_OK': + tcStatus = TC_STATUS.ERROR + + if tc.passed == None: + tcStatus = TC_STATUS.SKIPPED + + elif tcStatus == TC_STATUS.NONE and not tc.passed: + tcStatus = TC_STATUS.FAIL + + elif tcStatus != TC_STATUS.ERROR: + tcStatus = TC_STATUS.PASS + + if tcStatus == TC_STATUS.PASS: + + id_name = classname + "." + tc_name + p1 = " \n" % (self.test_id) + p2 = " %s\n" % (id_name) + p3 = " \n" % (tc_time) + p4 = " \n" + + self.passDict[id_name] = p1 + p2 + p4 # + p3 + self.passed_count += 1 + + elif tcStatus == TC_STATUS.FAIL: + id_name = classname + "." + tc_name + + message = "" + + if tc.summary.expected_total > 0: + pct = '%s' % (fmt_percent(tc.summary.expected_total-tc.summary.expected_fail, tc.summary.expected_total)) + message += "Expected Results: " + pct + "% FAIL | " + + if tc.summary.control_flow_total > 0: + pct = '%s' % (fmt_percent(tc.summary.control_flow_total - tc.summary.control_flow_fail, tc.summary.control_flow_total)) + message += "Control Flow: " + pct + "% FAIL | " + + if tc.summary.signals > 0: + message += "Signals : " + str(tc.summary.signals) + " FAIL | " + + if tc.summary.unexpected_exceptions > 0: + message += "Unexpected Exceptions :" + str(tc.summary.unexpected_exceptions) + " FAIL | " + if len(message) > 0: + message = message[:-3] + f1 = " \n" % (self.test_id) + f2 = " %s\n" % (id_name ) + f3 = " Failed\n" + f4 = " " + message + "\n" + f5 = " \n" + + self.failDict[id_name] = f1 + f2 + f3 + f4 + f5 + self.failed_count += 1 + + elif tcStatus == TC_STATUS.ERROR: + id_name = classname + "." + tc_name + + message = "" + for fr in tc.failure_reasons: + message += self.convertTHStatus(fr) + " | " + if len(message) > 0: + message = message[:-3] + f1 = " \n" % (self.test_id) + f2 = " %s\n" % (id_name ) + f3 = " Error\n" + f4 = " " + message + "\n" + f5 = " \n" + + self.failDict[id_name] = f1 + f2 + f3 + f4 + f5 + self.error_count += 1 + + self.test_id += 1 + +def __generate_xml(xml_file, envPath, env, xmlCoverReportName, xmlTestingReportName): + if xml_file.api == None: + print ("\nCannot find project file (.vcp or .vce): " + envPath + "/" + env) + + else: + xml_file.generate_unit() + print ("\nJunit plugin for Jenkins compatible file generated: " + xmlTestingReportName) + +def run(FullMP, xml_data_dir = "xml_data"): + xml_file = GenerateManageXml(FullMP, xml_data_dir=xml_data_dir) + xml_file.generate_testresults() + del xml_file + +if __name__ == '__main__': + + import argparse + parser = argparse.ArgumentParser() + parser.add_argument('--project', "-p", help='VectorCAST Project name', default=None) + parser.add_argument('--environment', "-e", help='VectorCAST environment name', default=None) + parser.add_argument('-v', '--verbose', default=False, help='Enable verbose output', action="store_true") + args = parser.parse_args() + + if args.project: + if not args.project.endswith(".vcm"): + args.project += ".vcm" + + if not os.path.exists(args.project): + print("Path to VectorCAST Project not found: ", args.project) + sys.exit(-1) + + run(args.project) + + if args.environment: + envPath = os.path.dirname(os.path.abspath(args.environment)) + env = os.path.basename(args.environment) + + if env.endswith(".vcp"): + env = env[:-4] + + if env.endswith(".vce"): + env = env[:-4] + + jobNameDotted = env + jenkins_name = env + jenkins_link = env + xmlTestingReportName = "test_results_" + env + ".xml" + + xml_file = GenerateXml(env, + envPath, + env, "", "", + jenkins_name, + xmlTestingReportName, + jenkins_link, + jobNameDotted, + args.verbose, + None) + + __generate_xml( + xml_file, + envPath, + env, + xmlTestingReportName) + + + del xml_file From 035cd742f930e2b0f0777a838f92dc4e7bccdc11 Mon Sep 17 00:00:00 2001 From: TimSVector Date: Wed, 5 Jun 2024 10:47:13 -0400 Subject: [PATCH 004/112] Update to pom.xml formatting --- pom.xml | 312 +++++++++++++++++++++++++++----------------------------- 1 file changed, 148 insertions(+), 164 deletions(-) diff --git a/pom.xml b/pom.xml index 3d00d8f4..f331b539 100644 --- a/pom.xml +++ b/pom.xml @@ -1,21 +1,18 @@ 4.0.0 - org.jenkins-ci.plugins plugin 3.54 - + - VectorCAST Execution Run VectorCAST manage jobs from Jenkins vectorcast-execution 0.77-SNAPSHOT hpi https://github.com/jenkinsci/vectorcast-execution-plugin - MIT License @@ -23,7 +20,6 @@ repo - UTF-8 UTF-8 @@ -36,12 +32,10 @@ 2.56 1.6.2 - Vector Informatik, GmbH https://www.vector.com/ - TimSVector @@ -50,14 +44,12 @@ Vector Informatik, GmbH - scm:git:https://github.com/jenkinsci/vectorcast-execution-plugin.git scm:git:https://github.com/jenkinsci/vectorcast-execution-plugin.git https://github.com/jenkinsci/vectorcast-execution-plugin HEAD - repo.jenkins-ci.org @@ -70,7 +62,6 @@ https://repo.jenkins-ci.org/public/ - @@ -82,24 +73,23 @@ - - - org.jenkins-ci.plugins.workflow - workflow-aggregator - 2.5 - + + org.jenkins-ci.plugins.workflow + workflow-aggregator + 2.5 + org.jenkinsci.plugins pipeline-model-api 1.9.3 - - org.jenkins-ci.plugins.workflow - workflow-job - 1145.v7f2433caa07f - test - + + org.jenkins-ci.plugins.workflow + workflow-job + 1145.v7f2433caa07f + test + org.mockito mockito-all @@ -130,12 +120,12 @@ ${powermock.version} test - - com.google.code.findbugs - jsr305 - 3.0.1 - test - + + com.google.code.findbugs + jsr305 + 3.0.1 + test + com.google.code.findbugs annotations @@ -176,132 +166,128 @@ commons-io 2.11.0 - - io.jenkins.plugins - warnings-ng - 9.11.1 - - - org.slf4j - slf4j-api - 1.7.36 - - - org.slf4j - jcl-over-slf4j - 1.7.36 - - - org.slf4j - slf4j-simple - 1.6.2 - - - com.github.spotbugs - spotbugs-annotations - 4.6.0 - - - io.jenkins.plugins - echarts-api - 5.3.0-2 - - - org.ow2.asm - asm-analysis - 9.3 - - - org.ow2.asm - asm-tree - 9.3 - - - org.slf4j - log4j-over-slf4j - 1.7.36 - - - org.slf4j - slf4j-jdk14 - 1.7.36 - test - - - org.jenkins-ci - annotation-indexer - 1.16 - - - org.kohsuke - access-modifier-annotation - 1.27 - provided - - - org.json - json - 20230227 - - - io.jenkins.plugins - forensics-api - 1.12.0 - - - io.jenkins.plugins - bootstrap5-api - 5.1.3-6 - - - io.jenkins.plugins - data-tables-api - 1.11.4-4 - - - org.apache.commons - commons-lang3 - 3.12.0 - - - org.apache.ant - ant - 1.10.12 - - - org.hamcrest - hamcrest - 2.2 - test - - - - org.jenkins-ci.plugins - pipeline-utility-steps - - - org.codehaus.plexus - plexus-utils - 3.4.1 - - - + + io.jenkins.plugins + warnings-ng + 9.11.1 + + + org.slf4j + slf4j-api + 1.7.36 + + + org.slf4j + jcl-over-slf4j + 1.7.36 + + + org.slf4j + slf4j-simple + 1.6.2 + + + com.github.spotbugs + spotbugs-annotations + 4.6.0 + + + io.jenkins.plugins + echarts-api + 5.3.0-2 + + + org.ow2.asm + asm-analysis + 9.3 + + + org.ow2.asm + asm-tree + 9.3 + + + org.slf4j + log4j-over-slf4j + 1.7.36 + + + org.slf4j + slf4j-jdk14 + 1.7.36 + test + + + org.jenkins-ci + annotation-indexer + 1.16 + + + org.kohsuke + access-modifier-annotation + 1.27 + provided + + + org.json + json + 20230227 + + + io.jenkins.plugins + forensics-api + 1.12.0 + + + io.jenkins.plugins + bootstrap5-api + 5.1.3-6 + + + io.jenkins.plugins + data-tables-api + 1.11.4-4 + + + org.apache.commons + commons-lang3 + 3.12.0 + + + org.apache.ant + ant + 1.10.12 + + + org.hamcrest + hamcrest + 2.2 + test + + + org.jenkins-ci.plugins + pipeline-utility-steps + + + org.codehaus.plexus + plexus-utils + 3.4.1 + - - org.apache.maven.plugins - maven-release-plugin - 3.0.0-M1 + org.apache.maven.plugins + maven-release-plugin + 3.0.0-M1 - org.apache.maven.plugins - maven-scm-plugin - 1.11.2 - - connection - + org.apache.maven.plugins + maven-scm-plugin + 1.11.2 + + connection + org.apache.maven.plugins @@ -316,7 +302,6 @@ org.codehaus.mojo build-helper-maven-plugin - @@ -333,7 +318,6 @@ - org.jenkins-ci.tools maven-hpi-plugin @@ -353,25 +337,25 @@ run-findbugs - verify + verify + + check + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + + attach-javadocs - check + jar - - org.apache.maven.plugins - maven-javadoc-plugin - - - attach-javadocs - - jar - - - - From 90fe3c6f8e53227cbb1ddf9231e01b1de5a6a9f5 Mon Sep 17 00:00:00 2001 From: TimSVector Date: Thu, 6 Jun 2024 15:26:18 -0400 Subject: [PATCH 005/112] Updates for newer jenkins version and java 11 --- README.md | 8 + pom.xml | 239 ++++++------------ .../VectorCASTJobRoot.java | 16 +- .../common/VcastUtils.java | 17 +- .../job/NewPipelineTest.java | 83 +++--- .../job/NewSingleJobTest.java | 59 ++--- 6 files changed, 155 insertions(+), 267 deletions(-) diff --git a/README.md b/README.md index 40a04fc7..4881a71b 100644 --- a/README.md +++ b/README.md @@ -174,6 +174,14 @@ environment before disabling. This takes into account enviornments that are dir ## Change Log +### Version 0.78 (17 Jun 2024) +- Adding in following capabilities + - Extended Cobertura format output for use with [Jenkins Coverage Plugin](https://github.com/jenkinsci/coverage-plugin) + - Unit Test Data format output in SonarQube format + - Adding capability to generate an index.html for all .html reports +- Refactored New Job code to reduce duplication +- Moved to Jenkins 2.454 and Java 11 + ### Version 0.77 (26 Dec 2023) - Updated for findbugs to spotbugs - Fixed changed based testing analysis for compound tests being shown as Skipped diff --git a/pom.xml b/pom.xml index f331b539..9dc63f43 100644 --- a/pom.xml +++ b/pom.xml @@ -4,13 +4,13 @@ org.jenkins-ci.plugins plugin - 3.54 + 4.83 VectorCAST Execution Run VectorCAST manage jobs from Jenkins vectorcast-execution - 0.77-SNAPSHOT + 0.78-SNAPSHOT hpi https://github.com/jenkinsci/vectorcast-execution-plugin @@ -24,13 +24,8 @@ UTF-8 UTF-8 UTF-8 - 3.0.4 false - - 2.289.3 - 8 - 2.56 - 1.6.2 + 2.454 Vector Informatik, GmbH @@ -55,6 +50,10 @@ repo.jenkins-ci.org https://repo.jenkins-ci.org/public/ + + incrementals.jenkins-ci.org + https://repo.jenkins-ci.org/incrementals/ + @@ -66,212 +65,136 @@ io.jenkins.tools.bom - bom-2.289.x - 1246.va_b_50630c1d19 + bom-2.452.x + 3105.v672692894683 import pom + - org.jenkins-ci.plugins.workflow - workflow-aggregator - 2.5 - - - org.jenkinsci.plugins - pipeline-model-api - 1.9.3 - - - org.jenkins-ci.plugins.workflow - workflow-job - 1145.v7f2433caa07f - test - - - org.mockito - mockito-all - 1.10.19 - test + io.jenkins.plugins + javax-mail-api + 1.6.2-11-rc98.96ca_fb_762c25 + - org.powermock - powermock-core - ${powermock.version} - test + org.jenkins-ci.plugins + scm-api + 683.vb_16722fb_b_80b_ + - org.powermock - powermock-module-junit4 - ${powermock.version} - test + org.apache.commons + commons-lang3 + 3.14.0 + - org.powermock - powermock-api-mockito - ${powermock.version} - test + org.apache.commons + commons-text + 1.12.0 + - org.powermock - powermock-reflect - ${powermock.version} - test + org.apache.sshd + sshd-core + 2.12.1 + - com.google.code.findbugs - jsr305 - 3.0.1 - test + io.jenkins.plugins.mina-sshd-api + mina-sshd-api-core + - com.google.code.findbugs - annotations - 3.0.1 - test + org.json + json + 20240303 + org.jenkins-ci.plugins - vectorcast-coverage - 0.21 + structs + 338.vf374c77e250b_ + - org.jvnet.hudson.plugins - groovy-postbuild - 2.4 - - - org.jenkins-ci.plugins.workflow - workflow-cps + io.jenkins.plugins + caffeine-api + 3.1.8-150.v3c41c9596941 + org.jenkins-ci.plugins - copyartifact - 1.44 + display-url-api + 2.205.ve04eb_51370c3 + - org.jenkins-ci.main - maven-plugin - 3.4 + io.jenkins.plugins + ionicons-api + 75.v56116b_da_f880 + org.jenkins-ci.plugins - ws-cleanup - 0.28 + script-security + 1343.v4ee5332b_718b_ + - commons-io - commons-io - 2.11.0 + org.jenkins-ci.plugins + matrix-project + 835.ve327939f05d0 io.jenkins.plugins warnings-ng - 9.11.1 - - - org.slf4j - slf4j-api - 1.7.36 - - - org.slf4j - jcl-over-slf4j - 1.7.36 - - - org.slf4j - slf4j-simple - 1.6.2 - - - com.github.spotbugs - spotbugs-annotations - 4.6.0 + 11.3.0 io.jenkins.plugins - echarts-api - 5.3.0-2 - - - org.ow2.asm - asm-analysis - 9.3 - - - org.ow2.asm - asm-tree - 9.3 - - - org.slf4j - log4j-over-slf4j - 1.7.36 - - - org.slf4j - slf4j-jdk14 - 1.7.36 - test - - - org.jenkins-ci - annotation-indexer - 1.16 - - - org.kohsuke - access-modifier-annotation - 1.27 - provided + coverage + 1.14.0 - org.json - json - 20230227 - - - io.jenkins.plugins - forensics-api - 1.12.0 + org.jenkins-ci.plugins + vectorcast-coverage + 0.22 - io.jenkins.plugins - bootstrap5-api - 5.1.3-6 + org.jvnet.hudson.plugins + groovy-postbuild + 2.4 - io.jenkins.plugins - data-tables-api - 1.11.4-4 + org.jenkins-ci.plugins + copyartifact + 1.44 - org.apache.commons - commons-lang3 - 3.12.0 + org.jenkins-ci.plugins + ws-cleanup + 0.47-rc428.5a_149a_5d662a_ - org.apache.ant - ant - 1.10.12 + com.github.spotbugs + spotbugs-annotations + 4.6.0 - org.hamcrest - hamcrest - 2.2 + org.mockito + mockito-core + 5.12.0 test org.jenkins-ci.plugins - pipeline-utility-steps - - - org.codehaus.plexus - plexus-utils - 3.4.1 + credentials-binding + 678.v697736529f0c @@ -302,8 +225,6 @@ org.codehaus.mojo build-helper-maven-plugin - add-localizer-source-folder generate-sources diff --git a/src/main/java/com/vectorcast/plugins/vectorcastexecution/VectorCASTJobRoot.java b/src/main/java/com/vectorcast/plugins/vectorcastexecution/VectorCASTJobRoot.java index 07a5aa30..e53e6ca8 100644 --- a/src/main/java/com/vectorcast/plugins/vectorcastexecution/VectorCASTJobRoot.java +++ b/src/main/java/com/vectorcast/plugins/vectorcastexecution/VectorCASTJobRoot.java @@ -120,14 +120,16 @@ public String getVersion() { * @return dynamic job */ public JobBase getDynamic(String name) { - for (JobBase ui : getAll()) - try { - if (ui.getUrlName().equals(name)) - return ui; - } catch (NullPointerException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + for (JobBase ui : getAll()) { + if (ui != null) { + String urlName = ui.getUrlName(); + if (urlName != null) { + if (urlName.equals(name)) { + return ui; + } + } } + } return null; } /** diff --git a/src/main/java/com/vectorcast/plugins/vectorcastexecution/common/VcastUtils.java b/src/main/java/com/vectorcast/plugins/vectorcastexecution/common/VcastUtils.java index 3af62814..8f9e07cf 100644 --- a/src/main/java/com/vectorcast/plugins/vectorcastexecution/common/VcastUtils.java +++ b/src/main/java/com/vectorcast/plugins/vectorcastexecution/common/VcastUtils.java @@ -30,6 +30,7 @@ import java.util.jar.Attributes; import java.util.jar.JarFile; import java.util.jar.Manifest; +import java.io.FileNotFoundException; public class VcastUtils { @@ -39,15 +40,17 @@ public static Optional< String > getVersion() try { File file = new File( URLDecoder.decode( VcastUtils.class.getProtectionDomain().getCodeSource().getLocation().getPath(), "utf-8" ) ); JarFile jarfile = new JarFile( file ); - version = Optional.ofNullable( jarfile.getManifest().getMainAttributes().getValue( "Plugin-Version" ) ); - jarfile.close(); - - } catch ( IOException e ) { + if (jarfile != null) { + version = Optional.ofNullable( jarfile.getManifest().getMainAttributes().getValue( "Plugin-Version" ) ); + jarfile.close(); + } + } + catch ( FileNotFoundException e ) { e.printStackTrace(); - } catch ( NullPointerException e ) { + } + catch ( IOException e ) { e.printStackTrace(); - } - + } return version; } diff --git a/src/test/java/com/vectorcast/plugins/vectorcastexecution/job/NewPipelineTest.java b/src/test/java/com/vectorcast/plugins/vectorcastexecution/job/NewPipelineTest.java index 41872643..cb94f728 100644 --- a/src/test/java/com/vectorcast/plugins/vectorcastexecution/job/NewPipelineTest.java +++ b/src/test/java/com/vectorcast/plugins/vectorcastexecution/job/NewPipelineTest.java @@ -1,78 +1,54 @@ -/* - * The MIT License - * - * Copyright 2016 Vector Software, East Greenwich, Rhode Island USA - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ package com.vectorcast.plugins.vectorcastexecution.job; -import com.vectorcast.plugins.vectorcastcoverage.VectorCASTPublisher; -import com.vectorcast.plugins.vectorcastexecution.VectorCASTCommand; -import com.vectorcast.plugins.vectorcastexecution.VectorCASTSetup; -import hudson.model.Descriptor; +import com.vectorcast.plugins.vectorcastexecution.job.ScmConflictException; +import com.vectorcast.plugins.vectorcastexecution.job.ExternalResultsFileException; +import com.vectorcast.plugins.vectorcastexecution.job.JobAlreadyExistsException; + +import hudson.model.FreeStyleProject; import hudson.model.Item; -import hudson.plugins.ws_cleanup.PreBuildCleanup; import hudson.security.Permission; -import hudson.tasks.ArtifactArchiver; -import hudson.tasks.BuildWrapper; -import hudson.tasks.Builder; -import hudson.tasks.Publisher; -import hudson.util.DescribableList; +import java.io.IOException; +import javax.servlet.ServletException; import jenkins.model.Jenkins; -import junit.framework.TestCase; import net.sf.json.JSONObject; -import hudson.tasks.junit.JUnitResultArchiver; import org.junit.Assert; import org.junit.Rule; import org.junit.Test; -import org.junit.runner.RunWith; -import org.jvnet.hudson.plugins.groovypostbuild.GroovyPostbuildRecorder; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; import org.jvnet.hudson.test.JenkinsRule; import org.jvnet.hudson.test.MockAuthorizationStrategy; +import org.jvnet.hudson.test.SingleFileSCM; import org.kohsuke.stapler.StaplerRequest; import org.kohsuke.stapler.StaplerResponse; import org.mockito.Mockito; -import static org.powermock.api.mockito.PowerMockito.when; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; -import org.powermock.core.classloader.annotations.PowerMockIgnore; +import org.mockito.Mockito; +import hudson.model.Descriptor.FormException; + +import static org.mockito.Mockito.when; + +public class NewPipelineTest { -@RunWith(PowerMockRunner.class) -@PrepareForTest(Jenkins.class) -@PowerMockIgnore("jdk.internal.reflect.*") + @Rule public JenkinsRule j = new JenkinsRule(); -public class NewPipelineTest extends TestCase { - @Rule - public JenkinsRule r = new JenkinsRule(); + @BeforeEach + void setUpStaticMocks() { + } + + @AfterEach + void tearDownStaticMocks() { + } - private static final String PROJECTNAME = "project_vcast_pipeline"; + @Test public void customizeWorkspaceWithFile() + throws Exception { + j.jenkins.setSecurityRealm(j.createDummySecurityRealm()); - @Test - public void testBasic() throws Exception { - r.jenkins.setSecurityRealm(r.createDummySecurityRealm()); MockAuthorizationStrategy mockStrategy = new MockAuthorizationStrategy(); mockStrategy.grant(Jenkins.READ).everywhere().to("devel"); for (Permission p : Item.PERMISSIONS.getPermissions()) { mockStrategy.grant(p).everywhere().to("devel"); } - r.jenkins.setAuthorizationStrategy(mockStrategy); + j.jenkins.setAuthorizationStrategy(mockStrategy); StaplerRequest request = Mockito.mock(StaplerRequest.class); StaplerResponse response = Mockito.mock(StaplerResponse.class); @@ -85,7 +61,6 @@ public void testBasic() throws Exception { NewPipelineJob job = new NewPipelineJob(request, response); Assert.assertEquals("project", job.getBaseName()); job.create(false); - Assert.assertEquals(PROJECTNAME, job.getProjectName()); - //Assert.assertTrue(job.getTopProject() != null); + Assert.assertEquals("project_vcast_pipeline", job.getProjectName()); } } diff --git a/src/test/java/com/vectorcast/plugins/vectorcastexecution/job/NewSingleJobTest.java b/src/test/java/com/vectorcast/plugins/vectorcastexecution/job/NewSingleJobTest.java index ebdf77a6..9add26b4 100644 --- a/src/test/java/com/vectorcast/plugins/vectorcastexecution/job/NewSingleJobTest.java +++ b/src/test/java/com/vectorcast/plugins/vectorcastexecution/job/NewSingleJobTest.java @@ -1,26 +1,3 @@ -/* - * The MIT License - * - * Copyright 2016 Vector Software, East Greenwich, Rhode Island USA - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ package com.vectorcast.plugins.vectorcastexecution.job; import com.vectorcast.plugins.vectorcastcoverage.VectorCASTPublisher; @@ -43,36 +20,40 @@ import org.junit.Assert; import org.junit.Rule; import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; import org.jvnet.hudson.plugins.groovypostbuild.GroovyPostbuildRecorder; import org.jvnet.hudson.test.JenkinsRule; import org.jvnet.hudson.test.MockAuthorizationStrategy; import org.kohsuke.stapler.StaplerRequest; import org.kohsuke.stapler.StaplerResponse; import org.mockito.Mockito; -import static org.powermock.api.mockito.PowerMockito.when; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.core.classloader.annotations.PowerMockIgnore; -import org.powermock.modules.junit4.PowerMockRunner; -@RunWith(PowerMockRunner.class) -@PrepareForTest(Jenkins.class) -@PowerMockIgnore("jdk.internal.reflect.*") -public class NewSingleJobTest extends TestCase { - @Rule - public JenkinsRule r = new JenkinsRule(); +import static org.mockito.Mockito.when; +public class NewSingleJobTest { + + @Rule + public JenkinsRule j = new JenkinsRule(); private static final String PROJECTNAME = "project.vcast.single"; - @Test + @BeforeEach + void setUpStaticMocks() { + } + + @AfterEach + void tearDownStaticMocks() { + } + + @Test public void testBasic() throws Exception { - r.jenkins.setSecurityRealm(r.createDummySecurityRealm()); + j.jenkins.setSecurityRealm(j.createDummySecurityRealm()); MockAuthorizationStrategy mockStrategy = new MockAuthorizationStrategy(); mockStrategy.grant(Jenkins.READ).everywhere().to("devel"); for (Permission p : Item.PERMISSIONS.getPermissions()) { mockStrategy.grant(p).everywhere().to("devel"); } - r.jenkins.setAuthorizationStrategy(mockStrategy); + j.jenkins.setAuthorizationStrategy(mockStrategy); StaplerRequest request = Mockito.mock(StaplerRequest.class); StaplerResponse response = Mockito.mock(StaplerResponse.class); @@ -134,7 +115,5 @@ public void testBasic() throws Exception { // Publisher 3 - GroovyPostbuildRecorder Assert.assertTrue(publisherList.get(3) instanceof GroovyPostbuildRecorder); GroovyPostbuildRecorder groovyScript = (GroovyPostbuildRecorder)publisherList.get(3); - Assert.assertEquals(/*failure*/2, groovyScript.getBehavior()); - } - + Assert.assertEquals(/*failure*/2, groovyScript.getBehavior()); } } From 481e2de0f52d3707663eca2700788836643bb823 Mon Sep 17 00:00:00 2001 From: TimSVector Date: Wed, 12 Jun 2024 11:00:50 -0400 Subject: [PATCH 006/112] Updates for copyright comment --- README.md | 2 +- pom.xml | 28 ++++--- .../vectorcastexecution/Messages.properties | 4 +- .../VectorCASTCommand/config.jelly | 34 ++++---- .../VectorCASTCommand/config.properties | 2 +- .../VectorCASTJobDiag/done.jelly | 2 +- .../VectorCASTJobDiag/done.properties | 2 +- .../VectorCASTJobDiag/index.jelly | 2 +- .../VectorCASTJobDiag/index.properties | 2 +- .../VectorCASTJobPipeline/conflict.jelly | 2 +- .../VectorCASTJobPipeline/conflict.properties | 2 +- .../VectorCASTJobPipeline/created.jelly | 2 +- .../VectorCASTJobPipeline/created.properties | 2 +- .../VectorCASTJobPipeline/exists.jelly | 2 +- .../VectorCASTJobPipeline/exists.properties | 2 +- .../VectorCASTJobPipeline/extresblank.jelly | 2 +- .../extresblank.properties | 2 +- .../VectorCASTJobPipeline/index.jelly | 2 +- .../VectorCASTJobPipeline/index.properties | 2 +- .../VectorCASTJobPipeline/unsupported.jelly | 2 +- .../unsupported.properties | 2 +- .../VectorCASTJobRoot/index.jelly | 2 +- .../VectorCASTJobRoot/index.properties | 2 +- .../VectorCASTJobSingle/created.jelly | 2 +- .../VectorCASTJobSingle/created.properties | 2 +- .../VectorCASTJobSingle/exists.jelly | 2 +- .../VectorCASTJobSingle/exists.properties | 2 +- .../VectorCASTJobSingle/extresblank.jelly | 2 +- .../extresblank.properties | 2 +- .../VectorCASTJobSingle/index.jelly | 2 +- .../VectorCASTJobSingle/index.properties | 2 +- .../VectorCASTSetup/config.jelly | 2 +- .../VectorCASTSetup/config.properties | 2 +- src/main/resources/index.jelly | 2 +- .../lib/VectorCAST/additionalTools.jelly | 2 +- .../lib/VectorCAST/additionalTools.properties | 2 +- .../lib/VectorCAST/jobOptionsDefault.jelly | 2 +- .../VectorCAST/jobOptionsDefault.properties | 2 +- .../VectorCAST/jobOptionsLabelMaster.jelly | 2 +- .../jobOptionsLabelMaster.properties | 2 +- .../VectorCAST/jobOptionsLabelNoDefault.jelly | 2 +- .../jobOptionsLabelNoDefault.properties | 2 +- .../lib/VectorCAST/jobOptionsNoDefault.jelly | 2 +- .../VectorCAST/jobOptionsNoDefault.properties | 2 +- .../lib/VectorCAST/jobOptionsPipeline.jelly | 2 +- .../VectorCAST/jobOptionsPipeline.properties | 2 +- .../resources/lib/VectorCAST/options.jelly | 2 +- .../lib/VectorCAST/options.properties | 2 +- .../lib/VectorCAST/pipelineScripts.jelly | 2 +- .../lib/VectorCAST/pipelineScripts.properties | 2 +- src/main/resources/lib/VectorCAST/retry.jelly | 2 +- .../resources/lib/VectorCAST/retry.properties | 2 +- src/main/resources/lib/VectorCAST/scm.jelly | 2 +- .../resources/lib/VectorCAST/scm.properties | 2 +- .../resources/lib/VectorCAST/scripts.jelly | 2 +- .../lib/VectorCAST/scripts.properties | 2 +- src/main/resources/scripts/cobertura.py | 78 +++++++++---------- src/main/resources/scripts/copy_build_dir.py | 2 +- .../resources/scripts/extract_build_dir.py | 2 +- .../resources/scripts/generate-results.py | 2 +- .../scripts/generate_sonarqube_testresults.py | 2 +- src/main/resources/scripts/generate_xml.py | 2 +- .../incremental_build_report_aggregator.py | 2 +- src/main/resources/scripts/managewait.py | 2 +- src/main/resources/scripts/safe_open.py | 2 +- src/main/resources/scripts/tcmr2csv.py | 2 +- .../resources/scripts/vcastcsv2jenkins.py | 2 +- .../requests/packages/urllib3/response.py | 2 +- .../VectorCASTCommandTest.java | 2 +- 69 files changed, 141 insertions(+), 133 deletions(-) diff --git a/README.md b/README.md index 4881a71b..c00b5801 100644 --- a/README.md +++ b/README.md @@ -180,7 +180,7 @@ environment before disabling. This takes into account enviornments that are dir - Unit Test Data format output in SonarQube format - Adding capability to generate an index.html for all .html reports - Refactored New Job code to reduce duplication -- Moved to Jenkins 2.454 and Java 11 +- Moved to Jenkins 2.440 and Java 11 ### Version 0.77 (26 Dec 2023) - Updated for findbugs to spotbugs diff --git a/pom.xml b/pom.xml index 9dc63f43..ba76116f 100644 --- a/pom.xml +++ b/pom.xml @@ -25,7 +25,7 @@ UTF-8 UTF-8 false - 2.454 + 2.452.1 Vector Informatik, GmbH @@ -73,11 +73,19 @@ + + + + org.slf4j + slf4j-api + 2.0.13 + + io.jenkins.plugins javax-mail-api - 1.6.2-11-rc98.96ca_fb_762c25 + 1.6.2-10 @@ -118,37 +126,37 @@ org.jenkins-ci.plugins structs - 338.vf374c77e250b_ + 337.v1b_04ea_4df7c8 io.jenkins.plugins caffeine-api - 3.1.8-150.v3c41c9596941 + 3.1.8-133.v17b_1ff2e0599 org.jenkins-ci.plugins display-url-api - 2.205.ve04eb_51370c3 + 2.204.vf6fddd8a_8b_e9 io.jenkins.plugins ionicons-api - 75.v56116b_da_f880 + 74.v93d5eb_813d5f org.jenkins-ci.plugins script-security - 1343.v4ee5332b_718b_ + 1341.va_2819b_414686 org.jenkins-ci.plugins matrix-project - 835.ve327939f05d0 + 832.va_66e270d2946 io.jenkins.plugins @@ -178,7 +186,7 @@ org.jenkins-ci.plugins ws-cleanup - 0.47-rc428.5a_149a_5d662a_ + 0.46 com.github.spotbugs @@ -194,7 +202,7 @@ org.jenkins-ci.plugins credentials-binding - 678.v697736529f0c + 677.vdc9d38cb_254d diff --git a/src/main/resources/com/vectorcast/plugins/vectorcastexecution/Messages.properties b/src/main/resources/com/vectorcast/plugins/vectorcastexecution/Messages.properties index b55cd38c..6b9018be 100644 --- a/src/main/resources/com/vectorcast/plugins/vectorcastexecution/Messages.properties +++ b/src/main/resources/com/vectorcast/plugins/vectorcastexecution/Messages.properties @@ -1,6 +1,7 @@ +# # The MIT License # -# Copyright 2016 Vector Software, East Greenwich, Rhode Island USA +# Copyright 2024 Vector Informatik, GmbH. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -19,6 +20,7 @@ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. +# VectorCASTCommand.DisplayName=VectorCAST Command VectorCASTCommand.AddVCJob=VectorCAST diff --git a/src/main/resources/com/vectorcast/plugins/vectorcastexecution/VectorCASTCommand/config.jelly b/src/main/resources/com/vectorcast/plugins/vectorcastexecution/VectorCASTCommand/config.jelly index 76633059..3d635376 100644 --- a/src/main/resources/com/vectorcast/plugins/vectorcastexecution/VectorCASTCommand/config.jelly +++ b/src/main/resources/com/vectorcast/plugins/vectorcastexecution/VectorCASTCommand/config.jelly @@ -1,25 +1,25 @@ diff --git a/src/main/resources/com/vectorcast/plugins/vectorcastexecution/VectorCASTCommand/config.properties b/src/main/resources/com/vectorcast/plugins/vectorcastexecution/VectorCASTCommand/config.properties index f90ffbd1..35afbe57 100644 --- a/src/main/resources/com/vectorcast/plugins/vectorcastexecution/VectorCASTCommand/config.properties +++ b/src/main/resources/com/vectorcast/plugins/vectorcastexecution/VectorCASTCommand/config.properties @@ -1,7 +1,7 @@ # # The MIT License # -# Copyright 2016 Vector Software, East Greenwich, Rhode Island USA +# Copyright 2024 Vector Informatik, GmbH. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/resources/com/vectorcast/plugins/vectorcastexecution/VectorCASTJobDiag/done.jelly b/src/main/resources/com/vectorcast/plugins/vectorcastexecution/VectorCASTJobDiag/done.jelly index 38cb03ef..4cef647e 100644 --- a/src/main/resources/com/vectorcast/plugins/vectorcastexecution/VectorCASTJobDiag/done.jelly +++ b/src/main/resources/com/vectorcast/plugins/vectorcastexecution/VectorCASTJobDiag/done.jelly @@ -1,7 +1,7 @@ - - - - -

${%VCJob.Control.Title}

-

${%VCJob.Control.Description}

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-
+ + + + +

${%VCJob.Control.Title}

+

${%VCJob.Control.Description}

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
\ No newline at end of file diff --git a/src/main/resources/com/vectorcast/plugins/vectorcastexecution/VectorCASTJobSingle/index.jelly b/src/main/resources/com/vectorcast/plugins/vectorcastexecution/VectorCASTJobSingle/index.jelly index d781e067..dda29c2d 100644 --- a/src/main/resources/com/vectorcast/plugins/vectorcastexecution/VectorCASTJobSingle/index.jelly +++ b/src/main/resources/com/vectorcast/plugins/vectorcastexecution/VectorCASTJobSingle/index.jelly @@ -45,6 +45,7 @@ + From fcf91f10bde89a0d73f9843474f8021b956ae727 Mon Sep 17 00:00:00 2001 From: TimSVector Date: Thu, 13 Jun 2024 17:02:03 -0400 Subject: [PATCH 013/112] Update --- .../common/package-info.java | 32 ++ .../vectorcastexecution/job/package-info.java | 32 ++ .../vectorcastexecution/package-info.java | 32 ++ .../lib/VectorCAST/coverageDisplay.jelly | 45 ++ .../lib/VectorCAST/coverageDisplay.properties | 31 ++ .../prevcast_parallel_build_execute.py | 481 ++++++++++++++++++ src/main/resources/scripts/vcast_exec.py | 350 +++++++++++++ 7 files changed, 1003 insertions(+) create mode 100644 src/main/java/com/vectorcast/plugins/vectorcastexecution/common/package-info.java create mode 100644 src/main/java/com/vectorcast/plugins/vectorcastexecution/job/package-info.java create mode 100644 src/main/java/com/vectorcast/plugins/vectorcastexecution/package-info.java create mode 100644 src/main/resources/lib/VectorCAST/coverageDisplay.jelly create mode 100644 src/main/resources/lib/VectorCAST/coverageDisplay.properties create mode 100644 src/main/resources/scripts/prevcast_parallel_build_execute.py create mode 100644 src/main/resources/scripts/vcast_exec.py diff --git a/src/main/java/com/vectorcast/plugins/vectorcastexecution/common/package-info.java b/src/main/java/com/vectorcast/plugins/vectorcastexecution/common/package-info.java new file mode 100644 index 00000000..b60acd6a --- /dev/null +++ b/src/main/java/com/vectorcast/plugins/vectorcastexecution/common/package-info.java @@ -0,0 +1,32 @@ +/* + * The MIT License + * + * Copyright 2024 Vector Informatik, GmbH. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/** + * Common VCE java utilities. + * + * @author Vector Informatik, GmbH. + */ + +package com.vectorcast.plugins.vectorcastexecution.common; + diff --git a/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/package-info.java b/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/package-info.java new file mode 100644 index 00000000..c119d676 --- /dev/null +++ b/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/package-info.java @@ -0,0 +1,32 @@ +/* + * The MIT License + * + * Copyright 2024 Vector Informatik, GmbH. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/** + * Job-specific java for VCE. + * + * @author Vector Informatik, GmbH. + */ + +package com.vectorcast.plugins.vectorcastexecution.job; + diff --git a/src/main/java/com/vectorcast/plugins/vectorcastexecution/package-info.java b/src/main/java/com/vectorcast/plugins/vectorcastexecution/package-info.java new file mode 100644 index 00000000..9eb55823 --- /dev/null +++ b/src/main/java/com/vectorcast/plugins/vectorcastexecution/package-info.java @@ -0,0 +1,32 @@ +/* + * The MIT License + * + * Copyright 2024 Vector Informatik, GmbH. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/** + * Non-specific java for VCE. + * + * @author Vector Informatik, GmbH. + */ + +package com.vectorcast.plugins.vectorcastexecution; + diff --git a/src/main/resources/lib/VectorCAST/coverageDisplay.jelly b/src/main/resources/lib/VectorCAST/coverageDisplay.jelly new file mode 100644 index 00000000..1f3f7024 --- /dev/null +++ b/src/main/resources/lib/VectorCAST/coverageDisplay.jelly @@ -0,0 +1,45 @@ + + + + + + + + + + + + diff --git a/src/main/resources/lib/VectorCAST/coverageDisplay.properties b/src/main/resources/lib/VectorCAST/coverageDisplay.properties new file mode 100644 index 00000000..69a5a415 --- /dev/null +++ b/src/main/resources/lib/VectorCAST/coverageDisplay.properties @@ -0,0 +1,31 @@ +# +# The MIT License +# +# Copyright 2024 Vector Informatik, GmbH. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# + +coverageDisplay.SectionName = Coverage Diplay Selection + +coverageDisplay.coverage.jenkinsCoverage.title = Use Jenkins Coverage Plugin +coverageDisplay.coverage.jenkinsCoverage.description = This is the standard Jenkins Coverage Plugin + +coverageDisplay.coverage.vectorCastCoverage.title = Use Legacy VectorCAST Coverage Plugin +coverageDisplay.coverage.vectorCastCoverage.description = This is the legacy VectorCAST Coverage Plugin \ No newline at end of file diff --git a/src/main/resources/scripts/prevcast_parallel_build_execute.py b/src/main/resources/scripts/prevcast_parallel_build_execute.py new file mode 100644 index 00000000..059ff9b7 --- /dev/null +++ b/src/main/resources/scripts/prevcast_parallel_build_execute.py @@ -0,0 +1,481 @@ +#parallel_build_execute.py + +from __future__ import unicode_literals +import sys, os, subprocess, argparse, glob, shutil +from pprint import pprint +import pdb, time +from datetime import timedelta +from io import open + +from vector.apps.DataAPI.vcproject_api import VCProjectApi +from threading import Thread, Lock +try: + from Queue import Queue, Empty +except ImportError: + from queue import Queue, Empty # python 3.x + +VCD = os.environ['VECTORCAST_DIR'] +MONITOR_SLEEP=6 + +VERSION="v0.2" +VERSION_DATE="2023-10-14" + +class ParallelExecute(object): + def __init__(self): + self.manageProject = None + self.jobs = "1" + self.dryrun = False + self.tc_order = False + self.prioritize = [] + self.use_ci = "" + self.compiler = None + self.testsuite = None + self.incremental = "" + self.verbose = False + + + + def parseParallelExecuteArgs(self): + parser = argparse.ArgumentParser() + # running from manage + + parser.add_argument('--project', '-p', help='VectorCAST Project Project Name') + parser.add_argument('--compiler','-c', help='VectorCAST Project Compiler Node', default=None) + parser.add_argument('--testsuite','-t', help='VectorCAST Project TestSuite Node', default=None) + parser.add_argument('--incremental', help='Using build-execute incremental (CBT)', action="store_true", default=False) + parser.add_argument('--dryrun', help='Dry Run without build/execute', action="store_true",default=False) + parser.add_argument('--verbose', help='Dry Run without build/execute', action="store_true",default=False) + parser.add_argument('--jobs', '-j', help='Number of concurrent jobs (default = 1)', default="1") + parser.add_argument('--prioritize', '-pr', help='Comma separated list of environments to add to front of the que', default=None) + parser.add_argument('--tc_order', '-tc', help='Add environments to que based on # of testcases', action="store_true", default=False) + parser.add_argument('--use_ci', help='Use continuous integration licenses', action="store_true", default=False) + parser.add_argument('--vcast_action', help = 'Choose the VectorCAST Action (default = build-execute)', choices = ['build', 'execute', 'build-execute'], default = 'build-execute') + args = parser.parse_args() + + try: + self.manageProject = os.environ['VCV_ENVIRONMENT_FILE'] + except: + self.manageProject = args.project + + self.jobs = args.jobs + if self.jobs == "0": + self.jobs = "1" + + self.dryrun = args.dryrun + self.tc_order = args.tc_order + + self.vcast_action = args.vcast_action + + if args.prioritize == None: + self.priority_list = [] + else: + self.priority_list = args.prioritize.split(',') + print("Adding the following environments to the top of the que: " + ",".join(self.priority_list)) + + self.compiler = args.compiler + self.testsuite = args.testsuite + + if self.manageProject is None: + print ("\n** Use either --project [Manage Project Name] or enviroment variable VCV_ENVIRONMENT_FILE to specify the manage project name") + sys.exit() + + if not os.path.isfile(self.manageProject) and not os.path.isfile(self.manageProject + ".vcm"): + raise IOError(self.manageProject + ' does not exist') + return + + if args.incremental: + self.incremental = "--incremental" + else: + self.incremental = "" + + if args.use_ci: + self.use_ci = " --ci " + else: + self.use_ci = "" + + if args.verbose: + self.verbose = True + else: + self.verbose = False + + self.currently_executing_jobs = [] + self.jobs_run_time = {} + self.script_start_time = time.time() + + self.running_jobs = 0 + self.lock = Lock() + self.system_test_lock = Lock() + self.mpName = self.manageProject.replace(".vcm","") + + def th_Print (self, str): + self.lock.acquire() + print (str) + self.lock.release() + + def th_lock_acquire(self): + self.lock.acquire() + + def th_lock_release(self): + self.lock.release() + + def run_env(self, env_in, queue, exec_queue, is_system_test): + + if is_system_test: + self.system_test_lock.acquire() + + self.th_lock_acquire() + self.running_jobs += 1 + self.th_lock_release() + + compiler, testsuite, env = env_in.split() + level = compiler + "/" + testsuite + full_name = "/".join([compiler, testsuite, env]) + exec_cmd = VCD + "/manage --project " + self.manageProject + self.use_ci + \ + " --" + self.vcast_action + " " + self.incremental + " --level " + level + \ + " --environment " + env + \ + " --output " + "_".join([compiler, testsuite, env])+ "_rebuild.html" + + + log_name = ".".join(["build",compiler, testsuite, env,"log"]) + build_log = open(log_name,"w") + + start_time = time.time() + if not self.dryrun: + if self.verbose: + print("\nStarting an environment job for " + env + " environment. Exec Command:\n\t" + exec_cmd) + process = subprocess.Popen(exec_cmd, shell=True, stdout=build_log, stderr=build_log) + process.wait() + else: + if self.verbose: + self.th_Print ("RUN>> " + exec_cmd) + else: + self.th_Print ("RUN>> " + full_name ) + + end_time = time.time() + uptime = end_time - start_time + human_uptime = str(timedelta(seconds=int(uptime))) + self.jobs_run_time[full_name] = human_uptime + + build_log.close() + + if self.verbose: + with open(log_name, 'r', encoding='utf-8') as bldlog: + if "Environment built Successfully" not in bldlog.read(): + print("\nERROR!!! Environment " + env + " not built successfully! See " + log_name + " for more details") + else: + print("\nCompleted execution of " + env + " environment. Run Time was " + human_uptime + ".") + + #print ("Harness Loading/Execution", full_name, "Complete") + exec_queue.get() + queue.task_done() + + self.th_lock_acquire() + self.currently_executing_jobs.remove(full_name) + self.th_lock_release() + + self.th_lock_acquire() + self.running_jobs -= 1 + self.th_lock_release() + + if is_system_test: + self.system_test_lock.release() + + def run_compiler(self, compiler, max, queue, compiler_queue): + ##pdb.set_trace() + compiler_queue.get() + + parallel_exec_queue = Queue(maxsize=max) + + while not queue.empty(): + q_entry = queue.get() + env = q_entry[0] + isSystemTest = q_entry[1] + + parallel_exec_queue.put(env) + + self.th_lock_acquire() + self.currently_executing_jobs.append("/".join(env.split())) + self.th_lock_release() + + t = Thread(target=self.run_env, args=[env, queue, parallel_exec_queue, isSystemTest]) + t.daemon = True # thread dies with the program + t.start() + + # sleep the main thread to get the newly spawned thread a change to get running + time.sleep(.2) + + queue.join() + + compiler_queue.task_done() + + def monitor_jobs(self): + + while self.running_jobs != 0: + print ("\n\nWaiting on jobs (", self.running_jobs , len(self.currently_executing_jobs), ")") + print ("===============\n ") + si = self.currently_executing_jobs + si.sort() + print (" " + "\n ".join(si)) + + for compiler in self.waiting_execution_queue: + qsz = self.waiting_execution_queue[compiler].qsize() + if qsz > 0: + print (" >> ", compiler, "has", qsz, "environment(s) in queue") + + time.sleep(MONITOR_SLEEP) + + print ("waiting for jobs to finalize" ) + self.compiler_exec_queue.join() + script_end_time = time.time() + script_uptime = script_end_time - self.script_start_time + script_human_uptime = str(timedelta(seconds=int(script_uptime))) + + exec_cmd = VCD + "/manage --project " + self.manageProject + self.use_ci + " --full-status" + process = subprocess.Popen(exec_cmd, shell=True) + process.wait() + + print ("\n\nSummary of Parallel Execution") + print ( "=============================") + print (" Total time :", script_human_uptime) + for job in self.jobs_run_time: + print (" ", self.jobs_run_time[job], job) + + def parse_html_files(self): + + from bs4 import BeautifulSoup + report_file_list = [] + full_file_list = os.listdir(".") + for file in glob.glob("*_rebuild.html"): + report_file_list.append(file) + + if len(report_file_list) == 0: + print(" No incrementatal rebuild reports found in the workspace...skipping") + return + + try: + main_soup = BeautifulSoup(open(report_file_list[0]),features="lxml") + except: + main_soup = BeautifulSoup(open(report_file_list[0])) + + preserved_count = 0 + executed_count = 0 + total_count = 0 + if main_soup.find(id="report-title"): + main_manage_api_report = True + # New Manage reports have div with id=report-title + # Want second table (skip config data section) + main_row_list = main_soup.find_all('table')[1].tr.find_next_siblings() + main_count_list = main_row_list[-1].th.find_next_siblings() + else: + main_manage_api_report = False + main_row_list = main_soup.table.table.tr.find_next_siblings() + main_count_list = main_row_list[-1].td.find_next_siblings() + + preserved_count = preserved_count + int(main_count_list[1].get_text()) + executed_count = executed_count + int(main_count_list[2].get_text()) + total_count = total_count + int(main_count_list[3].get_text()) + if main_manage_api_report: + build_success, build_total = [int(s.strip()) for s in main_count_list[0].get_text().strip().split('(')[0][:-1].split('/')] + else: + build_success, build_total = [int(s.strip()) for s in main_count_list[0].get_text().strip().split('(')[-1][:-1].split('/')] + + insert_idx = 2 + for file in report_file_list[1:]: + try: + soup = BeautifulSoup(open(file),features="lxml") + except: + soup = BeautifulSoup(open(file)) + if soup.find(id="report-title"): + manage_api_report = True + # New Manage reports have div with id=report-title + # Want second table (skip config data section) + row_list = soup.find_all('table')[1].tr.find_next_siblings() + count_list = row_list[-1].th.find_next_siblings() + else: + manage_api_report = False + row_list = soup.table.table.tr.find_next_siblings() + count_list = row_list[-1].td.find_next_siblings() + for item in row_list[:-1]: + if manage_api_report: + main_soup.find_all('table')[1].insert(insert_idx,item) + else: + main_soup.table.table.insert(insert_idx,item) + insert_idx = insert_idx + 1 + preserved_count = preserved_count + int(count_list[1].get_text()) + executed_count = executed_count + int(count_list[2].get_text()) + total_count = total_count + int(count_list[3].get_text()) + if manage_api_report: + build_totals = [int(s.strip()) for s in count_list[0].get_text().strip().split('(')[0][:-1].split('/')] + else: + build_totals = [int(s.strip()) for s in count_list[0].get_text().strip().split('(')[-1][:-1].split('/')] + build_success = build_success + build_totals[0] + build_total = build_total + build_totals[1] + + try: + percentage = build_success * 100 // build_total + except: + percentage = 0 + if main_manage_api_report: + main_row_list = main_soup.find_all('table')[1].tr.find_next_siblings() + main_count_list = main_row_list[-1].th.find_next_siblings() + main_count_list[0].string.replace_with(str(build_success) + " / " + str(build_total) + " (" + str(percentage) + "%)" ) + else: + main_row_list = main_soup.table.table.tr.find_next_siblings() + main_count_list = main_row_list[-1].td.find_next_siblings() + main_count_list[0].string.replace_with(str(percentage) + "% (" + str(build_success) + " / " + str(build_total) + ")") + + main_count_list[1].string.replace_with(str(preserved_count)) + main_count_list[2].string.replace_with(str(executed_count)) + main_count_list[3].string.replace_with(str(total_count)) + + # moving rebuild reports down in to a sub directory + f = open(self.mpName + "_incremental_rebuild_report.html","w", encoding="utf-8") + f.write(main_soup.prettify(formatter="html")) + f.close() + + # moving rebuild reports down in to a sub directory + if not os.path.exists("rebuild_reports"): + os.mkdir("rebuild_reports") + for file in report_file_list: + if os.path.exists(file): + shutil.move(file, "rebuild_reports/"+file) + + def get_testcase_list(self,env_list): + new_env_list = [] + temp_env_list = [] + for env in env_list: + temp_env_list.append([env,self.get_testcase_count(env)]) + print("\nSorted Environment List:\n") + for i in sorted(temp_env_list,key=lambda item: item[1],reverse=True): + print(" Env Name: " + i[0].name + ",\t\tTestcases: " + str(i[1])) + new_env_list.append(i[0]) + print("\n") + return new_env_list + + def get_testcase_count(self, env): + count=0 + for efile in env.file_list: + if '.tst' in efile: + test_file = efile + break + with open(test_file, 'r', encoding='utf-8') as tst: + for line in tst: + if 'TEST.NAME' in line: + count += 1 + return count + + def cleanup(self): + + print ("\n\n") + + build_log_data = "" + for file in glob.glob("build*.log"): + build_log_data += "\n".join(open(file,"r").readlines()) + if not self.verbose: + os.remove(file) + + open(self.mpName + "_build.log","w", encoding="utf-8").write(build_log_data) + + if self.incremental: + self.parse_html_files() + + def doit(self): + api = VCProjectApi(self.manageProject) + + self.parallel_exec_info = {} + self.waiting_execution_queue = {} + + if self.tc_order: + testcase_list_all = self.get_testcase_list(api.Environment.all()) + else: + testcase_list_all = api.Environment.all() + + testcase_list = [] + for env in testcase_list_all: + if not env.is_active: + continue + testcase_list.append(env) + + for env in testcase_list: + count = int(self.jobs) + def_list = env.options['enums']['C_DEFINE_LIST'][0] + if "VCAST_PARALLEL_PROCESS_COUNT" in def_list: + li = def_list.split() + for item in li: + if "VCAST_PARALLEL_PROCESS_COUNT" in item: + count = int(item.split("=")[-1]) + + self.parallel_exec_info[env.compiler.name] = (count, []) + + for env in testcase_list: + if env.system_tests: + isSystemTest = True + else: + isSystemTest = False + + compiler = env.compiler.name + + if compiler in self.parallel_exec_info: + if self.compiler == None or self.compiler==compiler: + if self.testsuite == None or self.testsuite==env.testsuite.name: + env_list = self.parallel_exec_info[compiler][1] + full_name = env.compiler.name + " " + env.testsuite.name + " " + env.name + if env.name in self.priority_list: + env_list.insert(0,[full_name, isSystemTest]) + else: + env_list.append([full_name, isSystemTest]) + self.waiting_execution_queue[compiler] = Queue() + + #waiting_execution_queue[compiler].append(full_name) + + api.close() + + if self.verbose: + pprint(self.parallel_exec_info) + + for entry in self.parallel_exec_info: + count = self.parallel_exec_info[entry][0] + for item in self.parallel_exec_info[entry][1]: + compiler, testsuite, env = item[0].split() + self.waiting_execution_queue[compiler].put(item) + + ## start threads that start threads + self.compiler_exec_queue = Queue() + + ## create the directory structure in the manage project before building + exec_cmd = VCD + "/manage --project " + self.manageProject + self.use_ci +" --status" + process = subprocess.Popen(exec_cmd, shell=True) + process.wait() + + for compiler in self.waiting_execution_queue: + max = self.parallel_exec_info[compiler][0] + + t = Thread(target=self.run_compiler, args=[compiler, max, self.waiting_execution_queue[compiler], self.compiler_exec_queue],) + self.compiler_exec_queue.put(t) + t.daemon = True # thread dies with the program + t.start() + + ## Quiet down period + time.sleep(1) + + self.monitor_jobs() + + self.cleanup() + +# API for importing the module into another script +def parallel_build_execute(in_args): + prev_argv = sys.argv + try: + sys.argv = ["prevcast_parallel_build_execute.py"] + in_args.split(' ') + pe = ParallelExecute() + pe.parseParallelExecuteArgs() + pe.doit() + finally: + sys.argv = prev_argv + +if __name__ == '__main__': + print ("VectorCAST parallel_build_execute.py ", VERSION, " ", VERSION_DATE) + pe = ParallelExecute() + pe.parseParallelExecuteArgs() + pe.doit() + diff --git a/src/main/resources/scripts/vcast_exec.py b/src/main/resources/scripts/vcast_exec.py new file mode 100644 index 00000000..ca24b738 --- /dev/null +++ b/src/main/resources/scripts/vcast_exec.py @@ -0,0 +1,350 @@ +# +# The MIT License +# +# Copyright 2020 Vector Informatik, GmbH. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# + +import os, subprocess,argparse, glob, sys, shutil + +from managewait import ManageWait +import generate_results +import cobertura +import create_index_html + +try: + import vector.apps.parallel.parallel_build_execute as parallel_build_execute +except: + import prevcast_parallel_build_execute as parallel_build_execute + +class VectorCASTExecute(object): + + def __init__(self, args): + + # setup default values + self.azure = args.azure + self.gitlab = args.gitlab + self.print_exc = args.print_exc + self.print_exc = args.print_exc + self.timing = args.timing + self.jobs = args.jobs + self.sonarqube = args.sonarqube + self.junit = args.junit + self.cobertura = args.cobertura + self.cobertura_extended = args.cobertura_extended + self.metrics = args.metrics + self.aggregate = args.aggregate + + self.html_base_dir = args.html_base_dir + + if args.exit_with_failed_count == 'not present': + self.useJunitFailCountPct = False + self.junit_percent_to_fail = 0 + elif args.exit_with_failed_count == '(default 0)': + self.useJunitFailCountPct = True + self.junit_percent_to_fail = 0 + else: + self.useJunitFailCountPct = True + self.junit_percent_to_fail = int(args.exit_with_failed_count) + self.failed_count = 0 + + if args.output_dir: + self.xml_data_dir = os.path.join(args.output_dir, 'xml_data') + if not os.path.exists(self.xml_data_dir): + os.makedirs(self.xml_data_dir) + else: + self.xml_data_dir = "xml_data" + + if args.build and not args.build_execute: + self.build_execute = "build" + self.vcast_action = "--vcast_action " + self.build_execute + elif args.build_execute: + self.build_execute = "build-execute" + self.vcast_action = "--vcast_action " + self.build_execute + else: + self.build_execute = "" + self.vcast_action = "" + + self.verbose = args.verbose + self.FullMP = args.ManageProject + self.mpName = os.path.basename(args.ManageProject)[:-4] + + if args.ci: + self.useCI = " --use_ci " + self.ci = " --ci " + else: + self.useCI = "" + self.ci = "" + + if args.incremental: + self.useCBT = " --incremental " + else: + self.useCBT = "" + + self.useLevelEnv = False + self.environment = None + self.level = None + self.compiler = None + self.testsuite = None + self.reportsName = "" + self.env_option = "" + self.level_option = "" + self.needIndexHtml = False + + # if a manage level was specified... + if args.level: + self.useLevelEnv = True + self.level = args.level + + # try level being Compiler/TestSuite + try: + self.compiler, self.testsuite = args.level.split("/") + self.reportsName = "_" + self.compiler + "_" + self.testsuite + except: + # just use the compiler name + self.compiler = args.level + self.reportsName = "_" + self.compiler + + self.level_option = "--level " + args.level + " " + + # if an environment was specified + if args.environment: + # afix the proper settings for commands later and report names + self.useLevelEnv = True + self.environment = args.environment + self.env_option = "--environment " + args.environment + " " + self.reportsName += "_" + self.environment + + if self.useLevelEnv: + self.build_log_name = "build" + self.reportsName + ".log" + else: + self.build_log_name = "build" + self.mpName + ".log" + + self.manageWait = ManageWait(self.verbose, "", 30, 1, self.FullMP, self.ci) + + self.cleanup("junit", "test_results_") + self.cleanup("cobertura", "coverage_results_") + self.cleanup("sonarqube", "test_results_") + self.cleanup("pclp", "pclp_results_") + self.cleanup(".", self.mpName + "_aggregate_report.html") + self.cleanup(".", self.mpName + "_metrics_report.html") + + def cleanup(self, dirName, fname): + for file in glob.glob(os.path.join(self.xml_data_dir, dirName, fname + "*.*")): + try: + os.remove(file); + except: + print("Error removing file after failed to remove directory: " + file) + + try: + shutil.rmtree(os.path.join(self.xml_data_dir , dirName)) + except: + pass + + + def generateIndexHtml(self): + try: + prj_dir = os.environ['CI_PROJECT_DIR'].replace("\\","/") + "/" + except: + prj_dir = os.getcwd().replace("\\","/") + "/" + + tempHtmlReportList = glob.glob("*.html") + tempHtmlReportList += glob.glob(os.path.join(args.html_base_dir, "*.html")) + htmlReportList = [] + + for report in tempHtmlReportList: + if "index.html" not in report: + report = report.replace("\\","/") + report = report.replace(prj_dir,"") + htmlReportList.append(report) + + create_index_html.run(htmlReportList) + + def runJunitMetrics(self): + print("Creating JUnit Metrics") + + generate_results.verbose = self.verbose + generate_results.print_exc = self.print_exc + generate_results.timing = self.timing + self.failed_count, self.passed_count = generate_results.buildReports(self.FullMP,self.level,self.environment, True, self.timing, xml_data_dir = self.xml_data_dir) + + # calculate the failed percentage + self.failed_pct = 100 * self.failed_count/ (self.failed_count + self.passed_count) + + # if the failed percentage is less that the specified limit (default = 0) + # clear the failed count + if self.useJunitFailCountPct and self.failed_pct < self.junit_percent_to_fail: + self.failed_count = 0 + + self.needIndexHtml = True + + def runCoberturaMetrics(self): + if self.cobertura_extended: + print("Creating Extended Cobertura Metrics") + else: + print("Creating Cobertura Metrics") + + cobertura.verbose = self.verbose + cobertura.extended = self.cobertura_extended + cobertura.generateCoverageResults(self.FullMP, self.azure, self.xml_data_dir) + + def runSonarQubeMetrics(self): + print("Creating SonarQube Metrics") + import generate_sonarqube_testresults + generate_sonarqube_testresults.run(self.FullMP, self.xml_data_dir) + + def runPcLintPlusMetrics(self, input_xml): + print("Creating PC-lint Plus Metrics") + import generate_plcp_reports + os.makedirs(os.path.join(self.xml_data_dir,"pclp")) + report_name = os.path.join(self.xml_data_dir,"pclp","gl-code-quality-report.json") + print("PC-lint Plus Metrics file: ", report_name) + generate_plcp_reports.generate_reports(input_xml, output_gitlab = report_name) + + def runReports(self): + if self.aggregate: + self.manageWait.exec_manage_command ("--create-report=aggregate --output=" + self.mpName + "_aggregate_report.html") + self.needIndexHtml = True + if self.metrics: + self.manageWait.exec_manage_command ("--create-report=metrics --output=" + self.mpName + "_metrics_report.html") + self.needIndexHtml = True + + def runExec(self): + + self.manageWait.exec_manage_command ("--status") + self.manageWait.exec_manage_command ("--force --release-locks") + self.manageWait.exec_manage_command ("--config VCAST_CUSTOM_REPORT_FORMAT=HTML") + + if self.useLevelEnv: + output = "--output " + self.mpName + self.reportsName + "_rebuild.html" + else: + output = "" + + if self.jobs != "1": + + # should work for pre-vcast parallel_build_execute or vcast parallel_build_execute + pstr = "--project " + self.FullMP + jstr = "--jobs="+str(self.jobs) + cstr = "" if (self.compiler == None) else "--compiler="+self.compiler + tstr = "" if (self.testsuite == None) else "--testsuite="+self.testsuite + cbtStr = self.useCBT + ciStr = self.useCI + vbStr = "--verbose" if (self.verbose) else "" + + # filter out the blank ones + callList = [] + for s in [pstr, jstr, cstr, tstr, cbtStr, ciStr, vbStr, self.vcast_action]: + if s != "": + s = s.strip() + callList.append(s) + + callStr = " ".join(callList) + parallel_build_execute.parallel_build_execute(callStr) + + else: + cmd = "--" + self.build_execute + " " + self.useCBT + self.level_option + self.env_option + output + build_log = self.manageWait.exec_manage_command (cmd) + open(self.build_log_name,"w").write(build_log) + + +if __name__ == '__main__': + + parser = argparse.ArgumentParser() + parser.add_argument('ManageProject', help='VectorCAST Project Name') + + actionGroup = parser.add_argument_group('Script Actions', 'Options for the main tasks') + actionGroup.add_argument('--build-execute', help='Builds and exeuctes the VectorCAST Project', action="store_true", default = False) + parser_specify = actionGroup.add_mutually_exclusive_group() + parser_specify.add_argument('--build', help='Only builds the VectorCAST Project', action="store_true", default = False) + parser_specify.add_argument('--incremental', help='Use Change Based Testing (Cannot be used with --build)', action="store_true", default = False) + + metricsGroup = parser.add_argument_group('Metrics Options', 'Options generating metrics') + metricsGroup.add_argument('--output_dir', help='Set the base directory of the xml_data directory. Default is the workspace directory', default = None) + metricsGroup.add_argument("--html_base_dir", help='Set the base directory of the html_reports directory. The default is the workspace directory', default = "html_reports") + metricsGroup.add_argument('--cobertura', help='Generate coverage results in Cobertura xml format', action="store_true", default = False) + metricsGroup.add_argument('--cobertura_extended', help='Generate coverage results in extended Cobertura xml format', action="store_true", default = False) + metricsGroup.add_argument('--junit', help='Generate test results in Junit xml format', action="store_true", default = False) + metricsGroup.add_argument('--sonarqube', help='Generate test results in SonarQube Generic test execution report format (CppUnit)', action="store_true", default = False) + metricsGroup.add_argument('--pclp_input', help='Generate static analysis results from PC-lint Plus XML file to generic static analysis format (codequality)', action="store", default = None) + metricsGroup.add_argument('--exit_with_failed_count', help='Returns failed test case count as script exit. Set a value to indicate a percentage above which the job will be marked as failed', + nargs='?', default='not present', const='(default 0)') + + reportGroup = parser.add_argument_group('Report Selection', 'VectorCAST Manage reports that can be generated') + reportGroup.add_argument('--aggregate', help='Generate aggregate coverage report VectorCAST Project', action="store_true", default = False) + reportGroup.add_argument('--metrics', help='Genenereate metrics reports for VectorCAST Project', action="store_true", default = False) + + beGroup = parser.add_argument_group('Build/Execution Options', 'Options that effect build/execute operation') + + beGroup.add_argument('--jobs', help='Number of concurrent jobs (default = 1)', default="1") + beGroup.add_argument('--ci', help='Use Continuous Integration Licenses', action="store_true", default = False) + beGroup.add_argument('-l', '--level', help='Environment Name if only doing single environment. Should be in the form of compiler/testsuite', default=None) + beGroup.add_argument('-e', '--environment', help='Environment Name if only doing single environment.', default=None) + + parser_specify = beGroup.add_mutually_exclusive_group() + parser_specify.add_argument('--gitlab', help='Build using GitLab CI (default)', action="store_true", default = True) + parser_specify.add_argument('--azure', help='Build using Azure DevOps', action="store_true", default = False) + + actionGroup = parser.add_argument_group('Script Debug ', 'Options used for debugging the script') + actionGroup.add_argument('--print_exc', help='Prints exceptions', action="store_true", default = False) + actionGroup.add_argument('--timing', help='Prints timing information for metrics generation', action="store_true", default = False) + actionGroup.add_argument('-v', '--verbose', help='Enable verbose output', action="store_true", default = False) + + + args = parser.parse_args() + + if args.ci: + os.environ['VCAST_USE_CI_LICENSES'] = "1" + + os.environ['VCAST_MANAGE_PROJECT_DIRECTORY'] = os.path.abspath(args.ManageProject).rsplit(".",1)[0] + + if not os.path.isfile(args.ManageProject): + print ("Manage project (.vcm file) provided does not exist: " + args.ManageProject) + print ("exiting...") + sys.exit(-1) + + + vcExec = VectorCASTExecute(args) + + if args.build_execute or args.build: + vcExec.runExec() + + if args.cobertura or args.cobertura_extended: + vcExec.runCoberturaMetrics() + + if args.junit or vcExec.useJunitFailCountPct: + vcExec.runJunitMetrics() + + if args.sonarqube: + vcExec.runSonarQubeMetrics() + + if args.pclp_input: + vcExec.runPcLintPlusMetrics(args.pclp_input) + + if args.aggregate or args.metrics: + vcExec.runReports() + + + if vcExec.useJunitFailCountPct: + print("--exit_with_failed_count=" + args.exit_with_failed_count + " specified. Fail Percent = " + str(round(vcExec.failed_pct,0)) + "% Return code: ", str(vcExec.failed_count)) + sys.exit(vcExec.failed_count) + + if vcExec.needIndexHtml: + vcExec.generateIndexHtml() + From 267c988340e4aeae157792633ffa3c6090d9e7e9 Mon Sep 17 00:00:00 2001 From: TimSVector Date: Thu, 13 Jun 2024 17:02:23 -0400 Subject: [PATCH 014/112] updates --- .../help-optuseJenkinsCoveragePlugin.html | 72 ++++++++++++++ .../help-optuseVectorCastCoveragePlugin.html | 97 +++++++++++++++++++ 2 files changed, 169 insertions(+) create mode 100644 src/main/webapp/help-optuseJenkinsCoveragePlugin.html create mode 100644 src/main/webapp/help-optuseVectorCastCoveragePlugin.html diff --git a/src/main/webapp/help-optuseJenkinsCoveragePlugin.html b/src/main/webapp/help-optuseJenkinsCoveragePlugin.html new file mode 100644 index 00000000..2bc28c44 --- /dev/null +++ b/src/main/webapp/help-optuseJenkinsCoveragePlugin.html @@ -0,0 +1,72 @@ + + +
+

Information about Jenkins Coverage Plugin

+ + + The Jenkins Coverage Plugin publishes a report of the code and mutation coverage in your build, so you can navigate to a summary report from the main build page. Additionally, the plugin gathers several metrics (lines of code, cyclomatic complexity, number of tests per class) and visualizes these results along with the coverage information. + + +

+

+ + From there you can also dive into the details: +
    +
  • Tree charts that show the distribution of the metrics by type (line, branch, complexity, tests, etc.) +
  • Tabular listing of all files with their coverage, complexity and number of tests +
  • Source code of the files with the coverage highlighted +
  • Trend charts of the coverage over time +
+ +
+
+

Advanced Settings for Jenkins Coverage Plugin

+ Two classes of settings can be accessed in the Jenkins Coverage Plugin + + +
    +
  • Quality Gates +
  • Advanced Options +
+ + + To access the advanced settings: +
    +
  • Pipeline Jobs - You can access the Snippet Generator + and use the configure a new pipeline snippet. Once you have the step configured, you can use the Generate Pipeline Script button, + copy that snippet and replace the existing Coverage snippet in the job configuration. + For more information regarding the advanced settings of the Jenkins Coverage Plugin, please refer to the documentation +

    Settings to process VectorCAST Coverage Results: +

      +
    • Sample Step: recordCoverage: Record code coverage results
    • +
    • Code Coverage Tool > Coverage Parser: VectorCAST Coverage Results
    • +
    • Code Coverage Tool > Report File Pattern: xml_data/cobertura/coverage_results*.html
    • +
    +

    +

  • Single Job - The setup for the Single Job will be one of the post-build steps. +
+ +
+
diff --git a/src/main/webapp/help-optuseVectorCastCoveragePlugin.html b/src/main/webapp/help-optuseVectorCastCoveragePlugin.html new file mode 100644 index 00000000..e84cd49f --- /dev/null +++ b/src/main/webapp/help-optuseVectorCastCoveragePlugin.html @@ -0,0 +1,97 @@ + + + !DOCTYPE html> + + + +
+

Information about legacy VectorCAST Coverage Plugin

+ + + The VectorCAST Coverage Plugin Processes code coverage metrics from for VectorCAST Projects + + +

+

+ + This legacy plugin allows you to capture code coverage reports from VectorCAST Projects. Jenkins will generate the trend report of coverage. This plugin is used automatically with the VectorCAST Execution Plugin +

+ Coverage information from tests runs that has been converted to XML files is read and displayed by this plugin. It shows coverage trends and allows drilling down to more detailed coverage information + +

    +
  • Tree charts that show the distribution of the metrics by type (line, branch, MC/DC Pairs, Function Coverage, etc.) +
  • Tabular listing of all environments/files with their coverage and complexity +
  • Trend charts of the coverage over time +
+ +
+
+ +

⚠ Legacy Plugin Info

This is a legacy plugin and will have no futher development beyond bug fixes and security updates +
From 79e65526127301e3d7f5ccfa2ca3f3f0b35ecba2 Mon Sep 17 00:00:00 2001 From: TimSVector Date: Fri, 14 Jun 2024 11:56:15 -0400 Subject: [PATCH 015/112] Updates for jenkins coverage plugin --- pom.xml | 2 +- .../vectorcastexecution/VectorCASTSetup.java | 15 +++++++ .../vectorcastexecution/job/BaseJob.java | 45 ++++++++++++++++++- .../job/NewPipelineJob.java | 1 + .../vectorcastexecution/job/NewSingleJob.java | 29 ++++++++++-- .../resources/scripts/baseJenkinsfile.groovy | 24 +++++++--- src/main/resources/scripts/cobertura.py | 2 +- .../job/NewSingleJobTest.java | 1 + 8 files changed, 105 insertions(+), 14 deletions(-) diff --git a/pom.xml b/pom.xml index 4ba5d9d1..164bb448 100644 --- a/pom.xml +++ b/pom.xml @@ -166,7 +166,7 @@ io.jenkins.plugins coverage - 1.14.0 + 1.15.0-SNAPSHOT org.jenkins-ci.plugins diff --git a/src/main/java/com/vectorcast/plugins/vectorcastexecution/VectorCASTSetup.java b/src/main/java/com/vectorcast/plugins/vectorcastexecution/VectorCASTSetup.java index 2fea8979..2646d31e 100644 --- a/src/main/java/com/vectorcast/plugins/vectorcastexecution/VectorCASTSetup.java +++ b/src/main/java/com/vectorcast/plugins/vectorcastexecution/VectorCASTSetup.java @@ -86,6 +86,7 @@ public class VectorCASTSetup extends Builder implements SimpleBuildStep { private boolean useImportedResults = false; private boolean useLocalImportedResults = false; private boolean useExternalImportedResults = false; + private boolean useCoveragePlugin = true; private String externalResultsFilename; /** Use coverage history to control build status */ @@ -345,6 +346,20 @@ public boolean getUseStrictTestcaseImport() { public void setUseStrictTestcaseImport(boolean useStrictTestcaseImport) { this.useStrictTestcaseImport = useStrictTestcaseImport; } + /** + * Get option to use coverage plugin or vectorcast coverage plugin + * @return true use coverage plugin or vectorcast coverage plugin + */ + public boolean getUseCoveragePlugin() { + return useCoveragePlugin; + } + /** + * Set option to use coverage plugin or vectorcast coverage plugin + * @param useCoveragePlugin use coverage plugin or vectorcast coverage plugin + */ + public void setUseCoveragePlugin(boolean useCoveragePlugin) { + this.useCoveragePlugin = useCoveragePlugin; + } /** * Get option to Use imported results * @return true to Use imported results, false to not diff --git a/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/BaseJob.java b/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/BaseJob.java index ccc007b5..2d90b775 100644 --- a/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/BaseJob.java +++ b/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/BaseJob.java @@ -1,7 +1,7 @@ /* * The MIT License * - * Copyright 2016 Vector Software, East Greenwich, Rhode Island USA + * Copyright 2024 Vector Software, East Greenwich, Rhode Island USA * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -46,6 +46,9 @@ import hudson.tasks.junit.JUnitResultArchiver; import io.jenkins.plugins.analysis.warnings.PcLint; import io.jenkins.plugins.analysis.core.steps.IssuesRecorder; +import io.jenkins.plugins.coverage.metrics.steps.CoverageRecorder; +import io.jenkins.plugins.coverage.metrics.steps.CoverageTool; +import io.jenkins.plugins.coverage.metrics.steps.CoverageTool.Parser; import org.jenkinsci.plugins.credentialsbinding.impl.SecretBuildWrapper; import org.jenkinsci.plugins.credentialsbinding.impl.UsernamePasswordMultiBinding; import org.jenkinsci.plugins.credentialsbinding.MultiBinding; @@ -53,6 +56,7 @@ import java.util.Collections; import java.util.logging.Logger; import java.util.logging.Level; +import java.util.ArrayList; /** * Base job management - create/delete/update @@ -97,6 +101,9 @@ abstract public class BaseJob { /** Use strict testcase import */ private boolean useStrictTestcaseImport; + + /** Use coveagePlugin */ + private boolean useCoveragePlugin = true; /** Use imported results */ private boolean useImportedResults = false; @@ -198,6 +205,11 @@ protected BaseJob(final StaplerRequest request, final StaplerResponse response, useCILicenses = json.optBoolean("useCiLicense", false); useStrictTestcaseImport = json.optBoolean("useStrictTestcaseImport", true); useImportedResults = json.optBoolean("useImportedResults", false); + if (json.optInt("coverageDisplayOption", 0) == 0) { + useCoveragePlugin = true; + } else { + useCoveragePlugin = false; + } externalResultsFilename = ""; if (useImportedResults) { @@ -264,6 +276,7 @@ public void useSavedData(VectorCASTSetup savedData) { useCoverageHistory = savedData.getUseCoverageHistory(); maxParallel = savedData.getMaxParallel(); + useCoveragePlugin = savedData.getUseCoveragePlugin(); usingSCM = savedData.getUsingSCM(); scm = savedData.getSCM(); @@ -478,6 +491,20 @@ protected boolean getUseStrictTestcaseImport() { protected void setUseStrictTestcaseImport(boolean useStrictTestcaseImport) { this.useStrictTestcaseImport = useStrictTestcaseImport; } + /** + * Get option to use coverage plugin or vectorcast coverage plugin + * @return true use coverage plugin or vectorcast coverage plugin + */ + protected boolean getUseCoveragePlugin() { + return useCoveragePlugin; + } + /** + * Set option to use coverage plugin or vectorcast coverage plugin + * @param useCoveragePlugin use coverage plugin or vectorcast coverage plugin + */ + protected void setUseCoveragePlugin(boolean useCoveragePlugin) { + this.useCoveragePlugin = useCoveragePlugin; + } /** * Get option to Use imported results * @return true to Use imported results, false to not @@ -954,6 +981,22 @@ protected void addVCCoverage(Project project) { publisher.setUseCoverageHistory(useCoverageHistory); project.getPublishersList().add(publisher); } + /** + * Add Jenkins coverage reporting step + * @param project project to add step to + */ + protected void addJenkinsCoverage(Project project) { + CoverageTool tool = new CoverageTool(); + tool.setParser(Parser.VECTORCAST); + tool.setPattern("xml_data/cobertura/coverage_results*.xml"); + List list = new ArrayList(); + list.add(tool); + + CoverageRecorder publisher = new CoverageRecorder(); + publisher.setTools(list); + + project.getPublishersList().add(publisher); + } protected void addCredentialID(Project project) { project.getBuildWrappersList().add(new SecretBuildWrapper(Collections.>singletonList(new UsernamePasswordMultiBinding("VC_TI_USR","VC_TI_PWS",TESTinsights_credentials_id)))); } diff --git a/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/NewPipelineJob.java b/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/NewPipelineJob.java index 6e81e355..d09fd394 100644 --- a/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/NewPipelineJob.java +++ b/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/NewPipelineJob.java @@ -452,6 +452,7 @@ private String generateJenkinsfile() throws IOException { "VC_useOneCheckoutDir = " + singleCheckout + "\n" + "VC_UseCILicense = " + VC_Use_CI + "\n" + "VC_useCBT = " + incremental + "\n" + + "VC_useCoveragePlugin = " + getUseCoveragePlugin() + "\n" + "VC_createdWithVersion = '" + VcastUtils.getVersion().orElse( "Unknown" ) + "'\n" + "VC_usePCLintPlus = " + String.valueOf(getPclpCommand().length() != 0) + "\n" + "VC_pclpCommand = '" + getPclpCommand() + "'\n" + diff --git a/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/NewSingleJob.java b/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/NewSingleJob.java index 9edf0137..33a37037 100644 --- a/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/NewSingleJob.java +++ b/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/NewSingleJob.java @@ -172,7 +172,14 @@ private void addCommandSingleJob() { } else { addEnvVars += "set VCAST_USE_IMPORTED_RESULTS=FALSE\n"; } - + + if (getUseCoveragePlugin()) { + addEnvVars += "set VCAST_USE_COVERAGE_PLUGIN=TRUE\n"; + } else { + addEnvVars += "set VCAST_USE_COVERAGE_PLUGIN=FALSE\n"; + } + + String pluginVersion = VcastUtils.getVersion().orElse( "Unknown" ); String win = ":: Created with vectorcast-execution plugin v" + pluginVersion + "\n\n" + @@ -212,10 +219,11 @@ private void addCommandSingleJob() { win += "%VECTORCAST_DIR%\\vpython \"%WORKSPACE%\\vc_scripts\\managewait.py\" --wait_time " + getWaitTime() + " --wait_loops " + getWaitLoops() + " --command_line \"--project \\\"@PROJECT@\\\" --config VCAST_CUSTOM_REPORT_FORMAT=HTML\"\n" + "%VECTORCAST_DIR%\\vpython \"%WORKSPACE%\\vc_scripts\\generate-results.py\" --junit --wait_time " + getWaitTime() + " --wait_loops " + getWaitLoops() + " \"@PROJECT@\" " + noGenExecReport + " --buildlog complete_build.log\n" + - +"\"%VCAST_USE_COVERAGE_PLUGIN%\"==\"TRUE\" ( \n" + +" %VECTORCAST_DIR%\\vpython \"%WORKSPACE%\\vc_scripts\\cobertura.py\" --project \\\"@PROJECT@\\\"\n" + +")\n" + "%VECTORCAST_DIR%\\vpython \"%WORKSPACE%\\vc_scripts\\full_report_no_toc.py\" \"@PROJECT@\" \n" + "%VECTORCAST_DIR%\\vpython \"%WORKSPACE%\\vc_scripts\\fixup_reports.py\" \"@PROJECT_BASE@_rebuild" + html_text + "_tmp\"\n" + - "%VECTORCAST_DIR%\\vpython \"%WORKSPACE%\\vc_scripts\\managewait.py\" --wait_time " + getWaitTime() + " --wait_loops " + getWaitLoops() + " --command_line \"--project \\\"@PROJECT@\\\" --full-status=\\\"@PROJECT_BASE@_full_report.html\\\"\"\n" + "%VECTORCAST_DIR%\\vpython \"%WORKSPACE%\\vc_scripts\\managewait.py\" --wait_time " + getWaitTime() + " --wait_loops " + getWaitLoops() + " --command_line \"--project \\\"@PROJECT@\\\" --create-report=aggregate --output=\\\"@PROJECT_BASE@_aggregate_report.html\\\"\"\n" + "%VECTORCAST_DIR%\\vpython \"%WORKSPACE%\\vc_scripts\\managewait.py\" --wait_time " + getWaitTime() + " --wait_loops " + getWaitLoops() + " --command_line \"--project \\\"@PROJECT@\\\" --create-report=environment --output=\\\"@PROJECT_BASE@_environment_report.html\\\"\"\n" + @@ -257,6 +265,12 @@ private void addCommandSingleJob() { addEnvVars += "VCAST_USE_IMPORTED_RESULTS=0\n"; } + if (getUseCoveragePlugin()) { + addEnvVars += "VCAST_USE_COVERAGE_PLUGIN=1\n"; + } else { + addEnvVars += "VCAST_USE_COVERAGE_PLUGIN=0\n"; + } + String unix = "##Created with vectorcast-execution plugin v" + pluginVersion + "\n\n" + getEnvironmentSetupUnix() + "\n" + @@ -295,6 +309,9 @@ private void addCommandSingleJob() { unix += "$VECTORCAST_DIR/vpython \"$WORKSPACE/vc_scripts/managewait.py\" --wait_time " + getWaitTime() + " --wait_loops " + getWaitLoops() + " --command_line \"--project \\\"@PROJECT@\\\" --config VCAST_CUSTOM_REPORT_FORMAT=HTML\"\n" + "$VECTORCAST_DIR/vpython \"$WORKSPACE/vc_scripts/generate-results.py\" --junit --wait_time " + getWaitTime() + " --wait_loops " + getWaitLoops() + " \"@PROJECT@\" " + noGenExecReport + " --buildlog complete_build.log\n" + +"if [[ $VCAST_USE_COVERAGE_PLUGIN -eq 1 ]] ; then \n" + +" $VECTORCAST_DIR/vpython \"$WORKSPACE/vc_scripts/cobertura.py\" --project \\\"@PROJECT@\\\"\n" + +"fi\n" + "$VECTORCAST_DIR/vpython \"$WORKSPACE/vc_scripts/full_report_no_toc.py\" \"@PROJECT@\" \n" + "$VECTORCAST_DIR/vpython \"$WORKSPACE/vc_scripts/fixup_reports.py\" \"@PROJECT_BASE@_rebuild" + html_text + "_tmp\"\n" + "$VECTORCAST_DIR/vpython \"$WORKSPACE/vc_scripts/managewait.py\" --wait_time " + getWaitTime() + " --wait_loops " + getWaitLoops() + " --command_line \"--project \\\"@PROJECT@\\\" --create-report=aggregate --output=\\\"@PROJECT_BASE@_aggregate_report.html\\\"\"\n" + @@ -505,7 +522,11 @@ public void doCreate(boolean update) throws IOException, ServletException, Descr addArchiveArtifacts(getTopProject()); addPCLintPlus(getTopProject()); addJunit(getTopProject()); - addVCCoverage(getTopProject()); + if (getUseCoveragePlugin()) { + addJenkinsCoverage(getTopProject()); + } else { + addVCCoverage(getTopProject()); + } addGroovyScriptSingleJob(); if (getTESTinsights_URL().length() != 0) { addCredentialID(getTopProject()); diff --git a/src/main/resources/scripts/baseJenkinsfile.groovy b/src/main/resources/scripts/baseJenkinsfile.groovy index 91241f5a..73e4dc05 100644 --- a/src/main/resources/scripts/baseJenkinsfile.groovy +++ b/src/main/resources/scripts/baseJenkinsfile.groovy @@ -869,6 +869,10 @@ pipeline { // run the metrics at the end buildLogText += runCommands("""_VECTORCAST_DIR/vpython "${env.WORKSPACE}"/vc_scripts/generate-results.py ${VC_Manage_Project} --wait_time ${VC_waitTime} --wait_loops ${VC_waitLoops} --junit --buildlog unstashed_build.log""") + if (VC_useCoveragePlugin) { + buildLogText += runCommands("""_VECTORCAST_DIR/vpython "${env.WORKSPACE}"/vc_scripts/cobertura.py ${VC_Manage_Project}""") + } + cmds = """ _VECTORCAST_DIR/vpython "${env.WORKSPACE}"/vc_scripts/incremental_build_report_aggregator.py ${mpName} --rptfmt HTML _VECTORCAST_DIR/vpython "${env.WORKSPACE}"/vc_scripts/full_report_no_toc.py "${VC_Manage_Project}" @@ -904,13 +908,19 @@ pipeline { currResult = currentBuild.result } - // Send reports to the code coverage plugin - step([$class: 'VectorCASTPublisher', - includes: 'xml_data/coverage_results*.xml', - useThreshold: VC_Use_Threshold, - healthyTarget: VC_Healthy_Target, - useCoverageHistory: VC_useCoverageHistory, - maxHistory : 20]) + if (VC_useCoveragePlugin) { + // Send reports to the Jenkins Coverage Plugin + recordCoverage tools: [[parser: 'VECTORCAST', pattern: 'xml_data/cobertura/coverage_results*.xml']] + + } else { + // Send reports to the VectorCAST Soverage Plugin + step([$class: 'VectorCASTPublisher', + includes: 'xml_data/coverage_results*.xml', + useThreshold: VC_Use_Threshold, + healthyTarget: VC_Healthy_Target, + useCoverageHistory: VC_useCoverageHistory, + maxHistory : 20]) + } if (VC_useCoverageHistory) { if ((currResult != currentBuild.result) && (currentBuild.result == 'FAILURE')) { diff --git a/src/main/resources/scripts/cobertura.py b/src/main/resources/scripts/cobertura.py index 77095e78..8bc2002c 100644 --- a/src/main/resources/scripts/cobertura.py +++ b/src/main/resources/scripts/cobertura.py @@ -725,6 +725,6 @@ def generateCoverageResults(inFile, azure, xml_data_dir = "xml_data"): except Exception as e: azure = False - generateCoverageResults(inFile, azure, "cov_plugin") + generateCoverageResults(inFile, azure) diff --git a/src/test/java/com/vectorcast/plugins/vectorcastexecution/job/NewSingleJobTest.java b/src/test/java/com/vectorcast/plugins/vectorcastexecution/job/NewSingleJobTest.java index 9add26b4..743db8f3 100644 --- a/src/test/java/com/vectorcast/plugins/vectorcastexecution/job/NewSingleJobTest.java +++ b/src/test/java/com/vectorcast/plugins/vectorcastexecution/job/NewSingleJobTest.java @@ -60,6 +60,7 @@ public void testBasic() throws Exception { JSONObject jsonForm = new JSONObject(); jsonForm.put("manageProjectName", "/home/jenkins/vcast/project.vcm"); jsonForm.put("optionClean", true); + jsonForm.put("coverageDisplayOption", 1); when(request.getSubmittedForm()).thenReturn(jsonForm); NewSingleJob job = new NewSingleJob(request, response); From fd121e53ebef0023e8a35b69094adbad819426c9 Mon Sep 17 00:00:00 2001 From: TimSVector Date: Wed, 26 Jun 2024 09:41:46 -0400 Subject: [PATCH 016/112] Updates for environment report removal and cobertura --- pom.xml | 2 +- .../vectorcastexecution/job/NewSingleJob.java | 7 ++-- .../resources/scripts/baseJenkinsfile.groovy | 1 - src/main/resources/scripts/cobertura.py | 38 ++++++++++--------- src/main/resources/scripts/vcast_exec.py | 9 +++-- 5 files changed, 30 insertions(+), 27 deletions(-) diff --git a/pom.xml b/pom.xml index 164bb448..2eef35f4 100644 --- a/pom.xml +++ b/pom.xml @@ -166,7 +166,7 @@ io.jenkins.plugins coverage - 1.15.0-SNAPSHOT + 1.16.0-SNAPSHOT org.jenkins-ci.plugins diff --git a/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/NewSingleJob.java b/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/NewSingleJob.java index 33a37037..35b7a3cb 100644 --- a/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/NewSingleJob.java +++ b/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/NewSingleJob.java @@ -220,13 +220,12 @@ private void addCommandSingleJob() { "%VECTORCAST_DIR%\\vpython \"%WORKSPACE%\\vc_scripts\\managewait.py\" --wait_time " + getWaitTime() + " --wait_loops " + getWaitLoops() + " --command_line \"--project \\\"@PROJECT@\\\" --config VCAST_CUSTOM_REPORT_FORMAT=HTML\"\n" + "%VECTORCAST_DIR%\\vpython \"%WORKSPACE%\\vc_scripts\\generate-results.py\" --junit --wait_time " + getWaitTime() + " --wait_loops " + getWaitLoops() + " \"@PROJECT@\" " + noGenExecReport + " --buildlog complete_build.log\n" + "\"%VCAST_USE_COVERAGE_PLUGIN%\"==\"TRUE\" ( \n" + -" %VECTORCAST_DIR%\\vpython \"%WORKSPACE%\\vc_scripts\\cobertura.py\" --project \\\"@PROJECT@\\\"\n" + +" %VECTORCAST_DIR%\\vpython \"%WORKSPACE%\\vc_scripts\\cobertura.py\" \"@PROJECT@\"\n" + ")\n" + "%VECTORCAST_DIR%\\vpython \"%WORKSPACE%\\vc_scripts\\full_report_no_toc.py\" \"@PROJECT@\" \n" + "%VECTORCAST_DIR%\\vpython \"%WORKSPACE%\\vc_scripts\\fixup_reports.py\" \"@PROJECT_BASE@_rebuild" + html_text + "_tmp\"\n" + "%VECTORCAST_DIR%\\vpython \"%WORKSPACE%\\vc_scripts\\managewait.py\" --wait_time " + getWaitTime() + " --wait_loops " + getWaitLoops() + " --command_line \"--project \\\"@PROJECT@\\\" --full-status=\\\"@PROJECT_BASE@_full_report.html\\\"\"\n" + "%VECTORCAST_DIR%\\vpython \"%WORKSPACE%\\vc_scripts\\managewait.py\" --wait_time " + getWaitTime() + " --wait_loops " + getWaitLoops() + " --command_line \"--project \\\"@PROJECT@\\\" --create-report=aggregate --output=\\\"@PROJECT_BASE@_aggregate_report.html\\\"\"\n" + -"%VECTORCAST_DIR%\\vpython \"%WORKSPACE%\\vc_scripts\\managewait.py\" --wait_time " + getWaitTime() + " --wait_loops " + getWaitLoops() + " --command_line \"--project \\\"@PROJECT@\\\" --create-report=environment --output=\\\"@PROJECT_BASE@_environment_report.html\\\"\"\n" + "\n:: Use Imported Results\n" + "if \"%VCAST_USE_IMPORTED_RESULTS%\"==\"TRUE\" if \"%VCAST_USE_LOCAL_IMPORTED_RESULTS%\"==\"TRUE\" (\n" + " %VECTORCAST_DIR%\\vpython \"%WORKSPACE%\\vc_scripts\\managewait.py\" --wait_time " + getWaitTime() + " --wait_loops " + getWaitLoops() + " --command_line \"--project \\\"@PROJECT@\\\" --export-result=@PROJECT_BASE@_results.vcr\"\n" + @@ -310,12 +309,12 @@ private void addCommandSingleJob() { "$VECTORCAST_DIR/vpython \"$WORKSPACE/vc_scripts/managewait.py\" --wait_time " + getWaitTime() + " --wait_loops " + getWaitLoops() + " --command_line \"--project \\\"@PROJECT@\\\" --config VCAST_CUSTOM_REPORT_FORMAT=HTML\"\n" + "$VECTORCAST_DIR/vpython \"$WORKSPACE/vc_scripts/generate-results.py\" --junit --wait_time " + getWaitTime() + " --wait_loops " + getWaitLoops() + " \"@PROJECT@\" " + noGenExecReport + " --buildlog complete_build.log\n" + "if [[ $VCAST_USE_COVERAGE_PLUGIN -eq 1 ]] ; then \n" + -" $VECTORCAST_DIR/vpython \"$WORKSPACE/vc_scripts/cobertura.py\" --project \\\"@PROJECT@\\\"\n" + +" $VECTORCAST_DIR/vpython \"$WORKSPACE/vc_scripts/cobertura.py\" \"@PROJECT@\"\n" + "fi\n" + "$VECTORCAST_DIR/vpython \"$WORKSPACE/vc_scripts/full_report_no_toc.py\" \"@PROJECT@\" \n" + "$VECTORCAST_DIR/vpython \"$WORKSPACE/vc_scripts/fixup_reports.py\" \"@PROJECT_BASE@_rebuild" + html_text + "_tmp\"\n" + "$VECTORCAST_DIR/vpython \"$WORKSPACE/vc_scripts/managewait.py\" --wait_time " + getWaitTime() + " --wait_loops " + getWaitLoops() + " --command_line \"--project \\\"@PROJECT@\\\" --create-report=aggregate --output=\\\"@PROJECT_BASE@_aggregate_report.html\\\"\"\n" + -"$VECTORCAST_DIR/vpython \"$WORKSPACE/vc_scripts/managewait.py\" --wait_time " + getWaitTime() + " --wait_loops " + getWaitLoops() + " --command_line \"--project \\\"@PROJECT@\\\" --create-report=environment --output=\\\"@PROJECT_BASE@_environment_report.html\\\"\"\n" + +"\n# Use strict testcase import\n" + "\n# Use strict testcase import\n" + "if [[ $VCAST_USE_IMPORTED_RESULTS -eq 1 ]] && [[ $VCAST_USE_LOCAL_IMPORTED_RESULTS -eq 1 ]] ; then\n" + " $VECTORCAST_DIR/vpython \"$WORKSPACE/vc_scripts/managewait.py\" --wait_time " + getWaitTime() + " --wait_loops " + getWaitLoops() + " --command_line \"--project \\\"@PROJECT@\\\" --export-result=@PROJECT_BASE@_results.vcr \"\n" + diff --git a/src/main/resources/scripts/baseJenkinsfile.groovy b/src/main/resources/scripts/baseJenkinsfile.groovy index 73e4dc05..ace24482 100644 --- a/src/main/resources/scripts/baseJenkinsfile.groovy +++ b/src/main/resources/scripts/baseJenkinsfile.groovy @@ -877,7 +877,6 @@ pipeline { _VECTORCAST_DIR/vpython "${env.WORKSPACE}"/vc_scripts/incremental_build_report_aggregator.py ${mpName} --rptfmt HTML _VECTORCAST_DIR/vpython "${env.WORKSPACE}"/vc_scripts/full_report_no_toc.py "${VC_Manage_Project}" _VECTORCAST_DIR/vpython "${env.WORKSPACE}"/vc_scripts/managewait.py --wait_time ${VC_waitTime} --wait_loops ${VC_waitLoops} --command_line "--project "${VC_Manage_Project}" ${VC_UseCILicense} --create-report=aggregate --output=${mpName}_aggregate_report.html" - _VECTORCAST_DIR/vpython "${env.WORKSPACE}"/vc_scripts/managewait.py --wait_time ${VC_waitTime} --wait_loops ${VC_waitLoops} --command_line "--project "${VC_Manage_Project}" ${VC_UseCILicense} --create-report=environment --output=${mpName}_environment_report.html" """ if (VC_useImportedResults) { diff --git a/src/main/resources/scripts/cobertura.py b/src/main/resources/scripts/cobertura.py index 8bc2002c..0f3a29bb 100644 --- a/src/main/resources/scripts/cobertura.py +++ b/src/main/resources/scripts/cobertura.py @@ -31,11 +31,8 @@ from collections import defaultdict from pprint import pprint - fileList = [] -extended = False - def dump(obj): if hasattr(obj, '__dict__'): return vars(obj) @@ -323,7 +320,7 @@ def processStatementBranchMCDC(fileApi, lines): return linesCovered, linesTotal -def procesCoverage(coverXML, coverApi): +def procesCoverage(coverXML, coverApi, extended = False): methods, lines = getFileXML(coverXML, coverApi) @@ -368,14 +365,14 @@ def procesCoverage(coverXML, coverApi): return processStatementBranchMCDC(coverApi, lines) -def runCoverageResultsMP(packages, mpFile, verbose = False): +def runCoverageResultsMP(packages, mpFile, verbose = False, extended=False): vcproj = VCProjectApi(mpFile) api = vcproj.project.cover_api - return runCoberturaResults(packages, api) + return runCoberturaResults(packages, api, verbose = False, extended = extended) -def runCoberturaResults(packages, api, verbose = False): +def runCoberturaResults(packages, api, verbose = False, extended = False): total_br = 0 total_st = 0 @@ -534,8 +531,7 @@ def runCoberturaResults(packages, api, verbose = False): pkg_cov_fc = 0 pkg_cov_mcdc = 0 pkg_vg = 0 - - + if verbose: print ("adding data for " + path) @@ -568,7 +564,7 @@ def runCoberturaResults(packages, api, verbose = False): total_func += funcTotal cov_func += funcCovTotal - linesCovered, linesTotal = procesCoverage(classes, file) + linesCovered, linesTotal = procesCoverage(classes, file, extended) total_lines += linesTotal cov_lines += linesCovered @@ -652,7 +648,10 @@ def runCoberturaResults(packages, api, verbose = False): return total_st, cov_st, total_lines, cov_lines, total_br, cov_br, total_func, cov_func, total_fc, cov_fc, total_mcdc, cov_mcdc, branch_rate, statement_rate, line_rate, func_rate, FC_rate, MCDC_rate, vg -def generateCoverageResults(inFile, azure, xml_data_dir = "xml_data"): +def generateCoverageResults(inFile, azure, xml_data_dir = "xml_data", verbose = False, extended = False): + + cwd = os.getcwd() + xml_data_dir = os.path.join(cwd,xml_data_dir) #coverage results coverages=etree.Element("coverage") @@ -668,11 +667,12 @@ def generateCoverageResults(inFile, azure, xml_data_dir = "xml_data"): if inFile.endswith(".vce"): api=UnitTestApi(inFile) cdb = api.environment.get_coverdb_api() - total_st, cov_st, total_lines, cov_lines, total_br, cov_br, total_func, cov_func, total_fc, cov_fc, total_mcdc, cov_mcdc, branch_rate, statement_rate, line_rate, func_rate, FC_rate, MCDC_rate, complexity = runCoberturaResults(packages, cdb, False) + total_st, cov_st, total_lines, cov_lines, total_br, cov_br, total_func, cov_func, total_fc, cov_fc, total_mcdc, cov_mcdc, branch_rate, statement_rate, line_rate, func_rate, FC_rate, MCDC_rate, complexity = runCoberturaResults(packages, cdb, verbose=verbose, extended=extended) elif inFile.endswith(".vcp"): - api=CoverAPI(inFile) + api=CoverApi(inFile) + total_st, cov_st, total_lines, cov_lines, total_br, cov_br, total_func, cov_func, total_fc, cov_fc, total_mcdc, cov_mcdc, branch_rate, statement_rate, line_rate, func_rate, FC_rate, MCDC_rate, complexity = runCoberturaResults(packages, api, verbose=verbose, extended=extended) else: - total_st, cov_st, total_lines, cov_lines, total_br, cov_br, total_func, cov_func, total_fc, cov_fc, total_mcdc, cov_mcdc, branch_rate, statement_rate, line_rate, func_rate, FC_rate, MCDC_rate, complexity = runCoverageResultsMP(packages, inFile) + total_st, cov_st, total_lines, cov_lines, total_br, cov_br, total_func, cov_func, total_fc, cov_fc, total_mcdc, cov_mcdc, branch_rate, statement_rate, line_rate, func_rate, FC_rate, MCDC_rate, complexity = runCoverageResultsMP(packages, inFile, verbose=verbose, extended=extended) if line_rate != -1.0: coverages.attrib['line-rate'] = str(line_rate) if statement_rate != -1.0: coverages.attrib['statement-rate'] = str(statement_rate) @@ -715,16 +715,20 @@ def generateCoverageResults(inFile, azure, xml_data_dir = "xml_data"): if __name__ == '__main__': + extended = False + azure = False + inFile = sys.argv[1] try: if "--azure" == sys.argv[2]: azure = True print ("using azure mode") - else: - azure = False + elif "--extended" == sys.argv[2]: + extended = True except Exception as e: azure = False + extended = False - generateCoverageResults(inFile, azure) + generateCoverageResults(inFile, azure, xml_data_dir = "xml_data", verbose = False, extended = extended) diff --git a/src/main/resources/scripts/vcast_exec.py b/src/main/resources/scripts/vcast_exec.py index ca24b738..0828e9be 100644 --- a/src/main/resources/scripts/vcast_exec.py +++ b/src/main/resources/scripts/vcast_exec.py @@ -186,7 +186,10 @@ def runJunitMetrics(self): self.failed_count, self.passed_count = generate_results.buildReports(self.FullMP,self.level,self.environment, True, self.timing, xml_data_dir = self.xml_data_dir) # calculate the failed percentage - self.failed_pct = 100 * self.failed_count/ (self.failed_count + self.passed_count) + if (self.failed_count + self.passed_count > 0): + self.failed_pct = 100 * self.failed_count/ (self.failed_count + self.passed_count) + else: + self.failed_pct = 0 # if the failed percentage is less that the specified limit (default = 0) # clear the failed count @@ -201,9 +204,7 @@ def runCoberturaMetrics(self): else: print("Creating Cobertura Metrics") - cobertura.verbose = self.verbose - cobertura.extended = self.cobertura_extended - cobertura.generateCoverageResults(self.FullMP, self.azure, self.xml_data_dir) + cobertura.generateCoverageResults(self.FullMP, self.azure, self.xml_data_dir, verbose = self.verbose, extended=self.cobertura_extended) def runSonarQubeMetrics(self): print("Creating SonarQube Metrics") From 571702dc7d8996ceef5a7966639fb924026cd5ec Mon Sep 17 00:00:00 2001 From: TimSVector Date: Mon, 1 Jul 2024 11:39:25 -0400 Subject: [PATCH 017/112] update for FB101427 - language issue in datapi --- src/main/resources/scripts/managewait.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/resources/scripts/managewait.py b/src/main/resources/scripts/managewait.py index 92a71d80..43eeef0d 100644 --- a/src/main/resources/scripts/managewait.py +++ b/src/main/resources/scripts/managewait.py @@ -44,7 +44,6 @@ def __init__(self, verbose, command_line, wait_time, wait_loops): self.wait_loops = wait_loops self.verbose = verbose self.command_line = command_line - self.encFmt = 'utf-8' # get the VC langaguge and encoding self.encFmt = 'utf-8' @@ -60,6 +59,8 @@ def __init__(self, verbose, command_line, wait_time, wait_loops): except: pass + os.environ['PYTHONIOENCODING'] = self.encFmt + def enqueueOutput(self, io_target, queue, logfile): while True: line = io_target.readline() @@ -79,7 +80,7 @@ def startOutputThread(self, io_target, logfile): self.io_t.start() def exec_manage(self, silent=False): - with open("command.log", 'a') as logfile: + with open("command.log", 'a', encoding=self.encFmt) as logfile: return self.__exec_manage(silent, logfile) def __exec_manage(self, silent, logfile): @@ -89,12 +90,12 @@ def __exec_manage(self, silent, logfile): if self.verbose: logfile.write( "\nVerbose: %s\n" % callStr) - + # capture the output of the manage call loop_count = 0 while 1: loop_count += 1 - p = subprocess.Popen(callStr,stdout=subprocess.PIPE,stderr=subprocess.STDOUT, shell=True, universal_newlines=True) + p = subprocess.Popen(callStr,stdout=subprocess.PIPE,stderr=subprocess.STDOUT, shell=True, universal_newlines=True, encoding=self.encFmt) self.startOutputThread(p.stdout, logfile) @@ -156,6 +157,7 @@ def __exec_manage(self, silent, logfile): ## main if __name__ == '__main__': + parser = argparse.ArgumentParser() parser.add_argument('-v', '--verbose', help='Enable verbose output', action="store_true") parser.add_argument('--command_line', help='Command line to pass to Manage', required=True) From 020449d48ec374c0fec2c22bfdb482df0d13d7af Mon Sep 17 00:00:00 2001 From: TimSVector Date: Mon, 1 Jul 2024 14:50:25 -0400 Subject: [PATCH 018/112] Updates for PMD warnings --- .../vectorcastexecution/VectorCASTJobRoot.java | 6 +----- .../vectorcastexecution/VectorCASTSetup.java | 14 +++++--------- .../vectorcastexecution/common/VcastUtils.java | 2 -- .../plugins/vectorcastexecution/job/BaseJob.java | 10 ++++------ .../vectorcastexecution/job/NewPipelineJob.java | 9 ++------- .../vectorcastexecution/job/NewSingleJob.java | 3 --- 6 files changed, 12 insertions(+), 32 deletions(-) diff --git a/src/main/java/com/vectorcast/plugins/vectorcastexecution/VectorCASTJobRoot.java b/src/main/java/com/vectorcast/plugins/vectorcastexecution/VectorCASTJobRoot.java index e53e6ca8..ac7fde26 100644 --- a/src/main/java/com/vectorcast/plugins/vectorcastexecution/VectorCASTJobRoot.java +++ b/src/main/java/com/vectorcast/plugins/vectorcastexecution/VectorCASTJobRoot.java @@ -28,8 +28,6 @@ import java.util.List; import jenkins.model.Jenkins; -import java.util.logging.Level; -import java.util.logging.Logger; import hudson.security.Permission; import hudson.security.PermissionGroup; import hudson.security.PermissionScope; @@ -123,10 +121,8 @@ public JobBase getDynamic(String name) { for (JobBase ui : getAll()) { if (ui != null) { String urlName = ui.getUrlName(); - if (urlName != null) { - if (urlName.equals(name)) { + if (urlName != null && urlName.equals(name)) { return ui; - } } } } diff --git a/src/main/java/com/vectorcast/plugins/vectorcastexecution/VectorCASTSetup.java b/src/main/java/com/vectorcast/plugins/vectorcastexecution/VectorCASTSetup.java index 2646d31e..3737d66d 100644 --- a/src/main/java/com/vectorcast/plugins/vectorcastexecution/VectorCASTSetup.java +++ b/src/main/java/com/vectorcast/plugins/vectorcastexecution/VectorCASTSetup.java @@ -523,7 +523,7 @@ public void setPclpCommand(String pclpCommand) { * @return true/false if we have a PC Lint Command */ public boolean getUsingPCLP() { - return (pclpCommand.length() != 0); + return pclpCommand.length() != 0; } /** * Get pc-lint plus result pattern @@ -545,7 +545,7 @@ public void setPclpResultsPattern(String pclpResultsPattern) { * @return true/false if we have a squoreCommand */ public boolean getUsingSquoreCommand() { - return (squoreCommand.length() != 0); + return squoreCommand.length() != 0; } /** @@ -856,7 +856,7 @@ public void perform(Run build, FilePath workspace, Launcher launcher, TaskL try { jFile.close(); } catch (IOException ex) { - // Ignore + assert true; } } } @@ -868,11 +868,8 @@ public void perform(Run build, FilePath workspace, Launcher launcher, TaskL { for (File file : files) { - if (file.isFile()) - { - if (!file.delete()) { - throw new IOException("Unable to delete file: " + file.getAbsolutePath()); - } + if (file.isFile() && !file.delete()) { + throw new IOException("Unable to delete file: " + file.getAbsolutePath()); } } } @@ -908,7 +905,6 @@ public String getDisplayName() { return Messages.VectorCASTSetup_DisplayName(); } } - private static final Logger logger = Logger.getLogger(VectorCASTSetup.class.getName()); @Override public String toString() { diff --git a/src/main/java/com/vectorcast/plugins/vectorcastexecution/common/VcastUtils.java b/src/main/java/com/vectorcast/plugins/vectorcastexecution/common/VcastUtils.java index e6ace053..ff0a5b1b 100644 --- a/src/main/java/com/vectorcast/plugins/vectorcastexecution/common/VcastUtils.java +++ b/src/main/java/com/vectorcast/plugins/vectorcastexecution/common/VcastUtils.java @@ -27,9 +27,7 @@ import java.io.IOException; import java.net.URLDecoder; import java.util.Optional; -import java.util.jar.Attributes; import java.util.jar.JarFile; -import java.util.jar.Manifest; import java.io.FileNotFoundException; public class VcastUtils diff --git a/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/BaseJob.java b/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/BaseJob.java index 2d90b775..b3d79b78 100644 --- a/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/BaseJob.java +++ b/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/BaseJob.java @@ -73,7 +73,7 @@ abstract public class BaseJob { /** Base name generated from the manage project name */ private String baseName; /** Top-level project */ - private Project topProject; + protected Project topProject; /** Environment setup for windows */ private String environmentSetupWin; /** Environment setup for unix */ @@ -171,9 +171,7 @@ protected BaseJob(final StaplerRequest request, final StaplerResponse response, baseName = FilenameUtils.getBaseName(manageProjectName); this.useSavedData = useSavedData; - if (useSavedData) { - // Data will be set later - } else { + if (!useSavedData) { this.usingSCM = false; environmentSetupWin = json.optString("environmentSetupWin"); @@ -232,12 +230,12 @@ protected BaseJob(final StaplerRequest request, final StaplerResponse response, } } } - externalResultsFilename = json.optString("externalResultsFilename", "").replace('\\','/');; + externalResultsFilename = json.optString("externalResultsFilename", "").replace('\\','/'); useCoverageHistory = json.optBoolean("useCoverageHistory", false); maxParallel = json.optLong("maxParallel", 0); /* Additional Tools */ - pclpCommand = json.optString("pclpCommand", "").replace('\\','/');; + pclpCommand = json.optString("pclpCommand", "").replace('\\','/'); pclpResultsPattern = json.optString("pclpResultsPattern", ""); squoreCommand = json.optString("squoreCommand", "").replace('\\','/'); TESTinsights_URL = json.optString("TESTinsights_URL", ""); diff --git a/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/NewPipelineJob.java b/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/NewPipelineJob.java index d09fd394..388f2206 100644 --- a/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/NewPipelineJob.java +++ b/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/NewPipelineJob.java @@ -31,12 +31,10 @@ import net.sf.json.JSONObject; import java.io.BufferedReader; -import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.OutputStreamWriter; -import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -61,7 +59,6 @@ import java.util.logging.Logger; import java.util.logging.Level; -import java.util.Map; import javax.servlet.ServletException; import javax.servlet.http.HttpServletResponse; @@ -76,9 +73,7 @@ public class NewPipelineJob extends BaseJob { /** project name */ private String projectName; - - private Project topProject; - + private String sharedArtifactDirectory; private String pipelineSCM = ""; @@ -287,7 +282,7 @@ public void doCreate(boolean update) throws IOException, ServletException, Descr e.printStackTrace(); } catch (SAXException e) { e.printStackTrace(); - } catch (java.lang.IllegalArgumentException e) { + } catch (IllegalArgumentException e) { e.printStackTrace(); } diff --git a/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/NewSingleJob.java b/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/NewSingleJob.java index 35b7a3cb..ee894a0c 100644 --- a/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/NewSingleJob.java +++ b/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/NewSingleJob.java @@ -335,13 +335,10 @@ private void addCommandSingleJob() { */ private void addGroovyScriptSingleJob() { String html_text; - String html_newline; if (getOptionHTMLBuildDesc().equalsIgnoreCase("HTML")) { html_text = ".html"; - html_newline = "
"; } else { html_text = ".txt"; - html_newline = "\\n"; } String script = "import hudson.FilePath\n" + From c46aaf77f4734f9cffaae99af63469729e530b7c Mon Sep 17 00:00:00 2001 From: TimSVector Date: Wed, 3 Jul 2024 16:35:41 -0400 Subject: [PATCH 019/112] RGW workaround testing --- src/main/resources/scripts/copy_build_dir.py | 27 +++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/src/main/resources/scripts/copy_build_dir.py b/src/main/resources/scripts/copy_build_dir.py index ab051433..33ace0b3 100644 --- a/src/main/resources/scripts/copy_build_dir.py +++ b/src/main/resources/scripts/copy_build_dir.py @@ -31,6 +31,7 @@ import sqlite3 import shutil import tee_print +from patch_rgw_directory import getReqRepo global build_dir @@ -87,10 +88,12 @@ def addFile(tf, file, backOneDir = False): except: pass -def addDirectory(tf, dir): - global build_dir +def addDirectory(tf, build_dir, dir): - rootDir = os.path.join(build_dir,dir) + if build_dir is None: + rootDir = dir + else: + rootDir = os.path.join(build_dir,dir).replace("\\","/") for dirName, subdirList, fileList in os.walk(rootDir): for fname in fileList: @@ -160,18 +163,28 @@ def addConvertFiles(tf, workspace, nocase): os.environ['VCAST_MANAGE_PROJECT_DIRECTORY'] = os.path.abspath(ManageProjectName).rsplit(".",1)[0] manageCMD = os.path.join(os.environ.get('VECTORCAST_DIR'), "manage") - p = subprocess.Popen(manageCMD + " --project " + ManageProjectName + " --build-directory-name --level " + Level + " -e " + Env, + cmd = manageCMD + " --project " + ManageProjectName + " --build-directory-name --level " + Level + " -e " + Env + print(cmd) + p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, universal_newlines=True) out, err = p.communicate() list = out.splitlines() build_dir = '' + for str in list: if "Build Directory:" in str: length = len(str.split()[0]) + 1 + len(str.split()[1]) + 1 build_dir = os.path.relpath(str[length:]) + try: + rgwDir = getReqRepo(ManageProjectName).replace("\\","/").replace(workspace+"/","") + rgwExportDir = os.path.join(rgwDir, "requirements_gateway/export_data") + except: + pass + + if build_dir != "": build_dir = build_dir + os.path.sep + Env tf = tarfile.open(BaseName + "_build.tar", mode='w') @@ -185,7 +198,7 @@ def addConvertFiles(tf, workspace, nocase): addFile(tf, "testcase_data.xml") addFile(tf, "*.LIS") addFile(tf, "system_test_results.xml") - addDirectory(tf, "TESTCASES") + addDirectory(tf, build_dir, "TESTCASES") addFile(tf, Env + ".vce", backOneDir=True) addFile(tf, Env + ".vcp", backOneDir=True) addFile(tf, Env + ".env", backOneDir=True) @@ -193,6 +206,8 @@ def addConvertFiles(tf, workspace, nocase): addFile(tf, Env + "_cba.cvr", backOneDir=True) addFile(tf, "vcast_manage.cfg", backOneDir=True) - + if rgwDir is not None: + addDirectory(tf, None, rgwExportDir) + finally: tf.close() From b42580532ae153cc15282f33c021257b0e9b7833 Mon Sep 17 00:00:00 2001 From: TimSVector Date: Mon, 8 Jul 2024 11:24:54 -0400 Subject: [PATCH 020/112] RGW3 trial --- .../vectorcastexecution/VectorCASTSetup.java | 21 ++++++ .../vectorcastexecution/job/BaseJob.java | 20 ++++++ .../job/NewPipelineJob.java | 1 + .../vectorcastexecution/job/NewSingleJob.java | 20 +++++- .../lib/VectorCAST/jobOptionsNoDefault.jelly | 5 ++ .../VectorCAST/jobOptionsNoDefault.properties | 3 + .../lib/VectorCAST/jobOptionsPipeline.jelly | 5 ++ .../VectorCAST/jobOptionsPipeline.properties | 4 ++ .../resources/scripts/baseJenkinsfile.groovy | 25 +++++-- src/main/resources/scripts/copy_build_dir.py | 5 +- .../resources/scripts/extract_build_dir.py | 12 +++- src/main/resources/scripts/generate_xml.py | 4 ++ .../resources/scripts/patch_rgw_directory.py | 67 +++++++++++++++++++ src/main/webapp/help-optuseRGW3.html | 27 ++++++++ 14 files changed, 207 insertions(+), 12 deletions(-) create mode 100644 src/main/resources/scripts/patch_rgw_directory.py create mode 100644 src/main/webapp/help-optuseRGW3.html diff --git a/src/main/java/com/vectorcast/plugins/vectorcastexecution/VectorCASTSetup.java b/src/main/java/com/vectorcast/plugins/vectorcastexecution/VectorCASTSetup.java index 3737d66d..c7d3d990 100644 --- a/src/main/java/com/vectorcast/plugins/vectorcastexecution/VectorCASTSetup.java +++ b/src/main/java/com/vectorcast/plugins/vectorcastexecution/VectorCASTSetup.java @@ -82,6 +82,8 @@ public class VectorCASTSetup extends Builder implements SimpleBuildStep { private boolean useCILicenses; /** Use strict testcase import */ private boolean useStrictTestcaseImport; + /** Use RGW3 */ + private boolean useRGW3; /** Use imported results */ private boolean useImportedResults = false; private boolean useLocalImportedResults = false; @@ -346,6 +348,21 @@ public boolean getUseStrictTestcaseImport() { public void setUseStrictTestcaseImport(boolean useStrictTestcaseImport) { this.useStrictTestcaseImport = useStrictTestcaseImport; } + + /** + * Get option to Use RGW3 capabilities + * @return true use RGW3 capabilities, false to not + */ + public boolean getUseRGW3() { + return useRGW3; + } + /** + * Set option to use RGW3 capabilities + * @param useRGW3 true to allow RGW3 test cases to run and export + */ + public void setUseRGW3(boolean useRGW3) { + this.useRGW3 = useRGW3; + } /** * Get option to use coverage plugin or vectorcast coverage plugin * @return true use coverage plugin or vectorcast coverage plugin @@ -664,6 +681,7 @@ public void setTESTinsights_SCM_Tech(String TESTinsights_SCM_Tech) { * @param optionClean clean * @param useCILicenses use CI licenses * @param useStrictTestcaseImport Use strict testcase import + * @param useRGW3 Use RGW3 capabilities * @param useImportedResults use imported results * @param useLocalImportedResults use local imported results * @param useExternalImportedResults use extern imported results @@ -699,6 +717,7 @@ public VectorCASTSetup(String environmentSetupWin, boolean optionClean, boolean useCILicenses, boolean useStrictTestcaseImport, + boolean useRGW3, boolean useImportedResults, boolean useLocalImportedResults, boolean useExternalImportedResults, @@ -732,6 +751,7 @@ public VectorCASTSetup(String environmentSetupWin, this.optionClean = optionClean; this.useCILicenses = useCILicenses; this.useStrictTestcaseImport = useStrictTestcaseImport; + this.useRGW3 = useRGW3; this.useImportedResults = useImportedResults; this.useLocalImportedResults = useLocalImportedResults; this.useExternalImportedResults = useExternalImportedResults; @@ -923,6 +943,7 @@ public String toString() { + "\t optionClean: " + optionClean + "\n" + "\t useCILicenses: " + useCILicenses + "\n" + "\t useStrictTestcaseImport: " + useStrictTestcaseImport + "\n" + + "\t useRGW3: " + useRGW3 + "\n" + "\t useImportedResults: " + useImportedResults + "\n" + "\t useLocalImportedResults: " + useLocalImportedResults + "\n" + "\t useExternalImportedResults: " + useExternalImportedResults + "\n" diff --git a/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/BaseJob.java b/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/BaseJob.java index b3d79b78..5757f8a3 100644 --- a/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/BaseJob.java +++ b/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/BaseJob.java @@ -102,6 +102,9 @@ abstract public class BaseJob { /** Use strict testcase import */ private boolean useStrictTestcaseImport; + /** Allow RGW3 test to be executed and exported */ + private boolean useRGW3; + /** Use coveagePlugin */ private boolean useCoveragePlugin = true; @@ -202,6 +205,7 @@ protected BaseJob(final StaplerRequest request, final StaplerResponse response, useCILicenses = json.optBoolean("useCiLicense", false); useStrictTestcaseImport = json.optBoolean("useStrictTestcaseImport", true); + useRGW3 = json.optBoolean("useRGW3", false); useImportedResults = json.optBoolean("useImportedResults", false); if (json.optInt("coverageDisplayOption", 0) == 0) { useCoveragePlugin = true; @@ -267,6 +271,7 @@ public void useSavedData(VectorCASTSetup savedData) { optionClean = savedData.getOptionClean(); useCILicenses = savedData.getUseCILicenses(); useStrictTestcaseImport = savedData.getUseStrictTestcaseImport(); + useRGW3 = savedData.getUseRGW3(); useImportedResults = savedData.getUseImportedResults(); useLocalImportedResults = savedData.getUseLocalImportedResults(); useExternalImportedResults = savedData.getUseExternalImportedResults(); @@ -489,6 +494,20 @@ protected boolean getUseStrictTestcaseImport() { protected void setUseStrictTestcaseImport(boolean useStrictTestcaseImport) { this.useStrictTestcaseImport = useStrictTestcaseImport; } + /** + * Get option to Use RGW3 capabilities + * @return true use RGW3 capabilities, false to not + */ + protected boolean getUseRGW3() { + return useRGW3; + } + /** + * Set option to use RGW3 capabilities + * @param useRGW3 true to allow RGW3 test cases to run and export + */ + protected void setUseRGW3(boolean useRGW3) { + this.useRGW3 = useRGW3; + } /** * Get option to use coverage plugin or vectorcast coverage plugin * @return true use coverage plugin or vectorcast coverage plugin @@ -870,6 +889,7 @@ protected VectorCASTSetup addSetup(Project project) { optionClean, useCILicenses, useStrictTestcaseImport, + useRGW3, useImportedResults, useLocalImportedResults, useExternalImportedResults, diff --git a/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/NewPipelineJob.java b/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/NewPipelineJob.java index 388f2206..199eaa80 100644 --- a/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/NewPipelineJob.java +++ b/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/NewPipelineJob.java @@ -464,6 +464,7 @@ private String generateJenkinsfile() throws IOException { "VC_TESTinsights_Revision = \"\"\n" + "VC_useCoverageHistory = " + getUseCoverageHistory() + "\n" + "VC_useStrictImport = " + getUseStrictTestcaseImport() + "\n" + + "VC_useRGW3 = " + getUseRGW3() + "\n" + "VC_useImportedResults = " + getUseImportedResults() + "\n" + "VC_useLocalImportedResults = " + getUseLocalImportedResults() + "\n" + "VC_useExternalImportedResults = " + getUseExternalImportedResults() + "\n" + diff --git a/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/NewSingleJob.java b/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/NewSingleJob.java index ee894a0c..d78961ee 100644 --- a/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/NewSingleJob.java +++ b/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/NewSingleJob.java @@ -154,6 +154,12 @@ private void addCommandSingleJob() { addEnvVars += "set VCAST_USE_STRICT_IMPORT=FALSE\n"; } + if (getUseRGW3()) { + addEnvVars += "set VCAST_USE_RGW3=TRUE\n"; + } else { + addEnvVars += "set VCAST_USE_RGW3=FALSE\n"; + } + if (getUseLocalImportedResults()) { addEnvVars += "set VCAST_USE_LOCAL_IMPORTED_RESULTS=TRUE\n"; } else { @@ -219,7 +225,10 @@ private void addCommandSingleJob() { win += "%VECTORCAST_DIR%\\vpython \"%WORKSPACE%\\vc_scripts\\managewait.py\" --wait_time " + getWaitTime() + " --wait_loops " + getWaitLoops() + " --command_line \"--project \\\"@PROJECT@\\\" --config VCAST_CUSTOM_REPORT_FORMAT=HTML\"\n" + "%VECTORCAST_DIR%\\vpython \"%WORKSPACE%\\vc_scripts\\generate-results.py\" --junit --wait_time " + getWaitTime() + " --wait_loops " + getWaitLoops() + " \"@PROJECT@\" " + noGenExecReport + " --buildlog complete_build.log\n" + -"\"%VCAST_USE_COVERAGE_PLUGIN%\"==\"TRUE\" ( \n" + +"if \"%VCAST_USE_RGW3\"==\"TRUE\" (\n" + +" %VECTORCAST_DIR%\\vpython \"%WORKSPACE%\\vc_scripts\\managewait.py\" --wait_time " + getWaitTime() + " --wait_loops " + getWaitLoops() + " --command_line \"--project \\\"@PROJECT@\\\" --clicast-args rgw export\"\n" + +")\n" + +"if \"%VCAST_USE_COVERAGE_PLUGIN%\"==\"TRUE\" ( \n" + " %VECTORCAST_DIR%\\vpython \"%WORKSPACE%\\vc_scripts\\cobertura.py\" \"@PROJECT@\"\n" + ")\n" + "%VECTORCAST_DIR%\\vpython \"%WORKSPACE%\\vc_scripts\\full_report_no_toc.py\" \"@PROJECT@\" \n" + @@ -243,6 +252,12 @@ private void addCommandSingleJob() { } else { addEnvVars += "VCAST_USE_STRICT_IMPORT=0\n"; } + if (getUseRGW3()) { + addEnvVars += "VCAST_USE_RGW3=1\n"; + } else { + addEnvVars += "VCAST_USE_RGW3=0\n"; + } + if (getUseLocalImportedResults()) { addEnvVars += "VCAST_USE_LOCAL_IMPORTED_RESULTS=1\n"; } else { @@ -308,6 +323,9 @@ private void addCommandSingleJob() { unix += "$VECTORCAST_DIR/vpython \"$WORKSPACE/vc_scripts/managewait.py\" --wait_time " + getWaitTime() + " --wait_loops " + getWaitLoops() + " --command_line \"--project \\\"@PROJECT@\\\" --config VCAST_CUSTOM_REPORT_FORMAT=HTML\"\n" + "$VECTORCAST_DIR/vpython \"$WORKSPACE/vc_scripts/generate-results.py\" --junit --wait_time " + getWaitTime() + " --wait_loops " + getWaitLoops() + " \"@PROJECT@\" " + noGenExecReport + " --buildlog complete_build.log\n" + +"if [[ $VCAST_USE_RGW3 -eq 1 ]] ; then \n" + +" $VECTORCAST_DIR/vpython \"$WORKSPACE/vc_scripts/managewait.py\" --wait_time " + getWaitTime() + " --wait_loops " + getWaitLoops() + " --command_line \"--project \\\"@PROJECT@\\\" --clicast-args rgw export\\\"\"\n" + +")\n" + "if [[ $VCAST_USE_COVERAGE_PLUGIN -eq 1 ]] ; then \n" + " $VECTORCAST_DIR/vpython \"$WORKSPACE/vc_scripts/cobertura.py\" \"@PROJECT@\"\n" + "fi\n" + diff --git a/src/main/resources/lib/VectorCAST/jobOptionsNoDefault.jelly b/src/main/resources/lib/VectorCAST/jobOptionsNoDefault.jelly index 51bd73fe..1db9599b 100644 --- a/src/main/resources/lib/VectorCAST/jobOptionsNoDefault.jelly +++ b/src/main/resources/lib/VectorCAST/jobOptionsNoDefault.jelly @@ -53,6 +53,11 @@ help="/plugin/vectorcast-execution/help-optuseStrictTestcaseImport.html"> + + + + + + 1: + leaveFiles = True +except: + pass + for file in os.listdir("."): if file.endswith("_build.tar"): print("* Extracting " + file) @@ -36,4 +44,6 @@ tf.close() except: print("Problem with tarfile " + file + "...skipping") - os.remove(file) + + if not leaveFiles: + os.remove(file) diff --git a/src/main/resources/scripts/generate_xml.py b/src/main/resources/scripts/generate_xml.py index 128b5687..14628118 100644 --- a/src/main/resources/scripts/generate_xml.py +++ b/src/main/resources/scripts/generate_xml.py @@ -685,6 +685,10 @@ def generate_cover(self): for env in environments: if not env.is_active: continue + try: + n = len(env.api.SourceFile.all()) + except: + continue for srcFile in env.api.SourceFile.all(): display_path = srcFile.display_path if display_path not in localDisplayPaths: diff --git a/src/main/resources/scripts/patch_rgw_directory.py b/src/main/resources/scripts/patch_rgw_directory.py new file mode 100644 index 00000000..44381df1 --- /dev/null +++ b/src/main/resources/scripts/patch_rgw_directory.py @@ -0,0 +1,67 @@ +import subprocess, os +import argparse +from managewait import ManageWait + +def getReqRepo(VC_Manage_Project, testing=False): + VC_waitLoops = 1 + VC_waitTime = 30 + + command_line= f"--project \"{VC_Manage_Project}\" --list-configuration\"" + manageWait = ManageWait(False, command_line, VC_waitTime, VC_waitLoops) + output = manageWait.exec_manage(True) + + lines = output.split("\n") + + reqRepoDir = None + if testing: + reqRepoDir = "d:/dev/PointOfSales_v2/CurrentRelease/vcast-workarea/vc_manage/reqrepo" + else: + for line in lines: + if "VCAST_REPOSITORY" in line: + reqRepoDir = line.split("VCAST_REPOSITORY VALUE:")[1] + break + + if reqRepoDir is None: + raise("Requirements Repository Directory not set") + + reqRepoDir = reqRepoDir.replace("\\","/").strip() + + print(reqRepoDir) + + return reqRepoDir + +def updateReqRepo(VC_Manage_Project, VC_Workspace, testing): + + VC_Workspace = VC_Workspace.replace("\\","/") + + reqRepoDir = getReqRepo(VC_Manage_Project, testing) + + projDir = VC_Manage_Project.replace("\\","/").rsplit("/",1)[0] + + if projDir in reqRepoDir: + + basePath = reqRepoDir.split(projDir,1)[0] + newPath = os.path.join(VC_Workspace, reqRepoDir.replace(basePath,"")).replace("\\","/") + + if not os.path.exists(newPath): + raise Exception(f'Patch ReqRepo Path {newPath} not found') + + command_line = f"--project \"{VC_Manage_Project}\" --config VCAST_REPOSITORY={newPath}\"" + manageWait = ManageWait(False, command_line, 30, 1) + manageWait.exec_manage(True) + + print(f"RGW directory patched from:\n {reqRepoDir}\n {newPath}") + else: + print(f"RGW directory not patched:\n {reqRepoDir}\n {projDir}") + + +## main +if __name__ == '__main__': + + parser = argparse.ArgumentParser() + parser.add_argument('VcProject', help='VectorCAST Project Name') + parser.add_argument('-v', '--verbose', default=False, help='Enable verbose output', action="store_true") + parser.add_argument('-t', '--testing', default=False, help='Enable testing code', action="store_true") + args = parser.parse_args() + + updateReqRepo(args.VcProject, os.getenv('WORKSPACE'), args.testing) \ No newline at end of file diff --git a/src/main/webapp/help-optuseRGW3.html b/src/main/webapp/help-optuseRGW3.html new file mode 100644 index 00000000..99d91bed --- /dev/null +++ b/src/main/webapp/help-optuseRGW3.html @@ -0,0 +1,27 @@ + + +
+ This option enables Requirements Gateway v3 jobs to execute and export data at the end of the run. +
From b062c0d4b590b634ab03222e8dd073e9f9a939ca Mon Sep 17 00:00:00 2001 From: TimSVector Date: Mon, 8 Jul 2024 11:36:26 -0400 Subject: [PATCH 021/112] Updates for using coverage history only with legacy coverage plugin --- .../resources/lib/VectorCAST/jobOptionsNoDefault.properties | 4 ++-- .../resources/lib/VectorCAST/jobOptionsPipeline.properties | 2 +- src/main/webapp/help-optuseCoverageHistory.html | 2 ++ 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/resources/lib/VectorCAST/jobOptionsNoDefault.properties b/src/main/resources/lib/VectorCAST/jobOptionsNoDefault.properties index d36a4f90..3abf7baf 100644 --- a/src/main/resources/lib/VectorCAST/jobOptionsNoDefault.properties +++ b/src/main/resources/lib/VectorCAST/jobOptionsNoDefault.properties @@ -33,8 +33,8 @@ VCJob.JobOptions.nodeLabel.description = The node label is used for the Pipeline VCJob.JobOptions.sharedArtifactDir.title = Shared Artifact Directory VCJob.JobOptions.sharedArtifactDir.description = Specify a shared artifact directory to be used for the VectorCAST Project. Use only if all executors have access to the fully qualified path -VCJob.JobOptions.useCoverageHistory.title = Use Coverage History -VCJob.JobOptions.useCoverageHistory.description = Mark build as failed if statement or branch coverage decrease +VCJob.JobOptions.useCoverageHistory.title = Use Coverage History with Legacy VectorCAST Coverage Plugin +VCJob.JobOptionsPipeline.useCoverageHistory.description = Mark build as failed if statement or branch coverage decrease. Use with Legacy VectorCAST Coverage Plugin VCJob.JobOptions.useStrictTestcaseImport.title = Use Strict Test Case Importing VCJob.JobOptions.useStrictTestcaseImport.description = Any errors encountered during test script import cause the test case's status to be set to Fail. diff --git a/src/main/resources/lib/VectorCAST/jobOptionsPipeline.properties b/src/main/resources/lib/VectorCAST/jobOptionsPipeline.properties index a4227842..1c028b7b 100644 --- a/src/main/resources/lib/VectorCAST/jobOptionsPipeline.properties +++ b/src/main/resources/lib/VectorCAST/jobOptionsPipeline.properties @@ -28,7 +28,7 @@ VCJob.JobOptionsPipeline.jobName.title = Job name VCJob.JobOptionsPipeline.jobName.description = The name to be used for the Pipeline Job (if not blank) VCJob.JobOptionsPipeline.useCoverageHistory.title = Use Coverage History -VCJob.JobOptionsPipeline.useCoverageHistory.description = Mark build as failed if statement or branch coverage decrease +VCJob.JobOptionsPipeline.useCoverageHistory.description = Mark build as failed if statement or branch coverage decrease. Use with legacy VectorCAST Coverage Plugin VCJob.JobOptionsPipeline.useStrictTestcaseImport.title = Use Strict Test Case Importing VCJob.JobOptionsPipeline.useStrictTestcaseImport.description = Any errors encountered during test script import cause the test case's status to be set to Fail. diff --git a/src/main/webapp/help-optuseCoverageHistory.html b/src/main/webapp/help-optuseCoverageHistory.html index a0db3a5d..6be8843c 100644 --- a/src/main/webapp/help-optuseCoverageHistory.html +++ b/src/main/webapp/help-optuseCoverageHistory.html @@ -23,5 +23,7 @@ THE SOFTWARE. -->
+

This option is used with the Legacy VectorCAST Coverage Plugin

This option will compare the previous build's statement and branch coverage to the current build's statement and branch coverage. If either of the coverages have decreased the job will be marked as failed. +
From 8847b3b901befb9d8954850d08400e43cb423ac5 Mon Sep 17 00:00:00 2001 From: TimSVector Date: Tue, 9 Jul 2024 10:22:12 -0400 Subject: [PATCH 022/112] Updates from RGW3 testing --- .../vectorcastexecution/job/NewSingleJob.java | 2 +- .../lib/VectorCAST/jobOptionsNoDefault.jelly | 3 +- .../VectorCAST/jobOptionsNoDefault.properties | 6 +- .../lib/VectorCAST/jobOptionsPipeline.jelly | 5 +- .../VectorCAST/jobOptionsPipeline.properties | 7 +- .../resources/scripts/baseJenkinsfile.groovy | 430 +++++++++--------- src/main/resources/scripts/copy_build_dir.py | 1 + .../resources/scripts/patch_rgw_directory.py | 26 +- src/main/webapp/help-optuseRGW3.html | 2 +- 9 files changed, 245 insertions(+), 237 deletions(-) diff --git a/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/NewSingleJob.java b/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/NewSingleJob.java index d78961ee..ca70dce3 100644 --- a/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/NewSingleJob.java +++ b/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/NewSingleJob.java @@ -225,7 +225,7 @@ private void addCommandSingleJob() { win += "%VECTORCAST_DIR%\\vpython \"%WORKSPACE%\\vc_scripts\\managewait.py\" --wait_time " + getWaitTime() + " --wait_loops " + getWaitLoops() + " --command_line \"--project \\\"@PROJECT@\\\" --config VCAST_CUSTOM_REPORT_FORMAT=HTML\"\n" + "%VECTORCAST_DIR%\\vpython \"%WORKSPACE%\\vc_scripts\\generate-results.py\" --junit --wait_time " + getWaitTime() + " --wait_loops " + getWaitLoops() + " \"@PROJECT@\" " + noGenExecReport + " --buildlog complete_build.log\n" + -"if \"%VCAST_USE_RGW3\"==\"TRUE\" (\n" + +"if \"%VCAST_USE_RGW3%\"==\"TRUE\" (\n" + " %VECTORCAST_DIR%\\vpython \"%WORKSPACE%\\vc_scripts\\managewait.py\" --wait_time " + getWaitTime() + " --wait_loops " + getWaitLoops() + " --command_line \"--project \\\"@PROJECT@\\\" --clicast-args rgw export\"\n" + ")\n" + "if \"%VCAST_USE_COVERAGE_PLUGIN%\"==\"TRUE\" ( \n" + diff --git a/src/main/resources/lib/VectorCAST/jobOptionsNoDefault.jelly b/src/main/resources/lib/VectorCAST/jobOptionsNoDefault.jelly index 1db9599b..f3f5d3c6 100644 --- a/src/main/resources/lib/VectorCAST/jobOptionsNoDefault.jelly +++ b/src/main/resources/lib/VectorCAST/jobOptionsNoDefault.jelly @@ -58,7 +58,8 @@ help="/plugin/vectorcast-execution/help-optuseRGW3.html"> - diff --git a/src/main/resources/lib/VectorCAST/jobOptionsNoDefault.properties b/src/main/resources/lib/VectorCAST/jobOptionsNoDefault.properties index 3abf7baf..00171159 100644 --- a/src/main/resources/lib/VectorCAST/jobOptionsNoDefault.properties +++ b/src/main/resources/lib/VectorCAST/jobOptionsNoDefault.properties @@ -34,7 +34,7 @@ VCJob.JobOptions.sharedArtifactDir.title = Shared Artifact Directory VCJob.JobOptions.sharedArtifactDir.description = Specify a shared artifact directory to be used for the VectorCAST Project. Use only if all executors have access to the fully qualified path VCJob.JobOptions.useCoverageHistory.title = Use Coverage History with Legacy VectorCAST Coverage Plugin -VCJob.JobOptionsPipeline.useCoverageHistory.description = Mark build as failed if statement or branch coverage decrease. Use with Legacy VectorCAST Coverage Plugin +VCJob.JobOptions.useCoverageHistory.description = Mark build as failed if statement or branch coverage decrease. Use with Legacy VectorCAST Coverage Plugin VCJob.JobOptions.useStrictTestcaseImport.title = Use Strict Test Case Importing VCJob.JobOptions.useStrictTestcaseImport.description = Any errors encountered during test script import cause the test case's status to be set to Fail. @@ -51,5 +51,5 @@ VCJob.JobOptions.useExternalImportedResults.description = Import results from ex VCJob.JobOptions.externalResultsFilename.title = External Result Filename VCJob.JobOptions.externalResultsFilename.description = External Result Filename (.vcr) -VCJob.JobOptions.useRGW3.title = External Result Filename -VCJob.JobOptions.useRGW3.description = External Result Filename (.vcr) +VCJob.JobOptions.useRGW3.title = Use Requirements Gateway 3 capabilities +VCJob.JobOptions.useRGW3.description = Specifies that test environments with existing tests linked to an Requirements Gateway v3 implementation to execute and export data at the end of the run diff --git a/src/main/resources/lib/VectorCAST/jobOptionsPipeline.jelly b/src/main/resources/lib/VectorCAST/jobOptionsPipeline.jelly index 6494a122..47121e97 100644 --- a/src/main/resources/lib/VectorCAST/jobOptionsPipeline.jelly +++ b/src/main/resources/lib/VectorCAST/jobOptionsPipeline.jelly @@ -65,10 +65,11 @@ + help="/plugin/vectorcast-execution/help-optuseRGW3.html"> - diff --git a/src/main/resources/lib/VectorCAST/jobOptionsPipeline.properties b/src/main/resources/lib/VectorCAST/jobOptionsPipeline.properties index 1c028b7b..7095c1d8 100644 --- a/src/main/resources/lib/VectorCAST/jobOptionsPipeline.properties +++ b/src/main/resources/lib/VectorCAST/jobOptionsPipeline.properties @@ -27,7 +27,7 @@ VCJob.JobOptionsPipeline = Job Options VCJob.JobOptionsPipeline.jobName.title = Job name VCJob.JobOptionsPipeline.jobName.description = The name to be used for the Pipeline Job (if not blank) -VCJob.JobOptionsPipeline.useCoverageHistory.title = Use Coverage History +VCJob.JobOptionsPipeline.useCoverageHistory.title = Use Coverage History with Legacy VectorCAST Coverage Plugin VCJob.JobOptionsPipeline.useCoverageHistory.description = Mark build as failed if statement or branch coverage decrease. Use with legacy VectorCAST Coverage Plugin VCJob.JobOptionsPipeline.useStrictTestcaseImport.title = Use Strict Test Case Importing @@ -54,6 +54,5 @@ VCJob.JobOptionsPipeline.sharedArtifactDir.description = Specify a shared artifa VCJob.JobOptionsPipeline.maxParallel.title = Maximum Parallel Queued Jobs VCJob.JobOptionsPipeline.maxParallel.description = Specifies the maximum number of unit test jobs to queue up at any one time for parallel execution. To queue all jobs, leave blank or set to zero (0) -VCJob.JobOptionsPipeline.useRGW3.title = Use Requirements Gateway 3 -VCJob.JobOptionsPipeline.useRGW3.description = Specifies that actions required for gathering back requirements .json files and exporting will be executed - +VCJob.JobOptionsPipeline.useRGW3.title = Use Requirements Gateway 3 capabilities +VCJob.JobOptionsPipeline.useRGW3.description = Specifies that test environments with existing tests linked to an Requirements Gateway v3 implementation to execute and export data at the end of the run diff --git a/src/main/resources/scripts/baseJenkinsfile.groovy b/src/main/resources/scripts/baseJenkinsfile.groovy index 483edb73..0a168151 100644 --- a/src/main/resources/scripts/baseJenkinsfile.groovy +++ b/src/main/resources/scripts/baseJenkinsfile.groovy @@ -2,12 +2,12 @@ // Basis path coverage is no longer support after VectorCAST 2019SP1 VC_Healthy_Target = [ maxStatement: 100, maxBranch: 100, maxFunctionCall: 100, maxFunction: 100, maxMCDC: 100, minStatement: 20, minBranch: 20, minFunctionCall: 20, minFunction: 20, minMCDC: 20] - + VC_Use_Threshold = true // =============================================================== -// +// // Generic file from VectorCAST Pipeline Plug-in DO NOT ALTER // // =============================================================== @@ -16,7 +16,7 @@ VC_Use_Threshold = true // Failure phrases for checkLogsForErrors VC_FailurePhrases = ["No valid edition(s) available", - "py did not execute correctly", + "py did not execute correctly", "Traceback (most recent call last)", "Failed to acquire lock on environment", "Environment Creation Failed", @@ -38,22 +38,22 @@ VC_FailurePhrases = ["No valid edition(s) available", "Please ensure that the project has the proper permissions and that the environment is not being accessed by another process.", "Error: That command is not permitted in continuous integration mode" ] - + // Unstable phrases for checkLogsForErrors -VC_UnstablePhrases = ["Dropping probe point", - "Value Line Error - Command Ignored", - "INFO: Problem parsing test results file", - "INFO: File System Error ", - "ERROR: Error accessing DataAPI", +VC_UnstablePhrases = ["Dropping probe point", + "Value Line Error - Command Ignored", + "INFO: Problem parsing test results file", + "INFO: File System Error ", + "ERROR: Error accessing DataAPI", "ERROR: Undefined Error" - ] - + ] + // =============================================================== // // Function : checkLogsForErrors // Inputs : log -// Action : Scans the input log file to for keywords listed above +// Action : Scans the input log file to for keywords listed above // Returns : found foundKeywords, failure and/or unstable_flag // Notes : Used to Check for VectorCAST build errors/problems // @@ -67,20 +67,20 @@ def checkLogsForErrors(log) { // Check for unstable first // Loop over all the unstable keywords above - VC_UnstablePhrases.each { + VC_UnstablePhrases.each { if (log.contains(it)) { - // found a phrase considered unstable, mark the build accordingly - foundKeywords = foundKeywords + it + ", " + // found a phrase considered unstable, mark the build accordingly + foundKeywords = foundKeywords + it + ", " unstable_flag = true } } - + // The check for failure keywords first // Loop over all the failure keywords above - VC_FailurePhrases.each { + VC_FailurePhrases.each { if (log.contains(it)) { - // found a phrase considered failure, mark the build accordingly - foundKeywords = foundKeywords + it + ", " + // found a phrase considered failure, mark the build accordingly + foundKeywords = foundKeywords + it + ", " failure = true } } @@ -95,7 +95,7 @@ def checkLogsForErrors(log) { // // Function : checkBuildLogForErrors // Inputs : logFile -// Action : Scans the input log file to for keywords listed above +// Action : Scans the input log file to for keywords listed above // Returns : found foundKeywords, failure and/or unstable_flag // Notes : Used to Check for VectorCAST build errors/problems // @@ -118,7 +118,7 @@ def checkBuildLogForErrors(logFile) { cmd = "findstr /g:phrases.txt " + logFile + " > search_results.txt" status = bat label: 'Checking build log for errors', returnStatus: true, script: cmd } - + if (status == 0) { output = readFile("search_results.txt") foundKeywords += output.replaceAll("\n",",") @@ -126,13 +126,13 @@ def checkBuildLogForErrors(logFile) { } else { return [foundKeywords, failure, unstable_flag] } - + error ("Error in checking build log file: " + cmd) - + } // *************************************************************** -// +// // SCM Utilities // // *************************************************************** @@ -149,26 +149,26 @@ def checkBuildLogForErrors(logFile) { def get_SCM_rev() { def scm_rev = "" def cmd = "" - + if (VC_TESTinsights_SCM_Tech=='git') { cmd = "git rev-parse HEAD" } else { cmd = "svn info --show-item revision" } - + if (isUnix()) { scm_rev = sh returnStdout: true, script: cmd } else { cmd = "@echo off \n " + cmd scm_rev = bat returnStdout: true, script: cmd } - + println "Git Rev Reply " + scm_rev.trim() + "***" return scm_rev.trim() } // *************************************************************** -// +// // File/Pathing Utilities // // *************************************************************** @@ -177,8 +177,8 @@ def get_SCM_rev() { // // Function : getMPname // Inputs : None -// Action : Returns the base name -// Notes : Used for creating report name +// Action : Returns the base name +// Notes : Used for creating report name // // =============================================================== @@ -198,12 +198,12 @@ def getMPname() { // // Function : stripLeadingWhitespace // Inputs : string or multiline string with leading spaces -// Action : input string with leading spaces removed +// Action : input string with leading spaces removed // Notes : None // // =============================================================== def stripLeadingWhitespace(str) { - def lines = str.split('\n') + def lines = str.split('\n') def trimmedString = "" lines.each { line -> trimmedString += line.trim() + "\n" @@ -217,7 +217,7 @@ def stripLeadingWhitespace(str) { // // Function : getMPpath // Inputs : None -// Action : Returns the path name to the manage project's directory +// Action : Returns the path name to the manage project's directory // Notes : Used for accessing the build directory // // =============================================================== @@ -237,7 +237,7 @@ def getMPpath() { // // Function : formatPath // Inputs : directory path -// Action : on Windows it will change / path seperators to \ (\\) +// Action : on Windows it will change / path seperators to \ (\\) // Returns : fixed path // Notes : Used to Check for VectorCAST build errors/problems // @@ -254,7 +254,7 @@ def formatPath(inPath) { // =============================================================== // // Function : fixUpName -// Inputs : command list +// Inputs : command list // Action : Fixup name so it doesn't include / or %## or any other special characters // Returns : Fixed up name // Notes : Used widely @@ -268,7 +268,7 @@ def fixUpName(name) { // =============================================================== // // Function : concatenateBuildLogs -// Inputs : file list +// Inputs : file list // Action : Concatenate build logs into one file // Returns : None // Notes : Generate-Overall-Reports @@ -276,14 +276,14 @@ def fixUpName(name) { // =============================================================== def concatenateBuildLogs(logFileNames, outputFileName) { - + def cmd = "" if (isUnix()) { cmd = "cat " } else { cmd = "type " } - + cmd += logFileNames + " > " + outputFileName runCommands(cmd) @@ -291,7 +291,7 @@ def concatenateBuildLogs(logFileNames, outputFileName) { // *************************************************************** -// +// // Execution Utilities // // *************************************************************** @@ -300,7 +300,7 @@ def concatenateBuildLogs(logFileNames, outputFileName) { // =============================================================== // // Function : runCommands -// Inputs : command list +// Inputs : command list // Action : 1. Adds VC Setup calls to beginning of script // 2. If using CI licenses, it set the appropriate envionment variables // 3. Replaces keywords for windows/linux @@ -315,23 +315,23 @@ def runCommands(cmds) { def boolean unstable_flag = false; def foundKeywords = "" def localCmds = """""" - + // clear that old command log writeFile file: "command.log", text: "" - + // if its Linux run the sh command and save the stdout for analysis if (isUnix()) { // add VC setup to beginning of script // add extra env vars to make debugging of commands useful - // add extra env for reports + // add extra env for reports localCmds = """ ${VC_EnvSetup} export VCAST_RPTS_PRETTY_PRINT_HTML=FALSE export VCAST_NO_FILE_TRUNCATION=1 export VCAST_RPTS_SELF_CONTAINED=FALSE - + """ - + // if using CI licenses add in both CI license env vars if (VC_UseCILicense.length() != 0) { localCmds += """ @@ -342,23 +342,23 @@ def runCommands(cmds) { cmds = localCmds + cmds cmds = stripLeadingWhitespace(cmds.replaceAll("_VECTORCAST_DIR","\\\$VECTORCAST_DIR").replaceAll("_RM","rm -rf ").replaceAll("_COPY","cp -p ").replaceAll("_IF_EXIST","if [[ -f ").replaceAll("_IF_THEN"," ]] ; then ").replaceAll("_ENDIF"," fi") ) println "Running commands: " + cmds - + // run command in shell sh label: 'Running VectorCAST Commands', returnStdout: false, script: cmds - + } else { // add VC setup to beginning of script // add extra env vars to make debugging of commands useful - // add extra env for reports + // add extra env for reports localCmds = """ @echo off ${VC_EnvSetup} set VCAST_RPTS_PRETTY_PRINT_HTML=FALSE set VCAST_NO_FILE_TRUNCATION=1 set VCAST_RPTS_SELF_CONTAINED=FALSE - + """ - + // if using CI licenses add in both CI license env vars if (VC_UseCILicense.length() != 0) { localCmds += """ @@ -369,16 +369,16 @@ def runCommands(cmds) { cmds = localCmds + cmds cmds = stripLeadingWhitespace(cmds.replaceAll("_VECTORCAST_DIR","%VECTORCAST_DIR%").replaceAll("_RM","DEL /Q ").replaceAll("_COPY","copy /y /b").replaceAll("_IF_EXIST","if exist ").replaceAll("_IF_THEN"," ( ").replaceAll("_ENDIF"," )")) println "Running commands: " + cmds - + // run command in bat bat label: 'Running VectorCAST Commands', returnStdout: false, script: cmds } - - // read back the command.log - this is specific to + + // read back the command.log - this is specific to log = readFile "command.log" - - println "Commands Output: " + log - + + println "Commands Output: " + log + return log } @@ -386,8 +386,8 @@ def runCommands(cmds) { // // Function : setupManageProject // Inputs : none -// Action : Issues commands needed to run manage project from -// .vcm and environment defintions +// Action : Issues commands needed to run manage project from +// .vcm and environment defintions // Returns : None // Notes : Used once per manage project checkout // @@ -395,24 +395,24 @@ def runCommands(cmds) { def setupManageProject() { def mpName = getMPname() - + def cmds = """""" - + if (VC_sharedArtifactDirectory.length() > 0) { - cmds += """ - _VECTORCAST_DIR/vpython "${env.WORKSPACE}"/vc_scripts/managewait.py --wait_time ${VC_waitTime} --wait_loops ${VC_waitLoops} --command_line "--project "${VC_Manage_Project}" ${VC_UseCILicense} ${VC_sharedArtifactDirectory} --status" + cmds += """ + _VECTORCAST_DIR/vpython "${env.WORKSPACE}"/vc_scripts/managewait.py --wait_time ${VC_waitTime} --wait_loops ${VC_waitLoops} --command_line "--project "${VC_Manage_Project}" ${VC_UseCILicense} ${VC_sharedArtifactDirectory} --status" """ - } + } if (VC_useStrictImport) { - cmds += """ - _VECTORCAST_DIR/vpython "${env.WORKSPACE}"/vc_scripts/managewait.py --wait_time ${VC_waitTime} --wait_loops ${VC_waitLoops} --command_line "--project "${VC_Manage_Project}" ${VC_UseCILicense} --config=VCAST_STRICT_TEST_CASE_IMPORT=TRUE" + cmds += """ + _VECTORCAST_DIR/vpython "${env.WORKSPACE}"/vc_scripts/managewait.py --wait_time ${VC_waitTime} --wait_loops ${VC_waitLoops} --command_line "--project "${VC_Manage_Project}" ${VC_UseCILicense} --config=VCAST_STRICT_TEST_CASE_IMPORT=TRUE" """ } - cmds += """ + cmds += """ _RM *_rebuild.html - _VECTORCAST_DIR/vpython "${env.WORKSPACE}"/vc_scripts/managewait.py --wait_time ${VC_waitTime} --wait_loops ${VC_waitLoops} --command_line "--project "${VC_Manage_Project}" ${VC_UseCILicense} --status" + _VECTORCAST_DIR/vpython "${env.WORKSPACE}"/vc_scripts/managewait.py --wait_time ${VC_waitTime} --wait_loops ${VC_waitLoops} --command_line "--project "${VC_Manage_Project}" ${VC_UseCILicense} --status" _VECTORCAST_DIR/vpython "${env.WORKSPACE}"/vc_scripts/managewait.py --wait_time ${VC_waitTime} --wait_loops ${VC_waitLoops} --command_line "--project "${VC_Manage_Project}" ${VC_UseCILicense} --force --release-locks" _VECTORCAST_DIR/vpython "${env.WORKSPACE}"/vc_scripts/managewait.py --wait_time ${VC_waitTime} --wait_loops ${VC_waitLoops} --command_line "--project "${VC_Manage_Project}" ${VC_UseCILicense} --config VCAST_CUSTOM_REPORT_FORMAT=HTML" """ @@ -422,8 +422,8 @@ def setupManageProject() { try { copyArtifacts filter: "${mpName}_results.vcr", fingerprintArtifacts: true, optional: true, projectName: "${env.JOB_NAME}", selector: lastSuccessful() cmds += """ - _VECTORCAST_DIR/vpython "${env.WORKSPACE}"/vc_scripts/managewait.py --wait_time ${VC_waitTime} --wait_loops ${VC_waitLoops} --command_line "--project "${VC_Manage_Project}" ${VC_UseCILicense} --force --import-result=${mpName}_results.vcr" - _VECTORCAST_DIR/vpython "${env.WORKSPACE}"/vc_scripts/managewait.py --wait_time ${VC_waitTime} --wait_loops ${VC_waitLoops} --command_line "--project "${VC_Manage_Project}" ${VC_UseCILicense} --status" + _VECTORCAST_DIR/vpython "${env.WORKSPACE}"/vc_scripts/managewait.py --wait_time ${VC_waitTime} --wait_loops ${VC_waitLoops} --command_line "--project "${VC_Manage_Project}" ${VC_UseCILicense} --force --import-result=${mpName}_results.vcr" + _VECTORCAST_DIR/vpython "${env.WORKSPACE}"/vc_scripts/managewait.py --wait_time ${VC_waitTime} --wait_loops ${VC_waitLoops} --command_line "--project "${VC_Manage_Project}" ${VC_UseCILicense} --status" _IF_EXIST ${mpName}_results.vcr _IF_THEN _COPY ${mpName}_results.vcr ${mpName}_results_orig.vcr _ENDIF """ } catch (exe) { @@ -432,15 +432,15 @@ def setupManageProject() { } else if (VC_useExternalImportedResults) { if (VC_externalResultsFilename.length() != 0) { cmds += """ - _VECTORCAST_DIR/vpython "${env.WORKSPACE}"/vc_scripts/managewait.py --wait_time ${VC_waitTime} --wait_loops ${VC_waitLoops} --command_line "--project "${VC_Manage_Project}" ${VC_UseCILicense} --force --import-result=${VC_externalResultsFilename}" - _VECTORCAST_DIR/vpython "${env.WORKSPACE}"/vc_scripts/managewait.py --wait_time ${VC_waitTime} --wait_loops ${VC_waitLoops} --command_line "--project "${VC_Manage_Project}" ${VC_UseCILicense} --status" + _VECTORCAST_DIR/vpython "${env.WORKSPACE}"/vc_scripts/managewait.py --wait_time ${VC_waitTime} --wait_loops ${VC_waitLoops} --command_line "--project "${VC_Manage_Project}" ${VC_UseCILicense} --force --import-result=${VC_externalResultsFilename}" + _VECTORCAST_DIR/vpython "${env.WORKSPACE}"/vc_scripts/managewait.py --wait_time ${VC_waitTime} --wait_loops ${VC_waitLoops} --command_line "--project "${VC_Manage_Project}" ${VC_UseCILicense} --status" """ } else { error ("External result specified, but external result file is blank") } } } - + runCommands(cmds) } @@ -456,20 +456,20 @@ def setupManageProject() { // =============================================================== def transformIntoStep(inputString) { - + // grab the compiler test_suite and environment out the single line def (compiler, test_suite, environment) = inputString.split() - + // set the stashed file name for later String stashName = fixUpName("${env.JOB_NAME}_${compiler}_${test_suite}_${environment}-build-execute-stage") - + // return the auto-generated node and job // node is based on compiler label - // this will route the job to a specific node matching that label + // this will route the job to a specific node matching that label return { catchError(buildResult: 'UNSTABLE', stageResult: 'FAILURE') { - - // Try to use VCAST_FORCE_NODE_EXEC_NAME parameter. + + // Try to use VCAST_FORCE_NODE_EXEC_NAME parameter. // If 0 length or not present, use the compiler name as a node label def nodeID = "default" try { @@ -482,28 +482,28 @@ def transformIntoStep(inputString) { } catch (exe) { nodeID = compiler } - + print "Using NodeID = " + nodeID - - + + // node definition and job starting here node ( nodeID as String ){ - + println "Starting Build-Execute Stage for ${compiler}/${test_suite}/${environment}" - + // if we are not using a single checkout directory if (!VC_useOneCheckoutDir) { - + // call the scmStep for each job scmStep() } - + // Run the setup step to copy over the scripts step([$class: 'VectorCASTSetup']) // if we are not using a single checkout directory and using SCM step if (VC_usingSCM && !VC_useOneCheckoutDir) { - + // set options for each manage project pulled out out of SCM setupManageProject() } @@ -517,28 +517,28 @@ def transformIntoStep(inputString) { ${VC_EnvTeardown} """ } else { - + cmds = """ ${VC_EnvSetup} ${VC_Build_Preamble} _VECTORCAST_DIR/vpython "${env.WORKSPACE}"/vc_scripts/managewait.py --wait_time ${VC_waitTime} --wait_loops ${VC_waitLoops} --command_line "--project "${VC_Manage_Project}" ${VC_UseCILicense} --level ${compiler}/${test_suite} -e ${environment} --build-execute ${VC_useCBT} --output ${compiler}_${test_suite}_${environment}_rebuild.html" ${VC_EnvTeardown} """ - } - - + } + + // setup build lot test variable to hold all VC commands results for this job def buildLogText = "" - + // run the build-execute step and save the results buildLogText = runCommands(cmds) - + def foundKeywords = "" def boolean failure = false def boolean unstable_flag = false - + // check log for errors/unstable keywords - (foundKeywords, failure, unstable_flag) = checkLogsForErrors(buildLogText) - + (foundKeywords, failure, unstable_flag) = checkLogsForErrors(buildLogText) + // if we didn't fail and don't have a shared artifact directory - we may have to copy back build directory artifacts... if (!failure && VC_sharedArtifactDirectory.length() == 0) { @@ -548,27 +548,27 @@ def transformIntoStep(inputString) { buildLogText += runCommands("""_VECTORCAST_DIR/vpython "${env.WORKSPACE}"/vc_scripts/copy_build_dir.py ${VC_Manage_Project} ${compiler}/${test_suite} ${fixedJobName}_${compiler}_${test_suite}_${environment} ${environment}""" ) } } - + // write a build log file for compiler/test suite/environment writeFile file: "${compiler}_${test_suite}_${environment}_build.log", text: buildLogText // no cleanup - possible CBT // use individual names def fixedJobName = fixUpName("${env.JOB_NAME}") - + // save artifact in a "stash" to be "unstashed" by the main job stash includes: "${compiler}_${test_suite}_${environment}_build.log, **/${compiler}_${test_suite}_${environment}_rebuild.html, execution/*.html, management/*${compiler}_${test_suite}_${environment}*, xml_data/*${compiler}_${test_suite}_${environment}*, ${fixedJobName}_${compiler}_${test_suite}_${environment}_build.tar", name: stashName as String - + println "Finished Build-Execute Stage for ${compiler}/${test_suite}/${environment}" // check log for errors/unstable keywords again since the copy build dir could have thrown errors/unstable keywords - (foundKeywords, failure, unstable_flag) = checkLogsForErrors(buildLogText) - + (foundKeywords, failure, unstable_flag) = checkLogsForErrors(buildLogText) + // if something failed, raise an error if (failure) { error ("Error in Commands: " + foundKeywords) - - // else if something made the job unstable, mark as unsable + + // else if something made the job unstable, mark as unsable } else if (unstable_flag) { unstable("Triggering stage unstable because keywords found: " + foundKeywords) } @@ -591,7 +591,7 @@ def stepsForJobList(localEnvList) { localEnvList.each { jobList[it] = transformIntoStep(it) } - + return jobList } @@ -600,10 +600,10 @@ EnvList = [] UtEnvList = [] StEnvList = [] origManageProject = VC_Manage_Project - - + + // *************************************************************** -// +// // VectorCAST Execution Pipeline // // *************************************************************** @@ -612,7 +612,7 @@ pipeline { // Use the input from the job creation label as for the "main job" agent {label VC_Agent_Label as String} - + stages { // Place holder for previous stages the customer may need to use stage('Previous-Stage') { @@ -622,7 +622,7 @@ pipeline { } } } - + // If we are using a single checkout directory option, do the checkout here // This stage also includes the implementation for the parameterized Jenkins job // that includes a forced node name and an external repository @@ -645,18 +645,18 @@ pipeline { } catch (exe) { usingExternalRepo = false } - - // If we are using a single checkout directory option and its not a + + // If we are using a single checkout directory option and its not a // SMC checkout from another job... if (VC_useOneCheckoutDir && !usingExternalRepo) { - + // we need to convert all the future job's workspaces to point to the original checkout VC_OriginalWorkspace = "${env.WORKSPACE}" println "scmStep executed here: " + VC_OriginalWorkspace scmStep() print "Updating " + VC_Manage_Project + " to: " + VC_OriginalWorkspace + "/" + VC_Manage_Project VC_Manage_Project = VC_OriginalWorkspace + "/" + VC_Manage_Project - + def origSetup = VC_EnvSetup def origTeardown = VC_EnvTeardown def orig_VC_sharedArtifactDirectory = VC_sharedArtifactDirectory @@ -666,24 +666,24 @@ pipeline { VC_EnvSetup = VC_EnvSetup.replace("\$WORKSPACE" ,VC_OriginalWorkspace) VC_EnvTeardown = VC_EnvTeardown.replace("\$WORKSPACE" ,VC_OriginalWorkspace) VC_sharedArtifactDirectory = VC_sharedArtifactDirectory.replace("\$WORKSPACE" ,VC_OriginalWorkspace) - VC_postScmStepsCmds = VC_postScmStepsCmds.replace("\$WORKSPACE" ,VC_OriginalWorkspace) + VC_postScmStepsCmds = VC_postScmStepsCmds.replace("\$WORKSPACE" ,VC_OriginalWorkspace) } else { VC_OriginalWorkspace = VC_OriginalWorkspace.replace('\\','/') - + def tmpInfo = "" - + // replace case insensitive workspace with WORKSPACE tmpInfo = VC_EnvSetup.replaceAll("(?i)%WORKSPACE%","%WORKSPACE%") VC_EnvSetup = tmpInfo.replace("%WORKSPACE%",VC_OriginalWorkspace) - + // replace case insensitive workspace with WORKSPACE tmpInfo = VC_EnvTeardown.replaceAll("(?i)%WORKSPACE%","%WORKSPACE%") VC_EnvTeardown = tmpInfo.replace("%WORKSPACE%",VC_OriginalWorkspace) - + // replace case insensitive workspace with WORKSPACE tmpInfo = VC_sharedArtifactDirectory.replaceAll("(?i)%WORKSPACE%","%WORKSPACE%") VC_sharedArtifactDirectory = tmpInfo.replace("%WORKSPACE%" ,VC_OriginalWorkspace) - + // replace case insensitive workspace with WORKSPACE tmpInfo = VC_postScmStepsCmds.replaceAll("(?i)%WORKSPACE%","%WORKSPACE%") VC_postScmStepsCmds = tmpInfo.replace("%WORKSPACE%" ,VC_OriginalWorkspace) @@ -708,7 +708,7 @@ pipeline { } } } - + // This stage gets the information on the manage project from the full-status report // Parsing the output determines the level and environment name stage('Get-Environment-Info') { @@ -721,7 +721,7 @@ pipeline { if (!VC_useOneCheckoutDir) { // Get the repo (should only need the .vcm file) scmStep() - + // If there are post SCM checkout steps, do them now if (VC_postScmStepsCmds.length() > 0) { runCommands(VC_postScmStepsCmds) @@ -733,18 +733,18 @@ pipeline { // Run the setup step to copy over the scripts step([$class: 'VectorCASTSetup']) - + // ------------------------------------------------------------------------------------------- // this part could be done with Manage_Project.getJobs() but it doesn't seem to be working VVV def EnvData = "" - + // Run a script to determine the compiler test_suite and environment EnvData = runCommands("""_VECTORCAST_DIR/vpython "${env.WORKSPACE}"/vc_scripts/getjobs.py ${VC_Manage_Project} --type""") - + // for a groovy list that is stored in a global variable EnvList to be use later in multiple places def lines = EnvData.split('\n') - - // loop over each returned line from getjobs.py to determine if its a system test or unit test + + // loop over each returned line from getjobs.py to determine if its a system test or unit test // and add it to the appropriate list lines.each { line -> def trimmedString = line.trim() @@ -766,26 +766,26 @@ pipeline { print("??:" + trimmedString) return } - + print ("++ " + trimmedString) EnvList = EnvList + [trimmedString] - } + } } // down to here ^^^ - // ------------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------------------------- } } } - // This is the stage that we use the EnvList via stepsForJobList >> transformIntoStep + // This is the stage that we use the EnvList via stepsForJobList >> transformIntoStep stage('System Test Build-Execute Stage') { steps { script { setupManageProject() - + // Get the job list from the system test environment listed jobs = stepsForJobList(StEnvList) - + // run each of those jobs in serial jobs.each { name, job -> print ("Running System Test Job: " + name) @@ -795,15 +795,15 @@ pipeline { } } - // This is the stage that we use the EnvList via stepsForJobList >> transformIntoStep + // This is the stage that we use the EnvList via stepsForJobList >> transformIntoStep stage('Unit Test Build-Execute Stage') { steps { script { setupManageProject() - + // Get the job list from the unit test environment listed jobs = stepsForJobList(UtEnvList) - + if (VC_maxParallel > 0) { def runningJobs = [:] jobs.each { job -> @@ -820,96 +820,100 @@ pipeline { } else { // run those jobs in parallel parallel jobs - } + } } } } // Generating the reports needed for VectorCAST/Coverage plugin and JUnit stage('Generate-Overall-Reports') { - + steps { catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') { - + // Run the setup step to copy over the scripts step([$class: 'VectorCASTSetup']) - + // run script to unstash files and generate results/reports script { def buildFileNames = "" - + // Loop over all environnment and unstash each of the files // These files will be logs and build artifacts EnvList.each { (compiler, test_suite, environment) = it.split() String stashName = fixUpName("${env.JOB_NAME}_${compiler}_${test_suite}_${environment}-build-execute-stage") - + try { unstash stashName as String buildFileNames += "${compiler}_${test_suite}_${environment}_build.log " - + } catch (Exception ex) { println ex } - } - - concatenateBuildLogs(buildFileNames, "unstashed_build.log") - + } + + concatenateBuildLogs(buildFileNames, "unstashed_build.log") + // get the manage project's base name for use in rebuild naming def mpName = getMPname() - + def buildLogText = "" - + // if we are using SCM and not using a shared artifact directory... if (VC_usingSCM && !VC_useOneCheckoutDir && VC_sharedArtifactDirectory.length() == 0) { // run a script to extract stashed files and process data into xml reports def mpPath = getMPpath() def coverDBpath = formatPath(mpPath + "/build/vcast_data/cover.db") - + cmds = """ _RM ${coverDBpath} _VECTORCAST_DIR/vpython "${env.WORKSPACE}"/vc_scripts/extract_build_dir.py --leave_files _VECTORCAST_DIR/vpython "${env.WORKSPACE}"/vc_scripts/managewait.py --wait_time ${VC_waitTime} --wait_loops ${VC_waitLoops} --command_line "--project "${VC_Manage_Project}" ${VC_UseCILicense} --refresh" """ buildLogText += runCommands(cmds) - - } + + } // run the metrics at the end buildLogText += runCommands("""_VECTORCAST_DIR/vpython "${env.WORKSPACE}"/vc_scripts/generate-results.py ${VC_Manage_Project} --wait_time ${VC_waitTime} --wait_loops ${VC_waitLoops} --junit --buildlog unstashed_build.log""") - buildLogText += runCommands("""_VECTORCAST_DIR/vpython "${env.WORKSPACE}"/vc_scripts/managewait.py --wait_time ${VC_waitTime} --wait_loops ${VC_waitLoops} --command_line "--project "${VC_Manage_Project}" ${VC_UseCILicense} --clicast-args rgw export" """) + + if (VC_useRGW3) { + buildLogText += runCommands("""_VECTORCAST_DIR/vpython "${env.WORKSPACE}"/vc_scripts/patch_rgw_directory.py ${VC_Manage_Project}""") + buildLogText += runCommands("""_VECTORCAST_DIR/vpython "${env.WORKSPACE}"/vc_scripts/managewait.py --wait_time ${VC_waitTime} --wait_loops ${VC_waitLoops} --command_line "--project "${VC_Manage_Project}" ${VC_UseCILicense} --clicast-args rgw export" """) + } if (VC_useCoveragePlugin) { buildLogText += runCommands("""_VECTORCAST_DIR/vpython "${env.WORKSPACE}"/vc_scripts/cobertura.py ${VC_Manage_Project}""") } - - cmds = """ + + cmds = """ _VECTORCAST_DIR/vpython "${env.WORKSPACE}"/vc_scripts/incremental_build_report_aggregator.py ${mpName} --rptfmt HTML _VECTORCAST_DIR/vpython "${env.WORKSPACE}"/vc_scripts/full_report_no_toc.py "${VC_Manage_Project}" _VECTORCAST_DIR/vpython "${env.WORKSPACE}"/vc_scripts/managewait.py --wait_time ${VC_waitTime} --wait_loops ${VC_waitLoops} --command_line "--project "${VC_Manage_Project}" ${VC_UseCILicense} --create-report=aggregate --output=${mpName}_aggregate_report.html" """ - + if (VC_useImportedResults) { if (VC_useLocalImportedResults) { cmds += """ - _VECTORCAST_DIR/vpython "${env.WORKSPACE}"/vc_scripts/managewait.py --wait_time ${VC_waitTime} --wait_loops ${VC_waitLoops} --command_line "--project "${VC_Manage_Project}" ${VC_UseCILicense} --export-result=${mpName}_results.vcr" - _VECTORCAST_DIR/vpython "${env.WORKSPACE}"/vc_scripts/merge_vcr.py --new ${mpName}_results.vcr --orig ${mpName}_results_orig.vcr + _VECTORCAST_DIR/vpython "${env.WORKSPACE}"/vc_scripts/managewait.py --wait_time ${VC_waitTime} --wait_loops ${VC_waitLoops} --command_line "--project "${VC_Manage_Project}" ${VC_UseCILicense} --export-result=${mpName}_results.vcr" + _VECTORCAST_DIR/vpython "${env.WORKSPACE}"/vc_scripts/merge_vcr.py --new ${mpName}_results.vcr --orig ${mpName}_results_orig.vcr """ } } - + buildLogText += runCommands(cmds) - + writeFile file: "metrics_build.log", text: buildLogText - + buildFileNames += "metrics_build.log " concatenateBuildLogs(buildFileNames, "complete_build.log") - - (foundKeywords, failure, unstable_flag) = checkBuildLogForErrors("complete_build.log") - + + (foundKeywords, failure, unstable_flag) = checkBuildLogForErrors("complete_build.log") + if (failure) { throw new Exception ("Error in Commands: " + foundKeywords) } @@ -917,21 +921,21 @@ pipeline { if (VC_useCoverageHistory) { currResult = currentBuild.result } - + if (VC_useCoveragePlugin) { // Send reports to the Jenkins Coverage Plugin recordCoverage tools: [[parser: 'VECTORCAST', pattern: 'xml_data/cobertura/coverage_results*.xml']] - + } else { // Send reports to the VectorCAST Soverage Plugin - step([$class: 'VectorCASTPublisher', - includes: 'xml_data/coverage_results*.xml', - useThreshold: VC_Use_Threshold, + step([$class: 'VectorCASTPublisher', + includes: 'xml_data/coverage_results*.xml', + useThreshold: VC_Use_Threshold, healthyTarget: VC_Healthy_Target, useCoverageHistory: VC_useCoverageHistory, maxHistory : 20]) } - + if (VC_useCoverageHistory) { if ((currResult != currentBuild.result) && (currentBuild.result == 'FAILURE')) { createSummary icon: "error.gif", text: "Code Coverage Decreased" @@ -939,17 +943,17 @@ pipeline { addBadge icon: "error.gif", text: "Code Coverage Decreased" } } - + // Send test results to JUnit plugin step([$class: 'JUnitResultArchiver', keepLongStdio: true, allowEmptyResults: true, testResults: '**/test_results_*.xml']) } - } + } // Save all the html, xml, and txt files archiveArtifacts allowEmptyArchive: true, artifacts: '**/*.html, xml_data/*.xml, unit_test_fail_count.txt, **/*.png, **/*.css, complete_build.log, *_results.vcr' } } - + // checking the build log of all the VC commands that have run // setup overall job's build descript with aggregated incremental build report and full status report stage('Check-Build-Log') { @@ -958,62 +962,62 @@ pipeline { script { def mpName = getMPname() - + def foundKeywords = "" def boolean failure = false def boolean unstable_flag = false - - (foundKeywords, failure, unstable_flag) = checkBuildLogForErrors('complete_build.log') + + (foundKeywords, failure, unstable_flag) = checkBuildLogForErrors('complete_build.log') // if the found keywords is great that the init value \n then we found something // set the build description accordingly if (foundKeywords.size() > 0) { currentBuild.description += "Problematic data found in console output, search the console output for the following phrases: " + foundKeywords + "\n" } - + // Make sure the build completed and we have two key reports // - Using CBT - CombinedReport.html (combined rebuild reports from all the environments) // - full status report from the manage project - + // Grab the coverage differences def summaryText = "" - - if (fileExists('coverage_diffs.html_tmp')) { + + if (fileExists('coverage_diffs.html_tmp')) { summaryText = readFile('coverage_diffs.html_tmp') } else { - print "coverage_diffs.html_tmp missing" + print "coverage_diffs.html_tmp missing" } if (VC_useCBT) { if (fileExists('combined_incr_rebuild.tmp') && fileExists("${mpName}_full_report.html_tmp") && fileExists("${mpName}_metrics_report.html_tmp")) { // If we have both of these, add them to the summary in the "normal" job view // Blue ocean view doesn't have a summary - + summaryText += readFile('combined_incr_rebuild.tmp') + "
" + readFile("${mpName}_full_report.html_tmp") + "
" + readFile("${mpName}_metrics_report.html_tmp") createSummary icon: "monitor.gif", text: summaryText - + } else { - if (fileExists('combined_incr_rebuild.tmp')) { - print "combined_incr_rebuild.tmp found" + if (fileExists('combined_incr_rebuild.tmp')) { + print "combined_incr_rebuild.tmp found" } else { - print "combined_incr_rebuild.tmp missing" + print "combined_incr_rebuild.tmp missing" } - if (fileExists("${mpName}_full_report.html_tmp")) { - print "${mpName}_full_report.html_tmp found" + if (fileExists("${mpName}_full_report.html_tmp")) { + print "${mpName}_full_report.html_tmp found" } else { - print "${mpName}_full_report.html_tmp missing" + print "${mpName}_full_report.html_tmp missing" } - if (fileExists("${mpName}_metrics_report.html_tmp")) { - print "${mpName}_metrics_report.html_tmp found" + if (fileExists("${mpName}_metrics_report.html_tmp")) { + print "${mpName}_metrics_report.html_tmp found" } else { - print "${mpName}_metrics_report.html_tmp missing" + print "${mpName}_metrics_report.html_tmp missing" } - - // If not, something went wrong... Make the build as unstable + + // If not, something went wrong... Make the build as unstable currentBuild.result = 'UNSTABLE' createSummary icon: "warning.gif", text: "General Failure" currentBuild.description += "General Failure, Incremental Build Report or Full Report Not Present. Please see the console for more information\n" - } + } } else { if (fileExists("${mpName}_full_report.html_tmp") && fileExists("${mpName}_metrics_report.html_tmp")) { // If we have both of these, add them to the summary in the "normal" job view @@ -1021,25 +1025,25 @@ pipeline { summaryText += readFile("${mpName}_full_report.html_tmp") + "
" + readFile("${mpName}_metrics_report.html_tmp") createSummary icon: "monitor.gif", text: summaryText - + } else { - // If not, something went wrong... Make the build as unstable + // If not, something went wrong... Make the build as unstable currentBuild.result = 'UNSTABLE' createSummary icon: "warning.gif", text: "General Failure" currentBuild.description += "General Failure, Full Report or Metrics Report Not Present. Please see the console for more information\n" - } + } } // Remove temporary files used for summary page - def cmds = """ + def cmds = """ _RM coverage_diffs.html_tmp _RM combined_incr_rebuild.tmp _RM ${mpName}_full_report.html_tmp _RM ${mpName}_metrics_report.html_tmp """ - + runCommands(cmds) - + // use unit_test_fail_count.txt to see if there were any failed test cases // if any failed test cases, Junit will mark as at least unstable. def unitTestErrorCount = "" @@ -1057,15 +1061,15 @@ pipeline { } } } - + // Stage for additional tools from Vector // Currently supporting PC Lint Plus, Squore, and TESTInsights stage('Additional Tools') { steps { catchError(buildResult: 'UNSTABLE', stageResult: 'FAILURE') { script { - - // If there's a PC Lint Plus command... + + // If there's a PC Lint Plus command... if (VC_usePCLintPlus) { // run the PC Lint Plus command runCommands(VC_pclpCommand) @@ -1074,47 +1078,47 @@ pipeline { // Archive the PC Lint Results archiveArtifacts allowEmptyArchive: true, artifacts: VC_pclpResultsPattern } - + // If we are using Squore... if (VC_useSquore) { // Generate the results from Squore and run the squore command which should publish the information to Squore Server cmd = "${VC_squoreCommand}" runCommands(cmd) - + // Archive the Squore results archiveArtifacts allowEmptyArchive: true, artifacts: 'xml_data/squore_results*.xml' } - + // If we using TESTInsights... if (VC_useTESTinsights){ - + // using the credentials passed in when creating the job... withCredentials([usernamePassword(credentialsId: VC_TESTinsights_Credential_ID, usernameVariable : "VC_TI_USR", passwordVariable : "VC_TI_PWS")]){ TI_proxy = "" - + // if we are using a proxy to communicate with TESTInsights, set the proxy from data input during job creation if (VC_TESTinsights_Proxy.length() != 0) { TI_proxy = "--proxy ${VC_TESTinsights_Proxy}" } - // Build the base TESTInsights command + // Build the base TESTInsights command TESTinsight_Command = "testinsights_connector --api ${VC_TESTinsights_URL} --user " + VC_TI_USR + " --pass " + VC_TI_PWS + " --action PUSH --project ${VC_TESTinsights_Project} --test-object ${BUILD_NUMBER} --vc-project ${VC_Manage_Project} " + TI_proxy + " --log TESTinsights_Push.log" // If we are using an SCM, attempt to link the SCM info into TESTInsights if (VC_usingSCM) { - + // Get the TESTinsights Revision VC_TESTinsights_Revision = get_SCM_rev() println "Git Rev: ${VC_TESTinsights_Revision}" - + // Update the TESTInsights command TESTinsight_Command += " --vc-project-local-path=${origManageProject} --vc-project-scm-path=${VC_TESTinsights_SCM_URL}/${origManageProject} --src-local-path=${env.WORKSPACE} --src-scm-path=${VC_TESTinsights_SCM_URL}/ --vc-project-scm-technology=${VC_TESTinsights_SCM_Tech} --src-scm-technology=${VC_TESTinsights_SCM_Tech} --vc-project-scm-revision=${VC_TESTinsights_Revision} --src-scm-revision ${VC_TESTinsights_Revision} --versioned" - + } // Run the command to push data to TESTInsights runCommands(TESTinsight_Command) - + // Archive the push log archiveArtifacts allowEmptyArchive: true, artifacts: 'TESTinsights_Push.log' } @@ -1123,7 +1127,7 @@ pipeline { } } } - + // Place holder for previous stages the customer may need to use stage('Next-Stage') { steps { diff --git a/src/main/resources/scripts/copy_build_dir.py b/src/main/resources/scripts/copy_build_dir.py index d459674c..09fa734a 100644 --- a/src/main/resources/scripts/copy_build_dir.py +++ b/src/main/resources/scripts/copy_build_dir.py @@ -198,6 +198,7 @@ def addConvertFiles(tf, workspace, nocase): addFile(tf, "*.LIS") addFile(tf, "system_test_results.xml") addDirectory(tf, build_dir, "TESTCASES") + addFile(tf, "CCAST_.CFG", backOneDir=True) addFile(tf, Env + ".vce", backOneDir=True) addFile(tf, Env + ".vcp", backOneDir=True) addFile(tf, Env + ".env", backOneDir=True) diff --git a/src/main/resources/scripts/patch_rgw_directory.py b/src/main/resources/scripts/patch_rgw_directory.py index 44381df1..e38a0393 100644 --- a/src/main/resources/scripts/patch_rgw_directory.py +++ b/src/main/resources/scripts/patch_rgw_directory.py @@ -2,7 +2,7 @@ import argparse from managewait import ManageWait -def getReqRepo(VC_Manage_Project, testing=False): +def getReqRepo(VC_Manage_Project): VC_waitLoops = 1 VC_waitTime = 30 @@ -13,13 +13,10 @@ def getReqRepo(VC_Manage_Project, testing=False): lines = output.split("\n") reqRepoDir = None - if testing: - reqRepoDir = "d:/dev/PointOfSales_v2/CurrentRelease/vcast-workarea/vc_manage/reqrepo" - else: - for line in lines: - if "VCAST_REPOSITORY" in line: - reqRepoDir = line.split("VCAST_REPOSITORY VALUE:")[1] - break + for line in lines: + if "VCAST_REPOSITORY" in line: + reqRepoDir = line.split("VCAST_REPOSITORY VALUE:")[1] + break if reqRepoDir is None: raise("Requirements Repository Directory not set") @@ -30,11 +27,11 @@ def getReqRepo(VC_Manage_Project, testing=False): return reqRepoDir -def updateReqRepo(VC_Manage_Project, VC_Workspace, testing): +def updateReqRepo(VC_Manage_Project, VC_Workspace, top_level): VC_Workspace = VC_Workspace.replace("\\","/") - reqRepoDir = getReqRepo(VC_Manage_Project, testing) + reqRepoDir = getReqRepo(VC_Manage_Project,) projDir = VC_Manage_Project.replace("\\","/").rsplit("/",1)[0] @@ -50,6 +47,11 @@ def updateReqRepo(VC_Manage_Project, VC_Workspace, testing): manageWait = ManageWait(False, command_line, 30, 1) manageWait.exec_manage(True) + if top_level: + command_line = f"--project \"{VC_Manage_Project}\" --clicast-args option VCAST_REPOSITORY {newPath}\"" + manageWait = ManageWait(False, command_line, 30, 1) + manageWait.exec_manage(True) + print(f"RGW directory patched from:\n {reqRepoDir}\n {newPath}") else: print(f"RGW directory not patched:\n {reqRepoDir}\n {projDir}") @@ -61,7 +63,7 @@ def updateReqRepo(VC_Manage_Project, VC_Workspace, testing): parser = argparse.ArgumentParser() parser.add_argument('VcProject', help='VectorCAST Project Name') parser.add_argument('-v', '--verbose', default=False, help='Enable verbose output', action="store_true") - parser.add_argument('-t', '--testing', default=False, help='Enable testing code', action="store_true") + parser.add_argument('-t', '--top_level', default=False, help='Apply VCAST_REPOSITORY at the top level', action="store_true") args = parser.parse_args() - updateReqRepo(args.VcProject, os.getenv('WORKSPACE'), args.testing) \ No newline at end of file + updateReqRepo(args.VcProject, os.getenv('WORKSPACE'), args.top_level) \ No newline at end of file diff --git a/src/main/webapp/help-optuseRGW3.html b/src/main/webapp/help-optuseRGW3.html index 99d91bed..339b26ea 100644 --- a/src/main/webapp/help-optuseRGW3.html +++ b/src/main/webapp/help-optuseRGW3.html @@ -23,5 +23,5 @@ THE SOFTWARE. -->
- This option enables Requirements Gateway v3 jobs to execute and export data at the end of the run. + This option allows test environments with existing tests linked to an Requirements Gateway v3 implementation to execute and export data at the end of the run
From bc45f3ec62d548e8ff0dbf6832c5c70cafd18cbc Mon Sep 17 00:00:00 2001 From: TimSVector Date: Tue, 9 Jul 2024 10:25:37 -0400 Subject: [PATCH 023/112] Update for documentation --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index c00b5801..a435b2e2 100644 --- a/README.md +++ b/README.md @@ -174,13 +174,15 @@ environment before disabling. This takes into account enviornments that are dir ## Change Log -### Version 0.78 (17 Jun 2024) +### Version 0.78 (10 Sep 2024) - Adding in following capabilities - Extended Cobertura format output for use with [Jenkins Coverage Plugin](https://github.com/jenkinsci/coverage-plugin) - Unit Test Data format output in SonarQube format - Adding capability to generate an index.html for all .html reports - Refactored New Job code to reduce duplication - Moved to Jenkins 2.440 and Java 11 +- Added BETA support for RGW3 +- Removed VectorCAST Project Environment report ### Version 0.77 (26 Dec 2023) - Updated for findbugs to spotbugs From bd5ac85e7cd587b3b09a63b5b9767e930f8cfdd7 Mon Sep 17 00:00:00 2001 From: TimSVector Date: Tue, 9 Jul 2024 10:39:55 -0400 Subject: [PATCH 024/112] Updating auto tests --- .github/workflows/ci.yml | 3 +-- .github/workflows/coverage.yml | 4 ++-- .github/workflows/run-release-drafter.yml | 1 - .github/workflows/sync-labels.yml | 1 - 4 files changed, 3 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index feb069e1..e5b0894f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,7 +4,6 @@ on: push: branches: - master - - main pull_request: jobs: @@ -13,7 +12,7 @@ jobs: strategy: matrix: platform: [ubuntu-latest, windows-latest] - jdk: [17, 21] + jdk: [11, 17, 21] runs-on: ${{ matrix.platform }} name: on ${{ matrix.platform }} with JDK ${{ matrix.jdk }} diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 5b4060e6..2c1fb5c5 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -27,9 +27,9 @@ jobs: with: maven-version: 3.9.6 - name: Generate coverage with JaCoCo - run: mvn -V --color always -ntp clean verify '-Dgpg.skip' + run: mvn -V --color always -ntp clean verify -Pci --file pom.xml - name: Upload coverage to Codecov - uses: codecov/codecov-action@v4.3.0 + uses: codecov/codecov-action@v4.5.0 with: files: 'target/site/jacoco/jacoco.xml' token: ${{secrets.CODECOV_TOKEN}} diff --git a/.github/workflows/run-release-drafter.yml b/.github/workflows/run-release-drafter.yml index 44b786ac..9eed0915 100644 --- a/.github/workflows/run-release-drafter.yml +++ b/.github/workflows/run-release-drafter.yml @@ -4,7 +4,6 @@ on: push: branches: - master - - main jobs: update-release-draft: diff --git a/.github/workflows/sync-labels.yml b/.github/workflows/sync-labels.yml index e0ce7c9e..e770fa0e 100644 --- a/.github/workflows/sync-labels.yml +++ b/.github/workflows/sync-labels.yml @@ -3,7 +3,6 @@ on: push: branches: - master - - main paths: - .github/labels.yml - .github/workflows/sync-labels.yml From 7756ab0dd0af8cd437b06ff86aae6733c52b3c3b Mon Sep 17 00:00:00 2001 From: TimSVector Date: Tue, 9 Jul 2024 10:57:46 -0400 Subject: [PATCH 025/112] Updates for typos --- pom.xml | 4 +--- src/main/resources/lib/VectorCAST/jobOptionsPipeline.jelly | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 2eef35f4..24e8162e 100644 --- a/pom.xml +++ b/pom.xml @@ -250,10 +250,8 @@ org.jenkins-ci.tools maven-hpi-plugin + 3.55 true - - 2.0 - com.github.spotbugs diff --git a/src/main/resources/lib/VectorCAST/jobOptionsPipeline.jelly b/src/main/resources/lib/VectorCAST/jobOptionsPipeline.jelly index 47121e97..4c2d6fc6 100644 --- a/src/main/resources/lib/VectorCAST/jobOptionsPipeline.jelly +++ b/src/main/resources/lib/VectorCAST/jobOptionsPipeline.jelly @@ -68,7 +68,7 @@ help="/plugin/vectorcast-execution/help-optuseRGW3.html"> - Date: Tue, 9 Jul 2024 11:01:27 -0400 Subject: [PATCH 026/112] fixing version of coverage plugin --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 24e8162e..fcad9c92 100644 --- a/pom.xml +++ b/pom.xml @@ -166,7 +166,7 @@ io.jenkins.plugins coverage - 1.16.0-SNAPSHOT + 1.16.1 org.jenkins-ci.plugins From 0635200056466ee42678647c2270c7e0bbf1a732 Mon Sep 17 00:00:00 2001 From: TimSVector Date: Tue, 9 Jul 2024 14:34:43 -0400 Subject: [PATCH 027/112] Fixing CodeQL issues --- .../vectorcastexecution/job/BaseJob.java | 17 ++-- .../job/NewPipelineJob.java | 89 ++++++++++++------- 2 files changed, 67 insertions(+), 39 deletions(-) diff --git a/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/BaseJob.java b/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/BaseJob.java index 5757f8a3..25473b35 100644 --- a/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/BaseJob.java +++ b/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/BaseJob.java @@ -947,15 +947,14 @@ protected void addArchiveArtifacts(Project project) { */ protected void addCopyResultsToImport(Project project) { StatusBuildSelector selector = new StatusBuildSelector(); - CopyArtifact archiverCopier = new CopyArtifact( - /* ProjectName */ project.getName(), - /* Parameters */ "", - /* BuildSelector */ selector, - /* filter */ baseName + "_results.vcr", - /* target */ "", - /* flatten */ false, - /* optional */ true - ); + CopyArtifact archiverCopier = new CopyArtifact(project.getName()); + archiverCopier.setParameters(""); + archiverCopier.setSelector(selector); + archiverCopier.setFilter(baseName + "_results.vcr"); + archiverCopier.setTarget(""); + archiverCopier.setFlatten(false); + archiverCopier.setOptional(true); + project.getBuildersList().add(archiverCopier); } diff --git a/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/NewPipelineJob.java b/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/NewPipelineJob.java index 199eaa80..72220325 100644 --- a/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/NewPipelineJob.java +++ b/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/NewPipelineJob.java @@ -67,6 +67,16 @@ import java.util.List; import java.nio.charset.StandardCharsets; +import java.io.UncheckedIOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.attribute.PosixFilePermission; +import java.nio.file.attribute.PosixFilePermissions; +import java.nio.file.StandardCopyOption; + +import java.util.EnumSet; + /** * Create a new single job */ @@ -236,7 +246,7 @@ protected Project createProject() throws IOException, JobAlreadyExistsException public void doCreate(boolean update) throws IOException, ServletException, Descriptor.FormException { // Get config.xml resource from jar and write it to temp - File configFile = writeConfigFile(); + File configFile = writeConfigFile_FILES(); try { @@ -307,55 +317,74 @@ public void create(boolean update) throws IOException, ServletException, Descrip topProject = createProject(); doCreate(update); } + + static private Path createTempFile(Path tempDirChild) throws UncheckedIOException { + try { + if (tempDirChild.getFileSystem().supportedFileAttributeViews().contains("posix")) { + // Explicit permissions setting is only required on unix-like systems because + // the temporary directory is shared between all users. + // This is not necessary on Windows, each user has their own temp directory + final EnumSet posixFilePermissions = + EnumSet.of( + PosixFilePermission.OWNER_READ, + PosixFilePermission.OWNER_WRITE + ); + if (!Files.exists(tempDirChild)) { + Files.createFile( + tempDirChild, + PosixFilePermissions.asFileAttribute(posixFilePermissions) + ); // GOOD: Directory has permissions `-rw-------` + } else { + Files.setPosixFilePermissions( + tempDirChild, + posixFilePermissions + ); // GOOD: Good has permissions `-rw-------`, or will throw an exception if this fails + } + } else if (!Files.exists(tempDirChild)) { + // On Windows, we still need to create the directory, when it doesn't already exist. + Files.createDirectory(tempDirChild); // GOOD: Windows doesn't share the temp directory between users + } + + return tempDirChild.toAbsolutePath(); + } catch (IOException exception) { + throw new UncheckedIOException("Failed to create temp file", exception); + } + } /** * Retrieves config.xml from the jar and writes it to the systems temp * directory. * * @return - * @throws IOException + * @throws UncheckedIOException */ - private File writeConfigFile() throws IOException { - + private File writeConfigFile_FILES() throws IOException { InputStream in; - + Path configFile; + if (useParameters) { in = getClass().getResourceAsStream("/scripts/config_parameters.xml"); } else { in = getClass().getResourceAsStream("/scripts/config.xml"); } - //InputStream in = getClass().getResourceAsStream("/scripts/config_parameters.xml"); - BufferedReader br = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8)); - - // TODO: Should switch to Files for CodeQL - // Local information disclosure in a temporary directory - File configFile = File.createTempFile("config_temp", ".xml"); - - //FileWriter fw = null - FileOutputStream fosw = null; - OutputStreamWriter osrw = null; + configFile = createTempFile(Paths.get("config_temp.xml")); try { - // write out to temp file - fosw = new FileOutputStream(configFile); - osrw = new OutputStreamWriter(fosw, StandardCharsets.UTF_8); - - String line = null; - while ((line = br.readLine()) != null) { - osrw.write(line + "\n"); - } - } finally { - // cleanup - if (osrw != null) osrw.close(); - br.close(); - in.close(); - if (fosw != null) fosw.close(); + Files.copy(in, configFile, StandardCopyOption.REPLACE_EXISTING); + } catch (IOException exception) { + Logger.getLogger(NewPipelineJob.class.getName()).log(Level.SEVERE, null, exception); + } catch (UnsupportedOperationException exception) { + Logger.getLogger(NewPipelineJob.class.getName()).log(Level.SEVERE, null, exception); + } catch (SecurityException exception) { + Logger.getLogger(NewPipelineJob.class.getName()).log(Level.SEVERE, null, exception); } + + return configFile.toFile(); - return configFile.getAbsoluteFile(); } + /** * Get getSharedArtifactDirectory From 9fdc22c215c9424ef51044bb136cb3a743094936 Mon Sep 17 00:00:00 2001 From: Tim Schneider Date: Tue, 9 Jul 2024 15:13:27 -0400 Subject: [PATCH 028/112] Update coverage.yml --- .github/workflows/coverage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 2c1fb5c5..6d28c2ff 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -27,7 +27,7 @@ jobs: with: maven-version: 3.9.6 - name: Generate coverage with JaCoCo - run: mvn -V --color always -ntp clean verify -Pci --file pom.xml + run: mvn -V --color always -ntp clean verify --file pom.xml - name: Upload coverage to Codecov uses: codecov/codecov-action@v4.5.0 with: From 053c784fdffb18ee66e96fec7e9eae8f1b55921e Mon Sep 17 00:00:00 2001 From: Tim Schneider Date: Tue, 9 Jul 2024 15:15:05 -0400 Subject: [PATCH 029/112] Update pom.xml --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index fcad9c92..ddf1bbc9 100644 --- a/pom.xml +++ b/pom.xml @@ -223,7 +223,7 @@ org.apache.maven.plugins maven-compiler-plugin - 2.3.2 + 3.13.0 1.8 1.8 From f2e11c9f43ffb88fa42604e18ee9e7643a70b28a Mon Sep 17 00:00:00 2001 From: TimSVector Date: Tue, 9 Jul 2024 15:38:57 -0400 Subject: [PATCH 030/112] Updates --- .github/workflows/coverage.yml | 2 +- README.md | 5 +++++ pom.xml | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 2c1fb5c5..6d28c2ff 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -27,7 +27,7 @@ jobs: with: maven-version: 3.9.6 - name: Generate coverage with JaCoCo - run: mvn -V --color always -ntp clean verify -Pci --file pom.xml + run: mvn -V --color always -ntp clean verify --file pom.xml - name: Upload coverage to Codecov uses: codecov/codecov-action@v4.5.0 with: diff --git a/README.md b/README.md index a435b2e2..a5290efb 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,8 @@ +[![CodeCov](https://github.com/jenkinsci/vectorcast-execution-plugin/actions/workflows/coverage.yml/badge.svg?branch=tms_078)](https://github.com/jenkinsci/vectorcast-execution-plugin/actions/workflows/coverage.yml) +[![CodeQL](https://github.com/jenkinsci/vectorcast-execution-plugin/actions/workflows/codeql.yml/badge.svg?branch=tms_078)](https://github.com/jenkinsci/vectorcast-execution-plugin/actions/workflows/codeql.yml) +[![GitHub CI](https://github.com/jenkinsci/vectorcast-execution-plugin/actions/workflows/ci.yml/badge.svg?branch=tms_078)](https://github.com/jenkinsci/vectorcast-execution-plugin/actions/workflows/ci.yml) + + # Summary diff --git a/pom.xml b/pom.xml index fcad9c92..ddf1bbc9 100644 --- a/pom.xml +++ b/pom.xml @@ -223,7 +223,7 @@ org.apache.maven.plugins maven-compiler-plugin - 2.3.2 + 3.13.0 1.8 1.8 From 8d3bd80ab84811114fae1814dc45730a32cef8f4 Mon Sep 17 00:00:00 2001 From: TimSVector Date: Thu, 11 Jul 2024 11:23:11 -0400 Subject: [PATCH 031/112] Updates for -Xlint and additional tests --- pom.xml | 34 ++- .../plugins/vectorcastexecution/JobBase.java | 4 +- .../VectorCASTCommand.java | 8 +- .../VectorCASTJobDiag.java | 4 +- .../VectorCASTJobRoot.java | 10 +- .../vectorcastexecution/VectorCASTSetup.java | 157 +++++----- .../vectorcastexecution/job/BaseJob.java | 61 ++-- .../job/ExternalResultsFileException.java | 1 + .../job/InvalidProjectFileException.java | 1 + .../job/JobAlreadyExistsException.java | 2 + .../job/NewPipelineJob.java | 19 +- .../vectorcastexecution/job/NewSingleJob.java | 26 +- .../job/ScmConflictException.java | 2 + src/main/resources/scripts/generate_xml.py | 2 +- .../job/NewSingleJobTest.java | 281 +++++++++++++++--- 15 files changed, 422 insertions(+), 190 deletions(-) diff --git a/pom.xml b/pom.xml index ddf1bbc9..17b3a2ea 100644 --- a/pom.xml +++ b/pom.xml @@ -51,7 +51,7 @@ https://repo.jenkins-ci.org/public/ - incrementals.jenkins-ci.org + incremental.jenkins-ci.org https://repo.jenkins-ci.org/incrementals/ @@ -74,85 +74,85 @@ - + org.slf4j slf4j-api 2.0.13 - + io.jenkins.plugins javax-mail-api 1.6.2-10 - + org.jenkins-ci.plugins scm-api 683.vb_16722fb_b_80b_ - + org.apache.commons commons-lang3 3.14.0 - + org.apache.commons commons-text 1.12.0 - + org.apache.sshd sshd-core 2.12.1 - + io.jenkins.plugins.mina-sshd-api mina-sshd-api-core - + org.json json 20240303 - + org.jenkins-ci.plugins structs 337.v1b_04ea_4df7c8 - + io.jenkins.plugins caffeine-api 3.1.8-133.v17b_1ff2e0599 - + org.jenkins-ci.plugins display-url-api 2.204.vf6fddd8a_8b_e9 - + io.jenkins.plugins ionicons-api 74.v93d5eb_813d5f - + org.jenkins-ci.plugins script-security 1341.va_2819b_414686 - + org.jenkins-ci.plugins matrix-project @@ -227,6 +227,10 @@ 1.8 1.8 + diff --git a/src/main/java/com/vectorcast/plugins/vectorcastexecution/JobBase.java b/src/main/java/com/vectorcast/plugins/vectorcastexecution/JobBase.java index ecc6be7a..7f73afea 100644 --- a/src/main/java/com/vectorcast/plugins/vectorcastexecution/JobBase.java +++ b/src/main/java/com/vectorcast/plugins/vectorcastexecution/JobBase.java @@ -88,7 +88,7 @@ public String getDisplayName() { */ @Override public JobBaseDescriptor getDescriptor() { - Jenkins instance = Jenkins.getInstance(); + Jenkins instance = Jenkins.get(); if (instance == null) { return null; } else { @@ -101,7 +101,7 @@ public JobBaseDescriptor getDescriptor() { * @return all extensions based on JobBase */ public static ExtensionList all() { - Jenkins instance = Jenkins.getInstance(); + Jenkins instance = Jenkins.get(); if (instance == null) { return null; } else { diff --git a/src/main/java/com/vectorcast/plugins/vectorcastexecution/VectorCASTCommand.java b/src/main/java/com/vectorcast/plugins/vectorcastexecution/VectorCASTCommand.java index b9d76cf9..279e38fd 100644 --- a/src/main/java/com/vectorcast/plugins/vectorcastexecution/VectorCASTCommand.java +++ b/src/main/java/com/vectorcast/plugins/vectorcastexecution/VectorCASTCommand.java @@ -36,6 +36,7 @@ import hudson.tasks.Builder; import hudson.tasks.BuildStepDescriptor; import hudson.tasks.Shell; +import hudson.EnvVars; import jenkins.tasks.SimpleBuildStep; import org.kohsuke.stapler.DataBoundConstructor; @@ -79,7 +80,7 @@ public VectorCASTCommand(String winCommand, String unixCommand) { } @Override - public void perform(Run build, FilePath workspace, Launcher launcher, TaskListener listener) { + public void perform(Run build, FilePath workspace, EnvVars env, Launcher launcher, TaskListener listener) { // Windows check and run batch command // // Get the windows batch command and run it if this node is Windows @@ -88,7 +89,7 @@ public void perform(Run build, FilePath workspace, Launcher launcher, TaskL String windowsCmd = getWinCommand(); BatchFile batchFile = new BatchFile(windowsCmd); try { - if (!batchFile.perform((AbstractBuild)build, launcher, (BuildListener)listener)) { + if (!batchFile.perform((AbstractBuild)build, launcher, (BuildListener)listener)) { build.setResult(Result.FAILURE); } } catch (InterruptedException ex) { @@ -106,7 +107,7 @@ public void perform(Run build, FilePath workspace, Launcher launcher, TaskL String unixCmd = getUnixCommand(); Shell shell = new Shell(unixCmd); try { - if (!shell.perform((AbstractBuild)build, launcher, (BuildListener)listener)) { + if (!shell.perform((AbstractBuild)build, launcher, (BuildListener)listener)) { build.setResult(Result.FAILURE); } } catch (InterruptedException ex) { @@ -136,6 +137,7 @@ public DescriptorImpl() { } @Override + @SuppressWarnings("rawtypes") public boolean isApplicable(Class aClass) { // Indicates that this builder can be used with all kinds of project types return true; diff --git a/src/main/java/com/vectorcast/plugins/vectorcastexecution/VectorCASTJobDiag.java b/src/main/java/com/vectorcast/plugins/vectorcastexecution/VectorCASTJobDiag.java index 1813f82c..7a7bd5ba 100644 --- a/src/main/java/com/vectorcast/plugins/vectorcastexecution/VectorCASTJobDiag.java +++ b/src/main/java/com/vectorcast/plugins/vectorcastexecution/VectorCASTJobDiag.java @@ -60,7 +60,7 @@ public static final class DescriptorImpl extends JobBaseDescriptor { * @return true if it exists and false if not */ public boolean isExists() { - Jenkins instance = Jenkins.getInstance(); + Jenkins instance = Jenkins.get(); if (instance != null && instance.getJobNames().contains(PROJECT_NAME)) { return true; } else { @@ -78,7 +78,7 @@ public boolean isExists() { */ @RequirePOST public HttpResponse doCreate(final StaplerRequest request, final StaplerResponse response) throws ServletException, IOException, Descriptor.FormException { - Jenkins instance = Jenkins.getInstance(); + Jenkins instance = Jenkins.get(); if (instance != null && !instance.getJobNames().contains(PROJECT_NAME)) { FreeStyleProject project = instance.createProject(FreeStyleProject.class, PROJECT_NAME); String winCommand = diff --git a/src/main/java/com/vectorcast/plugins/vectorcastexecution/VectorCASTJobRoot.java b/src/main/java/com/vectorcast/plugins/vectorcastexecution/VectorCASTJobRoot.java index ac7fde26..6e8de7f3 100644 --- a/src/main/java/com/vectorcast/plugins/vectorcastexecution/VectorCASTJobRoot.java +++ b/src/main/java/com/vectorcast/plugins/vectorcastexecution/VectorCASTJobRoot.java @@ -40,11 +40,11 @@ @Extension public class VectorCASTJobRoot implements RootAction { - public static final PermissionGroup PERMISSIONS_GROUP = new PermissionGroup( - VectorCASTJobRoot.class,Messages._VectorCASTRootAction_PermissionGroup()); + public static final PermissionGroup PERMISSIONS_GROUP = new PermissionGroup( + VectorCASTJobRoot.class,Messages._VectorCASTRootAction_PermissionGroup()); private static final PermissionScope scope[] = {PermissionScope.JENKINS}; - public static final Permission VIEW = new Permission(PERMISSIONS_GROUP, - "View", Messages._VectorCASTRootAction_ViewPermissionDescription(), + public static final Permission VIEW = new Permission(PERMISSIONS_GROUP, + "View", Messages._VectorCASTRootAction_ViewPermissionDescription(), Jenkins.ADMINISTER, true, scope); @@ -63,7 +63,7 @@ public String getIconFileName() { // will catch and report any permissions issues if (permission) { String iconName; - String jenkinsVersion = Jenkins.getInstance().VERSION; + String jenkinsVersion = Jenkins.VERSION; String version[] = jenkinsVersion.split("\\."); Integer major, minor; Boolean colorIcon = true; diff --git a/src/main/java/com/vectorcast/plugins/vectorcastexecution/VectorCASTSetup.java b/src/main/java/com/vectorcast/plugins/vectorcastexecution/VectorCASTSetup.java index c7d3d990..893678ef 100644 --- a/src/main/java/com/vectorcast/plugins/vectorcastexecution/VectorCASTSetup.java +++ b/src/main/java/com/vectorcast/plugins/vectorcastexecution/VectorCASTSetup.java @@ -48,6 +48,7 @@ import jenkins.tasks.SimpleBuildStep; import org.apache.commons.io.FileUtils; import org.kohsuke.stapler.DataBoundConstructor; +import hudson.EnvVars; /** * VectorCAST setup build action @@ -115,7 +116,7 @@ public class VectorCASTSetup extends Builder implements SimpleBuildStep { private String pclpResultsPattern; /** PC Lint Plus Path */ private String squoreCommand; - + /** TESTinsights Push information **/ private String TESTinsights_URL; private String TESTinsights_project; @@ -286,7 +287,7 @@ public String getOptionHtmlBuildDesc() { return optionHtmlBuildDesc; } /** - * Set option for HTML build description * + * Set option for HTML build description * * @param optionHtmlBuildDesc HTML or TEXT */ public void setOptionHtmlBuildDesc(String optionHtmlBuildDesc) { @@ -333,7 +334,7 @@ public boolean getUseCILicenses() { */ public void setUseCILicenses(boolean useCILicenses) { this.useCILicenses = useCILicenses; - } + } /** * Get option to Use strict testcase import * @return true to Use strict testcase import, false to not @@ -347,8 +348,8 @@ public boolean getUseStrictTestcaseImport() { */ public void setUseStrictTestcaseImport(boolean useStrictTestcaseImport) { this.useStrictTestcaseImport = useStrictTestcaseImport; - } - + } + /** * Get option to Use RGW3 capabilities * @return true use RGW3 capabilities, false to not @@ -362,7 +363,7 @@ public boolean getUseRGW3() { */ public void setUseRGW3(boolean useRGW3) { this.useRGW3 = useRGW3; - } + } /** * Get option to use coverage plugin or vectorcast coverage plugin * @return true use coverage plugin or vectorcast coverage plugin @@ -376,7 +377,7 @@ public boolean getUseCoveragePlugin() { */ public void setUseCoveragePlugin(boolean useCoveragePlugin) { this.useCoveragePlugin = useCoveragePlugin; - } + } /** * Get option to Use imported results * @return true to Use imported results, false to not @@ -390,8 +391,8 @@ public boolean getUseImportedResults() { */ public void setUseImportedResults(boolean useImportedResults) { this.useImportedResults = useImportedResults; - } - + } + /** * Get option to Use local imported results * @return true to Use local imported results, false to not @@ -405,7 +406,7 @@ public boolean getUseLocalImportedResults() { */ public void setUseLocalImportedResults(boolean useLocalImportedResults) { this.useLocalImportedResults = useLocalImportedResults; - } + } /** * Get option to Use external imported results @@ -420,7 +421,7 @@ public boolean getUseExternalImportedResults() { */ public void setUseExternalImportedResults(boolean useExternalImportedResults) { this.useExternalImportedResults = useExternalImportedResults; - } + } /** * Get option to Use as external result filename @@ -435,7 +436,7 @@ public String getExternalResultsFilename() { */ public void setExternalResultsFilename(String externalResultsFilename) { this.externalResultsFilename = externalResultsFilename; - } + } /** * Get option to Use coverage history to control build status @@ -450,7 +451,7 @@ public boolean getUseCoverageHistory() { */ public void setUseCoverageHistory(boolean useCoverageHistory) { this.useCoverageHistory = useCoverageHistory; - } + } /** * Get using SCM * @return true/false @@ -556,7 +557,7 @@ public String getPclpResultsPattern() { public void setPclpResultsPattern(String pclpResultsPattern) { this.pclpResultsPattern = pclpResultsPattern; } - + /** * Get using getUsingPCLP command * @return true/false if we have a squoreCommand @@ -587,77 +588,77 @@ public void setSquoreCommand(String squoreCommand) { */ public String getTESTinsights_URL() { return TESTinsights_URL; - } + } /** * Set URL for TESTinsights * @param TESTinsights_URL - TESTinsights URL */ public void setTESTinsights_URL(String TESTinsights_URL) { this.TESTinsights_URL = TESTinsights_URL; - } + } /** * Get Project for TESTinsights * @return TESTinsights Project */ public String getTESTinsights_project() { return TESTinsights_project; - } + } /** * Set Project for TESTinsights * @param TESTinsights_project - Project for TESTinsights */ public void setTESTinsights_project(String TESTinsights_project) { this.TESTinsights_project = TESTinsights_project; - } + } /** * Get Proxy for TESTinsights * @return TESTinsights proxy */ public String getTESTinsights_proxy() { return TESTinsights_proxy; - } + } /** * Set Proxy for TESTinsights * @param TESTinsights_proxy TESTinsights proxy */ public void setTESTinsights_proxy(String TESTinsights_proxy) { this.TESTinsights_proxy = TESTinsights_proxy; - } + } /** * Get Credentials ID for TESTinsights * @return TESTinsights Credentials */ public String getTESTinsights_credentials_id() { return TESTinsights_credentials_id; - } + } /** * Set Credentials ID for TESTinsights * @param TESTinsights_credentials_id - Credentials ID for TESTinsights */ public void setTESTinsights_credentials_id(String TESTinsights_credentials_id) { this.TESTinsights_credentials_id = TESTinsights_credentials_id; - } + } /** * Get SCM URL for TESTinsights * @return TESTinsights SCM URL */ public String getTESTinsights_SCM_URL() { return TESTinsights_SCM_URL; - } + } /** * Get SCM Technology TESTinsights * @return TESTinsights SCM Technology */ public String getTESTinsights_SCM_Tech() { return TESTinsights_SCM_Tech; - } + } /** * Set SCM URL for TESTinsights * @param TESTinsights_SCM_URL - URL for TESTinsights */ public void setTESTinsights_SCM_URL(String TESTinsights_SCM_URL) { this.TESTinsights_SCM_URL = TESTinsights_SCM_URL; - } + } /** * Set SCM Technology TESTinsights * @param TESTinsights_SCM_Tech - SCM Technology TESTinsights (git or svn) @@ -665,7 +666,7 @@ public void setTESTinsights_SCM_URL(String TESTinsights_SCM_URL) { public void setTESTinsights_SCM_Tech(String TESTinsights_SCM_Tech) { this.TESTinsights_SCM_Tech = TESTinsights_SCM_Tech; - } + } /** * Create setup step * @param environmentSetupWin environment setup for windows @@ -778,7 +779,7 @@ public VectorCASTSetup(String environmentSetupWin, /** * Copy the files in a directory recursively to the job workspace. * This is used when the source is NOT a jar file - * + * * @param dir directory to process * @param base base * @param destDir destination directory @@ -811,19 +812,20 @@ private void processDir(File dir, String base, FilePath destDir, Boolean directD private void printVersion( PrintStream logger ) { - logger.println( "[VectorCAST Execution Version]: " + VcastUtils.getVersion().orElse( "Error - Could not determine version" ) ); + logger.println( "[VectorCAST Execution Version]: " + VcastUtils.getVersion().orElse( "Error - Could not determine version" ) ); } /** * Perform the build step. Copy the scripts from the archive/directory to the workspace * @param build build * @param workspace workspace + * @param env environment variables * @param launcher launcher * @param listener listener - * @throws IOException exception - */ + * @throws IOException exception + */ @Override - public void perform(Run build, FilePath workspace, Launcher launcher, TaskListener listener) throws IOException { + public void perform(Run build, FilePath workspace, EnvVars env, Launcher launcher, TaskListener listener) throws IOException { FilePath destScriptDir = new FilePath(workspace, "vc_scripts"); JarFile jFile = null; try { @@ -880,16 +882,16 @@ public void perform(Run build, FilePath workspace, Launcher launcher, TaskL } } } - + // clean up old xml_data files - + File[] files = new File(workspace + "/xml_data/").listFiles(); if (files != null) { - for (File file : files) + for (File file : files) { if (file.isFile() && !file.delete()) { - throw new IOException("Unable to delete file: " + file.getAbsolutePath()); + throw new IOException("Unable to delete file: " + file.getAbsolutePath()); } } } @@ -905,15 +907,16 @@ public DescriptorImpl getDescriptor() { @Extension public static final class DescriptorImpl extends BuildStepDescriptor { /** - * In order to load the persisted global configuration, you have to + * In order to load the persisted global configuration, you have to * call load() in the constructor. */ public DescriptorImpl() { load(); } @Override + @SuppressWarnings("rawtypes") public boolean isApplicable(Class aClass) { - // Indicates that this builder can be used with all kinds of project types + // Indicates that this builder can be used with all kinds of project types return true; } /** @@ -925,47 +928,47 @@ public String getDisplayName() { return Messages.VectorCASTSetup_DisplayName(); } } - + @Override public String toString() { - - String string = "\nVectorCASTSetup: \n" - + "\t environmentSetupUnix: " + environmentSetupUnix + "\n" - + "\t executePreambleWin: " + executePreambleWin + "\n" - + "\t executePreambleUnix: " + executePreambleUnix + "\n" - + "\t environmentTeardownWin: " + environmentTeardownWin + "\n" - + "\t environmentTeardownUnix: " + environmentTeardownUnix + "\n" - + "\t optionUseReporting: " + optionUseReporting + "\n" - + "\t optionErrorLevel: " + optionErrorLevel + "\n" - + "\t optionHtmlBuildDesc: " + optionHtmlBuildDesc + "\n" - + "\t optionHtmlBuildDesc: " + optionHtmlBuildDesc + "\n" - + "\t optionExecutionReport: " + optionExecutionReport + "\n" - + "\t optionClean: " + optionClean + "\n" - + "\t useCILicenses: " + useCILicenses + "\n" - + "\t useStrictTestcaseImport: " + useStrictTestcaseImport + "\n" - + "\t useRGW3: " + useRGW3 + "\n" - + "\t useImportedResults: " + useImportedResults + "\n" - + "\t useLocalImportedResults: " + useLocalImportedResults + "\n" - + "\t useExternalImportedResults: " + useExternalImportedResults + "\n" - + "\t externalResultsFilename: " + externalResultsFilename + "\n" - + "\t useCoverageHistory: " + useCoverageHistory + "\n" - + "\t usingSCM: " + usingSCM + "\n" - + "\t scm: " + scm + "\n" - + "\t waitLoops: " + waitLoops + "\n" - + "\t waitTime: " + waitTime + "\n" - + "\t maxParallel: " + maxParallel + "\n" - + "\t manageProjectName: " + manageProjectName + "\n" - + "\t jobName: " + jobName + "\n" - + "\t nodeLabel: " + nodeLabel + "\n" - + "\t pclpCommand: " + pclpCommand + "\n" - + "\t pclpResultsPattern: " + pclpResultsPattern + "\n" - + "\t squoreCommand: " + squoreCommand + "\n" - + "\t TESTinsights_URL: " + TESTinsights_URL + "\n" - + "\t TESTinsights_project: " + TESTinsights_project + "\n" - + "\t TESTinsights_credentials_id: " + TESTinsights_credentials_id + "\n" - + "\t TESTinsights_proxy: " + TESTinsights_proxy + "\n" - + "\t TESTinsights_SCM_URL: " + TESTinsights_SCM_URL + "\n" - + "\t TESTinsights_SCM_Tech: " + TESTinsights_SCM_Tech + "\n"; - return string; + + String string = "\nVectorCASTSetup: \n" + + "\t environmentSetupUnix: " + environmentSetupUnix + "\n" + + "\t executePreambleWin: " + executePreambleWin + "\n" + + "\t executePreambleUnix: " + executePreambleUnix + "\n" + + "\t environmentTeardownWin: " + environmentTeardownWin + "\n" + + "\t environmentTeardownUnix: " + environmentTeardownUnix + "\n" + + "\t optionUseReporting: " + optionUseReporting + "\n" + + "\t optionErrorLevel: " + optionErrorLevel + "\n" + + "\t optionHtmlBuildDesc: " + optionHtmlBuildDesc + "\n" + + "\t optionHtmlBuildDesc: " + optionHtmlBuildDesc + "\n" + + "\t optionExecutionReport: " + optionExecutionReport + "\n" + + "\t optionClean: " + optionClean + "\n" + + "\t useCILicenses: " + useCILicenses + "\n" + + "\t useStrictTestcaseImport: " + useStrictTestcaseImport + "\n" + + "\t useRGW3: " + useRGW3 + "\n" + + "\t useImportedResults: " + useImportedResults + "\n" + + "\t useLocalImportedResults: " + useLocalImportedResults + "\n" + + "\t useExternalImportedResults: " + useExternalImportedResults + "\n" + + "\t externalResultsFilename: " + externalResultsFilename + "\n" + + "\t useCoverageHistory: " + useCoverageHistory + "\n" + + "\t usingSCM: " + usingSCM + "\n" + + "\t scm: " + scm + "\n" + + "\t waitLoops: " + waitLoops + "\n" + + "\t waitTime: " + waitTime + "\n" + + "\t maxParallel: " + maxParallel + "\n" + + "\t manageProjectName: " + manageProjectName + "\n" + + "\t jobName: " + jobName + "\n" + + "\t nodeLabel: " + nodeLabel + "\n" + + "\t pclpCommand: " + pclpCommand + "\n" + + "\t pclpResultsPattern: " + pclpResultsPattern + "\n" + + "\t squoreCommand: " + squoreCommand + "\n" + + "\t TESTinsights_URL: " + TESTinsights_URL + "\n" + + "\t TESTinsights_project: " + TESTinsights_project + "\n" + + "\t TESTinsights_credentials_id: " + TESTinsights_credentials_id + "\n" + + "\t TESTinsights_proxy: " + TESTinsights_proxy + "\n" + + "\t TESTinsights_SCM_URL: " + TESTinsights_SCM_URL + "\n" + + "\t TESTinsights_SCM_Tech: " + TESTinsights_SCM_Tech + "\n"; + return string; } } diff --git a/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/BaseJob.java b/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/BaseJob.java index 25473b35..d0285b1b 100644 --- a/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/BaseJob.java +++ b/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/BaseJob.java @@ -57,11 +57,14 @@ import java.util.logging.Logger; import java.util.logging.Level; import java.util.ArrayList; +import java.lang.UnsupportedOperationException; /** * Base job management - create/delete/update */ abstract public class BaseJob { + private String projectName; + /** Jenkins instance */ private Jenkins instance; /** Request */ @@ -73,7 +76,7 @@ abstract public class BaseJob { /** Base name generated from the manage project name */ private String baseName; /** Top-level project */ - protected Project topProject; + protected Project topProject; /** Environment setup for windows */ private String environmentSetupWin; /** Environment setup for unix */ @@ -159,7 +162,7 @@ abstract public class BaseJob { * @throws ExternalResultsFileException exception */ protected BaseJob(final StaplerRequest request, final StaplerResponse response, boolean useSavedData) throws ServletException, IOException, ExternalResultsFileException { - instance = Jenkins.getInstance(); + instance = Jenkins.get(); this.request = request; this.response = response; JSONObject json = request.getSubmittedForm(); @@ -234,7 +237,6 @@ protected BaseJob(final StaplerRequest request, final StaplerResponse response, } } } - externalResultsFilename = json.optString("externalResultsFilename", "").replace('\\','/'); useCoverageHistory = json.optBoolean("useCoverageHistory", false); maxParallel = json.optLong("maxParallel", 0); @@ -586,7 +588,7 @@ protected void setExternalResultsFilename(String externalResultsFilename) { * Get option to Use coverage history to control build status * @return true to Use imported results, false to not */ - protected boolean getUseCoverageHistory() { + public boolean getUseCoverageHistory() { return useCoverageHistory; } /** @@ -656,7 +658,7 @@ protected String getJobName() { * Get top-level project * @return project */ - protected Project getTopProject() { + protected Project getTopProject() { return topProject; } /** @@ -780,6 +782,20 @@ protected StaplerRequest getRequest() { protected Jenkins getInstance() { return instance; } + /** + * Get the name of the project + * @return the project name + */ + public String getProjectName() { + return projectName; + } + /** + * Sets the name of the project + * @param projectName - project name + */ + public void setProjectName(final String projectName) { + this.projectName = projectName; + } /** * Get response * @return response @@ -791,9 +807,9 @@ protected StaplerResponse getResponse() { * Add the delete workspace before build starts option * @param project project to add to */ - protected void addDeleteWorkspaceBeforeBuildStarts(Project project) { + protected void addDeleteWorkspaceBeforeBuildStarts(Project project) { if (optionClean) { - PreBuildCleanup cleanup = new PreBuildCleanup(/*patterns*/null, true, /*cleanup param*/"", /*external delete*/""); + PreBuildCleanup cleanup = new PreBuildCleanup(/*patterns*/null, true, /*cleanup param*/"", /*external delete*/"", /*disableDeferredWipeout*/ false); project.getBuildWrappersList().add(cleanup); } } @@ -854,7 +870,7 @@ public void create(boolean update) throws IOException, ServletException, Descrip * @throws IOException exception * @throws JobAlreadyExistsException exception */ - abstract protected Project createProject() throws IOException, JobAlreadyExistsException; + abstract protected Project createProject() throws IOException, JobAlreadyExistsException; /** * Cleanup top-level project, as in delete */ @@ -874,7 +890,7 @@ public void create(boolean update) throws IOException, ServletException, Descrip * @param project project * @return the setup build step */ - protected VectorCASTSetup addSetup(Project project) { + protected VectorCASTSetup addSetup(Project project) throws IOException{ VectorCASTSetup setup = new VectorCASTSetup(environmentSetupWin, environmentSetupUnix, @@ -915,13 +931,14 @@ protected VectorCASTSetup addSetup(Project project) { setup.setSCM(scm); project.getBuildersList().add(setup); + return setup; } /** * Add archive artifacts step * @param project project to add to */ - protected void addArchiveArtifacts(Project project) { + protected void addArchiveArtifacts(Project project) { String pclpArchive = ""; String TIArchive = ""; @@ -932,12 +949,11 @@ protected void addArchiveArtifacts(Project project) { TIArchive = ", TESTinsights_Push.log"; } String addToolsArchive = pclpArchive + TIArchive; + String defaultArchive = "**/*.html, xml_data/*.xml, unit_test_fail_count.txt, **/*.png, **/*.css, complete_build.log, *_results.vcr"; - ArtifactArchiver archiver = new ArtifactArchiver( - /*artifacts*/"**/*.html, xml_data/*.xml, unit_test_fail_count.txt, **/*.png, **/*.css, complete_build.log, *_results.vcr" + addToolsArchive, - /*excludes*/"", - /*latest only*/false, - /*allow empty archive*/false); + ArtifactArchiver archiver = new ArtifactArchiver(defaultArchive + addToolsArchive); + archiver.setExcludes(""); + archiver.setAllowEmptyArchive(false); project.getPublishersList().add(archiver); } @@ -945,7 +961,7 @@ protected void addArchiveArtifacts(Project project) { * Add archive artifacts step * @param project project to add to */ - protected void addCopyResultsToImport(Project project) { + protected void addCopyResultsToImport(Project project) { StatusBuildSelector selector = new StatusBuildSelector(); CopyArtifact archiverCopier = new CopyArtifact(project.getName()); archiverCopier.setParameters(""); @@ -963,7 +979,7 @@ protected void addCopyResultsToImport(Project project) { * @param project project to add step to */ - protected void addJunit(Project project) { + protected void addJunit(Project project) { JUnitResultArchiver junit = new JUnitResultArchiver("**/test_results_*.xml"); project.getPublishersList().add(junit); } @@ -972,7 +988,7 @@ protected void addJunit(Project project) { * @param project project to add step to do PC-Lint Plus */ - protected void addPCLintPlus(Project project) { + protected void addPCLintPlus(Project project) { if (pclpCommand.length() != 0) { IssuesRecorder recorder = new IssuesRecorder(); @@ -990,7 +1006,7 @@ protected void addPCLintPlus(Project project) { * Add VectorCAST coverage reporting step * @param project project to add step to */ - protected void addVCCoverage(Project project) { + protected void addVCCoverage(Project project) { VectorCASTHealthReportThresholds healthReports = new VectorCASTHealthReportThresholds(0, 100, 0, 70, 0, 80, 0, 80, 0, 80, 0, 80); VectorCASTPublisher publisher = new VectorCASTPublisher(); publisher.includes = "**/coverage_results_*.xml"; @@ -1002,7 +1018,7 @@ protected void addVCCoverage(Project project) { * Add Jenkins coverage reporting step * @param project project to add step to */ - protected void addJenkinsCoverage(Project project) { + protected void addJenkinsCoverage(Project project) { CoverageTool tool = new CoverageTool(); tool.setParser(Parser.VECTORCAST); tool.setPattern("xml_data/cobertura/coverage_results*.xml"); @@ -1014,7 +1030,8 @@ protected void addJenkinsCoverage(Project project) { project.getPublishersList().add(publisher); } - protected void addCredentialID(Project project) { - project.getBuildWrappersList().add(new SecretBuildWrapper(Collections.>singletonList(new UsernamePasswordMultiBinding("VC_TI_USR","VC_TI_PWS",TESTinsights_credentials_id)))); + protected void addCredentialID(Project project) { + project.getBuildWrappersList().add(new SecretBuildWrapper(Collections.>singletonList( + new UsernamePasswordMultiBinding("VC_TI_USR","VC_TI_PWS",TESTinsights_credentials_id)))); } } diff --git a/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/ExternalResultsFileException.java b/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/ExternalResultsFileException.java index dadb0537..154388ae 100644 --- a/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/ExternalResultsFileException.java +++ b/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/ExternalResultsFileException.java @@ -27,6 +27,7 @@ * Exception raised if the supplied manage project file cannot be read */ public class ExternalResultsFileException extends Exception { + private static final long serialVersionUID = 7429348150624478731L; public ExternalResultsFileException() { super(); } diff --git a/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/InvalidProjectFileException.java b/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/InvalidProjectFileException.java index e71cb803..a1fe0321 100644 --- a/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/InvalidProjectFileException.java +++ b/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/InvalidProjectFileException.java @@ -27,6 +27,7 @@ * Exception raised if the supplied manage project file cannot be read */ public class InvalidProjectFileException extends Exception { + private static final long serialVersionUID = 3544833590470742391L; public InvalidProjectFileException() { super(); } diff --git a/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/JobAlreadyExistsException.java b/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/JobAlreadyExistsException.java index a80bbaab..684f7464 100644 --- a/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/JobAlreadyExistsException.java +++ b/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/JobAlreadyExistsException.java @@ -27,6 +27,8 @@ * Exception raised if job being created already exists */ public class JobAlreadyExistsException extends Exception { + private static final long serialVersionUID = 2678119599631146760L; + /** Name of project */ private final String project; /** diff --git a/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/NewPipelineJob.java b/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/NewPipelineJob.java index 72220325..1b695edd 100644 --- a/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/NewPipelineJob.java +++ b/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/NewPipelineJob.java @@ -82,7 +82,6 @@ */ public class NewPipelineJob extends BaseJob { /** project name */ - private String projectName; private String sharedArtifactDirectory; @@ -190,15 +189,6 @@ public NewPipelineJob(final StaplerRequest request, final StaplerResponse respon } } - /** - * Get the name of the project - * - * @return the project name - */ - public String getProjectName() { - return projectName; - } - /** * Create project * @@ -208,8 +198,9 @@ public String getProjectName() { */ @Override - protected Project createProject() throws IOException, JobAlreadyExistsException { + protected Project createProject() throws IOException, JobAlreadyExistsException { + String projectName; if (getBaseName().isEmpty()) { getResponse().sendError(HttpServletResponse.SC_NOT_MODIFIED, "No project name specified"); @@ -226,6 +217,8 @@ protected Project createProject() throws IOException, JobAlreadyExistsException // Remove all non-alphanumeric characters from the Jenkins Job name projectName = projectName.replaceAll("[^a-zA-Z0-9_]","_"); + setProjectName(projectName); + if (getInstance().getJobNames().contains(projectName)) { throw new JobAlreadyExistsException(projectName); } @@ -277,7 +270,7 @@ public void doCreate(boolean update) throws IOException, ServletException, Descr * cannot be cast to Project */ - getInstance().createProjectFromXML(this.projectName, xmlInput); + getInstance().createProjectFromXML(getProjectName(), xmlInput); } catch (IOException e) { e.printStackTrace(); } finally { @@ -403,7 +396,7 @@ private String getBaseJenkinsfile() throws IOException { InputStream in = getClass().getResourceAsStream("/scripts/baseJenkinsfile.groovy"); try { - result = IOUtils.toString(in); + result = IOUtils.toString(in, "UTF-8"); } catch (IOException ex) { Logger.getLogger(NewPipelineJob.class.getName()).log(Level.SEVERE, null, ex); } finally { diff --git a/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/NewSingleJob.java b/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/NewSingleJob.java index ca70dce3..6d06cf6f 100644 --- a/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/NewSingleJob.java +++ b/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/NewSingleJob.java @@ -44,8 +44,6 @@ * Create a new single job */ public class NewSingleJob extends BaseJob { - /** project name */ - private String projectName; /** * Constructor * @param request request object @@ -57,13 +55,6 @@ public class NewSingleJob extends BaseJob { public NewSingleJob(final StaplerRequest request, final StaplerResponse response) throws ServletException, IOException, ExternalResultsFileException { super(request, response, false); } - /** - * Get the name of the project - * @return the project name - */ - public String getProjectName() { - return projectName; - } /** * Add build commands step to job */ @@ -346,7 +337,9 @@ private void addCommandSingleJob() { unix = StringUtils.replace(unix, "@PROJECT_BASE@", getBaseName()); VectorCASTCommand command = new VectorCASTCommand(win, unix); - getTopProject().getBuildersList().add(command); + if (!getTopProject().getBuildersList().add(command)) { + throw new UnsupportedOperationException("Failed to add VectorCASTCommand to Builders List"); + } } /** * Add groovy script step to job @@ -487,7 +480,9 @@ private void addGroovyScriptSingleJob() { SecureGroovyScript secureScript = new SecureGroovyScript(script, /*sandbox*/false, /*classpath*/null); GroovyPostbuildRecorder groovy = new GroovyPostbuildRecorder(secureScript, /*behaviour*/2, /*matrix parent*/false); - getTopProject().getPublishersList().add(groovy); + if (!getTopProject().getPublishersList().add(groovy)) { + throw new UnsupportedOperationException("Failed to add GroovyPostbuildRecorder to Publishers List"); + } } /** * Create project @@ -496,19 +491,22 @@ private void addGroovyScriptSingleJob() { * @throws JobAlreadyExistsException exception */ @Override - protected Project createProject() throws IOException, JobAlreadyExistsException { + protected Project createProject() throws IOException, JobAlreadyExistsException { if (getBaseName().isEmpty()) { getResponse().sendError(HttpServletResponse.SC_NOT_MODIFIED, "No project name specified"); return null; } - projectName = getBaseName() + ".vcast.single"; + String projectName = getBaseName() + ".vcast.single"; if (getJobName() != null && !getJobName().isEmpty()) { projectName = getJobName(); } if (getInstance().getJobNames().contains(projectName)) { throw new JobAlreadyExistsException(projectName); } - Project project = getInstance().createProject(FreeStyleProject.class, projectName); + Project project = getInstance().createProject(FreeStyleProject.class, projectName); + + setProjectName(projectName); + if (getNodeLabel() != null && !getNodeLabel().isEmpty()) { Label label = new LabelAtom(getNodeLabel()); project.setAssignedLabel(label); diff --git a/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/ScmConflictException.java b/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/ScmConflictException.java index ffe920ac..c1d22a3b 100644 --- a/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/ScmConflictException.java +++ b/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/ScmConflictException.java @@ -27,6 +27,8 @@ * Exception raised if job being created already exists */ public class ScmConflictException extends Exception { + private static final long serialVersionUID = -1889207053537494684L; + /** Name of project */ private final String scmSnippet; private final String pathToManageProject; diff --git a/src/main/resources/scripts/generate_xml.py b/src/main/resources/scripts/generate_xml.py index 14628118..88a2f45b 100644 --- a/src/main/resources/scripts/generate_xml.py +++ b/src/main/resources/scripts/generate_xml.py @@ -765,7 +765,7 @@ def generate_local_results(self, results, key): print(" {}/{}/{}".format(comp, ts, env_name)) return - xmlUnitReportName = os.getcwd() + os.sep + "xml_data" + os.sep + "test_results_" + key.replace("/","_") + ".xml" + xmlUnitReportName = os.getcwd() + os.sep + "xml_data" + os.sep + "test_results_" + "_".join([comp, ts, env_name]) + ".xml" localXML = GenerateXml(self.FullManageProjectName, build_dir, env_name, comp, ts, None, key, xmlUnitReportName, None, None, False, diff --git a/src/test/java/com/vectorcast/plugins/vectorcastexecution/job/NewSingleJobTest.java b/src/test/java/com/vectorcast/plugins/vectorcastexecution/job/NewSingleJobTest.java index 743db8f3..bf5cf7c1 100644 --- a/src/test/java/com/vectorcast/plugins/vectorcastexecution/job/NewSingleJobTest.java +++ b/src/test/java/com/vectorcast/plugins/vectorcastexecution/job/NewSingleJobTest.java @@ -13,7 +13,6 @@ import hudson.tasks.Publisher; import hudson.util.DescribableList; import jenkins.model.Jenkins; -import junit.framework.TestCase; import net.sf.json.JSONObject; import hudson.tasks.junit.JUnitResultArchiver; import hudson.plugins.copyartifact.CopyArtifact; @@ -31,8 +30,22 @@ import static org.mockito.Mockito.when; +import io.jenkins.plugins.coverage.metrics.steps.CoverageRecorder; +import io.jenkins.plugins.coverage.metrics.steps.CoverageTool; +import io.jenkins.plugins.coverage.metrics.steps.CoverageTool.Parser; +import java.util.List; +import java.io.IOException; +import javax.servlet.ServletException; + +import hudson.model.Descriptor.FormException; + public class NewSingleJobTest { + final String DEFAULT_ARTIFACT_LIST = "**/*.html, xml_data/*.xml, unit_test_fail_count.txt, **/*.png, **/*.css, complete_build.log, *_results.vcr"; + final long USE_LOCAL_IMPORTED_RESULTS = 1; + final long USE_EXTERNAL_IMPORTED_RESULTS = 2; + final String EXTERNAL_RESULT_FILENAME = "archivedResults/project.vcr"; + @Rule public JenkinsRule j = new JenkinsRule(); private static final String PROJECTNAME = "project.vcast.single"; @@ -45,8 +58,9 @@ void setUpStaticMocks() { void tearDownStaticMocks() { } - @Test - public void testBasic() throws Exception { + private NewSingleJob setupTestBasic(JSONObject jsonForm) throws ServletException, IOException, + ExternalResultsFileException, FormException, JobAlreadyExistsException, + InvalidProjectFileException { j.jenkins.setSecurityRealm(j.createDummySecurityRealm()); MockAuthorizationStrategy mockStrategy = new MockAuthorizationStrategy(); mockStrategy.grant(Jenkins.READ).everywhere().to("devel"); @@ -57,64 +71,259 @@ public void testBasic() throws Exception { StaplerRequest request = Mockito.mock(StaplerRequest.class); StaplerResponse response = Mockito.mock(StaplerResponse.class); - JSONObject jsonForm = new JSONObject(); - jsonForm.put("manageProjectName", "/home/jenkins/vcast/project.vcm"); - jsonForm.put("optionClean", true); - jsonForm.put("coverageDisplayOption", 1); + when(request.getSubmittedForm()).thenReturn(jsonForm); NewSingleJob job = new NewSingleJob(request, response); + Assert.assertEquals("project", job.getBaseName()); job.create(false); Assert.assertEquals(PROJECTNAME, job.getProjectName()); - Assert.assertTrue(job.getTopProject() != null); + Assert.assertNotNull(job.getTopProject()); + return job; + } + + private void checkJunitGroovy(DescribableList> publisherList, int jUnitIndex, int groovyIndex) { + // Publisher 1- JUnitResultArchiver + Assert.assertTrue(publisherList.get(jUnitIndex) instanceof JUnitResultArchiver); + JUnitResultArchiver jUnit = (JUnitResultArchiver)publisherList.get(jUnitIndex); + Assert.assertEquals("**/test_results_*.xml", jUnit.getTestResults()); + + // Publisher 3 - GroovyPostbuildRecorder + Assert.assertTrue(publisherList.get(groovyIndex) instanceof GroovyPostbuildRecorder); + GroovyPostbuildRecorder groovyScript = (GroovyPostbuildRecorder)publisherList.get(groovyIndex); + Assert.assertEquals(/*failure*/2, groovyScript.getBehavior()); + + } + + private void checkArchiverList(ArtifactArchiver archiver, String artifactsList) { + String artifactsFromArchiver = archiver.getArtifacts(); + Assert.assertEquals(artifactsList,artifactsFromArchiver); + Assert.assertFalse(archiver.getAllowEmptyArchive()); + } + + private void checkVectorCASTPublisher(DescribableList> publisherList, Boolean useCoverageHistory, int vcPubIndex) { + // Publisher 2 - VectorCASTPublisher + Assert.assertTrue(publisherList.get(vcPubIndex) instanceof VectorCASTPublisher); + VectorCASTPublisher vcPublisher = (VectorCASTPublisher)publisherList.get(vcPubIndex); + Assert.assertEquals("**/coverage_results_*.xml", vcPublisher.includes); + Assert.assertEquals(useCoverageHistory, vcPublisher.getUseCoverageHistory()); + Assert.assertEquals("**/coverage_results_*.xml", vcPublisher.includes); + Assert.assertEquals(80, vcPublisher.healthReports.getMaxBasisPath()); + Assert.assertEquals(0, vcPublisher.healthReports.getMinBasisPath()); + Assert.assertEquals(100, vcPublisher.healthReports.getMaxStatement()); + Assert.assertEquals(0, vcPublisher.healthReports.getMinStatement()); + Assert.assertEquals(70, vcPublisher.healthReports.getMaxBranch()); + Assert.assertEquals(0, vcPublisher.healthReports.getMinBranch()); + Assert.assertEquals(80, vcPublisher.healthReports.getMaxFunction()); + Assert.assertEquals(0, vcPublisher.healthReports.getMinFunction()); + Assert.assertEquals(80, vcPublisher.healthReports.getMaxFunctionCall()); + Assert.assertEquals(0, vcPublisher.healthReports.getMinFunctionCall()); + Assert.assertEquals(80, vcPublisher.healthReports.getMaxMCDC()); + Assert.assertEquals(0, vcPublisher.healthReports.getMinMCDC()); + } + + private void checkCoveragePlugin(DescribableList> publisherList, int pubListIndex) { + + // Publisher 2 - CoverageRecorder + Assert.assertTrue(publisherList.get(pubListIndex) instanceof CoverageRecorder); + CoverageRecorder publisher = (CoverageRecorder) publisherList.get(pubListIndex); + + // CoverageRecorder > CoverageTool + List coverageToolsList = publisher.getTools(); + Assert.assertEquals(1, coverageToolsList.size()); + Assert.assertTrue(coverageToolsList.get(0) instanceof CoverageTool); + CoverageTool coverageTool = (CoverageTool)coverageToolsList.get(0); + + Assert.assertEquals("xml_data/cobertura/coverage_results*.xml", coverageTool.getPattern()); + Assert.assertEquals(Parser.VECTORCAST, coverageTool.getParser()); + } + + private void checkBuildWrappers(NewSingleJob job, int builderSize){ + // Check build wrappers... DescribableList> bldWrappersList = job.getTopProject().getBuildWrappersList(); - Assert.assertEquals(1, bldWrappersList.size()); + Assert.assertEquals(builderSize, bldWrappersList.size()); BuildWrapper wrapper = bldWrappersList.get(0); Assert.assertTrue(wrapper instanceof PreBuildCleanup); PreBuildCleanup cleanup = (PreBuildCleanup)wrapper; Assert.assertTrue(cleanup.getDeleteDirs()); - + } + + private void checkBuildAction (NewSingleJob job) { // Check build actions... DescribableList> bldrsList = job.getTopProject().getBuildersList(); Assert.assertEquals(3, bldrsList.size()); Assert.assertTrue(bldrsList.get(0) instanceof CopyArtifact); Assert.assertTrue(bldrsList.get(1) instanceof VectorCASTSetup); Assert.assertTrue(bldrsList.get(2) instanceof VectorCASTCommand); + } + + private void checkImportedResults(NewSingleJob job, long useLocalResults, Boolean useExternalResults, String externalResultsFilename) { + if (useLocalResults == USE_LOCAL_IMPORTED_RESULTS) { + Assert.assertTrue(job.getUseLocalImportedResults()); + } + else if (useLocalResults == USE_EXTERNAL_IMPORTED_RESULTS) { + Assert.assertFalse(job.getUseLocalImportedResults()); + } + Assert.assertEquals(useExternalResults, job.getUseExternalImportedResults()); + Assert.assertEquals(externalResultsFilename, job.getExternalResultsFilename()); + } + + @Test + public void testBasic() throws Exception { + JSONObject jsonForm = new JSONObject(); + jsonForm.put("manageProjectName", "/home/jenkins/vcast/project.vcm"); + jsonForm.put("optionClean", true); + jsonForm.put("coverageDisplayOption", 1); + + NewSingleJob job = setupTestBasic(jsonForm); // Check publishers... DescribableList> publisherList = job.getTopProject().getPublishersList(); Assert.assertEquals(4, publisherList.size()); + // Publisher 0 - ArtifactArchiver Assert.assertTrue(publisherList.get(0) instanceof ArtifactArchiver); ArtifactArchiver archiver = (ArtifactArchiver)publisherList.get(0); - Assert.assertEquals("**/*.html, xml_data/*.xml, unit_test_fail_count.txt, **/*.png, **/*.css, complete_build.log, *_results.vcr",archiver.getArtifacts()); - Assert.assertFalse(archiver.getAllowEmptyArchive()); - // Publisher 1- JUnitResultArchiver - Assert.assertTrue(publisherList.get(1) instanceof JUnitResultArchiver); - JUnitResultArchiver jUnit = (JUnitResultArchiver)publisherList.get(1); - Assert.assertEquals("**/test_results_*.xml", jUnit.getTestResults()); - // Publisher 2 - VectorCASTPublisher - Assert.assertTrue(publisherList.get(2) instanceof VectorCASTPublisher); - VectorCASTPublisher vcPublisher = (VectorCASTPublisher)publisherList.get(2); - Assert.assertEquals("**/coverage_results_*.xml", vcPublisher.includes); - Assert.assertEquals(80, vcPublisher.healthReports.getMaxBasisPath()); - Assert.assertEquals(0, vcPublisher.healthReports.getMinBasisPath()); - Assert.assertEquals(100, vcPublisher.healthReports.getMaxStatement()); - Assert.assertEquals(0, vcPublisher.healthReports.getMinStatement()); - Assert.assertEquals(70, vcPublisher.healthReports.getMaxBranch()); - Assert.assertEquals(0, vcPublisher.healthReports.getMinBranch()); - Assert.assertEquals(80, vcPublisher.healthReports.getMaxFunction()); - Assert.assertEquals(0, vcPublisher.healthReports.getMinFunction()); - Assert.assertEquals(80, vcPublisher.healthReports.getMaxFunctionCall()); - Assert.assertEquals(0, vcPublisher.healthReports.getMinFunctionCall()); - Assert.assertEquals(80, vcPublisher.healthReports.getMaxMCDC()); - Assert.assertEquals(0, vcPublisher.healthReports.getMinMCDC()); - // Publisher 3 - GroovyPostbuildRecorder - Assert.assertTrue(publisherList.get(3) instanceof GroovyPostbuildRecorder); - GroovyPostbuildRecorder groovyScript = (GroovyPostbuildRecorder)publisherList.get(3); - Assert.assertEquals(/*failure*/2, groovyScript.getBehavior()); } + checkBuildWrappers(job, 1); + checkBuildAction(job); + checkArchiverList(archiver, DEFAULT_ARTIFACT_LIST); + checkJunitGroovy(publisherList, 1, 3); + checkVectorCASTPublisher(publisherList, false, 2); + + } + + @Test + public void testAdditionalTools() throws Exception { + + JSONObject jsonForm = new JSONObject(); + jsonForm.put("manageProjectName", "/home/jenkins/vcast/project.vcm"); + jsonForm.put("optionClean", true); + jsonForm.put("coverageDisplayOption", 1); // VectorCAST Coverage Plugin + jsonForm.put("useCoverageHistory", true); + jsonForm.put("pclpCommand","call lint_my_code.bat"); + jsonForm.put("pclpResultsPattern","lint_results.xml"); + jsonForm.put("TESTinsights_URL","https://teamservices.vector.com/teamareas/pct"); + + NewSingleJob job = setupTestBasic(jsonForm); + + // Check publishers... + DescribableList> publisherList = job.getTopProject().getPublishersList(); + Assert.assertEquals(5, publisherList.size()); + + // Publisher 0 - ArtifactArchiver + Assert.assertTrue(publisherList.get(0) instanceof ArtifactArchiver); + ArtifactArchiver archiver = (ArtifactArchiver)publisherList.get(0); + + String addToolArtifacts = DEFAULT_ARTIFACT_LIST; + addToolArtifacts += ", lint_results.xml"; + addToolArtifacts += ", TESTinsights_Push.log"; + + checkBuildWrappers(job, 2); + checkBuildAction(job); + checkArchiverList(archiver, addToolArtifacts); + checkJunitGroovy(publisherList,2,4); + checkVectorCASTPublisher(publisherList, true, 3); + } + + @Test + public void testCoveragePlugin() throws Exception { + + JSONObject jsonForm = new JSONObject(); + jsonForm.put("manageProjectName", "/home/jenkins/vcast/project.vcm"); + jsonForm.put("optionClean", true); + jsonForm.put("coverageDisplayOption", 0); // Jenkins Coverage Plugin + jsonForm.put("useCoverageHistory", false); // VectorCAST Coverage Plugin + jsonForm.put("pclpCommand","call lint_my_code.bat"); + jsonForm.put("pclpResultsPattern","lint_results.xml"); + jsonForm.put("TESTinsights_URL","https://teamservices.vector.com/teamareas/pct"); + + NewSingleJob job = setupTestBasic(jsonForm); + + // Check publishers... + DescribableList> publisherList = job.getTopProject().getPublishersList(); + Assert.assertEquals(5, publisherList.size()); + + // Publisher 0 - ArtifactArchiver + Assert.assertTrue(publisherList.get(0) instanceof ArtifactArchiver); + ArtifactArchiver archiver = (ArtifactArchiver)publisherList.get(0); + + String addToolArtifacts = DEFAULT_ARTIFACT_LIST; + addToolArtifacts += ", lint_results.xml"; + addToolArtifacts += ", TESTinsights_Push.log"; + + checkBuildWrappers(job, 2); + checkBuildAction(job); + checkArchiverList(archiver, addToolArtifacts); + checkJunitGroovy(publisherList, 2, 4); + checkCoveragePlugin(publisherList, 3); + } + + @Test + public void testLocalImportedResults() throws Exception { + + JSONObject jsonImportResults = new JSONObject(); + jsonImportResults.put("value", USE_LOCAL_IMPORTED_RESULTS); + + JSONObject jsonForm = new JSONObject(); + jsonForm.put("manageProjectName", "/home/jenkins/vcast/project.vcm"); + jsonForm.put("optionClean", true); + jsonForm.put("coverageDisplayOption", 0); + jsonForm.put("useImportedResults", true); + jsonForm.put("importedResults", jsonImportResults); + + NewSingleJob job = setupTestBasic(jsonForm); + + // Check publishers... + DescribableList> publisherList = job.getTopProject().getPublishersList(); + Assert.assertEquals(4, publisherList.size()); + + // Publisher 0 - ArtifactArchiver + Assert.assertTrue(publisherList.get(0) instanceof ArtifactArchiver); + ArtifactArchiver archiver = (ArtifactArchiver)publisherList.get(0); + + checkBuildWrappers(job, 1); + checkBuildAction(job); + checkArchiverList(archiver, DEFAULT_ARTIFACT_LIST); + checkJunitGroovy(publisherList, 1, 3); + checkCoveragePlugin(publisherList, 2); + checkImportedResults(job, USE_LOCAL_IMPORTED_RESULTS, false, ""); + } + + @Test + public void testExternalImportedResults() throws Exception { + + JSONObject jsonImportResults = new JSONObject(); + jsonImportResults.put("value", USE_EXTERNAL_IMPORTED_RESULTS); + jsonImportResults.put("externalResultsFilename",EXTERNAL_RESULT_FILENAME); + + JSONObject jsonForm = new JSONObject(); + jsonForm.put("manageProjectName", "/home/jenkins/vcast/project.vcm"); + jsonForm.put("optionClean", true); + jsonForm.put("coverageDisplayOption", 0); + jsonForm.put("useImportedResults", true); + jsonForm.put("importedResults", jsonImportResults); + + NewSingleJob job = setupTestBasic(jsonForm); + + // Check publishers... + DescribableList> publisherList = job.getTopProject().getPublishersList(); + Assert.assertEquals(4, publisherList.size()); + + // Publisher 0 - ArtifactArchiver + Assert.assertTrue(publisherList.get(0) instanceof ArtifactArchiver); + ArtifactArchiver archiver = (ArtifactArchiver)publisherList.get(0); + + + checkBuildWrappers(job, 1); + checkBuildAction(job); + checkArchiverList(archiver, DEFAULT_ARTIFACT_LIST); + checkJunitGroovy(publisherList, 1, 3); + checkCoveragePlugin(publisherList, 2); + checkImportedResults(job, USE_EXTERNAL_IMPORTED_RESULTS, true, EXTERNAL_RESULT_FILENAME); + } } + From 570f5c4a7efc6561e04d8869e2458c72d3566f98 Mon Sep 17 00:00:00 2001 From: TimSVector Date: Thu, 11 Jul 2024 12:49:54 -0400 Subject: [PATCH 032/112] Fixing xlint issues --- pom.xml | 24 +++++++++++++++++-- .../plugins/vectorcastexecution/JobBase.java | 14 ++--------- 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/pom.xml b/pom.xml index 17b3a2ea..9e664723 100644 --- a/pom.xml +++ b/pom.xml @@ -227,10 +227,9 @@ 1.8 1.8 - @@ -287,6 +286,27 @@
+ + org.jacoco + jacoco-maven-plugin + 0.8.2 + + + + prepare-agent + + + + + report + test + + report + + + + +
diff --git a/src/main/java/com/vectorcast/plugins/vectorcastexecution/JobBase.java b/src/main/java/com/vectorcast/plugins/vectorcastexecution/JobBase.java index 7f73afea..7265ca13 100644 --- a/src/main/java/com/vectorcast/plugins/vectorcastexecution/JobBase.java +++ b/src/main/java/com/vectorcast/plugins/vectorcastexecution/JobBase.java @@ -88,12 +88,7 @@ public String getDisplayName() { */ @Override public JobBaseDescriptor getDescriptor() { - Jenkins instance = Jenkins.get(); - if (instance == null) { - return null; - } else { - return (JobBaseDescriptor) instance.getDescriptorOrDie(getClass()); - } + return (JobBaseDescriptor) Jenkins.get().getDescriptorOrDie(getClass()); } /** @@ -101,11 +96,6 @@ public JobBaseDescriptor getDescriptor() { * @return all extensions based on JobBase */ public static ExtensionList all() { - Jenkins instance = Jenkins.get(); - if (instance == null) { - return null; - } else { - return instance.getExtensionList(JobBase.class); - } + return Jenkins.get().getExtensionList(JobBase.class); } } From f0ab902b45ce4c62ab61ccd8cdbfaf1ff829a6bc Mon Sep 17 00:00:00 2001 From: TimSVector Date: Thu, 11 Jul 2024 16:06:09 -0400 Subject: [PATCH 033/112] Updates for PMD and Lint --- .github/workflows/lint.yml | 36 ++++++++ pom.xml | 72 ++++++++++------ .../vectorcastexecution/job/BaseJob.java | 1 - .../job/NewPipelineJob.java | 9 +- .../job/NewSingleJobTest.java | 86 +++++++++---------- 5 files changed, 128 insertions(+), 76 deletions(-) create mode 100644 .github/workflows/lint.yml diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 00000000..b53dc120 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,36 @@ +name: 'Java Lint' + +on: + push: + branches: + - master + pull_request: + +jobs: + build: + + strategy: + matrix: + platform: [ubuntu-latest, windows-latest] + jdk: [11, 17, 21] + + runs-on: ${{ matrix.platform }} + name: on ${{ matrix.platform }} with JDK ${{ matrix.jdk }} + + steps: + - uses: actions/checkout@v4 + - name: Set up JDK ${{ matrix.jdk }} + uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: '${{ matrix.jdk }}' + check-latest: true + cache: 'maven' + - name: Set up Maven + uses: stCarolas/setup-maven@v5 + with: + maven-version: 3.9.6 + - name: Build with Maven + env: + BROWSER: chrome-container + run: mvn -V --color always -ntp clean compile -Plint --file pom.xml '-Djenkins.test.timeout=5000' '-Dgpg.skip' \ No newline at end of file diff --git a/pom.xml b/pom.xml index 9e664723..323b43f2 100644 --- a/pom.xml +++ b/pom.xml @@ -73,14 +73,12 @@ - org.slf4j slf4j-api 2.0.13 - io.jenkins.plugins @@ -205,6 +203,42 @@ 677.vdc9d38cb_254d + + + + lint + + -Xlint:all,-processing + + + + jacoco + + + + org.jacoco + jacoco-maven-plugin + 0.8.2 + + + + prepare-agent + + + + + report + test + + report + + + + + + + + @@ -227,10 +261,19 @@ 1.8 1.8 - - -Xlint:all,-processing + + ${lintCompilerArgs} + + + run-spotbugs + verify + + check + + + org.codehaus.mojo @@ -286,27 +329,6 @@ - - org.jacoco - jacoco-maven-plugin - 0.8.2 - - - - prepare-agent - - - - - report - test - - report - - - - - diff --git a/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/BaseJob.java b/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/BaseJob.java index d0285b1b..7d7f1a3d 100644 --- a/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/BaseJob.java +++ b/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/BaseJob.java @@ -57,7 +57,6 @@ import java.util.logging.Logger; import java.util.logging.Level; import java.util.ArrayList; -import java.lang.UnsupportedOperationException; /** * Base job management - create/delete/update diff --git a/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/NewPipelineJob.java b/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/NewPipelineJob.java index 1b695edd..4b5b21b8 100644 --- a/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/NewPipelineJob.java +++ b/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/NewPipelineJob.java @@ -30,14 +30,10 @@ import hudson.model.Project; import net.sf.json.JSONObject; -import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.OutputStreamWriter; import java.io.IOException; import java.io.InputStream; -import java.io.InputStreamReader; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; @@ -65,7 +61,6 @@ import java.util.ArrayList; import java.util.List; -import java.nio.charset.StandardCharsets; import java.io.UncheckedIOException; import java.nio.file.Files; @@ -171,7 +166,7 @@ public NewPipelineJob(final StaplerRequest request, final StaplerResponse respon /* absoulte path and SCM checkout of manage project conflicts with the copy_build_dir.py ability to make LIS files relative path */ - String MPName = this.getManageProjectName().replaceAll("^[ \t]+|[ \t]+$", ""); + String MPName = getManageProjectName().replaceAll("^[ \t]+|[ \t]+$", ""); Boolean absPath = false; if (MPName.startsWith("\\\\")) absPath = true; @@ -454,7 +449,7 @@ private String generateJenkinsfile() throws IOException { "//\n" + "// ===============================================================\n" + "\n" + - "VC_Manage_Project = \'" + this.getManageProjectName() + "\'\n" + + "VC_Manage_Project = \'" + getManageProjectName() + "\'\n" + "VC_EnvSetup = '''" + setup + "'''\n" + "VC_Build_Preamble = \"" + preamble + "\"\n" + "VC_EnvTeardown = '''" + teardown + "'''\n" + diff --git a/src/test/java/com/vectorcast/plugins/vectorcastexecution/job/NewSingleJobTest.java b/src/test/java/com/vectorcast/plugins/vectorcastexecution/job/NewSingleJobTest.java index bf5cf7c1..440cfa92 100644 --- a/src/test/java/com/vectorcast/plugins/vectorcastexecution/job/NewSingleJobTest.java +++ b/src/test/java/com/vectorcast/plugins/vectorcastexecution/job/NewSingleJobTest.java @@ -46,7 +46,7 @@ public class NewSingleJobTest { final long USE_EXTERNAL_IMPORTED_RESULTS = 2; final String EXTERNAL_RESULT_FILENAME = "archivedResults/project.vcr"; - @Rule + @Rule public JenkinsRule j = new JenkinsRule(); private static final String PROJECTNAME = "project.vcast.single"; @@ -58,7 +58,7 @@ void setUpStaticMocks() { void tearDownStaticMocks() { } - private NewSingleJob setupTestBasic(JSONObject jsonForm) throws ServletException, IOException, + private NewSingleJob setupTestBasic(JSONObject jsonForm) throws ServletException, IOException, ExternalResultsFileException, FormException, JobAlreadyExistsException, InvalidProjectFileException { j.jenkins.setSecurityRealm(j.createDummySecurityRealm()); @@ -71,11 +71,11 @@ private NewSingleJob setupTestBasic(JSONObject jsonForm) throws ServletException StaplerRequest request = Mockito.mock(StaplerRequest.class); StaplerResponse response = Mockito.mock(StaplerResponse.class); - + when(request.getSubmittedForm()).thenReturn(jsonForm); NewSingleJob job = new NewSingleJob(request, response); - + Assert.assertEquals("project", job.getBaseName()); job.create(false); Assert.assertEquals(PROJECTNAME, job.getProjectName()); @@ -83,26 +83,26 @@ private NewSingleJob setupTestBasic(JSONObject jsonForm) throws ServletException return job; } - + private void checkJunitGroovy(DescribableList> publisherList, int jUnitIndex, int groovyIndex) { // Publisher 1- JUnitResultArchiver Assert.assertTrue(publisherList.get(jUnitIndex) instanceof JUnitResultArchiver); JUnitResultArchiver jUnit = (JUnitResultArchiver)publisherList.get(jUnitIndex); Assert.assertEquals("**/test_results_*.xml", jUnit.getTestResults()); - + // Publisher 3 - GroovyPostbuildRecorder Assert.assertTrue(publisherList.get(groovyIndex) instanceof GroovyPostbuildRecorder); GroovyPostbuildRecorder groovyScript = (GroovyPostbuildRecorder)publisherList.get(groovyIndex); - Assert.assertEquals(/*failure*/2, groovyScript.getBehavior()); + Assert.assertEquals(/*failure*/2, groovyScript.getBehavior()); } - + private void checkArchiverList(ArtifactArchiver archiver, String artifactsList) { String artifactsFromArchiver = archiver.getArtifacts(); Assert.assertEquals(artifactsList,artifactsFromArchiver); Assert.assertFalse(archiver.getAllowEmptyArchive()); } - + private void checkVectorCASTPublisher(DescribableList> publisherList, Boolean useCoverageHistory, int vcPubIndex) { // Publisher 2 - VectorCASTPublisher Assert.assertTrue(publisherList.get(vcPubIndex) instanceof VectorCASTPublisher); @@ -123,25 +123,25 @@ private void checkVectorCASTPublisher(DescribableList> publisherList, int pubListIndex) { - + // Publisher 2 - CoverageRecorder Assert.assertTrue(publisherList.get(pubListIndex) instanceof CoverageRecorder); CoverageRecorder publisher = (CoverageRecorder) publisherList.get(pubListIndex); - + // CoverageRecorder > CoverageTool List coverageToolsList = publisher.getTools(); Assert.assertEquals(1, coverageToolsList.size()); Assert.assertTrue(coverageToolsList.get(0) instanceof CoverageTool); - CoverageTool coverageTool = (CoverageTool)coverageToolsList.get(0); + CoverageTool coverageTool = coverageToolsList.get(0); Assert.assertEquals("xml_data/cobertura/coverage_results*.xml", coverageTool.getPattern()); - Assert.assertEquals(Parser.VECTORCAST, coverageTool.getParser()); + Assert.assertEquals(Parser.VECTORCAST, coverageTool.getParser()); } - + private void checkBuildWrappers(NewSingleJob job, int builderSize){ - + // Check build wrappers... DescribableList> bldWrappersList = job.getTopProject().getBuildWrappersList(); Assert.assertEquals(builderSize, bldWrappersList.size()); @@ -150,7 +150,7 @@ private void checkBuildWrappers(NewSingleJob job, int builderSize){ PreBuildCleanup cleanup = (PreBuildCleanup)wrapper; Assert.assertTrue(cleanup.getDeleteDirs()); } - + private void checkBuildAction (NewSingleJob job) { // Check build actions... DescribableList> bldrsList = job.getTopProject().getBuildersList(); @@ -171,7 +171,7 @@ else if (useLocalResults == USE_EXTERNAL_IMPORTED_RESULTS) { Assert.assertEquals(externalResultsFilename, job.getExternalResultsFilename()); } - @Test + @Test public void testBasic() throws Exception { JSONObject jsonForm = new JSONObject(); jsonForm.put("manageProjectName", "/home/jenkins/vcast/project.vcm"); @@ -183,45 +183,45 @@ public void testBasic() throws Exception { // Check publishers... DescribableList> publisherList = job.getTopProject().getPublishersList(); Assert.assertEquals(4, publisherList.size()); - + // Publisher 0 - ArtifactArchiver Assert.assertTrue(publisherList.get(0) instanceof ArtifactArchiver); ArtifactArchiver archiver = (ArtifactArchiver)publisherList.get(0); - + checkBuildWrappers(job, 1); checkBuildAction(job); checkArchiverList(archiver, DEFAULT_ARTIFACT_LIST); checkJunitGroovy(publisherList, 1, 3); checkVectorCASTPublisher(publisherList, false, 2); - + } - - @Test + + @Test public void testAdditionalTools() throws Exception { - + JSONObject jsonForm = new JSONObject(); jsonForm.put("manageProjectName", "/home/jenkins/vcast/project.vcm"); jsonForm.put("optionClean", true); jsonForm.put("coverageDisplayOption", 1); // VectorCAST Coverage Plugin - jsonForm.put("useCoverageHistory", true); + jsonForm.put("useCoverageHistory", true); jsonForm.put("pclpCommand","call lint_my_code.bat"); jsonForm.put("pclpResultsPattern","lint_results.xml"); jsonForm.put("TESTinsights_URL","https://teamservices.vector.com/teamareas/pct"); NewSingleJob job = setupTestBasic(jsonForm); - + // Check publishers... DescribableList> publisherList = job.getTopProject().getPublishersList(); Assert.assertEquals(5, publisherList.size()); - + // Publisher 0 - ArtifactArchiver Assert.assertTrue(publisherList.get(0) instanceof ArtifactArchiver); ArtifactArchiver archiver = (ArtifactArchiver)publisherList.get(0); - + String addToolArtifacts = DEFAULT_ARTIFACT_LIST; addToolArtifacts += ", lint_results.xml"; addToolArtifacts += ", TESTinsights_Push.log"; - + checkBuildWrappers(job, 2); checkBuildAction(job); checkArchiverList(archiver, addToolArtifacts); @@ -229,9 +229,9 @@ public void testAdditionalTools() throws Exception { checkVectorCASTPublisher(publisherList, true, 3); } - @Test + @Test public void testCoveragePlugin() throws Exception { - + JSONObject jsonForm = new JSONObject(); jsonForm.put("manageProjectName", "/home/jenkins/vcast/project.vcm"); jsonForm.put("optionClean", true); @@ -242,27 +242,27 @@ public void testCoveragePlugin() throws Exception { jsonForm.put("TESTinsights_URL","https://teamservices.vector.com/teamareas/pct"); NewSingleJob job = setupTestBasic(jsonForm); - + // Check publishers... DescribableList> publisherList = job.getTopProject().getPublishersList(); Assert.assertEquals(5, publisherList.size()); - + // Publisher 0 - ArtifactArchiver Assert.assertTrue(publisherList.get(0) instanceof ArtifactArchiver); ArtifactArchiver archiver = (ArtifactArchiver)publisherList.get(0); - + String addToolArtifacts = DEFAULT_ARTIFACT_LIST; addToolArtifacts += ", lint_results.xml"; addToolArtifacts += ", TESTinsights_Push.log"; - + checkBuildWrappers(job, 2); checkBuildAction(job); checkArchiverList(archiver, addToolArtifacts); checkJunitGroovy(publisherList, 2, 4); checkCoveragePlugin(publisherList, 3); } - - @Test + + @Test public void testLocalImportedResults() throws Exception { JSONObject jsonImportResults = new JSONObject(); @@ -276,11 +276,11 @@ public void testLocalImportedResults() throws Exception { jsonForm.put("importedResults", jsonImportResults); NewSingleJob job = setupTestBasic(jsonForm); - + // Check publishers... DescribableList> publisherList = job.getTopProject().getPublishersList(); Assert.assertEquals(4, publisherList.size()); - + // Publisher 0 - ArtifactArchiver Assert.assertTrue(publisherList.get(0) instanceof ArtifactArchiver); ArtifactArchiver archiver = (ArtifactArchiver)publisherList.get(0); @@ -292,8 +292,8 @@ public void testLocalImportedResults() throws Exception { checkCoveragePlugin(publisherList, 2); checkImportedResults(job, USE_LOCAL_IMPORTED_RESULTS, false, ""); } - - @Test + + @Test public void testExternalImportedResults() throws Exception { JSONObject jsonImportResults = new JSONObject(); @@ -308,11 +308,11 @@ public void testExternalImportedResults() throws Exception { jsonForm.put("importedResults", jsonImportResults); NewSingleJob job = setupTestBasic(jsonForm); - + // Check publishers... DescribableList> publisherList = job.getTopProject().getPublishersList(); Assert.assertEquals(4, publisherList.size()); - + // Publisher 0 - ArtifactArchiver Assert.assertTrue(publisherList.get(0) instanceof ArtifactArchiver); ArtifactArchiver archiver = (ArtifactArchiver)publisherList.get(0); From 4c7c5ee9b88d8597632175f37003352f166ded85 Mon Sep 17 00:00:00 2001 From: TimSVector Date: Thu, 11 Jul 2024 16:18:53 -0400 Subject: [PATCH 034/112] Updates for auto testing --- .github/workflows/lint.yml | 4 ++-- .github/workflows/pylint.yml | 34 ++++++++++++++++++++++++++++++++++ pom.xml | 9 --------- 3 files changed, 36 insertions(+), 11 deletions(-) create mode 100644 .github/workflows/pylint.yml diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index b53dc120..ba2d2020 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -11,8 +11,8 @@ jobs: strategy: matrix: - platform: [ubuntu-latest, windows-latest] - jdk: [11, 17, 21] + platform: [ubuntu-latest] + jdk: [17] runs-on: ${{ matrix.platform }} name: on ${{ matrix.platform }} with JDK ${{ matrix.jdk }} diff --git a/.github/workflows/pylint.yml b/.github/workflows/pylint.yml new file mode 100644 index 00000000..0d1a7495 --- /dev/null +++ b/.github/workflows/pylint.yml @@ -0,0 +1,34 @@ +name: 'Python Lint' + +on: + # Trigger the workflow on push or pull request, + # but only for the main branch + push: + branches: + - main + pull_request: + branches: + - main + +jobs: + run-linters: + name: Run linters + runs-on: ubuntu-latest + + steps: + - name: Check out Git repository + uses: actions/checkout@v3 + + - name: Set up Python + uses: actions/setup-python@v1 + with: + python-version: 3.8 + + - name: Install Python dependencies + run: pip install black flake8 + + - name: Run linters + uses: wearerequired/lint-action@v2 + with: + black: true + flake8: true \ No newline at end of file diff --git a/pom.xml b/pom.xml index 323b43f2..522a5bb6 100644 --- a/pom.xml +++ b/pom.xml @@ -265,15 +265,6 @@ ${lintCompilerArgs} - - - run-spotbugs - verify - - check - - - org.codehaus.mojo From 07928948537c036a4ce1b16c617ce7a519445408 Mon Sep 17 00:00:00 2001 From: TimSVector Date: Thu, 11 Jul 2024 16:39:34 -0400 Subject: [PATCH 035/112] Updates for auto-testing --- .github/workflows/codeql.yml | 2 +- .github/workflows/lint.yml | 36 ------------------- .../job/NewPipelineJob.java | 2 +- 3 files changed, 2 insertions(+), 38 deletions(-) delete mode 100644 .github/workflows/lint.yml diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index af74477f..c0023a0c 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -49,7 +49,7 @@ jobs: queries: +security-and-quality - name: Build with Maven - run: mvn -V --color always -ntp clean verify --file pom.xml -Pskip + run: mvn -V --color always -ntp clean verify -Plint --file pom.xml -Pskip - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v3 diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml deleted file mode 100644 index ba2d2020..00000000 --- a/.github/workflows/lint.yml +++ /dev/null @@ -1,36 +0,0 @@ -name: 'Java Lint' - -on: - push: - branches: - - master - pull_request: - -jobs: - build: - - strategy: - matrix: - platform: [ubuntu-latest] - jdk: [17] - - runs-on: ${{ matrix.platform }} - name: on ${{ matrix.platform }} with JDK ${{ matrix.jdk }} - - steps: - - uses: actions/checkout@v4 - - name: Set up JDK ${{ matrix.jdk }} - uses: actions/setup-java@v4 - with: - distribution: 'temurin' - java-version: '${{ matrix.jdk }}' - check-latest: true - cache: 'maven' - - name: Set up Maven - uses: stCarolas/setup-maven@v5 - with: - maven-version: 3.9.6 - - name: Build with Maven - env: - BROWSER: chrome-container - run: mvn -V --color always -ntp clean compile -Plint --file pom.xml '-Djenkins.test.timeout=5000' '-Dgpg.skip' \ No newline at end of file diff --git a/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/NewPipelineJob.java b/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/NewPipelineJob.java index 4b5b21b8..5e157c7b 100644 --- a/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/NewPipelineJob.java +++ b/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/NewPipelineJob.java @@ -166,7 +166,7 @@ public NewPipelineJob(final StaplerRequest request, final StaplerResponse respon /* absoulte path and SCM checkout of manage project conflicts with the copy_build_dir.py ability to make LIS files relative path */ - String MPName = getManageProjectName().replaceAll("^[ \t]+|[ \t]+$", ""); + String MPName = getManageProjectName(); Boolean absPath = false; if (MPName.startsWith("\\\\")) absPath = true; From 682e28461dd28761c5da1c4afedecb8e4e6ee52e Mon Sep 17 00:00:00 2001 From: TimSVector Date: Wed, 17 Jul 2024 14:33:46 -0400 Subject: [PATCH 036/112] Updates for expanded testing and fixes from 077 function coverage stuff --- .../vectorcastexecution/job/BaseJob.java | 220 ++++++--------- .../job/NewPipelineJob.java | 259 +++++++++++------- src/main/resources/scripts/cobertura.py | 4 +- .../resources/scripts/generate-results.py | 8 +- .../scripts/generate_sonarqube_testresults.py | 2 + src/main/resources/scripts/generate_xml.py | 43 ++- src/main/resources/scripts/managewait.py | 10 +- src/main/resources/scripts/vcast_exec.py | 4 +- .../job/NewPipelineTest.java | 230 +++++++++++++++- .../job/NewSingleJobTest.java | 163 ++++++++++- 10 files changed, 675 insertions(+), 268 deletions(-) diff --git a/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/BaseJob.java b/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/BaseJob.java index 7d7f1a3d..7a7f598a 100644 --- a/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/BaseJob.java +++ b/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/BaseJob.java @@ -123,8 +123,6 @@ abstract public class BaseJob { private boolean usingSCM; /** The SCM being used */ private SCM scm; - /** Use saved data or not */ - private boolean useSavedData; /** Wait time */ private Long waitTime; /** Wait loops */ @@ -165,139 +163,91 @@ protected BaseJob(final StaplerRequest request, final StaplerResponse response, this.request = request; this.response = response; JSONObject json = request.getSubmittedForm(); - + + Logger.getLogger(BaseJob.class.getName()).log(Level.INFO, "JSONObject Submitted Form"+ json.toString()); + manageProjectName = json.optString("manageProjectName"); if (!manageProjectName.isEmpty()) { // Force unix style path to avoid problems later manageProjectName = manageProjectName.replace('\\','/'); manageProjectName = manageProjectName.replaceAll("^[ \t]+|[ \t]+$", ""); if (! manageProjectName.toLowerCase().endsWith(".vcm")) manageProjectName += ".vcm"; - } + } baseName = FilenameUtils.getBaseName(manageProjectName); - this.useSavedData = useSavedData; - if (!useSavedData) { - this.usingSCM = false; + environmentSetupWin = json.optString("environmentSetupWin"); + executePreambleWin = json.optString("executePreambleWin"); + environmentTeardownWin = json.optString("environmentTeardownWin"); - environmentSetupWin = json.optString("environmentSetupWin"); - executePreambleWin = json.optString("executePreambleWin"); - environmentTeardownWin = json.optString("environmentTeardownWin"); + environmentSetupUnix = json.optString("environmentSetupUnix"); + executePreambleUnix = json.optString("executePreambleUnix"); + environmentTeardownUnix = json.optString("environmentTeardownUnix"); - environmentSetupUnix = json.optString("environmentSetupUnix"); - executePreambleUnix = json.optString("executePreambleUnix"); - environmentTeardownUnix = json.optString("environmentTeardownUnix"); + optionUseReporting = json.optBoolean("optionUseReporting", true); + optionErrorLevel = json.optString("optionErrorLevel", "Unstable"); + optionHtmlBuildDesc = json.optString("optionHtmlBuildDesc", "HTML"); + optionExecutionReport = json.optBoolean("optionExecutionReport", true); + optionClean = json.optBoolean("optionClean", false); - optionUseReporting = json.optBoolean("optionUseReporting", true); - optionErrorLevel = json.optString("optionErrorLevel", "Unstable"); - optionHtmlBuildDesc = json.optString("optionHtmlBuildDesc", "HTML"); - optionExecutionReport = json.optBoolean("optionExecutionReport", true); - optionClean = json.optBoolean("optionClean", false); + waitTime = json.optLong("waitTime", 5); + waitLoops = json.optLong("waitLoops", 2); - waitTime = json.optLong("waitTime", 5); - waitLoops = json.optLong("waitLoops", 2); - - jobName = json.optString("jobName", null); - - if (jobName != null) { - // Remove all non-alphanumeric characters from the Jenkins Job name - jobName = jobName.replaceAll("[^a-zA-Z0-9_]","_"); - } - - nodeLabel = json.optString("nodeLabel", ""); - - useCILicenses = json.optBoolean("useCiLicense", false); - useStrictTestcaseImport = json.optBoolean("useStrictTestcaseImport", true); - useRGW3 = json.optBoolean("useRGW3", false); - useImportedResults = json.optBoolean("useImportedResults", false); - if (json.optInt("coverageDisplayOption", 0) == 0) { - useCoveragePlugin = true; - } else { - useCoveragePlugin = false; - } - externalResultsFilename = ""; + jobName = json.optString("jobName", null); + + if (jobName != null) { + // Remove all non-alphanumeric characters from the Jenkins Job name + jobName = jobName.replaceAll("[^a-zA-Z0-9_]","_"); + } + + nodeLabel = json.optString("nodeLabel", ""); + + useCILicenses = json.optBoolean("useCiLicense", false); + useStrictTestcaseImport = json.optBoolean("useStrictTestcaseImport", true); + useRGW3 = json.optBoolean("useRGW3", false); + useImportedResults = json.optBoolean("useImportedResults", false); + if (json.optInt("coverageDisplayOption", 0) == 0) { + useCoveragePlugin = true; + } else { + useCoveragePlugin = false; + } + externalResultsFilename = ""; + + if (useImportedResults) { + JSONObject jsonImportResults = json.optJSONObject("importedResults"); - if (useImportedResults) { - JSONObject jsonImportResults = json.optJSONObject("importedResults"); + if (jsonImportResults != null) { + final long int_ext = jsonImportResults.optLong("value",0); - if (jsonImportResults != null) { - final long int_ext = jsonImportResults.optLong("value",0); - - if (int_ext == 1) { - useLocalImportedResults = true; - useExternalImportedResults = false; - externalResultsFilename = ""; - } else if (int_ext == 2) { - useLocalImportedResults = false; - useExternalImportedResults = true; - externalResultsFilename = jsonImportResults.optString("externalResultsFilename",""); - if (externalResultsFilename.length() == 0) { - throw new ExternalResultsFileException(); - } + if (int_ext == 1) { + useLocalImportedResults = true; + useExternalImportedResults = false; + externalResultsFilename = ""; + } else if (int_ext == 2) { + useLocalImportedResults = false; + useExternalImportedResults = true; + externalResultsFilename = jsonImportResults.optString("externalResultsFilename",""); + if (externalResultsFilename.length() == 0) { + throw new ExternalResultsFileException(); } } } - useCoverageHistory = json.optBoolean("useCoverageHistory", false); - maxParallel = json.optLong("maxParallel", 0); - - /* Additional Tools */ - pclpCommand = json.optString("pclpCommand", "").replace('\\','/'); - pclpResultsPattern = json.optString("pclpResultsPattern", ""); - squoreCommand = json.optString("squoreCommand", "").replace('\\','/'); - TESTinsights_URL = json.optString("TESTinsights_URL", ""); - TESTinsights_project = json.optString("TESTinsights_project", ""); - if (TESTinsights_project.length() == 0) { - TESTinsights_project = "env.JOB_BASE_NAME"; - } - TESTinsights_credentials_id = json.optString("TESTinsights_credentials_id", ""); - TESTinsights_proxy = json.optString("TESTinsights_proxy", ""); - } + } + useCoverageHistory = json.optBoolean("useCoverageHistory", false); + maxParallel = json.optLong("maxParallel", 0); + + /* Additional Tools */ + pclpCommand = json.optString("pclpCommand", "").replace('\\','/'); + pclpResultsPattern = json.optString("pclpResultsPattern", ""); + squoreCommand = json.optString("squoreCommand", "").replace('\\','/'); + TESTinsights_URL = json.optString("TESTinsights_URL", ""); + TESTinsights_project = json.optString("TESTinsights_project", ""); + if (TESTinsights_project.length() == 0) { + TESTinsights_project = "env.JOB_BASE_NAME"; + } + TESTinsights_credentials_id = json.optString("TESTinsights_credentials_id", ""); + TESTinsights_proxy = json.optString("TESTinsights_proxy", ""); } - /** - * Use Saved Data - * @param savedData saved data to use - */ - public void useSavedData(VectorCASTSetup savedData) { - environmentSetupWin = savedData.getEnvironmentSetupWin(); - executePreambleWin = savedData.getExecutePreambleWin(); - environmentTeardownWin = savedData.getEnvironmentTeardownWin(); - - environmentSetupUnix = savedData.getEnvironmentSetupUnix(); - executePreambleUnix = savedData.getExecutePreambleUnix(); - environmentTeardownUnix = savedData.getEnvironmentTeardownUnix(); - optionUseReporting = savedData.getOptionUseReporting(); - optionErrorLevel = savedData.getOptionErrorLevel(); - optionHtmlBuildDesc = savedData.getOptionHtmlBuildDesc(); - optionExecutionReport = savedData.getOptionExecutionReport(); - optionClean = savedData.getOptionClean(); - useCILicenses = savedData.getUseCILicenses(); - useStrictTestcaseImport = savedData.getUseStrictTestcaseImport(); - useRGW3 = savedData.getUseRGW3(); - useImportedResults = savedData.getUseImportedResults(); - useLocalImportedResults = savedData.getUseLocalImportedResults(); - useExternalImportedResults = savedData.getUseExternalImportedResults(); - externalResultsFilename = savedData.getExternalResultsFilename(); - useCoverageHistory = savedData.getUseCoverageHistory(); - maxParallel = savedData.getMaxParallel(); - - useCoveragePlugin = savedData.getUseCoveragePlugin(); - usingSCM = savedData.getUsingSCM(); - scm = savedData.getSCM(); - - waitTime = savedData.getWaitTime(); - waitLoops = savedData.getWaitLoops(); - jobName = savedData.getJobName(); - nodeLabel = savedData.getNodeLabel(); - pclpCommand = savedData.getPclpCommand(); - pclpResultsPattern = savedData.getPclpResultsPattern(); - squoreCommand = savedData.getSquoreCommand(); - TESTinsights_URL = savedData.getTESTinsights_URL(); - TESTinsights_project = savedData.getTESTinsights_project(); - TESTinsights_proxy = savedData.getTESTinsights_proxy(); - TESTinsights_credentials_id = savedData.getTESTinsights_credentials_id(); - TESTinsights_SCM_URL = savedData.getTESTinsights_SCM_URL(); - TESTinsights_SCM_Tech = savedData.getTESTinsights_SCM_Tech(); - } /** * Using some form of SCM * @return true or false @@ -829,28 +779,26 @@ public void create(boolean update) throws IOException, ServletException, Descrip return; } - if (!useSavedData) { - // Read the SCM setup - scm = SCMS.parseSCM(request, topProject); - if (scm == null) { - scm = new NullSCM(); - } - if (scm instanceof NullSCM) { - usingSCM = false; + // Read the SCM setup + scm = SCMS.parseSCM(request, topProject); + if (scm == null) { + scm = new NullSCM(); + } + if (scm instanceof NullSCM) { + usingSCM = false; + } else { + usingSCM = true; + + // for TESTinsights SCM connector + String scmName = scm.getDescriptor().getDisplayName(); + if (scmName == "Git") { + TESTinsights_SCM_Tech = "git"; + } else if (scmName == "Subversion") { + TESTinsights_SCM_Tech = "svn"; } else { - usingSCM = true; - - // for TESTinsights SCM connector - String scmName = scm.getDescriptor().getDisplayName(); - if (scmName == "Git") { - TESTinsights_SCM_Tech = "git"; - } else if (scmName == "Subversion") { - TESTinsights_SCM_Tech = "svn"; - } else { - TESTinsights_SCM_Tech = ""; - } - Logger.getLogger(BaseJob.class.getName()).log(Level.INFO, "SCM Info: " + scmName); + TESTinsights_SCM_Tech = ""; } + Logger.getLogger(BaseJob.class.getName()).log(Level.INFO, "SCM Info: " + scmName); } topProject.setScm(scm); diff --git a/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/NewPipelineJob.java b/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/NewPipelineJob.java index 5e157c7b..5a279322 100644 --- a/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/NewPipelineJob.java +++ b/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/NewPipelineJob.java @@ -77,19 +77,19 @@ */ public class NewPipelineJob extends BaseJob { /** project name */ - + private String sharedArtifactDirectory; - + private String pipelineSCM = ""; - + private boolean singleCheckout; - + private boolean useCBT; private boolean useParameters; - + private String postSCMCheckoutCommands; - + /** Environment setup script */ private String environmentSetup; /** Execute preamble */ @@ -99,7 +99,7 @@ public class NewPipelineJob extends BaseJob { /** * Constructor - * + * * @param request request object * @param response response object * @throws ServletException exception @@ -110,31 +110,31 @@ public class NewPipelineJob extends BaseJob { public NewPipelineJob(final StaplerRequest request, final StaplerResponse response) throws ServletException, IOException, ScmConflictException, ExternalResultsFileException { super(request, response, false); - + JSONObject json = request.getSubmittedForm(); - + sharedArtifactDirectory = json.optString("sharedArtifactDir",""); pipelineSCM = json.optString("scmSnippet","").trim(); - + String[] lines = pipelineSCM.split("\n"); - + List scm_list = new ArrayList(); scm_list.add("git"); scm_list.add("svn"); - + String url = ""; String scm_technology = ""; for (String line : lines) { - + for (String scm : scm_list) { if (line.startsWith(scm)) { scm_technology = scm; - + if (line.indexOf("url:") == -2) { String[] elements = line.split(","); for (String ele : elements) { - + if (ele.startsWith("url:")) { String[] ele_list = ele.split(" "); url = ele_list[ele_list.length - 1]; @@ -149,10 +149,10 @@ public NewPipelineJob(final StaplerRequest request, final StaplerResponse respon } setTESTinsights_SCM_URL(url.replace("'","")); setTESTinsights_SCM_Tech(scm_technology); - + singleCheckout = json.optBoolean("singleCheckout", false); - - // remove the win/linux options since there's no platform any more + + // remove the win/linux options since there's no platform any more environmentSetup = json.optString("environmentSetup", null); executePreamble = json.optString("executePreamble", null); environmentTeardown = json.optString("environmentTeardown", null); @@ -162,23 +162,23 @@ public NewPipelineJob(final StaplerRequest request, final StaplerResponse respon if (sharedArtifactDirectory.length() != 0) { sharedArtifactDirectory = "--workspace="+sharedArtifactDirectory.replace("\\","/"); } - - /* absoulte path and SCM checkout of manage project conflicts with - the copy_build_dir.py ability to make LIS files relative path + + /* absoulte path and SCM checkout of manage project conflicts with + the copy_build_dir.py ability to make LIS files relative path */ String MPName = getManageProjectName(); Boolean absPath = false; - + if (MPName.startsWith("\\\\")) absPath = true; if (MPName.startsWith("/")) absPath = true; if (MPName.matches("[a-zA-Z]:.*")) absPath = true; - + if (! MPName.toLowerCase().endsWith(".vcm")) MPName += ".vcm"; - + if (pipelineSCM.length() != 0 && absPath) { throw new ScmConflictException(pipelineSCM, MPName); } - + if (getTESTinsights_project() == "env.JOB_BASE_NAME") { setTESTinsights_project("${JOB_BASE_NAME}"); } @@ -186,11 +186,11 @@ public NewPipelineJob(final StaplerRequest request, final StaplerResponse respon /** * Create project - * + * * @return project * @throws IOException exception * @throws JobAlreadyExistsException exception - + */ @Override protected Project createProject() throws IOException, JobAlreadyExistsException { @@ -206,25 +206,25 @@ protected Project createProject() throws IOException, JobAlreadyExistsExcep projectName = getJobName(); } else { - projectName = getBaseName() + ".vcast.pipeline"; + projectName = getBaseName() + ".vcast.pipeline"; } // Remove all non-alphanumeric characters from the Jenkins Job name projectName = projectName.replaceAll("[^a-zA-Z0-9_]","_"); - + setProjectName(projectName); if (getInstance().getJobNames().contains(projectName)) { throw new JobAlreadyExistsException(projectName); } - + Logger.getLogger(NewPipelineJob.class.getName()).log(Level.INFO, "Pipeline Project Name: " + projectName, "Pipeline Project Name: " + projectName); return null; } /** * Add build steps - * + * * @param update true to update, false to not * @throws IOException exception * @throws ServletException exception @@ -232,7 +232,7 @@ protected Project createProject() throws IOException, JobAlreadyExistsExcep */ @Override public void doCreate(boolean update) throws IOException, ServletException, Descriptor.FormException { - + // Get config.xml resource from jar and write it to temp File configFile = writeConfigFile_FILES(); @@ -283,9 +283,9 @@ public void doCreate(boolean update) throws IOException, ServletException, Descr } catch (IllegalArgumentException e) { e.printStackTrace(); } - + if (!configFile.delete()) { - throw new IOException("Unable to delete file: " + configFile.getAbsolutePath()); + throw new IOException("Unable to delete file: " + configFile.getAbsolutePath()); } } @@ -297,15 +297,15 @@ public void doCreate(boolean update) throws IOException, ServletException, Descr * @throws hudson.model.Descriptor.FormException exception * @throws JobAlreadyExistsException exception * @throws InvalidProjectFileException exception - */ - public void create(boolean update) throws IOException, ServletException, Descriptor.FormException, + */ + public void create(boolean update) throws IOException, ServletException, Descriptor.FormException, JobAlreadyExistsException, InvalidProjectFileException { - + // Create the top-level project - topProject = createProject(); + topProject = createProject(); doCreate(update); } - + static private Path createTempFile(Path tempDirChild) throws UncheckedIOException { try { if (tempDirChild.getFileSystem().supportedFileAttributeViews().contains("posix")) { @@ -332,31 +332,31 @@ static private Path createTempFile(Path tempDirChild) throws UncheckedIOExceptio // On Windows, we still need to create the directory, when it doesn't already exist. Files.createDirectory(tempDirChild); // GOOD: Windows doesn't share the temp directory between users } - + return tempDirChild.toAbsolutePath(); } catch (IOException exception) { throw new UncheckedIOException("Failed to create temp file", exception); } } - + /** * Retrieves config.xml from the jar and writes it to the systems temp * directory. - * + * * @return * @throws UncheckedIOException */ private File writeConfigFile_FILES() throws IOException { - + InputStream in; Path configFile; - + if (useParameters) { in = getClass().getResourceAsStream("/scripts/config_parameters.xml"); } else { in = getClass().getResourceAsStream("/scripts/config.xml"); } - + configFile = createTempFile(Paths.get("config_temp.xml")); try { @@ -364,24 +364,85 @@ private File writeConfigFile_FILES() throws IOException { } catch (IOException exception) { Logger.getLogger(NewPipelineJob.class.getName()).log(Level.SEVERE, null, exception); } catch (UnsupportedOperationException exception) { - Logger.getLogger(NewPipelineJob.class.getName()).log(Level.SEVERE, null, exception); + Logger.getLogger(NewPipelineJob.class.getName()).log(Level.SEVERE, null, exception); } catch (SecurityException exception) { Logger.getLogger(NewPipelineJob.class.getName()).log(Level.SEVERE, null, exception); } - + return configFile.toFile(); + } + /** + * Get pipelineSCM + * @return pipelineSCM String + */ + protected String getPipelineSCM() { + return this.pipelineSCM; + } + /** + * Get getPostSCMCheckoutCommands + * @return postSCMCheckoutCommands String + */ + protected String getPostSCMCheckoutCommands() { + return this.postSCMCheckoutCommands; + } + + /** + * Get getUseParameters + * @return useParameters boolean + */ + protected boolean getUseParameters() { + return this.useParameters; + } + + /** + * Get getSingleCheckout + * @return singleCheckout boolean + */ + protected boolean getSingleCheckout() { + return this.singleCheckout; + } + + /** + * Get getEnvironmentSetup + * @return environmentSetup String + */ + protected String getEnvironmentSetup() { + return this.environmentSetup; + } + + /** + * Get getExecutePreamble + * @return executePreamble String + */ + protected String getExecutePreamble() { + return this.executePreamble; + } + + /** + * Get getExecutePreamble + * @return executePreamble String + */ + protected String getEnvironmentTeardown() { + return this.environmentTeardown; } - /** * Get getSharedArtifactDirectory * @return sharedArtifactDirectory string */ - protected String getSharedArtifactDirectory() { + protected String getSharedArtifactDir() { return this.sharedArtifactDirectory; } + /** + * Get getUseCBT + * @return getUseCBT boolean + */ + protected boolean getUseCBT() { + return this.useCBT; + } + /** * Get BaseJenkinsfile * @return BaseJenkinsfile string @@ -403,12 +464,12 @@ private String getBaseJenkinsfile() throws IOException { /** * Generates the