Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Be more careful about default, empty step phases #2833

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

happz
Copy link
Collaborator

@happz happz commented Apr 5, 2024

Pull Request Checklist

  • implement the feature
  • write the documentation
  • extend the test coverage
  • update the specification
  • adjust plugin docstring
  • modify the json schema
  • mention the version
  • include a release note

@happz
Copy link
Collaborator Author

happz commented Apr 5, 2024

Related to #2827

Very much a work in progress, tests will fail. I'm collecting data and looking for patterns in various use cases that need to be supported, to identify possible conflicts and issues.

@happz happz force-pushed the never-ever-add-a-default-phase-except-on-sunny-weekends-and-every-third-tuesday-after-full-moon branch from a07b384 to a7752a5 Compare April 8, 2024 09:56
@happz happz added the ci | full test Pull request is ready for the full test execution label Apr 8, 2024
@happz
Copy link
Collaborator Author

happz commented Apr 9, 2024

/packit test

@happz happz force-pushed the never-ever-add-a-default-phase-except-on-sunny-weekends-and-every-third-tuesday-after-full-moon branch from a7752a5 to 883a3fb Compare April 9, 2024 12:59
Copy link
Collaborator

@psss psss left a comment

Choose a reason for hiding this comment

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

Thanks a lot for looking into this! The approach sounds good to me. Added just a couple questions to clarify some points.

any(invocation.options['how'] for invocation in cli_invocations):
raw_data = _ensure_default_phase()

elif isinstance(self, (prepare.Prepare, finish.Finish)): # noqa: SIM102
Copy link
Collaborator

Choose a reason for hiding this comment

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

Perhaps a short explanation why Prepare and Finish steps do not need default phase unless prepare --how or finish --how are provided on the command line would be useful for future readers of the code?

elif isinstance(self, provision.Provision):
if self.enabled or cli_invocations and \
any(invocation.options['how'] for invocation in cli_invocations):
raw_data = _ensure_default_phase()
Copy link
Collaborator

Choose a reason for hiding this comment

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

Doesn't any provision invocation contains how condition imply that the provision command was provided on the command line and thus the step must be enabled? In other words, shouldn't this be simplified as if self.enabled?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Sounds plausible, although I expect it to blow up - if it wouldn't be ruining a test somewhere, I wouldn't end up makingcli_invocations check part of the condition ;)

I'll give it a try because I can't imagine (or recall) how a provision step can have CLI invocation and not be enabled. The self.enabled runs the following:

    def enabled(self) -> Optional[bool]:
        """ True if the step is enabled """
        if self.plan.my_run is None or self.plan.my_run._cli_context_object is None:
            return None

        return self.name in self.plan.my_run._cli_context_object.steps

That looks like you could be right, on the other hand, it's a game of whac-a-mole and I would be very, very surprised if no tests hit this harmless iceberg.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

And the winner is, tmt try :)

Namely /tests/try/basic:

::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::   Default Plan
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

:: [ 11:05:40 ] :: [  BEGIN   ] :: Running 'TMT_CONFIG_DIR=/tmp/tmp.iZXubjJN2N ./local.exp'
spawn tmt try fedora@local
/var/tmp/tmt/run-053
Let's try /tests/base/bad, /tests/base/good, /tests/base/weird and 3 more tests with /default/plan on fedora@local.

/default/plan
    discover
        how: fmf
        order: 50
        directory: /home/happz/git/tmt/tests/try/basic/data
        summary: 6 tests selected
            /tests/base/bad
            /tests/base/good
            /tests/base/weird
            /tests/core/bad
            /tests/core/good
            /tests/core/weird
    provision
    
        summary: 0 guests provisioned
    prepare
    
        summary: 0 preparations applied
    execute

ESC[31mNo guests available for execution.ESC[0m
send: spawn id exp4 not open
    while executing
"send -- "q\r""
    (file "./local.exp" line 6)
:: [ 11:05:41 ] :: [   FAIL   ] :: Command 'TMT_CONFIG_DIR=/tmp/tmp.iZXubjJN2N ./local.exp' (Expected 0, got 1)
:: [ 11:05:41 ] :: [   PASS   ] :: File '/var/tmp/rlRun_LOG.BX2fu54m' should contain 'Let's try.*/default/plan' 
:: [ 11:05:41 ] :: [   FAIL   ] :: File '/var/tmp/rlRun_LOG.BX2fu54m' should contain 'Run .* successfully finished. Bye for now!' 
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::   Duration: 1s
::   Assertions: 1 good, 2 bad
::   RESULT: FAIL (Default Plan)

The provision step is not enabled, but there is a custom CLI invocation, CliInvocation(context=None, options={'image': 'fedora', 'how': 'local'}). Hence the or & test for CLI invocations. self.name in self.plan.my_run._cli_context_object.steps fails because steps is an empty set.

@psss what would you propose? Shall try modify the steps set, to mark steps as enabled?

Copy link
Contributor

Choose a reason for hiding this comment

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

Doesn't any provision invocation contains how

What I often find confusing is that a default how is injected, usually the virtual provider. It is not well documented how the user can control this default. The only reference I found was of PROVISION_HOW which is specific to tmt's testing

self._workdir_cleanup()
self.status('todo')
if isinstance(self, tmt.steps.report.Report):
self._assert_default_phase()
Copy link
Collaborator

Choose a reason for hiding this comment

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

Which commands / scenario would actually trigger this code branch? Seems that checks around line 885 always ensure that there are some raw data and they run before wake(). Is it included "just to be sure"?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

True, _assert_default_phase() may no longer be necessary. I will try it out.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ci | full test Pull request is ready for the full test execution
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants