Skip to content
Open
Show file tree
Hide file tree
Changes from 4 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
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
28 changes: 19 additions & 9 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), yaml_type='rt')),
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 All @@ -584,7 +585,9 @@ def save(self, run: 'Run') -> None:
),
plans=[_RecipePlan.from_plan(plan) for plan in run.plans],
)
self.write(run.run_workdir / 'recipe.yaml', tmt.utils.to_yaml(recipe.to_spec()))
self.write(
run.run_workdir / 'recipe.yaml', tmt.utils.to_yaml(recipe.to_spec(), yaml_type='rt')
)
Comment thread
LecrisUT marked this conversation as resolved.
Outdated

def tests(self, recipe: Recipe, plan_name: str) -> list[TestOrigin]:
"""
Expand All @@ -603,12 +606,19 @@ 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 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})
root = str(Path.cwd())
fmf_tree.root = root
for node in fmf_tree.climb(): # pyright: ignore[reportUnknownVariableType]
if isinstance(node, fmf.Tree):
node.root = root
run._tree = Tree(logger=run._logger, tree=fmf_tree)

def _update_cli_context(self, recipe: Recipe) -> None:
"""
Expand Down
32 changes: 30 additions & 2 deletions tmt/steps/report/reportportal.py
Comment thread
tcornell-bus marked this conversation as resolved.
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, Optional, Union, overload
from typing import TYPE_CHECKING, Any, Callable, Optional, Union, cast, overload

import requests
import urllib3
Expand All @@ -14,8 +14,9 @@
import tmt.utils.templates
from tmt._compat.pathlib import Path
from tmt.base.core import Test
from tmt.container import container, field
from tmt.container import container, field, option_to_key
from tmt.result import Result, ResultOutcome
from tmt.steps import _RawStepData
from tmt.utils import (
ActionType,
catch_warnings_safe,
Expand Down Expand Up @@ -380,6 +381,33 @@ 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