diff --git a/module_build_service/migrations/versions/40b2c7d988d7_add_reused_module_id_column.py b/module_build_service/migrations/versions/40b2c7d988d7_add_reused_module_id_column.py new file mode 100644 index 00000000..514786b6 --- /dev/null +++ b/module_build_service/migrations/versions/40b2c7d988d7_add_reused_module_id_column.py @@ -0,0 +1,23 @@ +"""add reused_module_id column + +Revision ID: 40b2c7d988d7 +Revises: bf861b6af29a +Create Date: 2019-06-21 13:41:06.041269 + +""" + +# revision identifiers, used by Alembic. +revision = '40b2c7d988d7' +down_revision = 'bf861b6af29a' + +from alembic import op +import sqlalchemy as sa + + +def upgrade(): + op.add_column('module_builds', sa.Column('reused_module_id', sa.Integer(), nullable=True)) + sa.ForeignKeyConstraint(['reused_module_id'], ['module_builds.id'], ), + + +def downgrade(): + op.drop_column('module_builds', 'reused_module_id') diff --git a/module_build_service/models.py b/module_build_service/models.py index 17c73bb3..b3fae068 100644 --- a/module_build_service/models.py +++ b/module_build_service/models.py @@ -221,6 +221,8 @@ class ModuleBuild(MBSBase): rebuild_strategy = db.Column(db.String, nullable=False) virtual_streams = db.relationship( "VirtualStream", secondary=module_builds_to_virtual_streams, back_populates="module_builds") + reused_module_id = db.Column(db.Integer, db.ForeignKey("module_builds.id")) + reused_module = db.relationship("ModuleBuild", remote_side="ModuleBuild.id") # List of arches against which the module is built. # NOTE: It is not filled for imported modules, because imported module builds have not been diff --git a/module_build_service/utils/reuse.py b/module_build_service/utils/reuse.py index 9ae05687..b1397144 100644 --- a/module_build_service/utils/reuse.py +++ b/module_build_service/utils/reuse.py @@ -85,8 +85,11 @@ def get_reusable_module(session, module): :param module: the ModuleBuild object of module being built. :return: ModuleBuild object which can be used for component reuse. """ - mmd = module.mmd() + if module.reused_module: + return module.reused_module + + mmd = module.mmd() # Find the latest module that is in the done or ready state previous_module_build = ( session.query(models.ModuleBuild) @@ -111,6 +114,9 @@ def get_reusable_module(session, module): log.info("Cannot re-use. %r is the first module build." % module) return None + module.reused_module_id = previous_module_build.id + session.commit() + return previous_module_build diff --git a/tests/test_utils/test_utils.py b/tests/test_utils/test_utils.py index 2abe6975..cb04883e 100644 --- a/tests/test_utils/test_utils.py +++ b/tests/test_utils/test_utils.py @@ -1429,3 +1429,45 @@ class TestOfflineLocalBuilds: module_build = models.ModuleBuild.get_build_from_nsvc( db.session, "platform", "y", 1, "000000") assert module_build + + +class TestUtilsModuleReuse: + + def setup_method(self, test_method): + init_data() + + def teardown_method(self, test_method): + clean_database() + + def test_get_reusable_module_when_reused_module_not_set(self): + module = models.ModuleBuild.query.filter_by( + name="nginx").order_by(models.ModuleBuild.id.desc()).first() + module.state = models.BUILD_STATES["build"] + db.session.commit() + + assert not module.reused_module + + reusable_module = module_build_service.utils.get_reusable_module( + db.session, module) + + assert module.reused_module + assert reusable_module.id == module.reused_module_id + + def test_get_reusable_module_when_reused_module_already_set(self): + modules = models.ModuleBuild.query.filter_by( + name="nginx").order_by(models.ModuleBuild.id.desc()).limit(2).all() + build_module = modules[0] + reused_module = modules[1] + build_module.state = models.BUILD_STATES["build"] + build_module.reused_module_id = reused_module.id + db.session.commit() + + assert build_module.reused_module + assert reused_module == build_module.reused_module + + reusable_module = module_build_service.utils.get_reusable_module( + db.session, build_module) + + assert build_module.reused_module + assert reusable_module.id == build_module.reused_module_id + assert reusable_module.id == reused_module.id