Repository: fedora-infra/bodhi

Issue:
Cannot create new updates: IntegrityError: null value in column "alias"
There is an issue on our develop branch that prevents new updates from being created:

```
2019-03-22 14:55:16,552 ERROR [bodhi.server][waitress] Failed to create update
Traceback (most recent call last):
  File "/usr/lib64/python3.7/site-packages/sqlalchemy/engine/base.py", line 1236, in _execute_context
    cursor, statement, parameters, context
  File "/usr/lib64/python3.7/site-packages/sqlalchemy/engine/default.py", line 536, in do_execute
    cursor.execute(statement, parameters)
psycopg2.IntegrityError: null value in column "alias" violates not-null constraint
DETAIL:  Failing row contains (134283, 3, -3, , t, t, test, enhancement, pending, null, unspecified, unspecified, f, f, f, t, 2019-03-22 14:55:16.544772, null, null, null, null, null, 2897, null, null, t, null, ).
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
  File "/home/vagrant/bodhi/bodhi/server/services/updates.py", line 507, in new_update
    result, _caveats = Update.new(request, _data)
  File "/home/vagrant/bodhi/bodhi/server/models.py", line 1991, in new
    up = Update(**data, release=release)
  File "<string>", line 4, in __init__
  File "/usr/lib64/python3.7/site-packages/sqlalchemy/orm/state.py", line 428, in _initialize_instance
    manager.dispatch.init_failure(self, args, kwargs)
  File "/usr/lib64/python3.7/site-packages/sqlalchemy/util/langhelpers.py", line 67, in __exit__
    compat.reraise(exc_type, exc_value, exc_tb)
  File "/usr/lib64/python3.7/site-packages/sqlalchemy/util/compat.py", line 277, in reraise
    raise value
  File "/usr/lib64/python3.7/site-packages/sqlalchemy/orm/state.py", line 425, in _initialize_instance
    return manager.original_init(*mixed[1:], **kwargs)
  File "/home/vagrant/bodhi/bodhi/server/models.py", line 1687, in __init__
    super(Update, self).__init__(*args, **kwargs)
  File "/usr/lib64/python3.7/site-packages/sqlalchemy/ext/declarative/base.py", line 801, in _declarative_constructor
    setattr(self, k, kwargs[k])
  File "/usr/lib64/python3.7/site-packages/sqlalchemy/orm/attributes.py", line 261, in __set__
    instance_state(instance), instance_dict(instance), value, None
  File "/usr/lib64/python3.7/site-packages/sqlalchemy/orm/attributes.py", line 932, in set
    value = self.fire_replace_event(state, dict_, value, old, initiator)
  File "/usr/lib64/python3.7/site-packages/sqlalchemy/orm/attributes.py", line 955, in fire_replace_event
    state, value, previous, initiator or self._replace_token
  File "/usr/lib64/python3.7/site-packages/sqlalchemy/orm/util.py", line 168, in set_
    return validator(state.obj(), key, value)
  File "/home/vagrant/bodhi/bodhi/server/models.py", line 1741, in validate_release
    u = Update.query.filter(Update.release_id == release.id, Update.id != self.id).first()
  File "/usr/lib64/python3.7/site-packages/sqlalchemy/orm/query.py", line 2979, in first
    ret = list(self[0:1])
  File "/usr/lib64/python3.7/site-packages/sqlalchemy/orm/query.py", line 2771, in __getitem__
    return list(res)
  File "/usr/lib64/python3.7/site-packages/sqlalchemy/orm/query.py", line 3080, in __iter__
    self.session._autoflush()
  File "/usr/lib64/python3.7/site-packages/sqlalchemy/orm/session.py", line 1582, in _autoflush
    util.raise_from_cause(e)
  File "/usr/lib64/python3.7/site-packages/sqlalchemy/util/compat.py", line 296, in raise_from_cause
    reraise(type(exception), exception, tb=exc_tb, cause=cause)
  File "/usr/lib64/python3.7/site-packages/sqlalchemy/util/compat.py", line 277, in reraise
    raise value
  File "/usr/lib64/python3.7/site-packages/sqlalchemy/orm/session.py", line 1571, in _autoflush
    self.flush()
  File "/usr/lib64/python3.7/site-packages/sqlalchemy/orm/session.py", line 2446, in flush
    self._flush(objects)
  File "/usr/lib64/python3.7/site-packages/sqlalchemy/orm/session.py", line 2584, in _flush
    transaction.rollback(_capture_exception=True)
  File "/usr/lib64/python3.7/site-packages/sqlalchemy/util/langhelpers.py", line 67, in __exit__
    compat.reraise(exc_type, exc_value, exc_tb)
  File "/usr/lib64/python3.7/site-packages/sqlalchemy/util/compat.py", line 277, in reraise
    raise value
  File "/usr/lib64/python3.7/site-packages/sqlalchemy/orm/session.py", line 2544, in _flush
    flush_context.execute()
  File "/usr/lib64/python3.7/site-packages/sqlalchemy/orm/unitofwork.py", line 416, in execute
    rec.execute(self)
  File "/usr/lib64/python3.7/site-packages/sqlalchemy/orm/unitofwork.py", line 583, in execute
    uow,
  File "/usr/lib64/python3.7/site-packages/sqlalchemy/orm/persistence.py", line 245, in save_obj
    insert,
  File "/usr/lib64/python3.7/site-packages/sqlalchemy/orm/persistence.py", line 1116, in _emit_insert_statements
    statement, params
  File "/usr/lib64/python3.7/site-packages/sqlalchemy/engine/base.py", line 980, in execute
    return meth(self, multiparams, params)
  File "/usr/lib64/python3.7/site-packages/sqlalchemy/sql/elements.py", line 273, in _execute_on_connection
    return connection._execute_clauseelement(self, multiparams, params)
  File "/usr/lib64/python3.7/site-packages/sqlalchemy/engine/base.py", line 1099, in _execute_clauseelement
    distilled_params,
  File "/usr/lib64/python3.7/site-packages/sqlalchemy/engine/base.py", line 1240, in _execute_context
    e, statement, parameters, cursor, context
  File "/usr/lib64/python3.7/site-packages/sqlalchemy/engine/base.py", line 1458, in _handle_dbapi_exception
    util.raise_from_cause(sqlalchemy_exception, exc_info)
  File "/usr/lib64/python3.7/site-packages/sqlalchemy/util/compat.py", line 296, in raise_from_cause
    reraise(type(exception), exception, tb=exc_tb, cause=cause)
  File "/usr/lib64/python3.7/site-packages/sqlalchemy/util/compat.py", line 276, in reraise
    raise value.with_traceback(tb)
  File "/usr/lib64/python3.7/site-packages/sqlalchemy/engine/base.py", line 1236, in _execute_context
    cursor, statement, parameters, context
  File "/usr/lib64/python3.7/site-packages/sqlalchemy/engine/default.py", line 536, in do_execute
    cursor.execute(statement, parameters)
sqlalchemy.exc.IntegrityError: (raised as a result of Query-invoked autoflush; consider using a session.no_autoflush block if this flush is occurring prematurely) (psycopg2.IntegrityError) null value in column "alias" violates not-null constraint
DETAIL:  Failing row contains (134283, 3, -3, , t, t, test, enhancement, pending, null, unspecified, unspecified, f, f, f, t, 2019-03-22 14:55:16.544772, null, null, null, null, null, 2897, null, null, t, null, ).
 [SQL: 'INSERT INTO updates (autokarma, stable_karma, unstable_karma, requirements, require_bugs, require_testcases, display_name, notes, type, status, request, severity, suggest, locked, pushed, critpath, close_bugs, date_submitted, date_modified, date_approved, date_pushed, date_testing, date_stable, alias, release_id, user_id, test_gating_status) VALUES (%(autokarma)s, %(stable_karma)s, %(unstable_karma)s, %(requirements)s, %(require_bugs)s, %(require_testcases)s, %(display_name)s, %(notes)s, %(type)s, %(status)s, %(request)s, %(severity)s, %(suggest)s, %(locked)s, %(pushed)s, %(critpath)s, %(close_bugs)s, %(date_submitted)s, %(date_modified)s, %(date_approved)s, %(date_pushed)s, %(date_testing)s, %(date_stable)s, %(alias)s, %(release_id)s, %(user_id)s, %(test_gating_status)s) RETURNING updates.id'] [parameters: {'autokarma': True, 'stable_karma': 3, 'unstable_karma': -3, 'requirements': '', 'require_bugs': True, 'require_testcases': True, 'display_name': '', 'notes': 'test', 'type': 'enhancement', 'status': 'pending', 'request': None, 'severity': 'unspecified', 'suggest': 'unspecified', 'locked': False, 'pushed': False, 'critpath': False, 'close_bugs': True, 'date_submitted': datetime.datetime(2019, 3, 22, 14, 55, 16, 544772), 'date_modified': None, 'date_approved': None, 'date_pushed': None, 'date_testing': None, 'date_stable': None, 'alias': None, 'release_id': None, 'user_id': 2897, 'test_gating_status': None}] (Background on this error at: http://sqlalche.me/e/gkpj)
```


Discussion:

Resolving patch:
diff --git a/bodhi/server/models.py b/bodhi/server/models.py
--- a/bodhi/server/models.py
+++ b/bodhi/server/models.py
@@ -1684,17 +1684,19 @@ def __init__(self, *args, **kwargs):
         We use this as a way to inject an alias into the Update, since it is a required field and
         we don't want callers to have to generate the alias themselves.
         """
-        super(Update, self).__init__(*args, **kwargs)
-
         # Let's give this Update an alias so the DB doesn't become displeased with us.
-        if not self.release:
+        if 'release' not in kwargs:
             raise ValueError('You must specify a Release when creating an Update.')
-        prefix = self.release.id_prefix
+        prefix = kwargs['release'].id_prefix
         year = time.localtime()[0]
         id = hashlib.sha1(str(uuid.uuid4()).encode('utf-8')).hexdigest()[:10]
         alias = u'%s-%s-%s' % (prefix, year, id)
-        log.debug('Setting alias for %s to %s' % (self.get_title(), alias))
         self.alias = alias
+        self.release_id = kwargs['release'].id
+
+        super(Update, self).__init__(*args, **kwargs)
+
+        log.debug('Set alias for %s to %s' % (self.get_title(), alias))
 
     @property
     def side_tag_locked(self):


Test patch: