diff --git a/cli/copr_cli/main.py b/cli/copr_cli/main.py index 328322aa8..15496a948 100644 --- a/cli/copr_cli/main.py +++ b/cli/copr_cli/main.py @@ -481,6 +481,7 @@ def action_create(self, args): appstream=ON_OFF_MAP[args.appstream], runtime_dependencies=args.runtime_dependencies, packit_forge_projects_allowed=args.packit_forge_projects_allowed, + repo_priority=args.repo_priority, ) owner_part = username.replace('@', "g/") @@ -514,6 +515,7 @@ def action_modify_project(self, args): appstream=ON_OFF_MAP[args.appstream], runtime_dependencies=args.runtime_dependencies, packit_forge_projects_allowed=args.packit_forge_projects_allowed, + repo_priority=args.repo_priority, ) @requires_api_auth @@ -1174,6 +1176,9 @@ def setup_parser(): "created for you (as soon as they are available) as rawhide " "chroot forks.")) + parser_create.add_argument("--repo-priority", default=None, + help="Set the priority value of this repository") + create_and_modify_common_opts(parser_create) parser_create.set_defaults(func="action_create") @@ -1241,6 +1246,9 @@ def setup_parser(): "created for you (as soon as they are available) as rawhide " "chroot forks.")) + parser_modify.add_argument("--repo-priority", default=None, + help="Set the priority value of this repository") + create_and_modify_common_opts(parser_modify) parser_modify.set_defaults(func="action_modify_project") diff --git a/cli/tests/test_cli.py b/cli/tests/test_cli.py index 97c887f91..98b7a70c7 100644 --- a/cli/tests/test_cli.py +++ b/cli/tests/test_cli.py @@ -479,6 +479,7 @@ def test_create_project(config_from_file, project_proxy_add, capsys): "appstream": False, "runtime_dependencies": None, "packit_forge_projects_allowed": None, + "repo_priority": None, } assert stdout == "New project was successfully created: http://copr/coprs/jdoe/foo/\n" @@ -575,6 +576,7 @@ def test_create_multilib_project(config_from_file, project_proxy_add, capsys): "appstream": False, "runtime_dependencies": None, "packit_forge_projects_allowed": None, + "repo_priority": None, } assert stdout == "New project was successfully created: http://copr/coprs/jdoe/foo/\n" diff --git a/frontend/coprs_frontend/alembic/versions/7d9f6f921fa0_add_repo_priority_field.py b/frontend/coprs_frontend/alembic/versions/7d9f6f921fa0_add_repo_priority_field.py new file mode 100644 index 000000000..dfaa9eee9 --- /dev/null +++ b/frontend/coprs_frontend/alembic/versions/7d9f6f921fa0_add_repo_priority_field.py @@ -0,0 +1,25 @@ +""" +Add repo priority field + +Revision ID: 7d9f6f921fa0 +Revises: ba6ac0936bfb +Create Date: 2023-05-25 11:05:39.877208 +""" + +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = '7d9f6f921fa0' +down_revision = 'ba6ac0936bfb' +branch_labels = None +depends_on = None + + +def upgrade(): + op.add_column('copr', sa.Column('repo_priority', sa.Integer(), nullable=True)) + + +def downgrade(): + op.drop_column('copr', 'repo_priority') diff --git a/frontend/coprs_frontend/coprs/constants.py b/frontend/coprs_frontend/coprs/constants.py index 4f51c2511..0bd8ab83a 100644 --- a/frontend/coprs_frontend/coprs/constants.py +++ b/frontend/coprs_frontend/coprs/constants.py @@ -4,3 +4,5 @@ BANNER_LOCATION = "/var/lib/copr/data/banner-include.html" + +DEFAULT_REPO_PRIORITY_VALUE = 99 diff --git a/frontend/coprs_frontend/coprs/forms.py b/frontend/coprs_frontend/coprs/forms.py index 2c658f9d8..f1d8df52a 100644 --- a/frontend/coprs_frontend/coprs/forms.py +++ b/frontend/coprs_frontend/coprs/forms.py @@ -15,13 +15,14 @@ from flask_wtf import Form as FlaskForm from coprs import app +from coprs import exceptions from coprs import helpers from coprs import models +from coprs.constants import DEFAULT_REPO_PRIORITY_VALUE from coprs.logic.coprs_logic import CoprsLogic, MockChrootsLogic from coprs.logic.users_logic import UsersLogic from coprs.logic.dist_git_logic import DistGitLogic from coprs.logic.complex_logic import ComplexLogic -from coprs import exceptions from wtforms import ValidationError @@ -655,6 +656,17 @@ class CoprForm(BaseForm): filters=[StringListFilter(), StripUrlSchemaListFilter()], validators=[wtforms.validators.Optional()],) + repo_priority = wtforms.IntegerField( + "The priority value of this repository", + description="""If there is more than one package to install from (e.g. vim from + Fedora repo and Copr repo), the repo with lower priority is picked.""", + render_kw={"placeholder": "Optional - integer, e.g. 22"}, + validators=[ + wtforms.validators.Optional(), + wtforms.validators.NumberRange(min=1, max=DEFAULT_REPO_PRIORITY_VALUE)], + default=None, + ) + @property def errors(self): """ diff --git a/frontend/coprs_frontend/coprs/models.py b/frontend/coprs_frontend/coprs/models.py index 038534b47..e14fac82b 100644 --- a/frontend/coprs_frontend/coprs/models.py +++ b/frontend/coprs_frontend/coprs/models.py @@ -388,6 +388,20 @@ class _CoprPublic(db.Model, helpers.Serializer): # allowed to build in this Copr via Packit packit_forge_projects_allowed = db.Column(db.Text) + # priority=NUMBER in repo configs + repo_priority = db.Column(db.Integer, nullable=True) + + @validates("repo_priority") + def validate_repo_priority(self, _, value): + """Checks whether priority value is correct""" + if value < 1: + raise ValueError("Repo priority can't be lower than 1") + + if value > 99: + raise ValueError("Repo priority can't be higher than 99") + + return value + class _CoprPrivate(db.Model, helpers.Serializer): """ diff --git a/frontend/coprs_frontend/coprs/templates/coprs/_coprs_forms.html b/frontend/coprs_frontend/coprs/templates/coprs/_coprs_forms.html index 6430624cd..004605e5a 100644 --- a/frontend/coprs_frontend/coprs/templates/coprs/_coprs_forms.html +++ b/frontend/coprs_frontend/coprs/templates/coprs/_coprs_forms.html @@ -156,6 +156,11 @@

{{ counter('instructions') }}. Other options

placeholder='Optional', info='Delete the project after the specfied period of time (empty = disabled)') }} + {{ render_field(form.repo_priority, + class="short-input-field", + placeholder='Optional', + info='Set the priority value of this repository. Defaults to 99.') }} + {{ render_field(form.isolation, placeholder='default') }} {{ render_bootstrap_options(form) }} diff --git a/frontend/coprs_frontend/coprs/views/apiv3_ns/apiv3_projects.py b/frontend/coprs_frontend/coprs/views/apiv3_ns/apiv3_projects.py index 1b4b8b389..dd5e99133 100644 --- a/frontend/coprs_frontend/coprs/views/apiv3_ns/apiv3_projects.py +++ b/frontend/coprs_frontend/coprs/views/apiv3_ns/apiv3_projects.py @@ -39,6 +39,7 @@ def to_dict(copr): "appstream": copr.appstream, "packit_forge_projects_allowed": copr.packit_forge_projects_allowed_list, "follow_fedora_branching": copr.follow_fedora_branching, + "repo_priority": copr.repo_priority, } @@ -162,6 +163,7 @@ def _form_field_repos(form_field): runtime_dependencies=_form_field_repos(form.runtime_dependencies), appstream=form.appstream.data, packit_forge_projects_allowed=_form_field_repos(form.packit_forge_projects_allowed), + repo_priority=form.repo_priority.data, ) db.session.commit() except (DuplicateException, diff --git a/frontend/coprs_frontend/coprs/views/backend_ns/backend_general.py b/frontend/coprs_frontend/coprs/views/backend_ns/backend_general.py index 2be533678..59a11c877 100755 --- a/frontend/coprs_frontend/coprs/views/backend_ns/backend_general.py +++ b/frontend/coprs_frontend/coprs/views/backend_ns/backend_general.py @@ -165,6 +165,7 @@ def get_build_record(task, for_backend=False): "isolation": task.build.isolation, "fedora_review": task.build.copr.fedora_review, "appstream": bool(task.build.appstream), + "repo_priority": task.build.copr.repo_priority }) copr_chroot = CoprChrootsLogic.get_by_name_safe(task.build.copr, task.mock_chroot.name) diff --git a/frontend/coprs_frontend/coprs/views/coprs_ns/coprs_general.py b/frontend/coprs_frontend/coprs/views/coprs_ns/coprs_general.py index 88325a150..64365c9e3 100644 --- a/frontend/coprs_frontend/coprs/views/coprs_ns/coprs_general.py +++ b/frontend/coprs_frontend/coprs/views/coprs_ns/coprs_general.py @@ -282,6 +282,7 @@ def copr_new(username=None, group_name=None): isolation=form.isolation.data, appstream=form.appstream.data, packit_forge_projects_allowed=form.packit_forge_projects_allowed.data, + repo_priority=form.repo_priority.data ) db.session.commit() @@ -554,6 +555,8 @@ def process_copr_update(copr, form): copr.isolation = form.isolation.data copr.appstream = form.appstream.data copr.packit_forge_projects_allowed = form.packit_forge_projects_allowed.data + copr.repo_priority = form.repo_priority.data + if flask.g.user.admin: copr.auto_prune = form.auto_prune.data else: diff --git a/frontend/coprs_frontend/tests/test_apiv3/test_projects.py b/frontend/coprs_frontend/tests/test_apiv3/test_projects.py index 800211cdc..2a8a9cd6c 100644 --- a/frontend/coprs_frontend/tests/test_apiv3/test_projects.py +++ b/frontend/coprs_frontend/tests/test_apiv3/test_projects.py @@ -77,7 +77,7 @@ def test_update_copr_api3(self): # testing method! already_tested = set([ "delete_after", "build_enable_net", "auto_createrepo", "repos", - "runtime_dependencies", "packit_forge_projects_allowed" + "runtime_dependencies", "packit_forge_projects_allowed", "repo_priority" ]) # check non-trivial changes @@ -91,6 +91,7 @@ def test_update_copr_api3(self): assert old_data["auto_prune"] is True assert old_data["follow_fedora_branching"] is True assert old_data["packit_forge_projects_allowed"] == "" + assert old_data["repo_priority"] is None self.api3.modify_project( "test", delete_after_days=5, enable_net=True, devel_mode=True, repos=["http://example/repo/", "http://another/"], @@ -100,7 +101,8 @@ def test_update_copr_api3(self): "https://github.com/packit/ogr", "github.com/packit/requre", "http://github.com/packit/packit" - ] + ], + repo_priority=13, ) new_data = self._get_copr_id_data(1) delete_after = datetime.datetime.now() + datetime.timedelta(days=5) @@ -113,6 +115,7 @@ def test_update_copr_api3(self): old_data["bootstrap"] = "default" old_data["packit_forge_projects_allowed"] = "github.com/packit/ogr\ngithub.com/packit/requre\ngithub.com" \ "/packit/packit" + old_data["repo_priority"] = 13 assert old_data == new_data old_data = new_data diff --git a/python/copr/v3/proxies/project.py b/python/copr/v3/proxies/project.py index e22642757..89b062ea2 100644 --- a/python/copr/v3/proxies/project.py +++ b/python/copr/v3/proxies/project.py @@ -71,7 +71,8 @@ def add(self, ownername, projectname, chroots, description=None, instructions=No auto_prune=True, use_bootstrap_container=None, devel_mode=False, delete_after_days=None, multilib=False, module_hotfixes=False, bootstrap=None, bootstrap_image=None, isolation=None, follow_fedora_branching=True, - fedora_review=None, appstream=False, runtime_dependencies=None, packit_forge_projects_allowed=None): + fedora_review=None, appstream=False, runtime_dependencies=None, packit_forge_projects_allowed=None, + repo_priority=None): """ Create a project @@ -139,6 +140,7 @@ def add(self, ownername, projectname, chroots, description=None, instructions=No "appstream": appstream, "runtime_dependencies": runtime_dependencies, "packit_forge_projects_allowed": packit_forge_projects_allowed, + "repo_priority": repo_priority, } _compat_use_bootstrap_container(data, use_bootstrap_container) @@ -157,7 +159,8 @@ def edit(self, ownername, projectname, chroots=None, description=None, instructi auto_prune=None, use_bootstrap_container=None, devel_mode=None, delete_after_days=None, multilib=None, module_hotfixes=None, bootstrap=None, bootstrap_image=None, isolation=None, follow_fedora_branching=None, - fedora_review=None, appstream=None, runtime_dependencies=None, packit_forge_projects_allowed=None): + fedora_review=None, appstream=None, runtime_dependencies=None, packit_forge_projects_allowed=None, + repo_priority=None): """ Edit a project @@ -223,6 +226,7 @@ def edit(self, ownername, projectname, chroots=None, description=None, instructi "appstream": appstream, "runtime_dependencies": runtime_dependencies, "packit_forge_projects_allowed": packit_forge_projects_allowed, + "repo_priority": repo_priority, } _compat_use_bootstrap_container(data, use_bootstrap_container) diff --git a/rpmbuild/copr_rpmbuild/builders/mock.py b/rpmbuild/copr_rpmbuild/builders/mock.py index 003a79eef..97622baf6 100644 --- a/rpmbuild/copr_rpmbuild/builders/mock.py +++ b/rpmbuild/copr_rpmbuild/builders/mock.py @@ -27,6 +27,11 @@ def __init__(self, task, sourcedir, resultdir, config): self.buildroot_pkgs = task.get("buildroot_pkgs") self.enable_net = task.get("enable_net") self.repos = task.get("repos") + if self.repos and task.get("repo_priority") is not None: + repo_priority = task.get("repo_priority") + for repo in self.repos: + repo["priority"] = repo_priority + self.bootstrap = task.get("bootstrap") self.bootstrap_image = task.get("bootstrap_image") self.timeout = task.get("timeout", 3600)