Store the build_context without base modules in a database.

For KojiResolver, we need to be able to find out the module to reuse
components from based only on the non-base-module buildrequires. The
base module buildrequirement will be defined by the Koji tag inheritance.

For this, we need to store build_context computed without the base
modules.
This commit is contained in:
Jan Kaluza
2019-10-01 13:28:31 +02:00
parent d4b7a019c7
commit fc39df9487
4 changed files with 71 additions and 6 deletions

View File

@@ -0,0 +1,56 @@
"""Add build_context_no_bms
Revision ID: a97269751cb4
Revises: f87d25079115
Create Date: 2019-10-01 13:59:48.947851
"""
# revision identifiers, used by Alembic.
revision = "a87264eeb49f"
down_revision = "1817e62719f9"
from alembic import op
import sqlalchemy as sa
from module_build_service import Modulemd
from module_build_service.models import ModuleBuild
modulebuild = sa.Table(
"module_builds",
sa.MetaData(),
sa.Column("id", sa.Integer, primary_key=True),
sa.Column("modulemd", sa.String()),
sa.Column("build_context_no_bms", sa.String()),
)
def upgrade():
connection = op.get_bind()
op.add_column("module_builds", sa.Column("build_context_no_bms", sa.String(), nullable=True))
# Determine what the contexts should be based on the modulemd
for build in connection.execute(modulebuild.select()):
if not build.modulemd:
continue
try:
mmd = Modulemd.ModuleStream.read_string(build.modulemd, True)
mmd = mmd.upgrade(Modulemd.ModuleStreamVersionEnum.TWO)
except Exception:
# If the modulemd isn"t parseable then skip this build
continue
# It's possible this module build was built before MBS filled out xmd or before MBS
# filled out the requires in xmd
mbs_xmd_buildrequires = mmd.get_xmd().get("mbs", {}).get("buildrequires")
if not mbs_xmd_buildrequires:
continue
build_context_no_bms = ModuleBuild.calculate_build_context(mbs_xmd_buildrequires, True)
connection.execute(
modulebuild.update().where(modulebuild.c.id == build.id).values(
build_context_no_bms=build_context_no_bms))
def downgrade():
with op.batch_alter_table("module_builds", schema=None) as batch_op:
batch_op.drop_column("build_context_no_bms")

View File

@@ -86,7 +86,8 @@ INVERSE_BUILD_STATES = {v: k for k, v in BUILD_STATES.items()}
FAILED_STATES = (BUILD_STATES["failed"], BUILD_STATES["garbage"])
Contexts = namedtuple("Contexts", "build_context runtime_context context")
Contexts = namedtuple(
"Contexts", "build_context runtime_context context build_context_no_bms")
def _utc_datetime_to_iso(datetime_object):
@@ -257,6 +258,7 @@ class ModuleBuild(MBSBase):
stream = db.Column(db.String, nullable=False)
version = db.Column(db.String, nullable=False)
build_context = db.Column(db.String)
build_context_no_bms = db.Column(db.String)
runtime_context = db.Column(db.String)
context = db.Column(db.String, nullable=False, server_default=DEFAULT_MODULE_CONTEXT)
state = db.Column(db.Integer, nullable=False)
@@ -647,24 +649,30 @@ class ModuleBuild(MBSBase):
mmd_deps = mmd.get_dependencies()
build_context = cls.calculate_build_context(mbs_xmd_buildrequires)
build_context_no_bms = cls.calculate_build_context(mbs_xmd_buildrequires, True)
runtime_context = cls.calculate_runtime_context(mmd_deps)
return Contexts(
build_context,
runtime_context,
cls.calculate_module_context(build_context, runtime_context)
cls.calculate_module_context(build_context, runtime_context),
build_context_no_bms
)
@staticmethod
def calculate_build_context(mbs_xmd_buildrequires):
def calculate_build_context(mbs_xmd_buildrequires, filter_base_modules=False):
"""
Returns the hash of stream names of expanded buildrequires
:param mbs_xmd_buildrequires: xmd["mbs"]["buildrequires"] from Modulemd
:param bool filter_base_modules: When True, base modules are not used to compute
the build context.
:rtype: str
:return: build_context hash
"""
deps_to_filter = conf.base_module_names if filter_base_modules else []
mmd_formatted_buildrequires = {
dep: info["stream"] for dep, info in mbs_xmd_buildrequires.items()
if dep not in deps_to_filter
}
property_json = json.dumps(OrderedDict(sorted(mmd_formatted_buildrequires.items())))
return hashlib.sha1(property_json.encode("utf-8")).hexdigest()

View File

@@ -1030,8 +1030,8 @@ def submit_module_build(db_session, username, mmd, params):
scratch=params.get("scratch"),
srpms=params.get("srpms"),
)
module.build_context, module.runtime_context, module.context = \
module.contexts_from_mmd(module.modulemd)
module.build_context, module.runtime_context, module.context, \
module.build_context_no_bms = module.contexts_from_mmd(module.modulemd)
module.context += context_suffix
all_modules_skipped = False

View File

@@ -67,11 +67,12 @@ class TestModels:
build = ModuleBuild.get_by_id(db_session, 1)
db_session.commit()
build.modulemd = read_staged_data("testmodule_dependencies")
build.build_context, build.runtime_context, build.context = \
build.build_context, build.runtime_context, build.context, build.build_context_no_bms = \
ModuleBuild.contexts_from_mmd(build.modulemd)
assert build.build_context == "089df24993c037e10174f3fa7342ab4dc191a4d4"
assert build.runtime_context == "bbc84c7b817ab3dd54916c0bcd6c6bdf512f7f9c"
assert build.context == "3ee22b28"
assert build.build_context_no_bms == "089df24993c037e10174f3fa7342ab4dc191a4d4"
def test_siblings_property(self, db_session):
""" Tests that the siblings property returns the ID of all modules with