Merge pull request #2652 from charltonaustin/failing_repository_notifications_to_be_disabled_after_n_failures_in_a_row_144646649

Failing repository notifications to be disabled after n failures in a row 144646649
This commit is contained in:
Charlton Austin 2017-05-22 09:30:53 -04:00 committed by GitHub
commit a71f60a9c1
14 changed files with 156 additions and 33 deletions

View file

@ -1006,6 +1006,7 @@ class RepositoryNotification(BaseModel):
title = CharField(null=True)
config_json = TextField()
event_config_json = TextField(default='{}')
number_of_failures = IntegerField(default=0)
class RepositoryAuthorizedEmail(BaseModel):

View file

@ -0,0 +1,29 @@
"""add notification number of failures column
Revision ID: dc4af11a5f90
Revises: 53e2ac668296
Create Date: 2017-05-16 17:24:02.630365
"""
# revision identifiers, used by Alembic.
revision = 'dc4af11a5f90'
down_revision = '53e2ac668296'
import sqlalchemy as sa
from alembic import op
def upgrade(tables):
op.add_column('repositorynotification', sa.Column('number_of_failures', sa.Integer(), nullable=False))
op.bulk_insert(tables.logentrykind, [
{'name': 'reset_repo_notification'},
])
def downgrade(tables):
op.drop_column('repositorynotification', 'number_of_failures')
op.execute(tables
.logentrykind
.delete()
.where(tables.logentrykind.c.name == op.inline_literal('reset_repo_notification')))

View file

@ -1,9 +1,9 @@
import json
from data.model import InvalidNotificationException, db_transaction
from data.database import (Notification, NotificationKind, User, Team, TeamMember, TeamRole,
RepositoryNotification, ExternalNotificationEvent, Repository,
ExternalNotificationMethod, Namespace)
ExternalNotificationMethod, Namespace, db_for_update)
from data.model import InvalidNotificationException, db_transaction
def create_notification(kind_name, target, metadata={}, lookup_path=None):
@ -125,6 +125,29 @@ def delete_matching_notifications(target, kind_name, **kwargs):
notification.delete_instance()
def increment_notification_failure_count(notification_id):
""" This increments the number of failures by one """
RepositoryNotification.update(number_of_failures=RepositoryNotification.number_of_failures + 1).where(
RepositoryNotification.id == notification_id).execute()
def reset_notification_number_of_failures(namespace_name, repository_name, uuid):
""" This resets the number of failures for a repo notification to 0 """
try:
notification = RepositoryNotification.select().where(RepositoryNotification.uuid == uuid).get()
if (notification.repository.namespace_user.username != namespace_name or
notification.repository.name != repository_name):
raise InvalidNotificationException('No repository notification found with uuid: %s' % uuid)
reset_number_of_failures_to_zero(notification.id)
except RepositoryNotification.DoesNotExist:
pass
def reset_number_of_failures_to_zero(notification_id):
""" This resets the number of failures for a repo notification to 0 """
RepositoryNotification.update(number_of_failures=0).where(RepositoryNotification.id == notification_id).execute()
def create_repo_notification(repo, event_name, method_name, method_config, event_config, title=None):
event = ExternalNotificationEvent.get(ExternalNotificationEvent.name == event_name)
method = ExternalNotificationMethod.get(ExternalNotificationMethod.name == method_name)
@ -134,23 +157,34 @@ def create_repo_notification(repo, event_name, method_name, method_config, event
event_config_json=json.dumps(event_config))
def _base_get_notification(uuid):
""" This is a base query for get statements """
return (RepositoryNotification
.select(RepositoryNotification, Repository, Namespace)
.join(Repository)
.join(Namespace, on=(Repository.namespace_user == Namespace.id))
.where(RepositoryNotification.uuid == uuid))
def get_enabled_notification(uuid):
""" This returns a notification with less than 3 failures """
try:
return _base_get_notification(uuid).where(RepositoryNotification.number_of_failures < 3).get()
except RepositoryNotification.DoesNotExist:
raise InvalidNotificationException('No repository notification found with uuid: %s' % uuid)
def get_repo_notification(uuid):
try:
return (RepositoryNotification
.select(RepositoryNotification, Repository, Namespace)
.join(Repository)
.join(Namespace, on=(Repository.namespace_user == Namespace.id))
.where(RepositoryNotification.uuid == uuid)
.get())
return _base_get_notification(uuid).get()
except RepositoryNotification.DoesNotExist:
raise InvalidNotificationException('No repository notification found with id: %s' % uuid)
raise InvalidNotificationException('No repository notification found with uuid: %s' % uuid)
def delete_repo_notification(namespace_name, repository_name, uuid):
found = get_repo_notification(uuid)
if (found.repository.namespace_user.username != namespace_name or
found.repository.name != repository_name):
raise InvalidNotificationException('No repository notifiation found with id: %s' % uuid)
if found.repository.namespace_user.username != namespace_name or found.repository.name != repository_name:
raise InvalidNotificationException('No repository notifiation found with uuid: %s' % uuid)
found.delete_instance()
return found