Validate Helm CLI version (>= 4.2.0) before Kubernetes deploy#17491
Conversation
Aspire's Kubernetes deployment pipeline shells out to 'helm upgrade --install' for the main application chart and for any AddHelmChart(...) resources on a KubernetesEnvironmentResource. Previously we only checked that 'helm' was on PATH; we never asserted the installed Helm version was new enough for the flags and behaviors we depend on (e.g. '--server-side=true --force-conflicts' in the Helm 4 form). Missing or older Helm produced confusing low-level errors like 'unknown flag: --force-conflicts', 'Flag --force has been deprecated', or raw process-spawn failures. Changes: * Add internal HelmVersionValidator that runs 'helm version --short --client', parses the SemVer, and asserts a minimum of Helm 4.2.0. Throws a clear actionable InvalidOperationException (detected vs required + link to https://helm.sh/docs/intro/install/) when the version is too old, unparseable, or the command fails. * Wire the validator into the existing check-helm-prereqs-{env} pipeline step in HelmDeploymentEngine. One check per environment covers both the main chart deploy and AddHelmChart(...) flows since they all DependsOn this step. * Update the 'Helm CLI not found' message to also mention the minimum version requirement. * Remove the now-redundant ad-hoc 'helm version --short' probe at the top of HelmDeployAsync (the prereq step covers it with a much better error). * Promote FakeHelmRunner to a file-scoped test helper that emits canned 'helm version' stdout (defaults to v4.2.0+gfa15ec0) and supports a separate VersionExitCode, so any test exercising the deploy path automatically passes the prereq check. * Add HelmVersionValidatorTests covering: SemVer parsing of v3/v4/v5 outputs with and without '+gitsha' build metadata, rejection of unparseable output, threshold behavior for too-old versions (v4.1.0, v4.0.0, v3.18.0, v3.14.4), and that error messages include the detected version, the required version, and the install docs URL. * Document the Helm 4.2.0+ requirement in the Aspire.Hosting.Kubernetes and Aspire.Hosting.Azure.Kubernetes READMEs. Fixes #16977 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 17491Or
iex "& { $(irm https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 17491" |
|
Not for this PR but we have a whole system for this in run mode, I wonder if we can reuse it IRequiredCommandValidator |
There was a problem hiding this comment.
Pull request overview
This PR adds an explicit Helm CLI minimum-version check to Aspire’s Kubernetes deployment pipeline so users get a single actionable error when Helm is missing or too old, instead of confusing flag/spawn failures during helm upgrade --install.
Changes:
- Added
HelmVersionValidatorand wired it into the per-environmentcheck-helm-prereqs-{env}pipeline step. - Added unit tests for version parsing/threshold behavior and promoted
FakeHelmRunnerinto a reusable test helper. - Documented the Helm v4.2.0+ prerequisite in the Kubernetes hosting READMEs.
Show a summary per file
| File | Description |
|---|---|
| tests/Aspire.Hosting.Kubernetes.Tests/KubernetesDeployTests.cs | Removes the inline FakeHelmRunner in favor of a shared helper. |
| tests/Aspire.Hosting.Kubernetes.Tests/HelmVersionValidatorTests.cs | Adds unit coverage for parsing + minimum-version enforcement behavior. |
| tests/Aspire.Hosting.Kubernetes.Tests/FakeHelmRunner.cs | Introduces a shared in-memory IHelmRunner for tests with canned helm version output. |
| src/Aspire.Hosting.Kubernetes/README.md | Adds Helm v4.2.0+ as a documented prerequisite. |
| src/Aspire.Hosting.Kubernetes/Deployment/HelmVersionValidator.cs | Implements Helm version probing/parsing and minimum-version enforcement. |
| src/Aspire.Hosting.Kubernetes/Deployment/HelmDeploymentEngine.cs | Runs the prereq check once per environment and removes the old ad-hoc probe from the deploy step. |
| src/Aspire.Hosting.Azure.Kubernetes/README.md | Adds Helm v4.2.0+ as a documented prerequisite for AKS deploy flows. |
Copilot's findings
- Files reviewed: 7/7 changed files
- Comments generated: 5
The validator was invoking 'helm version --short --client', but the --client flag was removed in Helm 4 (it existed in Helm 2 for the real client/server split, was kept as a no-op in Helm 3, and is unknown in Helm 4). Since this validator's purpose is to enforce Helm 4.2.0 or later, passing --client guarantees a failure against the very minimum version we require, surfacing the exact kind of confusing prereq error this step exists to prevent. Caught by dogfood testing of PR #17491 against a local Helm 4.2.0 install, which produced: Step 'check-helm-prereqs-k8s' failed: 'helm version --short --client' failed (Error: unknown flag: --client). Aspire requires Helm 4.2.0 or later. Switch to 'helm version --short', which produces identical output shape (e.g. v4.2.0+gfa15ec0) on Helm 3 and Helm 4. Add a regression test that records the arguments passed to the runner and asserts --client is never included. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
PR Testing Report — #17491PR Information
CLI Version Verification
Changes Analyzed
Test Scenarios ExecutedScenario 1 — End-to-end
|
| Scenario | Status | Notes |
|---|---|---|
1 — aspire deploy w/ Helm 4.2.0 (happy path) |
❌ Failed on 3a088b9e |
--client flag removed in Helm 4 |
2 — Regression test (no --client ever) |
✅ Added | Locks invariant |
Overall Result
❌ Issue found and fixed in-PR. A re-dogfood of the updated PR head (ced45a67) is needed to confirm the deploy now proceeds past check-helm-prereqs-k8s on Helm 4.2.0.
Three review items from the automated PR reviewer:
1. Gate destroy/uninstall on the same Helm prereq check as deploy.
Both 'destroy-helm-{env}' and 'helm-uninstall-{env}' invoke 'helm
uninstall', so a missing or too-old Helm would surface as a raw
process-spawn / unknown-flag error during teardown instead of the
actionable validator message. Add a 'DependsOn(check-helm-prereqs-
{env})' on both, and add a regression test that asserts the
dependency edge exists.
2. Fix the misleading comment above HelmVersionRegex. The regex is
intentionally unanchored so we tolerate banner/shim lines that
some shells, oh-my-zsh plugins, or asdf-style shims can prepend
to the version output. Update the comment to describe that
intent instead of claiming a start anchor that isn't there.
3. Shorten the Helm prerequisite bullets in both Kubernetes README
files. Keep the bullet to the requirement itself and move the
'why we validate up front' narrative into a short paragraph
below, matching the scannable style of the other hosting READMEs.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The 11 DeployK8s* CLI E2E tests failed on commit d03916c because the container install scripts default HELM_VERSION to v3.17.3 — below the new HelmVersionValidator.MinimumHelmVersion (v4.2.0) that the check-helm-prereqs-{env} pipeline step now enforces. Centralize the version constants in a new tests/Aspire.Cli.EndToEnd.Tests/Helpers/KubernetesE2EVersions.cs so the default lives in one place (and points at the validator's documented minimum), then bump HelmVersion default v3.17.3 -> v4.2.0 (used by every DeployK8s* test and by the quarantined KubernetesPublishTests). HELM_VERSION / KIND_VERSION / KUBECTL_VERSION env-var overrides are preserved so CI can still bump to a newer point release without a code change. The AKS deployment workflow (deployment-tests.yml) still pins azure/setup-helm to v4.1.4 and needs the same bump to v4.2.0 to avoid breaking AKS scenarios under the new validator; that workflow file edit will land in a separate push that has 'workflow' OAuth scope. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Match Aspire.Hosting.Kubernetes' new minimum supported Helm version
(HelmVersionValidator.MinimumHelmVersion). The check-helm-prereqs-{env}
pipeline step now fails fast on older Helm CLIs, so leaving the AKS
deployment workflow pinned to v4.1.4 would break every AKS deployment
scenario. Also refresh the surrounding rationale comment, which still
referred to the historical v3.18 server-side narrative.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
/deployment-test |
|
🚀 Deployment tests starting on PR #17491... This will deploy to real Azure infrastructure. Results will be posted here when complete. |
|
✅ Deployment E2E Tests passed — 40 passed, 0 failed, 0 cancelled View test results and recordings
|
PR Testing ReportPR Information
CLI Version Verification
Changes AnalyzedFiles Changed
Change Categories
Test Environment
Test Scenarios ExecutedScenario 1: PR CLI/version verificationObjective: Install the PR dogfood CLI and verify it matches the latest PR head commit. Steps:
Evidence:
Observations:
Scenario 2: Happy-path Kubernetes deploy with Helm 4.2.0Objective: Validate that Kubernetes deployment proceeds when Helm meets the new minimum version requirement. Steps:
Evidence:
Observations:
Scenario 3: Too-old Helm rejectionObjective: Verify Aspire fails early with an actionable error when Steps:
Expected Unhappy-Path Outcome: Non-zero exit before Helm install/upgrade, with a message that includes the detected version, required version, and Helm install docs. Evidence:
Observations:
Scenario 4: Unparseable Helm output rejectionObjective: Verify Aspire fails early and clearly when Helm version output cannot be parsed. Steps:
Expected Unhappy-Path Outcome: Non-zero exit before deploy with a parse error and Helm install guidance. Evidence:
Observations:
Scenario 5: Helm version command failureObjective: Verify Aspire reports an actionable error when Steps:
Expected Unhappy-Path Outcome: Non-zero exit before deploy with command failure detail and Helm install guidance. Evidence:
Observations:
Summary
Overall Result✅ PR VERIFIED The PR CLI build for #17491 validated the new Helm prerequisite behavior on a fresh DigitalOcean droplet. Kubernetes deploy succeeds with Helm 4.2.0 and fails early with clear actionable errors for too-old, unparseable, and failing Helm version probes. Artifacts
|
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Re-running the failed jobs in the CI workflow for this pull request because 1 job was identified as retry-safe transient failures in the CI run attempt.
|
|
❓ CLI E2E Tests unknown — 107 passed, 0 failed, 2 unknown (commit View all recordings
📹 Recordings uploaded automatically from CI run #26507816679 |
|
/backport to release/13.4 |
|
Started backporting to |
|
Pull request created: #1090
|
|
📝 Documentation has been drafted in microsoft/aspire.dev#1090 targeting Updated two existing pages to document the Helm v4.2.0+ minimum prerequisite introduced by this PR:
Note This draft PR needs human review before merging. |
Description
Aspire's Kubernetes deployment pipeline shells out to
helm upgrade --installfor the main application chart and anyAddHelmChart(...)resources on aKubernetesEnvironmentResource. Previously we only checked thathelmwas onPATH; we never asserted the installed version was new enough for the flags and behaviors we depend on (notably the Helm 4 form of--server-side=true --force-conflicts). Missing or old Helm produced confusing low-level errors likeunknown flag: --force-conflicts,Flag --force has been deprecated, or raw process-spawn failures.This PR adds an up-front version assertion of Helm 4.2.0+ (the latest stable at the time of writing) and turns those cryptic failures into a single clear, actionable error.
Approach
HelmVersionValidatorthat runshelm version --short --clientthrough the existingIHelmRunnerabstraction, parses the SemVer (v?MAJOR.MINOR.PATCH, ignoring+gitshabuild metadata), and asserts the minimum. Failures include the detected version, the required version, and a link tohttps://helm.sh/docs/intro/install/.check-helm-prereqs-{env}pipeline step inHelmDeploymentEngine. One check per environment covers both the engine's main chart deploy andAddHelmChart(...)flows since they allDependsOnthis step.helm version --shortprobe at the top ofHelmDeployAsync(the prereq step covers it with a much better error).FakeHelmRunnerfrom a private test class into a shared test helper that emits cannedhelm versionstdout (defaults tov4.2.0+gfa15ec0) so any test exercising the deploy path automatically passes the new prereq check.Aspire.Hosting.KubernetesandAspire.Hosting.Azure.KubernetesREADMEs.Notes for reviewers
check-helm-prereqs-{env}uses the realPathLookupHelper.FindFullPathFromPath("helm")and would behave nondeterministically based on whetherhelmhappens to be installed on the test machine. The validator itself has 18 unit tests covering parsing, threshold behavior, and error message content.Fixes #16977
Checklist
<remarks />and<code />elements on your triple slash comments?