diff --git a/module_build_service/scheduler/handlers/repos.py b/module_build_service/scheduler/handlers/repos.py index 57c97ee3..68b74c06 100644 --- a/module_build_service/scheduler/handlers/repos.py +++ b/module_build_service/scheduler/handlers/repos.py @@ -106,7 +106,8 @@ def done(config, session, msg): unbuilt_components = [ c for c in module_build.component_builds if (c.state != koji.BUILD_STATES['COMPLETE'] - and c.state != koji.BUILD_STATES["FAILED"]) + and c.state != koji.BUILD_STATES["FAILED"] + and c.state != koji.BUILD_STATES["CANCELED"]) ] further_work = [] @@ -130,7 +131,20 @@ def done(config, session, msg): return further_work else: - module_build.transition(config, state=models.BUILD_STATES['done']) + # We know that there are no unbuilt components in this module build, + # so we can mark the state as "done" or "failed (in case there are + # some failed or canceled components in a build). + failed_component_present = False + for c in module_build.component_builds: + if c.state in (koji.BUILD_STATES['FAILED'], + koji.BUILD_STATES["CANCELED"]): + failed_component_present = True + break + if failed_component_present: + module_build.transition(config, state=models.BUILD_STATES['failed'], + state_reason="Some components failed to build.") + else: + module_build.transition(config, state=models.BUILD_STATES['done']) session.commit() builder.finalize() diff --git a/tests/__init__.py b/tests/__init__.py index be4a91d9..42f44aac 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -183,7 +183,7 @@ def init_data(): session.commit() -def scheduler_init_data(): +def scheduler_init_data(communicator_state = None): db.session.remove() db.drop_all() db.create_all() @@ -217,7 +217,7 @@ def scheduler_init_data(): '#da95886c8a443b36a9ce31abda1f9bed22f2f9c2') component_one_build_one.format = 'rpms' component_one_build_one.task_id = 12312345 - component_one_build_one.state = None + component_one_build_one.state = communicator_state component_one_build_one.nvr = 'communicator-1.10.1-2.module_starcommand_1_3' component_one_build_one.batch = 2 component_one_build_one.module_id = 1 diff --git a/tests/test_scheduler/test_repo_done.py b/tests/test_scheduler/test_repo_done.py index 8094db7a..c7a02b81 100644 --- a/tests/test_scheduler/test_repo_done.py +++ b/tests/test_scheduler/test_repo_done.py @@ -29,7 +29,7 @@ import module_build_service.messaging import module_build_service.scheduler.handlers.repos import module_build_service.models from tests import scheduler_init_data -from tests import conf, db +from tests import conf, db, app base_dir = dirname(dirname(__file__)) cassette_dir = base_dir + '/vcr-request-data/' @@ -99,3 +99,27 @@ class TestRepoDone(unittest.TestCase): .filter_by(package='communicator').one() self.assertEquals(component_build.state_reason, 'Failed to submit artifact communicator to Koji') + + @mock.patch('module_build_service.builder.KojiModuleBuilder.list_tasks_for_components', return_value=[]) + @mock.patch('module_build_service.builder.KojiModuleBuilder.buildroot_ready', return_value=True) + @mock.patch('module_build_service.builder.KojiModuleBuilder.get_session') + @mock.patch('module_build_service.builder.KojiModuleBuilder.build') + @mock.patch('module_build_service.builder.KojiModuleBuilder.buildroot_connect') + @mock.patch("module_build_service.builder.GenericBuilder.default_buildroot_groups", return_value = {'build': [], 'srpm-build': []}) + def test_failed_component_build(self, dbg, connect, build_fn, config, ready, list_tasks_fn): + """ Test that when a KojiModuleBuilder.build fails, the build is + marked as failed with proper state_reason. + """ + with app.app_context(): + scheduler_init_data(3) + config.return_value = mock.Mock(), 'development' + build_fn.return_value = None, 4, 'Failed to submit artifact communicator to Koji', None + + msg = module_build_service.messaging.KojiRepoChange( + 'some_msg_id', 'module-starcommand-1.3-build') + module_build_service.scheduler.handlers.repos.done( + config=conf, session=db.session, msg=msg) + module_build = module_build_service.models.ModuleBuild.query\ + .filter_by(name='starcommand').one() + + self.assertEquals(module_build.state, module_build_service.models.BUILD_STATES["failed"])