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

Add reportportal scripts #297

Merged
merged 1 commit into from
Dec 4, 2023
Merged
Show file tree
Hide file tree
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
15 changes: 14 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.PHONY: commit-acceptance pylint mypy black reformat test performance authorino poetry poetry-no-dev mgc container-image
.PHONY: commit-acceptance pylint mypy black reformat test performance authorino poetry poetry-no-dev mgc container-image polish-junit reportportal

TB ?= short
LOGLEVEL ?= INFO
Expand All @@ -10,6 +10,7 @@ resultsdir ?= .
endif

PYTEST = poetry run python -m pytest --tb=$(TB) -o cache_dir=$(resultsdir)/.pytest_cache.$(@F)
RUNSCRIPT = poetry run ./scripts/

ifdef junit
PYTEST += --junitxml=$(resultsdir)/junit-$(@F).xml -o junit_suite_name=$(@F)
Expand Down Expand Up @@ -71,6 +72,18 @@ poetry: .make-poetry-sync ## Installs poetry with all dependencies

poetry-no-dev: .make-poetry-sync-no-dev ## Installs poetry without development dependencies

polish-junit: ## Remove skipped tests and logs from passing tests
polish-junit:
gzip -f $(resultsdir)/junit-*.xml
# 'cat' on next line is neessary to avoid wipe of the files
for file in $(resultsdir)/junit-*.xml.gz; do zcat $$file | $(RUNSCRIPT)xslt-apply ./xslt/polish-junit.xsl >$${file%.gz}; done # bashism!!!
# this deletes something it didn't create, dangerous!!!
-rm -f $(resultsdir)/junit-*.xml.gz

reportportal: ## Upload results to reportportal. Appropriate variables for juni2reportportal must be set
reportportal: polish-junit
$(RUNSCRIPT)junit2reportportal $(resultsdir)/junit-*.xml

# Check http://marmelab.com/blog/2016/02/29/auto-documented-makefile.html
help: ## Print this help
@awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST)
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ pytest-html = "*"
dynaconf = "*"
python-keycloak = ">=3.6"
python-jose = "*"
lxml = "*"
cryptography = "*"
backoff = "*"
httpx = { version = "*", extras = ["http2"] }
Expand Down
80 changes: 80 additions & 0 deletions scripts/junit2reportportal
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#!/usr/bin/env python

import argparse
import io
import os
import sys
import zipfile

from lxml import etree
import requests

aparser = argparse.ArgumentParser(description="Upload junit to reportportal")
aparser.add_argument(
"--reportportal", help="URL of reportportal. default: REPORTPORTAL env", default=os.environ.get("REPORTPORTAL")
)
aparser.add_argument(
"--project",
help="reportportal project where to import. default: RP_PROJECT env",
default=os.environ.get("RP_PROJECT"),
)
aparser.add_argument(
"--launch-name",
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("--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.token_variable:
sys.exit("You must define correct token-variable")

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

stream = io.BytesIO()

xml = None
with zipfile.ZipFile(stream, mode="w", compression=zipfile.ZIP_DEFLATED) as azip:
for junitfile in args.junitfile:
if zipfile.is_zipfile(junitfile):
with zipfile.ZipFile(junitfile) as inzip:
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))
azip.writestr(file.name, content)
else:
xml = etree.parse(junitfile)
content = etree.tostring(polish(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"

print(
requests.post(
launch_import,
files={"file": (f"{args.launch_name}.zip", stream.getbuffer(), "application/zip")},
headers=auth,
).text
)
7 changes: 7 additions & 0 deletions scripts/xslt-apply
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/usr/bin/env python

import sys
from lxml import etree

xslt = etree.XSLT(etree.parse(sys.argv[1]))
print(xslt(etree.parse(sys.stdin)))
49 changes: 49 additions & 0 deletions xslt/polish-junit.xsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?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:template match="node()|@*">
<!-- this copies all objects that do not match other template -->
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>

<xsl:template match="/testsuites">
<xsl:copy>
<xsl:if test="$polarionProperties">
<xsl:copy-of select="./testsuite/properties"/>
</xsl:if>
<xsl:apply-templates select="node()|@*"/>
</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>