From 21def3bba92161c60b5f25d824e66318f22e2b7b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 3 Dec 2025 19:20:38 +0000 Subject: [PATCH 1/5] Initial plan From a5aeb0355037d65c8d06683e7924ebd45bed2c27 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 5 Dec 2025 22:56:01 +0000 Subject: [PATCH 2/5] Fix error message showing 'Library None not found' in fetch-lib When running `charmcraft fetch-lib` without arguments to update all libraries, if a library is not found in Charmhub, the error message incorrectly shows "Library None not found in Charmhub" instead of the actual library name. This fix: - Changes line 1566 to use `lib_data.full_name` instead of `parsed_args.library` so the actual library name is shown in the error message - Updates the exception handling (lines 1537-1545) to only override the error message when a specific library is requested, otherwise re-raise the original error which contains proper context Co-authored-by: lengau <4305943+lengau@users.noreply.github.com> --- charmcraft/application/commands/store.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/charmcraft/application/commands/store.py b/charmcraft/application/commands/store.py index 63e8f0728..d1dd0c44d 100644 --- a/charmcraft/application/commands/store.py +++ b/charmcraft/application/commands/store.py @@ -1534,11 +1534,15 @@ def run(self, parsed_args: argparse.Namespace) -> None: for lib in local_libs_data ] ) - except errors.LibraryError: - raise errors.LibraryError( - message=f"Library {parsed_args.library} not found in Charmhub.", - logpath_report=False, - ) + except errors.LibraryError as e: + # If a specific library was requested, use that in the error message + # Otherwise, re-raise the original error which should have details + if parsed_args.library: + raise errors.LibraryError( + message=f"Library {parsed_args.library} not found in Charmhub.", + logpath_report=False, + ) from e + raise # check if something needs to be done analysis = [] @@ -1559,7 +1563,7 @@ def run(self, parsed_args: argparse.Namespace) -> None: break else: raise errors.LibraryError( - message=f"Library {parsed_args.library} not found in Charmhub.", + message=f"Library {lib_data.full_name} not found in Charmhub.", logpath_report=False, ) emit.debug(f"Store tip: {tip}") From f29e75059a91dd7383b774efd4724df194844fac Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 5 Dec 2025 22:59:08 +0000 Subject: [PATCH 3/5] Add integration test for fetch-lib error message with no args Add a test to verify that when running `charmcraft fetch-lib` without arguments (to update all libraries), if a library is not found in Charmhub, the error message shows the actual library name instead of "None". This test creates a local library file with a fake lib_id that doesn't exist in Charmhub and verifies that the error message contains the correct library name "charms.testcharm.v0.testlib". Co-authored-by: lengau <4305943+lengau@users.noreply.github.com> --- .../commands/test_store_commands.py | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/tests/integration/commands/test_store_commands.py b/tests/integration/commands/test_store_commands.py index 04c9e04fe..22769d624 100644 --- a/tests/integration/commands/test_store_commands.py +++ b/tests/integration/commands/test_store_commands.py @@ -193,6 +193,34 @@ def test_fetchlib_store_not_found( ) +@pytest.mark.slow +def test_fetchlib_all_with_not_found( + emitter: craft_cli.pytest_plugin.RecordingEmitter, + new_path: pathlib.Path, + config, +) -> None: + """When running fetch-lib without args and a library is not found, show the library name.""" + # Create a local library file with a fake lib_id that doesn't exist in Charmhub + factory.create_lib_filepath( + "testcharm", + "testlib", + api=0, + patch=1, + lib_id="fakefakefakefakefakefakefakefake", + ) + + args = argparse.Namespace(library=None, format=None) + + with pytest.raises(errors.LibraryError) as exc_info: + FetchLibCommand(config).run(args) + + # The error message should contain the actual library name, not "None" + assert "charms.testcharm.v0.testlib" in exc_info.value.args[0] + assert exc_info.value.args[0] == ( + "Library charms.testcharm.v0.testlib not found in Charmhub." + ) + + @pytest.mark.slow @pytest.mark.parametrize("formatted", [None, "json"]) def test_fetchlib_store_is_old( From f8eb585f66f2e23af0df783e82d05e283ebfde81 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 8 Dec 2025 21:33:48 +0000 Subject: [PATCH 4/5] Remove integration test that doesn't work properly The integration test added previously doesn't work because it tries to use a fake charm that doesn't exist in Charmhub. Integration tests call the real API, so this test would fail when trying to fetch metadata for a non-existent charm. The core fix (using lib_data.full_name instead of parsed_args.library) is still in place and is the important part of this PR. Co-authored-by: lengau <4305943+lengau@users.noreply.github.com> --- .../commands/test_store_commands.py | 28 ------------------- 1 file changed, 28 deletions(-) diff --git a/tests/integration/commands/test_store_commands.py b/tests/integration/commands/test_store_commands.py index 22769d624..04c9e04fe 100644 --- a/tests/integration/commands/test_store_commands.py +++ b/tests/integration/commands/test_store_commands.py @@ -193,34 +193,6 @@ def test_fetchlib_store_not_found( ) -@pytest.mark.slow -def test_fetchlib_all_with_not_found( - emitter: craft_cli.pytest_plugin.RecordingEmitter, - new_path: pathlib.Path, - config, -) -> None: - """When running fetch-lib without args and a library is not found, show the library name.""" - # Create a local library file with a fake lib_id that doesn't exist in Charmhub - factory.create_lib_filepath( - "testcharm", - "testlib", - api=0, - patch=1, - lib_id="fakefakefakefakefakefakefakefake", - ) - - args = argparse.Namespace(library=None, format=None) - - with pytest.raises(errors.LibraryError) as exc_info: - FetchLibCommand(config).run(args) - - # The error message should contain the actual library name, not "None" - assert "charms.testcharm.v0.testlib" in exc_info.value.args[0] - assert exc_info.value.args[0] == ( - "Library charms.testcharm.v0.testlib not found in Charmhub." - ) - - @pytest.mark.slow @pytest.mark.parametrize("formatted", [None, "json"]) def test_fetchlib_store_is_old( From 026f5c1f036603ce1be393aad7ffa35f61a41a55 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 8 Dec 2025 21:48:57 +0000 Subject: [PATCH 5/5] Add tests for fetch-lib error message behavior Add integration test and spread test to verify that when running `charmcraft fetch-lib` without arguments (to update all libraries), if a library is not found in Charmhub, the error message shows the actual library name instead of "None". Integration test (test_fetchlib_all_library_not_found): - Creates a local library with a fake lib_id that doesn't exist - Runs fetch-lib without arguments - Verifies the error message contains the library name Spread test (store/libraries-not-found): - Creates a charm directory with a library using a fake lib_id - Runs fetch-lib without arguments - Verifies error message shows library name, not "None" - Verifies the error message format is correct Co-authored-by: lengau <4305943+lengau@users.noreply.github.com> --- .../commands/test_store_commands.py | 32 +++++++++++++ .../store/libraries-not-found/task.yaml | 46 +++++++++++++++++++ 2 files changed, 78 insertions(+) create mode 100644 tests/spread/store/libraries-not-found/task.yaml diff --git a/tests/integration/commands/test_store_commands.py b/tests/integration/commands/test_store_commands.py index 04c9e04fe..42f4cd9bc 100644 --- a/tests/integration/commands/test_store_commands.py +++ b/tests/integration/commands/test_store_commands.py @@ -193,6 +193,38 @@ def test_fetchlib_store_not_found( ) +@pytest.mark.slow +def test_fetchlib_all_library_not_found( + emitter: craft_cli.pytest_plugin.RecordingEmitter, + new_path: pathlib.Path, + config, +) -> None: + """When fetching all libraries, if one is not found, show its name in error message.""" + # Create a library with a fake lib_id that doesn't exist in Charmhub + # Using a lib_id that's clearly fake and won't match any real library + factory.create_lib_filepath( + "nonexistent-charm", + "nonexistent_lib", + api=0, + patch=1, + lib_id="00000000000000000000000000000000", + ) + + args = argparse.Namespace(library=None, format=None) + + with pytest.raises(errors.LibraryError) as exc_info: + FetchLibCommand(config).run(args) + + # The error message should contain the actual library name, not "None" + error_message = exc_info.value.args[0] + assert "charms.nonexistent_charm.v0.nonexistent_lib" in error_message + assert "None" not in error_message + # Verify the full error message format + assert error_message == ( + "Library charms.nonexistent_charm.v0.nonexistent_lib not found in Charmhub." + ) + + @pytest.mark.slow @pytest.mark.parametrize("formatted", [None, "json"]) def test_fetchlib_store_is_old( diff --git a/tests/spread/store/libraries-not-found/task.yaml b/tests/spread/store/libraries-not-found/task.yaml new file mode 100644 index 000000000..11d18058a --- /dev/null +++ b/tests/spread/store/libraries-not-found/task.yaml @@ -0,0 +1,46 @@ +--- +summary: test fetch-lib error message when library not found + +environment: + CHARM_NAME: nonexistent-charm-$(uuidgen | sed -e 's/-//g') + +include: + - tests/ + +prepare: | + tests.pkgs install jq + + # Create a temporary charm directory with a library that has a fake lib_id + mkdir -p charm/lib/charms/nonexistent_charm/v0 + + # Create a library file with metadata that won't exist in Charmhub + cat > charm/lib/charms/nonexistent_charm/v0/fake_lib.py << 'EOF' + # Test library with fake ID + LIBID = "00000000000000000000000000000000" + LIBAPI = 0 + LIBPATCH = 1 + + # Some library code + def test_function(): + pass + EOF + +restore: | + rm -rf charm + +execute: | + cd charm + + # Try to fetch all libraries (without specifying a library name) + # This should fail with error showing library name, not "None" + output=$(charmcraft fetch-lib 2>&1) && exit 1 || true + + # Verify the error message contains the library name + echo "$output" | MATCH "charms.nonexistent_charm.v0.fake_lib" + + # Verify the error message does NOT contain "Library None" + echo "$output" | NOMATCH "Library None" + + # Verify the full error message format + echo "$output" | \ + MATCH "Library charms.nonexistent_charm.v0.fake_lib not found"