Add comment

This commit is contained in:
Stephan Kulow 2017-07-19 14:18:29 +02:00
parent 429ff42489
commit c17a336856

View File

@ -61,7 +61,7 @@ QA_INPROGRESS = 1
QA_FAILED = 2 QA_FAILED = 2
QA_PASSED = 3 QA_PASSED = 3
comment_marker_re = re.compile(r'<!-- openqa state=(?P<state>done|seen)(?: result=(?P<result>accepted|declined))? -->') comment_marker_re = re.compile(r'<!-- openqa state=(?P<state>done|seen)(?: result=(?P<result>accepted|declined))?(?: maxreporevision=(?P<revision>\d+))? -->')
logger = None logger = None
@ -685,13 +685,14 @@ class OpenQABot(ReviewBot.ReviewBot):
comment = "<!-- openqa state=%s%s -->\n" % (state, ' result=%s' % result if result else '') comment = "<!-- openqa state=%s%s -->\n" % (state, ' result=%s' % result if result else '')
comment += "\n" + msg comment += "\n" + msg
(comment_id, comment_state, comment_result, comment_text) = self.find_obs_request_comment(req, state) info = self.find_obs_request_comment(state=state, request_id=req.reqid)
comment_id = info.get('id', None)
if comment_id is not None and state == comment_state: if state == info.get('state', 'missing'):
lines_before = len(comment_text.split('\n')) lines_before = len(info['comment'].split('\n'))
lines_after = len(comment.split('\n')) lines_after = len(comment.split('\n'))
if lines_before == lines_after: if lines_before == lines_after:
self.logger.debug("not worth the update, previous comment %s is state %s", comment_id, comment_state) self.logger.debug("not worth the update, previous comment %s is state %s", comment_id, info['state'])
return return
self.logger.debug("adding comment to %s, state %s result %s", req.reqid, state, result) self.logger.debug("adding comment to %s, state %s result %s", req.reqid, state, result)
@ -718,7 +719,10 @@ class OpenQABot(ReviewBot.ReviewBot):
def summarize_one_openqa_job(self, job): def summarize_one_openqa_job(self, job):
testurl = osc.core.makeurl(self.openqa.baseurl, ['tests', str(job['id'])]) testurl = osc.core.makeurl(self.openqa.baseurl, ['tests', str(job['id'])])
if not job['result'] in ['passed', 'failed', 'softfailed']: if not job['result'] in ['passed', 'failed', 'softfailed']:
return '\n- [%s](%s) is %s' % (self.job_test_name(job), testurl, job['result']) rstring = job['result']
if rstring == 'none':
rstring = job['state']
return '\n- [%s](%s) is %s' % (self.job_test_name(job), testurl, rstring)
modstrings = [] modstrings = []
for module in job['modules']: for module in job['modules']:
@ -732,43 +736,7 @@ class OpenQABot(ReviewBot.ReviewBot):
return '\n- [%s](%s) failed' % (self.job_test_name(job), testurl) return '\n- [%s](%s) failed' % (self.job_test_name(job), testurl)
return '' return ''
def check_one_request(self, req): def summarize_openqa_jobs(self, jobs):
ret = None
try:
jobs = self.request_get_openqa_jobs(req)
qa_state = self.calculate_qa_status(jobs)
self.logger.debug("request %s state %s", req.reqid, qa_state)
msg = None
if self.force or qa_state == QA_UNKNOWN:
ret = ReviewBot.ReviewBot.check_one_request(self, req)
jobs = self.request_get_openqa_jobs(req)
if self.force:
# make sure to delete previous comments if we're forcing
(comment_id, comment_state, comment_result, comment_text) = self.find_obs_request_comment(req)
if comment_id is not None:
self.logger.debug("deleting old comment %s", comment_id)
if not self.dryrun:
self.commentapi.delete(comment_id)
if not jobs:
msg = "no openQA tests defined"
self.add_comment(req, msg, 'done', 'accepted')
ret = True
else:
# no notification until the result is done
osc.core.change_review_state(self.apiurl, req.reqid, newstate='new',
by_group=self.review_group, by_user=self.review_user,
message='now testing in openQA')
elif qa_state == QA_FAILED or qa_state == QA_PASSED:
# don't take test repo results into the calculation of total
# this is for humans to decide which incident broke the test repo
jobs += self.request_get_openqa_jobs(req, incident=False, test_repo=True)
if self.calculate_qa_status(jobs) == QA_INPROGRESS:
self.logger.debug(
"incident tests for request %s are done, but need to wait for test repo", req.reqid)
return
groups = dict() groups = dict()
for job in jobs: for job in jobs:
gl = "%s@%s" % (self.emd(job['group']), self.emd(job['settings']['FLAVOR'])) gl = "%s@%s" % (self.emd(job['group']), self.emd(job['settings']['FLAVOR']))
@ -792,23 +760,62 @@ class OpenQABot(ReviewBot.ReviewBot):
gmsg = groups[gl] gmsg = groups[gl]
groups[gl]['failed'].append(job_summary) groups[gl]['failed'].append(job_summary)
if qa_state == QA_PASSED: msg = ''
self.logger.debug("request %s passed", req.reqid)
msg = "openQA tests passed\n"
state = 'accepted'
ret = True
else:
self.logger.debug("request %s failed", req.reqid)
msg = "openQA tests problematic\n"
state = 'declined'
ret = False
for group in sorted(groups.keys()): for group in sorted(groups.keys()):
msg += "\n\n" + groups[group]['title'] msg += "\n\n" + groups[group]['title']
msg += "(%d tests passed, %d failed)\n" % (groups[group]['passed'], len(groups[group]['failed'])) msg += "(%d tests passed, %d failed)\n" % (groups[group]['passed'], len(groups[group]['failed']))
for fail in groups[group]['failed']: for fail in groups[group]['failed']:
msg += fail msg += fail
return msg
def check_one_request(self, req):
ret = None
try:
jobs = self.request_get_openqa_jobs(req)
qa_state = self.calculate_qa_status(jobs)
self.logger.debug("request %s state %s", req.reqid, qa_state)
msg = None
if self.force or qa_state == QA_UNKNOWN:
ret = ReviewBot.ReviewBot.check_one_request(self, req)
jobs = self.request_get_openqa_jobs(req)
if self.force:
# make sure to delete previous comments if we're forcing
info = self.find_obs_request_comment(request_id=req.reqid)
if 'id' in info:
self.logger.debug("deleting old comment %s", info['id'])
if not self.dryrun:
self.commentapi.delete(info['id'])
if not jobs:
msg = "no openQA tests defined"
self.add_comment(req, msg, 'done', 'accepted')
ret = True
else:
# no notification until the result is done
osc.core.change_review_state(self.apiurl, req.reqid, newstate='new',
by_group=self.review_group, by_user=self.review_user,
message='now testing in openQA')
elif qa_state == QA_FAILED or qa_state == QA_PASSED:
# don't take test repo results into the calculation of total
# this is for humans to decide which incident broke the test repo
jobs += self.request_get_openqa_jobs(req, incident=False, test_repo=True)
if self.calculate_qa_status(jobs) == QA_INPROGRESS:
self.logger.debug(
"incident tests for request %s are done, but need to wait for test repo", req.reqid)
return
if qa_state == QA_PASSED:
msg = "openQA tests passed\n"
state = 'accepted'
ret = True
else:
msg = "openQA tests problematic\n"
state = 'declined'
ret = False
msg += self.summarize_openqa_jobs(jobs)
self.add_comment(req, msg, 'done', state) self.add_comment(req, msg, 'done', state)
elif qa_state == QA_INPROGRESS: elif qa_state == QA_INPROGRESS:
self.logger.debug("request %s still in progress", req.reqid) self.logger.debug("request %s still in progress", req.reqid)
@ -823,15 +830,15 @@ class OpenQABot(ReviewBot.ReviewBot):
return ret return ret
def find_obs_request_comment(self, req, state=None): def find_obs_request_comment(self, request_id=None, project_name=None, state=None):
"""Return previous comments (should be one).""" """Return previous comments (should be one)."""
if self.do_comments: if self.do_comments:
comments = self.commentapi.get_comments(request_id=req.reqid) comments = self.commentapi.get_comments(request_id=request_id, project_name=project_name)
for c in comments.values(): for c in comments.values():
m = comment_marker_re.match(c['comment']) m = comment_marker_re.match(c['comment'])
if m and (state is None or state == m.group('state')): if m and (state is None or state == m.group('state')):
return c['id'], m.group('state'), m.group('result'), c['comment'] return { 'id' : c['id'], 'state': m.group('state'), 'result': m.group('result'), 'comment': c['comment'], 'revision': m.group('revision') }
return None, None, None, None return {}
def check_product(self, job, product_prefix): def check_product(self, job, product_prefix):
pmap = API_MAP[product_prefix] pmap = API_MAP[product_prefix]
@ -861,14 +868,17 @@ class OpenQABot(ReviewBot.ReviewBot):
def test(self): def test(self):
for inc in requests.get('https://maintenance.suse.de/api/incident/active/').json(): for inc in requests.get('https://maintenance.suse.de/api/incident/active/').json():
if not inc == '2129': continue if not inc == '4871': continue
job = requests.get('https://maintenance.suse.de/api/incident/' + inc).json() job = requests.get('https://maintenance.suse.de/api/incident/' + inc).json()
print json.dumps(job, indent=4)
if job['meta']['state'] in ['final', 'gone']: if job['meta']['state'] in ['final', 'gone']:
continue continue
openqa_posts = [] openqa_posts = []
for prod in API_MAP.keys(): for prod in API_MAP.keys():
s = self.check_product(job['base'], prod) s = self.check_product(job['base'], prod)
openqa_posts += s openqa_posts += s
openqa_jobs = []
openqa_done = True
for s in openqa_posts: for s in openqa_posts:
jobs = self.openqa.openqa_request( jobs = self.openqa.openqa_request(
'GET', 'jobs', 'GET', 'jobs',
@ -879,14 +889,33 @@ class OpenQABot(ReviewBot.ReviewBot):
'flavor': s['FLAVOR'], 'flavor': s['FLAVOR'],
'build': s['BUILD'], 'build': s['BUILD'],
'scope': 'relevant', 'scope': 'relevant',
'latest': '1'
})['jobs'] })['jobs']
if not len(jobs): if not len(jobs):
if self.dryrun: if self.dryrun:
print 'WOULD POST', s print 'WOULD POST', s
else: else:
ret = self.openqa.openqa_request('POST', 'isos', data=s, retries=1) ret = self.openqa.openqa_request('POST', 'isos', data=s, retries=1)
openqa_done = False
else: else:
print jobs print s, 'got', len(jobs)
openqa_jobs += jobs
#print openqa_jobs
msg = self.summarize_openqa_jobs(openqa_jobs)
state = 'running'
comment = "<!-- openqa state=%s maxreporevision=%s -->\n" % (state, job.get('openqa_build'))
comment += "\n" + msg
info = self.find_obs_request_comment(state=state, project_name=str(job['base']['project']))
comment_id = info.get('id', None)
self.logger.debug("adding comment to %s, state %s", job['base']['project'], state)
self.logger.debug("message: %s", msg)
if not self.dryrun:
if comment_id is not None:
self.commentapi.delete(comment_id)
self.commentapi.add_comment(project_name=str(job['base']['project']), comment=str(comment))
class CommandLineInterface(ReviewBot.CommandLineInterface): class CommandLineInterface(ReviewBot.CommandLineInterface):