mirror of
https://pagure.io/fm-orchestrator.git
synced 2026-02-02 20:59:06 +08:00
Allow specifying a specific module build to reuse components from
This resolves #1296.
This commit is contained in:
@@ -128,6 +128,8 @@ Options:
|
||||
rebuilt). For the available options, please look at the "Rebuild Strategies" section below.
|
||||
- ``require_overrides`` - the requires to override the modulemd with. The overrides must be to
|
||||
existing requires on the modulemd. The expected format is ``{'platform': ['f28', 'f29']}``.
|
||||
- ``reuse_components_from`` - the ID or NSVC of the module build to reuse components from. If it's
|
||||
not set, MBS will try to find a compatible module build to reuse components from.
|
||||
- ``scratch`` - a boolean indicating if a scratch module build should be performed.
|
||||
Only allowed to be ``True`` if the MBS setting ``MODULES_ALLOW_SCRATCH`` is ``True``.
|
||||
- ``srpms`` - an optional list of Koji upload URLs of SRPMs to include in a module scratch build.
|
||||
@@ -357,6 +359,7 @@ parameters::
|
||||
"modulemd": "...."
|
||||
"name": "testmodule",
|
||||
"owner": "mprahl",
|
||||
"reused_module_id": 121,
|
||||
"scmurl": "https://src.fedoraproject.org/modules/testmodule.git?#86d9cfe53d20118d863ae051641fc3784d91d981",
|
||||
"state": 5,
|
||||
"state_name": "ready",
|
||||
@@ -479,6 +482,7 @@ parameters include:
|
||||
- ``new_repo_task_id``
|
||||
- ``owner``
|
||||
- ``rebuild_strategy``
|
||||
- ``reuse_components_from`` - the compatible module that was used for component reuse
|
||||
- ``scmurl``
|
||||
- ``state`` - Can be the state name or the state ID e.g. ``state=done``. This
|
||||
parameter can be given multiple times, in which case or-ing will be used.
|
||||
|
||||
@@ -75,6 +75,9 @@ module with the following requirements:
|
||||
Additionally, if the rebuild strategy for the module being built is ``changed-and-after``, then the
|
||||
module to reuse components from will have a rebuild strategy of ``changed-and-after`` or ``all``.
|
||||
|
||||
If the user wants to specify the compatible module, they can use the ``reuse_components_from``
|
||||
parameter.
|
||||
|
||||
|
||||
How the Rebuild Strategies Work
|
||||
===============================
|
||||
|
||||
@@ -877,6 +877,7 @@ class ModuleBuild(MBSBase):
|
||||
"build_context": self.build_context,
|
||||
"modulemd": self.modulemd,
|
||||
"ref_build_context": self.ref_build_context,
|
||||
"reused_module_id": self.reused_module_id,
|
||||
"runtime_context": self.runtime_context,
|
||||
"state_trace": [
|
||||
{
|
||||
|
||||
@@ -1014,6 +1014,7 @@ def submit_module_build(username, mmd, params):
|
||||
scmurl=params.get("scmurl"),
|
||||
username=username,
|
||||
rebuild_strategy=params.get("rebuild_strategy"),
|
||||
reused_module_id=params.get("reuse_components_from"),
|
||||
scratch=params.get("scratch"),
|
||||
srpms=params.get("srpms"),
|
||||
)
|
||||
|
||||
@@ -305,6 +305,7 @@ class BaseHandler(object):
|
||||
"module_name",
|
||||
"owner",
|
||||
"rebuild_strategy",
|
||||
"reuse_components_from",
|
||||
"require_overrides",
|
||||
"scmurl",
|
||||
"scratch",
|
||||
@@ -382,6 +383,40 @@ class BaseHandler(object):
|
||||
self._validate_dep_overrides_format("buildrequire_overrides")
|
||||
self._validate_dep_overrides_format("require_overrides")
|
||||
|
||||
if "reuse_components_from" in self.data:
|
||||
if "rebuild_strategy" in self.data and self.data["rebuild_strategy"] == "all":
|
||||
raise ValidationError(
|
||||
'You cannot specify the parameter "reuse_components_from" when the '
|
||||
'"rebuild_strategy" parameter is set to "all"'
|
||||
)
|
||||
|
||||
invalid_identifier_msg = (
|
||||
'The parameter "reuse_components_from" contains an invalid module identifier')
|
||||
|
||||
if isinstance(self.data["reuse_components_from"], int):
|
||||
reuse_module = models.ModuleBuild.get_by_id(
|
||||
db.session, self.data["reuse_components_from"])
|
||||
elif isinstance(self.data["reuse_components_from"], string_types):
|
||||
try:
|
||||
n, s, v, c = self.data["reuse_components_from"].split(":")
|
||||
except ValueError:
|
||||
raise ValidationError(invalid_identifier_msg)
|
||||
reuse_module = models.ModuleBuild.get_build_from_nsvc(db.session, n, s, v, c)
|
||||
else:
|
||||
raise ValidationError(invalid_identifier_msg)
|
||||
|
||||
if not reuse_module:
|
||||
raise ValidationError(
|
||||
'The module in the parameter "reuse_components_from" could not be found')
|
||||
|
||||
if reuse_module.state != models.BUILD_STATES["ready"]:
|
||||
raise ValidationError(
|
||||
'The module in the parameter "reuse_components_from" must be in the ready state'
|
||||
)
|
||||
|
||||
# Normalize the value so that it simplifies any code that uses this value
|
||||
self.data["reuse_components_from"] = reuse_module.id
|
||||
|
||||
|
||||
class SCMHandler(BaseHandler):
|
||||
def validate(self, skip_branch=False, skip_optional_params=False):
|
||||
|
||||
@@ -31,6 +31,7 @@ from os import path, mkdir
|
||||
from os.path import basename, dirname, splitext
|
||||
from requests.utils import quote
|
||||
import hashlib
|
||||
import koji
|
||||
import pytest
|
||||
import re
|
||||
import sqlalchemy
|
||||
@@ -39,7 +40,7 @@ from tests import app, init_data, clean_database, reuse_component_init_data, sta
|
||||
from tests import read_staged_data
|
||||
from tests.test_scm import base_dir as scm_base_dir
|
||||
from module_build_service.errors import UnprocessableEntity
|
||||
from module_build_service.models import ModuleBuild
|
||||
from module_build_service.models import ModuleBuild, BUILD_STATES
|
||||
from module_build_service import db, version
|
||||
import module_build_service.config as mbs_config
|
||||
import module_build_service.scheduler.handlers.modules
|
||||
@@ -207,6 +208,7 @@ class TestViews:
|
||||
assert data["name"] == "nginx"
|
||||
assert data["owner"] == "Moe Szyslak"
|
||||
assert data["rebuild_strategy"] == "changed-and-after"
|
||||
assert data["reused_module_id"] is None
|
||||
assert data["scmurl"] == \
|
||||
"git://pkgs.domain.local/modules/nginx?#ba95886c7a443b36a9ce31abda1f9bef22f2f8c9"
|
||||
assert data["scratch"] is False
|
||||
@@ -2592,3 +2594,112 @@ class TestViews:
|
||||
mock_get.assert_called_once_with(expected_url, timeout=15)
|
||||
else:
|
||||
mock_get.assert_not_called()
|
||||
|
||||
@pytest.mark.parametrize("reuse_components_from", (7, "testmodule:4.3.43:7:00000000"))
|
||||
@patch("module_build_service.auth.get_user", return_value=user)
|
||||
@patch("module_build_service.scm.SCM")
|
||||
def test_submit_build_reuse_components_from(
|
||||
self, mocked_scm, mocked_get_user, reuse_components_from,
|
||||
):
|
||||
"""Test a build submission using the reuse_components_from parameter."""
|
||||
module_to_reuse = db.session.query(ModuleBuild).get(7)
|
||||
module_to_reuse.state = BUILD_STATES["ready"]
|
||||
for c in module_to_reuse.component_builds:
|
||||
c.state = koji.BUILD_STATES["COMPLETE"]
|
||||
db.session.commit()
|
||||
|
||||
FakeSCM(
|
||||
mocked_scm, "testmodule", "testmodule.yaml", "620ec77321b2ea7b0d67d82992dda3e1d67055b4")
|
||||
rv = self.client.post(
|
||||
"/module-build-service/1/module-builds/",
|
||||
data=json.dumps({
|
||||
"branch": "master",
|
||||
"reuse_components_from": reuse_components_from,
|
||||
"scmurl": (
|
||||
"https://src.stg.fedoraproject.org/modules/testmodule.git?"
|
||||
"#68931c90de214d9d13feefbd35246a81b6cb8d49"
|
||||
),
|
||||
}),
|
||||
)
|
||||
data = json.loads(rv.data)
|
||||
assert data["reused_module_id"] == 7
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"reuse_components_from, expected_error",
|
||||
(
|
||||
(
|
||||
"testmodule:4.3.43:7",
|
||||
'The parameter "reuse_components_from" contains an invalid module identifier',
|
||||
),
|
||||
(
|
||||
{},
|
||||
'The parameter "reuse_components_from" contains an invalid module identifier',
|
||||
),
|
||||
(
|
||||
912312312,
|
||||
'The module in the parameter "reuse_components_from" could not be found',
|
||||
),
|
||||
(
|
||||
7,
|
||||
'The module in the parameter "reuse_components_from" must be in the ready state',
|
||||
)
|
||||
)
|
||||
)
|
||||
@patch("module_build_service.auth.get_user", return_value=user)
|
||||
@patch("module_build_service.scm.SCM")
|
||||
def test_submit_build_reuse_components_from_errors(
|
||||
self, mocked_scm, mocked_get_user, reuse_components_from, expected_error,
|
||||
):
|
||||
"""
|
||||
Test a build submission using an invalid value for the reuse_components_from parameter.
|
||||
"""
|
||||
FakeSCM(
|
||||
mocked_scm, "testmodule", "testmodule.yaml", "620ec77321b2ea7b0d67d82992dda3e1d67055b4")
|
||||
rv = self.client.post(
|
||||
"/module-build-service/1/module-builds/",
|
||||
data=json.dumps({
|
||||
"branch": "master",
|
||||
"reuse_components_from": reuse_components_from,
|
||||
"scmurl": (
|
||||
"https://src.stg.fedoraproject.org/modules/testmodule.git?"
|
||||
"#68931c90de214d9d13feefbd35246a81b6cb8d49"
|
||||
),
|
||||
}),
|
||||
)
|
||||
data = json.loads(rv.data)
|
||||
assert rv.status_code == 400
|
||||
assert data["message"] == expected_error
|
||||
|
||||
@patch("module_build_service.auth.get_user", return_value=user)
|
||||
@patch("module_build_service.scm.SCM")
|
||||
@patch(
|
||||
"module_build_service.config.Config.rebuild_strategy_allow_override",
|
||||
new_callable=PropertyMock,
|
||||
return_value=True,
|
||||
)
|
||||
def test_submit_build_reuse_components_rebuild_strategy_all(
|
||||
self, mock_rsao, mocked_scm, mocked_get_user,
|
||||
):
|
||||
"""
|
||||
Test a build submission using reuse_components_from and the rebuild_strategy of all.
|
||||
"""
|
||||
FakeSCM(
|
||||
mocked_scm, "testmodule", "testmodule.yaml", "620ec77321b2ea7b0d67d82992dda3e1d67055b4")
|
||||
rv = self.client.post(
|
||||
"/module-build-service/1/module-builds/",
|
||||
data=json.dumps({
|
||||
"branch": "master",
|
||||
"rebuild_strategy": "all",
|
||||
"reuse_components_from": 7,
|
||||
"scmurl": (
|
||||
"https://src.stg.fedoraproject.org/modules/testmodule.git?"
|
||||
"#68931c90de214d9d13feefbd35246a81b6cb8d49"
|
||||
),
|
||||
}),
|
||||
)
|
||||
data = json.loads(rv.data)
|
||||
assert rv.status_code == 400
|
||||
assert data["message"] == (
|
||||
'You cannot specify the parameter "reuse_components_from" when the "rebuild_strategy" '
|
||||
'parameter is set to "all"'
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user