Add support for checks plugin
Change-Id: Iabaf1c928571ff0191e1201f395050f278f19a75
This commit is contained in:
parent
5ff7d2061e
commit
b8dca06da7
43
gertty/alembic/versions/45d33eccc7a7_add_checks.py
Normal file
43
gertty/alembic/versions/45d33eccc7a7_add_checks.py
Normal file
@ -0,0 +1,43 @@
|
||||
"""add-checks
|
||||
|
||||
Revision ID: 45d33eccc7a7
|
||||
Revises: 6f6183367a8f
|
||||
Create Date: 2020-02-20 13:16:22.342039
|
||||
|
||||
"""
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '45d33eccc7a7'
|
||||
down_revision = '6f6183367a8f'
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
def upgrade():
|
||||
op.create_table('checker',
|
||||
sa.Column('key', sa.Integer(), nullable=False),
|
||||
sa.Column('uuid', sa.String(255), index=True, unique=True, nullable=False),
|
||||
sa.Column('name', sa.String(255), nullable=False),
|
||||
sa.Column('status', sa.String(255), nullable=False),
|
||||
sa.Column('blocking', sa.String(255)),
|
||||
sa.Column('description', sa.Text()),
|
||||
sa.PrimaryKeyConstraint('key')
|
||||
)
|
||||
op.create_table('check',
|
||||
sa.Column('key', sa.Integer(), nullable=False),
|
||||
sa.Column('revision_key', sa.Integer(), index=True),
|
||||
sa.Column('checker_key', sa.Integer(), index=True),
|
||||
sa.Column('state', sa.String(255), nullable=False),
|
||||
sa.Column('url', sa.Text()),
|
||||
sa.Column('message', sa.Text()),
|
||||
sa.Column('started', sa.DateTime()),
|
||||
sa.Column('finished', sa.DateTime()),
|
||||
sa.Column('created', sa.DateTime(), index=True, nullable=False),
|
||||
sa.Column('updated', sa.DateTime(), index=True, nullable=False),
|
||||
sa.PrimaryKeyConstraint('key')
|
||||
)
|
||||
|
||||
|
||||
def downgrade():
|
||||
pass
|
64
gertty/db.py
64
gertty/db.py
@ -200,6 +200,28 @@ server_table = Table(
|
||||
Column('key', Integer, primary_key=True),
|
||||
Column('own_account_key', Integer, ForeignKey("account.key"), index=True),
|
||||
)
|
||||
checker_table = Table(
|
||||
'checker', metadata,
|
||||
Column('key', Integer, primary_key=True),
|
||||
Column('uuid', String(255), index=True, unique=True, nullable=False),
|
||||
Column('name', String(255), nullable=False),
|
||||
Column('status', String(255), nullable=False),
|
||||
Column('blocking', String(255)),
|
||||
Column('description', Text),
|
||||
)
|
||||
check_table = Table(
|
||||
'check', metadata,
|
||||
Column('key', Integer, primary_key=True),
|
||||
Column('revision_key', Integer, ForeignKey("revision.key"), index=True),
|
||||
Column('checker_key', Integer, ForeignKey("checker.key"), index=True),
|
||||
Column('state', String(255), nullable=False),
|
||||
Column('url', Text),
|
||||
Column('message', Text),
|
||||
Column('started', DateTime),
|
||||
Column('finished', DateTime),
|
||||
Column('created', DateTime, index=True, nullable=False),
|
||||
Column('updated', DateTime, index=True, nullable=False),
|
||||
)
|
||||
|
||||
|
||||
class Account(object):
|
||||
@ -503,6 +525,15 @@ class Revision(object):
|
||||
self._file_cache[f.path] = f
|
||||
return f
|
||||
|
||||
def createCheck(self, *args, **kw):
|
||||
session = Session.object_session(self)
|
||||
args = [self] + list(args)
|
||||
c = Check(*args, **kw)
|
||||
self.checks.append(c)
|
||||
session.add(c)
|
||||
session.flush()
|
||||
return c
|
||||
|
||||
def getFile(self, path):
|
||||
if not hasattr(self, '_file_cache'):
|
||||
self._file_cache = {}
|
||||
@ -660,6 +691,19 @@ class Server(object):
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
class Checker(object):
|
||||
def __init__(self, uuid, name, status):
|
||||
self.uuid = uuid
|
||||
self.name = name
|
||||
self.status = status
|
||||
|
||||
class Check(object):
|
||||
def __init__(self, revision, checker, state, created, updated):
|
||||
self.revision_key = revision.key
|
||||
self.checker_key = checker.key
|
||||
self.state = state
|
||||
self.created = created
|
||||
self.updated = updated
|
||||
|
||||
mapper(Account, account_table)
|
||||
mapper(Project, project_table, properties=dict(
|
||||
@ -742,6 +786,9 @@ mapper(Revision, revision_table, properties=dict(
|
||||
cascade='all, delete-orphan'),
|
||||
pending_cherry_picks=relationship(PendingCherryPick, backref='revision',
|
||||
cascade='all, delete-orphan'),
|
||||
checks=relationship(Check, backref='revision',
|
||||
cascade='all, delete-orphan'),
|
||||
|
||||
))
|
||||
mapper(Message, message_table, properties=dict(
|
||||
author=relationship(Account)))
|
||||
@ -769,6 +816,10 @@ mapper(Hashtag, hashtag_table)
|
||||
mapper(Server, server_table, properties=dict(
|
||||
own_account=relationship(Account)
|
||||
))
|
||||
mapper(Checker, checker_table)
|
||||
mapper(Check, check_table, properties=dict(
|
||||
checker=relationship(Checker)))
|
||||
|
||||
|
||||
def match(expr, item):
|
||||
if item is None:
|
||||
@ -779,6 +830,7 @@ def match(expr, item):
|
||||
def add_sqlite_match(dbapi_connection, connection_record):
|
||||
dbapi_connection.create_function("matches", 2, match)
|
||||
|
||||
|
||||
class Database(object):
|
||||
def __init__(self, app, dburi, search):
|
||||
self.log = logging.getLogger('gertty.db')
|
||||
@ -1122,3 +1174,15 @@ class DatabaseSession(object):
|
||||
self.session().add(o)
|
||||
self.session().flush()
|
||||
return o
|
||||
|
||||
def createChecker(self, *args, **kw):
|
||||
o = Checker(*args, **kw)
|
||||
self.session().add(o)
|
||||
self.session().flush()
|
||||
return o
|
||||
|
||||
def getCheckerByUUID(self, uuid):
|
||||
try:
|
||||
return self.session().query(Checker).filter_by(uuid=uuid).one()
|
||||
except sqlalchemy.orm.exc.NoResultFound:
|
||||
return None
|
||||
|
@ -74,6 +74,12 @@ DEFAULT_PALETTE={
|
||||
'lines-removed': ['light red', ''],
|
||||
'reviewer-name': ['yellow', ''],
|
||||
'reviewer-own-name': ['light cyan', ''],
|
||||
'check-SUCCESSFUL': ['light green', ''],
|
||||
'check-FAILED': ['light red', ''],
|
||||
'check-NOT_STARTED': ['dark gray', ''],
|
||||
'check-SCHEDULED': ['dark magenta', '', ''],
|
||||
'check-RUNNING': ['dark magenta', ''],
|
||||
'check-NOT_RELEVANT': ['dark gray', ''],
|
||||
# project list
|
||||
'unreviewed-project': ['white', ''],
|
||||
'subscribed-project': ['default', ''],
|
||||
|
@ -567,6 +567,38 @@ class SyncChangeTask(Task):
|
||||
return True
|
||||
return False
|
||||
|
||||
def _updateChecks(self, session, change, revision, remote_checks_data):
|
||||
# Called from run inside of db transaction
|
||||
local_checks = {c.checker.uuid: c for c in revision.checks}
|
||||
for checks_data in remote_checks_data:
|
||||
uuid = checks_data['checker_uuid']
|
||||
name = checks_data['checker_name']
|
||||
status = checks_data['checker_status']
|
||||
checker = session.getCheckerByUUID(uuid)
|
||||
if checker is None:
|
||||
self.log.info("Creating checker %s", uuid)
|
||||
checker = session.createChecker(uuid, name, status)
|
||||
checker.name = name
|
||||
checker.status = status
|
||||
checker.blocking = ' '.join(checks_data['blocking'])
|
||||
check = local_checks.get(uuid)
|
||||
updated = dateutil.parser.parse(checks_data['updated'])
|
||||
started = dateutil.parser.parse(checks_data['started'])
|
||||
finished = dateutil.parser.parse(checks_data['finished'])
|
||||
state = checks_data['state']
|
||||
if check is None:
|
||||
created = dateutil.parser.parse(checks_data['created'])
|
||||
self.log.info("Creating check %s on revision %s", uuid, revision.key)
|
||||
check = revision.createCheck(checker,
|
||||
state,
|
||||
created, updated)
|
||||
check.updated = updated
|
||||
check.state = state
|
||||
check.url = checks_data.get('url')
|
||||
check.message = checks_data.get('message')
|
||||
check.started = started
|
||||
check.finished = finished
|
||||
|
||||
def run(self, sync):
|
||||
start_time = time.time()
|
||||
try:
|
||||
@ -596,6 +628,13 @@ class SyncChangeTask(Task):
|
||||
remote_robot_comments_data = sync.get('changes/%s/revisions/%s/robotcomments' % (
|
||||
self.change_id, remote_commit))
|
||||
remote_revision['_gertty_remote_robot_comments_data'] = remote_robot_comments_data
|
||||
|
||||
if sync.checks_plugin:
|
||||
remote_checks_data = sync.get('changes/%s/revisions/%s/checks' % (self.change_id, remote_commit))
|
||||
if remote_checks_data is None:
|
||||
sync.checks_plugin = False
|
||||
else:
|
||||
remote_revision['_gertty_remote_checks_data'] = remote_checks_data
|
||||
try:
|
||||
remote_conflicts = sync.query(['q=status:open+is:mergeable+conflicts:%s' %
|
||||
remote_change['_number']])
|
||||
@ -775,6 +814,9 @@ class SyncChangeTask(Task):
|
||||
else:
|
||||
if comment.author != account:
|
||||
comment.author = account
|
||||
if remote_revision.get('_gertty_remote_checks_data'):
|
||||
self._updateChecks(session, change, revision, remote_revision['_gertty_remote_checks_data'])
|
||||
# End revisions
|
||||
new_message = False
|
||||
for remote_message in remote_change.get('messages', []):
|
||||
if 'author' in remote_message:
|
||||
@ -927,6 +969,7 @@ class SyncChangeTask(Task):
|
||||
|
||||
remote_hashtags = remote_change.get('hashtags', [])
|
||||
change.setHashtags(remote_hashtags)
|
||||
|
||||
change.outdated = False
|
||||
for url, refs in fetches.items():
|
||||
self.log.debug("Fetching from %s with refs %s", url, refs)
|
||||
@ -1423,6 +1466,7 @@ class Sync(object):
|
||||
self.version = (0, 0, 0)
|
||||
self.offline = False
|
||||
self.account_id = None
|
||||
self.checks_plugin = True
|
||||
self.app = app
|
||||
self.log = logging.getLogger('gertty.sync')
|
||||
self.queue = MultiQueue([HIGH_PRIORITY, NORMAL_PRIORITY, LOW_PRIORITY])
|
||||
|
@ -854,13 +854,27 @@ class ChangeView(urwid.WidgetWrap):
|
||||
self.listbox.body.remove(row)
|
||||
del self.message_rows[key]
|
||||
listbox_index -= 1
|
||||
self._updateTestResults(result_systems)
|
||||
self._updateTestResults(change, result_systems)
|
||||
|
||||
def _updateTestResults(self, result_systems):
|
||||
def _updateTestResults(self, change, result_systems):
|
||||
text = []
|
||||
for system, results in result_systems.items():
|
||||
for job, result in results.items():
|
||||
text.append(result)
|
||||
|
||||
# Add check results
|
||||
revision = change.revisions[-1]
|
||||
for check in revision.checks:
|
||||
# link checker name/url, color result, in time
|
||||
link = mywid.Link('{:<42}'.format(check.checker.name), 'link', 'focused-link')
|
||||
urwid.connect_signal(link, 'selected', lambda link:self.app.openURL(check.url))
|
||||
color = 'check-%s' % check.state
|
||||
result = (color, check.state)
|
||||
line = [link, result]
|
||||
if check.finished and check.started:
|
||||
line.append(' in %s' % (check.finished-check.started))
|
||||
text.append(line)
|
||||
|
||||
if text:
|
||||
self.results.set_text(text)
|
||||
else:
|
||||
|
Loading…
Reference in New Issue
Block a user