From 748419aec7fe0b600b665888abf9a7d2cc7f4354 Mon Sep 17 00:00:00 2001 From: phala Date: Tue, 28 Nov 2023 11:59:58 +0100 Subject: [PATCH] Add reportportal scripts --- Makefile | 15 ++++++- pyproject.toml | 1 + scripts/junit2reportportal | 80 ++++++++++++++++++++++++++++++++++++++ scripts/xslt-apply | 7 ++++ xslt/polish-junit.xsl | 49 +++++++++++++++++++++++ 5 files changed, 151 insertions(+), 1 deletion(-) create mode 100755 scripts/junit2reportportal create mode 100755 scripts/xslt-apply create mode 100644 xslt/polish-junit.xsl diff --git a/Makefile b/Makefile index b1661332..4f3675e8 100644 --- a/Makefile +++ b/Makefile @@ -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 @@ -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) @@ -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) diff --git a/pyproject.toml b/pyproject.toml index 072ac5bf..d5ff48df 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -16,6 +16,7 @@ pytest-html = "*" dynaconf = "*" python-keycloak = ">=3.6" python-jose = "*" +lxml = "*" cryptography = "*" backoff = "*" httpx = { version = "*", extras = ["http2"] } diff --git a/scripts/junit2reportportal b/scripts/junit2reportportal new file mode 100755 index 00000000..c2dad327 --- /dev/null +++ b/scripts/junit2reportportal @@ -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 +) diff --git a/scripts/xslt-apply b/scripts/xslt-apply new file mode 100755 index 00000000..0d63713b --- /dev/null +++ b/scripts/xslt-apply @@ -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))) diff --git a/xslt/polish-junit.xsl b/xslt/polish-junit.xsl new file mode 100644 index 00000000..5dc28bca --- /dev/null +++ b/xslt/polish-junit.xsl @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + + + + + + + + + + + + + + +