IPU 8.10 -> 9.9: CTC1 candidate 1
- Bump leapp-framework to 6.5 - Change how commands are converted for text based report from the list representation - Introduce the format_list function for unified presentation of lists in reports and logs - Resolves: RHEL-169278
This commit is contained in:
parent
38a2d9d4a8
commit
0190620420
194
0001-introduce-the-format_list-function.patch
Normal file
194
0001-introduce-the-format_list-function.patch
Normal file
@ -0,0 +1,194 @@
|
||||
From d67332c2234e437113493bfdce37594c1e2ae417 Mon Sep 17 00:00:00 2001
|
||||
From: Petr Stodulka <pstodulk@redhat.com>
|
||||
Date: Wed, 3 Dec 2025 08:48:08 +0100
|
||||
Subject: [PATCH 01/10] introduce the format_list function
|
||||
|
||||
The construction of report messages involving lists (e.g., package
|
||||
names, file paths) lacked a consistent formatting which led to
|
||||
inconsistencies and redefinitions when creating reports.
|
||||
|
||||
This patch introduces the format_list function to provide a consistent
|
||||
formatting option across all reports. The function is available from both
|
||||
leapp.libraries.stdlib and leapp.reporting. It supports custom sorting,
|
||||
item limits, and configurable separator.
|
||||
|
||||
Jira-ref: RHEL-126447
|
||||
---
|
||||
docs/source/best-practices.md | 17 +++++++++++
|
||||
leapp/libraries/stdlib/__init__.py | 36 +++++++++++++++++++++--
|
||||
leapp/reporting/__init__.py | 5 +++-
|
||||
packaging/leapp.spec | 2 +-
|
||||
tests/scripts/test_format_list.py | 47 ++++++++++++++++++++++++++++++
|
||||
5 files changed, 103 insertions(+), 4 deletions(-)
|
||||
create mode 100644 tests/scripts/test_format_list.py
|
||||
|
||||
diff --git a/docs/source/best-practices.md b/docs/source/best-practices.md
|
||||
index 11f861a..913dcbd 100644
|
||||
--- a/docs/source/best-practices.md
|
||||
+++ b/docs/source/best-practices.md
|
||||
@@ -155,6 +155,23 @@ In case of [StopActorExecutionError](leapp.exceptions.StopActorExecutionError) t
|
||||
|
||||
You can also use the [StopActorExecution](leapp.exceptions.StopActorExecution) and [StopActorExecutionError](leapp.exceptions.StopActorExecutionError) exceptions inside a private or shared library.
|
||||
|
||||
+## Consistent list formatting in reports
|
||||
+
|
||||
+When constructing report messages that include lists of items (e.g. package names, file paths), use the `format_list` function to ensure consistent formatting across all reports. The function is available from both `leapp.libraries.stdlib` and `leapp.reporting`. It supports custom sorting, item limits, and configurable separators.
|
||||
+
|
||||
+```python
|
||||
+from leapp.reporting import format_list
|
||||
+
|
||||
+pkgs = ['kernel', 'bash', 'glibc']
|
||||
+msg = 'The following packages will be removed:{}'.format(format_list(pkgs))
|
||||
+
|
||||
+# Output:
|
||||
+#The following packages will be removed:
|
||||
+# - bash
|
||||
+# - glibc
|
||||
+# - kernel
|
||||
+```
|
||||
+
|
||||
## Use the LEAPP and LEAPP\_DEVEL prefixes for new envars
|
||||
|
||||
In case you need to change a behaviour of actor(s) for testing or development purposes - e.g. be able to skip a functionality in your actor - use environment variables. Such environment variables should start with prefix *LEAPP\_DEVEL*. Such variables are not possible to use on production systems without special *LEAPP\_UNSUPPORTED* variable. This prevents users to break their systems by a mistake.
|
||||
diff --git a/leapp/libraries/stdlib/__init__.py b/leapp/libraries/stdlib/__init__.py
|
||||
index 89e59b2..efe2029 100644
|
||||
--- a/leapp/libraries/stdlib/__init__.py
|
||||
+++ b/leapp/libraries/stdlib/__init__.py
|
||||
@@ -8,12 +8,15 @@ import logging
|
||||
import os
|
||||
import sys
|
||||
import uuid
|
||||
+from itertools import islice
|
||||
|
||||
from leapp.exceptions import LeappError
|
||||
-from leapp.utils.audit import create_audit_entry
|
||||
from leapp.libraries.stdlib import api
|
||||
-from leapp.libraries.stdlib.call import _call, STDOUT
|
||||
+from leapp.libraries.stdlib.call import STDOUT, _call
|
||||
from leapp.libraries.stdlib.config import is_debug
|
||||
+from leapp.utils.audit import create_audit_entry
|
||||
+
|
||||
+FMT_LIST_SEPARATOR = '\n - '
|
||||
|
||||
|
||||
class CalledProcessError(LeappError):
|
||||
@@ -214,3 +217,32 @@ def run(args, split=False, callback_raw=_console_logging_handler, callback_lineb
|
||||
)
|
||||
api.current_logger().debug('External command has finished: {0}'.format(str(args)))
|
||||
return result
|
||||
+
|
||||
+
|
||||
+def format_list(data, sep=FMT_LIST_SEPARATOR, callback_sort=sorted, limit=0):
|
||||
+ """
|
||||
+ Format an iterable into a string using a specified separator that is prepended to every item.
|
||||
+
|
||||
+ This function can be used to consistently format lists in reports, logs, and error messages.
|
||||
+
|
||||
+ :param data: Iterable of items to format.
|
||||
+ :type data: Iterable
|
||||
+ :param sep: Separator prepended to each item. Defaults to FMT_LIST_SEPARATOR.
|
||||
+ :type sep: str
|
||||
+ :param callback_sort: Callable returning a new list, called before the limit is applied.
|
||||
+ Set to None to preserve original order. Defaults to sorted.
|
||||
+ :type callback_sort: Callable or None
|
||||
+ :param limit: Maximum number of items to include. Defaults to 0 (no limit).
|
||||
+ :type limit: int
|
||||
+ :returns: A string with each item prefixed by the specified separator.
|
||||
+ :rtype: str
|
||||
+ """
|
||||
+ items = data
|
||||
+ if callback_sort is not None:
|
||||
+ items = callback_sort(data)
|
||||
+
|
||||
+ if limit > 0:
|
||||
+ items = islice(items, limit)
|
||||
+
|
||||
+ res = ['{}{}'.format(sep, item) for item in items]
|
||||
+ return ''.join(res)
|
||||
diff --git a/leapp/reporting/__init__.py b/leapp/reporting/__init__.py
|
||||
index 7a0e223..34af17a 100644
|
||||
--- a/leapp/reporting/__init__.py
|
||||
+++ b/leapp/reporting/__init__.py
|
||||
@@ -6,9 +6,12 @@ import os
|
||||
import six
|
||||
|
||||
from leapp.compat import string_types
|
||||
+# NOTE(pstodulk): the format_list is imported to provide the function
|
||||
+# also in this library. Its use is not planned here however.
|
||||
+from leapp.libraries.stdlib import format_list
|
||||
+from leapp.libraries.stdlib.api import produce
|
||||
from leapp.models import fields, Model, ErrorModel
|
||||
from leapp.topics import ReportTopic
|
||||
-from leapp.libraries.stdlib.api import produce
|
||||
from leapp.utils.deprecation import deprecated
|
||||
|
||||
|
||||
diff --git a/packaging/leapp.spec b/packaging/leapp.spec
|
||||
index 1e32cf6..a06b141 100644
|
||||
--- a/packaging/leapp.spec
|
||||
+++ b/packaging/leapp.spec
|
||||
@@ -13,7 +13,7 @@
|
||||
# This is kind of help for more flexible development of leapp repository,
|
||||
# so people do not have to wait for new official release of leapp to ensure
|
||||
# it is installed/used the compatible one.
|
||||
-%global framework_version 6.2
|
||||
+%global framework_version 6.3
|
||||
|
||||
# IMPORTANT: everytime the requirements are changed, increment number by one
|
||||
# - same for Provides in deps subpackage
|
||||
diff --git a/tests/scripts/test_format_list.py b/tests/scripts/test_format_list.py
|
||||
new file mode 100644
|
||||
index 0000000..1b0ca24
|
||||
--- /dev/null
|
||||
+++ b/tests/scripts/test_format_list.py
|
||||
@@ -0,0 +1,47 @@
|
||||
+import pytest
|
||||
+
|
||||
+from leapp.libraries.stdlib import FMT_LIST_SEPARATOR, format_list
|
||||
+
|
||||
+SEP = ', '
|
||||
+
|
||||
+
|
||||
+@pytest.mark.parametrize('data, kwargs, expected', [
|
||||
+ # Basic usage
|
||||
+ ([], {}, ''),
|
||||
+ (['c', 'a', 'b'], {}, '{0}a{0}b{0}c'.format(FMT_LIST_SEPARATOR)),
|
||||
+ (['c', 'a', 'b'], {'sep': SEP}, ', a, b, c'),
|
||||
+ (['a'], {'sep': SEP}, ', a'),
|
||||
+ # Sorting
|
||||
+ (['c', 'a', 'b'], {'sep': SEP, 'callback_sort': None}, ', c, a, b'),
|
||||
+ (['c', 'a', 'b'], {'sep': SEP, 'callback_sort': lambda d: sorted(d, reverse=True)}, ', c, b, a'),
|
||||
+ # Limit
|
||||
+ (['c', 'a', 'b'], {'sep': SEP, 'limit': 2}, ', a, b'),
|
||||
+ (['c', 'a', 'b'], {'sep': SEP, 'limit': 0}, ', a, b, c'),
|
||||
+ (['b', 'a'], {'sep': SEP, 'limit': 10}, ', a, b'),
|
||||
+ (['c', 'a', 'b'], {'sep': SEP, 'limit': -1}, ', a, b, c'),
|
||||
+ # Non-list iterables
|
||||
+ ({'a', 'b', 'c'}, {'sep': SEP, 'limit': 2}, ', a, b'),
|
||||
+ (('a', 'b'), {'sep': SEP}, ', a, b'),
|
||||
+ ({'b': 1, 'a': 2}, {'sep': SEP}, ', a, b'),
|
||||
+ # Generators
|
||||
+ ((x for x in ['c', 'a', 'b']), {'sep': SEP}, ', a, b, c'),
|
||||
+ ((x for x in ['c', 'a', 'b']), {'sep': SEP, 'callback_sort': None, 'limit': 2}, ', c, a'),
|
||||
+], ids=[
|
||||
+ 'empty_data',
|
||||
+ 'single_item',
|
||||
+ 'default_separator',
|
||||
+ 'custom_separator',
|
||||
+ 'no_sort',
|
||||
+ 'reverse_sort',
|
||||
+ 'limit',
|
||||
+ 'limit_zero',
|
||||
+ 'limit_larger_than_data',
|
||||
+ 'negative_limit_ignored',
|
||||
+ 'set_input',
|
||||
+ 'tuple_input',
|
||||
+ 'dict_keys_input',
|
||||
+ 'generator_sorted',
|
||||
+ 'generator_unsorted_with_limit',
|
||||
+])
|
||||
+def test_format_list(data, kwargs, expected):
|
||||
+ assert format_list(data, **kwargs) == expected
|
||||
--
|
||||
2.53.0
|
||||
|
||||
61
0002-packit-remove-unsupported-upgrade-path-from-tests.patch
Normal file
61
0002-packit-remove-unsupported-upgrade-path-from-tests.patch
Normal file
@ -0,0 +1,61 @@
|
||||
From 2f210e763a8b851f1804f518fb02466db9cb55fa Mon Sep 17 00:00:00 2001
|
||||
From: Peter Mocary <pmocary@redhat.com>
|
||||
Date: Tue, 3 Mar 2026 16:30:31 +0100
|
||||
Subject: [PATCH 02/10] packit: remove unsupported upgrade path from tests
|
||||
|
||||
---
|
||||
.packit.yaml | 31 -------------------------------
|
||||
1 file changed, 31 deletions(-)
|
||||
|
||||
diff --git a/.packit.yaml b/.packit.yaml
|
||||
index 0566801..254b24b 100644
|
||||
--- a/.packit.yaml
|
||||
+++ b/.packit.yaml
|
||||
@@ -326,15 +326,6 @@ jobs:
|
||||
provisioning:
|
||||
tags:
|
||||
BusinessUnit: sst_upgrades@leapp_upstream_test
|
||||
- - &tmt-env-settings-centos9torhel101
|
||||
- tmt:
|
||||
- context: &tmt-context-centos9torhel101
|
||||
- distro: "centos-9"
|
||||
- distro_target: "rhel-10.1"
|
||||
- settings:
|
||||
- provisioning:
|
||||
- tags:
|
||||
- BusinessUnit: sst_upgrades@leapp_upstream_test
|
||||
- &tmt-env-settings-98to102
|
||||
tmt:
|
||||
context: &tmt-context-98to102
|
||||
@@ -521,28 +512,6 @@ jobs:
|
||||
# ###################### CentOS Stream > RHEL ########################## #
|
||||
# ###################################################################### #
|
||||
|
||||
-# ###################################################################### #
|
||||
-# ############################ 9 > 10.1 ################################ #
|
||||
-# ###################################################################### #
|
||||
-
|
||||
-- &sanity-centos9torhel101
|
||||
- <<: *sanity-abstract-9to10
|
||||
- trigger: pull_request
|
||||
- identifier: sanity-CentOS9toRHEL10.1
|
||||
- targets:
|
||||
- epel-9-x86_64:
|
||||
- distros: [CentOS-Stream-9]
|
||||
- tf_extra_params:
|
||||
- test:
|
||||
- tmt:
|
||||
- plan_filter: 'tag:9to10 & tag:tier0 & enabled:true & tag:-rhsm'
|
||||
- environments:
|
||||
- - artifacts: *artifacts-for-rhel9
|
||||
- - *tmt-env-settings-centos9torhel101
|
||||
- env: &env-centos9to101
|
||||
- SOURCE_RELEASE: "9"
|
||||
- TARGET_RELEASE: "10.1"
|
||||
-
|
||||
# ###################################################################### #
|
||||
# ############################ 9 > 10.2 ################################ #
|
||||
# ###################################################################### #
|
||||
--
|
||||
2.53.0
|
||||
|
||||
300
0003-packit-add-new-upgrade-paths-to-tests.patch
Normal file
300
0003-packit-add-new-upgrade-paths-to-tests.patch
Normal file
@ -0,0 +1,300 @@
|
||||
From 80c700223948b7a11af1b71c1ed81145662786ae Mon Sep 17 00:00:00 2001
|
||||
From: Peter Mocary <pmocary@redhat.com>
|
||||
Date: Fri, 6 Mar 2026 17:56:10 +0100
|
||||
Subject: [PATCH 03/10] packit: add new upgrade paths to tests
|
||||
|
||||
Adds the 8.10 -> 9.9 -> 10.3 upgrade paths to CI tests.
|
||||
---
|
||||
.packit.yaml | 187 ++++++++++++++++++++++++++++++++++++++++++++++++---
|
||||
1 file changed, 179 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/.packit.yaml b/.packit.yaml
|
||||
index 254b24b..cd45f27 100644
|
||||
--- a/.packit.yaml
|
||||
+++ b/.packit.yaml
|
||||
@@ -23,6 +23,7 @@ jobs:
|
||||
get-current-version:
|
||||
# get version from spec file instead from git tag
|
||||
- bash -c "grep -m1 '^Version:' packaging/leapp.spec | grep -om1 '[0-9].[0-9.]**'"
|
||||
+
|
||||
- job: copr_build
|
||||
trigger: commit
|
||||
metadata:
|
||||
@@ -107,6 +108,15 @@ jobs:
|
||||
provisioning:
|
||||
tags:
|
||||
BusinessUnit: sst_upgrades@leapp_upstream_test
|
||||
+ - &tmt-env-settings-810to99
|
||||
+ tmt:
|
||||
+ context: &tmt-context-810to99
|
||||
+ distro: "rhel-8.10"
|
||||
+ distro_target: "rhel-9.9"
|
||||
+ settings:
|
||||
+ provisioning:
|
||||
+ tags:
|
||||
+ BusinessUnit: sst_upgrades@leapp_upstream_test
|
||||
|
||||
- &sanity-abstract-8to9-aws
|
||||
<<: *sanity-abstract-8to9
|
||||
@@ -188,7 +198,7 @@ jobs:
|
||||
tf_extra_params:
|
||||
test:
|
||||
tmt:
|
||||
- plan_filter: 'tag:8to9 & tag:kernel-rt & enabled:true & tag:-rhsm'
|
||||
+ plan_filter: 'tag:8to9 & tag:kernel-rt & enabled:true & tag:-rhsm'
|
||||
environments:
|
||||
- artifacts: *artifacts-for-rhel8
|
||||
- *tmt-env-settings-810to96
|
||||
@@ -217,7 +227,6 @@ jobs:
|
||||
env:
|
||||
<<: *env-810to96
|
||||
|
||||
-
|
||||
# ###################################################################### #
|
||||
# ############################# 8.10 > 9.8 ############################# #
|
||||
# ###################################################################### #
|
||||
@@ -268,13 +277,70 @@ jobs:
|
||||
tf_extra_params:
|
||||
test:
|
||||
tmt:
|
||||
- plan_filter: 'tag:8to9 & tag:kernel-rt & enabled:true'
|
||||
+ plan_filter: 'tag:8to9 & tag:kernel-rt & enabled:true'
|
||||
environments:
|
||||
- artifacts: *artifacts-for-rhel8
|
||||
- *tmt-env-settings-810to98
|
||||
env:
|
||||
<<: *env-810to98
|
||||
|
||||
+# ###################################################################### #
|
||||
+# ############################# 8.10 > 9.9 ############################# #
|
||||
+# ###################################################################### #
|
||||
+
|
||||
+- &sanity-810to99
|
||||
+ <<: *sanity-abstract-8to9
|
||||
+ trigger: pull_request
|
||||
+ identifier: sanity-8.10to9.9
|
||||
+ tf_extra_params:
|
||||
+ test:
|
||||
+ tmt:
|
||||
+ plan_filter: 'tag:8to9 & tag:tier0 & enabled:true'
|
||||
+ environments:
|
||||
+ - artifacts: *artifacts-for-rhel8
|
||||
+ - *tmt-env-settings-810to99
|
||||
+ env: &env-810to99
|
||||
+ SOURCE_RELEASE: "8.10"
|
||||
+ TARGET_RELEASE: "9.9"
|
||||
+
|
||||
+# On-demand minimal beaker tests
|
||||
+- &beaker-minimal-810to99
|
||||
+ <<: *beaker-minimal-8to9-abstract-ondemand
|
||||
+ trigger: pull_request
|
||||
+ labels:
|
||||
+ - beaker-minimal
|
||||
+ - beaker-minimal-8.10to9.9
|
||||
+ - 8.10to9.9
|
||||
+ identifier: sanity-8.10to9.9-beaker-minimal-ondemand
|
||||
+ tf_extra_params:
|
||||
+ test:
|
||||
+ tmt:
|
||||
+ plan_filter: 'tag:8to9 & tag:partitioning & enabled:true'
|
||||
+ environments:
|
||||
+ - artifacts: *artifacts-for-rhel8
|
||||
+ - *tmt-env-settings-810to99
|
||||
+ env:
|
||||
+ <<: *env-810to99
|
||||
+
|
||||
+# On-demand kernel-rt tests
|
||||
+- &kernel-rt-810to99
|
||||
+ <<: *kernel-rt-abstract-8to9-ondemand
|
||||
+ trigger: pull_request
|
||||
+ labels:
|
||||
+ - kernel-rt
|
||||
+ - kernel-rt-8.10to9.9
|
||||
+ - 8.10to9.9
|
||||
+ identifier: sanity-8.10to9.9-kernel-rt-ondemand
|
||||
+ tf_extra_params:
|
||||
+ test:
|
||||
+ tmt:
|
||||
+ plan_filter: 'tag:8to9 & tag:kernel-rt & enabled:true'
|
||||
+ environments:
|
||||
+ - artifacts: *artifacts-for-rhel8
|
||||
+ - *tmt-env-settings-810to99
|
||||
+ env:
|
||||
+ <<: *env-810to99
|
||||
+
|
||||
# ###################################################################### #
|
||||
# ############################## 9 TO 10 ################################ #
|
||||
# ###################################################################### #
|
||||
@@ -344,6 +410,24 @@ jobs:
|
||||
provisioning:
|
||||
tags:
|
||||
BusinessUnit: sst_upgrades@leapp_upstream_test
|
||||
+ - &tmt-env-settings-99to103
|
||||
+ tmt:
|
||||
+ context: &tmt-context-99to103
|
||||
+ distro: "rhel-9.9"
|
||||
+ distro_target: "rhel-10.3"
|
||||
+ settings:
|
||||
+ provisioning:
|
||||
+ tags:
|
||||
+ BusinessUnit: sst_upgrades@leapp_upstream_test
|
||||
+ - &tmt-env-settings-centos9torhel103
|
||||
+ tmt:
|
||||
+ context: &tmt-context-centos9torhel103
|
||||
+ distro: "centos-9"
|
||||
+ distro_target: "rhel-10.3"
|
||||
+ settings:
|
||||
+ provisioning:
|
||||
+ tags:
|
||||
+ BusinessUnit: sst_upgrades@leapp_upstream_test
|
||||
|
||||
- &sanity-abstract-9to10-aws
|
||||
<<: *sanity-abstract-9to10
|
||||
@@ -412,7 +496,7 @@ jobs:
|
||||
tf_extra_params:
|
||||
test:
|
||||
tmt:
|
||||
- plan_filter: 'tag:8to9 & tag:partitioning & enabled:true & tag:-rhsm'
|
||||
+ plan_filter: 'tag:9to10 & tag:partitioning & enabled:true & tag:-rhsm'
|
||||
environments:
|
||||
- artifacts: *artifacts-for-rhel9
|
||||
- *tmt-env-settings-96to100
|
||||
@@ -431,7 +515,7 @@ jobs:
|
||||
tf_extra_params:
|
||||
test:
|
||||
tmt:
|
||||
- plan_filter: 'tag:8to9 & tag:kernel-rt & enabled:true & tag:-rhsm'
|
||||
+ plan_filter: 'tag:9to10 & tag:kernel-rt & enabled:true & tag:-rhsm'
|
||||
environments:
|
||||
- artifacts: *artifacts-for-rhel9
|
||||
- *tmt-env-settings-96to100
|
||||
@@ -475,7 +559,7 @@ jobs:
|
||||
tf_extra_params:
|
||||
test:
|
||||
tmt:
|
||||
- plan_filter: 'tag:8to9 & tag:partitioning & enabled:true & tag:-rhsm'
|
||||
+ plan_filter: 'tag:9to10 & tag:partitioning & enabled:true & tag:-rhsm'
|
||||
environments:
|
||||
- artifacts: *artifacts-for-rhel9
|
||||
- *tmt-env-settings-98to102
|
||||
@@ -497,13 +581,79 @@ jobs:
|
||||
tf_extra_params:
|
||||
test:
|
||||
tmt:
|
||||
- plan_filter: 'tag:8to9 & tag:kernel-rt & enabled:true & tag:-rhsm'
|
||||
+ plan_filter: 'tag:9to10 & tag:kernel-rt & enabled:true & tag:-rhsm'
|
||||
environments:
|
||||
- artifacts: *artifacts-for-rhel9
|
||||
- *tmt-env-settings-98to102
|
||||
env:
|
||||
<<: *env-98to102
|
||||
|
||||
+# ###################################################################### #
|
||||
+# ############################# 9.9 > 10.3 ############################# #
|
||||
+# ###################################################################### #
|
||||
+
|
||||
+- &sanity-99to103
|
||||
+ <<: *sanity-abstract-9to10
|
||||
+ trigger: pull_request
|
||||
+ identifier: sanity-9.9to10.3
|
||||
+ targets:
|
||||
+ epel-9-x86_64:
|
||||
+ distros: [RHEL-9.9.0-Nightly]
|
||||
+ tf_extra_params:
|
||||
+ test:
|
||||
+ tmt:
|
||||
+ plan_filter: 'tag:9to10 & tag:tier0 & enabled:true'
|
||||
+ environments:
|
||||
+ - artifacts: *artifacts-for-rhel9
|
||||
+ - *tmt-env-settings-99to103
|
||||
+ env: &env-99to103
|
||||
+ SOURCE_RELEASE: "9.9"
|
||||
+ TARGET_RELEASE: "10.3"
|
||||
+
|
||||
+# On-demand minimal beaker tests
|
||||
+- &beaker-minimal-99to103
|
||||
+ <<: *beaker-minimal-9to10-abstract-ondemand
|
||||
+ trigger: pull_request
|
||||
+ labels:
|
||||
+ - beaker-minimal
|
||||
+ - beaker-minimal-9.9to10.3
|
||||
+ - 9.9to10.3
|
||||
+ identifier: sanity-9.9to10.3-beaker-minimal-ondemand
|
||||
+ targets:
|
||||
+ epel-9-x86_64:
|
||||
+ distros: [RHEL-9.9-Nightly]
|
||||
+ tf_extra_params:
|
||||
+ test:
|
||||
+ tmt:
|
||||
+ plan_filter: 'tag:9to10 & tag:partitioning & enabled:true'
|
||||
+ environments:
|
||||
+ - artifacts: *artifacts-for-rhel9
|
||||
+ - *tmt-env-settings-99to103
|
||||
+ env:
|
||||
+ <<: *env-99to103
|
||||
+
|
||||
+# On-demand kernel-rt tests
|
||||
+- &kernel-rt-99to103
|
||||
+ <<: *kernel-rt-abstract-9to10-ondemand
|
||||
+ trigger: pull_request
|
||||
+ labels:
|
||||
+ - kernel-rt
|
||||
+ - kernel-rt-9.9to10.3
|
||||
+ - 9.9to10.3
|
||||
+ identifier: sanity-9.9to10.3-kernel-rt-ondemand
|
||||
+ targets:
|
||||
+ epel-9-x86_64:
|
||||
+ distros: [RHEL-9.9-Nightly]
|
||||
+ tf_extra_params:
|
||||
+ test:
|
||||
+ tmt:
|
||||
+ plan_filter: 'tag:9to10 & tag:kernel-rt & enabled:true'
|
||||
+ environments:
|
||||
+ - artifacts: *artifacts-for-rhel9
|
||||
+ - *tmt-env-settings-99to103
|
||||
+ env:
|
||||
+ <<: *env-99to103
|
||||
+
|
||||
# ###################################################################### #
|
||||
# ########################## CentOS Stream ############################# #
|
||||
# ###################################################################### #
|
||||
@@ -527,7 +677,6 @@ jobs:
|
||||
test:
|
||||
tmt:
|
||||
plan_filter: 'tag:9to10 & tag:tier0 & enabled:true & tag:-rhsm'
|
||||
- name:
|
||||
environments:
|
||||
- artifacts: *artifacts-for-rhel9
|
||||
- *tmt-env-settings-centos9torhel102
|
||||
@@ -535,6 +684,28 @@ jobs:
|
||||
SOURCE_RELEASE: "9"
|
||||
TARGET_RELEASE: "10.2"
|
||||
|
||||
+# ###################################################################### #
|
||||
+# ############################ 9 > 10.3 ################################ #
|
||||
+# ###################################################################### #
|
||||
+
|
||||
+- &sanity-centos9torhel103
|
||||
+ <<: *sanity-abstract-9to10
|
||||
+ trigger: pull_request
|
||||
+ identifier: sanity-CentOS9toRHEL10.3
|
||||
+ targets:
|
||||
+ epel-9-x86_64:
|
||||
+ distros: [CentOS-Stream-9]
|
||||
+ tf_extra_params:
|
||||
+ test:
|
||||
+ tmt:
|
||||
+ plan_filter: 'tag:9to10 & tag:tier0 & enabled:true & tag:-rhsm'
|
||||
+ environments:
|
||||
+ - artifacts: *artifacts-for-rhel9
|
||||
+ - *tmt-env-settings-centos9torhel103
|
||||
+ env: &env-centos9torhel103
|
||||
+ SOURCE_RELEASE: "9"
|
||||
+ TARGET_RELEASE: "10.3"
|
||||
+
|
||||
# ###################################################################### #
|
||||
# ################## CentOS Stream > CentOS Stream ##################### #
|
||||
# ###################################################################### #
|
||||
--
|
||||
2.53.0
|
||||
|
||||
48
0004-chore-deps-update-actions-checkout-action-to-v6.patch
Normal file
48
0004-chore-deps-update-actions-checkout-action-to-v6.patch
Normal file
@ -0,0 +1,48 @@
|
||||
From 136ed3baac103bfb0945d74703c7b7a05f40d8bd Mon Sep 17 00:00:00 2001
|
||||
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
|
||||
Date: Thu, 5 Mar 2026 09:51:22 +0000
|
||||
Subject: [PATCH 04/10] chore(deps): update actions/checkout action to v6
|
||||
|
||||
---
|
||||
.github/workflows/reuse-copr-build.yml | 4 ++--
|
||||
.github/workflows/unit-tests.yml | 2 +-
|
||||
2 files changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/.github/workflows/reuse-copr-build.yml b/.github/workflows/reuse-copr-build.yml
|
||||
index c2fb51c..5e33fe3 100644
|
||||
--- a/.github/workflows/reuse-copr-build.yml
|
||||
+++ b/.github/workflows/reuse-copr-build.yml
|
||||
@@ -49,7 +49,7 @@ jobs:
|
||||
# TODO: The correct way to checkout would be to use simmilar approach as in get_commit_by_timestamp function of
|
||||
# the github gluetool module (i.e. do not use HEAD but the last commit before comment).
|
||||
id: checkout
|
||||
- uses: actions/checkout@v5
|
||||
+ uses: actions/checkout@v6
|
||||
with:
|
||||
ref: "refs/pull/${{ steps.pr_nr.outputs.pr_nr }}/head"
|
||||
|
||||
@@ -121,7 +121,7 @@ jobs:
|
||||
- name: Checkout leapp-repository
|
||||
id: checkout_leapp_repository
|
||||
if: ${{ steps.leapp_repository_pr_regex_match.outputs.match != '' }}
|
||||
- uses: actions/checkout@v5
|
||||
+ uses: actions/checkout@v6
|
||||
with:
|
||||
repository: "oamg/leapp-repository"
|
||||
ref: "refs/pull/${{ steps.leapp_repository_pr.outputs.leapp_repository_pr }}/head"
|
||||
diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml
|
||||
index 70d624d..906a45d 100644
|
||||
--- a/.github/workflows/unit-tests.yml
|
||||
+++ b/.github/workflows/unit-tests.yml
|
||||
@@ -36,7 +36,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
- uses: actions/checkout@v5
|
||||
+ uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: '0'
|
||||
- name: Set main to origin/main
|
||||
--
|
||||
2.53.0
|
||||
|
||||
@ -0,0 +1,34 @@
|
||||
From dc9e1c60e5cc84abf1b5df0972072f7795bc860c Mon Sep 17 00:00:00 2001
|
||||
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
|
||||
Date: Thu, 5 Mar 2026 09:51:26 +0000
|
||||
Subject: [PATCH 05/10] chore(deps): update actions/github-script action to v8
|
||||
|
||||
---
|
||||
.github/workflows/reuse-copr-build.yml | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/.github/workflows/reuse-copr-build.yml b/.github/workflows/reuse-copr-build.yml
|
||||
index 5e33fe3..0f6b823 100644
|
||||
--- a/.github/workflows/reuse-copr-build.yml
|
||||
+++ b/.github/workflows/reuse-copr-build.yml
|
||||
@@ -102,7 +102,7 @@ jobs:
|
||||
- name: Add comment with copr build url
|
||||
# TODO: Create comment when copr build fails.
|
||||
id: link_copr
|
||||
- uses: actions/github-script@v7
|
||||
+ uses: actions/github-script@v8
|
||||
with:
|
||||
script: |
|
||||
github.issues.createComment({
|
||||
@@ -160,7 +160,7 @@ jobs:
|
||||
# TODO: Create comment when copr build fails.
|
||||
id: link_copr_leapp_repository
|
||||
if: ${{ steps.leapp_repository_pr_regex_match.outputs.match != '' }}
|
||||
- uses: actions/github-script@v7
|
||||
+ uses: actions/github-script@v8
|
||||
with:
|
||||
script: |
|
||||
github.issues.createComment({
|
||||
--
|
||||
2.53.0
|
||||
|
||||
@ -0,0 +1,26 @@
|
||||
From a2cbc6e98539926dc25862172b89a5585562009b Mon Sep 17 00:00:00 2001
|
||||
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
|
||||
Date: Thu, 5 Mar 2026 09:51:28 +0000
|
||||
Subject: [PATCH 06/10] chore(deps): update
|
||||
peter-evans/create-or-update-comment action to v5
|
||||
|
||||
---
|
||||
.github/workflows/pr-welcome-msg.yml | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/.github/workflows/pr-welcome-msg.yml b/.github/workflows/pr-welcome-msg.yml
|
||||
index 66d001e..5d9fc3e 100644
|
||||
--- a/.github/workflows/pr-welcome-msg.yml
|
||||
+++ b/.github/workflows/pr-welcome-msg.yml
|
||||
@@ -14,7 +14,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Create comment
|
||||
- uses: peter-evans/create-or-update-comment@v4
|
||||
+ uses: peter-evans/create-or-update-comment@v5
|
||||
with:
|
||||
issue-number: ${{ github.event.pull_request.number }}
|
||||
body: |
|
||||
--
|
||||
2.53.0
|
||||
|
||||
157
0007-reporting-fix-incorrect-converting-of-list-based-com.patch
Normal file
157
0007-reporting-fix-incorrect-converting-of-list-based-com.patch
Normal file
@ -0,0 +1,157 @@
|
||||
From 9fbd48b20f556cb613f3ca7999f4fc9d74e24024 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Mocary <pmocary@redhat.com>
|
||||
Date: Tue, 17 Mar 2026 12:22:35 +0100
|
||||
Subject: [PATCH 07/10] reporting: fix incorrect converting of list based
|
||||
commands
|
||||
|
||||
The reporting module handled conversion between shell command
|
||||
representations for the text and json reports incorrectly. The list of
|
||||
strings representation was converted without preserving the argument
|
||||
separation correctly which results in malformed commands in the text
|
||||
report.
|
||||
|
||||
This patch utilizes the built-in shlex Python library for the conversion
|
||||
which preserves the argument separation by wrapping arguments in quotes
|
||||
when necessary.
|
||||
|
||||
Jira: RHEL-156521
|
||||
---
|
||||
leapp/reporting/__init__.py | 9 +++--
|
||||
packaging/leapp.spec | 2 +-
|
||||
tests/scripts/test_reporting.py | 61 +++++++++++++++++++++++++++++++--
|
||||
3 files changed, 66 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/leapp/reporting/__init__.py b/leapp/reporting/__init__.py
|
||||
index 34af17a..ca2b80b 100644
|
||||
--- a/leapp/reporting/__init__.py
|
||||
+++ b/leapp/reporting/__init__.py
|
||||
@@ -1,8 +1,9 @@
|
||||
import datetime
|
||||
-import json
|
||||
import hashlib
|
||||
+import json
|
||||
import logging
|
||||
import os
|
||||
+import shlex
|
||||
import six
|
||||
|
||||
from leapp.compat import string_types
|
||||
@@ -10,7 +11,7 @@ from leapp.compat import string_types
|
||||
# also in this library. Its use is not planned here however.
|
||||
from leapp.libraries.stdlib import format_list
|
||||
from leapp.libraries.stdlib.api import produce
|
||||
-from leapp.models import fields, Model, ErrorModel
|
||||
+from leapp.models import ErrorModel, Model, fields
|
||||
from leapp.topics import ReportTopic
|
||||
from leapp.utils.deprecation import deprecated
|
||||
|
||||
@@ -281,8 +282,10 @@ class RemediationCommand(BaseRemediation):
|
||||
def __repr__(self):
|
||||
# NOTE(ivasilev) As the message can contain non-ascii characters let's deal with it properly.
|
||||
# As per python practices repr has to return an encoded string
|
||||
+ # Note(pmocary) Using shlex.join is not possible here due to it being available from Python 3.8,
|
||||
+ # thus we use the shlex.quote on each argument instead which is the same as shlex.join implementation.
|
||||
return "[{}] {}".format(self._value['type'],
|
||||
- ' '.join([_guarantee_encoded_str(c) for c in self._value['context']]))
|
||||
+ ' '.join([shlex.quote(_guarantee_encoded_str(c)) for c in self._value['context']]))
|
||||
|
||||
|
||||
class RemediationHint(BaseRemediation):
|
||||
diff --git a/packaging/leapp.spec b/packaging/leapp.spec
|
||||
index a06b141..ba906cf 100644
|
||||
--- a/packaging/leapp.spec
|
||||
+++ b/packaging/leapp.spec
|
||||
@@ -13,7 +13,7 @@
|
||||
# This is kind of help for more flexible development of leapp repository,
|
||||
# so people do not have to wait for new official release of leapp to ensure
|
||||
# it is installed/used the compatible one.
|
||||
-%global framework_version 6.3
|
||||
+%global framework_version 6.4
|
||||
|
||||
# IMPORTANT: everytime the requirements are changed, increment number by one
|
||||
# - same for Provides in deps subpackage
|
||||
diff --git a/tests/scripts/test_reporting.py b/tests/scripts/test_reporting.py
|
||||
index 2b0f245..8c284cb 100644
|
||||
--- a/tests/scripts/test_reporting.py
|
||||
+++ b/tests/scripts/test_reporting.py
|
||||
@@ -14,11 +14,10 @@ from leapp.reporting import (
|
||||
create_report_from_deprecation,
|
||||
create_report_from_error,
|
||||
_create_report_object,
|
||||
- Audience, Flags, Groups, Key, RelatedResource, Remediation, Summary, Severity, Tags, Title
|
||||
+ Audience, Flags, Groups, Key, RelatedResource, Remediation, RemediationCommand, Summary, Severity, Tags, Title
|
||||
)
|
||||
from leapp.utils.report import generate_report_file
|
||||
|
||||
-
|
||||
ReportPrimitive = namedtuple('ReportPrimitive', ['data', 'path', 'value', 'is_leaf_list'])
|
||||
|
||||
leaf_is_dict = ReportPrimitive({}, ('summary',), 'We better fix this!', False)
|
||||
@@ -103,6 +102,64 @@ def test_report_tags_and_flags():
|
||||
assert Flags(["This is a new flag", Groups.INHIBITOR]).value == ["This is a new flag", "inhibitor"]
|
||||
|
||||
|
||||
+@pytest.mark.parametrize('command, expected_command_form', [
|
||||
+ (['cmd'], "cmd"),
|
||||
+ (['cmd', ''], "cmd ''"),
|
||||
+ (['cmd', 'not_quoted'], "cmd not_quoted"),
|
||||
+ (['ls', '-la', '/home/user'], "ls -la /home/user"),
|
||||
+
|
||||
+ # Quoting ' '
|
||||
+ (['cmd', 'is quoted'], "cmd 'is quoted'"),
|
||||
+ (['mv', '/home/user/test file', '/home/user/test_file'], "mv '/home/user/test file' /home/user/test_file"),
|
||||
+
|
||||
+ # Quoting '$'
|
||||
+ # Note: Execution of the first command would fail, but it is the correct conversion.
|
||||
+ # The second test case should be used to utilize the shell expansion.
|
||||
+ (['chsh', '-s', '$(which zsh)', '$USER'], "chsh -s '$(which zsh)' '$USER'"),
|
||||
+ (['bash', '-c', 'chsh -s $(which zsh) $USER'], "bash -c 'chsh -s $(which zsh) $USER'"),
|
||||
+
|
||||
+ # Quoting '\'
|
||||
+ (['echo', '\\'], "echo '\\'"),
|
||||
+ (['sed', '-i', 's/\\t/ /g', 'file.txt'], "sed -i 's/\\t/ /g' file.txt"),
|
||||
+
|
||||
+ # Quoting '"'
|
||||
+ (['echo', '"'], "echo '\"'"),
|
||||
+ (['grep', 'key="value"', 'file.txt'], "grep 'key=\"value\"' file.txt"),
|
||||
+
|
||||
+ # Quoting '`'
|
||||
+ (['usermod', '-aG', 'wheel', '`whoami`'], "usermod -aG wheel '`whoami`'"),
|
||||
+])
|
||||
+def test_remediation_command_repr_quoting(command, expected_command_form):
|
||||
+ """Test that RemediationCommand.__repr__ properly quotes arguments with special characters."""
|
||||
+ remediation_command = RemediationCommand(value=command)
|
||||
+ assert repr(remediation_command) == f'[command] {expected_command_form}'
|
||||
+
|
||||
+
|
||||
+@pytest.mark.parametrize("report_suffix", ('.json', '.txt'))
|
||||
+def test_remediation_command_in_report(report_suffix):
|
||||
+ """Test that commands with spaces in arguments are preserved correctly in reports."""
|
||||
+ remediation_command_as_list = ["mv", "file with spaces.txt", "file_without_spaces.txt"]
|
||||
+ remediation_command_as_string = "mv 'file with spaces.txt' file_without_spaces.txt"
|
||||
+
|
||||
+ report_entries = [Title('Test title'), Summary('Test summary'), Audience('sysadmin')]
|
||||
+ remediation = Remediation(commands=[remediation_command_as_list])
|
||||
+ report_entries.append(remediation)
|
||||
+
|
||||
+ report_message = _create_report_object(report_entries).report
|
||||
+
|
||||
+ with tempfile.NamedTemporaryFile(suffix=report_suffix) as reportfile:
|
||||
+ generate_report_file([report_message], 'leapp-run-id', reportfile.name)
|
||||
+ with open(reportfile.name) as f:
|
||||
+ content = f.read()
|
||||
+ if report_suffix == '.txt':
|
||||
+ assert remediation_command_as_string in content
|
||||
+ else:
|
||||
+ report_data = json.loads(content)
|
||||
+ remediations = report_data['entries'][0]['detail']['remediations']
|
||||
+ cmd_entry = [r for r in remediations if r['type'] == 'command'][0]
|
||||
+ assert cmd_entry['context'] == remediation_command_as_list
|
||||
+
|
||||
+
|
||||
@pytest.mark.parametrize("report_suffix", ('.json', '.txt'))
|
||||
def test_remediation_with_non_ascii_value(report_suffix):
|
||||
report_entries = [Title('Some report title'), Summary('Some summary not used for dynamical key generation'),
|
||||
--
|
||||
2.53.0
|
||||
|
||||
171
0008-fixup-reporting-fix-incorrect-converting-of-list-bas.patch
Normal file
171
0008-fixup-reporting-fix-incorrect-converting-of-list-bas.patch
Normal file
@ -0,0 +1,171 @@
|
||||
From ad50bb2bdcc8a4b734c82f9d190dfe8c1611903a Mon Sep 17 00:00:00 2001
|
||||
From: Peter Mocary <pmocary@redhat.com>
|
||||
Date: Wed, 25 Mar 2026 19:20:22 +0100
|
||||
Subject: [PATCH 08/10] fixup! reporting: fix incorrect converting of list
|
||||
based commands
|
||||
|
||||
---
|
||||
leapp/reporting/__init__.py | 34 ++++++++++++++++---
|
||||
tests/scripts/test_reporting.py | 60 ++++++++++++++++++++++++++++++---
|
||||
2 files changed, 86 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/leapp/reporting/__init__.py b/leapp/reporting/__init__.py
|
||||
index ca2b80b..6bd0b49 100644
|
||||
--- a/leapp/reporting/__init__.py
|
||||
+++ b/leapp/reporting/__init__.py
|
||||
@@ -4,9 +4,11 @@ import json
|
||||
import logging
|
||||
import os
|
||||
import shlex
|
||||
+
|
||||
import six
|
||||
|
||||
from leapp.compat import string_types
|
||||
+
|
||||
# NOTE(pstodulk): the format_list is imported to provide the function
|
||||
# also in this library. Its use is not planned here however.
|
||||
from leapp.libraries.stdlib import format_list
|
||||
@@ -273,6 +275,32 @@ def _guarantee_decoded_str(text, encoding='utf-8'):
|
||||
return text
|
||||
|
||||
|
||||
+def _quote_for_shell(s):
|
||||
+ """
|
||||
+ Quote a string for shell usage as a literal.
|
||||
+
|
||||
+ This function quotes the given string in single-quotes using the
|
||||
+ shlex.quote. However, when the single-quote is present in the string it
|
||||
+ instead uses double-quotes, resulting in cleaner output (e.g. "don't"
|
||||
+ instead of 'don'"'"'t' that would be produced by shlex.quote).
|
||||
+
|
||||
+ :param str s: String to quote for shell usage
|
||||
+ :return str: Quoted string safe for shell usage
|
||||
+ """
|
||||
+
|
||||
+ if "'" not in s:
|
||||
+ return shlex.quote(s)
|
||||
+
|
||||
+ # The string contains a single-quote, use double-quote style instead.
|
||||
+ # Escape following characters to make it literal: \ " $ ` !
|
||||
+ escaped = (s.replace('\\', '\\\\')
|
||||
+ .replace('"', '\\"')
|
||||
+ .replace('$', '\\$')
|
||||
+ .replace('`', '\\`')
|
||||
+ .replace('!', '\\!'))
|
||||
+ return '"{}"'.format(escaped)
|
||||
+
|
||||
+
|
||||
class RemediationCommand(BaseRemediation):
|
||||
def __init__(self, value=None):
|
||||
if not isinstance(value, list):
|
||||
@@ -282,10 +310,8 @@ class RemediationCommand(BaseRemediation):
|
||||
def __repr__(self):
|
||||
# NOTE(ivasilev) As the message can contain non-ascii characters let's deal with it properly.
|
||||
# As per python practices repr has to return an encoded string
|
||||
- # Note(pmocary) Using shlex.join is not possible here due to it being available from Python 3.8,
|
||||
- # thus we use the shlex.quote on each argument instead which is the same as shlex.join implementation.
|
||||
- return "[{}] {}".format(self._value['type'],
|
||||
- ' '.join([shlex.quote(_guarantee_encoded_str(c)) for c in self._value['context']]))
|
||||
+ quoted_command_args = [_quote_for_shell(_guarantee_encoded_str(c)) for c in self._value['context']]
|
||||
+ return "[{}] {}".format(self._value['type'], ' '.join(quoted_command_args))
|
||||
|
||||
|
||||
class RemediationHint(BaseRemediation):
|
||||
diff --git a/tests/scripts/test_reporting.py b/tests/scripts/test_reporting.py
|
||||
index 8c284cb..2a4e724 100644
|
||||
--- a/tests/scripts/test_reporting.py
|
||||
+++ b/tests/scripts/test_reporting.py
|
||||
@@ -1,20 +1,31 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
-from collections import namedtuple
|
||||
import datetime
|
||||
import json
|
||||
import os
|
||||
import tempfile
|
||||
+from collections import namedtuple
|
||||
|
||||
import jsonschema
|
||||
import pytest
|
||||
|
||||
from leapp.reporting import (
|
||||
- _add_to_dict,
|
||||
_DEPRECATION_SEVERITY_THRESHOLD,
|
||||
+ Audience,
|
||||
+ Flags,
|
||||
+ Groups,
|
||||
+ Key,
|
||||
+ RelatedResource,
|
||||
+ Remediation,
|
||||
+ RemediationCommand,
|
||||
+ Severity,
|
||||
+ Summary,
|
||||
+ Tags,
|
||||
+ Title,
|
||||
+ _add_to_dict,
|
||||
+ _create_report_object,
|
||||
+ _quote_for_shell,
|
||||
create_report_from_deprecation,
|
||||
create_report_from_error,
|
||||
- _create_report_object,
|
||||
- Audience, Flags, Groups, Key, RelatedResource, Remediation, RemediationCommand, Summary, Severity, Tags, Title
|
||||
)
|
||||
from leapp.utils.report import generate_report_file
|
||||
|
||||
@@ -102,6 +113,40 @@ def test_report_tags_and_flags():
|
||||
assert Flags(["This is a new flag", Groups.INHIBITOR]).value == ["This is a new flag", "inhibitor"]
|
||||
|
||||
|
||||
+@pytest.mark.parametrize('string, expected_quoted', [
|
||||
+ # No quoting needed
|
||||
+ ('path/to_the/file-name.txt', 'path/to_the/file-name.txt'),
|
||||
+ ('user@host', 'user@host'),
|
||||
+ ('value=123', 'value=123'),
|
||||
+ ('a:b:c', 'a:b:c'),
|
||||
+ ('99%', '99%'),
|
||||
+ ('a+b', 'a+b'),
|
||||
+
|
||||
+ # Single-quote style (no single quote in string)
|
||||
+ ('', "''"),
|
||||
+ ('file with spaces.txt', "'file with spaces.txt'"),
|
||||
+ ('$(whoami)', "'$(whoami)'"),
|
||||
+ ('$USER', "'$USER'"),
|
||||
+ ('back`tick', "'back`tick'"),
|
||||
+ ('double"quote', "'double\"quote'"),
|
||||
+ ('exclaim!', "'exclaim!'"),
|
||||
+ ('back\\slash', "'back\\slash'"),
|
||||
+ ('new\nline', "'new\nline'"),
|
||||
+ ('key="value"', "'key=\"value\"'"),
|
||||
+
|
||||
+ # Double-quote style (a single quote in string)
|
||||
+ ("It's fine", "\"It's fine\""),
|
||||
+ ("It's `whoami`", "\"It's \\`whoami\\`\""),
|
||||
+ ("User's home: $HOME", "\"User's home: \\$HOME\""),
|
||||
+ ("Don't panic!", "\"Don't panic\\!\""),
|
||||
+ ("s/'/\"/g", "\"s/'/\\\"/g\""),
|
||||
+ ("sed -i 's/'/\"/g' file.txt", "\"sed -i 's/'/\\\"/g' file.txt\""),
|
||||
+])
|
||||
+def test_quote_for_shell(string, expected_quoted):
|
||||
+ """Test that _quote_for_shell properly quotes strings for shell usage."""
|
||||
+ assert _quote_for_shell(string) == expected_quoted
|
||||
+
|
||||
+
|
||||
@pytest.mark.parametrize('command, expected_command_form', [
|
||||
(['cmd'], "cmd"),
|
||||
(['cmd', ''], "cmd ''"),
|
||||
@@ -128,6 +173,13 @@ def test_report_tags_and_flags():
|
||||
|
||||
# Quoting '`'
|
||||
(['usermod', '-aG', 'wheel', '`whoami`'], "usermod -aG wheel '`whoami`'"),
|
||||
+
|
||||
+ # Double-quote style when single quote is present
|
||||
+ (['echo', "It's fine"], "echo \"It's fine\""),
|
||||
+ (['mv', "user's file.txt", 'newfile.txt'], "mv \"user's file.txt\" newfile.txt"),
|
||||
+ (['sed', '-i', "s/'/\"/g", 'file.txt'], "sed -i \"s/'/\\\"/g\" file.txt"),
|
||||
+ (['bash', '-c', "echo \"user's home: $HOME\""], "bash -c \"echo \\\"user's home: \\$HOME\\\"\""),
|
||||
+ (['grep', "can't find", '/var/log/some report.log'], "grep \"can't find\" '/var/log/some report.log'"),
|
||||
])
|
||||
def test_remediation_command_repr_quoting(command, expected_command_form):
|
||||
"""Test that RemediationCommand.__repr__ properly quotes arguments with special characters."""
|
||||
--
|
||||
2.53.0
|
||||
|
||||
37
0009-python-test-deps-update-pytest-requirements.patch
Normal file
37
0009-python-test-deps-update-pytest-requirements.patch
Normal file
@ -0,0 +1,37 @@
|
||||
From bf931901cdc18275aed2023e5c37da0e246ae8a7 Mon Sep 17 00:00:00 2001
|
||||
From: Petr Stodulka <pstodulk@redhat.com>
|
||||
Date: Tue, 14 Apr 2026 14:21:39 +0200
|
||||
Subject: [PATCH 09/10] python test deps: update pytest requirements
|
||||
|
||||
Originally we required pytest v6.2.5 for any python. This is
|
||||
pretty old requirement coming from time of python ~ 3.8 and recently
|
||||
a CVE-2025-71176 occuared, which is fix in pytest v9.0.3.
|
||||
So let's update ranges to actually allow use of newer pytest on newer
|
||||
systems:
|
||||
|
||||
+----------------+---------------+
|
||||
| pytest version | python range |
|
||||
+----------------+---------------+
|
||||
| 6.2.5 | 3.7- |
|
||||
| 7.4.4 | 3.8.x - 3.9.x |
|
||||
| 9.0.3 | 3.10+ |
|
||||
+----------------+---------------+
|
||||
---
|
||||
requirements-tests.txt | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/requirements-tests.txt b/requirements-tests.txt
|
||||
index d4501f2..5859a2a 100644
|
||||
--- a/requirements-tests.txt
|
||||
+++ b/requirements-tests.txt
|
||||
@@ -7,4 +7,6 @@ jsonschema==3.2.0
|
||||
mock
|
||||
pylint
|
||||
pytest-cov
|
||||
-pytest==6.2.5
|
||||
+pytest==6.2.5; python_version < '3.8'
|
||||
+pytest==7.4.4; python_version >= '3.8' and python_version < '3.10'
|
||||
+pytest==9.0.3; python_version >= '3.10'
|
||||
--
|
||||
2.53.0
|
||||
|
||||
173
0010-fix-reporting-use-single-quoting-when-converting-rem.patch
Normal file
173
0010-fix-reporting-use-single-quoting-when-converting-rem.patch
Normal file
@ -0,0 +1,173 @@
|
||||
From eaf4af1a549b3cb675f49f03d46d9d5de362753f Mon Sep 17 00:00:00 2001
|
||||
From: Peter Mocary <pmocary@redhat.com>
|
||||
Date: Fri, 10 Apr 2026 21:51:42 +0200
|
||||
Subject: [PATCH 10/10] fix(reporting): use single quoting when converting
|
||||
remediation commands
|
||||
|
||||
The remediation commands are provided as a list of arguments that is
|
||||
used in leapp-report.json. The same command is also converted to a
|
||||
string that is used in leapp-report.txt and can be copy-pasted by the
|
||||
user into shell.
|
||||
|
||||
Originally, the command conversion tried to make the resulting commands
|
||||
prettier by enabling double quoting whenever there was a single quote in
|
||||
an argument, while still trying to make the double quoted argument a
|
||||
literal. This proved to be problematic approach due to multiple cases
|
||||
that resulted with incorrect commands. Namely, when the command called
|
||||
`bash -c` with a subcommand that would be evaluated by another
|
||||
non-interactive shell, or when there was an exclamation mark that would
|
||||
have different meaning in non-interactive and interactive shell and its
|
||||
escaping was not possible unless single-quotes are used.
|
||||
|
||||
This patch makes the command conversion produce pretty commands in the
|
||||
most cases, moreover, it makes sure the command is always correct (if
|
||||
the list version is correct to begin with). This approach leaves
|
||||
possibility to encounter unintuitive escaping in the resulting converted
|
||||
command, although this can be prevented by carefully crafting the
|
||||
command when creating the report.
|
||||
|
||||
Note that if there is a subcommand called in the converted command, the
|
||||
report creator is responsible for its form and for the best resulting
|
||||
command it should favor the double quoting of its arguments when
|
||||
possible.
|
||||
---
|
||||
leapp/reporting/__init__.py | 28 +------------------
|
||||
packaging/leapp.spec | 2 +-
|
||||
tests/scripts/test_reporting.py | 48 +++++----------------------------
|
||||
3 files changed, 9 insertions(+), 69 deletions(-)
|
||||
|
||||
diff --git a/leapp/reporting/__init__.py b/leapp/reporting/__init__.py
|
||||
index 6bd0b49..43aa17d 100644
|
||||
--- a/leapp/reporting/__init__.py
|
||||
+++ b/leapp/reporting/__init__.py
|
||||
@@ -275,32 +275,6 @@ def _guarantee_decoded_str(text, encoding='utf-8'):
|
||||
return text
|
||||
|
||||
|
||||
-def _quote_for_shell(s):
|
||||
- """
|
||||
- Quote a string for shell usage as a literal.
|
||||
-
|
||||
- This function quotes the given string in single-quotes using the
|
||||
- shlex.quote. However, when the single-quote is present in the string it
|
||||
- instead uses double-quotes, resulting in cleaner output (e.g. "don't"
|
||||
- instead of 'don'"'"'t' that would be produced by shlex.quote).
|
||||
-
|
||||
- :param str s: String to quote for shell usage
|
||||
- :return str: Quoted string safe for shell usage
|
||||
- """
|
||||
-
|
||||
- if "'" not in s:
|
||||
- return shlex.quote(s)
|
||||
-
|
||||
- # The string contains a single-quote, use double-quote style instead.
|
||||
- # Escape following characters to make it literal: \ " $ ` !
|
||||
- escaped = (s.replace('\\', '\\\\')
|
||||
- .replace('"', '\\"')
|
||||
- .replace('$', '\\$')
|
||||
- .replace('`', '\\`')
|
||||
- .replace('!', '\\!'))
|
||||
- return '"{}"'.format(escaped)
|
||||
-
|
||||
-
|
||||
class RemediationCommand(BaseRemediation):
|
||||
def __init__(self, value=None):
|
||||
if not isinstance(value, list):
|
||||
@@ -310,7 +284,7 @@ class RemediationCommand(BaseRemediation):
|
||||
def __repr__(self):
|
||||
# NOTE(ivasilev) As the message can contain non-ascii characters let's deal with it properly.
|
||||
# As per python practices repr has to return an encoded string
|
||||
- quoted_command_args = [_quote_for_shell(_guarantee_encoded_str(c)) for c in self._value['context']]
|
||||
+ quoted_command_args = [shlex.quote(_guarantee_encoded_str(c)) for c in self._value['context']]
|
||||
return "[{}] {}".format(self._value['type'], ' '.join(quoted_command_args))
|
||||
|
||||
|
||||
diff --git a/packaging/leapp.spec b/packaging/leapp.spec
|
||||
index ba906cf..0fde883 100644
|
||||
--- a/packaging/leapp.spec
|
||||
+++ b/packaging/leapp.spec
|
||||
@@ -13,7 +13,7 @@
|
||||
# This is kind of help for more flexible development of leapp repository,
|
||||
# so people do not have to wait for new official release of leapp to ensure
|
||||
# it is installed/used the compatible one.
|
||||
-%global framework_version 6.4
|
||||
+%global framework_version 6.5
|
||||
|
||||
# IMPORTANT: everytime the requirements are changed, increment number by one
|
||||
# - same for Provides in deps subpackage
|
||||
diff --git a/tests/scripts/test_reporting.py b/tests/scripts/test_reporting.py
|
||||
index 2a4e724..2010d29 100644
|
||||
--- a/tests/scripts/test_reporting.py
|
||||
+++ b/tests/scripts/test_reporting.py
|
||||
@@ -23,7 +23,6 @@ from leapp.reporting import (
|
||||
Title,
|
||||
_add_to_dict,
|
||||
_create_report_object,
|
||||
- _quote_for_shell,
|
||||
create_report_from_deprecation,
|
||||
create_report_from_error,
|
||||
)
|
||||
@@ -113,40 +112,6 @@ def test_report_tags_and_flags():
|
||||
assert Flags(["This is a new flag", Groups.INHIBITOR]).value == ["This is a new flag", "inhibitor"]
|
||||
|
||||
|
||||
-@pytest.mark.parametrize('string, expected_quoted', [
|
||||
- # No quoting needed
|
||||
- ('path/to_the/file-name.txt', 'path/to_the/file-name.txt'),
|
||||
- ('user@host', 'user@host'),
|
||||
- ('value=123', 'value=123'),
|
||||
- ('a:b:c', 'a:b:c'),
|
||||
- ('99%', '99%'),
|
||||
- ('a+b', 'a+b'),
|
||||
-
|
||||
- # Single-quote style (no single quote in string)
|
||||
- ('', "''"),
|
||||
- ('file with spaces.txt', "'file with spaces.txt'"),
|
||||
- ('$(whoami)', "'$(whoami)'"),
|
||||
- ('$USER', "'$USER'"),
|
||||
- ('back`tick', "'back`tick'"),
|
||||
- ('double"quote', "'double\"quote'"),
|
||||
- ('exclaim!', "'exclaim!'"),
|
||||
- ('back\\slash', "'back\\slash'"),
|
||||
- ('new\nline', "'new\nline'"),
|
||||
- ('key="value"', "'key=\"value\"'"),
|
||||
-
|
||||
- # Double-quote style (a single quote in string)
|
||||
- ("It's fine", "\"It's fine\""),
|
||||
- ("It's `whoami`", "\"It's \\`whoami\\`\""),
|
||||
- ("User's home: $HOME", "\"User's home: \\$HOME\""),
|
||||
- ("Don't panic!", "\"Don't panic\\!\""),
|
||||
- ("s/'/\"/g", "\"s/'/\\\"/g\""),
|
||||
- ("sed -i 's/'/\"/g' file.txt", "\"sed -i 's/'/\\\"/g' file.txt\""),
|
||||
-])
|
||||
-def test_quote_for_shell(string, expected_quoted):
|
||||
- """Test that _quote_for_shell properly quotes strings for shell usage."""
|
||||
- assert _quote_for_shell(string) == expected_quoted
|
||||
-
|
||||
-
|
||||
@pytest.mark.parametrize('command, expected_command_form', [
|
||||
(['cmd'], "cmd"),
|
||||
(['cmd', ''], "cmd ''"),
|
||||
@@ -174,12 +139,13 @@ def test_quote_for_shell(string, expected_quoted):
|
||||
# Quoting '`'
|
||||
(['usermod', '-aG', 'wheel', '`whoami`'], "usermod -aG wheel '`whoami`'"),
|
||||
|
||||
- # Double-quote style when single quote is present
|
||||
- (['echo', "It's fine"], "echo \"It's fine\""),
|
||||
- (['mv', "user's file.txt", 'newfile.txt'], "mv \"user's file.txt\" newfile.txt"),
|
||||
- (['sed', '-i', "s/'/\"/g", 'file.txt'], "sed -i \"s/'/\\\"/g\" file.txt"),
|
||||
- (['bash', '-c', "echo \"user's home: $HOME\""], "bash -c \"echo \\\"user's home: \\$HOME\\\"\""),
|
||||
- (['grep', "can't find", '/var/log/some report.log'], "grep \"can't find\" '/var/log/some report.log'"),
|
||||
+ # Single quote in argument — shlex.quote uses the '"'"' pattern
|
||||
+ (['echo', "It's fine"], "echo 'It'\"'\"'s fine'"),
|
||||
+ (['mv', "user's file.txt", 'newfile.txt'], "mv 'user'\"'\"'s file.txt' newfile.txt"),
|
||||
+ (['sed', '-i', "s/'/\"/g", 'file.txt'], "sed -i 's/'\"'\"'/\"/g' file.txt"),
|
||||
+ (['bash', '-c', "echo \"user's home: $HOME\""], "bash -c 'echo \"user'\"'\"'s home: $HOME\"'"),
|
||||
+ (['grep', "can't find", '/var/log/some report.log'], "grep 'can'\"'\"'t find' '/var/log/some report.log'"),
|
||||
+ (['echo', "Don't panic!"], "echo 'Don'\"'\"'t panic!'"),
|
||||
])
|
||||
def test_remediation_command_repr_quoting(command, expected_command_form):
|
||||
"""Test that RemediationCommand.__repr__ properly quotes arguments with special characters."""
|
||||
--
|
||||
2.53.0
|
||||
|
||||
32
leapp.spec
32
leapp.spec
@ -7,7 +7,7 @@
|
||||
# it. In case of upstream, dependencies are set differently, but YUM is not
|
||||
# capable enough to deal with them correctly all the time; we continue to use
|
||||
# simplified deps in RHEL to ensure that YUM can deal with it.
|
||||
%global framework_version 6.2
|
||||
%global framework_version 6.5
|
||||
|
||||
# IMPORTANT: everytime the requirements are changed, increment number by one
|
||||
# - same for Provides in deps subpackage
|
||||
@ -37,7 +37,7 @@
|
||||
|
||||
Name: leapp
|
||||
Version: 0.21.0
|
||||
Release: 1%{?dist}
|
||||
Release: 2%{?dist}
|
||||
Summary: OS & Application modernization framework
|
||||
|
||||
License: ASL 2.0
|
||||
@ -65,6 +65,17 @@ Requires: leapp-repository
|
||||
|
||||
# PATCHES HERE
|
||||
# Patch0001: filename.patch
|
||||
Patch0001: 0001-introduce-the-format_list-function.patch
|
||||
Patch0002: 0002-packit-remove-unsupported-upgrade-path-from-tests.patch
|
||||
Patch0003: 0003-packit-add-new-upgrade-paths-to-tests.patch
|
||||
Patch0004: 0004-chore-deps-update-actions-checkout-action-to-v6.patch
|
||||
Patch0005: 0005-chore-deps-update-actions-github-script-action-to-v8.patch
|
||||
Patch0006: 0006-chore-deps-update-peter-evans-create-or-update-comme.patch
|
||||
Patch0007: 0007-reporting-fix-incorrect-converting-of-list-based-com.patch
|
||||
Patch0008: 0008-fixup-reporting-fix-incorrect-converting-of-list-bas.patch
|
||||
Patch0009: 0009-python-test-deps-update-pytest-requirements.patch
|
||||
Patch0010: 0010-fix-reporting-use-single-quoting-when-converting-rem.patch
|
||||
|
||||
|
||||
%description
|
||||
Leapp utility provides the possibility to use the Leapp framework via CLI.
|
||||
@ -161,7 +172,16 @@ Requires: findutils
|
||||
|
||||
# APPLY REGISTERED PATCHES HERE
|
||||
# %%patch -P 0001 -p1
|
||||
|
||||
%patch -P 0001 -p1
|
||||
%patch -P 0002 -p1
|
||||
%patch -P 0003 -p1
|
||||
%patch -P 0004 -p1
|
||||
%patch -P 0005 -p1
|
||||
%patch -P 0006 -p1
|
||||
%patch -P 0007 -p1
|
||||
%patch -P 0008 -p1
|
||||
%patch -P 0009 -p1
|
||||
%patch -P 0010 -p1
|
||||
##################################################
|
||||
# Build
|
||||
##################################################
|
||||
@ -245,6 +265,12 @@ install -m 0644 -p man/leapp.1 %{buildroot}%{_mandir}/man1/
|
||||
# no files here
|
||||
|
||||
%changelog
|
||||
* Fri Apr 17 2026 Matej Matuska <mmatuska@redhat.com> - 0.21.0-1
|
||||
- Bump leapp-framework to 6.5
|
||||
- Change how commands are converted for text based report from the list representation
|
||||
- Introduce the format_list function for unified presentation of lists in reports and logs
|
||||
- Resolves: RHEL-169278
|
||||
|
||||
* Tue Feb 10 2026 Matej Matuska <mmatuska@redhat.com> - 0.21.0
|
||||
- Rebase to version 0.21.0
|
||||
- Resolves: RHEL-128270
|
||||
|
||||
@ -6,11 +6,11 @@ summary: Internal Tier0 tests
|
||||
|
||||
environment:
|
||||
SOURCE_RELEASE: '8.10'
|
||||
TARGET_RELEASE: '9.8'
|
||||
TARGET_RELEASE: '9.9'
|
||||
|
||||
context:
|
||||
distro: rhel-8.10
|
||||
distro_target: rhel-9.8
|
||||
distro_target: rhel-9.9
|
||||
|
||||
adjust:
|
||||
- enabled: false
|
||||
|
||||
Loading…
Reference in New Issue
Block a user