Skip to content

Commit

Permalink
Add autopush and stable_days to an update.
Browse files Browse the repository at this point in the history
This commit adds an autopush boolean and stable_days integer
to an update. When this boolean is true the approve_testing
cronjob will push the update to stable if it has meet the
testing requirements (stable_days).

stable_days cannot be smaller than the release
mandatory_days_in_testing.

Signed-off-by: Clement Verna <cverna@tutanota.com>
  • Loading branch information
cverna committed Apr 24, 2019
1 parent 0561675 commit 155988e
Show file tree
Hide file tree
Showing 12 changed files with 442 additions and 40 deletions.
3 changes: 3 additions & 0 deletions bodhi/client/__init__.py
Expand Up @@ -106,6 +106,9 @@ def _set_logging_debug(ctx, param, value):
click.option('--close-bugs', is_flag=True, help='Automatically close bugs'),
click.option('--request', help='Requested repository',
type=click.Choice(['testing', 'stable', 'unpush'])),
click.option('--autotime', is_flag=True, help='Enable stable push base on time in testing'),
click.option('--stable-days', type=click.INT,
help='Days in testing required to push to stable'),
click.option('--autokarma', is_flag=True, help='Enable karma automatism'),
click.option('--stable-karma', type=click.INT, help='Stable karma threshold'),
click.option('--unstable-karma', type=click.INT, help='Unstable karma threshold'),
Expand Down
5 changes: 5 additions & 0 deletions bodhi/client/bindings.py
Expand Up @@ -239,6 +239,11 @@ def save(self, **kwargs):
(``reboot``, ``logout``).
inheritance (bool): Follow koji build inheritance, which may result in
this update being pushed out to additional releases.
autotime (bool): Allow bodhi to automatically change the state of this
update based on the time spent in testing by this update. It
will push your update to ``stable`` once it reaches the ``stable_days``.
stable_days (int): The minimun amount of time an update has to spend in
``testing`` before being automatically pushed to ``stable``.
autokarma (bool): Allow bodhi to automatically change the state of this
update based on the ``karma`` from user feedback. It will
push your update to ``stable`` once it reaches the ``stable_karma``
Expand Down
@@ -0,0 +1,50 @@
# Copyright (c) 2019 Red Hat, Inc.
#
# This file is part of Bodhi.
#
# This program 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; either version 2
# of the License, or (at your option) any later version.
#
# 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.
"""
Add autotime boolean and stable_days to Update.
Revision ID: b1fd856efcf6
Revises: 7ba286412ad4
Create Date: 2019-03-22 09:51:53.941289
"""
from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision = 'b1fd856efcf6'
down_revision = '7ba286412ad4'


def upgrade():
"""Add the autotime boolean and stable_days integer to the updates table."""
# autotime
op.add_column('updates', sa.Column('autotime', sa.Boolean()))
op.execute('UPDATE updates SET autotime=FALSE')
op.alter_column('updates', 'autotime', existing_type=sa.Boolean(), nullable=False)

# stable_days
op.add_column('updates', sa.Column('stable_days', sa.Integer()))
op.execute('UPDATE updates SET stable_days=0')
op.alter_column('updates', 'stable_days', existing_type=sa.Integer(), nullable=False)


def downgrade():
"""Drop the autotime boolean and the stable_days integer from the updates table."""
op.drop_column('updates', 'autotime')
op.drop_column('updates', 'stable_days')
28 changes: 27 additions & 1 deletion bodhi/server/models.py
Expand Up @@ -1536,8 +1536,12 @@ class Update(Base):
Attributes:
autokarma (bool): A boolean that indicates whether or not the update will
be automatically pushed when the stable_karma threshold is reached.
autotime (bool): A boolean that indicates whether or not the update will
be automatically pushed when the time threshold is reached.
stable_karma (int): A positive integer that indicates the amount of "good"
karma the update must receive before being automatically marked as stable.
stable_days (int): A positive integer that indicates the number of days an update
needs to spend in testing before being automatically marked as stable.
unstable_karma (int): A positive integer that indicates the amount of "bad"
karma the update must receive before being automatically marked as unstable.
requirements (unicode): A list of taskotron tests that must pass for this
Expand Down Expand Up @@ -1606,7 +1610,9 @@ class Update(Base):
__get_by__ = ('alias',)

autokarma = Column(Boolean, default=True, nullable=False)
autotime = Column(Boolean, default=False, nullable=False)
stable_karma = Column(Integer, nullable=False)
stable_days = Column(Integer, nullable=False, default=0)
unstable_karma = Column(Integer, nullable=False)
requirements = Column(UnicodeText)
require_bugs = Column(Boolean, default=False)
Expand Down Expand Up @@ -1984,6 +1990,16 @@ def new(cls, request, data):
release = data.pop('release', None)
up = Update(**data, release=release)

# We want to make sure that the value of stable_days
# will not be lower than the mandatory_days_in_testing.
if up.mandatory_days_in_testing > up.stable_days:
up.stable_days = up.mandatory_days_in_testing
caveats.append({
'name': 'stable days',
'description': "The number of stable days required was set to the mandatory "
f"release value {up.mandatory_days_in_testing} days"
})

log.debug("Setting request for new update.")
up.set_request(db, req, request.user.name)

Expand Down Expand Up @@ -2022,6 +2038,16 @@ def edit(cls, request, data):
caveats = []
edited_builds = [build.nvr for build in up.builds]

# stable_days can be set by the user we want to make sure that the value
# will not be lower than the mandatory_days_in_testing.
if up.mandatory_days_in_testing > data.get('stable_days', up.stable_days):
data['stable_days'] = up.mandatory_days_in_testing
caveats.append({
'name': 'stable days',
'description': "The number of stable days required was raised to the mandatory "
f"release value {up.mandatory_days_in_testing} days"
})

# Determine which builds have been added
new_builds = []
for build in data['builds']:
Expand Down Expand Up @@ -3341,7 +3367,7 @@ def met_testing_requirements(self):
if min_num_days:
if not self.meets_testing_requirements:
return False
else:
elif not self.autotime:
return True
for comment in self.comments_since_karma_reset:
if comment.user.name == 'bodhi' and \
Expand Down
9 changes: 9 additions & 0 deletions bodhi/server/schemas.py
Expand Up @@ -230,6 +230,15 @@ class SaveUpdateSchema(CSRFProtectedSchema, colander.MappingSchema):
colander.Boolean(),
missing=True,
)
autotime = colander.SchemaNode(
colander.Boolean(),
missing=True,
)
stable_days = colander.SchemaNode(
colander.Integer(),
validator=colander.Range(min=0),
missing=0,
)


class Cosmetics(colander.MappingSchema):
Expand Down
15 changes: 11 additions & 4 deletions bodhi/server/scripts/approve_testing.py
Expand Up @@ -28,7 +28,7 @@

from pyramid.paster import get_appsettings

from ..models import Update, UpdateStatus
from ..models import Update, UpdateStatus, UpdateRequest
from ..config import config
from bodhi.messages.schemas import update as update_schemas
from bodhi.server import Session, initialize_db, notifications
Expand Down Expand Up @@ -76,10 +76,12 @@ def main(argv=sys.argv):
testing = db.query(Update).filter_by(status=UpdateStatus.testing,
request=None)
for update in testing:
# If this release does not have any testing requirements, skip it
if not update.release.mandatory_days_in_testing:
print('%s doesn\'t have mandatory days in testing' % update.release.name)
continue
if not update.autotime:
# If this release does not have any testing requirements and is not autotime,
# skip it
print('%s doesn\'t have mandatory days in testing' % update.release.name)
continue

# If this has already met testing requirements, skip it
if update.met_testing_requirements:
Expand Down Expand Up @@ -107,6 +109,11 @@ def main(argv=sys.argv):

notifications.publish(update_schemas.UpdateRequirementsMetStableV1.from_dict(
dict(update=update)))

if update.autotime and update.days_in_testing >= update.stable_days:
print(f"Automatically marking {update.alias} as stable")
update.set_request(db=db, action=UpdateRequest.stable, username="bodhi")

db.commit()

except Exception as e:
Expand Down
39 changes: 29 additions & 10 deletions bodhi/server/templates/new_update.html
Expand Up @@ -217,20 +217,29 @@ <h2 class="pull-left">Edit
checked
% endif
></dd>
<dt data-toggle="tooltip" title="If checked, this option allows bodhi to automatically move your update from testing to stable once enough positive karma has been given.">
Auto-request stable based on karma ?</dt>
<dd> <input type="checkbox" name="autokarma" data-singleton="true"
% if update and update.autokarma:
checked
% elif not update:
checked
% endif>
</dd>
<dt data-toggle="tooltip" title="If checked, this option allows bodhi to automatically move your update from testing to stable once enough time was spent in testing.">
Auto-request stable based on time ?</dt>
<dd> <input type="checkbox" name="autotime" data-singleton="true"
% if update and update.autotime:
checked
% elif not update:
checked
% endif>
</dd>
</dl>
</div>

<div class="col-md-5">
<dl id='radios'>
<dt data-toggle="tooltip" title="If checked, this option allows bodhi to automatically move your update from testing to stable once enough positive karma has been given.">
Auto-request stable?</dt>
<dd> <input type="checkbox" name="autokarma" data-singleton="true"
% if update and update.autokarma:
checked
% elif not update:
checked
% endif
></dd>
<dl>
<dt data-toggle="tooltip" title="This is the threshold of positive karma required to automatically push an update from testing to stable.">
Stable karma</dt>
<dd> <input type="number" name="stable_karma" min="1" required
Expand All @@ -251,6 +260,16 @@ <h2 class="pull-left">Edit
% endif
></dd>

<dt data-toggle="tooltip" title="This is the number of days an update needs to spend in testing to be automatically pushed to stable.">
Stable days</dt>
<dd> <input type="number" name="stable_days" min="1"
% if update:
value="${update.stable_days}"
% elif not update:
value=""
% endif
></dd>

<dt data-toggle="tooltip" title="If checked, this will require that positive feedback be given on all associated bugs before the update can pass to stable. If your update has no associated bugs, this option has no effect.">
Require bugs
</dt>
Expand Down
29 changes: 26 additions & 3 deletions bodhi/server/templates/update.html
Expand Up @@ -913,7 +913,7 @@ <h5 class="m-t-2">

<div class="p-b-1">
<div>
<strong>Autopush</strong>
<strong>Autopush (karma)</strong>
</div>
<div>
% if update.autokarma is True:
Expand All @@ -925,8 +925,31 @@ <h5 class="m-t-2">
</td>
% elif update.autokarma is False:
<td>
<span class='text-muted' data-toggle='tooltip' title='The update will never be automatically pushed
to stable.'>
<span class='text-muted' data-toggle='tooltip' title='The update will not be automatically pushed
to stable based on karma.'>
<span class='label label-danger'>Disabled</span>
</span>
</td>
% endif
</div>
</div>

<div class="p-b-1">
<div>
<strong>Autopush (time)</strong>
</div>
<div>
% if update.autotime is True:
<td>
<span class='text-muted' data-toggle='tooltip' title='The update will be automatically pushed
to stable once the required time in testing is reached.'>
<span class='label label-success'>Enabled</span>
</span>
</td>
% elif update.autotime is False:
<td>
<span class='text-muted' data-toggle='tooltip' title='The update will not be automatically pushed
to stable base on time in testing.'>
<span class='label label-danger'>Disabled</span>
</span>
</td>
Expand Down

0 comments on commit 155988e

Please sign in to comment.