Skip to content

Conversation

@bajertom
Copy link
Contributor

@bajertom bajertom commented Dec 12, 2025

Pull Request Checklist

  • implement the feature
  • extend the test coverage
  • include a release note

dependencies_to_test gathers both requires + recommends and tmt is going to fail when something could not be installed in the require phase already. If all required packages are available to install, but a recommended one is not, then it will fail also, but the message {package}: required by {test_name} might be a bit misleading, because it is not required, only recommended. Should the messaging be handled separately or is simply "needed by" enough to cover both requires+recommend in general?

Output:

---------------------------✄-------------------------------------
        prepare task #3: requires on default-0
        how: install
        summary: Install required packages
        name: requires
        where: default-0
        package: sed, grep, coreutils and 5 more
        warn: Installation failed, trying again after metadata refresh.
        package: sed, grep, coreutils and 5 more
        fail: Command 'rpm -q --whatprovides sed grep coreutils bash absent wrong nonexistent missing || dnf5 install -y  sed grep coreutils bash absent wrong nonexistent ridiculous' returned 1.
    
        failed packages: 
            missing: required by /tests/FIRST
            absent: required by /tests/FIRST, /tests/SECOND
            wrong: required by /tests/FIRST, /tests/SECOND
            nonexistent: required by /tests/FIRST
    report
        how: display
        summary: 2 pending
    cleanup
---------------------------✄-------------------------------------

Test coverage needed?

Fixes #4302

@happz
Copy link
Contributor

happz commented Dec 12, 2025

Pull Request Checklist

  • implement the feature
  • extend the test coverage
  • include a release note

dependencies_to_test gathers both requires + recommends and tmt is going to fail when something could not be installed in the require phase already. If all required packages are available to install, but a recommended one is not, then it will fail also, but the message {package}: required by {test_name} might be a bit misleading, because it is not required, only recommended. Should the messaging be handled separately or is simply "needed by" enough to cover both requires+recommend in general?

I'd say it should be separated, wth proper messaging, e.g. "failed to install required packages, see the details below, we're done here" vs "failed to install recommended packages, see the details below, and let's move on".

Output:

---------------------------✄-------------------------------------
        prepare task #3: requires on default-0
        how: install
        summary: Install required packages
        name: requires
        where: default-0
        package: sed, grep, coreutils and 5 more
        warn: Installation failed, trying again after metadata refresh.
        package: sed, grep, coreutils and 5 more
        fail: Command 'rpm -q --whatprovides sed grep coreutils bash absent wrong nonexistent missing || dnf5 install -y  sed grep coreutils bash absent wrong nonexistent ridiculous' returned 1.
    
        failed packages: 
            missing: required by /tests/FIRST
            absent: required by /tests/FIRST, /tests/SECOND
            wrong: required by /tests/FIRST, /tests/SECOND
            nonexistent: required by /tests/FIRST
    report
        how: display
        summary: 2 pending
    cleanup
---------------------------✄-------------------------------------

Test coverage needed?

Yes. We should have a test somewhere checking whether a non-existent package failed to install, it should be enough to extend it with an assert or two to check for new messages.

@LecrisUT LecrisUT self-assigned this Dec 13, 2025
@github-project-automation github-project-automation bot moved this to backlog in planning Dec 13, 2025
@LecrisUT LecrisUT moved this from backlog to implement in planning Dec 13, 2025
@LecrisUT LecrisUT added this to the 1.64 milestone Dec 13, 2025
@AthreyVinay AthreyVinay self-assigned this Jan 6, 2026
@psss psss modified the milestones: 1.64, 1.65 Jan 8, 2026
@bajertom bajertom force-pushed the tbajer-improve-logging-of-requires branch from 795a3dc to b46f5c7 Compare January 9, 2026 21:34
@bajertom
Copy link
Contributor Author

bajertom commented Jan 9, 2026

I have addressed comments and suggestions in b46f5c7
If recommended packages can not be installed, tmt will not raise an exception and therefore I had to use CommandOutput instead and parse the packages from there.

For the "unattributed_packages" - I don't know if that can even happen that packages would not be required/recommended - but maybe the "essential requires" like beakerlib and /usr/bin/flock could fall into this category?

@thrix thrix self-requested a review January 12, 2026 11:47
@bajertom bajertom moved this from implement to review in planning Jan 12, 2026

raise NotImplementedError

def extract_package_name_from_package_manager_output(self, output: str) -> Iterator[str]:
Copy link
Contributor

Choose a reason for hiding this comment

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

Please, decorate with @abc.abstractmethod to make clear to linters this is an abstract method.

Copy link
Contributor

Choose a reason for hiding this comment

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

Or not. After seeing the actual methods, how about moving the patterns into classes, making something like _PACKAGE_NAME_IN_PM_OUTPUT_PATTERNS = [...], and the default implementation of this method can do what all the methods do: iterate over a list of patterns, match, yield. They are really repeating the same set of lines, right? The only thing that's different is the actual set of patterns.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Moved to classes. Should the compiles themselves be also inside a class?

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh yes, why not?

class ApkEngine(PackageManagerEngine):
    install_command = Command('add')


    _engine_class = ApkEngine

    _PACKAGE_NAME_IN_PM_OUTPUT_PATTERNS = [
        re.compile(r'unable to locate package\s+([^\s]+)', re.IGNORECASE),
        re.compile(r'ERROR:\s+([^\s:]+):\s+No such package', re.IGNORECASE)
    ]

# Compiled regex patterns for APT error messages
_UNABLE_TO_LOCATE_PATTERN = re.compile(r'Unable to locate package\s+([^\s]+)', re.IGNORECASE)
_E_UNABLE_TO_LOCATE_PATTERN = re.compile(
r'E:\s+Unable to locate package\s+([^\s]+)', re.IGNORECASE
Copy link
Contributor

Choose a reason for hiding this comment

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

Would (?:E:\s+)? be possible? Then we would need just one pattern, with the E: prefix being optional, the rest seems to be the same.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've used the non-capture group like you suggested.

@bajertom bajertom moved this from review to implement in planning Jan 13, 2026
@bajertom
Copy link
Contributor Author

I've addressed the comments in latest commits, now extending the tests remains.

@bajertom bajertom requested a review from happz January 13, 2026 19:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: implement

Development

Successfully merging this pull request may close these issues.

Improve logging of requires

6 participants