Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions tests/recipe/load.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,15 @@ rlJournalStart
rlRun "pushd data"
rlPhaseEnd

function replace_fmf_root () {
local recipe=$1
local temp_recipe=$(mktemp)
yq ".run.root = \"$PWD\"" "$recipe" > "$temp_recipe"
mv "$temp_recipe" "$recipe"
}

rlPhaseStartTest "Test recipe loading with library dependencies"
replace_fmf_root "local.yaml"
rlRun -s "tmt run -vvv --scratch --id $run --recipe local.yaml"
rlAssertGrep "name: discover-fmf" $rlRun_LOG
rlAssertGrep "name: discover-shell" $rlRun_LOG
Expand All @@ -24,6 +32,7 @@ rlJournalStart
rlPhaseEnd

rlPhaseStartTest "Test recipe loading with remote repository"
replace_fmf_root "remote.yaml"
rlRun -s "tmt run -vvv --scratch --id $run --recipe remote.yaml"
rlAssertGrep "summary: 1 test selected" $rlRun_LOG
rlAssertGrep "pass /tests/one" $rlRun_LOG
Expand All @@ -32,6 +41,7 @@ rlJournalStart
rlPhaseEnd

rlPhaseStartTest "Test recipe loading of imported plan"
replace_fmf_root "import.yaml"
rlRun -s "tmt run -vvv --scratch --id $run --recipe import.yaml"
rlAssertGrep "summary: 2 tests selected" $rlRun_LOG
rlPhaseEnd
Expand Down
4 changes: 2 additions & 2 deletions tmt/base/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -2923,8 +2923,8 @@ def __init__(
self.policies = policies or []
self.recipe_manager = RecipeManager(logger)
self.recipe = None
if recipe_path is not None and self._tree is not None:
self.recipe = self.recipe_manager.load(self, recipe_path, self._tree.tree)
if recipe_path is not None:
self.recipe = self.recipe_manager.load(self, recipe_path)

@property
def run_workdir(self) -> Path:
Expand Down
23 changes: 15 additions & 8 deletions tmt/recipe.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from typing import TYPE_CHECKING, Any, Callable, Optional, TypedDict, cast

from fmf import Tree
import fmf

import tmt.utils
from tmt.checks import Check, _RawCheck, normalize_test_checks
Expand Down Expand Up @@ -562,11 +562,12 @@ class RecipeManager(Common):
def __init__(self, logger: Logger):
super().__init__(logger=logger)

def load(self, run: 'Run', recipe_path: Path, fmf_tree: Tree) -> Recipe:
def load(self, run: 'Run', recipe_path: Path) -> Recipe:
recipe = Recipe.from_spec(
cast(_RawRecipe, tmt.utils.yaml_to_dict(self.read(recipe_path))), self._logger
cast(_RawRecipe, tmt.utils.yaml_to_dict(self.read(recipe_path))),
self._logger,
)
self._update_tree(recipe, fmf_tree)
self._update_tree(run, recipe)
# TODO: We should have a way to set which steps are enabled
# without modifying the CLI context directly.
self._update_cli_context(recipe)
Expand Down Expand Up @@ -603,12 +604,18 @@ def tests(self, recipe: Recipe, plan_name: str) -> list[TestOrigin]:
raise tmt.utils.GeneralError(f"Plan '{plan_name}' not found in the recipe.")

@staticmethod
def _update_tree(recipe: Recipe, tree: Tree) -> None:
def _update_tree(run: 'Run', recipe: Recipe) -> None:
"""
Load the plans from the recipe and update the given fmf tree with their specifications.
Create a new fmf tree from the recipe's run and plan specifications.
"""
tree.children.clear()
tree.update({plan.name: plan.to_fmf_spec() for plan in recipe.plans})
from tmt.base.core import Tree

fmf_tree = fmf.Tree({plan.name: plan.to_fmf_spec() for plan in recipe.plans})
fmf_tree.root = recipe.run.root
for node in fmf_tree.climb(): # pyright: ignore[reportUnknownVariableType]
if isinstance(node, fmf.Tree):
node.root = recipe.run.root
run._tree = Tree(logger=run._logger, tree=fmf_tree)

def _update_cli_context(self, recipe: Recipe) -> None:
"""
Expand Down
32 changes: 2 additions & 30 deletions tmt/steps/report/reportportal.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import os
import re
from re import Pattern
from typing import TYPE_CHECKING, Any, Callable, Optional, Union, cast, overload
from typing import TYPE_CHECKING, Any, Optional, Union, overload

import requests
import urllib3
Expand All @@ -14,9 +14,8 @@
import tmt.utils.templates
from tmt._compat.pathlib import Path
from tmt.base.core import Test
from tmt.container import container, field, option_to_key
from tmt.container import container, field
from tmt.result import Result, ResultOutcome
from tmt.steps import _RawStepData
from tmt.utils import (
ActionType,
catch_warnings_safe,
Expand Down Expand Up @@ -381,33 +380,6 @@ class ReportReportPortalData(tmt.steps.report.ReportStepData):
suite_uuid: Optional[str] = None
test_uuids: dict[int, str] = field(default_factory=dict)

def to_spec(self) -> _RawStepData:
spec = super().to_spec()
spec['log-size-limit'] = str(self.log_size_limit) # type: ignore[reportGeneralTypeIssues,typeddict-unknown-key,unused-ignore]
spec['traceback-size-limit'] = str(self.traceback_size_limit) # type: ignore[reportGeneralTypeIssues,typeddict-unknown-key,unused-ignore]
spec['upload-log-pattern'] = [pattern.pattern for pattern in self.upload_log_pattern] # type: ignore[reportGeneralTypeIssues,typeddict-unknown-key,unused-ignore]
return spec

def to_minimal_spec(self) -> _RawStepData:
spec = {**super().to_minimal_spec()}

field_map: dict[str, Callable[[Any], Any]] = {
'log-size-limit': lambda limit: str(limit),
'traceback-size-limit': lambda limit: str(limit),
'upload-log-pattern': lambda patterns: [pattern.pattern for pattern in patterns],
}
for key, transform in field_map.items():
value = getattr(self, option_to_key(key), None)
if value is not None:
value = transform(value)
# Do not include empty values
if value in (None, [], {}):
spec.pop(key, None)
else:
spec[key] = value

return cast(_RawStepData, spec)


@tmt.steps.provides_method("reportportal")
class ReportReportPortal(tmt.steps.report.ReportPlugin[ReportReportPortalData]):
Expand Down
Loading