Skip to content
Closed
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
25 changes: 1 addition & 24 deletions openqabot/approver.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
from urllib.error import HTTPError
from datetime import timedelta, datetime
import re
import string

import osc.conf
import osc.core
Expand Down Expand Up @@ -59,14 +58,6 @@ def _handle_http_error(e: HTTPError, inc: IncReq) -> bool:
return False


def sanitize_comment_text(
text,
):
text = "".join(x for x in text if x in string.printable)
text = text.replace("\r", " ").replace("\n", " ")
return text.strip()


class Approver:
def __init__(self, args: Namespace, single_incident=None) -> None:
self.dry = args.dry
Expand Down Expand Up @@ -134,20 +125,6 @@ def _approvable(self, inc: IncReq) -> bool:
# everything is green --> add incident to approve list
return True

@lru_cache(maxsize=512)
def is_job_marked_acceptable_for_incident(self, job_id: int, inc: int) -> bool:
regex = re.compile(
r"@review:acceptable_for:incident_%s:(.+?)(?:$|\s)" % inc, re.DOTALL
)
try:
for comment in self.client.get_job_comments(job_id):
sanitized_text = sanitize_comment_text(comment["text"])
if regex.search(sanitized_text):
return True
except RequestError:
pass
return False

@lru_cache(maxsize=512)
def validate_job_qam(self, job: int) -> bool:
# Check that valid test result is still present in the dashboard (see https://github.com/openSUSE/qem-dashboard/pull/78/files) to avoid using results related to an old release request
Expand Down Expand Up @@ -268,7 +245,7 @@ def job_acceptable(self, inc: int, api: str, res) -> bool:
if res["status"] == "passed":
return True
url = "{}/t{}".format(self.client.url.geturl(), res["job_id"])
if self.is_job_marked_acceptable_for_incident(res["job_id"], inc):
if self.client.is_job_marked_acceptable_for_incident(res["job_id"], inc):
log.info(
"Ignoring failed job %s for incident %s due to openQA comment", url, inc
)
Expand Down
5 changes: 5 additions & 0 deletions openqabot/incsyncres.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ def __call__(self) -> int:
except KeyError:
continue

if r["status"] != "passed":
r["acceptable_for_incidents"] = ",".join(
self.client.incidents_job_is_acceptable_for(r["job_id"])
)

results.append(r)

for r in results:
Expand Down
39 changes: 39 additions & 0 deletions openqabot/openqa.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
from pprint import pformat
from urllib.parse import ParseResult
from typing import Dict
import re
import string

from openqa_client.client import OpenQA_Client
from openqa_client.exceptions import RequestError
Expand All @@ -17,6 +19,14 @@
log = logging.getLogger("bot.openqa")


def sanitize_comment_text(
text,
):
text = "".join(x for x in text if x in string.printable)
text = text.replace("\r", " ").replace("\n", " ")
return text.strip()


class openQAInterface:
def __init__(self, args) -> None:
self.url: ParseResult = args.openqa_instance
Expand Down Expand Up @@ -91,6 +101,35 @@ def get_job_comments(self, job_id: int):
log.exception(e)
return ret

@lru_cache(maxsize=512)
def incidents_job_is_acceptable_for(self, job_id: int) -> list[int]:
regex = re.compile(
r"@review:acceptable_for:incident_(\d+):(.+?)(?:$|\s)", re.DOTALL
)
ret = []
try:
for comment in self.get_job_comments(job_id):
sanitized_text = sanitize_comment_text(comment["text"])
for match in regex.findall(sanitized_text):
ret.append(int(match[0]))
except RequestError:
pass
return ret

@lru_cache(maxsize=512)
def is_job_marked_acceptable_for_incident(self, job_id: int, inc: int) -> bool:
regex = re.compile(
r"@review:acceptable_for:incident_%s:(.+?)(?:$|\s)" % inc, re.DOTALL
)
try:
for comment in self.get_job_comments(job_id):
sanitized_text = sanitize_comment_text(comment["text"])
if regex.search(sanitized_text):
return True
except RequestError:
pass
return False

@lru_cache(maxsize=256)
def is_devel_group(self, groupid: int) -> bool:
ret = None
Expand Down
23 changes: 23 additions & 0 deletions tests/test_openqaclient.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,18 @@ def fake_responses_failing_job_update():
)


@pytest.fixture(scope="function")
def fake_responses_for_acceptable_incidents():
responses.add(
responses.GET,
url="https://openqa.suse.de/api/v1/jobs/100003/comments",
json=[
{"text": "@review:acceptable_for:incident_1234:foo"},
{"text": "@review:acceptable_for:incident_5678:bar"},
],
)


def test_bool():
false_address = urlparse("http://fake.openqa.site")
true_address = urlparse("https://openqa.suse.de")
Expand Down Expand Up @@ -93,3 +105,14 @@ def test_handle_job_not_found(caplog, fake_responses_failing_job_update):
assert len(responses.calls) == 1
assert "Job 42 not found in openQA, marking as obsolete on dashboard" in messages
assert "job not found" in messages # the 404 fixture is supposed to match


@responses.activate
def test_incidents_job_is_acceptable_for(
caplog, fake_responses_for_acceptable_incidents
):
client = oQAI(_args(urlparse("https://openqa.suse.de"), ""))
messages = [x[-1] for x in caplog.record_tuples]
res = client.incidents_job_is_acceptable_for(100003)
assert len(messages) == 0
assert res == [1234, 5678]
Loading