From a249d8d4c67fadde1c93bcffe567f699accaf47c Mon Sep 17 00:00:00 2001 From: Sam Arbid Date: Thu, 3 Apr 2025 12:40:31 +0200 Subject: [PATCH 1/5] config: add support for custom package managers in CLI configuration --- invenio_cli/helpers/cli_config.py | 10 ++++++- tests/helpers/test_cli_config.py | 47 +++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/invenio_cli/helpers/cli_config.py b/invenio_cli/helpers/cli_config.py index 7373abd3..d77ba2bd 100644 --- a/invenio_cli/helpers/cli_config.py +++ b/invenio_cli/helpers/cli_config.py @@ -4,6 +4,7 @@ # Copyright (C) 2019-2020 Northwestern University. # Copyright (C) 2021 Esteban J. G. Gabancho. # Copyright (C) 2024 Graz University of Technology. +# Copyright (C) 2025 KTH Royal Institute of Technology. # # Invenio-Cli is free software; you can redistribute it and/or modify it # under the terms of the MIT License; see LICENSE file for more details. @@ -227,11 +228,18 @@ def write(cls, project_dir, flavour, replay): config_parser[cls.CLI_SECTION] = {} config_parser[cls.CLI_SECTION]["flavour"] = flavour config_parser[cls.CLI_SECTION]["logfile"] = "/logs/invenio-cli.log" - + custom_package_managers = { + "javascript_package_manager": replay.get("cookiecutter").get( + "javascript_package_manager", None + ), + } # Cookiecutter user input section config_parser[cls.COOKIECUTTER_SECTION] = {} for key, value in replay[cls.COOKIECUTTER_SECTION].items(): config_parser[cls.COOKIECUTTER_SECTION][key] = str(value) + # Set the package managers in the CLI section + if custom_package_managers.get(key) == "pnpm": + config_parser[cls.CLI_SECTION][key] = value # Generated files section config_parser[cls.FILES_SECTION] = get_created_files(project_dir) diff --git a/tests/helpers/test_cli_config.py b/tests/helpers/test_cli_config.py index a3a29a5a..7db9dab2 100644 --- a/tests/helpers/test_cli_config.py +++ b/tests/helpers/test_cli_config.py @@ -2,6 +2,7 @@ # # Copyright (C) 2019-2020 CERN. # Copyright (C) 2019-2021 Northwestern University. +# Copyright (C) 2025 KTH Royal Institute of Technology. # # Invenio-Cli is free software; you can redistribute it and/or modify it # under the terms of the MIT License; see LICENSE file for more details. @@ -10,6 +11,7 @@ import os import tempfile +from configparser import ConfigParser from pathlib import Path import pytest @@ -120,3 +122,48 @@ def test_cli_config_get_project_shortname(config_dir): cli_config = CLIConfig(config_dir) assert cli_config.get_project_shortname() == "my-site" + + +@pytest.mark.parametrize( + "package_manager, expected_in_cli", + [ + ("pnpm", True), + ("npm", False), + (None, False), + ], +) +def test_javascript_package_manager_config(package_manager, expected_in_cli, tmpdir): + """Test JavaScript package manager is correctly set in CLI config.""" + project_dir = tmpdir.mkdir("test-project") + flavour = "RDM" + replay = { + "cookiecutter": { + "project_name": "My Site", + "project_shortname": "my-site", + "project_site": "my-site.com", + "github_repo": "my-site/my-site", + "description": "Invenio RDM My Site Instance", + "author_name": "CERN", + "author_email": "info@my-site.com", + "year": "2022", + "database": "postgresql", + "search": "opensearch1", + "_template": "https://github.com/inveniosoftware/cookiecutter-invenio-rdm.git", # noqa + } + } + if package_manager is not None: + replay["cookiecutter"]["javascript_package_manager"] = package_manager + + CLIConfig.write(str(project_dir), flavour, replay) + + config = ConfigParser() + config_path = project_dir.join(CLIConfig.CONFIG_FILENAME) + config.read(str(config_path)) + + if expected_in_cli: + assert config.has_option(CLIConfig.CLI_SECTION, "javascript_package_manager") + assert config.get(CLIConfig.CLI_SECTION, "javascript_package_manager") == "pnpm" + else: + assert not config.has_option( + CLIConfig.CLI_SECTION, "javascript_package_manager" + ) From ff0e99c0d226707ee2070508166c4e8fa36f68a0 Mon Sep 17 00:00:00 2001 From: Sam Arbid Date: Thu, 12 Feb 2026 09:24:40 +0100 Subject: [PATCH 2/5] feat: default js package manager to PNPM * adjust CLI configuration to set PNPM as the default JS package manager As discussed in the Telecon. * Update tests to match the new default --- invenio_cli/helpers/cli_config.py | 14 ++++---------- tests/helpers/test_cli_config.py | 24 ++++-------------------- 2 files changed, 8 insertions(+), 30 deletions(-) diff --git a/invenio_cli/helpers/cli_config.py b/invenio_cli/helpers/cli_config.py index d77ba2bd..0595f6e5 100644 --- a/invenio_cli/helpers/cli_config.py +++ b/invenio_cli/helpers/cli_config.py @@ -4,7 +4,7 @@ # Copyright (C) 2019-2020 Northwestern University. # Copyright (C) 2021 Esteban J. G. Gabancho. # Copyright (C) 2024 Graz University of Technology. -# Copyright (C) 2025 KTH Royal Institute of Technology. +# Copyright (C) 2025-2026 KTH Royal Institute of Technology. # # Invenio-Cli is free software; you can redistribute it and/or modify it # under the terms of the MIT License; see LICENSE file for more details. @@ -100,7 +100,7 @@ def javascript_package_manager(self) -> JavascriptPackageManager: elif manager_name == PNPM.name: return PNPM() - return NPM() + return PNPM() def get_project_dir(self): """Returns path to project directory.""" @@ -228,18 +228,12 @@ def write(cls, project_dir, flavour, replay): config_parser[cls.CLI_SECTION] = {} config_parser[cls.CLI_SECTION]["flavour"] = flavour config_parser[cls.CLI_SECTION]["logfile"] = "/logs/invenio-cli.log" - custom_package_managers = { - "javascript_package_manager": replay.get("cookiecutter").get( - "javascript_package_manager", None - ), - } + config_parser[cls.CLI_SECTION]["javascript_package_manager"] = PNPM.name + # Cookiecutter user input section config_parser[cls.COOKIECUTTER_SECTION] = {} for key, value in replay[cls.COOKIECUTTER_SECTION].items(): config_parser[cls.COOKIECUTTER_SECTION][key] = str(value) - # Set the package managers in the CLI section - if custom_package_managers.get(key) == "pnpm": - config_parser[cls.CLI_SECTION][key] = value # Generated files section config_parser[cls.FILES_SECTION] = get_created_files(project_dir) diff --git a/tests/helpers/test_cli_config.py b/tests/helpers/test_cli_config.py index 7db9dab2..e18848e6 100644 --- a/tests/helpers/test_cli_config.py +++ b/tests/helpers/test_cli_config.py @@ -124,16 +124,8 @@ def test_cli_config_get_project_shortname(config_dir): assert cli_config.get_project_shortname() == "my-site" -@pytest.mark.parametrize( - "package_manager, expected_in_cli", - [ - ("pnpm", True), - ("npm", False), - (None, False), - ], -) -def test_javascript_package_manager_config(package_manager, expected_in_cli, tmpdir): - """Test JavaScript package manager is correctly set in CLI config.""" +def test_javascript_package_manager_config(tmpdir): + """Test JavaScript package manager defaults to pnpm in CLI config.""" project_dir = tmpdir.mkdir("test-project") flavour = "RDM" replay = { @@ -151,19 +143,11 @@ def test_javascript_package_manager_config(package_manager, expected_in_cli, tmp "_template": "https://github.com/inveniosoftware/cookiecutter-invenio-rdm.git", # noqa } } - if package_manager is not None: - replay["cookiecutter"]["javascript_package_manager"] = package_manager - CLIConfig.write(str(project_dir), flavour, replay) config = ConfigParser() config_path = project_dir.join(CLIConfig.CONFIG_FILENAME) config.read(str(config_path)) - if expected_in_cli: - assert config.has_option(CLIConfig.CLI_SECTION, "javascript_package_manager") - assert config.get(CLIConfig.CLI_SECTION, "javascript_package_manager") == "pnpm" - else: - assert not config.has_option( - CLIConfig.CLI_SECTION, "javascript_package_manager" - ) + assert config.has_option(CLIConfig.CLI_SECTION, "javascript_package_manager") + assert config.get(CLIConfig.CLI_SECTION, "javascript_package_manager") == "pnpm" From 693e8829c749d335424fa28ea51f0fa64ddf9aa2 Mon Sep 17 00:00:00 2001 From: Sam Arbid Date: Thu, 12 Feb 2026 11:24:22 +0100 Subject: [PATCH 3/5] fix: update search type handling in CLI config * Simplify the get_search_type method to return a default value. * Remove hardcoded search type from test configurations. --- invenio_cli/helpers/cli_config.py | 6 ++---- tests/helpers/test_cli_config.py | 3 --- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/invenio_cli/helpers/cli_config.py b/invenio_cli/helpers/cli_config.py index 0595f6e5..d95e0854 100644 --- a/invenio_cli/helpers/cli_config.py +++ b/invenio_cli/helpers/cli_config.py @@ -175,7 +175,7 @@ def get_db_type(self): return self.config[CLIConfig.COOKIECUTTER_SECTION]["database"] def get_search_type(self): - """Returns the search type (opensearch1, elasticsearch7).""" + """Returns the search type.""" sections = self.config[CLIConfig.COOKIECUTTER_SECTION] if "elasticsearch" in sections: # cookiecutter < v10 @@ -185,9 +185,7 @@ def get_search_type(self): # cookiecutter >= v10 return sections["search"] else: - raise InvenioCLIConfigError( - "`search` or `elasticsearch` field not set in .invenio file" - ) + return "opensearch2" def get_file_storage(self): """Returns the file storage (local, s3, etc.).""" diff --git a/tests/helpers/test_cli_config.py b/tests/helpers/test_cli_config.py index e18848e6..291fd0c9 100644 --- a/tests/helpers/test_cli_config.py +++ b/tests/helpers/test_cli_config.py @@ -36,7 +36,6 @@ def test_cli_config_write(): "author_email": "info@my-site.com", "year": "2022", "database": "postgresql", - "search": "opensearch1", "_template": "https://github.com/inveniosoftware/cookiecutter-invenio-rdm.git", # noqa } } @@ -69,7 +68,6 @@ def config_dir(): "author_email": "info@my-site.com", "year": "2022", "database": "postgresql", - "search": "opensearch1", "_template": "https://github.com/inveniosoftware/cookiecutter-invenio-rdm.git", # noqa } } @@ -139,7 +137,6 @@ def test_javascript_package_manager_config(tmpdir): "author_email": "info@my-site.com", "year": "2022", "database": "postgresql", - "search": "opensearch1", "_template": "https://github.com/inveniosoftware/cookiecutter-invenio-rdm.git", # noqa } } From 5387ace4038c9cba57c7e7d82093ee2bb7d48190 Mon Sep 17 00:00:00 2001 From: Sam Arbid Date: Thu, 12 Feb 2026 11:37:07 +0100 Subject: [PATCH 4/5] fix: simplify get_search_type method * Refactored get_search_type to a static method. * Removed legacy search type handling for compatibility. * Updated tests to verify new search type behavior. --- invenio_cli/helpers/cli_config.py | 17 ++++++----------- tests/helpers/test_cli_config.py | 3 ++- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/invenio_cli/helpers/cli_config.py b/invenio_cli/helpers/cli_config.py index d95e0854..c3aec634 100644 --- a/invenio_cli/helpers/cli_config.py +++ b/invenio_cli/helpers/cli_config.py @@ -174,18 +174,10 @@ def get_db_type(self): """Returns the database type (mysql, postgresql).""" return self.config[CLIConfig.COOKIECUTTER_SECTION]["database"] - def get_search_type(self): + @staticmethod + def get_search_type(): """Returns the search type.""" - sections = self.config[CLIConfig.COOKIECUTTER_SECTION] - if "elasticsearch" in sections: - # cookiecutter < v10 - version = sections["elasticsearch"] - return f"elasticsearch{version}" - elif "search" in sections: - # cookiecutter >= v10 - return sections["search"] - else: - return "opensearch2" + return "opensearch2" def get_file_storage(self): """Returns the file storage (local, s3, etc.).""" @@ -232,6 +224,9 @@ def write(cls, project_dir, flavour, replay): config_parser[cls.COOKIECUTTER_SECTION] = {} for key, value in replay[cls.COOKIECUTTER_SECTION].items(): config_parser[cls.COOKIECUTTER_SECTION][key] = str(value) + # Keep compatibility with older tooling that expects `search` to exist. + # Search backend choice has been removed and opensearch2 is fixed. + config_parser[cls.COOKIECUTTER_SECTION]["search"] = cls.get_search_type() # Generated files section config_parser[cls.FILES_SECTION] = get_created_files(project_dir) diff --git a/tests/helpers/test_cli_config.py b/tests/helpers/test_cli_config.py index 291fd0c9..bf8c0d98 100644 --- a/tests/helpers/test_cli_config.py +++ b/tests/helpers/test_cli_config.py @@ -2,7 +2,7 @@ # # Copyright (C) 2019-2020 CERN. # Copyright (C) 2019-2021 Northwestern University. -# Copyright (C) 2025 KTH Royal Institute of Technology. +# Copyright (C) 2025-2026 KTH Royal Institute of Technology. # # Invenio-Cli is free software; you can redistribute it and/or modify it # under the terms of the MIT License; see LICENSE file for more details. @@ -148,3 +148,4 @@ def test_javascript_package_manager_config(tmpdir): assert config.has_option(CLIConfig.CLI_SECTION, "javascript_package_manager") assert config.get(CLIConfig.CLI_SECTION, "javascript_package_manager") == "pnpm" + assert config.get(CLIConfig.COOKIECUTTER_SECTION, "search") == "opensearch2" From 24ada7caa8ae2214b1cff993258436231408e123 Mon Sep 17 00:00:00 2001 From: Sam Arbid Date: Thu, 12 Feb 2026 12:34:11 +0100 Subject: [PATCH 5/5] cli: fix db type to 'postgresql' in config * keep only 'postgresql' in CLIConfig as options. * Adjust tests to reflect new database and search configurations. --- invenio_cli/cli/containers.py | 2 +- invenio_cli/cli/services.py | 2 +- invenio_cli/helpers/cli_config.py | 12 +++++++----- tests/helpers/test_cli_config.py | 8 +++----- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/invenio_cli/cli/containers.py b/invenio_cli/cli/containers.py index 54b9c379..cc3a3b4e 100644 --- a/invenio_cli/cli/containers.py +++ b/invenio_cli/cli/containers.py @@ -104,7 +104,7 @@ def setup(cli_config, force, no_demo_data, stop_services, services): def status(ctx, verbose): """Checks if the services are up and running. - NOTE: currently only search, DB (postgresql/mysql) and redis are supported. + NOTE: currently only search (opensearch2), DB (postgresql) and redis are supported. """ ctx.invoke(services_status_cmd, verbose=verbose) diff --git a/invenio_cli/cli/services.py b/invenio_cli/cli/services.py index 722615fa..5796f2b2 100644 --- a/invenio_cli/cli/services.py +++ b/invenio_cli/cli/services.py @@ -82,7 +82,7 @@ def setup(cli_config, force, no_demo_data, stop_services, services): def status(cli_config, verbose): """Checks if the services are up and running. - NOTE: currently only search (OS/ES), DB (postgresql/mysql) and redis are supported. + NOTE: currently only search (opensearch2), DB (postgresql) and redis are supported. """ commands = ServicesCommands(cli_config) services = ["redis", cli_config.get_db_type(), "search"] diff --git a/invenio_cli/helpers/cli_config.py b/invenio_cli/helpers/cli_config.py index c3aec634..9d6aef61 100644 --- a/invenio_cli/helpers/cli_config.py +++ b/invenio_cli/helpers/cli_config.py @@ -170,9 +170,10 @@ def get_web_host(self): """Returns web host.""" return self.private_config[CLIConfig.CLI_SECTION].get("web_host", "127.0.0.1") - def get_db_type(self): - """Returns the database type (mysql, postgresql).""" - return self.config[CLIConfig.COOKIECUTTER_SECTION]["database"] + @staticmethod + def get_db_type(): + """Returns the database type.""" + return "postgresql" @staticmethod def get_search_type(): @@ -224,8 +225,9 @@ def write(cls, project_dir, flavour, replay): config_parser[cls.COOKIECUTTER_SECTION] = {} for key, value in replay[cls.COOKIECUTTER_SECTION].items(): config_parser[cls.COOKIECUTTER_SECTION][key] = str(value) - # Keep compatibility with older tooling that expects `search` to exist. - # Search backend choice has been removed and opensearch2 is fixed. + # Keep compatibility with older tooling that expects `database`,`search`to exist. + # Database,Search backend choice has been removed and postgresql, opensearch2 is fixed. + config_parser[cls.COOKIECUTTER_SECTION]["database"] = cls.get_db_type() config_parser[cls.COOKIECUTTER_SECTION]["search"] = cls.get_search_type() # Generated files section diff --git a/tests/helpers/test_cli_config.py b/tests/helpers/test_cli_config.py index bf8c0d98..ada7ab6e 100644 --- a/tests/helpers/test_cli_config.py +++ b/tests/helpers/test_cli_config.py @@ -35,7 +35,6 @@ def test_cli_config_write(): "author_name": "CERN", "author_email": "info@my-site.com", "year": "2022", - "database": "postgresql", "_template": "https://github.com/inveniosoftware/cookiecutter-invenio-rdm.git", # noqa } } @@ -67,7 +66,6 @@ def config_dir(): "author_name": "CERN", "author_email": "info@my-site.com", "year": "2022", - "database": "postgresql", "_template": "https://github.com/inveniosoftware/cookiecutter-invenio-rdm.git", # noqa } } @@ -122,8 +120,8 @@ def test_cli_config_get_project_shortname(config_dir): assert cli_config.get_project_shortname() == "my-site" -def test_javascript_package_manager_config(tmpdir): - """Test JavaScript package manager defaults to pnpm in CLI config.""" +def test_package_manager_and_service_defaults(tmpdir): + """Test package manager, database, and search defaults in CLI config.""" project_dir = tmpdir.mkdir("test-project") flavour = "RDM" replay = { @@ -136,7 +134,6 @@ def test_javascript_package_manager_config(tmpdir): "author_name": "CERN", "author_email": "info@my-site.com", "year": "2022", - "database": "postgresql", "_template": "https://github.com/inveniosoftware/cookiecutter-invenio-rdm.git", # noqa } } @@ -148,4 +145,5 @@ def test_javascript_package_manager_config(tmpdir): assert config.has_option(CLIConfig.CLI_SECTION, "javascript_package_manager") assert config.get(CLIConfig.CLI_SECTION, "javascript_package_manager") == "pnpm" + assert config.get(CLIConfig.COOKIECUTTER_SECTION, "database") == "postgresql" assert config.get(CLIConfig.COOKIECUTTER_SECTION, "search") == "opensearch2"