Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor report portal launch import flow #646

Merged
merged 1 commit into from
Mar 6, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 29 additions & 19 deletions scripts/junit2reportportal
Original file line number Diff line number Diff line change
@@ -4,6 +4,7 @@ import argparse
import io
import os
import sys
import json
import zipfile

from lxml import etree
@@ -23,17 +24,29 @@ aparser.add_argument(
help="Desired launch name in reportportal. default: RP_LAUNCH_NAME env",
default=os.environ.get("RP_LAUNCH_NAME", os.environ.get("RP_LAUNCH")),
)
aparser.add_argument(
"--launch-description",
help="Description of the imported launch. default: RP_LAUNCH_DESC env",
default=os.environ.get("RP_LAUNCH_DESC", ""),
)
aparser.add_argument(
"--ocp-version",
help="OCP version of the cluster imported launch is from. default: OCP_VERSION env",
default=os.environ.get("OCP_VERSION"),
)
aparser.add_argument("--token-variable", help="env variable with auth token. default: RP_TOKEN", default="RP_TOKEN")
aparser.add_argument("junitfile", nargs="+", help="junit file to import")
args = aparser.parse_args()

if not args.reportportal:
sys.exit("You must define reportportal URL")
if not args.project:
sys.exit("You must define reportportal project")
if not args.launch_name:
sys.exit("You must define reportportal launch name")
if not args.token_variable:
sys.exit("You must define correct token-variable")

polish = etree.XSLT(etree.parse("./xslt/polish-junit.xsl"))

stream = io.BytesIO()

xml = None
@@ -44,37 +57,34 @@ with zipfile.ZipFile(stream, mode="w", compression=zipfile.ZIP_DEFLATED) as azip
for file in [i for i in zipfile.Path(inzip, at="archive/").iterdir() if i.name.startswith("junit-")]:
with file.open() as junit:
xml = etree.parse(junit)
content = etree.tostring(polish(xml))
content = etree.tostring(xml)
azip.writestr(file.name, content)
else:
xml = etree.parse(junitfile)
content = etree.tostring(polish(xml))
content = etree.tostring(xml)
azip.writestr(os.path.basename(junitfile), content)

if not args.launch_name:
try:
args.launch_name = xml.xpath("//property[@name = 'polarion-testrun-title']/@value")[0]
assert args.launch_name
except Exception:
sys.exit("You must define reportportal launch")

if not args.project:
try:
args.project = xml.xpath("//property[@name = 'project']/@value")[0]
assert args.project
except Exception:
sys.exit("You must define reportportal project")

token = os.environ[args.token_variable]
reportportal = args.reportportal.rstrip("/")

auth = {"Authorization": f"Bearer {token}"}
launch_import = f"{reportportal}/api/v1/{args.project}/launch/import"

launch_import_rq = {
"attributes": [
{"key": "skippedIsNotIssue", "system": True, "value": "true"},
],
"description": args.launch_description,
}
launch_import_rq["attributes"].extend([{"key": "ocp", "value": args.ocp_version}] if args.ocp_version else [])

print(
requests.post(
launch_import,
files={"file": (f"{args.launch_name}.zip", stream.getbuffer(), "application/zip")},
files={
"file": (f"{args.launch_name}.zip", stream.getbuffer(), "application/zip"),
"launchImportRq": (None, json.dumps(launch_import_rq), "application/json"),
},
headers=auth,
).text
)
48 changes: 12 additions & 36 deletions xslt/polish-junit.xsl
Original file line number Diff line number Diff line change
@@ -1,49 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<!-- https://source.redhat.com/groups/public/polarion/polarion_wiki/polarion_results_xunit_importer -->
<!-- https://mojo.redhat.com/docs/DOC-1073077 -->

<xsl:param name="rmfails"/>
<xsl:param name="rmlogs" select="true()"/>
<xsl:param name="polarionProperties"/>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="node()|@*">
<!-- this copies all objects that do not match other template -->
<!-- this copies all objects that do not match any other template -->
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>

<xsl:template match="/testsuites">
<!-- Add full testsuite path to each testcase name -->
<xsl:template match="testcase">
<xsl:copy>
<xsl:if test="$polarionProperties">
<xsl:copy-of select="./testsuite/properties"/>
</xsl:if>
<xsl:apply-templates select="node()|@*"/>
<!-- Copy all attributes except name -->
<xsl:apply-templates select="@*[not(name() = 'name')]"/>
<!-- Modify the name attribute -->
<xsl:attribute name="name">
<xsl:value-of select="concat(@classname, '.', @name)"/>
</xsl:attribute>
<!-- Copy child nodes -->
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>

<xsl:template match="testcase[skipped]"/>
<xsl:template match="testsuite/@skipped">
<xsl:attribute name="skipped">0</xsl:attribute>
</xsl:template>

<xsl:template match="testcase[failure or error]">
<xsl:if test="not($rmfails)">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:if>
</xsl:template>

<xsl:template match='testcase[not(failure or error)]/*[starts-with(name(), "system-")]/text()'>
<xsl:if test="not($rmlogs)">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:if>
</xsl:template>
</xsl:stylesheet>