Repository: roboll/helmfile
Pull request #1488 (2020-09-18 07:29:23)

Support the latest Helm (>=v3.3.2) and bump the Helm version in Docker image.
Bump Helm version to the latest as it contains several security fixes.

Ref:

- <https://github.com/helm/helm/releases/tag/v3.3.2>
- <https://github.com/helm/helm/releases/tag/v2.16.11>

wi1dcard: Please DO NOT MERGE THIS now. The breaking changes described in the release notes of helm impact helmfile while updating existing repos:

> One breaking change was made: The default behavior of helm repo add was changed: It no longer overwrites repositories by default. The flag --force-update was added to helm repo add to allow a repo to be overwritten. The flag --no-update still exists, but does nothing. This change accords with the Helm policy for allowing minor breaking changes in the name of security.

I'm going to fix it.

Patch:
diff --git a/.circleci/config.yml b/.circleci/config.yml
index a780b38..723ef6f 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -95,7 +95,7 @@ jobs:
       - run:
           name: Install helm
           environment:
-            HELM_VERSION: v2.16.1
+            HELM_VERSION: v2.16.12
           command: |
             HELM_FILENAME="helm-${HELM_VERSION}-linux-amd64.tar.gz"
             curl -Lo ${HELM_FILENAME} "https://kubernetes-helm.storage.googleapis.com/${HELM_FILENAME}"
@@ -153,7 +153,7 @@ jobs:
     - run:
         name: Install helm
         environment:
-          HELM_VERSION: v3.1.0
+          HELM_VERSION: v3.3.3
         command: |
           HELM_FILENAME="helm-${HELM_VERSION}-linux-amd64.tar.gz"
           curl -Lo ${HELM_FILENAME} "https://get.helm.sh/${HELM_FILENAME}"
diff --git a/Dockerfile b/Dockerfile
index 88e8ac0..6a588bf 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -11,10 +11,10 @@ FROM alpine:3.11
 
 RUN apk add --no-cache ca-certificates git bash curl jq
 
-ARG HELM_VERSION=v2.16.1
+ARG HELM_VERSION=v2.16.12
 ARG HELM_LOCATION="https://kubernetes-helm.storage.googleapis.com"
 ARG HELM_FILENAME="helm-${HELM_VERSION}-linux-amd64.tar.gz"
-ARG HELM_SHA256="7eebaaa2da4734242bbcdced62cc32ba8c7164a18792c8acdf16c77abffce202"
+ARG HELM_SHA256="756ab375314329b66b452c0f9d569f74b0760141670217c07b79890ad314c214"
 RUN wget ${HELM_LOCATION}/${HELM_FILENAME} && \
     echo Verifying ${HELM_FILENAME}... && \
     sha256sum ${HELM_FILENAME} | grep -q "${HELM_SHA256}" && \
diff --git a/Dockerfile.helm3 b/Dockerfile.helm3
index 68f56ce..387c01e 100644
--- a/Dockerfile.helm3
+++ b/Dockerfile.helm3
@@ -11,10 +11,10 @@ FROM alpine:3.11
 
 RUN apk add --no-cache ca-certificates git bash curl jq
 
-ARG HELM_VERSION=v3.2.1
+ARG HELM_VERSION=v3.3.3
 ARG HELM_LOCATION="https://get.helm.sh"
 ARG HELM_FILENAME="helm-${HELM_VERSION}-linux-amd64.tar.gz"
-ARG HELM_SHA256="018f9908cb950701a5d59e757653a790c66d8eda288625dbb185354ca6f41f6b"
+ARG HELM_SHA256="246d58b6b353e63ae8627415a7340089015e3eb542ff7b5ce124b0b1409369cc"
 RUN wget ${HELM_LOCATION}/${HELM_FILENAME} && \
     echo Verifying ${HELM_FILENAME}... && \
     sha256sum ${HELM_FILENAME} | grep -q "${HELM_SHA256}" && \
diff --git a/pkg/helmexec/exec.go b/pkg/helmexec/exec.go
index e45bbc0..6c4e685 100644
--- a/pkg/helmexec/exec.go
+++ b/pkg/helmexec/exec.go
@@ -130,6 +130,9 @@ func (helm *execer) AddRepo(name, repository, cafile, certfile, keyfile, usernam
 		return fmt.Errorf("empty field name")
 	}
 	args = append(args, "repo", "add", name, repository)
+	if helm.IsHelm3() && helm.IsVersionAtLeast(3, 3, 2) {
+		args = append(args, "--force-update")
+	}
 	if certfile != "" && keyfile != "" {
 		args = append(args, "--cert-file", certfile, "--key-file", keyfile)
 	}
@@ -398,6 +401,6 @@ func (helm *execer) GetVersion() Version {
 	return helm.version
 }
 
-func (helm *execer) IsVersionAtLeast(major int, minor int) bool {
-	return helm.version.Major >= major && helm.version.Minor >= minor
+func (helm *execer) IsVersionAtLeast(major int, minor int, patch int) bool {
+	return helm.version.Major >= major && helm.version.Minor >= minor && helm.version.Patch >= patch
 }
diff --git a/pkg/helmexec/helmexec.go b/pkg/helmexec/helmexec.go
index ba482f9..9f50f3a 100644
--- a/pkg/helmexec/helmexec.go
+++ b/pkg/helmexec/helmexec.go
@@ -28,7 +28,7 @@ type Interface interface {
 	DecryptSecret(context HelmContext, name string, flags ...string) (string, error)
 	IsHelm3() bool
 	GetVersion() Version
-	IsVersionAtLeast(major int, minor int) bool
+	IsVersionAtLeast(major int, minor int, patch int) bool
 }
 
 type DependencyUpdater interface {
diff --git a/pkg/state/state.go b/pkg/state/state.go
index 9c9422d..8431591 100644
--- a/pkg/state/state.go
+++ b/pkg/state/state.go
@@ -6,8 +6,6 @@ import (
 	"encoding/hex"
 	"errors"
 	"fmt"
-	"github.com/imdario/mergo"
-	"golang.org/x/sync/errgroup"
 	"io"
 	"io/ioutil"
 	"os"
@@ -20,6 +18,9 @@ import (
 	"sync"
 	"text/template"
 
+	"github.com/imdario/mergo"
+	"golang.org/x/sync/errgroup"
+
 	"github.com/variantdev/chartify"
 
 	"github.com/roboll/helmfile/pkg/environment"
@@ -2063,7 +2064,7 @@ func (st *HelmState) flagsForUpgrade(helm helmexec.Interface, release *ReleaseSp
 
 	if release.CreateNamespace != nil && *release.CreateNamespace ||
 		release.CreateNamespace == nil && (st.HelmDefaults.CreateNamespace == nil || *st.HelmDefaults.CreateNamespace) {
-		if helm.IsVersionAtLeast(3, 2) {
+		if helm.IsVersionAtLeast(3, 2, 0) {
 			flags = append(flags, "--create-namespace")
 		} else if release.CreateNamespace != nil || st.HelmDefaults.CreateNamespace != nil {
 			// createNamespace was set explicitly, but not running supported version of helm - error


Test patch:
diff --git a/pkg/app/app_test.go b/pkg/app/app_test.go
index 4d32713..22ac9b6 100644
--- a/pkg/app/app_test.go
+++ b/pkg/app/app_test.go
@@ -2462,7 +2462,7 @@ func (helm *mockHelmExec) GetVersion() helmexec.Version {
 	return helmexec.Version{}
 }
 
-func (helm *mockHelmExec) IsVersionAtLeast(major int, minor int) bool {
+func (helm *mockHelmExec) IsVersionAtLeast(major int, minor int, patch int) bool {
 	return false
 }
 
diff --git a/pkg/app/mocks_test.go b/pkg/app/mocks_test.go
index 8d8e7cd..b2ce967 100644
--- a/pkg/app/mocks_test.go
+++ b/pkg/app/mocks_test.go
@@ -97,7 +97,7 @@ func (helm *noCallHelmExec) GetVersion() helmexec.Version {
 	return helmexec.Version{}
 }
 
-func (helm *noCallHelmExec) IsVersionAtLeast(major int, minor int) bool {
+func (helm *noCallHelmExec) IsVersionAtLeast(major int, minor int, patch int) bool {
 	helm.doPanic()
 	return false
 }
diff --git a/pkg/exectest/helm.go b/pkg/exectest/helm.go
index 39a36e4..658c312 100644
--- a/pkg/exectest/helm.go
+++ b/pkg/exectest/helm.go
@@ -170,12 +170,12 @@ func (helm *Helm) GetVersion() helmexec.Version {
 	return helmexec.Version{}
 }
 
-func (helm *Helm) IsVersionAtLeast(major int, minor int) bool {
+func (helm *Helm) IsVersionAtLeast(major int, minor int, patch int) bool {
 	if helm.Version == nil {
 		return false
 	}
 
-	return helm.Version.Major >= major && minor >= helm.Version.Minor
+	return helm.Version.Major >= major && minor >= helm.Version.Minor && patch >= helm.Version.Patch
 }
 
 func (helm *Helm) sync(m *sync.Mutex, f func()) {
diff --git a/pkg/helmexec/exec_test.go b/pkg/helmexec/exec_test.go
index 832f793..704153d 100644
--- a/pkg/helmexec/exec_test.go
+++ b/pkg/helmexec/exec_test.go
@@ -557,15 +557,15 @@ func Test_GetVersion(t *testing.T) {
 func Test_IsVersionAtLeast(t *testing.T) {
 	helm2Runner := mockRunner{output: []byte("Client: v2.16.1+ge13bc94\n")}
 	helm := New("helm", NewLogger(os.Stdout, "info"), "dev", &helm2Runner)
-	if !helm.IsVersionAtLeast(2, 1) {
+	if !helm.IsVersionAtLeast(2, 1, 0) {
 		t.Error("helmexec.IsVersionAtLeast - 2.16.1 not atleast 2.1")
 	}
 
-	if helm.IsVersionAtLeast(2, 19) {
+	if helm.IsVersionAtLeast(2, 19, 0) {
 		t.Error("helmexec.IsVersionAtLeast - 2.16.1 is atleast 2.19")
 	}
 
-	if helm.IsVersionAtLeast(3, 2) {
+	if helm.IsVersionAtLeast(3, 2, 0) {
 		t.Error("helmexec.IsVersionAtLeast - 2.16.1 is atleast 3.2")
 	}