Repository: canonical/charmcraft

Issue:
reactive plugin charm tools version validation code is britle
The charm tools may soon remove the now redundant legacy charm store code, when that happens the output from the version command may no longer use the format expected here:
https://github.com/canonical/charmcraft/blob/dbf82a0fbaa6633248bb213d3943603c1e7c50a6/charmcraft/reactive_plugin.py#L64-L65

I would recommend either using the `--format json` argument or looking for the `charm-tools` string in the output rather than relying on there being a newline character there.

Ref: https://github.com/juju/charm-tools/blob/17812f0e00ad634f8440053d43d1a5370a71fa50/charmtools/version.py#L15-L25

Discussion:

Patch:
diff --git a/charmcraft/reactive_plugin.py b/charmcraft/reactive_plugin.py
index bc50b20f..337ac493 100644
--- a/charmcraft/reactive_plugin.py
+++ b/charmcraft/reactive_plugin.py
@@ -14,6 +14,7 @@
 
 """Charmcraft's reactive plugin for craft-parts."""
 
+import json
 import shlex
 import subprocess
 import sys
@@ -61,14 +62,19 @@ class ReactivePluginEnvironmentValidator(plugins.validator.PluginEnvironmentVali
         :raises PluginEnvironmentValidationError: If the environment is invalid.
         """
         try:
-            output = self._execute("charm version").strip()
-            _, tools_version = output.split("\n")
-
-            if not tools_version.startswith("charm-tools"):
+            version_data = json.loads(self._execute("charm version --format json"))
+
+            tool_name = "charm-tools"
+            if not (
+                tool_name in version_data
+                and "version" in version_data[tool_name]
+                and "git" in version_data[tool_name]
+            ):
                 raise PluginEnvironmentValidationError(
                     part_name=self._part_name,
-                    reason=f"invalid charm tools version {tools_version}",
+                    reason=f"invalid charm tools version {version_data}",
                 )
+            tools_version = f"{tool_name} {version_data[tool_name]['version']} ({version_data[tool_name]['git']})"
             emit.debug(f"found {tools_version}")
         except ValueError as err:
             raise PluginEnvironmentValidationError(


Test patch:
diff --git a/tests/test_reactive_plugin.py b/tests/test_reactive_plugin.py
index 8e12027e..bea27156 100644
--- a/tests/test_reactive_plugin.py
+++ b/tests/test_reactive_plugin.py
@@ -36,7 +36,7 @@ def charm_exe(tmp_path):
     charm_bin = pathlib.Path(tmp_path, "mock_bin", "charm")
     charm_bin.parent.mkdir(exist_ok=True)
     charm_bin.write_text(
-        '#!/bin/sh\necho "charmstore-client 2.5.1"\necho "charm-tools version 2.8.2"'
+        '#!/bin/sh\necho \'{"charm-tools": {"version": "2.8.4", "git": "+git-7-6126e17", "gitn": 7, "gitsha": "6126e17", "pre_release": false, "snap": "+snap-x12"}}\''
     )
     charm_bin.chmod(0o755)
     yield charm_bin