Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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 spec/recipe.fmf
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,8 @@ description: |
how: tmt
order: 50
...
# String, relative path to the results file from the previous run
results-path: plans/name/execute/results.yaml
# String, absolute path to the results file from the previous run
results-path: /var/tmp/tmt/run-001/plans/name/execute/results.yaml
Comment thread
LecrisUT marked this conversation as resolved.
Outdated

report:
enabled: true
Expand Down
2 changes: 1 addition & 1 deletion tests/recipe/data/import.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ plans:
execute:
enabled: false
phases: []
results-path: plans/import/execute/results.yaml
results-path: /run_path/plans/import/execute/results.yaml
report:
enabled: false
phases: []
Expand Down
2 changes: 1 addition & 1 deletion tests/recipe/data/insert.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ plans:
interactive: false
restraint-compatible: false
no-progress-bar: false
results-path: plans/insert/execute/results.yaml
results-path: /run_path/plans/insert/execute/results.yaml
report:
enabled: true
phases:
Expand Down
2 changes: 1 addition & 1 deletion tests/recipe/data/local.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ plans:
interactive: false
restraint-compatible: false
no-progress-bar: false
results-path: plans/local/execute/results.yaml
results-path: /run_path/plans/local/execute/results.yaml
report:
enabled: true
phases:
Expand Down
2 changes: 1 addition & 1 deletion tests/recipe/data/remote.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ plans:
interactive: false
restraint-compatible: false
no-progress-bar: false
results-path: plans/remote/execute/results.yaml
results-path: /run_path/plans/remote/execute/results.yaml
report:
enabled: true
phases:
Expand Down
1 change: 1 addition & 0 deletions tests/recipe/generate.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ rlJournalStart
function replace_values () {
temp_recipe=$(mktemp)
yq '.run.root = "/path/to/fmf_root"' "$recipe" > "$temp_recipe"
sed -i "s#$run#/run_path#g" "$temp_recipe"
mv "$temp_recipe" "$recipe"
}

Expand Down
2 changes: 1 addition & 1 deletion tmt/base/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -2924,7 +2924,7 @@ def __init__(
self.recipe_manager = RecipeManager(logger)
self.recipe = None
if recipe_path is not None and self._tree is not None:
Comment thread
therazix marked this conversation as resolved.
Outdated
self.recipe = self.recipe_manager.load(self, recipe_path, self._tree.tree)
self.recipe = self.recipe_manager.load(self, recipe_path)

@property
def run_workdir(self) -> Path:
Expand Down
27 changes: 18 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 @@ -368,7 +368,7 @@ def from_step(cls, step: 'Step') -> '_RecipeExecuteStep':
return _RecipeExecuteStep(
enabled=enabled,
phases=[phase.to_minimal_spec() for phase in step.data] if enabled else [],
results_path=(step.step_workdir / 'results.yaml').relative_to(step.run_workdir),
results_path=(step.step_workdir / 'results.yaml').resolve(),
)

def to_fmf_spec(self) -> list[_RawStepData]:
Expand Down Expand Up @@ -562,11 +562,11 @@ 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
)
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 +584,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.

def tests(self, recipe: Recipe, plan_name: str) -> list[TestOrigin]:
"""
Expand All @@ -603,12 +605,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
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if this PR is supposed to fix this or not, but I did a tmt run with report --how reportportal --project <my_project> and it made the recipe.yaml file with the key/values in the to_spec()\to_minimal_spec() functions. Then I tried loading that same recipe file (in the fmf root directory), and I got an exception:

/plans/all
summary: Run all tests

plan failed.

The exception was caused by 1 earlier exceptions

Cause number 1:

    cannot represent an object: {1: '<some-hash>'}

Where {1: '<some-hash>'} is the reportportal test-uuids value.

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