Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,22 @@ This can also be used to compare two revisions/versions of your helm release.
helm plugin install https://github.com/databus23/helm-diff
```

### Installing offline
If installing this in an offline/airgapped environment, download the bin `.tgz` from [releases](https://github.com/databus23/helm-diff/releases). Set `HELM_DIFF_BIN_TGZ` to the absolute path to the bin `.tgz`:

**POSIX shell:**
```sh
export HELM_DIFF_BIN_TGZ=/path/to/helm-diff-bin.tgz
```
Comment on lines +24 to +30
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

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

The offline install docs say to download a “bin .tgz” but the release assets are platform-specific (e.g., helm-diff-<os>-<arch>.tgz) and the GitHub release page also includes source archives. Please clarify which exact asset to download to avoid users grabbing the source tarball or the wrong OS/arch package, and make the example filename match the actual release naming.

Copilot uses AI. Check for mistakes.

**PowerShell:**
```powershell
$env:HELM_DIFF_BIN_TGZ = "C:\path\to\helm-diff-bin.tgz"
```

Now, run `helm plugin install /path/to/helm-diff/`.
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

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

These instructions end with helm plugin install /path/to/helm-diff/, but in offline scenarios it’s not obvious that you also need the plugin source directory (with plugin.yaml and install scripts) available locally (e.g., from a previously downloaded/cloned copy). Consider adding a brief note on obtaining the plugin directory offline so the steps are complete.

Suggested change
Now, run `helm plugin install /path/to/helm-diff/`.
Now, run `helm plugin install /path/to/helm-diff/`.
Here, `/path/to/helm-diff/` must be a local copy of the Helm Diff plugin source directory (including `plugin.yaml` and the install scripts), for example from a repo you cloned or a source archive you downloaded earlier and transferred into the offline environment.

Copilot uses AI. Check for mistakes.
The install script will skip the GitHub download and instead install from the `.tgz`.

**For Helm 4 users:**

Helm 4 requires plugin verification by default. Since this plugin does not yet provide provenance artifacts, you need to use the `--verify=false` flag:
Expand Down
34 changes: 19 additions & 15 deletions install-binary.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,22 @@ param (

function Get-Architecture {
$architecture = [System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture

$arch = switch ($architecture) {
"X64" { "amd64" }
"X64" { "amd64" }
"Arm64" { "arm64" }
Default { "" }
}

if ($arch -eq "") {
throw "Unsupported architecture: ${architecture}"
}

return $arch
}

function Get-Version {
param ([Parameter(Mandatory=$true)][bool] $Update)

if ($Update) {
return "latest"
}

return git describe --tags --exact-match 2>$null || "latest"
}

Expand All @@ -37,7 +32,6 @@ function New-TemporaryDirectory {

function Get-Url {
param ([Parameter(Mandatory=$true)][string] $Version, [Parameter(Mandatory=$true)][string] $Architecture)

if ($Version -eq "latest") {
return "https://github.com/databus23/helm-diff/releases/latest/download/helm-diff-windows-${Architecture}.tgz"
}
Expand All @@ -46,32 +40,42 @@ function Get-Url {

function Download-Plugin {
param ([Parameter(Mandatory=$true)][string] $Url, [Parameter(Mandatory=$true)][string] $Output)

Invoke-WebRequest -OutFile $Output $Url
}

function Install-Plugin {
param ([Parameter(Mandatory=$true)][string] $ArchiveDirectory, [Parameter(Mandatory=$true)][string] $ArchiveName, [Parameter(Mandatory=$true)][string] $Destination)

Push-Location $ArchiveDirectory
tar -xzf $ArchiveName -C .
Pop-Location

New-Item -ItemType Directory -Path $Destination -Force
Copy-Item -Path (Join-Path $ArchiveDirectory "diff" "bin" "diff.exe") -Destination $Destination -Force
}

$ErrorActionPreference = "Stop"

$archiveName = "helm-diff.tgz"
$arch = Get-Architecture
$version = Get-Version -Update $Update
$tmpDir = New-TemporaryDirectory
Comment on lines 56 to 59
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

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

Offline installs still execute Get-Version, which runs git describe. In airgapped/offline environments (and when installing from a local plugin directory without git available), this can fail even though a local .tgz is provided. Consider deferring version detection (and any git usage) until the online branch, or making Get-Version return "latest" when $env:HELM_DIFF_BIN_TGZ is set.

Copilot uses AI. Check for mistakes.

trap { Remove-Item -path $tmpDir -Recurse -Force }

$url = Get-Url -Version $version -Architecture $arch
$output = Join-Path $tmpDir $archiveName

Download-Plugin -Url $url -Output $output
Install-Plugin -ArchiveDirectory $tmpDir -ArchiveName $archiveName -Destination (Join-Path $env:HELM_PLUGIN_DIR "bin")
# Check for offline installation via environment variable
if ($env:HELM_DIFF_BIN_TGZ) {
Write-Host "HELM_DIFF_BIN_TGZ is set. Using local package at: $($env:HELM_DIFF_BIN_TGZ)"

if (-not (Test-Path $env:HELM_DIFF_BIN_TGZ -PathType Leaf)) {
throw "Offline installation failed: File not found at '$($env:HELM_DIFF_BIN_TGZ)'"
}
Copy-Item -Path $env:HELM_DIFF_BIN_TGZ -Destination $output
}
else {
# Proceed with online installation
Write-Host "HELM_DIFF_BIN_TGZ not set. Proceeding with online installation."
$url = Get-Url -Version $version -Architecture $arch
Download-Plugin -Url $url -Output $output
}

Install-Plugin -ArchiveDirectory $tmpDir -ArchiveName $archiveName -Destination (Join-Path $env:HELM_PLUGIN_DIR "bin")

51 changes: 30 additions & 21 deletions install-binary.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,14 @@ export GREP_COLOR="never"
# available. This is the case when using MSYS2 or Cygwin
# on Windows where helm returns a Windows path but we
# need a Unix path

if command -v cygpath >/dev/null 2>&1; then
HELM_BIN="$(cygpath -u "${HELM_BIN}")"
HELM_PLUGIN_DIR="$(cygpath -u "${HELM_PLUGIN_DIR}")"
fi

[ -z "$HELM_BIN" ] && HELM_BIN=$(command -v helm)

[ -z "$HELM_HOME" ] && HELM_HOME=$(helm env | grep 'HELM_DATA_HOME' | cut -d '=' -f2 | tr -d '"')

mkdir -p "$HELM_HOME"

: "${HELM_PLUGIN_DIR:="$HELM_HOME/plugins/helm-diff"}"

if [ "$SKIP_BIN_INSTALL" = "1" ]; then
Expand Down Expand Up @@ -55,7 +51,6 @@ initArch() {
# initOS discovers the operating system for this system.
initOS() {
OS=$(uname -s)

case "$OS" in
Windows_NT) OS='windows' ;;
# Msys support
Expand All @@ -77,16 +72,21 @@ verifySupported() {
exit 1
fi

if
! command -v curl >/dev/null 2>&1 && ! command -v wget >/dev/null 2>&1
then
echo "Either curl or wget is required"
exit 1
# Skip download tool check if using local file
if [ -z "$HELM_DIFF_BIN_TGZ" ]; then
if ! command -v curl >/dev/null 2>&1 && ! command -v wget >/dev/null 2>&1; then
echo "Either curl or wget is required"
exit 1
fi
fi
}

# getDownloadURL checks the latest available version.
getDownloadURL() {
# If HELM_DIFF_BIN_TGZ is set, we don't need a download URL
if [ -n "$HELM_DIFF_BIN_TGZ" ]; then
return
fi
version=$(git -C "$HELM_PLUGIN_DIR" describe --tags --exact-match 2>/dev/null || :)
if [ "$SCRIPT_MODE" = "install" ] && [ -n "$version" ]; then
DOWNLOAD_URL="https://github.com/$PROJECT_GH/releases/download/$version/helm-diff-$OS-$ARCH.tgz"
Expand All @@ -99,6 +99,7 @@ getDownloadURL() {
mkTempDir() {
HELM_TMP="$(mktemp -d -t "${PROJECT_NAME}-XXXXXX")"
}

rmTempDir() {
if [ -d "${HELM_TMP:-/tmp/helm-diff-tmp}" ]; then
rm -rf "${HELM_TMP:-/tmp/helm-diff-tmp}"
Expand All @@ -109,21 +110,29 @@ rmTempDir() {
# for that binary.
downloadFile() {
PLUGIN_TMP_FILE="${HELM_TMP}/${PROJECT_NAME}.tgz"

# If HELM_DIFF_BIN_TGZ is set, copy the local file instead of downloading
if [ -n "$HELM_DIFF_BIN_TGZ" ]; then
echo "Using local package at $HELM_DIFF_BIN_TGZ"
if [ ! -f "$HELM_DIFF_BIN_TGZ" ]; then
echo "Error: file not found at $HELM_DIFF_BIN_TGZ"
exit 1
fi
cp "$HELM_DIFF_BIN_TGZ" "$PLUGIN_TMP_FILE"
return
fi

echo "Downloading $DOWNLOAD_URL"
if
command -v curl >/dev/null 2>&1
then
if command -v curl >/dev/null 2>&1; then
curl -sSf -L "$DOWNLOAD_URL" >"$PLUGIN_TMP_FILE"
elif
command -v wget >/dev/null 2>&1
then
elif command -v wget >/dev/null 2>&1; then
wget -q -O - "$DOWNLOAD_URL" >"$PLUGIN_TMP_FILE"
fi
}

# installFile verifies the SHA256 for the file, then unpacks and
# installs it.
# Unpack the archive file, then install it into the helm directory.
installFile() {
PLUGIN_TMP_FILE="${HELM_TMP}/${PROJECT_NAME}.tgz"
tar xzf "$PLUGIN_TMP_FILE" -C "$HELM_TMP"
HELM_TMP_BIN="$HELM_TMP/diff/bin/diff"
if [ "${OS}" = "windows" ]; then
Expand All @@ -145,11 +154,11 @@ exit_trap() {
exit $result
}

# Execution

#Stop execution on any error
# --- Execution ---
# Stop execution on any error
trap "exit_trap" EXIT
set -e

initArch
initOS
verifySupported
Expand Down
Loading