From 6f44a995f411f21f37f12f29ffa9610418afbba4 Mon Sep 17 00:00:00 2001 From: mprahl Date: Fri, 21 Apr 2017 16:45:28 -0400 Subject: [PATCH] Raise an error when a module includes a module with the same component --- module_build_service/utils.py | 14 ++++++++ tests/staged_data/testmodule-variant.yaml | 32 +++++++++++++++++ tests/test_utils/test_utils.py | 42 +++++++++++++++++++++++ 3 files changed, 88 insertions(+) create mode 100644 tests/staged_data/testmodule-variant.yaml diff --git a/module_build_service/utils.py b/module_build_service/utils.py index 74226ec6..e51435f0 100644 --- a/module_build_service/utils.py +++ b/module_build_service/utils.py @@ -630,6 +630,20 @@ def record_component_builds(mmd, module, initial_batch=1, # When main_mmd is set, merge the metadata from this mmd to main_mmd, # otherwise our current mmd is main_mmd. if main_mmd: + # Check for components that are in both MMDs before merging since MBS + # currently can't handle that situation. + duplicate_components = [rpm for rpm in main_mmd.components.rpms.keys() + if rpm in mmd.components.rpms.keys()] + if duplicate_components: + error_msg = ( + 'The included module "{0}" in "{1}" have the following ' + 'conflicting components: {2}' + .format(mmd.name, main_mmd.name, + ', '.join(duplicate_components))) + module.transition(conf, models.BUILD_STATES["failed"], error_msg) + db.session.add(module) + db.session.commit() + raise RuntimeError(error_msg) merge_included_mmd(main_mmd, mmd) else: main_mmd = mmd diff --git a/tests/staged_data/testmodule-variant.yaml b/tests/staged_data/testmodule-variant.yaml new file mode 100644 index 00000000..8a3ff3b0 --- /dev/null +++ b/tests/staged_data/testmodule-variant.yaml @@ -0,0 +1,32 @@ +document: modulemd +version: 1 +data: + name: testmodule-variant + summary: A test module in all its whackiness + description: This module demonstrates how to write simple modulemd files And can be used for testing the build and release pipeline. + license: + module: [ MIT ] + dependencies: + buildrequires: + base-runtime: master + requires: + base-runtime: master + references: + community: https://fedoraproject.org/wiki/Modularity + documentation: https://fedoraproject.org/wiki/Fedora_Packaging_Guidelines_for_Modules + tracker: https://taiga.fedorainfracloud.org/project/modularity + profiles: + default: + rpms: + - python + api: + rpms: + - python + components: + rpms: + perl-List-Compare: + rationale: A dependency of tangerine. + ref: f25 + python: + rationale: This is irrational + ref: f24 diff --git a/tests/test_utils/test_utils.py b/tests/test_utils/test_utils.py index 1339d06d..07126da5 100644 --- a/tests/test_utils/test_utils.py +++ b/tests/test_utils/test_utils.py @@ -413,6 +413,48 @@ class TestUtils(unittest.TestCase): self.assertEqual(failed_component.state, None) self.assertEqual(canceled_component.state, None) + @vcr.use_cassette( + path.join(CASSETTES_DIR, 'tests.test_utils.TestUtils.test_format_mmd')) + @patch('module_build_service.scm.SCM') + def test_record_component_builds_duplicate_components(self, mocked_scm): + with app.app_context(): + test_reuse_component_init_data() + mocked_scm.return_value.commit = \ + '620ec77321b2ea7b0d67d82992dda3e1d67055b4' + # For all the RPMs in testmodule, get_latest is called + hashes_returned = { + 'f25': '4ceea43add2366d8b8c5a622a2fb563b625b9abf', + 'f24': 'fbed359411a1baa08d4a88e0d12d426fbf8f602c'} + + def mocked_get_latest(branch="master"): + return hashes_returned[branch] + + mocked_scm.return_value.get_latest = mocked_get_latest + + testmodule_variant_mmd_path = path.join( + BASE_DIR, '..', 'staged_data', 'testmodule-variant.yaml') + testmodule_variant_mmd = modulemd.ModuleMetadata() + with open(testmodule_variant_mmd_path) as mmd_file: + testmodule_variant_mmd.loads(mmd_file) + + module_build = \ + db.session.query(models.ModuleBuild).filter_by(id=1).one() + mmd = module_build.mmd() + + error_msg = ( + 'The included module "testmodule-variant" in "testmodule" have ' + 'the following conflicting components: perl-List-Compare') + try: + module_build_service.utils.record_component_builds( + testmodule_variant_mmd, module_build, main_mmd=mmd) + assert False, 'A RuntimeError was expected but was not raised' + except RuntimeError as e: + self.assertEqual(e.message, error_msg) + + self.assertEqual(module_build.state, models.BUILD_STATES['failed']) + self.assertEqual(module_build.state_reason, error_msg) + + class DummyModuleBuilder(GenericBuilder): """ Dummy module builder