Skip to content

Commit

Permalink
Merge pull request #1409 from djmitche/hidden-steps
Browse files Browse the repository at this point in the history
Add support for hidden steps
  • Loading branch information
Mikhail Sobolev committed Dec 4, 2014
2 parents 654a685 + 37331aa commit a05f71e
Show file tree
Hide file tree
Showing 14 changed files with 162 additions and 27 deletions.
6 changes: 4 additions & 2 deletions master/buildbot/data/steps.py
Expand Up @@ -32,6 +32,7 @@ def db2data(self, dbdict):
'state_string': dbdict['state_string'],
'results': dbdict['results'],
'urls': dbdict['urls'],
'hidden': dbdict['hidden'],
}
return defer.succeed(data)

Expand Down Expand Up @@ -123,6 +124,7 @@ class EntityType(types.Entity):
name=types.String(),
url=types.String()
))
hidden = types.Boolean()
entityType = EntityType(name)

@defer.inlineCallbacks
Expand Down Expand Up @@ -160,7 +162,7 @@ def addStepURL(self, stepid, name, url):

@base.updateMethod
@defer.inlineCallbacks
def finishStep(self, stepid, results):
def finishStep(self, stepid, results, hidden):
yield self.master.db.steps.finishStep(
stepid=stepid, results=results)
stepid=stepid, results=results, hidden=hidden)
yield self.generateEvent(stepid, 'finished')
24 changes: 24 additions & 0 deletions master/buildbot/db/migrate/versions/044_add_step_hidden.py
@@ -0,0 +1,24 @@
# This file is part of Buildbot. Buildbot is free software: you can
# redistribute it and/or modify it under the terms of the GNU General Public
# License as published by the Free Software Foundation, version 2.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc., 51
# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Copyright Buildbot Team Members

import sqlalchemy as sa


def upgrade(migrate_engine):
metadata = sa.MetaData()
metadata.bind = migrate_engine
steps_table = sa.Table('steps', metadata, autoload=True)
hidden = sa.Column('hidden', sa.SmallInteger, nullable=False, server_default='0')
hidden.create(steps_table)
1 change: 1 addition & 0 deletions master/buildbot/db/model.py
Expand Up @@ -144,6 +144,7 @@ class Model(base.DBConnectorComponent):
sa.Column('state_string', sa.Text, nullable=False, server_default=''),
sa.Column('results', sa.Integer),
sa.Column('urls_json', sa.Text, nullable=False),
sa.Column('hidden', sa.SmallInteger, nullable=False, server_default='0'),
)

# logs
Expand Down
8 changes: 5 additions & 3 deletions master/buildbot/db/steps.py
Expand Up @@ -153,13 +153,14 @@ def thd(conn):

return self.url_lock.run(lambda: self.db.pool.do(thd))

def finishStep(self, stepid, results, _reactor=reactor):
def finishStep(self, stepid, results, hidden, _reactor=reactor):
def thd(conn):
tbl = self.db.model.steps
q = tbl.update(whereclause=(tbl.c.id == stepid))
conn.execute(q,
complete_at=_reactor.seconds(),
results=results)
results=results,
hidden=1 if hidden else 0)
return self.db.pool.do(thd)

def _stepdictFromRow(self, row):
Expand All @@ -176,4 +177,5 @@ def mkdt(epoch):
complete_at=mkdt(row.complete_at),
state_string=row.state_string,
results=row.results,
urls=json.loads(row.urls_json))
urls=json.loads(row.urls_json),
hidden=bool(row.hidden))
7 changes: 4 additions & 3 deletions master/buildbot/process/buildstep.py
Expand Up @@ -499,8 +499,7 @@ def setRenderable(res, attr):
self.realUpdateSummary()
yield self.realUpdateSummary.stop()

yield self.master.data.updates.finishStep(self.stepid, self.results)

# determine whether we should hide this step
hidden = self.hideStepIf
if callable(hidden):
try:
Expand All @@ -511,7 +510,9 @@ def setRenderable(res, attr):
yield self.addLogWithFailure(why)
self.results = EXCEPTION
hidden = False
# TODO: hidden

yield self.master.data.updates.finishStep(self.stepid, self.results,
hidden)

self.releaseLocks()

Expand Down
4 changes: 3 additions & 1 deletion master/buildbot/test/fake/fakedata.py
Expand Up @@ -321,11 +321,13 @@ def setStepStateString(self, stepid, state_string):
self.stepStateString[stepid] = state_string
return defer.succeed(None)

def finishStep(self, stepid, results):
def finishStep(self, stepid, results, hidden):
validation.verifyType(self.testcase, 'stepid', stepid,
validation.IntValidator())
validation.verifyType(self.testcase, 'results', results,
validation.IntValidator())
validation.verifyType(self.testcase, 'hidden', hidden,
validation.BooleanValidator())
return defer.succeed(None)

def newLog(self, stepid, name, type):
Expand Down
12 changes: 8 additions & 4 deletions master/buildbot/test/fake/fakedb.py
Expand Up @@ -488,7 +488,8 @@ class Step(Row):
complete_at=None,
state_string='',
results=None,
urls_json='[]')
urls_json='[]',
hidden=False)

id_column = 'id'
foreignKeys = ('buildid',)
Expand Down Expand Up @@ -1852,7 +1853,8 @@ def _row2dict(self, row):
complete_at=_mkdt(row['complete_at']),
state_string=row['state_string'],
results=row['results'],
urls=json.loads(row['urls_json']))
urls=json.loads(row['urls_json']),
hidden=bool(row['hidden']))

def getStep(self, stepid=None, buildid=None, number=None, name=None):
if stepid is not None:
Expand Down Expand Up @@ -1913,7 +1915,8 @@ def addStep(self, buildid, name, state_string, _reactor=reactor):
'complete_at': None,
'results': None,
'state_string': state_string,
'urls_json': '[]'}
'urls_json': '[]',
'hidden': False}

return defer.succeed((id, number, name))

Expand Down Expand Up @@ -1945,12 +1948,13 @@ def addURL(self, stepid, name, url, _racehook=None):
b['urls_json'] = json.dumps(urls)
return defer.succeed(None)

def finishStep(self, stepid, results, _reactor=reactor):
def finishStep(self, stepid, results, hidden, _reactor=reactor):
now = _reactor.seconds()
b = self.steps.get(stepid)
if b:
b['complete_at'] = now
b['results'] = results
b['hidden'] = True if hidden else False
return defer.succeed(None)


Expand Down
19 changes: 15 additions & 4 deletions master/buildbot/test/unit/test_data_steps.py
Expand Up @@ -49,7 +49,7 @@ def setUp(self):
started_at=TIME2, complete_at=TIME3, results=2,
urls_json='[{"name":"url","url":"http://url"}]'),
fakedb.Step(id=72, number=2, name='three', buildid=30,
started_at=TIME3),
started_at=TIME3, hidden=True),
])

def tearDown(self):
Expand All @@ -69,7 +69,8 @@ def test_get_existing(self):
'started_at': epoch2datetime(TIME3),
'state_string': u'',
'stepid': 72,
'urls': []})
'urls': [],
'hidden': True})

@defer.inlineCallbacks
def test_get_existing_buildid_name(self):
Expand Down Expand Up @@ -174,6 +175,7 @@ def test_newStep(self):
'state_string': u'pending',
'stepid': stepid,
'urls': [],
'hidden': False,
}
self.master.mq.assertProductions([
(('builds', '10', 'steps', str(stepid), 'new'), msgBody),
Expand All @@ -190,6 +192,7 @@ def test_newStep(self):
'started_at': None,
'state_string': u'pending',
'urls': [],
'hidden': False,
})

@defer.inlineCallbacks
Expand Down Expand Up @@ -224,6 +227,7 @@ def test_startStep(self):
'state_string': u'pending',
'stepid': 100,
'urls': [],
'hidden': False,
}
self.master.mq.assertProductions([
(('builds', '10', 'steps', str(100), 'started'), msgBody),
Expand All @@ -240,6 +244,7 @@ def test_startStep(self):
'started_at': epoch2datetime(TIME1),
'state_string': u'pending',
'urls': [],
'hidden': False,
})

def test_signature_setStepStateString(self):
Expand All @@ -266,6 +271,7 @@ def test_setStepStateString(self):
'state_string': u'hi',
'stepid': 100,
'urls': [],
'hidden': False,
}
self.master.mq.assertProductions([
(('builds', '10', 'steps', str(100), 'updated'), msgBody),
Expand All @@ -282,13 +288,14 @@ def test_setStepStateString(self):
'started_at': None,
'state_string': u'hi',
'urls': [],
'hidden': False,
})

def test_signature_finishStep(self):
@self.assertArgSpecMatches(
self.master.data.updates.finishStep, # fake
self.rtype.finishStep) # real
def finishStep(self, stepid, results):
def finishStep(self, stepid, results, hidden):
pass

@defer.inlineCallbacks
Expand All @@ -299,7 +306,7 @@ def test_finishStep(self):
yield self.rtype.startStep(stepid=100)
self.patch(reactor, 'seconds', lambda: TIME2)
self.master.mq.clearProductions()
yield self.rtype.finishStep(stepid=100, results=9)
yield self.rtype.finishStep(stepid=100, results=9, hidden=False)

msgBody = {
'buildid': 10,
Expand All @@ -312,6 +319,7 @@ def test_finishStep(self):
'state_string': u'pending',
'stepid': 100,
'urls': [],
'hidden': False,
}
self.master.mq.assertProductions([
(('builds', '10', 'steps', str(100), 'finished'), msgBody),
Expand All @@ -328,6 +336,7 @@ def test_finishStep(self):
'started_at': epoch2datetime(TIME1),
'state_string': u'pending',
'urls': [],
'hidden': False,
})

def test_signature_addStepURL(self):
Expand All @@ -354,6 +363,7 @@ def test_addStepURL(self):
'state_string': u'pending',
'stepid': 100,
'urls': [{u'name': u'foo', u'url': u'bar'}],
'hidden': False,
}
self.master.mq.assertProductions([
(('builds', '10', 'steps', str(100), 'updated'), msgBody),
Expand All @@ -370,4 +380,5 @@ def test_addStepURL(self):
'started_at': None,
'state_string': u'pending',
'urls': [{u'name': u'foo', u'url': u'bar'}],
'hidden': False,
})
@@ -0,0 +1,68 @@
# This file is part of Buildbot. Buildbot is free software: you can
# redistribute it and/or modify it under the terms of the GNU General Public
# License as published by the Free Software Foundation, version 2.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc., 51
# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Copyright Buildbot Team Members

import sqlalchemy as sa

from buildbot.test.util import migration
from twisted.trial import unittest


class Migration(migration.MigrateTestMixin, unittest.TestCase):

def setUp(self):
return self.setUpMigrateTest()

def tearDown(self):
return self.tearDownMigrateTest()

def create_tables_thd(self, conn):
metadata = sa.MetaData()
metadata.bind = conn

steps = sa.Table('steps', metadata,
sa.Column('id', sa.Integer, primary_key=True),
sa.Column('number', sa.Integer, nullable=False),
sa.Column('name', sa.String(50), nullable=False),
sa.Column('buildid', sa.Integer),
sa.Column('started_at', sa.Integer),
sa.Column('complete_at', sa.Integer),
sa.Column('state_string', sa.Text, nullable=False, server_default=''),
sa.Column('results', sa.Integer),
sa.Column('urls_json', sa.Text, nullable=False))
steps.create()

conn.execute(steps.insert(), [
dict(number=3, name='echo', urls_json='[]')])

def test_update(self):
def setup_thd(conn):
self.create_tables_thd(conn)

def verify_thd(conn):
metadata = sa.MetaData()
metadata.bind = conn

steps = sa.Table('steps', metadata, autoload=True)
self.assertIsInstance(steps.c.hidden.type, sa.SmallInteger)

q = sa.select([steps.c.name, steps.c.hidden])
num_rows = 0
for row in conn.execute(q):
# verify that the default value was set correctly
self.assertEqual(row.hidden, 0)
num_rows += 1
self.assertEqual(num_rows, 1)

return self.do_test_migration(43, 44, setup_thd, verify_thd)

0 comments on commit a05f71e

Please sign in to comment.