Repository: pantsbuild/pants

Issue:
Helm unittest subsystem version >0.3.3 support
**Is your feature request related to a problem? Please describe.**
It seems that [the current project](https://github.com/quintush/helm-unittest) used for helm_unittests is no longer supported. Instead the maintainer proceeds the development in [the following project
](https://github.com/helm-unittest/helm-unittest).

**Describe the solution you'd like**
Does it make sense to switch unittesting to the project which is actually maintained?

Tried to do it within the configfile

```pants.toml
[helm-unittest]
version = "0.3.3"
url_template = "https://github.com/helm-unittest/helm-unittest/releases/download/v{version}/helm-unittest-{platform}-{version}.tgz"
use_unsupported_version = "warning"
known_versions = [
  "0.3.3|linux_x86_64|8ebe20f77012a5d4e7139760cabe36dd1ea38e40b26f57de3f4165d96bd486ff|21685365",
  "0.3.3|linux_arm64 |7f5e4426428cb9678f971576103df410e6fa38dd19b87fce4729f5217bd5c683|19944514",
  "0.3.3|macos_x86_64|b2298a513b3cb6482ba2e42079c93ad18be8a31a230bd4dffdeb01ec2881d0f5|21497144",
  "0.3.3|macos_arm64 |2365f5b3a99e6fc83218457046378b14039a3992e9ae96a4192bc2e43a33c742|20479438"
]
```
Errors occured:

```
16:07:27.77 [ERROR] Completed: Run Helm Unittest - pupkins/tests/pup_test.yaml - failed (exit code 1).
unknown flag: --helm3

Error: unknown flag: --helm3
```




Discussion:
Welcome to the Pantsbuild Community. This looks like your first issue here. Thanks for taking the time to write it.

If you haven't already, feel free to [come say hi on Slack](https://docs.google.com/forms/d/e/1FAIpQLSf9zgf-MXRnVDJbrVEST3urqneq7LCcy0zw8qU-GH4hPMn52A/viewform?usp=sf_link).

If you have questions, or just want to surface this issue, check out the `#development` channel.
(If you want to check it out without logging in, check out our [Linen mirror](https://chat.pantsbuild.org/))

Thanks again, and we look forward to your next Issue/PR :smile:!
Thanks for the issue report. The flag that causes the error comes from the internal implementation in the Helm backend, otherwise it would fail to run unit tests in Helm 3 charts.

It seems that this new version should be fully backwards compatible with the previous one, with the exception of the flag. So I don't see any reason to not do the upgrade.

Is it possible for you to run your tests using the builtin version or do you really need the most recent one?

Resolving patch:
diff --git a/src/python/pants/backend/helm/subsystems/unittest.py b/src/python/pants/backend/helm/subsystems/unittest.py
--- a/src/python/pants/backend/helm/subsystems/unittest.py
+++ b/src/python/pants/backend/helm/subsystems/unittest.py
@@ -2,6 +2,7 @@
 # Licensed under the Apache License, Version 2.0 (see LICENSE).
 
 from enum import Enum
+from typing import ClassVar
 
 from pants.backend.helm.util_rules.tool import (
     ExternalHelmPlugin,
@@ -25,16 +26,20 @@ class HelmUnitTestReportFormat(Enum):
 class HelmUnitTestSubsystem(ExternalHelmPlugin):
     options_scope = "helm-unittest"
     plugin_name = "unittest"
-    help = "BDD styled unit test framework for Kubernetes Helm charts as a Helm plugin. (https://github.com/quintush/helm-unittest)"
+    help = "BDD styled unit test framework for Kubernetes Helm charts as a Helm plugin. (https://github.com/helm-unittest)"
 
-    default_version = "0.2.8"
+    default_version = "0.3.3"
     default_known_versions = [
+        "0.3.3|linux_x86_64|8ebe20f77012a5d4e7139760cabe36dd1ea38e40b26f57de3f4165d96bd486ff|21685365",
+        "0.3.3|linux_arm64 |7f5e4426428cb9678f971576103df410e6fa38dd19b87fce4729f5217bd5c683|19944514",
+        "0.3.3|macos_x86_64|b2298a513b3cb6482ba2e42079c93ad18be8a31a230bd4dffdeb01ec2881d0f5|21497144",
+        "0.3.3|macos_arm64 |2365f5b3a99e6fc83218457046378b14039a3992e9ae96a4192bc2e43a33c742|20479438",
         "0.2.8|linux_x86_64|d7c452559ad4406a1197435394fbcffe51198060de1aa9b4cb6feaf876776ba0|18299096",
         "0.2.8|linux_arm64 |c793e241b063f0540ad9b4acc0a02e5a101bd9daea5bdf4d8562e9b2337fedb2|16943867",
         "0.2.8|macos_x86_64|1dc95699320894bdebf055c4f4cc084c2cfa0133d3cb7fd6a4c0adca94df5c96|18161928",
         "0.2.8|macos_arm64 |436e3167c26f71258b96e32c2877b4f97c051064db941de097cf3db2fc861342|17621648",
     ]
-    default_url_template = "https://github.com/quintush/helm-unittest/releases/download/v{version}/helm-unittest-{platform}-{version}.tgz"
+    default_url_template = "https://github.com/helm-unittest/helm-unittest/releases/download/v{version}/helm-unittest-{platform}-{version}.tgz"
     default_url_platform_mapping = {
         "linux_arm64": "linux-arm64",
         "linux_x86_64": "linux-amd64",
@@ -42,6 +47,11 @@ class HelmUnitTestSubsystem(ExternalHelmPlugin):
         "macos_x86_64": "macos-amd64",
     }
 
+    # TODO Remove after dropping support for the legacy tool
+    legacy_url_template: ClassVar[
+        str
+    ] = "https://github.com/quintush/helm-unittest/releases/download/v{version}/helm-unittest-{platform}-{version}.tgz"
+
     color = BoolOption(
         "--color",
         default=False,
@@ -55,6 +65,17 @@ class HelmUnitTestSubsystem(ExternalHelmPlugin):
 
     skip = SkipOption("test")
 
+    @property
+    def _is_legacy(self) -> bool:
+        version_parts = self.version.split(".")
+        return len(version_parts) >= 2 and version_parts[1] == "2"
+
+    def generate_url(self, plat: Platform) -> str:
+        if self._is_legacy:
+            platform = self.url_platform_mapping.get(plat.value, "")
+            return self.legacy_url_template.format(version=self.version, platform=platform)
+        return super().generate_url(plat)
+
     def generate_exe(self, _: Platform) -> str:
         return "./untt"
 
diff --git a/src/python/pants/core/util_rules/external_tool.py b/src/python/pants/core/util_rules/external_tool.py
--- a/src/python/pants/core/util_rules/external_tool.py
+++ b/src/python/pants/core/util_rules/external_tool.py
@@ -340,7 +340,7 @@ class TemplatedExternalTool(ExternalTool, TemplatedExternalToolOptionsMixin):
     The platform mapping dict is optional.
     """
 
-    def generate_url(self, plat: Platform):
+    def generate_url(self, plat: Platform) -> str:
         platform = self.url_platform_mapping.get(plat.value, "")
         return self.url_template.format(version=self.version, platform=platform)
 


Test patch:
diff --git a/src/python/pants/backend/helm/test/unittest.py b/src/python/pants/backend/helm/test/unittest.py
--- a/src/python/pants/backend/helm/test/unittest.py
+++ b/src/python/pants/backend/helm/test/unittest.py
@@ -24,6 +24,7 @@
 from pants.backend.helm.util_rules.chart import HelmChart, HelmChartRequest
 from pants.backend.helm.util_rules.sources import HelmChartRoot, HelmChartRootRequest
 from pants.backend.helm.util_rules.tool import HelmProcess
+from pants.base.deprecated import warn_or_error
 from pants.core.goals.test import TestFieldSet, TestRequest, TestResult, TestSubsystem
 from pants.core.target_types import ResourceSourceField
 from pants.core.util_rules.source_files import SourceFiles, SourceFilesRequest
@@ -126,15 +127,24 @@ async def run_helm_unittest(
         ProcessCacheScope.PER_SESSION if test_subsystem.force else ProcessCacheScope.SUCCESSFUL
     )
 
-    strict = field_set.strict.value
+    uses_legacy = unittest_subsystem._is_legacy
+    if uses_legacy:
+        warn_or_error(
+            "2.19.0.dev0",
+            f"[{unittest_subsystem.options_scope}].version < {unittest_subsystem.default_version}",
+            "You should upgrade your test suites to work with latest version.",
+            start_version="2.18.0.dev1",
+        )
+
     process_result = await Get(
         FallibleProcessResult,
         HelmProcess(
             argv=[
                 unittest_subsystem.plugin_name,
-                "--helm3",
+                # TODO remove this flag once support for legacy unittest tool is dropped.
+                *(("--helm3",) if uses_legacy else ()),
                 *(("--color",) if unittest_subsystem.color else ()),
-                *(("--strict",) if strict else ()),
+                *(("--strict",) if field_set.strict.value else ()),
                 "--output-type",
                 unittest_subsystem.output_type.value,
                 "--output-file",
diff --git a/src/python/pants/backend/helm/test/unittest_test.py b/src/python/pants/backend/helm/test/unittest_test.py
--- a/src/python/pants/backend/helm/test/unittest_test.py
+++ b/src/python/pants/backend/helm/test/unittest_test.py
@@ -79,6 +79,46 @@ def test_simple_success(rule_runner: RuleRunner) -> None:
     assert result.xml_results.files == (f"{target.address.path_safe_spec}.xml",)
 
 
+def test_simple_success_with_legacy_tool(rule_runner: RuleRunner) -> None:
+    rule_runner.write_files(
+        {
+            "BUILD": "helm_chart(name='mychart')",
+            "Chart.yaml": HELM_CHART_FILE,
+            "values.yaml": HELM_VALUES_FILE,
+            "templates/_helpers.tpl": HELM_TEMPLATE_HELPERS_FILE,
+            "templates/service.yaml": K8S_SERVICE_TEMPLATE,
+            "tests/BUILD": "helm_unittest_test(name='test', source='service_test.yaml')",
+            "tests/service_test.yaml": dedent(
+                """\
+                suite: test service
+                templates:
+                  - service.yaml
+                values:
+                  - ../values.yaml
+                tests:
+                  - it: should work
+                    asserts:
+                      - isKind:
+                          of: Service
+                      - equal:
+                          path: spec.type
+                          value: ClusterIP
+                """
+            ),
+        }
+    )
+
+    rule_runner.set_options(["--helm-unittest-version=0.2.8"])
+    target = rule_runner.get_target(Address("tests", target_name="test"))
+    field_set = HelmUnitTestFieldSet.create(target)
+
+    result = rule_runner.request(TestResult, [HelmUnitTestRequest.Batch("", (field_set,), None)])
+
+    assert result.exit_code == 0
+    assert result.xml_results and result.xml_results.files
+    assert result.xml_results.files == (f"{target.address.path_safe_spec}.xml",)
+
+
 def test_simple_failure(rule_runner: RuleRunner) -> None:
     rule_runner.write_files(
         {