Skip to content

Commit

Permalink
Merge branch 'main' into cpu-stepping
Browse files Browse the repository at this point in the history
  • Loading branch information
happz authored Oct 23, 2024
2 parents fd80b26 + b058850 commit 8c5b9cb
Show file tree
Hide file tree
Showing 12 changed files with 118 additions and 70 deletions.
2 changes: 1 addition & 1 deletion docs/guide.rst
Original file line number Diff line number Diff line change
Expand Up @@ -787,7 +787,7 @@ later using the ``tmt link`` command:

.. code-block:: shell
tmt link verifies:https://issues.redhat.com/browse/YOUR-ISSUE tests/core/smoke
tmt link --link verifies:https://issues.redhat.com/browse/YOUR-ISSUE tests/core/smoke
In order to enable this feature, create a configuration file
``.config/tmt/link.fmf`` and define an ``issue-tracker`` section
Expand Down
4 changes: 4 additions & 0 deletions docs/releases.rst
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ __ https://www.redhat.com/en/technologies/linux-platforms/enterprise-linux/image
The :ref:`/plugins/provision/beaker` provision plugin gains support
for :ref:`cpu.stepping</spec/hardware/cpu>` hardware requirement.

The ``tmt link`` command now supports providing multiple links by
using the ``--link`` option. See the :ref:`link-issues` section
for example usage.


tmt-1.37.0
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand Down
4 changes: 4 additions & 0 deletions tests/link/basic/main.fmf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
summary: Check basic functionality of the tmt link command
description:
Make sure that `tmt test create` and `tmt link` add provided
target link to the test metadata.
35 changes: 35 additions & 0 deletions tests/link/basic/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#!/bin/bash
. /usr/share/beakerlib/beakerlib.sh || exit 1

rlJournalStart
rlPhaseStartSetup
rlRun "tmp=\$(mktemp -d)" 0 "Create a tmp directory"
rlRun "pushd $tmp"
rlRun "tmt init"
rlPhaseEnd

rlPhaseStartTest "Create Test"
rlRun "tmt test create /test/created --template shell --link verifies:/feature/one"
rlRun -s "tmt test show /test/created"
rlAssertGrep "verifies /feature/one" $rlRun_LOG
rlPhaseEnd

rlPhaseStartTest "Existing Test"
rlRun "tmt test create /test/existing --template shell"
rlRun "tmt link /test/existing --link verifies:/feature/two"
rlRun "tmt link /test/existing --link verifies:/feature/three"
rlRun -s "tmt test show /test/existing"
rlAssertGrep "verifies /feature/two" $rlRun_LOG
rlAssertGrep "verifies /feature/three" $rlRun_LOG
rlPhaseEnd

rlPhaseStartTest "No Link Provided"
rlRun -s "tmt link /test/existing" 2
rlAssertGrep "Provide at least one link" $rlRun_LOG
rlPhaseEnd

rlPhaseStartCleanup
rlRun "popd"
rlRun "rm -r $tmp" 0 "Remove the tmp directory"
rlPhaseEnd
rlJournalEnd
23 changes: 16 additions & 7 deletions tmt/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -2242,14 +2242,19 @@ def completion_fish(context: Context, install: bool, **kwargs: Any) -> None:

@main.command(name='link')
@pass_context
@click.argument('link', nargs=1, metavar='[RELATION:]TARGET')
@click.argument('names', nargs=-1, metavar='[TEST|PLAN|STORY]...')
@option(
'--link', 'links', metavar='[RELATION:]TARGET', multiple=True,
help="""
Issue to which tests, plans or stories should be linked.
Can be provided multiple times.
""")
@option(
'--separate', is_flag=True,
help="Create linking separately for multiple passed objects.")
def link(context: Context,
names: list[str],
link: str,
links: list[str],
separate: bool,
) -> None:
"""
Expand All @@ -2268,8 +2273,12 @@ def link(context: Context,
if not tmt_objects:
raise tmt.utils.GeneralError("No test, plan or story found for linking.")

tmt.utils.jira.link(
tmt_objects=tmt_objects,
links=tmt.base.Links(data=link),
separate=separate,
logger=context.obj.logger)
if not links:
raise tmt.utils.GeneralError("Provide at least one link using the '--link' option.")

for link in links:
tmt.utils.jira.link(
tmt_objects=tmt_objects,
links=tmt.base.Links(data=link),
separate=separate,
logger=context.obj.logger)
3 changes: 2 additions & 1 deletion tmt/frameworks/beakerlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ def get_environment_variables(
return Environment({
'BEAKERLIB_DIR': EnvVarValue(invocation.path),
'BEAKERLIB_COMMAND_SUBMIT_LOG': EnvVarValue(
f'bash {invocation.guest.scripts_path / tmt.steps.execute.TMT_FILE_SUBMIT_SCRIPT.source_filename}') # noqa: E501
invocation.guest.scripts_path /
tmt.steps.execute.TMT_FILE_SUBMIT_SCRIPT.source_filename),
})

@classmethod
Expand Down
9 changes: 9 additions & 0 deletions tmt/steps/execute/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,15 @@ def handle_restart(self) -> bool:
else:
self._restart_count += 1

# Even though the reboot was not requested, it might have
# still happened! Imagine a test configuring autoreboot on
# kernel panic plus a test restart. The reboot would happen
# beyond tmt's control, and tmt would try to restart the
# test, but the guest may be still booting. Make sure it's
# alive.
if not self.guest.reconnect():
return False

self.logger.debug(
f"Test restart during test '{self.test}'"
f" with reboot count {self._reboot_count}"
Expand Down
21 changes: 9 additions & 12 deletions tmt/steps/execute/upgrade.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
from tmt.steps.execute import ExecutePlugin
from tmt.steps.execute.internal import ExecuteInternal, ExecuteInternalData
from tmt.steps.prepare import PreparePlugin
from tmt.steps.prepare.install import _RawPrepareInstallStepData
from tmt.steps.prepare.install import PrepareInstallData
from tmt.utils import Environment, EnvVarValue, Path, field

STATUS_VARIABLE = 'IN_PLACE_UPGRADE'
Expand Down Expand Up @@ -267,17 +267,14 @@ def _install_dependencies(
recommends: bool = False) -> None:
""" Install packages required/recommended for upgrade """
phase_name = 'recommended' if recommends else 'required'
data: _RawPrepareInstallStepData = {
'how': 'install',
'name': f'{phase_name}-packages-upgrade',
'summary': f'Install packages {phase_name} by the upgrade',
'package': [
dependency.to_spec()
for dependency in tmt.utils.uniq(dependencies)
],
'missing': 'skip' if recommends else 'fail'
}
PreparePlugin.delegate(self.step, raw_data=data).go( # type:ignore[attr-defined]
data = PrepareInstallData(
how='install',
name=f'{phase_name}-packages-upgrade',
summary=f'Install packages {phase_name} by the upgrade',
package=tmt.utils.uniq(dependencies),
missing='skip' if recommends else 'fail')

PreparePlugin.delegate(self.step, data=data).go( # type:ignore[attr-defined]
guest=guest, logger=self._logger)

def _prepare_remote_discover_data(self, plan: tmt.base.Plan) -> tmt.steps._RawStepData:
Expand Down
40 changes: 20 additions & 20 deletions tmt/steps/prepare/distgit.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from tmt.package_managers import Package
from tmt.result import PhaseResult
from tmt.steps.prepare import PreparePlugin
from tmt.steps.prepare.install import _RawPrepareInstallStepData
from tmt.steps.prepare.install import PrepareInstallData
from tmt.steps.provision import Guest
from tmt.utils import Command, Path, ShellScript, field, uniq

Expand Down Expand Up @@ -55,30 +55,30 @@ def insert_to_prepare_step(
prepare_step = discover_plugin.step.plan.prepare
where = cast(tmt.steps.discover.DiscoverStepData, discover_plugin.data).where
# Future install require
data_require: _RawPrepareInstallStepData = {
'how': 'install',
'name': 'requires (dist-git)',
'summary': 'Install required packages of tests detected by dist-git',
'order': tmt.utils.DEFAULT_PLUGIN_ORDER_REQUIRES,
'where': where,
'package': []}
data_require = PrepareInstallData(
how='install',
name='requires (dist-git)',
summary='Install required packages of tests detected by dist-git',
order=tmt.utils.DEFAULT_PLUGIN_ORDER_REQUIRES,
where=where,
package=[])
future_requires: PreparePlugin[Any] = cast(
PreparePlugin[Any], PreparePlugin.delegate(
prepare_step, raw_data=data_require))
PreparePlugin[Any],
PreparePlugin.delegate(prepare_step, data=data_require))
prepare_step._phases.append(future_requires)

# Future install recommend
data_recommend: _RawPrepareInstallStepData = {
'how': 'install',
'name': 'recommends (dist-git)',
'summary': 'Install recommended packages of tests detected by dist-git',
'order': tmt.utils.DEFAULT_PLUGIN_ORDER_RECOMMENDS,
'where': where,
'package': [],
'missing': 'skip'}
data_recommend = PrepareInstallData(
how='install',
name='recommends (dist-git)',
summary='Install recommended packages of tests detected by dist-git',
order=tmt.utils.DEFAULT_PLUGIN_ORDER_RECOMMENDS,
where=where,
package=[],
missing='skip')
future_recommends: PreparePlugin[Any] = cast(
PreparePlugin[Any], PreparePlugin.delegate(
prepare_step, raw_data=data_recommend))
PreparePlugin[Any],
PreparePlugin.delegate(prepare_step, data=data_recommend))
prepare_step._phases.append(future_recommends)

prepare_step._phases.append(
Expand Down
4 changes: 0 additions & 4 deletions tmt/steps/prepare/feature.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,6 @@ def disable(self) -> None:
}


class _RawPrepareFeatureStepData(tmt.steps.prepare._RawPrepareStepData, total=False):
epel: str


@dataclasses.dataclass
class PrepareFeatureData(tmt.steps.prepare.PrepareStepData):
epel: Optional[str] = field(
Expand Down
8 changes: 0 additions & 8 deletions tmt/steps/prepare/install.py
Original file line number Diff line number Diff line change
Expand Up @@ -526,14 +526,6 @@ def install_debuginfo(self) -> None:
'installing debuginfo packages.')


class _RawPrepareInstallStepData(tmt.steps.prepare._RawPrepareStepData, total=False):
package: Union[str, list[str]]
directory: Union[str, list[str]]
copr: Union[str, list[str]]
exclude: Union[str, list[str]]
missing: str


@dataclasses.dataclass
class PrepareInstallData(tmt.steps.prepare.PrepareStepData):
package: list[tmt.base.DependencySimple] = field(
Expand Down
35 changes: 18 additions & 17 deletions tmt/trying.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@
from tmt import Plan
from tmt.base import RunData
from tmt.steps.prepare import PreparePlugin
from tmt.steps.prepare.feature import _RawPrepareFeatureStepData
from tmt.steps.prepare.install import _RawPrepareInstallStepData
from tmt.utils import MetadataError, Path

USER_PLAN_NAME = "/user/plan"
Expand Down Expand Up @@ -417,31 +415,34 @@ def handle_epel(self, plan: Plan) -> None:
""" Enable EPEL repository """

# tmt run prepare --how feature --epel enabled
data: _RawPrepareFeatureStepData = {
"name": "tmt-try-epel",
'how': 'feature',
'epel': "enabled",
}
from tmt.steps.prepare.feature import PrepareFeatureData

data = PrepareFeatureData(
name="tmt-try-epel",
how='feature',
epel="enabled")

phase: PreparePlugin[Any] = cast(
PreparePlugin[Any], PreparePlugin.delegate(
plan.prepare, raw_data=data))
PreparePlugin[Any],
PreparePlugin.delegate(plan.prepare, data=data))

plan.prepare._phases.append(phase)

def handle_install(self, plan: Plan) -> None:
""" Install local rpm package on the guest. """
packages = list(self.opt("install"))

# tmt run prepare --how install --package PACKAGE
data: _RawPrepareInstallStepData = {
"name": "tmt-try-install",
'how': 'install',
'package': packages,
}
from tmt.steps.prepare.install import PrepareInstallData

data = PrepareInstallData(
name="tmt-try-install",
how='install',
package=list(self.opt("install")))

phase: PreparePlugin[Any] = cast(
PreparePlugin[Any], PreparePlugin.delegate(
plan.prepare, raw_data=data))
PreparePlugin[Any],
PreparePlugin.delegate(plan.prepare, data=data))

plan.prepare._phases.append(phase)

def go(self) -> None:
Expand Down

0 comments on commit 8c5b9cb

Please sign in to comment.