140 lines
4.6 KiB
Python
140 lines
4.6 KiB
Python
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
|
|
|
# Copyright 2014, Craig Tracey <craigtracey@gmail.com>
|
|
# All Rights Reserved.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
|
|
import re
|
|
|
|
import requests
|
|
|
|
from pygerrit.rest import GerritRestAPI
|
|
|
|
DEFAULT_GERRIT_URL = 'https://review.openstack.org'
|
|
|
|
|
|
class GerritReview(object):
|
|
|
|
def __init__(self, changeid, project, gerrit_url=DEFAULT_GERRIT_URL):
|
|
self.changeid = changeid
|
|
self.project = project
|
|
self._gerrit_url = gerrit_url
|
|
self._restclient = None
|
|
|
|
def build_pip_dependencies(self, py26=False, py27=True, string=False):
|
|
url = self._get_gate_build_log_url(py26, py27)
|
|
response = requests.get(url)
|
|
|
|
if response.status_code != 200:
|
|
raise Exception("Unable to get console log at %s. Error: %d" %
|
|
(url, response.status_code))
|
|
|
|
log = response.text.encode('utf-8')
|
|
|
|
freeze_found = False
|
|
dependencies = []
|
|
for line in log.split('\n'):
|
|
line = re.sub('.*\|\s*', '', line)
|
|
if not freeze_found:
|
|
if line.endswith("pip freeze") or line.endswith("pbr freeze"):
|
|
freeze_found = True
|
|
continue
|
|
elif re.match('[\w\-]+==.+', line) and not line.startswith('-e'):
|
|
dependencies.append(line)
|
|
|
|
short_name = self.project.split('/')[1]
|
|
dependencies = filter(lambda x: not x.startswith(short_name + "=="),
|
|
dependencies)
|
|
|
|
if string:
|
|
return (' ').join(dependencies)
|
|
return dependencies
|
|
|
|
def _get_rest_client(self):
|
|
if not self._restclient:
|
|
self._restclient = GerritRestAPI(url=self._gerrit_url)
|
|
return self._restclient
|
|
|
|
def _get_review_detail(self):
|
|
""" get review details for a given change ID """
|
|
restclient = self._get_rest_client()
|
|
url = "/changes/?q=%s" % self.changeid
|
|
changes = restclient.get(url)
|
|
|
|
change = None
|
|
for c in changes:
|
|
if c['project'] == self.project:
|
|
change = c
|
|
break
|
|
|
|
if not change:
|
|
raise Exception("could not find change with ID: %s" %
|
|
self.changeid)
|
|
|
|
detail = restclient.get("/changes/%s/detail" % change['id'])
|
|
return detail
|
|
|
|
def _get_reveiew_messages(self):
|
|
details = self._get_review_detail()
|
|
return details['messages']
|
|
|
|
def _get_gate_build_log_url(self, py26, py27):
|
|
messages = self._get_reveiew_messages()
|
|
messages.reverse()
|
|
|
|
mergemsg = None
|
|
for message in messages:
|
|
msgtext = message['message']
|
|
if re.search('Patch Set \d+: Verified', msgtext):
|
|
mergemsg = msgtext
|
|
break
|
|
|
|
gate_info = self._parse_merge_message(mergemsg)
|
|
url = None
|
|
for gate in gate_info:
|
|
if py26 and re.match('gate\-.+\-python26', gate['name']):
|
|
url = gate['url']
|
|
if py27 and re.match('gate\-.+\-python27', gate['name']):
|
|
url = gate['url']
|
|
|
|
# check if it is console.html or console.html.gz
|
|
resp = requests.get(url)
|
|
if resp.status_code != 200:
|
|
raise Exception("Unable to find the build's console log for %s" %
|
|
url)
|
|
|
|
build_log = None
|
|
if 'console.html.gz' in resp.text:
|
|
build_log = 'console.html.gz'
|
|
elif 'console.html' in resp.text:
|
|
build_log = 'console.html'
|
|
else:
|
|
raise Exception("Didn't find a build log. Does one exist?")
|
|
|
|
if url:
|
|
return "%s/%s" % (url, build_log)
|
|
return url
|
|
|
|
def _parse_merge_message(self, msg):
|
|
""" a function that parses a successful gate gerrit message """
|
|
gate_info = []
|
|
for line in msg.split('\n'):
|
|
parts = re.split('\s+', line)
|
|
if parts[0] == '-':
|
|
gate = {}
|
|
gate['name'] = parts[1]
|
|
gate['url'] = parts[2]
|
|
gate['result'] = parts[4]
|
|
gate_info.append(gate)
|
|
return gate_info
|