Skip to content

feat: install Helm v4 plugins from .tgz release assets#648

Merged
yxxhero merged 13 commits intohelmfile:mainfrom
saipavan9:feat/helm-v4-plugin-tgz-install
Feb 18, 2026
Merged

feat: install Helm v4 plugins from .tgz release assets#648
yxxhero merged 13 commits intohelmfile:mainfrom
saipavan9:feat/helm-v4-plugin-tgz-install

Conversation

@saipavan9
Copy link
Contributor

@saipavan9 saipavan9 commented Feb 14, 2026

Summary

  • Fixes Helm v4 plugin compatibility where plugins installed from repo URLs register as APIVERSION: legacy and don't expose subcommands (e.g., helm secrets returns "unknown command")
  • When Helm v4+ is detected, queries the plugin's GitHub release for .tgz assets with companion .prov provenance files and installs those natively
  • Imports the plugin author's GPG public key from https://github.com/<owner>.gpg before install so Helm v4's signature verification succeeds
  • Exports imported GPG keys to legacy pubring.gpg format since Helm v4 looks for GnuPG v1 keyring, not the modern pubring.kbx
  • Falls back to the existing --verify=false legacy install for plugins without v4 packages (e.g., helm-diff)

Problem

Helm v4 overhauled its plugin system. Installing plugins via the repo URL (helm plugin install https://github.com/jkroepke/helm-secrets) registers them as legacy plugins:

NAME    VERSION  TYPE       APIVERSION  PROVENANCE  SOURCE
secrets 4.7.1    getter/v1  legacy      unknown     unknown

Legacy plugins don't register as subcommands, so helm secrets decrypt fails with Error: unknown command "secrets".

Helm v4 plugins must be installed from .tgz release archives (per helm-secrets installation docs):

helm plugin install .../secrets-4.7.1.tgz
helm plugin install .../secrets-getter-4.7.1.tgz
helm plugin install .../secrets-post-renderer-4.7.1.tgz

Additionally, Helm v4 verifies .tgz signatures against .prov provenance files by default. Without the plugin author's GPG public key in the runner's keyring, install fails with:

Error: plugin verification failed: open /home/runner/.gnupg/pubring.gpg: no such file or directory

This happens because modern gpg (v2.x) imports keys into pubring.kbx (new keybox format), but Helm v4's verification code looks for pubring.gpg (old GnuPG v1 format).

Solution

The action now automatically handles Helm v4 plugin installation:

  1. Detects Helm v4 via helm version --short
  2. Queries the GitHub releases API for .tgz assets with companion .prov files (distinguishes v4 plugin packages from platform-specific binaries)
  3. Imports the plugin author's GPG key from https://github.com/<owner>.gpg for signature verification
  4. Exports keys to legacy pubring.gpg format — Helm v4 reads the old GnuPG v1 keyring, but modern gpg stores keys in pubring.kbx; gpg --export --output pubring.gpg creates the legacy file
  5. Installs each .tgz package natively — plugin registers as a proper v4 subcommand
  6. Falls back gracefully to --verify=false legacy install if no .tgz assets are found (e.g., helm-diff) or if the API call fails

No workflow changes required — existing configs work as-is:

helm-plugins: https://github.com/jkroepke/helm-secrets@v4.7.1

Test plan

  • All 18 unit tests pass (npm test)
  • npm run all (build + format + lint + package) succeeds
  • CI validates on ubuntu, windows, macos
  • Verify helm-secrets plugin installs correctly on Helm v4 with GPG verification and helm secrets subcommand works
  • Verify helm-diff plugin falls back to legacy install and works on Helm v4

Fixes #604

🤖 Generated with Claude Code

Helm v4 requires plugins to be distributed as .tgz packages to register
as subcommands. Installing from a repo URL registers them as "legacy"
plugins that don't expose subcommands (e.g., "helm secrets" won't work).

When Helm v4+ is detected, the action now queries the plugin's GitHub
release for .tgz assets with companion .prov (provenance) files and
installs those natively. Plugins without v4 packages (e.g., helm-diff)
fall back to the existing --verify=false legacy install.

Fixes helmfile#604
…ication

Helm v4 verifies .tgz plugin signatures against .prov provenance files
by default. The runner doesn't have plugin authors' GPG keys, causing
"plugin verification failed: open ~/.gnupg/pubring.gpg: no such file"
errors.

Before installing .tgz assets, the action now fetches the plugin
author's GPG public key from https://github.com/<owner>.gpg and imports
it via `gpg --import`. If the key import fails, a warning is logged but
the install still proceeds.
Helm v4's plugin verification looks for pubring.gpg (GnuPG v1 format),
but modern gpg stores imported keys in pubring.kbx (v2 format). After
importing the plugin author's GPG key, export the keyring to the legacy
format so Helm v4 can find it for signature verification.
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the action’s Helm plugin installation logic to support Helm v4’s new plugin distribution/verification model by preferring signed .tgz release assets (with .prov files) and importing GPG keys needed for verification, while retaining a legacy fallback path.

Changes:

  • Add Helm v4 detection and GitHub Releases asset resolution for .tgz+.prov plugin packages.
  • Import a plugin owner’s GPG public key and export a legacy pubring.gpg keyring for Helm v4 verification.
  • Extend Jest coverage for the new Helm v4 install paths and fallbacks.

Reviewed changes

Copilot reviewed 2 out of 4 changed files in this pull request and generated 3 comments.

File Description
src/helm.ts Adds Helm v4 plugin asset discovery + GPG key import/export and updates plugin install strategy.
dist/index.js Updates the bundled action output to include the new logic.
__tests__/helm.test.ts Adds/updates tests to cover Helm v4 asset install behavior and fallbacks.

@yxxhero
Copy link
Member

yxxhero commented Feb 16, 2026

@saipavan9 please take a look.

The `~` shorthand doesn't expand on Windows, causing the gpg --export
command to fail with "No such file or directory". Use os.homedir() and
path.join() for cross-platform path resolution. Also quote the output
path to handle spaces in Windows paths.
- Pass GPG arguments as arrays to exec() instead of string interpolation
  to handle paths with spaces correctly on Windows
- Use os.homedir() and path.join() for cross-platform path resolution
  instead of relying on ~ expansion
- Try both vX.Y.Z and X.Y.Z tag formats when querying GitHub releases
  API, since users may omit the v prefix but repos tag with it
@saipavan9
Copy link
Contributor Author

@yxxhero Fixed all the issues

When GPG verification fails for a .tgz plugin install (e.g., missing
key, wrong signer, gpg not available), retry with --verify=false instead
of hard-failing the action. The .tgz still registers as a proper v4
plugin even without verification.
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 4 changed files in this pull request and generated 1 comment.

When a user provides a direct .tgz URL (e.g., a specific release
download), install it directly instead of querying the GitHub releases
API, which could resolve different assets than what was requested.
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 4 changed files in this pull request and generated 4 comments.

- Refactor all exec() calls to pass command and arguments separately
  instead of string interpolation, preventing potential issues with
  special characters in URLs or paths
- Validate HTTP status code from GPG key endpoint before attempting
  import, avoiding feeding HTML error pages to gpg --import
- Remove unused variables from tests
- Replace == with === for exit code comparisons in legacy install path
- Pass 'helm plugin list' as argument array instead of command string
Extract GITHUB_REPO_REGEX constant to unify the GitHub URL parsing
pattern used in both resolveHelmV4PluginAssets and installHelmPlugins.
Add core.debug() message when GITHUB_TOKEN is not set to help users
understand potential rate limiting on GitHub API requests.
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 4 changed files in this pull request and generated 2 comments.

Replace GITHUB_REPO_REGEX with parseGitHubRepo() that uses new URL()
to properly validate hostname and extract clean owner/repo from
pathname segments. Only retry with --verify=false when stderr indicates
an actual verification failure (verification/pubring/openpgp keywords),
not for unrelated errors like 404 or corrupt archives.
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 4 changed files in this pull request and generated 1 comment.

Reset lastError after a successful API response so that an expected
404 on an alternate tag format (e.g. v3.15.0 vs 3.15.0) does not
produce a spurious warning when the other candidate succeeds.
@yxxhero yxxhero requested a review from Copilot February 16, 2026 14:15
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 4 changed files in this pull request and generated 1 comment.

Reject owners and repos with invalid characters (e.g. user@domain.com)
to prevent pointless API calls and confusing warnings for malformed
URLs that happen to have github.com as their hostname.
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 4 changed files in this pull request and generated 1 comment.

@yxxhero yxxhero merged commit 663319a into helmfile:main Feb 18, 2026
18 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Helm v4 require --verify=false when install helm-diff plugin(default install plugin)

3 participants