Skip to content

Mock provision: make detection of finished processes more deterministic#4437

Open
mkoncek wants to merge 9 commits into
teemtee:mainfrom
mkoncek:mock-process-fix
Open

Mock provision: make detection of finished processes more deterministic#4437
mkoncek wants to merge 9 commits into
teemtee:mainfrom
mkoncek:mock-process-fix

Conversation

@mkoncek

@mkoncek mkoncek commented Dec 17, 2025

Copy link
Copy Markdown
Collaborator

Based on: #4173
I found out that various environments (fedora-rawhide-x86_64) print different number of empty strings on their stdout as the commands spawned in the chroots finish. This causes some environments to hang.
This PR makes the detection more deterministic.

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

@mkoncek mkoncek added bug Something isn't working step | provision Stuff related to the provision step plugin | mock Related to mock provision plugin labels Dec 17, 2025
@happz happz added the ci | full test Pull request is ready for the full test execution label Jan 7, 2026
@happz happz added this to planning Jan 7, 2026
@github-project-automation github-project-automation Bot moved this to backlog in planning Jan 7, 2026
@happz happz moved this from backlog to review in planning Jan 7, 2026
@happz happz added the status | blocked The merging of PR is blocked on some other issue label Jan 7, 2026
@mkoncek

mkoncek commented Jan 21, 2026

Copy link
Copy Markdown
Collaborator Author

@happz Rebased on the current HEAD.

Comment thread tmt/steps/provision/mock.py Outdated
@mkoncek

mkoncek commented Feb 23, 2026

Copy link
Copy Markdown
Collaborator Author

The primary cause of this bug was the assumption that each finished command prints a single newline on stdout after it is finished. This turned out not to be true in some environments. So we print a binary zero after the initial commands are finished and then loop until we read that binary zero back.

Later the command completion is detected by returncode being written into its pre-determined file, instead of waiting on a newline on stdout again.

Comment thread tmt/steps/provision/mock.py
Comment thread tmt/steps/provision/mock.py Outdated
Comment thread tmt/steps/provision/mock.py Outdated
@LecrisUT LecrisUT removed the status | blocked The merging of PR is blocked on some other issue label Feb 23, 2026
@mkoncek

mkoncek commented Feb 23, 2026

Copy link
Copy Markdown
Collaborator Author

Also:

        self.mock_shell.stdin.write(''.join(command + '\n' for command in commands))
        # Issue a command writing a binary zero on the standard output after all
        # the previous commands are finished.
        self.mock_shell.stdin.write('echo -e \\\\x00\n')

could be rewritten as:

        self.mock_shell.stdin.write('\n'.join(commands))
        # Issue a command writing a binary zero on the standard output after all
        # the previous commands are finished.
        self.mock_shell.stdin.write('\necho -e \\\\x00\n')

And then we could use a different string to mark the end of commands.

Afaik in that initialization we only execute things like rm, mkdir, mkfifo and such so there are no arbitrary strings written to stdout.

Comment thread tmt/steps/provision/mock.py Outdated
@mkoncek

mkoncek commented Feb 26, 2026

Copy link
Copy Markdown
Collaborator Author

@LecrisUT I went over your concerns and tried to apply fixes.

@LecrisUT LecrisUT left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Looks good enough for me. Could you rebase please?

Unrelated, but can you also open a PR to revert and give more context on what needs to be done?

# TODO Disable for now under the mock provision plan because of
# https://bugzilla.redhat.com/show_bug.cgi?id=2415701
#- provision-mock

Would prefer to be explicit on the AVC checks that are skipped, but when I tried to revert that, it seemed to have some more genuine errors in it.

@LecrisUT LecrisUT removed their assignment Mar 13, 2026
@thrix thrix force-pushed the mock-process-fix branch from 8a7c7df to 3f5cf6d Compare March 15, 2026 20:28
@thrix

thrix commented Mar 15, 2026

Copy link
Copy Markdown
Contributor

Looks good enough for me. Could you rebase please?

I rebased it.

@thrix thrix left a comment

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.

Code Review: Mock provision — make detection of finished processes more deterministic

Reviewed against commit 3f5cf6d.

Summary

The PR fixes a real bug where mock shell environments produce varying numbers of spurious newlines on stdout, causing the previous counting-based completion detection to hang. The fix introduces two improvements:

  1. In _simple_execute: uses a sentinel keyword (TMT_FINISHED_EXEC) echoed to stdout instead of counting newlines
  2. In _spawn_command: uses the returncode file fd instead of mock shell stdout for completion detection

The overall approach is sound and addresses the root cause well. However, there's a bug in the sentinel detection that could cause the same hanging behavior.

Issues

1. _simple_execute sentinel comparison is fragile — potential hang (bug)

The sentinel check uses exact == equality on self.mock_shell.stdout.read(). Since stdout is a non-blocking TextIOWrapper, read() returns all currently available data. If spurious newlines and the sentinel arrive in the same pipe buffer (very likely since all commands are fast and flushed at once), read() returns e.g. '\n\n\n\nTMT_FINISHED_EXEC\n' which does NOT equal 'TMT_FINISHED_EXEC\n'. The loop hangs.

Verified with a Python test demonstrating the behavior. Fix: use endswith() instead of ==. See inline comment.

2. Stale comment (minor)

"Wait until we read the binary zero from stdout" refers to a previous implementation. Should say "finished keyword" or "sentinel". See inline comment.

Observations

3. _spawn_command: returncode_fd not in the event loop

When returncode_fd has data alongside other events, the data is left unread until it becomes the sole event. Works in practice but is less responsive than the old code. See inline comment.

Verdict

The approach is correct and a clear improvement over counting newlines. Issue #1 (fragile == comparison) must be fixed before merging — it could reproduce the exact hang this PR aims to solve.

Generated-by: Claude Code

Comment thread tmt/steps/provision/mock.py Outdated
Comment thread tmt/steps/provision/mock.py
Comment thread tmt/steps/provision/mock.py
@psss psss added this to the 1.70 milestone Mar 16, 2026
Comment thread tmt/steps/provision/mock.py Outdated
@mkoncek

This comment was marked as resolved.

@LecrisUT

Copy link
Copy Markdown
Member

Btw, you are missing

require+:
  - tmt+provision-mock

in /test/provision/mock/main.fmf

@mkoncek

mkoncek commented Mar 27, 2026

Copy link
Copy Markdown
Collaborator Author

Interesting.
Mock plugin does nothing with sudo.
Maybe I could try raising the priority of the mock package managers over bootc?
I will also add the FMF field.

@LecrisUT

Copy link
Copy Markdown
Member

Maybe I could try raising the priority of the mock package managers over bootc?

It's not the bootc specifically, it's somewhere in all of the _query commands, facts.sudo_prefix, guest.become etc. logic. It is a bit hard to tell and I suspect the stdout/stderr are coming out-of-order as well

@LecrisUT

Copy link
Copy Markdown
Member

More specifically, here is where the stdout/stderr started to diverge

tmt/tmt/guest/__init__.py

Lines 907 to 915 in 6fa1983

def _query_sudo_prefix(self, guest: 'Guest') -> str:
# Note: we cannot reuse `is_superuser` or `can_sudo` fact so we just recall the query
# functions for now
if self._query_is_superuser(guest):
# Root user does not need sudo
return ""
if self._query_can_sudo(guest):
return "sudo"
return ""

        cmd: whoami
        stdout: root
        cmd: sudo -n true
        cmd: whoami
        stderr: sh: sudo: command not found
        cmd: sudo -n true
        stdout: root

@mkoncek

mkoncek commented Mar 27, 2026

Copy link
Copy Markdown
Collaborator Author

Thank you for the debugging, it seems difficult to find cause...

@thrix

thrix commented Mar 31, 2026

Copy link
Copy Markdown
Contributor
testing-farm reserve --compose Fedora-44
(update tmt from the copr repository on the machine)
(logout)
testing-farm list --reservations
tmt run -a provision -h connect -g <IP_FROM_ABOVE> plan --name .... test --name ...

@LecrisUT

LecrisUT commented Apr 2, 2026

Copy link
Copy Markdown
Member

Thank you for the debugging, it seems difficult to find cause...

So the sudo part seems to be a red-herring because in another test, I saw it starting to diverge at a later point

        cmd: /bin/bash -c '[ -e /run/.toolboxenv ] && echo yes || echo no'
        stdout: no
        cmd: /bin/bash -c '[ -e /run/.containerenv ] && echo yes || echo no'
        cmd: /bin/bash -c 'echo -n "$container"'
        stdout: no
        cmd: /bin/bash -c '[ -d /usr/local/bin ] ||  mkdir -p /usr/local/bin'

It seems to me that there is something funky with the implementation. Something about missing read/writes to the epoll causing it to hang or skip some outputs.

At least I can confirm that @thrix's suggestion does help you reproduce it. You can add a login -t to it to get the shell after the test execution, although if the test is causing it to stall, then you have a long time to wait

@mkoncek

mkoncek commented Apr 2, 2026

Copy link
Copy Markdown
Collaborator Author

From traceback, first the traceback, the the cmd: ... output:

  File "/usr/lib64/python3.14/threading.py", line 1044, in _bootstrap
    self._bootstrap_inner()
  File "/usr/lib64/python3.14/threading.py", line 1082, in _bootstrap_inner
    self._context.run(self.run)
  File "/usr/lib64/python3.14/threading.py", line 1024, in run
    self._target(*self._args, **self._kwargs)
  File "/usr/lib64/python3.14/concurrent/futures/thread.py", line 119, in _worker
    work_item.run(ctx)
  File "/usr/lib64/python3.14/concurrent/futures/thread.py", line 86, in run
    result = ctx.run(self.task)
  File "/usr/lib64/python3.14/concurrent/futures/thread.py", line 73, in run
    return fn(*args, **kwargs)
  File "/home/mkoncek/Upstream/tmt/tmt/steps/provision/mock.py", line 887, in go
    self._guest.setup()
  File "/home/mkoncek/Upstream/tmt/tmt/guest/__init__.py", line 1949, in setup
    self.install_scripts(tmt.steps.scripts.SCRIPTS)
  File "/home/mkoncek/Upstream/tmt/tmt/guest/__init__.py", line 1902, in install_scripts
    f"[ -d {quote(str(self.scripts_path))} ] || "
  File "/usr/lib64/python3.14/functools.py", line 1126, in __get__
    val = self.func(instance)
  File "/home/mkoncek/Upstream/tmt/tmt/guest/__init__.py", line 1822, in scripts_path
    if self.facts.is_ostree
  File "/home/mkoncek/Upstream/tmt/tmt/guest/__init__.py", line 1978, in facts
    facts.sync(self)
  File "/home/mkoncek/Upstream/tmt/tmt/guest/__init__.py", line 1052, in sync
    self.is_superuser = self._query_is_superuser(guest)
  File "/home/mkoncek/Upstream/tmt/tmt/guest/__init__.py", line 891, in _query_is_superuser
    output = self._execute(guest, Command('whoami'))
  File "/home/mkoncek/Upstream/tmt/tmt/guest/__init__.py", line 654, in _execute
    return guest.execute(command, silent=True)
  File "/home/mkoncek/Upstream/tmt/tmt/steps/provision/mock.py", line 624, in execute
    *self.mock_shell.execute(
  File "/home/mkoncek/Upstream/tmt/tmt/steps/provision/mock.py", line 504, in execute
    traceback.print_stack()
        cmd: whoami
        stdout: root
  File "/usr/lib64/python3.14/threading.py", line 1044, in _bootstrap
    self._bootstrap_inner()
  File "/usr/lib64/python3.14/threading.py", line 1082, in _bootstrap_inner
    self._context.run(self.run)
  File "/usr/lib64/python3.14/threading.py", line 1024, in run
    self._target(*self._args, **self._kwargs)
  File "/usr/lib64/python3.14/concurrent/futures/thread.py", line 119, in _worker
    work_item.run(ctx)
  File "/usr/lib64/python3.14/concurrent/futures/thread.py", line 86, in run
    result = ctx.run(self.task)
  File "/usr/lib64/python3.14/concurrent/futures/thread.py", line 73, in run
    return fn(*args, **kwargs)
  File "/home/mkoncek/Upstream/tmt/tmt/steps/provision/mock.py", line 887, in go
    self._guest.setup()
  File "/home/mkoncek/Upstream/tmt/tmt/guest/__init__.py", line 1949, in setup
    self.install_scripts(tmt.steps.scripts.SCRIPTS)
  File "/home/mkoncek/Upstream/tmt/tmt/guest/__init__.py", line 1902, in install_scripts
    f"[ -d {quote(str(self.scripts_path))} ] || "
  File "/usr/lib64/python3.14/functools.py", line 1126, in __get__
    val = self.func(instance)
  File "/home/mkoncek/Upstream/tmt/tmt/guest/__init__.py", line 1822, in scripts_path
    if self.facts.is_ostree
  File "/home/mkoncek/Upstream/tmt/tmt/guest/__init__.py", line 1978, in facts
    facts.sync(self)
  File "/home/mkoncek/Upstream/tmt/tmt/guest/__init__.py", line 1053, in sync
    self.can_sudo = self._query_can_sudo(guest)
  File "/home/mkoncek/Upstream/tmt/tmt/guest/__init__.py", line 900, in _query_can_sudo
    guest.execute(Command("sudo", "-n", "true"), silent=True)
  File "/home/mkoncek/Upstream/tmt/tmt/steps/provision/mock.py", line 624, in execute
    *self.mock_shell.execute(
  File "/home/mkoncek/Upstream/tmt/tmt/steps/provision/mock.py", line 504, in execute
    traceback.print_stack()
        cmd: sudo -n true
        stderr: sh: sudo: command not found
  File "/usr/lib64/python3.14/threading.py", line 1044, in _bootstrap
    self._bootstrap_inner()
  File "/usr/lib64/python3.14/threading.py", line 1082, in _bootstrap_inner
    self._context.run(self.run)
  File "/usr/lib64/python3.14/threading.py", line 1024, in run
    self._target(*self._args, **self._kwargs)
  File "/usr/lib64/python3.14/concurrent/futures/thread.py", line 119, in _worker
    work_item.run(ctx)
  File "/usr/lib64/python3.14/concurrent/futures/thread.py", line 86, in run
    result = ctx.run(self.task)
  File "/usr/lib64/python3.14/concurrent/futures/thread.py", line 73, in run
    return fn(*args, **kwargs)
  File "/home/mkoncek/Upstream/tmt/tmt/steps/provision/mock.py", line 887, in go
    self._guest.setup()
  File "/home/mkoncek/Upstream/tmt/tmt/guest/__init__.py", line 1949, in setup
    self.install_scripts(tmt.steps.scripts.SCRIPTS)
  File "/home/mkoncek/Upstream/tmt/tmt/guest/__init__.py", line 1902, in install_scripts
    f"[ -d {quote(str(self.scripts_path))} ] || "
  File "/usr/lib64/python3.14/functools.py", line 1126, in __get__
    val = self.func(instance)
  File "/home/mkoncek/Upstream/tmt/tmt/guest/__init__.py", line 1822, in scripts_path
    if self.facts.is_ostree
  File "/home/mkoncek/Upstream/tmt/tmt/guest/__init__.py", line 1978, in facts
    facts.sync(self)
  File "/home/mkoncek/Upstream/tmt/tmt/guest/__init__.py", line 1054, in sync
    self.sudo_prefix = self._query_sudo_prefix(guest)
  File "/home/mkoncek/Upstream/tmt/tmt/guest/__init__.py", line 910, in _query_sudo_prefix
    if self._query_is_superuser(guest):
  File "/home/mkoncek/Upstream/tmt/tmt/guest/__init__.py", line 891, in _query_is_superuser
    output = self._execute(guest, Command('whoami'))
  File "/home/mkoncek/Upstream/tmt/tmt/guest/__init__.py", line 654, in _execute
    return guest.execute(command, silent=True)
  File "/home/mkoncek/Upstream/tmt/tmt/steps/provision/mock.py", line 624, in execute
    *self.mock_shell.execute(
  File "/home/mkoncek/Upstream/tmt/tmt/steps/provision/mock.py", line 504, in execute
    traceback.print_stack()
        cmd: whoami
        stdout: root
  File "/usr/lib64/python3.14/threading.py", line 1044, in _bootstrap
    self._bootstrap_inner()
  File "/usr/lib64/python3.14/threading.py", line 1082, in _bootstrap_inner
    self._context.run(self.run)
  File "/usr/lib64/python3.14/threading.py", line 1024, in run
    self._target(*self._args, **self._kwargs)
  File "/usr/lib64/python3.14/concurrent/futures/thread.py", line 119, in _worker
    work_item.run(ctx)
  File "/usr/lib64/python3.14/concurrent/futures/thread.py", line 86, in run
    result = ctx.run(self.task)
  File "/usr/lib64/python3.14/concurrent/futures/thread.py", line 73, in run
    return fn(*args, **kwargs)
  File "/home/mkoncek/Upstream/tmt/tmt/steps/provision/mock.py", line 887, in go
    self._guest.setup()
  File "/home/mkoncek/Upstream/tmt/tmt/guest/__init__.py", line 1949, in setup
    self.install_scripts(tmt.steps.scripts.SCRIPTS)
  File "/home/mkoncek/Upstream/tmt/tmt/guest/__init__.py", line 1902, in install_scripts
    f"[ -d {quote(str(self.scripts_path))} ] || "
  File "/usr/lib64/python3.14/functools.py", line 1126, in __get__
    val = self.func(instance)
  File "/home/mkoncek/Upstream/tmt/tmt/guest/__init__.py", line 1822, in scripts_path
    if self.facts.is_ostree
  File "/home/mkoncek/Upstream/tmt/tmt/guest/__init__.py", line 1978, in facts
    facts.sync(self)
  File "/home/mkoncek/Upstream/tmt/tmt/guest/__init__.py", line 1055, in sync
    self.is_ostree = self._query_is_ostree(guest)
  File "/home/mkoncek/Upstream/tmt/tmt/guest/__init__.py", line 919, in _query_is_ostree
    output = self._execute(
  File "/home/mkoncek/Upstream/tmt/tmt/guest/__init__.py", line 654, in _execute
    return guest.execute(command, silent=True)
  File "/home/mkoncek/Upstream/tmt/tmt/steps/provision/mock.py", line 624, in execute
    *self.mock_shell.execute(
  File "/home/mkoncek/Upstream/tmt/tmt/steps/provision/mock.py", line 504, in execute
    traceback.print_stack()
        cmd:
            /bin/bash -c '
            ( [ -e /run/ostree-booted ] || [ -L /ostree ] ) && echo yes || echo no
            '
        stdout: no
  File "/usr/lib64/python3.14/threading.py", line 1044, in _bootstrap
    self._bootstrap_inner()
  File "/usr/lib64/python3.14/threading.py", line 1082, in _bootstrap_inner
    self._context.run(self.run)
  File "/usr/lib64/python3.14/threading.py", line 1024, in run
    self._target(*self._args, **self._kwargs)
  File "/usr/lib64/python3.14/concurrent/futures/thread.py", line 119, in _worker
    work_item.run(ctx)
  File "/usr/lib64/python3.14/concurrent/futures/thread.py", line 86, in run
    result = ctx.run(self.task)
  File "/usr/lib64/python3.14/concurrent/futures/thread.py", line 73, in run
    return fn(*args, **kwargs)
  File "/home/mkoncek/Upstream/tmt/tmt/steps/provision/mock.py", line 887, in go
    self._guest.setup()
  File "/home/mkoncek/Upstream/tmt/tmt/guest/__init__.py", line 1949, in setup
    self.install_scripts(tmt.steps.scripts.SCRIPTS)
  File "/home/mkoncek/Upstream/tmt/tmt/guest/__init__.py", line 1902, in install_scripts
    f"[ -d {quote(str(self.scripts_path))} ] || "
  File "/usr/lib64/python3.14/functools.py", line 1126, in __get__
    val = self.func(instance)
  File "/home/mkoncek/Upstream/tmt/tmt/guest/__init__.py", line 1822, in scripts_path
    if self.facts.is_ostree
  File "/home/mkoncek/Upstream/tmt/tmt/guest/__init__.py", line 1978, in facts
    facts.sync(self)
  File "/home/mkoncek/Upstream/tmt/tmt/guest/__init__.py", line 1056, in sync
    self.is_image_mode = self._query_is_image_mode(guest)
  File "/home/mkoncek/Upstream/tmt/tmt/guest/__init__.py", line 944, in _query_is_image_mode
    sudo_prefix = self._query_sudo_prefix(guest)
  File "/home/mkoncek/Upstream/tmt/tmt/guest/__init__.py", line 910, in _query_sudo_prefix
    if self._query_is_superuser(guest):
  File "/home/mkoncek/Upstream/tmt/tmt/guest/__init__.py", line 891, in _query_is_superuser
    output = self._execute(guest, Command('whoami'))
  File "/home/mkoncek/Upstream/tmt/tmt/guest/__init__.py", line 654, in _execute
    return guest.execute(command, silent=True)
  File "/home/mkoncek/Upstream/tmt/tmt/steps/provision/mock.py", line 624, in execute
    *self.mock_shell.execute(
  File "/home/mkoncek/Upstream/tmt/tmt/steps/provision/mock.py", line 504, in execute
    traceback.print_stack()
        cmd: whoami
        stdout: root

It seems like the multiple invocations of whoami and sudo -n true are done by tmt, and not a mishandled output.

@LecrisUT

LecrisUT commented Apr 2, 2026

Copy link
Copy Markdown
Member

It seems like the multiple invocations of whoami and sudo -n true are done by tmt, and not a mishandled output.

Yes, the fact that some commands are done multiple times is not the issue. The issue seems to be with the out-of-order handling of stdout. It's like one of the stdout read was completely skipped and delayed for the next cmd execution. Maybe the following is also valuable from the centos-stream-9 logs

        cmd: /bin/bash -c '[ -d /usr/local/bin ] || sudo mkdir -p /usr/local/bin'
        fail:
            Invalid state when executing command 'tar -C /usr/local/bin -xf /srv/tmt-mock/filesync --exclude=/tmp/tmp.5rdImvI8F4/scripts/tmt.sh 1>/srv/tmt-mock/stdout 2>/srv/tmt-mock/stderr ; echo $?>/srv/tmt-mock/returncode
            '.
        mock: Exiting shell...
        mock: Exited shell.
    Cause number 1:

        Invalid state when executing command 'tar -C /usr/local/bin -xf /srv/tmt-mock/filesync --exclude=/tmp/tmp.5rdImvI8F4/scripts/tmt.sh 1>/srv/tmt-mock/stdout 2>/srv/tmt-mock/stderr ; echo $?>/srv/tmt-mock/returncode
        '.


            Traceback (most recent call last):

            File /usr/lib/python3.9/site-packages/tmt/queue.py, line 91, in _extract_task_outcome
              task.result = extract(*args, **kwargs)


            File /usr/lib64/python3.9/concurrent/futures/_base.py, line 439, in result
              return self.__get_result()


            File /usr/lib64/python3.9/concurrent/futures/_base.py, line 391, in __get_result
              raise self._exception


            File /usr/lib64/python3.9/concurrent/futures/thread.py, line 58, in run
              result = self.fn(*self.args, **self.kwargs)


            File /usr/lib/python3.9/site-packages/tmt/steps/provision/mock.py, line 881, in go
              self._guest.setup()


            File /usr/lib/python3.9/site-packages/tmt/guest/__init__.py, line 1949, in setup
              self.install_scripts(tmt.steps.scripts.SCRIPTS)


            File /usr/lib/python3.9/site-packages/tmt/guest/__init__.py, line 1930, in install_scripts
              self.push(


            File /usr/lib/python3.9/site-packages/tmt/steps/provision/mock.py, line 721, in push
              next(p)


            File /usr/lib/python3.9/site-packages/tmt/steps/provision/mock.py, line 480, in _spawn_command
              raise tmt.utils.RunError(

@thrix thrix moved this from review to implement in planning Apr 8, 2026
@thrix thrix modified the milestones: 1.71, 1.72 Apr 9, 2026
@happz happz removed this from the 1.71 milestone Apr 9, 2026
@tcornell-bus tcornell-bus self-assigned this Apr 30, 2026
@tcornell-bus

Copy link
Copy Markdown
Contributor

/packit build

@mkoncek mkoncek force-pushed the mock-process-fix branch from ad0bd1f to ed49426 Compare June 9, 2026 13:54
@mkoncek

mkoncek commented Jun 9, 2026

Copy link
Copy Markdown
Collaborator Author

I applied one more change as suggested by @tcornell-bus, which hopefully would fix the the failing test.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working ci | full test Pull request is ready for the full test execution plugin | mock Related to mock provision plugin step | provision Stuff related to the provision step

Projects

Status: implement

Development

Successfully merging this pull request may close these issues.

6 participants