diff --git a/0011-Fix-exception-in-normalize_schemas-for-conflicting-a.patch b/0011-Fix-exception-in-normalize_schemas-for-conflicting-a.patch new file mode 100644 index 0000000..bb518fc --- /dev/null +++ b/0011-Fix-exception-in-normalize_schemas-for-conflicting-a.patch @@ -0,0 +1,228 @@ +From 66883ef34b1e241838b9812a8920bf6f6fb380e0 Mon Sep 17 00:00:00 2001 +From: Matej Matuska +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 + 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 + diff --git a/0012-Makefile-add-test_no_lint.patch b/0012-Makefile-add-test_no_lint.patch new file mode 100644 index 0000000..77023c0 --- /dev/null +++ b/0012-Makefile-add-test_no_lint.patch @@ -0,0 +1,28 @@ +From 0a5b9b7bb44fbe71c97b10673be71e343abcf58c Mon Sep 17 00:00:00 2001 +From: Matej Matuska +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 + diff --git a/0013-Bump-framework_version.patch b/0013-Bump-framework_version.patch new file mode 100644 index 0000000..cfb0e7a --- /dev/null +++ b/0013-Bump-framework_version.patch @@ -0,0 +1,26 @@ +From 5aab7431b2d1db7ca149731e1a4e00df45db6a02 Mon Sep 17 00:00:00 2001 +From: Matej Matuska +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 + diff --git a/0014-chore-deps-update-actions-checkout-action-to-v7.patch b/0014-chore-deps-update-actions-checkout-action-to-v7.patch new file mode 100644 index 0000000..6caa890 --- /dev/null +++ b/0014-chore-deps-update-actions-checkout-action-to-v7.patch @@ -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 + diff --git a/0015-chore-deps-update-actions-github-script-action-to-v9.patch b/0015-chore-deps-update-actions-github-script-action-to-v9.patch new file mode 100644 index 0000000..548c49b --- /dev/null +++ b/0015-chore-deps-update-actions-github-script-action-to-v9.patch @@ -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 + diff --git a/0016-chore-deps-update-sclorg-testing-farm-as-github-acti.patch b/0016-chore-deps-update-sclorg-testing-farm-as-github-acti.patch new file mode 100644 index 0000000..77ab5a3 --- /dev/null +++ b/0016-chore-deps-update-sclorg-testing-farm-as-github-acti.patch @@ -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 + diff --git a/leapp.spec b/leapp.spec index 9bb781e..1c4782a 100644 --- a/leapp.spec +++ b/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.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 - 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 - 0.21.0-2 - Bump leapp-framework to 6.5 - Change how commands are converted for text based report from the list representation