name: Release
on:
push:
tags:
- '*'
branches:
- 'main'
- 'master'
pull_request:
branches:
- 'main'
- 'master'
workflow_dispatch:
permissions:
contents: write
jobs:
goreleaser:
runs-on: ubuntu-latest
steps:
-
if: ${{ !startsWith(github.ref, 'refs/tags/v') }}
run: echo "flags=--snapshot --skip=sign" >> $GITHUB_ENV
-
name: Checkout
uses: actions/checkout@v7
with:
fetch-depth: 0
-
name: Set up Go
uses: actions/setup-go@v7
with:
go-version-file: 'go.mod'
-
name: Import GPG key
if: ${{ startsWith(github.ref, 'refs/tags/v') }}
run: |
gpgconf --launch gpg-agent
printf '%s' "${{ secrets.GPG_PRIVATE_KEY }}" | base64 --decode | gpg --batch --import
-
name: Set GPG environment for signing
if: ${{ startsWith(github.ref, 'refs/tags/v') }}
run: |
echo "GPG_FINGERPRINT=${{ secrets.GPG_FINGERPRINT }}" >> "$GITHUB_ENV"
echo "GPG_PASSPHRASE=${{ secrets.GPG_PASSPHRASE }}" >> "$GITHUB_ENV"
-
name: Run GoReleaser
uses: goreleaser/goreleaser-action@v7
with:
distribution: goreleaser
version: '~> v1'
args: release --clean ${{ env.flags }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-
name: Verify archives bundle plugin files (snapshot only)
if: ${{ !startsWith(github.ref, 'refs/tags/v') }}
run: |
set -e
missing=0
# Archives wrap their content in a "diff/" directory: the layout
# every released install/update hook expects (issues #1071, #1076).
# Each platform is published under two names (see .goreleaser.yml):
# the historical "helm-diff-<os>-<arch>.tgz" and the versioned
# "diff-<version>-<os>-<arch>.tgz" installable by helm 4 directly
# from a local tarball.
for f in dist/*.tgz; do
echo "== $f =="
tar tzf "$f"
for member in "diff/plugin.yaml" "diff/install-binary.sh" "diff/install-binary.ps1"; do
if ! tar tzf "$f" | grep -q "^${member}$"; then
echo "ERROR: ${member} missing from ${f}"
missing=1
fi
done
# the binary has a .exe suffix on windows archives
if ! tar tzf "$f" | grep -qE "^diff/bin/diff(\\.exe)?$"; then
echo "ERROR: diff/bin/diff missing from ${f}"
missing=1
fi
done
legacy_count="$(find dist -maxdepth 1 -name 'helm-diff-*.tgz' | wc -l)"
versioned_count="$(find dist -maxdepth 1 -name 'diff-*.tgz' | wc -l)"
if [ "$legacy_count" -eq 0 ] || [ "$legacy_count" -ne "$versioned_count" ]; then
echo "ERROR: expected an equal, non-zero number of legacy (helm-diff-*) and versioned (diff-*) archives"
missing=1
fi
if [ "$missing" -ne 0 ]; then
echo "Smoke test failed: required plugin files missing from one or more archives"
exit 1
fi
echo "Smoke test passed: all archives bundle plugin.yaml, install scripts, and binary in a diff/ directory"
-
name: Set up Helm
if: ${{ !startsWith(github.ref, 'refs/tags/v') }}
uses: azure/setup-helm@v5
with:
version: v3.18.6
-
name: End-to-end archive install test (snapshot only)
if: ${{ !startsWith(github.ref, 'refs/tags/v') }}
run: |
set -e
# Reproduce issue #504: extract a release archive and install from it.
mkdir -p /tmp/archive-test
tar xzf dist/helm-diff-linux-amd64.tgz -C /tmp/archive-test
echo "Extracted archive layout:"
find /tmp/archive-test/diff -maxdepth 2 -type f | sort
out="$(helm plugin install /tmp/archive-test/diff 2>&1)"
echo "$out"
echo "$out" | grep -q "skipping download" || {
echo "ERROR: install hook did not skip the download."
echo "Archive install must not hit the network (binary is already bundled)."
exit 1
}
helm diff version
echo "End-to-end archive install test passed: installed from archive without downloading"
-
name: Set up Helm 4
if: ${{ !startsWith(github.ref, 'refs/tags/v') }}
uses: azure/setup-helm@v5
with:
version: v4.3.0
-
name: Legacy update hook regression test (snapshot only)
if: ${{ !startsWith(github.ref, 'refs/tags/v') }}
run: |
set -e
archive="$PWD/dist/helm-diff-linux-amd64.tgz"
for hook_version in v3.15.13 v3.15.14; do
echo "== simulating 'helm plugin update' with the $hook_version install hook =="
plugin_dir="$(mktemp -d)/diff"
mkdir -p "$plugin_dir/bin"
git show "${hook_version}:install-binary.sh" > "$plugin_dir/install-binary.sh"
HELM_BIN=helm HELM_PLUGIN_DIR="$plugin_dir" \
HELM_DIFF_BIN_TGZ="$archive" \
sh "$plugin_dir/install-binary.sh" -u
test -x "$plugin_dir/bin/diff"
"$plugin_dir/bin/diff" version
echo "$hook_version hook updated the plugin successfully"
done
echo "Legacy update hook regression test passed"
-
name: Helm 4 offline tarball install test (snapshot only)
if: ${{ !startsWith(github.ref, 'refs/tags/v') }}
env:
HELM_DATA_HOME: /tmp/helm4-data
run: |
set -e
archive="$(find dist -maxdepth 1 -name 'diff-*-linux-amd64.tgz')"
export GNUPGHOME="$(mktemp -d)"
chmod 700 "$GNUPGHOME"
gpg --batch --pinentry-mode loopback --passphrase '' \
--quick-generate-key "helm-diff-test" rsa3072 sign 0
GPG_FINGERPRINT=$(gpg --batch --with-colons --list-secret-keys "helm-diff-test" \
| grep '^fpr:' | head -1 | cut -d: -f10)
export GPG_FINGERPRINT GPG_PASSPHRASE=""
./scripts/sign-provenance.sh "$archive" "$archive.prov"
gpg --export --armor "helm-diff-test" > /tmp/keyring.gpg
out="$(helm plugin install "$archive" --keyring /tmp/keyring.gpg 2>&1)"
echo "$out"
echo "$out" | grep -q "Plugin Hash Verified" || {
echo "ERROR: helm 4 did not verify the signed archive."
exit 1
}
helm diff version
echo "Helm 4 offline tarball install test passed: installed and verified from a local tarball"
-
name: Export and upload public key
if: ${{ startsWith(github.ref, 'refs/tags/v') }}
run: |
gpg --export --armor "${{ secrets.GPG_FINGERPRINT }}" > pubkey.asc
gh release upload ${{ github.ref_name }} pubkey.asc
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
provenance-smoke-test:
runs-on: ubuntu-latest
if: ${{ !startsWith(github.ref, 'refs/tags/v') }}
steps:
-
name: Checkout
uses: actions/checkout@v7
-
name: Test provenance signing with disposable key
run: |
export GNUPGHOME="$(mktemp -d)"
tmpdir="$(mktemp -d)"
trap 'rm -rf "$GNUPGHOME" "$tmpdir"' EXIT
chmod 700 "$GNUPGHOME"
gpg --batch --pinentry-mode loopback --passphrase '' \
--quick-generate-key "helm-diff-test" ed25519 sign 0
GPG_FINGERPRINT=$(gpg --batch --with-colons --list-secret-keys "helm-diff-test" \
| grep '^fpr:' | head -1 | cut -d: -f10)
export GPG_FINGERPRINT
export GPG_PASSPHRASE=""
echo "dummy binary" > "$tmpdir/bin"
tar czf "$tmpdir/helm-diff-linux-amd64.tgz" -C "$tmpdir" bin
./scripts/sign-provenance.sh "$tmpdir/helm-diff-linux-amd64.tgz" "$tmpdir/helm-diff-linux-amd64.tgz.prov"
if [ ! -f "$tmpdir/helm-diff-linux-amd64.tgz.prov" ]; then
echo "ERROR: provenance file was not created"
exit 1
fi
echo "=== gpg --verify ==="
gpg --verify "$tmpdir/helm-diff-linux-amd64.tgz.prov"
echo ""
echo "=== Signed .prov content ==="
cat "$tmpdir/helm-diff-linux-amd64.tgz.prov"
echo ""
echo "=== Parsed provenance block ==="
gpg --batch --output - "$tmpdir/helm-diff-linux-amd64.tgz.prov" 2>/dev/null
echo ""
echo "Provenance smoke test passed"