This is an automated email from the git hooks/post-receive script.
praiskup pushed a commit to branch master
in repository copr/copr.
commit ddb706f92838dd167658be549761c71e00b2652e
Author: Tomas Hrnciar <thrnciar(a)redhat.com>
AuthorDate: Sun Jan 26 21:25:45 2020 +0100
frontend: module enable option for chroot settings
Merges: #1237
---
...7ba91dda3e3_add_module_toggle_to_copr_chroot.py | 20 ++++++++++
frontend/coprs_frontend/coprs/forms.py | 43 ++++++++++++++++++++++
frontend/coprs_frontend/coprs/logic/coprs_logic.py | 13 ++++---
frontend/coprs_frontend/coprs/models.py | 12 ++++++
.../coprs/templates/coprs/detail/edit_chroot.html | 8 ++++
.../coprs/views/backend_ns/backend_general.py | 9 ++++-
.../coprs/views/coprs_ns/coprs_chroots.py | 6 ++-
.../tests/test_logic/test_coprs_logic.py | 25 ++++++++++++-
.../test_backend_ns/test_backend_general.py | 30 ++++++++++++++-
9 files changed, 156 insertions(+), 10 deletions(-)
diff --git
a/frontend/coprs_frontend/alembic/schema/versions/67ba91dda3e3_add_module_toggle_to_copr_chroot.py
b/frontend/coprs_frontend/alembic/schema/versions/67ba91dda3e3_add_module_toggle_to_copr_chroot.py
new file mode 100644
index 0000000..904338b
--- /dev/null
+++
b/frontend/coprs_frontend/alembic/schema/versions/67ba91dda3e3_add_module_toggle_to_copr_chroot.py
@@ -0,0 +1,20 @@
+"""
+add module_toggle to copr_chroot
+
+Revision ID: 67ba91dda3e3
+Revises: 2561c13a3556
+Create Date: 2020-01-17 10:48:22.092706
+"""
+
+import sqlalchemy as sa
+from alembic import op
+
+
+revision = '67ba91dda3e3'
+down_revision = '2561c13a3556'
+
+def upgrade():
+ op.add_column('copr_chroot', sa.Column('module_toggle', sa.Text(),
nullable=True))
+
+def downgrade():
+ op.drop_column('copr_chroot', 'module_toggle')
diff --git a/frontend/coprs_frontend/coprs/forms.py
b/frontend/coprs_frontend/coprs/forms.py
index a05fb53..58b9b18 100644
--- a/frontend/coprs_frontend/coprs/forms.py
+++ b/frontend/coprs_frontend/coprs/forms.py
@@ -22,6 +22,7 @@ from coprs.logic.users_logic import UsersLogic
from coprs.logic.dist_git_logic import DistGitLogic
from coprs import exceptions
+from wtforms import ValidationError
FALSE_VALUES = {False, "false", ""}
@@ -165,6 +166,32 @@ class NameCharactersValidator(object):
message=self.message)
validator(form, field)
+class ModuleEnableNameValidator(object):
+
+ def __call__(self, form, field):
+ for module in form.module_toggle.data.split(","):
+ if module == "":
+ return True
+
+ try:
+ module_name, stream = module.strip().split(":")
+ except ValueError:
+ raise ValidationError(
+ message="Module name '{0}' must consist of two parts
separated with colon.\
+ Eg. module:stream"
+ .format(module))
+
+ pattern = re.compile(re.compile(r"^([a-zA-Z0-9-_!][^\ ]*)$"))
+ if pattern.match(module_name) == None:
+ raise ValidationError(
+ message="Module name '{0}' must contain only letters,
digits, dashes, underscores."
+ .format(module_name))
+
+ if pattern.match(stream) == None:
+ raise ValidationError(
+ message="Stream part of module name '{0}' must contain
only letters,\
+ digits, dashes, underscores."
+ .format(stream))
class ChrootsValidator(object):
def __call__(self, form, field):
@@ -220,6 +247,17 @@ class StringListFilter(object):
regex = re.compile(r"\s+")
return regex.sub(lambda x: '\n', result)
+class StringWhiteCharactersFilter(object):
+
+ def __call__(self, value):
+ if not value:
+ return ''
+
+ modules = [module.strip() for module in value.split(",")]
+ # to remove empty strings
+ modules = [m for m in modules if m]
+
+ return ", ".join(module for module in modules if module !=
"")
class ValueToPermissionNumberFilter(object):
@@ -1006,6 +1044,11 @@ class ChrootForm(FlaskForm):
comps = FileField("comps_xml")
+ module_toggle = wtforms.StringField("Enable module",
+ validators=[ModuleEnableNameValidator()],
+ filters=[StringWhiteCharactersFilter()]
+ )
+
with_opts = wtforms.StringField("With options")
without_opts = wtforms.StringField("Without options")
diff --git a/frontend/coprs_frontend/coprs/logic/coprs_logic.py
b/frontend/coprs_frontend/coprs/logic/coprs_logic.py
index 7d8a525..d53cbbf 100644
--- a/frontend/coprs_frontend/coprs/logic/coprs_logic.py
+++ b/frontend/coprs_frontend/coprs/logic/coprs_logic.py
@@ -632,7 +632,7 @@ class CoprChrootsLogic(object):
@classmethod
def create_chroot(cls, user, copr, mock_chroot, buildroot_pkgs=None, repos=None,
comps=None, comps_name=None,
with_opts="", without_opts="",
- delete_after=None, delete_notify=None):
+ delete_after=None, delete_notify=None,
module_toggle=""):
"""
:type user: models.User
:type mock_chroot: models.MockChroot
@@ -647,12 +647,12 @@ class CoprChrootsLogic(object):
chroot = models.CoprChroot(copr=copr, mock_chroot=mock_chroot)
cls._update_chroot(buildroot_pkgs, repos, comps, comps_name, chroot,
- with_opts, without_opts, delete_after, delete_notify)
+ with_opts, without_opts, delete_after, delete_notify,
module_toggle)
return chroot
@classmethod
def update_chroot(cls, user, copr_chroot, buildroot_pkgs=None, repos=None,
comps=None, comps_name=None,
- with_opts="", without_opts="",
delete_after=None, delete_notify=None):
+ with_opts="", without_opts="",
delete_after=None, delete_notify=None, module_toggle=""):
"""
:type user: models.User
:type copr_chroot: models.CoprChroot
@@ -662,12 +662,12 @@ class CoprChrootsLogic(object):
"Only owners and admins may update their projects.")
cls._update_chroot(buildroot_pkgs, repos, comps, comps_name,
- copr_chroot, with_opts, without_opts, delete_after,
delete_notify)
+ copr_chroot, with_opts, without_opts, delete_after,
delete_notify, module_toggle)
return copr_chroot
@classmethod
def _update_chroot(cls, buildroot_pkgs, repos, comps, comps_name,
- copr_chroot, with_opts, without_opts, delete_after,
delete_notify):
+ copr_chroot, with_opts, without_opts, delete_after, delete_notify,
module_toggle):
if buildroot_pkgs is not None:
copr_chroot.buildroot_pkgs = buildroot_pkgs
@@ -691,6 +691,9 @@ class CoprChrootsLogic(object):
if delete_notify is not None:
copr_chroot.delete_notify = delete_notify
+ if module_toggle is not None:
+ copr_chroot.module_toggle = module_toggle
+
db.session.add(copr_chroot)
@classmethod
diff --git a/frontend/coprs_frontend/coprs/models.py
b/frontend/coprs_frontend/coprs/models.py
index c228759..a0b6ca3 100644
--- a/frontend/coprs_frontend/coprs/models.py
+++ b/frontend/coprs_frontend/coprs/models.py
@@ -1282,6 +1282,8 @@ class CoprChroot(db.Model, helpers.Serializer):
comps_zlib = db.Column(db.LargeBinary(), nullable=True)
comps_name = db.Column(db.String(127), nullable=True)
+ module_toggle = db.Column(db.Text, nullable=True)
+
with_opts = db.Column(db.Text, default="", server_default="",
nullable=False)
without_opts = db.Column(db.Text, default="", server_default="",
nullable=False)
@@ -1333,6 +1335,16 @@ class CoprChroot(db.Model, helpers.Serializer):
days = (self.delete_after - now).days
return days if days > 0 else 0
+ @property
+ def module_toggle_array(self):
+ if not self.module_toggle:
+ return []
+ module_enable = []
+ for m in self.module_toggle.split(','):
+ if m[0] != "!":
+ module_enable.append(m)
+ return module_enable
+
def to_dict(self):
options = {"__columns_only__": [
"buildroot_pkgs", "repos", "comps_name",
"copr_id", "with_opts", "without_opts"
diff --git a/frontend/coprs_frontend/coprs/templates/coprs/detail/edit_chroot.html
b/frontend/coprs_frontend/coprs/templates/coprs/detail/edit_chroot.html
index 9585ae1..fb11de2 100644
--- a/frontend/coprs_frontend/coprs/templates/coprs/detail/edit_chroot.html
+++ b/frontend/coprs_frontend/coprs/templates/coprs/detail/edit_chroot.html
@@ -33,6 +33,14 @@
{{ render_field(form.repos, rows=5, cols=50, placeholder='Optional - URL to
additional yum repos, which can be used during build. Space separated. This should be
baseurl from .repo file. E.g.:
http://copr-be.cloud.fedoraproject.org/results/rhughes/f20-gnome-3-12/fed...)
}}
{{ render_field(
+ form.module_toggle,
+ size=80,
+ info='You can specify modules which will be enabled for builds in the given
chroot.',
+ placeholder='module:stream, module1:stream1'
+ )
+ }}
+
+ {{ render_field(
form.with_opts,
size=80,
info='You can specify rpmbuild --with options here for builds in the given
chroot.',
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 42cd1b6..429e9fa 100644
--- a/frontend/coprs_frontend/coprs/views/backend_ns/backend_general.py
+++ b/frontend/coprs_frontend/coprs/views/backend_ns/backend_general.py
@@ -9,7 +9,7 @@ from coprs.logic import actions_logic
from coprs.logic.builds_logic import BuildsLogic
from coprs.logic.complex_logic import ComplexLogic, BuildConfigLogic
from coprs.logic.packages_logic import PackagesLogic
-from coprs.logic.coprs_logic import MockChrootsLogic
+from coprs.logic.coprs_logic import MockChrootsLogic, CoprChrootsLogic
from coprs.exceptions import MalformedArgumentException, ObjectNotFound
from coprs.views import misc
@@ -92,6 +92,12 @@ def get_build_record(task, short=False):
build_record = None
try:
+ copr_chroot = CoprChrootsLogic.get_by_name_safe(task.build.copr,
task.mock_chroot.name)
+ enabled_disabled_modules = []
+ for module in copr_chroot.module_toggle_array:
+ if module:
+ enabled_disabled_modules.append({"enable": module})
+
build_record = {
"task_id": task.task_id,
"build_id": task.build.id,
@@ -114,6 +120,7 @@ def get_build_record(task, short=False):
"package_name": task.build.package.name,
"package_version": task.build.pkg_version,
"uses_devel_repo": task.build.copr.devel_mode,
+ "modules": {'toggle': enabled_disabled_modules},
}
if short:
return build_record
diff --git a/frontend/coprs_frontend/coprs/views/coprs_ns/coprs_chroots.py
b/frontend/coprs_frontend/coprs/views/coprs_ns/coprs_chroots.py
index fe1e08c..cd32db3 100644
--- a/frontend/coprs_frontend/coprs/views/coprs_ns/coprs_chroots.py
+++ b/frontend/coprs_frontend/coprs/views/coprs_ns/coprs_chroots.py
@@ -29,7 +29,8 @@ def render_chroot_edit(copr, chroot_name):
# form = forms.ChrootForm(buildroot_pkgs=copr.buildroot_pkgs(chroot))
form = forms.ChrootForm(buildroot_pkgs=chroot.buildroot_pkgs, repos=chroot.repos,
- with_opts=chroot.with_opts,
without_opts=chroot.without_opts)
+ module_toggle=chroot.module_toggle,
with_opts=chroot.with_opts,
+ without_opts=chroot.without_opts)
# FIXME - test if chroot belongs to copr
if flask.g.user.can_build_in(copr):
return render_template("coprs/detail/edit_chroot.html",
@@ -73,7 +74,8 @@ def process_chroot_update(copr, chroot_name):
form.buildroot_pkgs.data,
form.repos.data,
comps=comps_xml, comps_name=comps_name,
- with_opts=form.with_opts.data, without_opts=form.without_opts.data
+ with_opts=form.with_opts.data, without_opts=form.without_opts.data,
+ module_toggle=form.module_toggle.data
)
elif action == "delete_comps":
diff --git a/frontend/coprs_frontend/tests/test_logic/test_coprs_logic.py
b/frontend/coprs_frontend/tests/test_logic/test_coprs_logic.py
index 5fa758d..97d2eb2 100644
--- a/frontend/coprs_frontend/tests/test_logic/test_coprs_logic.py
+++ b/frontend/coprs_frontend/tests/test_logic/test_coprs_logic.py
@@ -8,7 +8,7 @@ from sqlalchemy import desc
from copr_common.enums import ActionTypeEnum
from coprs import app
-from coprs.forms import PinnedCoprsForm
+from coprs.forms import PinnedCoprsForm, ChrootForm, ModuleEnableNameValidator
from coprs.logic.actions_logic import ActionsLogic
from coprs.logic.coprs_logic import CoprsLogic, CoprChrootsLogic, PinnedCoprsLogic
from coprs.logic.users_logic import UsersLogic
@@ -211,3 +211,26 @@ class TestPinnedCoprsLogic(CoprsTestCase):
ComplexLogic.delete_copr(self.c2, admin_action=True)
assert set(CoprsLogic.get_multiple_by_username(self.u2.name)) == {self.c3}
assert set(PinnedCoprsLogic.get_by_owner(self.u2)) == {pc2}
+
+class TestChrootFormLogic(CoprsTestCase):
+
+ def test_module_toggle_format(self):
+ with app.app_context():
+ form = ChrootForm()
+ form.module_toggle.data = "module:stream"
+ assert form.validate()
+
+ form.module_toggle.data = ""
+ assert form.validate()
+
+ form.module_toggle.data = "module:stream, module1:stream1"
+ assert form.validate()
+
+ form.module_toggle.data = "module"
+ assert False == form.validate()
+
+ form.module_toggle.data = "module 1:stream"
+ assert False == form.validate()
+
+ form.module_toggle.data = "module: stream"
+ assert False == form.validate()
diff --git
a/frontend/coprs_frontend/tests/test_views/test_backend_ns/test_backend_general.py
b/frontend/coprs_frontend/tests/test_views/test_backend_ns/test_backend_general.py
index 9de4667..20f9efb 100644
--- a/frontend/coprs_frontend/tests/test_views/test_backend_ns/test_backend_general.py
+++ b/frontend/coprs_frontend/tests/test_views/test_backend_ns/test_backend_general.py
@@ -1,12 +1,40 @@
import json
-from unittest import mock
+from unittest import mock, skip
from copr_common.enums import BackendResultEnum, StatusEnum
from tests.coprs_test_case import CoprsTestCase, new_app_context
from coprs.logic.builds_logic import BuildsLogic
+class TestGetBuildTask(CoprsTestCase):
+
+ def test_module_name_empty(self, f_users, f_coprs, f_mock_chroots, f_builds, f_db):
+ self.c1.copr_chroots[0].module_toggle = ""
+ r = self.tc.get("/backend/get-build-task/" + str(self.b2.id) +
"-fedora-18-x86_64", headers=self.auth_header).data
+ data = json.loads(r.decode("utf-8"))
+ assert data['modules']['toggle'] == []
+
+ def test_module_name_enable(self, f_users, f_coprs, f_mock_chroots, f_builds, f_db):
+ self.c1.copr_chroots[0].module_toggle = "XXX"
+ r = self.tc.get("/backend/get-build-task/" + str(self.b2.id) +
"-fedora-18-x86_64", headers=self.auth_header).data
+ data = json.loads(r.decode("utf-8"))
+ assert data['modules']['toggle'] == [{'enable':
'XXX'}]
+
+ @skip("Modules disable not implemented yet.")
+ def test_module_name_disable(self, f_users, f_coprs, f_mock_chroots, f_builds,
f_db):
+ self.c1.copr_chroots[0].module_toggle = "!XXX"
+ r = self.tc.get("/backend/get-build-task/" + str(self.b2.id) +
"-fedora-18-x86_64", headers=self.auth_header).data
+ data = json.loads(r.decode("utf-8"))
+ assert data['modules']['toggle'] == [{'disable':
'!XXX'}]
+
+ @skip("Modules disable not implemented yet.")
+ def test_module_name_many_modules(self, f_users, f_coprs, f_mock_chroots, f_builds,
f_db):
+ self.c1.copr_chroots[0].module_toggle = "!XXX,YYY,ZZZ"
+ r = self.tc.get("/backend/get-build-task/" + str(self.b2.id) +
"-fedora-18-x86_64", headers=self.auth_header).data
+ data = json.loads(r.decode("utf-8"))
+ assert data['modules']['toggle'] == [{'disable':
'!XXX'}, {'enable': 'YYY'}, {'enable': 'ZZZ'}]
+
class TestWaitingBuilds(CoprsTestCase):
def test_no_pending_builds(self):
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.