IPU 9.9 -> 10.3: CTC2 candidate 1

- Bump leapp-framework to 6.6
- Fix crash when multiple actors use the same config schema
- Resolves: RHEL-188372
This commit is contained in:
karolinku 2026-06-25 12:56:51 +02:00 committed by Petr Stodulka
parent 304491eefd
commit 8ea8962438
7 changed files with 409 additions and 2 deletions

View File

@ -0,0 +1,228 @@
From 66883ef34b1e241838b9812a8920bf6f6fb380e0 Mon Sep 17 00:00:00 2001
From: Matej Matuska <mmatuska@redhat.com>
Date: Wed, 20 May 2026 12:32:48 +0200
Subject: [PATCH 11/16] Fix exception in normalize_schemas for conflicting
actor config schemas
The normalize_schemas function incorrectly raises an exception when a
config schema (subclass of Config) is contained more than once in it's
input, regardless of whether it's a conflicting (same section and name,
but a difference in other members) or the same (same section and name).
Traceback:
Traceback (most recent call last):
File "/usr/bin/leapp", line 33, in <module>
sys.exit(load_entry_point('leapp==0.21.0', 'console_scripts', 'leapp')())
File "/usr/lib/python3.9/site-packages/leapp/cli/__init__.py", line 51, in main
cli.command.execute('leapp version {}'.format(VERSION))
File "/usr/lib/python3.9/site-packages/leapp/utils/clicmd.py", line 111, in execute
args.func(args)
File "/usr/lib/python3.9/site-packages/leapp/utils/clicmd.py", line 133, in called
self.target(args)
File "/usr/lib/python3.9/site-packages/leapp/cli/commands/upgrade/breadcrumbs.py", line 169, in wrapper
return f(*args, breadcrumbs=breadcrumbs, **kwargs)
File "/usr/lib/python3.9/site-packages/leapp/cli/commands/preupgrade/__init__.py", line 86, in preupgrade
command_utils.load_actor_configs_and_store_it_in_db(context, repositories, cfg)
File "/usr/lib/python3.9/site-packages/leapp/cli/commands/command_utils.py", line 291, in load_actor_configs_and_store_it_in_db
actor_config_schemas = actor_config.normalize_schemas(actor_config_schemas)
File "/usr/lib/python3.9/site-packages/leapp/actors/config.py", line 180, in normalize_schemas
if unique_name in added_fields and added_fields[unique_name] != field:
TypeError: 'set' object is not subscriptable
The added_fields variable is a set. The condition for checking conflicts
attempts to do indexing on the set, which is not possible in Python sets
and results in a TypeError.
This patch removes the set altogether since it doesn't bring any
advantage over just using the normalized_schemas dict.
Also add unit tests for the function.
---
leapp/actors/config.py | 44 ++++++-----
tests/scripts/test_actor_config.py | 114 +++++++++++++++++++++++++++++
2 files changed, 138 insertions(+), 20 deletions(-)
create mode 100644 tests/scripts/test_actor_config.py
diff --git a/leapp/actors/config.py b/leapp/actors/config.py
index 55775d5..d952bb6 100644
--- a/leapp/actors/config.py
+++ b/leapp/actors/config.py
@@ -169,31 +169,35 @@ def _get_config(config_dir='/etc/leapp/actor_conf.d'):
def normalize_schemas(schemas):
"""
Merge all schemas into a single dictionary and validate them for errors we can detect.
+
+ :param schemas: List of schemas to normalize
+ :type schemas: Iterable[Iterable[Type[Config]]]
+ :return A dictionary with structure: section -> name -> Config
+ :rtype: DefaultDict[str, Dict[str, Type[Config]]]
"""
- added_fields = set()
normalized_schema = defaultdict(dict)
for schema in schemas:
for field in schema:
- unique_name = (field.section, field.name)
-
+ # section and name are the unique key for a config
+ existing_field = normalized_schema[field.section].get(field.name, None)
# Error if the field has been added by another schema
- if unique_name in added_fields and added_fields[unique_name] != field:
- # TODO: Also include information on what Actor contains the
- # conflicting fields but that information isn't passed into
- # this function right now.
- message = ('Two actors added incompatible configuration items'
- ' with the same name for Section: {section},'
- ' Field: {field}'.format(section=field.section,
- field=field.name))
- log.error(message)
- raise SchemaError(message)
-
- # TODO: More validation here.
-
- # Store the fields from the schema in a way that we can easily look
- # up while validating
- added_fields.add(unique_name)
- normalized_schema[field.section][field.name] = field
+ if existing_field:
+ if existing_field != field:
+ # TODO: Also include information on what Actor contains the
+ # conflicting fields but that information isn't passed into
+ # this function right now.
+ message = (
+ 'Two actors added incompatible configuration items with'
+ ' the same name for Section: {section}, Field: {field}'
+ ).format(section=field.section, field=field.name)
+
+ log.error(message)
+ raise SchemaError(message)
+
+ # TODO: More validation here.
+
+ else:
+ normalized_schema[field.section][field.name] = field
return normalized_schema
diff --git a/tests/scripts/test_actor_config.py b/tests/scripts/test_actor_config.py
new file mode 100644
index 0000000..b8c02cd
--- /dev/null
+++ b/tests/scripts/test_actor_config.py
@@ -0,0 +1,114 @@
+from collections import defaultdict
+import pytest
+
+from leapp.actors.config import Config, SchemaError, normalize_schemas
+from leapp.models import fields
+
+
+class _TestConfigA(Config):
+ section = "test"
+ name = "a_setting"
+ type_ = fields.String()
+ description = 'Description here'
+ default = "default value"
+
+
+class _TestConfigB(Config):
+ section = "other_section"
+ name = "other_setting"
+ type_ = fields.String()
+ description = 'Description here'
+ default = "some default value"
+
+
+# conflicts in default
+class _TestConfigConflictsInDefault(Config):
+ section = "test"
+ name = "a_setting"
+ type_ = fields.String()
+ description = 'Description here'
+ default = "different than in A"
+
+
+# conflicts in type_
+class _TestConfigConflictsInType(Config):
+ section = "test"
+ name = "a_setting"
+ type_ = fields.Integer()
+ description = 'Description here'
+ default = "default value"
+
+
+@pytest.mark.parametrize(
+ "schemas",
+ [
+ # test configs from single actors are merged
+ [(_TestConfigA, _TestConfigB)],
+ # test configs from multiple actors are merged
+ [(_TestConfigA,), (_TestConfigB,)],
+ # test "deduplication"
+ [(_TestConfigA, _TestConfigA, _TestConfigB)],
+ [(_TestConfigA,), (_TestConfigA, _TestConfigB,)]
+ ],
+)
+def test_normalize_schemas_ok(schemas):
+ """
+ Test that valid schemas are detected and if required deduplicated
+ """
+ expect = defaultdict(dict)
+ expect["test"] = {"a_setting": _TestConfigA}
+ expect["other_section"] = {"other_setting": _TestConfigB}
+ ret = normalize_schemas(schemas)
+ assert ret == expect
+
+
+def test_normalize_schemas_identical():
+ """
+ Test that identical Config class objects are deduplicated
+ """
+ expect = defaultdict(dict)
+ expect["test"] = {"a_setting": _TestConfigA}
+
+ config = _TestConfigA
+
+ schemas = [(config, config)]
+ ret = normalize_schemas(schemas)
+ assert ret == expect
+
+ schemas = [(config,), (config,)]
+ ret = normalize_schemas(schemas)
+ assert ret == expect
+
+
+@pytest.mark.parametrize(
+ "schemas",
+ [
+ [(_TestConfigA, _TestConfigConflictsInDefault)],
+ [(_TestConfigA, _TestConfigConflictsInType)],
+ ]
+)
+def test_normalize_schemas_intra_conflict(schemas):
+ """
+ Test that conflicts within a single Actor config schema are detected
+ """
+ with pytest.raises(SchemaError):
+ normalize_schemas(schemas)
+
+
+@pytest.mark.parametrize(
+ "schemas",
+ [
+ [(_TestConfigA,), (_TestConfigConflictsInDefault,)],
+ [(_TestConfigA,), (_TestConfigConflictsInType,)],
+ ]
+)
+def test_normalize_schemas_inter_conflict(schemas):
+ """
+ Test that conflicts between multiple Actor config schemas are detected
+ """
+ with pytest.raises(SchemaError):
+ normalize_schemas(schemas)
+
+
+def test_normalize_schemas_empty():
+ assert normalize_schemas([]) == defaultdict(dict)
--
2.54.0

View File

@ -0,0 +1,28 @@
From 0a5b9b7bb44fbe71c97b10673be71e343abcf58c Mon Sep 17 00:00:00 2001
From: Matej Matuska <mmatuska@redhat.com>
Date: Wed, 20 May 2026 12:45:21 +0200
Subject: [PATCH 12/16] Makefile: add test_no_lint
The test rules always lints, add a variant which just tests.
---
Makefile | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/Makefile b/Makefile
index a68b8fe..dd2d8b9 100644
--- a/Makefile
+++ b/Makefile
@@ -202,6 +202,10 @@ test: lint
@ $(ENTER_VENV) \
pytest -vv --cov-report term-missing --cov=leapp tests/scripts
+test_no_lint:
+ @ $(ENTER_VENV) \
+ pytest -vv --cov-report term-missing --cov=leapp tests/scripts
+
# TODO(pstodulk): create ticket to add rhel10 for testing.... py: 3.12
test_container:
@case $(_TEST_CONTAINER) in \
--
2.54.0

View File

@ -0,0 +1,26 @@
From 5aab7431b2d1db7ca149731e1a4e00df45db6a02 Mon Sep 17 00:00:00 2001
From: Matej Matuska <mmatuska@redhat.com>
Date: Thu, 11 Jun 2026 09:43:49 +0200
Subject: [PATCH 13/16] Bump framework_version
I forgot to bump it in 66883.
---
packaging/leapp.spec | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/packaging/leapp.spec b/packaging/leapp.spec
index 0fde883..8bb258a 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.5
+%global framework_version 6.6
# IMPORTANT: everytime the requirements are changed, increment number by one
# - same for Provides in deps subpackage
--
2.54.0

View File

@ -0,0 +1,48 @@
From 5c6035379bcf58678555db5fe614d793a7237141 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Thu, 18 Jun 2026 21:36:12 +0000
Subject: [PATCH 14/16] chore(deps): update actions/checkout action to v7
---
.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 0f6b823..3f413c5 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@v6
+ uses: actions/checkout@v7
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@v6
+ uses: actions/checkout@v7
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 906a45d..6c6a1eb 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@v6
+ uses: actions/checkout@v7
with:
fetch-depth: '0'
- name: Set main to origin/main
--
2.54.0

View File

@ -0,0 +1,34 @@
From 2e6e8ceac23a2b8060115d9f9e7864a1dfcec507 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Thu, 18 Jun 2026 21:36:17 +0000
Subject: [PATCH 15/16] chore(deps): update actions/github-script action to v9
---
.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 3f413c5..b312d0d 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@v8
+ uses: actions/github-script@v9
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@v8
+ uses: actions/github-script@v9
with:
script: |
github.issues.createComment({
--
2.54.0

View File

@ -0,0 +1,26 @@
From 418a650d9211c7c010fbd265c36120ad2bde556e Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Tue, 16 Jun 2026 18:02:05 +0000
Subject: [PATCH 16/16] chore(deps): update
sclorg/testing-farm-as-github-action action to v4.3.1
---
.github/workflows/reuse-tests-8to9.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/reuse-tests-8to9.yml b/.github/workflows/reuse-tests-8to9.yml
index 811fd8e..cea90fe 100644
--- a/.github/workflows/reuse-tests-8to9.yml
+++ b/.github/workflows/reuse-tests-8to9.yml
@@ -47,7 +47,7 @@ jobs:
steps:
- name: Schedule regression testing for 8to9
id: run_test_8to9
- uses: sclorg/testing-farm-as-github-action@v4.0.0
+ uses: sclorg/testing-farm-as-github-action@v4.3.1
with:
# required
api_url: ${{ secrets.TF_ENDPOINT }}
--
2.54.0

View File

@ -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.5
%global framework_version 6.6
# 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: 2%{?dist}
Release: 3%{?dist}
Summary: OS & Application modernization framework
License: ASL 2.0
@ -76,6 +76,12 @@ 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
Patch0011: 0011-Fix-exception-in-normalize_schemas-for-conflicting-a.patch
Patch0012: 0012-Makefile-add-test_no_lint.patch
Patch0013: 0013-Bump-framework_version.patch
Patch0014: 0014-chore-deps-update-actions-checkout-action-to-v7.patch
Patch0015: 0015-chore-deps-update-actions-github-script-action-to-v9.patch
Patch0016: 0016-chore-deps-update-sclorg-testing-farm-as-github-acti.patch
%description
Leapp utility provides the possibility to use the Leapp framework via CLI.
@ -182,6 +188,12 @@ Requires: findutils
%patch -P 0008 -p1
%patch -P 0009 -p1
%patch -P 0010 -p1
%patch -P 0011 -p1
%patch -P 0012 -p1
%patch -P 0013 -p1
%patch -P 0014 -p1
%patch -P 0015 -p1
%patch -P 0016 -p1
##################################################
# Build
@ -267,6 +279,11 @@ install -m 0644 -p man/leapp.1 %{buildroot}%{_mandir}/man1/
%changelog
* Thu Jul 25 2026 Karolina Kula <kkula@redhat.com> - 0.21.0-3
- Bump leapp-framework to 6.6
- Fix crash when multiple actors use the same config schema
- Resolves: RHEL-188372
* Fri Apr 17 2026 Petr Stodulka <pstodulk@redhat.com> - 0.21.0-2
- Bump leapp-framework to 6.5
- Change how commands are converted for text based report from the list representation