diff --git a/module_build_service/config.py b/module_build_service/config.py index 7cdbbf47..ccab1bfe 100644 --- a/module_build_service/config.py +++ b/module_build_service/config.py @@ -640,6 +640,12 @@ class Config(object): "default": False, "desc": "Allow module scratch builds", }, + "scratch_build_only_branches": { + "type": list, + "default": [], + "desc": "The list of regexes used to identify branches from which only the module " + "scratch builds can be built", + }, "product_pages_url": { "type": str, "default": "", diff --git a/module_build_service/utils/submit.py b/module_build_service/utils/submit.py index 614e9531..d8544ace 100644 --- a/module_build_service/utils/submit.py +++ b/module_build_service/utils/submit.py @@ -1003,6 +1003,18 @@ def submit_module_build(db_session, username, mmd, params): # append incrementing counter to context context_suffix = "_" + str(len(scrmods) + 1) mmd.set_context(mmd.get_context() + context_suffix) + else: + # In case the branch is defined, check whether user is allowed to submit + # non-scratch build from this branch. Note that the branch is always defined + # for official builds from SCM, because it is requested in views.py. + branch = params.get("branch", None) + if branch: + for regex in conf.scratch_build_only_branches: + branch_search = re.search(regex, branch) + if branch_search: + raise ValidationError( + "Only scratch module builds can be build from this branch." + ) log.debug("Creating new module build") module = models.ModuleBuild.create( diff --git a/tests/test_utils/test_utils.py b/tests/test_utils/test_utils.py index fd116233..78ae51cf 100644 --- a/tests/test_utils/test_utils.py +++ b/tests/test_utils/test_utils.py @@ -38,6 +38,7 @@ from tests import ( init_data, scheduler_init_data, make_module_in_db, + make_module, read_staged_data, staged_data_filename) import mock import koji @@ -1051,6 +1052,31 @@ class TestUtils: assert builds[0].siblings(db_session) == [builds[1].id] assert builds[1].siblings(db_session) == [builds[0].id] + @patch("module_build_service.utils.mse.generate_expanded_mmds") + @patch( + "module_build_service.config.Config.scratch_build_only_branches", + new_callable=mock.PropertyMock, + return_value=["^private-.*"], + ) + def test_submit_build_scratch_build_only_branches( + self, cfg, generate_expanded_mmds, db_session): + """ + Tests the "scratch_build_only_branches" config option. + """ + mmd = make_module("foo:stream:0:c1") + generate_expanded_mmds.return_value = [mmd] + # Create a copy of mmd1 without xmd.mbs, since that will cause validate_mmd to fail + mmd_copy = mmd.copy() + mmd_copy.set_xmd({}) + + with pytest.raises(ValidationError, + match="Only scratch module builds can be build from this branch."): + module_build_service.utils.submit_module_build( + db_session, "foo", mmd_copy, {"branch": "private-foo"}) + + module_build_service.utils.submit_module_build( + db_session, "foo", mmd_copy, {"branch": "otherbranch"}) + class DummyModuleBuilder(GenericBuilder): """