alembic.get_heads() returns all heads for all branches it can find in
scripts dir, while in alembic_version table, it does not store any heads
that were overridden by other branches, even if those depends_on it
instead of having it as down_revision.
To keep 'current' output in sync with what is in HEADS file, we can
attach liberty_* branches explicitly to kilo revision.
It's also a good idea to have a separate 'heads' command that would show
the latest alembic heads based on scripts dir state. See [1] for more
details.
While at it, since different subprojects can link their expand/contract
branches to kilo in different way (some using depends_on the previous
release branch, while others, as suggested in this patch, thru
down_revision to kilo), we kill the check on the number of heads
returned by script.get_heads() since it may differ. If we want to
validate that we don't branch more than twice from kilo, we may add a
separate validation just for that.
[1]: https://review.openstack.org/#/c/204551/
Change-Id: If551633ab26e0eac549c1e13cfa0771383a1a060
Partially-Implements: blueprint online-schema-migrations
2a16083502f3
9859ac9c136
-kilo
# revision identifiers, used by Alembic.
revision = '30018084ec99'
-down_revision = None
-depends_on = ('kilo',)
+down_revision = 'kilo'
branch_labels = ('liberty_contract',)
# revision identifiers, used by Alembic.
revision = '354db87e3225'
-down_revision = None
+down_revision = 'kilo'
branch_labels = ('liberty_expand',)
-depends_on = ('kilo',)
from alembic import op
import sqlalchemy as sa
def _get_sorted_heads(script):
'''Get the list of heads for all branches, sorted.'''
- heads = script.get_heads()
- # +1 stands for the core 'kilo' branch, the one that didn't have branches
- if len(heads) > len(MIGRATION_BRANCHES) + 1:
- alembic_util.err(_('No new branches are allowed except: %s') %
- ' '.join(MIGRATION_BRANCHES))
- return sorted(heads)
+ return sorted(script.get_heads())
def validate_heads_file(config):
mock_open.return_value.write.assert_called_once_with(
'\n'.join(sorted(heads)))
- def test_update_heads_file_excessive_heads_negative(self):
- with mock.patch('alembic.script.ScriptDirectory.from_config') as fc:
- heads = ('b', 'a', 'c', 'kilo')
- fc.return_value.get_heads.return_value = heads
- self.assertRaises(
- SystemExit,
- cli.update_heads_file,
- mock.sentinel.config
- )
- self.mock_alembic_err.assert_called_once_with(mock.ANY)
-
@mock.patch('os.path.exists')
@mock.patch('os.remove')
def test_update_heads_file_success(self, *os_mocks):