From b3e732942d87e9861f92285c3b0e8e7633f139b4 Mon Sep 17 00:00:00 2001 From: Miroslav Vadkerti Date: Thu, 7 May 2026 17:50:26 +0200 Subject: [PATCH] Fix support of inline scripts in `prepare/shell` An inline script in `prepare/shell` can break easily the RUN directive. We run into this when working on profiles where we had a script with a function: https://gitlab.com/testing-farm/profiles/-/merge_requests/85/diffs To fix this use RUN heredoc to properly support any scripts user can throw on us. Signed-off-by: Miroslav Vadkerti --- tests/prepare/shell/data/multiline.fmf | 12 ++++++++++++ tests/prepare/shell/test.sh | 7 +++++++ tmt/guest/__init__.py | 4 +++- tmt/package_managers/bootc.py | 2 +- 4 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 tests/prepare/shell/data/multiline.fmf diff --git a/tests/prepare/shell/data/multiline.fmf b/tests/prepare/shell/data/multiline.fmf new file mode 100644 index 0000000000..8b5f536bf4 --- /dev/null +++ b/tests/prepare/shell/data/multiline.fmf @@ -0,0 +1,12 @@ +provision: + how: container +prepare: + how: shell + script: | + test() { + echo "This is a multiline script" + } + test +execute: + how: tmt + script: "true" diff --git a/tests/prepare/shell/test.sh b/tests/prepare/shell/test.sh index d077fd9c63..43f00b90a8 100755 --- a/tests/prepare/shell/test.sh +++ b/tests/prepare/shell/test.sh @@ -44,6 +44,13 @@ rlJournalStart assert_image_mode rlPhaseEnd + rlPhaseStartTest "Multiline Shell Scripts" + rlRun -s "tmt run -arvvv provision --how=$PROVISION_HOW $image_opt plans -n multiline" + rlAssertGrep "stdout: STEP 2/2: RUN <<'_TMT_BUILD_SCRIPT'" "$rlRun_LOG" + rlAssertGrep "stdout: This is a multiline script" "$rlRun_LOG" + assert_image_mode + rlPhaseEnd + # TODO: #4785 Preparing from a remote script is broken in Image Mode if [ "$IMAGE_MODE" != "yes" ]; then rlPhaseStartTest "Remote Script" diff --git a/tmt/guest/__init__.py b/tmt/guest/__init__.py index a85111e87a..dda0b56865 100644 --- a/tmt/guest/__init__.py +++ b/tmt/guest/__init__.py @@ -2907,7 +2907,9 @@ def collect_command( # Add to the package manager's engine self.package_manager.engine.open_containerfile_directives() - self.package_manager.engine.containerfile_directives.append(f"RUN {collected_command}") + self.package_manager.engine.containerfile_directives.append("RUN <<'_TMT_BUILD_SCRIPT'") + self.package_manager.engine.containerfile_directives.append(f"{collected_command}") + self.package_manager.engine.containerfile_directives.append("_TMT_BUILD_SCRIPT") self.debug(f"Collected command for Containerfile: {collected_command}") @property diff --git a/tmt/package_managers/bootc.py b/tmt/package_managers/bootc.py index b2287dc718..0a0e198192 100644 --- a/tmt/package_managers/bootc.py +++ b/tmt/package_managers/bootc.py @@ -259,7 +259,7 @@ def build_container(self) -> Optional[CommandOutput]: ) ) self.guest.execute( - ShellScript(f'cat < {containerfile_path!s} \n{containerfile} \nEOF') + ShellScript(f'cat < {containerfile_path!s}\n{containerfile}\nEOF') ) self.debug(f"containerfile content: {containerfile}")