Repository: argoproj/argo-cd
Pull request #5864 (2021-03-25 03:59:40)

fix: add "--fix-missing" to test container dependency installation command
This changed help fix the following:

```
#8 109.1 Get:171 http://archive.ubuntu.com/ubuntu groovy/main amd64 libnginx-mod-http-xslt-filter amd64 1.18.0-6ubuntu2 [14.3 kB]
#8 109.1 Get:172 http://archive.ubuntu.com/ubuntu groovy/main amd64 libnginx-mod-mail amd64 1.18.0-6ubuntu2 [43.9 kB]
#8 109.2 Get:173 http://archive.ubuntu.com/ubuntu groovy/main amd64 libnginx-mod-stream amd64 1.18.0-6ubuntu2 [68.3 kB]
#8 109.5 Get:174 http://archive.ubuntu.com/ubuntu groovy/main amd64 libnginx-mod-stream-geoip2 amd64 1.18.0-6ubuntu2 [9644 B]
#8 109.5 Get:175 http://archive.ubuntu.com/ubuntu groovy/main amd64 libsasl2-modules amd64 2.1.27+dfsg-2ubuntu1 [48.8 kB]
#8 109.5 Get:176 http://archive.ubuntu.com/ubuntu groovy/main amd64 libwrap0 amd64 7.6.q-30 [46.3 kB]
#8 109.5 Get:177 http://archive.ubuntu.com/ubuntu groovy/main amd64 make amd64 4.3-4ubuntu1 [167 kB]
#8 109.6 Get:178 http://archive.ubuntu.com/ubuntu groovy/main amd64 manpages-dev all 5.08-1 [2290 kB]
#8 110.6 Get:179 http://archive.ubuntu.com/ubuntu groovy/main amd64 ncurses-term all 6.2-1 [247 kB]
#8 110.7 Get:180 http://archive.ubuntu.com/ubuntu groovy/main amd64 nginx-core amd64 1.18.0-6ubuntu2 [427 kB]
#8 111.1 Get:181 http://archive.ubuntu.com/ubuntu groovy/main amd64 nginx amd64 1.18.0-6ubuntu2 [3980 B]
#8 111.1 Get:182 http://archive.ubuntu.com/ubuntu groovy-updates/main amd64 openssh-sftp-server amd64 1:8.3p1-1ubuntu0.1 [51.8 kB]
#8 111.1 Get:183 http://archive.ubuntu.com/ubuntu groovy-updates/main amd64 openssh-server amd64 1:8.3p1-1ubuntu0.1 [382 kB]
#8 111.3 Get:184 http://archive.ubuntu.com/ubuntu groovy/main amd64 patch amd64 2.7.6-6 [105 kB]
#8 111.5 Get:185 http://archive.ubuntu.com/ubuntu groovy/main amd64 python3-certifi all 2020.4.5.1-1 [151 kB]
#8 111.5 Get:186 http://archive.ubuntu.com/ubuntu groovy/main amd64 python3-chardet all 3.0.4-7 [80.2 kB]
#8 111.5 Get:187 http://archive.ubuntu.com/ubuntu groovy/main amd64 python3-idna all 2.10-1 [35.2 kB]
#8 111.5 Get:188 http://archive.ubuntu.com/ubuntu groovy/main amd64 python3-six all 1.15.0-1 [12.0 kB]
#8 111.5 Get:189 http://archive.ubuntu.com/ubuntu groovy/main amd64 python3-urllib3 all 1.25.9-1 [88.8 kB]
#8 111.5 Get:190 http://archive.ubuntu.com/ubuntu groovy/main amd64 python3-requests all 2.23.0+dfsg-2 [50.9 kB]
#8 111.5 Get:191 http://archive.ubuntu.com/ubuntu groovy/main amd64 unzip amd64 6.0-25ubuntu1 [169 kB]
#8 111.6 Get:192 http://archive.ubuntu.com/ubuntu groovy/main amd64 zip amd64 3.0-11build1 [167 kB]
#8 111.7 Get:193 http://archive.ubuntu.com/ubuntu groovy/main amd64 python3-distro all 1.5.0-1 [14.8 kB]
#8 111.7 Get:194 http://archive.ubuntu.com/ubuntu groovy/main amd64 ssh-import-id all 5.10-0ubuntu1 [10.0 kB]
#8 111.7 Fetched 94.3 MB in 1min 39s (953 kB/s)
#8 111.7 E: Failed to fetch http://archive.ubuntu.com/ubuntu/pool/main/b/brotli/libbrotli1_1.0.9-2_amd64.deb  Error reading from server. Remote end closed connection [IP: 91.189.88.152 80]
#8 111.7 E: Unable to fetch some archives, maybe run apt-get update or try with --fix-missing?
```

Signed-off-by: Shoubhik Bose <shbose@redhat.com>




codecov[bot]: # [Codecov](https://codecov.io/gh/argoproj/argo-cd/pull/5864?src=pr&el=h1) Report
> Merging [#5864](https://codecov.io/gh/argoproj/argo-cd/pull/5864?src=pr&el=desc) (d3f8541) into [master](https://codecov.io/gh/argoproj/argo-cd/commit/6cc8ab025a115b9b922b9b007e4053a785c86cc4?el=desc) (6cc8ab0) will **not change** coverage.
> The diff coverage is `n/a`.

[![Impacted file tree graph](https://codecov.io/gh/argoproj/argo-cd/pull/5864/graphs/tree.svg?width=650&height=150&src=pr&token=kf5kwuegwE)](https://codecov.io/gh/argoproj/argo-cd/pull/5864?src=pr&el=tree)

```diff
@@           Coverage Diff           @@
##           master    #5864   +/-   ##
=======================================
  Coverage   40.88%   40.88%           
=======================================
  Files         147      147           
  Lines       19617    19617           
=======================================
  Hits         8021     8021           
  Misses      10491    10491           
  Partials     1105     1105           
```



------

[Continue to review full report at Codecov](https://codecov.io/gh/argoproj/argo-cd/pull/5864?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/argoproj/argo-cd/pull/5864?src=pr&el=footer). Last update [6cc8ab0...d3f8541](https://codecov.io/gh/argoproj/argo-cd/pull/5864?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/Dockerfile b/Dockerfile
index 10a93635e..ffe9ea16f 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,10 +1,10 @@
-ARG BASE_IMAGE=ubuntu:20.10
+ARG BASE_IMAGE=docker.io/library/ubuntu:20.10
 ####################################################################################################
 # Builder image
 # Initial stage which pulls prepares build dependencies and CLI tooling we need for our final image
 # Also used as the image in CI jobs so needs all dependencies
 ####################################################################################################
-FROM golang:1.16.2 as builder
+FROM docker.io/library/golang:1.16.2 as builder
 
 RUN echo 'deb http://deb.debian.org/debian buster-backports main' >> /etc/apt/sources.list
 
@@ -86,7 +86,7 @@ WORKDIR /home/argocd
 ####################################################################################################
 # Argo CD UI stage
 ####################################################################################################
-FROM node:12.18.4 as argocd-ui
+FROM docker.io/library/node:12.18.4 as argocd-ui
 
 WORKDIR /src
 ADD ["ui/package.json", "ui/yarn.lock", "./"]
diff --git a/Makefile b/Makefile
index b97ca8d8d..c846beb7e 100644
--- a/Makefile
+++ b/Makefile
@@ -309,7 +309,7 @@ mod-download: test-tools-image
 
 .PHONY: mod-download-local
 mod-download-local:
-	go mod download
+	go mod download && go mod tidy # go mod download changes go.sum https://github.com/golang/go/issues/42970
 
 .PHONY: mod-vendor
 mod-vendor: test-tools-image
diff --git a/USERS.md b/USERS.md
index 4cf9d589b..591b153cc 100644
--- a/USERS.md
+++ b/USERS.md
@@ -41,6 +41,7 @@ Currently, the following organizations are **officially** using Argo CD:
 1. [GMETRI](https://gmetri.com/)
 1. [Gojek](https://www.gojek.io/)
 1. [Greenpass](https://www.greenpass.com.br/)
+1. [Handelsbanken](https://www.handelsbanken.se)
 1. [Healy](https://www.healyworld.net)
 1. [hipages](https://hipages.com.au/)
 1. [Honestbank](https://honestbank.com)
@@ -48,6 +49,7 @@ Currently, the following organizations are **officially** using Argo CD:
 1. [InsideBoard](https://www.insideboard.com)
 1. [Intuit](https://www.intuit.com/)
 1. [JovianX](https://www.jovianx.com/)
+1. [Karrot](https://www.daangn.com/)
 1. [Kasa](https://kasa.co.kr/)
 1. [Keptn](https://keptn.sh)
 1. [Kinguin](https://www.kinguin.net/)
diff --git a/cmd/argocd-util/commands/app.go b/cmd/argocd-util/commands/app.go
index 9875da2c0..10b3acd1e 100644
--- a/cmd/argocd-util/commands/app.go
+++ b/cmd/argocd-util/commands/app.go
@@ -77,7 +77,7 @@ func NewGenAppSpecCommand() *cobra.Command {
 	argocd-util app generate-spec helm-guestbook --repo https://github.com/argoproj/argocd-example-apps.git --path helm-guestbook --dest-namespace default --dest-server https://kubernetes.default.svc --helm-set replicaCount=2
 
 	# Generate declarative config for a Helm app from a Helm repo
-	argocd-util app generate-spec nginx-ingress --repo https://kubernetes-charts.storage.googleapis.com --helm-chart nginx-ingress --revision 1.24.3 --dest-namespace default --dest-server https://kubernetes.default.svc
+	argocd-util app generate-spec nginx-ingress --repo https://charts.helm.sh/stable --helm-chart nginx-ingress --revision 1.24.3 --dest-namespace default --dest-server https://kubernetes.default.svc
 
 	# Generate declarative config for a Kustomize app
 	argocd-util app generate-spec kustomize-guestbook --repo https://github.com/argoproj/argocd-example-apps.git --path kustomize-guestbook --dest-namespace default --dest-server https://kubernetes.default.svc --kustomize-image gcr.io/heptio-images/ks-guestbook-demo:0.1
diff --git a/cmd/argocd-util/commands/repo.go b/cmd/argocd-util/commands/repo.go
index 67a69af08..878fa6efa 100644
--- a/cmd/argocd-util/commands/repo.go
+++ b/cmd/argocd-util/commands/repo.go
@@ -61,10 +61,10 @@ func NewGenRepoSpecCommand() *cobra.Command {
   argocd-util repo generate-spec https://git.example.com/repos/repo --username git --password secret --insecure-skip-server-verification
 
   # Add a public Helm repository named 'stable' via HTTPS
-  argocd-util repo generate-spec https://kubernetes-charts.storage.googleapis.com --type helm --name stable  
+  argocd-util repo generate-spec https://charts.helm.sh/stable --type helm --name stable  
 
   # Add a private Helm repository named 'stable' via HTTPS
-  argocd-util repo generate-spec https://kubernetes-charts.storage.googleapis.com --type helm --name stable --username test --password test
+  argocd-util repo generate-spec https://charts.helm.sh/stable --type helm --name stable --username test --password test
 
   # Add a private Helm OCI-based repository named 'stable' via HTTPS
   argocd-util repo generate-spec helm-oci-registry.cn-zhangjiakou.cr.aliyuncs.com --type helm --name stable --enable-oci --username test --password test
diff --git a/cmd/argocd-util/commands/settings_rbac.go b/cmd/argocd-util/commands/settings_rbac.go
index 50b892310..cbf0dec14 100644
--- a/cmd/argocd-util/commands/settings_rbac.go
+++ b/cmd/argocd-util/commands/settings_rbac.go
@@ -101,19 +101,19 @@ something.
 		Example: `
 # Check whether role some:role has permissions to create an application in the
 # 'default' project, using a local policy.csv file
-argocd-util rbac can some:role create application 'default/app' --policy-file policy.csv
+argocd-util settings rbac can some:role create application 'default/app' --policy-file policy.csv
 
 # Policy file can also be K8s config map with data keys like argocd-rbac-cm,
 # i.e. 'policy.csv' and (optionally) 'policy.default'
-argocd-util rbac can some:role create application 'default/app' --policy-file argocd-rbac-cm.yaml
+argocd-util settings rbac can some:role create application 'default/app' --policy-file argocd-rbac-cm.yaml
 
 # If --policy-file is not given, the ConfigMap 'argocd-rbac-cm' from K8s is
 # used. You need to specify the argocd namespace, and make sure that your
 # current Kubernetes context is pointing to the cluster Argo CD is running in
-argocd-util rbac can some:role create application 'default/app' --namespace argocd
+argocd-util settings rbac can some:role create application 'default/app' --namespace argocd
 
 # You can override a possibly configured default role
-argocd-util rbac can someuser create application 'default/app' --default-role role:readonly
+argocd-util settings rbac can someuser create application 'default/app' --default-role role:readonly
 
 `,
 		Run: func(c *cobra.Command, args []string) {
diff --git a/cmd/argocd/commands/app.go b/cmd/argocd/commands/app.go
index bb28c9439..2aa6fbe60 100644
--- a/cmd/argocd/commands/app.go
+++ b/cmd/argocd/commands/app.go
@@ -122,7 +122,7 @@ func NewApplicationCreateCommand(clientOpts *argocdclient.ClientOptions) *cobra.
 	argocd app create helm-guestbook --repo https://github.com/argoproj/argocd-example-apps.git --path helm-guestbook --dest-namespace default --dest-server https://kubernetes.default.svc --helm-set replicaCount=2
 
 	# Create a Helm app from a Helm repo
-	argocd app create nginx-ingress --repo https://kubernetes-charts.storage.googleapis.com --helm-chart nginx-ingress --revision 1.24.3 --dest-namespace default --dest-server https://kubernetes.default.svc
+	argocd app create nginx-ingress --repo https://charts.helm.sh/stable --helm-chart nginx-ingress --revision 1.24.3 --dest-namespace default --dest-server https://kubernetes.default.svc
 
 	# Create a Kustomize app
 	argocd app create kustomize-guestbook --repo https://github.com/argoproj/argocd-example-apps.git --path kustomize-guestbook --dest-namespace default --dest-server https://kubernetes.default.svc --kustomize-image gcr.io/heptio-images/ks-guestbook-demo:0.1
@@ -798,6 +798,7 @@ func NewApplicationDiffCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co
 	var (
 		refresh       bool
 		hardRefresh   bool
+		exitCode      bool
 		local         string
 		revision      string
 		localRepoRoot string
@@ -901,7 +902,7 @@ func NewApplicationDiffCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co
 					_ = cli.PrintDiff(item.key.Name, live, target)
 				}
 			}
-			if foundDiffs {
+			if foundDiffs && exitCode {
 				os.Exit(1)
 			}
 
@@ -909,6 +910,7 @@ func NewApplicationDiffCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co
 	}
 	command.Flags().BoolVar(&refresh, "refresh", false, "Refresh application data when retrieving")
 	command.Flags().BoolVar(&hardRefresh, "hard-refresh", false, "Refresh application data as well as target manifests cache")
+	command.Flags().BoolVar(&exitCode, "exit-code", true, "Return non-zero exit code when there is a diff")
 	command.Flags().StringVar(&local, "local", "", "Compare live app to a local manifests")
 	command.Flags().StringVar(&revision, "revision", "", "Compare live app to a particular revision")
 	command.Flags().StringVar(&localRepoRoot, "local-repo-root", "/", "Path to the repository root. Used together with --local allows setting the repository root")
diff --git a/cmd/argocd/commands/repo.go b/cmd/argocd/commands/repo.go
index 50bd2d7dc..cdbc47113 100644
--- a/cmd/argocd/commands/repo.go
+++ b/cmd/argocd/commands/repo.go
@@ -58,10 +58,10 @@ func NewRepoAddCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
   argocd repo add https://git.example.com/repos/repo --username git --password secret --insecure-skip-server-verification
 
   # Add a public Helm repository named 'stable' via HTTPS
-  argocd repo add https://kubernetes-charts.storage.googleapis.com --type helm --name stable  
+  argocd repo add https://charts.helm.sh/stable --type helm --name stable  
 
   # Add a private Helm repository named 'stable' via HTTPS
-  argocd repo add https://kubernetes-charts.storage.googleapis.com --type helm --name stable --username test --password test
+  argocd repo add https://charts.helm.sh/stable --type helm --name stable --username test --password test
 
   # Add a private Helm OCI-based repository named 'stable' via HTTPS
   argocd repo add helm-oci-registry.cn-zhangjiakou.cr.aliyuncs.com --type helm --name stable --enable-oci --username test --password test
diff --git a/cmd/util/app.go b/cmd/util/app.go
index 4ae5f4696..84dbc914a 100644
--- a/cmd/util/app.go
+++ b/cmd/util/app.go
@@ -111,10 +111,10 @@ func AddAppFlags(command *cobra.Command, opts *AppOptions) {
 	command.Flags().StringArrayVar(&opts.kustomizeCommonAnnotations, "kustomize-common-annotation", []string{}, "Set common labels in Kustomize")
 	command.Flags().StringVar(&opts.directoryExclude, "directory-exclude", "", "Set glob expression used to exclude files from application source path")
 	command.Flags().StringVar(&opts.directoryInclude, "directory-include", "", "Set glob expression used to include files from application source path")
-	command.Flags().Int64Var(&opts.retryLimit, "retry-limit", 0, "Max number of allowed sync retries")
-	command.Flags().DurationVar(&opts.retryBackoffDuration, "retry-backoff-duration", common.DefaultSyncRetryDuration, "Retry backoff base duration. Input needs to be a duration (e.g. 2m, 1h)")
-	command.Flags().DurationVar(&opts.retryBackoffMaxDuration, "retry-backoff-max-duration", common.DefaultSyncRetryMaxDuration, "Max retry backoff duration. Input needs to be a duration (e.g. 2m, 1h)")
-	command.Flags().Int64Var(&opts.retryBackoffFactor, "retry-backoff-factor", common.DefaultSyncRetryFactor, "Factor multiplies the base duration after each failed retry")
+	command.Flags().Int64Var(&opts.retryLimit, "sync-retry-limit", 0, "Max number of allowed sync retries")
+	command.Flags().DurationVar(&opts.retryBackoffDuration, "sync-retry-backoff-duration", common.DefaultSyncRetryDuration, "Sync retry backoff base duration. Input needs to be a duration (e.g. 2m, 1h)")
+	command.Flags().DurationVar(&opts.retryBackoffMaxDuration, "sync-retry-backoff-max-duration", common.DefaultSyncRetryMaxDuration, "Max sync retry backoff duration. Input needs to be a duration (e.g. 2m, 1h)")
+	command.Flags().Int64Var(&opts.retryBackoffFactor, "sync-retry-backoff-factor", common.DefaultSyncRetryFactor, "Factor multiplies the base duration after each failed sync retry")
 }
 
 func SetAppSpecOptions(flags *pflag.FlagSet, spec *argoappv1.ApplicationSpec, appOpts *AppOptions) int {
@@ -248,7 +248,7 @@ func SetAppSpecOptions(flags *pflag.FlagSet, spec *argoappv1.ApplicationSpec, ap
 			if spec.SyncPolicy.IsZero() {
 				spec.SyncPolicy = nil
 			}
-		case "retry-limit":
+		case "sync-retry-limit":
 			if appOpts.retryLimit > 0 {
 				if spec.SyncPolicy == nil {
 					spec.SyncPolicy = &argoappv1.SyncPolicy{}
@@ -268,7 +268,7 @@ func SetAppSpecOptions(flags *pflag.FlagSet, spec *argoappv1.ApplicationSpec, ap
 					spec.SyncPolicy.Retry = nil
 				}
 			} else {
-				log.Fatalf("Invalid retry-limit [%d]", appOpts.retryLimit)
+				log.Fatalf("Invalid sync-retry-limit [%d]", appOpts.retryLimit)
 			}
 		}
 	})
diff --git a/controller/state.go b/controller/state.go
index c0c281729..1041a2036 100644
--- a/controller/state.go
+++ b/controller/state.go
@@ -348,9 +348,11 @@ func (m *appStateManager) diffArrayCached(configArray []*unstructured.Unstructur
 			}
 			dr = res
 		}
-		diffResultList.Diffs[i] = *dr
-		if dr != nil && dr.Modified {
-			diffResultList.Modified = true
+		if dr != nil {
+			diffResultList.Diffs[i] = *dr
+			if dr.Modified {
+				diffResultList.Modified = true
+			}
 		}
 	}
 
diff --git a/docs/developer-guide/contributing.md b/docs/developer-guide/contributing.md
index 4f5419a4b..dffa56254 100644
--- a/docs/developer-guide/contributing.md
+++ b/docs/developer-guide/contributing.md
@@ -256,7 +256,7 @@ and others. Although you can make changes to these files and run them locally, i
 
     * `cd argo-ui`
     * `yarn link`
-    * `cd ../argo-cd`
+    * `cd ../argo-cd/ui`
     * `yarn link argo-ui`
 
     Once `argo-ui` package has been successfully linked, test out changes in your local development environment. 
diff --git a/docs/operator-manual/server-commands/argocd-util_app_generate-spec.md b/docs/operator-manual/server-commands/argocd-util_app_generate-spec.md
index 29f4651eb..5d9c2b03f 100644
--- a/docs/operator-manual/server-commands/argocd-util_app_generate-spec.md
+++ b/docs/operator-manual/server-commands/argocd-util_app_generate-spec.md
@@ -20,7 +20,7 @@ argocd-util app generate-spec APPNAME [flags]
 	argocd-util app generate-spec helm-guestbook --repo https://github.com/argoproj/argocd-example-apps.git --path helm-guestbook --dest-namespace default --dest-server https://kubernetes.default.svc --helm-set replicaCount=2
 
 	# Generate declarative config for a Helm app from a Helm repo
-	argocd-util app generate-spec nginx-ingress --repo https://kubernetes-charts.storage.googleapis.com --helm-chart nginx-ingress --revision 1.24.3 --dest-namespace default --dest-server https://kubernetes.default.svc
+	argocd-util app generate-spec nginx-ingress --repo https://charts.helm.sh/stable --helm-chart nginx-ingress --revision 1.24.3 --dest-namespace default --dest-server https://kubernetes.default.svc
 
 	# Generate declarative config for a Kustomize app
 	argocd-util app generate-spec kustomize-guestbook --repo https://github.com/argoproj/argocd-example-apps.git --path kustomize-guestbook --dest-namespace default --dest-server https://kubernetes.default.svc --kustomize-image gcr.io/heptio-images/ks-guestbook-demo:0.1
@@ -33,55 +33,55 @@ argocd-util app generate-spec APPNAME [flags]
 ### Options
 
 ```
-      --allow-empty                               Set allow zero live resources when sync is automated
-      --auto-prune                                Set automatic pruning when sync is automated
-      --config-management-plugin string           Config management plugin name
-      --dest-name string                          K8s cluster Name (e.g. minikube)
-      --dest-namespace string                     K8s target namespace (overrides the namespace specified in the ksonnet app.yaml)
-      --dest-server string                        K8s cluster URL (e.g. https://kubernetes.default.svc)
-      --directory-exclude string                  Set glob expression used to exclude files from application source path
-      --directory-include string                  Set glob expression used to include files from application source path
-      --directory-recurse                         Recurse directory
-      --env string                                Application environment to monitor
-  -f, --file string                               Filename or URL to Kubernetes manifests for the app
-      --helm-chart string                         Helm Chart name
-      --helm-set stringArray                      Helm set values on the command line (can be repeated to set several values: --helm-set key1=val1 --helm-set key2=val2)
-      --helm-set-file stringArray                 Helm set values from respective files specified via the command line (can be repeated to set several values: --helm-set-file key1=path1 --helm-set-file key2=path2)
-      --helm-set-string stringArray               Helm set STRING values on the command line (can be repeated to set several values: --helm-set-string key1=val1 --helm-set-string key2=val2)
-      --helm-version string                       Helm version
-  -h, --help                                      help for generate-spec
-      --jsonnet-ext-var-code stringArray          Jsonnet ext var
-      --jsonnet-ext-var-str stringArray           Jsonnet string ext var
-      --jsonnet-libs stringArray                  Additional jsonnet libs (prefixed by repoRoot)
-      --jsonnet-tla-code stringArray              Jsonnet top level code arguments
-      --jsonnet-tla-str stringArray               Jsonnet top level string arguments
-      --kustomize-common-annotation stringArray   Set common labels in Kustomize
-      --kustomize-common-label stringArray        Set common labels in Kustomize
-      --kustomize-image stringArray               Kustomize images (e.g. --kustomize-image node:8.15.0 --kustomize-image mysql=mariadb,alpine@sha256:24a0c4b4a4c0eb97a1aabb8e29f18e917d05abfe1b7a7c07857230879ce7d3d)
-      --kustomize-version string                  Kustomize version
-  -l, --label stringArray                         Labels to apply to the app
-      --name string                               A name for the app, ignored if a file is set (DEPRECATED)
-      --nameprefix string                         Kustomize nameprefix
-      --namesuffix string                         Kustomize namesuffix
-  -o, --output string                             Output format. One of: json|yaml (default "yaml")
-  -p, --parameter stringArray                     set a parameter override (e.g. -p guestbook=image=example/guestbook:latest)
-      --path string                               Path in repository to the app directory, ignored if a file is set
-      --plugin-env stringArray                    Additional plugin envs
-      --project string                            Application project name
-      --release-name string                       Helm release-name
-      --repo string                               Repository URL, ignored if a file is set
-      --retry-backoff-duration duration           Retry backoff base duration. Input needs to be a duration (e.g. 2m, 1h) (default 5s)
-      --retry-backoff-factor int                  Factor multiplies the base duration after each failed retry (default 2)
-      --retry-backoff-max-duration duration       Max retry backoff duration. Input needs to be a duration (e.g. 2m, 1h) (default 3m0s)
-      --retry-limit int                           Max number of allowed sync retries
-      --revision string                           The tracking source branch, tag, commit or Helm chart version the application will sync to
-      --revision-history-limit int                How many items to keep in revision history (default 10)
-      --self-heal                                 Set self healing when sync is automated
-      --sync-option Prune=false                   Add or remove a sync option, e.g add Prune=false. Remove using `!` prefix, e.g. `!Prune=false`
-      --sync-policy string                        Set the sync policy (one of: none, automated (aliases of automated: auto, automatic))
-      --validate                                  Validation of repo and cluster (default true)
-      --values stringArray                        Helm values file(s) to use
-      --values-literal-file string                Filename or URL to import as a literal Helm values block
+      --allow-empty                                Set allow zero live resources when sync is automated
+      --auto-prune                                 Set automatic pruning when sync is automated
+      --config-management-plugin string            Config management plugin name
+      --dest-name string                           K8s cluster Name (e.g. minikube)
+      --dest-namespace string                      K8s target namespace (overrides the namespace specified in the ksonnet app.yaml)
+      --dest-server string                         K8s cluster URL (e.g. https://kubernetes.default.svc)
+      --directory-exclude string                   Set glob expression used to exclude files from application source path
+      --directory-include string                   Set glob expression used to include files from application source path
+      --directory-recurse                          Recurse directory
+      --env string                                 Application environment to monitor
+  -f, --file string                                Filename or URL to Kubernetes manifests for the app
+      --helm-chart string                          Helm Chart name
+      --helm-set stringArray                       Helm set values on the command line (can be repeated to set several values: --helm-set key1=val1 --helm-set key2=val2)
+      --helm-set-file stringArray                  Helm set values from respective files specified via the command line (can be repeated to set several values: --helm-set-file key1=path1 --helm-set-file key2=path2)
+      --helm-set-string stringArray                Helm set STRING values on the command line (can be repeated to set several values: --helm-set-string key1=val1 --helm-set-string key2=val2)
+      --helm-version string                        Helm version
+  -h, --help                                       help for generate-spec
+      --jsonnet-ext-var-code stringArray           Jsonnet ext var
+      --jsonnet-ext-var-str stringArray            Jsonnet string ext var
+      --jsonnet-libs stringArray                   Additional jsonnet libs (prefixed by repoRoot)
+      --jsonnet-tla-code stringArray               Jsonnet top level code arguments
+      --jsonnet-tla-str stringArray                Jsonnet top level string arguments
+      --kustomize-common-annotation stringArray    Set common labels in Kustomize
+      --kustomize-common-label stringArray         Set common labels in Kustomize
+      --kustomize-image stringArray                Kustomize images (e.g. --kustomize-image node:8.15.0 --kustomize-image mysql=mariadb,alpine@sha256:24a0c4b4a4c0eb97a1aabb8e29f18e917d05abfe1b7a7c07857230879ce7d3d)
+      --kustomize-version string                   Kustomize version
+  -l, --label stringArray                          Labels to apply to the app
+      --name string                                A name for the app, ignored if a file is set (DEPRECATED)
+      --nameprefix string                          Kustomize nameprefix
+      --namesuffix string                          Kustomize namesuffix
+  -o, --output string                              Output format. One of: json|yaml (default "yaml")
+  -p, --parameter stringArray                      set a parameter override (e.g. -p guestbook=image=example/guestbook:latest)
+      --path string                                Path in repository to the app directory, ignored if a file is set
+      --plugin-env stringArray                     Additional plugin envs
+      --project string                             Application project name
+      --release-name string                        Helm release-name
+      --repo string                                Repository URL, ignored if a file is set
+      --revision string                            The tracking source branch, tag, commit or Helm chart version the application will sync to
+      --revision-history-limit int                 How many items to keep in revision history (default 10)
+      --self-heal                                  Set self healing when sync is automated
+      --sync-option Prune=false                    Add or remove a sync option, e.g add Prune=false. Remove using `!` prefix, e.g. `!Prune=false`
+      --sync-policy string                         Set the sync policy (one of: none, automated (aliases of automated: auto, automatic))
+      --sync-retry-backoff-duration duration       Sync retry backoff base duration. Input needs to be a duration (e.g. 2m, 1h) (default 5s)
+      --sync-retry-backoff-factor int              Factor multiplies the base duration after each failed sync retry (default 2)
+      --sync-retry-backoff-max-duration duration   Max sync retry backoff duration. Input needs to be a duration (e.g. 2m, 1h) (default 3m0s)
+      --sync-retry-limit int                       Max number of allowed sync retries
+      --validate                                   Validation of repo and cluster (default true)
+      --values stringArray                         Helm values file(s) to use
+      --values-literal-file string                 Filename or URL to import as a literal Helm values block
 ```
 
 ### SEE ALSO
diff --git a/docs/operator-manual/server-commands/argocd-util_rbac.md b/docs/operator-manual/server-commands/argocd-util_rbac.md
deleted file mode 100644
index 1dc03f6f7..000000000
--- a/docs/operator-manual/server-commands/argocd-util_rbac.md
+++ /dev/null
@@ -1,20 +0,0 @@
-## argocd-util rbac
-
-Validate and test RBAC configuration
-
-```
-argocd-util rbac [flags]
-```
-
-### Options
-
-```
-  -h, --help   help for rbac
-```
-
-### SEE ALSO
-
-* [argocd-util](argocd-util.md)	 - argocd-util tools used by Argo CD
-* [argocd-util rbac can](argocd-util_rbac_can.md)	 - Check RBAC permissions for a role or subject
-* [argocd-util rbac validate](argocd-util_rbac_validate.md)	 - Validate RBAC policy
-
diff --git a/docs/operator-manual/server-commands/argocd-util_rbac_can.md b/docs/operator-manual/server-commands/argocd-util_rbac_can.md
deleted file mode 100644
index 6071cb5e7..000000000
--- a/docs/operator-manual/server-commands/argocd-util_rbac_can.md
+++ /dev/null
@@ -1,70 +0,0 @@
-## argocd-util rbac can
-
-Check RBAC permissions for a role or subject
-
-### Synopsis
-
-
-Check whether a given role or subject has appropriate RBAC permissions to do
-something.
-
-
-```
-argocd-util rbac can ROLE/SUBJECT ACTION RESOURCE [SUB-RESOURCE] [flags]
-```
-
-### Examples
-
-```
-
-# Check whether role some:role has permissions to create an application in the
-# 'default' project, using a local policy.csv file
-argocd-util rbac can some:role create application 'default/app' --policy-file policy.csv
-
-# Policy file can also be K8s config map with data keys like argocd-rbac-cm,
-# i.e. 'policy.csv' and (optionally) 'policy.default'
-argocd-util rbac can some:role create application 'default/app' --policy-file argocd-rbac-cm.yaml
-
-# If --policy-file is not given, the ConfigMap 'argocd-rbac-cm' from K8s is
-# used. You need to specify the argocd namespace, and make sure that your
-# current Kubernetes context is pointing to the cluster Argo CD is running in
-argocd-util rbac can some:role create application 'default/app' --namespace argocd
-
-# You can override a possibly configured default role
-argocd-util rbac can someuser create application 'default/app' --default-role role:readonly
-
-
-```
-
-### Options
-
-```
-      --as string                      Username to impersonate for the operation
-      --as-group stringArray           Group to impersonate for the operation, this flag can be repeated to specify multiple groups.
-      --certificate-authority string   Path to a cert file for the certificate authority
-      --client-certificate string      Path to a client certificate file for TLS
-      --client-key string              Path to a client key file for TLS
-      --cluster string                 The name of the kubeconfig cluster to use
-      --context string                 The name of the kubeconfig context to use
-      --default-role string            name of the default role to use
-  -h, --help                           help for can
-      --insecure-skip-tls-verify       If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure
-      --kubeconfig string              Path to a kube config. Only required if out-of-cluster
-  -n, --namespace string               If present, the namespace scope for this CLI request
-      --password string                Password for basic authentication to the API server
-      --policy-file string             path to the policy file to use
-  -q, --quiet                          quiet mode - do not print results to stdout
-      --request-timeout string         The length of time to wait before giving up on a single server request. Non-zero values should contain a corresponding time unit (e.g. 1s, 2m, 3h). A value of zero means don't timeout requests. (default "0")
-      --server string                  The address and port of the Kubernetes API server
-      --strict                         whether to perform strict check on action and resource names (default true)
-      --tls-server-name string         If provided, this name will be used to validate server certificate. If this is not provided, hostname used to contact the server is used.
-      --token string                   Bearer token for authentication to the API server
-      --use-builtin-policy             whether to also use builtin-policy (default true)
-      --user string                    The name of the kubeconfig user to use
-      --username string                Username for basic authentication to the API server
-```
-
-### SEE ALSO
-
-* [argocd-util rbac](argocd-util_rbac.md)	 - Validate and test RBAC configuration
-
diff --git a/docs/operator-manual/server-commands/argocd-util_rbac_validate.md b/docs/operator-manual/server-commands/argocd-util_rbac_validate.md
deleted file mode 100644
index f121134e0..000000000
--- a/docs/operator-manual/server-commands/argocd-util_rbac_validate.md
+++ /dev/null
@@ -1,26 +0,0 @@
-## argocd-util rbac validate
-
-Validate RBAC policy
-
-### Synopsis
-
-
-Validates an RBAC policy for being syntactically correct. The policy must be
-a local file, and in either CSV or K8s ConfigMap format.
-
-
-```
-argocd-util rbac validate --policy-file=POLICYFILE [flags]
-```
-
-### Options
-
-```
-  -h, --help                 help for validate
-      --policy-file string   path to the policy file to use
-```
-
-### SEE ALSO
-
-* [argocd-util rbac](argocd-util_rbac.md)	 - Validate and test RBAC configuration
-
diff --git a/docs/operator-manual/server-commands/argocd-util_repo_generate-spec.md b/docs/operator-manual/server-commands/argocd-util_repo_generate-spec.md
index 30cd32d90..0f4b7adcc 100644
--- a/docs/operator-manual/server-commands/argocd-util_repo_generate-spec.md
+++ b/docs/operator-manual/server-commands/argocd-util_repo_generate-spec.md
@@ -23,10 +23,10 @@ argocd-util repo generate-spec REPOURL [flags]
   argocd-util repo generate-spec https://git.example.com/repos/repo --username git --password secret --insecure-skip-server-verification
 
   # Add a public Helm repository named 'stable' via HTTPS
-  argocd-util repo generate-spec https://kubernetes-charts.storage.googleapis.com --type helm --name stable  
+  argocd-util repo generate-spec https://charts.helm.sh/stable --type helm --name stable  
 
   # Add a private Helm repository named 'stable' via HTTPS
-  argocd-util repo generate-spec https://kubernetes-charts.storage.googleapis.com --type helm --name stable --username test --password test
+  argocd-util repo generate-spec https://charts.helm.sh/stable --type helm --name stable --username test --password test
 
   # Add a private Helm OCI-based repository named 'stable' via HTTPS
   argocd-util repo generate-spec helm-oci-registry.cn-zhangjiakou.cr.aliyuncs.com --type helm --name stable --enable-oci --username test --password test
diff --git a/docs/operator-manual/server-commands/argocd-util_settings_rbac_can.md b/docs/operator-manual/server-commands/argocd-util_settings_rbac_can.md
index e7358bed4..24a5c2d22 100644
--- a/docs/operator-manual/server-commands/argocd-util_settings_rbac_can.md
+++ b/docs/operator-manual/server-commands/argocd-util_settings_rbac_can.md
@@ -19,19 +19,19 @@ argocd-util settings rbac can ROLE/SUBJECT ACTION RESOURCE [SUB-RESOURCE] [flags
 
 # Check whether role some:role has permissions to create an application in the
 # 'default' project, using a local policy.csv file
-argocd-util rbac can some:role create application 'default/app' --policy-file policy.csv
+argocd-util settings rbac can some:role create application 'default/app' --policy-file policy.csv
 
 # Policy file can also be K8s config map with data keys like argocd-rbac-cm,
 # i.e. 'policy.csv' and (optionally) 'policy.default'
-argocd-util rbac can some:role create application 'default/app' --policy-file argocd-rbac-cm.yaml
+argocd-util settings rbac can some:role create application 'default/app' --policy-file argocd-rbac-cm.yaml
 
 # If --policy-file is not given, the ConfigMap 'argocd-rbac-cm' from K8s is
 # used. You need to specify the argocd namespace, and make sure that your
 # current Kubernetes context is pointing to the cluster Argo CD is running in
-argocd-util rbac can some:role create application 'default/app' --namespace argocd
+argocd-util settings rbac can some:role create application 'default/app' --namespace argocd
 
 # You can override a possibly configured default role
-argocd-util rbac can someuser create application 'default/app' --default-role role:readonly
+argocd-util settings rbac can someuser create application 'default/app' --default-role role:readonly
 
 
 ```
diff --git a/docs/user-guide/commands/argocd_app_create.md b/docs/user-guide/commands/argocd_app_create.md
index 890276809..f63baa8ea 100644
--- a/docs/user-guide/commands/argocd_app_create.md
+++ b/docs/user-guide/commands/argocd_app_create.md
@@ -20,7 +20,7 @@ argocd app create APPNAME [flags]
 	argocd app create helm-guestbook --repo https://github.com/argoproj/argocd-example-apps.git --path helm-guestbook --dest-namespace default --dest-server https://kubernetes.default.svc --helm-set replicaCount=2
 
 	# Create a Helm app from a Helm repo
-	argocd app create nginx-ingress --repo https://kubernetes-charts.storage.googleapis.com --helm-chart nginx-ingress --revision 1.24.3 --dest-namespace default --dest-server https://kubernetes.default.svc
+	argocd app create nginx-ingress --repo https://charts.helm.sh/stable --helm-chart nginx-ingress --revision 1.24.3 --dest-namespace default --dest-server https://kubernetes.default.svc
 
 	# Create a Kustomize app
 	argocd app create kustomize-guestbook --repo https://github.com/argoproj/argocd-example-apps.git --path kustomize-guestbook --dest-namespace default --dest-server https://kubernetes.default.svc --kustomize-image gcr.io/heptio-images/ks-guestbook-demo:0.1
@@ -33,55 +33,55 @@ argocd app create APPNAME [flags]
 ### Options
 
 ```
-      --allow-empty                               Set allow zero live resources when sync is automated
-      --auto-prune                                Set automatic pruning when sync is automated
-      --config-management-plugin string           Config management plugin name
-      --dest-name string                          K8s cluster Name (e.g. minikube)
-      --dest-namespace string                     K8s target namespace (overrides the namespace specified in the ksonnet app.yaml)
-      --dest-server string                        K8s cluster URL (e.g. https://kubernetes.default.svc)
-      --directory-exclude string                  Set glob expression used to exclude files from application source path
-      --directory-include string                  Set glob expression used to include files from application source path
-      --directory-recurse                         Recurse directory
-      --env string                                Application environment to monitor
-  -f, --file string                               Filename or URL to Kubernetes manifests for the app
-      --helm-chart string                         Helm Chart name
-      --helm-set stringArray                      Helm set values on the command line (can be repeated to set several values: --helm-set key1=val1 --helm-set key2=val2)
-      --helm-set-file stringArray                 Helm set values from respective files specified via the command line (can be repeated to set several values: --helm-set-file key1=path1 --helm-set-file key2=path2)
-      --helm-set-string stringArray               Helm set STRING values on the command line (can be repeated to set several values: --helm-set-string key1=val1 --helm-set-string key2=val2)
-      --helm-version string                       Helm version
-  -h, --help                                      help for create
-      --jsonnet-ext-var-code stringArray          Jsonnet ext var
-      --jsonnet-ext-var-str stringArray           Jsonnet string ext var
-      --jsonnet-libs stringArray                  Additional jsonnet libs (prefixed by repoRoot)
-      --jsonnet-tla-code stringArray              Jsonnet top level code arguments
-      --jsonnet-tla-str stringArray               Jsonnet top level string arguments
-      --kustomize-common-annotation stringArray   Set common labels in Kustomize
-      --kustomize-common-label stringArray        Set common labels in Kustomize
-      --kustomize-image stringArray               Kustomize images (e.g. --kustomize-image node:8.15.0 --kustomize-image mysql=mariadb,alpine@sha256:24a0c4b4a4c0eb97a1aabb8e29f18e917d05abfe1b7a7c07857230879ce7d3d)
-      --kustomize-version string                  Kustomize version
-  -l, --label stringArray                         Labels to apply to the app
-      --name string                               A name for the app, ignored if a file is set (DEPRECATED)
-      --nameprefix string                         Kustomize nameprefix
-      --namesuffix string                         Kustomize namesuffix
-  -p, --parameter stringArray                     set a parameter override (e.g. -p guestbook=image=example/guestbook:latest)
-      --path string                               Path in repository to the app directory, ignored if a file is set
-      --plugin-env stringArray                    Additional plugin envs
-      --project string                            Application project name
-      --release-name string                       Helm release-name
-      --repo string                               Repository URL, ignored if a file is set
-      --retry-backoff-duration duration           Retry backoff base duration. Input needs to be a duration (e.g. 2m, 1h) (default 5s)
-      --retry-backoff-factor int                  Factor multiplies the base duration after each failed retry (default 2)
-      --retry-backoff-max-duration duration       Max retry backoff duration. Input needs to be a duration (e.g. 2m, 1h) (default 3m0s)
-      --retry-limit int                           Max number of allowed sync retries
-      --revision string                           The tracking source branch, tag, commit or Helm chart version the application will sync to
-      --revision-history-limit int                How many items to keep in revision history (default 10)
-      --self-heal                                 Set self healing when sync is automated
-      --sync-option Prune=false                   Add or remove a sync option, e.g add Prune=false. Remove using `!` prefix, e.g. `!Prune=false`
-      --sync-policy string                        Set the sync policy (one of: none, automated (aliases of automated: auto, automatic))
-      --upsert                                    Allows to override application with the same name even if supplied application spec is different from existing spec
-      --validate                                  Validation of repo and cluster (default true)
-      --values stringArray                        Helm values file(s) to use
-      --values-literal-file string                Filename or URL to import as a literal Helm values block
+      --allow-empty                                Set allow zero live resources when sync is automated
+      --auto-prune                                 Set automatic pruning when sync is automated
+      --config-management-plugin string            Config management plugin name
+      --dest-name string                           K8s cluster Name (e.g. minikube)
+      --dest-namespace string                      K8s target namespace (overrides the namespace specified in the ksonnet app.yaml)
+      --dest-server string                         K8s cluster URL (e.g. https://kubernetes.default.svc)
+      --directory-exclude string                   Set glob expression used to exclude files from application source path
+      --directory-include string                   Set glob expression used to include files from application source path
+      --directory-recurse                          Recurse directory
+      --env string                                 Application environment to monitor
+  -f, --file string                                Filename or URL to Kubernetes manifests for the app
+      --helm-chart string                          Helm Chart name
+      --helm-set stringArray                       Helm set values on the command line (can be repeated to set several values: --helm-set key1=val1 --helm-set key2=val2)
+      --helm-set-file stringArray                  Helm set values from respective files specified via the command line (can be repeated to set several values: --helm-set-file key1=path1 --helm-set-file key2=path2)
+      --helm-set-string stringArray                Helm set STRING values on the command line (can be repeated to set several values: --helm-set-string key1=val1 --helm-set-string key2=val2)
+      --helm-version string                        Helm version
+  -h, --help                                       help for create
+      --jsonnet-ext-var-code stringArray           Jsonnet ext var
+      --jsonnet-ext-var-str stringArray            Jsonnet string ext var
+      --jsonnet-libs stringArray                   Additional jsonnet libs (prefixed by repoRoot)
+      --jsonnet-tla-code stringArray               Jsonnet top level code arguments
+      --jsonnet-tla-str stringArray                Jsonnet top level string arguments
+      --kustomize-common-annotation stringArray    Set common labels in Kustomize
+      --kustomize-common-label stringArray         Set common labels in Kustomize
+      --kustomize-image stringArray                Kustomize images (e.g. --kustomize-image node:8.15.0 --kustomize-image mysql=mariadb,alpine@sha256:24a0c4b4a4c0eb97a1aabb8e29f18e917d05abfe1b7a7c07857230879ce7d3d)
+      --kustomize-version string                   Kustomize version
+  -l, --label stringArray                          Labels to apply to the app
+      --name string                                A name for the app, ignored if a file is set (DEPRECATED)
+      --nameprefix string                          Kustomize nameprefix
+      --namesuffix string                          Kustomize namesuffix
+  -p, --parameter stringArray                      set a parameter override (e.g. -p guestbook=image=example/guestbook:latest)
+      --path string                                Path in repository to the app directory, ignored if a file is set
+      --plugin-env stringArray                     Additional plugin envs
+      --project string                             Application project name
+      --release-name string                        Helm release-name
+      --repo string                                Repository URL, ignored if a file is set
+      --revision string                            The tracking source branch, tag, commit or Helm chart version the application will sync to
+      --revision-history-limit int                 How many items to keep in revision history (default 10)
+      --self-heal                                  Set self healing when sync is automated
+      --sync-option Prune=false                    Add or remove a sync option, e.g add Prune=false. Remove using `!` prefix, e.g. `!Prune=false`
+      --sync-policy string                         Set the sync policy (one of: none, automated (aliases of automated: auto, automatic))
+      --sync-retry-backoff-duration duration       Sync retry backoff base duration. Input needs to be a duration (e.g. 2m, 1h) (default 5s)
+      --sync-retry-backoff-factor int              Factor multiplies the base duration after each failed sync retry (default 2)
+      --sync-retry-backoff-max-duration duration   Max sync retry backoff duration. Input needs to be a duration (e.g. 2m, 1h) (default 3m0s)
+      --sync-retry-limit int                       Max number of allowed sync retries
+      --upsert                                     Allows to override application with the same name even if supplied application spec is different from existing spec
+      --validate                                   Validation of repo and cluster (default true)
+      --values stringArray                         Helm values file(s) to use
+      --values-literal-file string                 Filename or URL to import as a literal Helm values block
 ```
 
 ### Options inherited from parent commands
diff --git a/docs/user-guide/commands/argocd_app_diff.md b/docs/user-guide/commands/argocd_app_diff.md
index 38f4e831d..c1c2583ca 100644
--- a/docs/user-guide/commands/argocd_app_diff.md
+++ b/docs/user-guide/commands/argocd_app_diff.md
@@ -15,6 +15,7 @@ argocd app diff APPNAME [flags]
 ### Options
 
 ```
+      --exit-code                Return non-zero exit code when there is a diff (default true)
       --hard-refresh             Refresh application data as well as target manifests cache
   -h, --help                     help for diff
       --local string             Compare live app to a local manifests
diff --git a/docs/user-guide/commands/argocd_app_set.md b/docs/user-guide/commands/argocd_app_set.md
index 6db866cf2..3d099a67e 100644
--- a/docs/user-guide/commands/argocd_app_set.md
+++ b/docs/user-guide/commands/argocd_app_set.md
@@ -9,51 +9,51 @@ argocd app set APPNAME [flags]
 ### Options
 
 ```
-      --allow-empty                               Set allow zero live resources when sync is automated
-      --auto-prune                                Set automatic pruning when sync is automated
-      --config-management-plugin string           Config management plugin name
-      --dest-name string                          K8s cluster Name (e.g. minikube)
-      --dest-namespace string                     K8s target namespace (overrides the namespace specified in the ksonnet app.yaml)
-      --dest-server string                        K8s cluster URL (e.g. https://kubernetes.default.svc)
-      --directory-exclude string                  Set glob expression used to exclude files from application source path
-      --directory-include string                  Set glob expression used to include files from application source path
-      --directory-recurse                         Recurse directory
-      --env string                                Application environment to monitor
-      --helm-chart string                         Helm Chart name
-      --helm-set stringArray                      Helm set values on the command line (can be repeated to set several values: --helm-set key1=val1 --helm-set key2=val2)
-      --helm-set-file stringArray                 Helm set values from respective files specified via the command line (can be repeated to set several values: --helm-set-file key1=path1 --helm-set-file key2=path2)
-      --helm-set-string stringArray               Helm set STRING values on the command line (can be repeated to set several values: --helm-set-string key1=val1 --helm-set-string key2=val2)
-      --helm-version string                       Helm version
-  -h, --help                                      help for set
-      --jsonnet-ext-var-code stringArray          Jsonnet ext var
-      --jsonnet-ext-var-str stringArray           Jsonnet string ext var
-      --jsonnet-libs stringArray                  Additional jsonnet libs (prefixed by repoRoot)
-      --jsonnet-tla-code stringArray              Jsonnet top level code arguments
-      --jsonnet-tla-str stringArray               Jsonnet top level string arguments
-      --kustomize-common-annotation stringArray   Set common labels in Kustomize
-      --kustomize-common-label stringArray        Set common labels in Kustomize
-      --kustomize-image stringArray               Kustomize images (e.g. --kustomize-image node:8.15.0 --kustomize-image mysql=mariadb,alpine@sha256:24a0c4b4a4c0eb97a1aabb8e29f18e917d05abfe1b7a7c07857230879ce7d3d)
-      --kustomize-version string                  Kustomize version
-      --nameprefix string                         Kustomize nameprefix
-      --namesuffix string                         Kustomize namesuffix
-  -p, --parameter stringArray                     set a parameter override (e.g. -p guestbook=image=example/guestbook:latest)
-      --path string                               Path in repository to the app directory, ignored if a file is set
-      --plugin-env stringArray                    Additional plugin envs
-      --project string                            Application project name
-      --release-name string                       Helm release-name
-      --repo string                               Repository URL, ignored if a file is set
-      --retry-backoff-duration duration           Retry backoff base duration. Input needs to be a duration (e.g. 2m, 1h) (default 5s)
-      --retry-backoff-factor int                  Factor multiplies the base duration after each failed retry (default 2)
-      --retry-backoff-max-duration duration       Max retry backoff duration. Input needs to be a duration (e.g. 2m, 1h) (default 3m0s)
-      --retry-limit int                           Max number of allowed sync retries
-      --revision string                           The tracking source branch, tag, commit or Helm chart version the application will sync to
-      --revision-history-limit int                How many items to keep in revision history (default 10)
-      --self-heal                                 Set self healing when sync is automated
-      --sync-option Prune=false                   Add or remove a sync option, e.g add Prune=false. Remove using `!` prefix, e.g. `!Prune=false`
-      --sync-policy string                        Set the sync policy (one of: none, automated (aliases of automated: auto, automatic))
-      --validate                                  Validation of repo and cluster (default true)
-      --values stringArray                        Helm values file(s) to use
-      --values-literal-file string                Filename or URL to import as a literal Helm values block
+      --allow-empty                                Set allow zero live resources when sync is automated
+      --auto-prune                                 Set automatic pruning when sync is automated
+      --config-management-plugin string            Config management plugin name
+      --dest-name string                           K8s cluster Name (e.g. minikube)
+      --dest-namespace string                      K8s target namespace (overrides the namespace specified in the ksonnet app.yaml)
+      --dest-server string                         K8s cluster URL (e.g. https://kubernetes.default.svc)
+      --directory-exclude string                   Set glob expression used to exclude files from application source path
+      --directory-include string                   Set glob expression used to include files from application source path
+      --directory-recurse                          Recurse directory
+      --env string                                 Application environment to monitor
+      --helm-chart string                          Helm Chart name
+      --helm-set stringArray                       Helm set values on the command line (can be repeated to set several values: --helm-set key1=val1 --helm-set key2=val2)
+      --helm-set-file stringArray                  Helm set values from respective files specified via the command line (can be repeated to set several values: --helm-set-file key1=path1 --helm-set-file key2=path2)
+      --helm-set-string stringArray                Helm set STRING values on the command line (can be repeated to set several values: --helm-set-string key1=val1 --helm-set-string key2=val2)
+      --helm-version string                        Helm version
+  -h, --help                                       help for set
+      --jsonnet-ext-var-code stringArray           Jsonnet ext var
+      --jsonnet-ext-var-str stringArray            Jsonnet string ext var
+      --jsonnet-libs stringArray                   Additional jsonnet libs (prefixed by repoRoot)
+      --jsonnet-tla-code stringArray               Jsonnet top level code arguments
+      --jsonnet-tla-str stringArray                Jsonnet top level string arguments
+      --kustomize-common-annotation stringArray    Set common labels in Kustomize
+      --kustomize-common-label stringArray         Set common labels in Kustomize
+      --kustomize-image stringArray                Kustomize images (e.g. --kustomize-image node:8.15.0 --kustomize-image mysql=mariadb,alpine@sha256:24a0c4b4a4c0eb97a1aabb8e29f18e917d05abfe1b7a7c07857230879ce7d3d)
+      --kustomize-version string                   Kustomize version
+      --nameprefix string                          Kustomize nameprefix
+      --namesuffix string                          Kustomize namesuffix
+  -p, --parameter stringArray                      set a parameter override (e.g. -p guestbook=image=example/guestbook:latest)
+      --path string                                Path in repository to the app directory, ignored if a file is set
+      --plugin-env stringArray                     Additional plugin envs
+      --project string                             Application project name
+      --release-name string                        Helm release-name
+      --repo string                                Repository URL, ignored if a file is set
+      --revision string                            The tracking source branch, tag, commit or Helm chart version the application will sync to
+      --revision-history-limit int                 How many items to keep in revision history (default 10)
+      --self-heal                                  Set self healing when sync is automated
+      --sync-option Prune=false                    Add or remove a sync option, e.g add Prune=false. Remove using `!` prefix, e.g. `!Prune=false`
+      --sync-policy string                         Set the sync policy (one of: none, automated (aliases of automated: auto, automatic))
+      --sync-retry-backoff-duration duration       Sync retry backoff base duration. Input needs to be a duration (e.g. 2m, 1h) (default 5s)
+      --sync-retry-backoff-factor int              Factor multiplies the base duration after each failed sync retry (default 2)
+      --sync-retry-backoff-max-duration duration   Max sync retry backoff duration. Input needs to be a duration (e.g. 2m, 1h) (default 3m0s)
+      --sync-retry-limit int                       Max number of allowed sync retries
+      --validate                                   Validation of repo and cluster (default true)
+      --values stringArray                         Helm values file(s) to use
+      --values-literal-file string                 Filename or URL to import as a literal Helm values block
 ```
 
 ### Options inherited from parent commands
diff --git a/docs/user-guide/commands/argocd_repo_add.md b/docs/user-guide/commands/argocd_repo_add.md
index c3a6f4ef1..c232fdd56 100644
--- a/docs/user-guide/commands/argocd_repo_add.md
+++ b/docs/user-guide/commands/argocd_repo_add.md
@@ -22,10 +22,10 @@ argocd repo add REPOURL [flags]
   argocd repo add https://git.example.com/repos/repo --username git --password secret --insecure-skip-server-verification
 
   # Add a public Helm repository named 'stable' via HTTPS
-  argocd repo add https://kubernetes-charts.storage.googleapis.com --type helm --name stable  
+  argocd repo add https://charts.helm.sh/stable --type helm --name stable  
 
   # Add a private Helm repository named 'stable' via HTTPS
-  argocd repo add https://kubernetes-charts.storage.googleapis.com --type helm --name stable --username test --password test
+  argocd repo add https://charts.helm.sh/stable --type helm --name stable --username test --password test
 
   # Add a private Helm OCI-based repository named 'stable' via HTTPS
   argocd repo add helm-oci-registry.cn-zhangjiakou.cr.aliyuncs.com --type helm --name stable --enable-oci --username test --password test
diff --git a/docs/user-guide/tracking_strategies.md b/docs/user-guide/tracking_strategies.md
index d3175f4e9..e1abe8571 100644
--- a/docs/user-guide/tracking_strategies.md
+++ b/docs/user-guide/tracking_strategies.md
@@ -40,7 +40,7 @@ If a branch name, or a symbolic reference (like HEAD) is specified, Argo CD will
 live state against the resource manifests defined at the tip of the specified branch or the
 resolved commit of the symbolic reference.
 
-To redeploy an app,  makes a changes to your manifests, commit/push to the branch/symbolic reference. They will then detected by Argo CD.
+To redeploy an app, make a change to (at least) one of your manifests, commit and push to the tracked branch/symbolic reference. The change will then be detected by Argo CD.
 
 ### Tag Tracking
 
diff --git a/go.mod b/go.mod
index 8a5a0318c..23095febf 100644
--- a/go.mod
+++ b/go.mod
@@ -1,13 +1,13 @@
 module github.com/argoproj/argo-cd
 
-go 1.14
+go 1.16
 
 require (
 	github.com/Masterminds/semver v1.5.0
 	github.com/TomOnTime/utfutil v0.0.0-20180511104225-09c41003ee1d
 	github.com/alicebob/miniredis v2.5.0+incompatible
 	github.com/alicebob/miniredis/v2 v2.14.2
-	github.com/argoproj/gitops-engine v0.3.0
+	github.com/argoproj/gitops-engine v0.3.1-0.20210325215106-1ce2acc845d2
 	github.com/argoproj/pkg v0.2.0
 	github.com/bombsimon/logrusr v1.0.0
 	github.com/bradleyfalzon/ghinstallation v1.1.1
diff --git a/go.sum b/go.sum
index 025de7e47..c6a971800 100644
--- a/go.sum
+++ b/go.sum
@@ -86,8 +86,8 @@ github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo
 github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA=
 github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
 github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
-github.com/argoproj/gitops-engine v0.3.0 h1:emDED8sHRX81mQOi8C24oW1wTJ3peXRHI6RJlvZWHkk=
-github.com/argoproj/gitops-engine v0.3.0/go.mod h1:IBHhAkqlC+3r/wBWUitWSidQhPzlLoSTWp2htq3dyQk=
+github.com/argoproj/gitops-engine v0.3.1-0.20210325215106-1ce2acc845d2 h1:SAzMwXM3dXNRam/iuNrvQ56KFA71b3Kcpuc2hzbxJVU=
+github.com/argoproj/gitops-engine v0.3.1-0.20210325215106-1ce2acc845d2/go.mod h1:IBHhAkqlC+3r/wBWUitWSidQhPzlLoSTWp2htq3dyQk=
 github.com/argoproj/pkg v0.2.0 h1:ETgC600kr8WcAi3MEVY5sA1H7H/u1/IysYOobwsZ8No=
 github.com/argoproj/pkg v0.2.0/go.mod h1:F4TZgInLUEjzsWFB/BTJBsewoEy0ucnKSq6vmQiD/yc=
 github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
@@ -218,7 +218,6 @@ github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5Kwzbycv
 github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
 github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ=
 github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
-github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ=
 github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
 github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
 github.com/form3tech-oss/jwt-go v3.2.2+incompatible h1:TcekIExNqud5crz4xD2pavyTgWiPvpYe4Xau31I0PRk=
diff --git a/hack/installers/install-lint-tools.sh b/hack/installers/install-lint-tools.sh
index a2805ee53..4c9bc3bb1 100755
--- a/hack/installers/install-lint-tools.sh
+++ b/hack/installers/install-lint-tools.sh
@@ -1,4 +1,4 @@
 #!/bin/bash
 set -eux -o pipefail
 
-GO111MODULE=on go get github.com/golangci/golangci-lint/cmd/golangci-lint@v1.26.0
+GO111MODULE=on go get github.com/golangci/golangci-lint/cmd/golangci-lint@v1.38.0
diff --git a/hack/known_types/main.go b/hack/known_types/main.go
index cae0cd934..9a6f804eb 100644
--- a/hack/known_types/main.go
+++ b/hack/known_types/main.go
@@ -7,7 +7,6 @@ import (
 	"go/types"
 	"io/ioutil"
 	"os"
-	"runtime"
 	"strings"
 
 	"github.com/spf13/cobra"
@@ -38,14 +37,8 @@ func newCommand() *cobra.Command {
 			packagePath := args[1]
 			outputPath := args[2]
 
-			var imprt types.Importer
-			if runtime.GOOS == "linux" {
-				// nolint:staticcheck
-				imprt = importer.For("source", nil)
-			} else {
-				imprt = importer.Default()
-			}
-
+			// nolint:staticcheck
+			imprt := importer.For("source", nil)
 			pkg, err := imprt.Import(packagePath)
 			if err != nil {
 				return err
diff --git a/manifests/ha/base/redis-ha/generate.sh b/manifests/ha/base/redis-ha/generate.sh
index 2da6a626d..7ef509a67 100755
--- a/manifests/ha/base/redis-ha/generate.sh
+++ b/manifests/ha/base/redis-ha/generate.sh
@@ -12,5 +12,5 @@ helm template argocd ./chart \
   >> ./chart/upstream_orig.yaml
 
 sed -e 's/check inter 1s/check inter 3s/' ./chart/upstream_orig.yaml >> ./chart/upstream.yaml && rm ./chart/upstream_orig.yaml
-sed -i 's/timeout server 30s/timeout server 6m/' ./chart/upstream.yaml
-sed -i 's/timeout client 30s/timeout client 6m/' ./chart/upstream.yaml
+sed -i.bak 's/timeout server 30s/timeout server 6m/' ./chart/upstream.yaml && rm ./chart/upstream.yaml.bak
+sed -i.bak 's/timeout client 30s/timeout client 6m/' ./chart/upstream.yaml && rm ./chart/upstream.yaml.bak
diff --git a/pkg/apis/application/v1alpha1/types.go b/pkg/apis/application/v1alpha1/types.go
index fa1359a71..1e7c5f2c3 100644
--- a/pkg/apis/application/v1alpha1/types.go
+++ b/pkg/apis/application/v1alpha1/types.go
@@ -191,7 +191,7 @@ func (a *ApplicationSource) IsHelmOci() bool {
 	if a.Chart == "" {
 		return false
 	}
-	return helm.IsHelmOciChart(a.Chart)
+	return helm.IsHelmOciRepo(a.RepoURL)
 }
 
 // IsZero returns true if the application source is considered empty
diff --git a/reposerver/repository/repository.go b/reposerver/repository/repository.go
index 13029b250..632873503 100644
--- a/reposerver/repository/repository.go
+++ b/reposerver/repository/repository.go
@@ -232,17 +232,13 @@ func (s *Service) runRepoOperation(
 	}
 
 	if source.IsHelm() {
-		version, err := semver.NewVersion(revision)
-		if err != nil {
-			return nil, err
-		}
 		if settings.noCache {
-			err = helmClient.CleanChartCache(source.Chart, version)
+			err = helmClient.CleanChartCache(source.Chart, revision)
 			if err != nil {
 				return nil, err
 			}
 		}
-		chartPath, closer, err := helmClient.ExtractChart(source.Chart, version)
+		chartPath, closer, err := helmClient.ExtractChart(source.Chart, revision)
 		if err != nil {
 			return nil, err
 		}
@@ -458,7 +454,7 @@ func (s *Service) getManifestCacheEntry(cacheKey string, q *apiclient.ManifestRe
 func getHelmRepos(repositories []*v1alpha1.Repository) []helm.HelmRepository {
 	repos := make([]helm.HelmRepository, 0)
 	for _, repo := range repositories {
-		repos = append(repos, helm.HelmRepository{Name: repo.Name, Repo: repo.Repo, Creds: repo.GetHelmCreds()})
+		repos = append(repos, helm.HelmRepository{Name: repo.Name, Repo: repo.Repo, Creds: repo.GetHelmCreds(), EnableOci: repo.EnableOCI})
 	}
 	return repos
 }
@@ -1301,13 +1297,12 @@ func (s *Service) newClientResolveRevision(repo *v1alpha1.Repository, revision s
 }
 
 func (s *Service) newHelmClientResolveRevision(repo *v1alpha1.Repository, revision string, chart string, noCache bool) (helm.Client, string, error) {
-	helmClient := s.newHelmClient(repo.Repo, repo.GetHelmCreds(), repo.EnableOCI || helm.IsHelmOciChart(chart))
-	if helm.IsVersion(revision) {
+	enableOCI := repo.EnableOCI || helm.IsHelmOciRepo(repo.Repo)
+	helmClient := s.newHelmClient(repo.Repo, repo.GetHelmCreds(), enableOCI)
+	// OCI helm registers don't support semver ranges. Assuming that given revision is exact version
+	if helm.IsVersion(revision) || enableOCI {
 		return helmClient, revision, nil
 	}
-	if repo.EnableOCI {
-		return nil, "", errors.New("OCI helm registers don't support semver ranges. Exact revision must be specified.")
-	}
 	constraints, err := semver.NewConstraint(revision)
 	if err != nil {
 		return nil, "", fmt.Errorf("invalid revision '%s': %v", revision, err)
diff --git a/server/application/application.go b/server/application/application.go
index b7f011e77..12b60b3ef 100644
--- a/server/application/application.go
+++ b/server/application/application.go
@@ -736,7 +736,7 @@ func (s *Server) Watch(q *application.ApplicationQuery, ws application.Applicati
 }
 
 func (s *Server) validateAndNormalizeApp(ctx context.Context, app *appv1.Application, validate bool) error {
-	proj, err := s.appclientset.ArgoprojV1alpha1().AppProjects(s.ns).Get(ctx, app.Spec.GetProject(), metav1.GetOptions{})
+	proj, err := argo.GetAppProject(&app.Spec, applisters.NewAppProjectLister(s.projInformer.GetIndexer()), s.ns, s.settingsMgr)
 	if err != nil {
 		if apierr.IsNotFound(err) {
 			return status.Errorf(codes.InvalidArgument, "application references project %s which does not exist", app.Spec.Project)
diff --git a/ui/src/app/applications/components/pod-logs-viewer/pod-logs-viewer.tsx b/ui/src/app/applications/components/pod-logs-viewer/pod-logs-viewer.tsx
index bec2a89b4..8ea3a19e6 100644
--- a/ui/src/app/applications/components/pod-logs-viewer/pod-logs-viewer.tsx
+++ b/ui/src/app/applications/components/pod-logs-viewer/pod-logs-viewer.tsx
@@ -3,7 +3,6 @@ import * as classNames from 'classnames';
 import * as React from 'react';
 import {useState} from 'react';
 import {Link} from 'react-router-dom';
-import {Observable} from 'rxjs';
 
 import * as models from '../../../shared/models';
 import {services} from '../../../shared/services';
@@ -43,11 +42,29 @@ export const PodsLogsViewer = (props: PodLogsProps & {fullscreen?: boolean}) =>
         literal: string;
         inverse: boolean;
     }
+
+    const [filterText, setFilterText] = useState('');
     const [filter, setFilter] = useState({inverse: false, literal: ''} as FilterData);
 
-    const filterQuery = () => {
-        return filter.literal && `${filter.inverse ? '!' : ''}${filter.literal}`;
+    const formatFilter = (f: FilterData): string => {
+        return f.literal && `${f.inverse ? '!' : ''}${f.literal}`;
     };
+
+    const [filterQuery, setFilterQuery] = React.useState(formatFilter(filter));
+    React.useEffect(() => {
+        setFilterQuery(formatFilter(filter));
+        if (loader) {
+            loader.reload();
+        }
+    }, [filter]);
+
+    React.useEffect(() => {
+        const to = setTimeout(() => {
+            setFilter({...filter, literal: filterText});
+        }, 500);
+        return () => clearTimeout(to);
+    }, [filterText]);
+
     const fullscreenURL =
         `/applications/${props.applicationName}/${props.namespace}/${props.containerName}/logs?` +
         `podName=${props.podName}&group=${props.group}&kind=${props.kind}&name=${props.name}`;
@@ -119,7 +136,6 @@ export const PodsLogsViewer = (props: PodLogsProps & {fullscreen?: boolean}) =>
                         </button>
                         <button
                             className='argo-button argo-button--base'
-                            style={{width: '100px'}}
                             onClick={async () => {
                                 const downloadURL = services.applications.getDownloadLogsURL(
                                     props.applicationName,
@@ -138,29 +154,20 @@ export const PodsLogsViewer = (props: PodLogsProps & {fullscreen?: boolean}) =>
                             </Link>
                         )}
                         <div className='pod-logs-viewer__filter'>
-                            <button
-                                className={`argo-button argo-button--base${filter.inverse ? '' : '-o'}`}
-                                onClick={() => setFilter({...filter, inverse: !filter.inverse})}
-                                style={{marginRight: '10px'}}>
-                                !
-                            </button>
+                            <Tooltip content={`Show lines that ${!filter.inverse ? '' : 'do not'} match filter`}>
+                                <button
+                                    className={`argo-button argo-button--base${filter.inverse ? '' : '-o'}`}
+                                    onClick={() => setFilter({...filter, inverse: !filter.inverse})}
+                                    style={{marginRight: '10px'}}>
+                                    !
+                                </button>
+                            </Tooltip>
                             <input
-                                ref={input => {
-                                    if (input) {
-                                        Observable.fromEvent(input, 'keyup')
-                                            .debounceTime(500)
-                                            .subscribe(() => {
-                                                if (loader) {
-                                                    loader.reload();
-                                                }
-                                            });
-                                    }
-                                }}
                                 type='text'
                                 placeholder='Filter string'
                                 className='argo-field'
-                                value={filter.literal}
-                                onChange={e => setFilter({...filter, literal: e.target.value})}
+                                value={filterText}
+                                onChange={e => setFilterText(e.target.value)}
                                 style={{padding: 0}}
                             />
                         </div>
@@ -185,7 +192,7 @@ export const PodsLogsViewer = (props: PodLogsProps & {fullscreen?: boolean}) =>
                                     maxLines * (page.number + 1),
                                     prefs.appDetails.followLogs && page.number === 0,
                                     page.untilTimes[page.untilTimes.length - 1],
-                                    filterQuery()
+                                    filterQuery
                                 )
                                 // show only current page lines
                                 .scan((lines, logEntry) => {
diff --git a/ui/src/app/settings/components/project-details/project-details.tsx b/ui/src/app/settings/components/project-details/project-details.tsx
index eb44d703b..037f72ee2 100644
--- a/ui/src/app/settings/components/project-details/project-details.tsx
+++ b/ui/src/app/settings/components/project-details/project-details.tsx
@@ -50,6 +50,26 @@ function loadGlobal(name: string) {
                 merged.clusterResourceWhitelist = merged.clusterResourceWhitelist.concat(proj.spec.clusterResourceWhitelist || []);
                 merged.namespaceResourceBlacklist = merged.namespaceResourceBlacklist.concat(proj.spec.namespaceResourceBlacklist || []);
                 merged.namespaceResourceWhitelist = merged.namespaceResourceWhitelist.concat(proj.spec.namespaceResourceWhitelist || []);
+                merged.sourceRepos = merged.sourceRepos.concat(proj.spec.sourceRepos || []);
+                merged.destinations = merged.destinations.concat(proj.spec.destinations || []);
+
+                merged.sourceRepos = merged.sourceRepos.filter((item, index) => {
+                    return (
+                        index ===
+                        merged.sourceRepos.findIndex(obj => {
+                            return obj === item;
+                        })
+                    );
+                });
+
+                merged.destinations = merged.destinations.filter((item, index) => {
+                    return (
+                        index ===
+                        merged.destinations.findIndex(obj => {
+                            return obj.server === item.server && obj.namespace === item.namespace;
+                        })
+                    );
+                });
 
                 merged.clusterResourceBlacklist = merged.clusterResourceBlacklist.filter((item, index) => {
                     return (
diff --git a/ui/src/app/settings/components/project-details/resource-lists-panel.tsx b/ui/src/app/settings/components/project-details/resource-lists-panel.tsx
index c1224669e..2e5c1d1fe 100644
--- a/ui/src/app/settings/components/project-details/resource-lists-panel.tsx
+++ b/ui/src/app/settings/components/project-details/resource-lists-panel.tsx
@@ -3,7 +3,7 @@ import * as React from 'react';
 import {FormApi} from 'react-form';
 
 import {EditablePanel} from '../../../shared/components';
-import {GroupKind, Groups, Project, ProjectSpec, ResourceKinds} from '../../../shared/models';
+import {ApplicationDestination, GroupKind, Groups, Project, ProjectSpec, ResourceKinds} from '../../../shared/models';
 
 function removeEl(items: any[], index: number) {
     return items.slice(0, index).concat(items.slice(index + 1));
@@ -69,6 +69,71 @@ function viewList(type: field, proj: Project) {
     );
 }
 
+const sourceReposInfoByField: {[type: string]: {title: string; helpText: string}} = {
+    sourceRepos: {
+        title: 'source repositories',
+        helpText: 'Git repositories where application manifests are permitted to be retrieved from'
+    }
+};
+
+function viewSourceReposInfoList(type: field, proj: Project) {
+    const info = sourceReposInfoByField[type];
+    const list = proj.spec[type] as Array<string>;
+    return (
+        <React.Fragment>
+            <p className='project-details__list-title'>
+                {info.title} {helpTip(info.helpText)}
+            </p>
+            {(list || []).length > 0 ? (
+                <React.Fragment>
+                    {list.map((repo, i) => (
+                        <div className='row white-box__details-row' key={i}>
+                            <div className='columns small-12'>{repo}</div>
+                        </div>
+                    ))}
+                </React.Fragment>
+            ) : (
+                <p>The {info.title} is empty</p>
+            )}
+        </React.Fragment>
+    );
+}
+
+const destinationsInfoByField: {[type: string]: {title: string; helpText: string}} = {
+    destinations: {
+        title: 'destinations',
+        helpText: 'Cluster and namespaces where applications are permitted to be deployed to'
+    }
+};
+
+function viewDestinationsInfoList(type: field, proj: Project) {
+    const info = destinationsInfoByField[type];
+    const list = proj.spec[type] as Array<ApplicationDestination>;
+    return (
+        <React.Fragment>
+            <p className='project-details__list-title'>
+                {info.title} {helpTip(info.helpText)}
+            </p>
+            {(list || []).length > 0 ? (
+                <React.Fragment>
+                    <div className='row white-box__details-row'>
+                        <div className='columns small-4'>Server</div>
+                        <div className='columns small-8'>Namespace</div>
+                    </div>
+                    {list.map((destination, i) => (
+                        <div className='row white-box__details-row' key={i}>
+                            <div className='columns small-4'>{destination.server}</div>
+                            <div className='columns small-8'>{destination.namespace}</div>
+                        </div>
+                    ))}
+                </React.Fragment>
+            ) : (
+                <p>The {info.title} is empty</p>
+            )}
+        </React.Fragment>
+    );
+}
+
 function editList(type: field, formApi: FormApi) {
     const info = infoByField[type];
 
@@ -114,6 +179,8 @@ export const ResourceListsPanel = ({proj, saveProject, title}: {proj: Project; t
                 {Object.keys(infoByField).map(key => (
                     <React.Fragment key={key}>{viewList(key as field, proj)}</React.Fragment>
                 ))}
+                {!proj.metadata && Object.keys(sourceReposInfoByField).map(key => <React.Fragment key={key}>{viewSourceReposInfoList(key as field, proj)}</React.Fragment>)}
+                {!proj.metadata && Object.keys(destinationsInfoByField).map(key => <React.Fragment key={key}>{viewDestinationsInfoList(key as field, proj)}</React.Fragment>)}
             </React.Fragment>
         }
         edit={
diff --git a/ui/src/app/shared/services/applications-service.ts b/ui/src/app/shared/services/applications-service.ts
index f110c7e9c..29758f386 100644
--- a/ui/src/app/shared/services/applications-service.ts
+++ b/ui/src/app/shared/services/applications-service.ts
@@ -113,7 +113,7 @@ export class ApplicationsService {
 
     public delete(name: string, propagationPolicy: string): Promise<boolean> {
         let cascade = true;
-        if (propagationPolicy === 'orphan') {
+        if (propagationPolicy === 'non-cascading') {
             propagationPolicy = '';
             cascade = false;
         }
diff --git a/util/argo/argo.go b/util/argo/argo.go
index b348b971f..d1790f5c0 100644
--- a/util/argo/argo.go
+++ b/util/argo/argo.go
@@ -3,6 +3,7 @@ package argo
 import (
 	"context"
 	"encoding/json"
+	"errors"
 	"fmt"
 	"strings"
 	"time"
@@ -172,6 +173,9 @@ func TestRepo(repo *argoappv1.Repository) error {
 		},
 		"helm": func() error {
 			if repo.EnableOCI {
+				if !helm.IsHelmOciRepo(repo.Repo) {
+					return errors.New("OCI Helm repository URL should include hostname and port only")
+				}
 				_, err := helm.NewClient(repo.Repo, repo.GetHelmCreds(), repo.EnableOCI).TestHelmOCI()
 				return err
 			} else {
diff --git a/util/helm/client.go b/util/helm/client.go
index c12163c0a..453750c39 100644
--- a/util/helm/client.go
+++ b/util/helm/client.go
@@ -16,16 +16,13 @@ import (
 	"strings"
 	"time"
 
-	"github.com/argoproj/argo-cd/common"
-
-	"github.com/argoproj/argo-cd/util/env"
-
-	"github.com/Masterminds/semver"
 	"github.com/argoproj/pkg/sync"
 	log "github.com/sirupsen/logrus"
 	"gopkg.in/yaml.v2"
 
+	"github.com/argoproj/argo-cd/common"
 	"github.com/argoproj/argo-cd/util/cache"
+	"github.com/argoproj/argo-cd/util/env"
 	executil "github.com/argoproj/argo-cd/util/exec"
 	"github.com/argoproj/argo-cd/util/io"
 )
@@ -47,8 +44,8 @@ type Creds struct {
 }
 
 type Client interface {
-	CleanChartCache(chart string, version *semver.Version) error
-	ExtractChart(chart string, version *semver.Version) (string, io.Closer, error)
+	CleanChartCache(chart string, version string) error
+	ExtractChart(chart string, version string) (string, io.Closer, error)
 	GetIndex(noCache bool) (*Index, error)
 	TestHelmOCI() (bool, error)
 }
@@ -97,11 +94,11 @@ func (c *nativeHelmChart) ensureHelmChartRepoPath() error {
 	return nil
 }
 
-func (c *nativeHelmChart) CleanChartCache(chart string, version *semver.Version) error {
+func (c *nativeHelmChart) CleanChartCache(chart string, version string) error {
 	return os.RemoveAll(c.getCachedChartPath(chart, version))
 }
 
-func (c *nativeHelmChart) ExtractChart(chart string, version *semver.Version) (string, io.Closer, error) {
+func (c *nativeHelmChart) ExtractChart(chart string, version string) (string, io.Closer, error) {
 	err := c.ensureHelmChartRepoPath()
 	if err != nil {
 		return "", nil, err
@@ -158,13 +155,13 @@ func (c *nativeHelmChart) ExtractChart(chart string, version *semver.Version) (s
 			}
 
 			// 'helm chart pull' ensures that chart is downloaded into local repository cache
-			_, err = helmCmd.ChartPull(c.repoURL, chart, version.String())
+			_, err = helmCmd.ChartPull(c.repoURL, chart, version)
 			if err != nil {
 				return "", nil, err
 			}
 
 			// 'helm chart export' copies cached chart into temp directory
-			_, err = helmCmd.ChartExport(c.repoURL, chart, version.String(), tempDest)
+			_, err = helmCmd.ChartExport(c.repoURL, chart, version, tempDest)
 			if err != nil {
 				return "", nil, err
 			}
@@ -177,7 +174,7 @@ func (c *nativeHelmChart) ExtractChart(chart string, version *semver.Version) (s
 				return "", nil, err
 			}
 		} else {
-			_, err = helmCmd.Fetch(c.repoURL, chart, version.String(), tempDest, c.creds)
+			_, err = helmCmd.Fetch(c.repoURL, chart, version, tempDest, c.creds)
 			if err != nil {
 				return "", nil, err
 			}
@@ -352,11 +349,16 @@ func normalizeChartName(chart string) string {
 	return nc
 }
 
-func (c *nativeHelmChart) getCachedChartPath(chart string, version *semver.Version) string {
-	return path.Join(c.repoPath, fmt.Sprintf("%s-%v.tgz", strings.ReplaceAll(chart, "/", "_"), version))
+func (c *nativeHelmChart) getCachedChartPath(chart string, version string) string {
+	return path.Join(c.repoPath, fmt.Sprintf("%s-%s.tgz", strings.ReplaceAll(chart, "/", "_"), version))
 }
 
-// Only OCI registries support storing charts under sub-directories.
-func IsHelmOciChart(chart string) bool {
-	return strings.Contains(chart, "/")
+// Ensures that given OCI registries URL does not have protocol
+func IsHelmOciRepo(repoURL string) bool {
+	if repoURL == "" {
+		return false
+	}
+	parsed, err := url.Parse(repoURL)
+	// the URL parser treat hostname as either path or opaque if scheme is not specified, so hostname must be empty
+	return err == nil && parsed.Host == ""
 }
diff --git a/util/helm/helm.go b/util/helm/helm.go
index e688c1ba8..47a768efc 100644
--- a/util/helm/helm.go
+++ b/util/helm/helm.go
@@ -17,8 +17,9 @@ import (
 
 type HelmRepository struct {
 	Creds
-	Name string
-	Repo string
+	Name      string
+	Repo      string
+	EnableOci bool
 }
 
 // Helm provides wrapper functionality around the `helm` command.
@@ -67,10 +68,26 @@ func (h *helm) Template(templateOpts *TemplateOpts) (string, error) {
 
 func (h *helm) DependencyBuild() error {
 	for _, repo := range h.repos {
-		_, err := h.cmd.RepoAdd(repo.Name, repo.Repo, repo.Creds)
+		if repo.EnableOci {
+			h.cmd.IsHelmOci = true
+			_, err := h.cmd.Login(repo.Repo, repo.Creds)
+			h.cmd.IsHelmOci = false
+
+			defer func() {
+				h.cmd.IsHelmOci = true
+				_, _ = h.cmd.Logout(repo.Repo, repo.Creds)
+				h.cmd.IsHelmOci = false
+			}()
+
+			if err != nil {
+				return err
+			}
+		} else {
+			_, err := h.cmd.RepoAdd(repo.Name, repo.Repo, repo.Creds)
 
-		if err != nil {
-			return err
+			if err != nil {
+				return err
+			}
 		}
 	}
 	h.repos = nil
diff --git a/util/helm/mocks/Client.go b/util/helm/mocks/Client.go
index db7a6a5b5..3eefcc771 100644
--- a/util/helm/mocks/Client.go
+++ b/util/helm/mocks/Client.go
@@ -7,8 +7,6 @@ import (
 	io "github.com/argoproj/argo-cd/util/io"
 
 	mock "github.com/stretchr/testify/mock"
-
-	semver "github.com/Masterminds/semver"
 )
 
 // Client is an autogenerated mock type for the Client type
@@ -17,11 +15,11 @@ type Client struct {
 }
 
 // CleanChartCache provides a mock function with given fields: chart, version
-func (_m *Client) CleanChartCache(chart string, version *semver.Version) error {
+func (_m *Client) CleanChartCache(chart string, version string) error {
 	ret := _m.Called(chart, version)
 
 	var r0 error
-	if rf, ok := ret.Get(0).(func(string, *semver.Version) error); ok {
+	if rf, ok := ret.Get(0).(func(string, string) error); ok {
 		r0 = rf(chart, version)
 	} else {
 		r0 = ret.Error(0)
@@ -31,18 +29,18 @@ func (_m *Client) CleanChartCache(chart string, version *semver.Version) error {
 }
 
 // ExtractChart provides a mock function with given fields: chart, version
-func (_m *Client) ExtractChart(chart string, version *semver.Version) (string, io.Closer, error) {
+func (_m *Client) ExtractChart(chart string, version string) (string, io.Closer, error) {
 	ret := _m.Called(chart, version)
 
 	var r0 string
-	if rf, ok := ret.Get(0).(func(string, *semver.Version) string); ok {
+	if rf, ok := ret.Get(0).(func(string, string) string); ok {
 		r0 = rf(chart, version)
 	} else {
 		r0 = ret.Get(0).(string)
 	}
 
 	var r1 io.Closer
-	if rf, ok := ret.Get(1).(func(string, *semver.Version) io.Closer); ok {
+	if rf, ok := ret.Get(1).(func(string, string) io.Closer); ok {
 		r1 = rf(chart, version)
 	} else {
 		if ret.Get(1) != nil {
@@ -51,7 +49,7 @@ func (_m *Client) ExtractChart(chart string, version *semver.Version) (string, i
 	}
 
 	var r2 error
-	if rf, ok := ret.Get(2).(func(string, *semver.Version) error); ok {
+	if rf, ok := ret.Get(2).(func(string, string) error); ok {
 		r2 = rf(chart, version)
 	} else {
 		r2 = ret.Error(2)


Test patch:
diff --git a/cmd/util/app_test.go b/cmd/util/app_test.go
index 90e514b64..eadc85f5c 100644
--- a/cmd/util/app_test.go
+++ b/cmd/util/app_test.go
@@ -165,10 +165,10 @@ func Test_setAppSpecOptions(t *testing.T) {
 		assert.Nil(t, f.spec.SyncPolicy)
 	})
 	t.Run("RetryLimit", func(t *testing.T) {
-		assert.NoError(t, f.SetFlag("retry-limit", "5"))
+		assert.NoError(t, f.SetFlag("sync-retry-limit", "5"))
 		assert.True(t, f.spec.SyncPolicy.Retry.Limit == 5)
 
-		assert.NoError(t, f.SetFlag("retry-limit", "0"))
-		assert.Nil(t, f.spec.SyncPolicy)
+		assert.NoError(t, f.SetFlag("sync-retry-limit", "0"))
+		assert.Nil(t, f.spec.SyncPolicy.Retry)
 	})
 }
diff --git a/reposerver/repository/repository_test.go b/reposerver/repository/repository_test.go
index dcda8c189..a55a70085 100644
--- a/reposerver/repository/repository_test.go
+++ b/reposerver/repository/repository_test.go
@@ -14,7 +14,6 @@ import (
 	"testing"
 	"time"
 
-	"github.com/Masterminds/semver"
 	"github.com/ghodss/yaml"
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/mock"
@@ -64,10 +63,6 @@ func newServiceWithMocks(root string, signed bool) (*Service, *gitmocks.Client)
 }
 
 func newServiceWithOpt(cf clientFunc) (*Service, *gitmocks.Client) {
-	// root, err := filepath.Abs(root)
-	// if err != nil {
-	// 	panic(err)
-	// }
 	helmClient := &helmmocks.Client{}
 	gitClient := &gitmocks.Client{}
 	cf(gitClient)
@@ -77,9 +72,9 @@ func newServiceWithOpt(cf clientFunc) (*Service, *gitmocks.Client) {
 	), RepoServerInitConstants{ParallelismLimit: 1})
 
 	chart := "my-chart"
-	version := semver.MustParse("1.1.0")
+	version := "1.1.0"
 	helmClient.On("GetIndex", true).Return(&helm.Index{Entries: map[string]helm.Entries{
-		chart: {{Version: "1.0.0"}, {Version: version.String()}},
+		chart: {{Version: "1.0.0"}, {Version: version}},
 	}}, nil)
 	helmClient.On("ExtractChart", chart, version).Return("./testdata/my-chart", io.NopCloser, nil)
 	helmClient.On("CleanChartCache", chart, version).Return(nil)
@@ -353,11 +348,11 @@ func TestManifestGenErrorCacheByNumRequests(t *testing.T) {
 
 				if adjustedInvocation < service.initConstants.PauseGenerationAfterFailedGenerationAttempts {
 					// GenerateManifest should not return cached errors for the first X responses, where X is the FailGenAttempts constants
-					assert.True(t, !isCachedError)
+					require.False(t, isCachedError)
 
-					assert.True(t, cachedManifestResponse != nil)
+					require.NotNil(t, cachedManifestResponse)
 					// nolint:staticcheck
-					assert.True(t, cachedManifestResponse.ManifestResponse == nil)
+					assert.Nil(t, cachedManifestResponse.ManifestResponse)
 					// nolint:staticcheck
 					assert.True(t, cachedManifestResponse.FirstFailureTimestamp != 0)
 
@@ -371,9 +366,9 @@ func TestManifestGenErrorCacheByNumRequests(t *testing.T) {
 					// GenerateManifest SHOULD return cached errors for the next X responses, where X is the
 					// PauseGenerationOnFailureForRequests constant
 					assert.True(t, isCachedError)
-					assert.True(t, cachedManifestResponse != nil)
+					require.NotNil(t, cachedManifestResponse)
 					// nolint:staticcheck
-					assert.True(t, cachedManifestResponse.ManifestResponse == nil)
+					assert.Nil(t, cachedManifestResponse.ManifestResponse)
 					// nolint:staticcheck
 					assert.True(t, cachedManifestResponse.FirstFailureTimestamp != 0)
 
diff --git a/test/container/Dockerfile b/test/container/Dockerfile
index d83f86099..3253808a4 100644
--- a/test/container/Dockerfile
+++ b/test/container/Dockerfile
@@ -7,7 +7,7 @@ FROM golang:1.16.0 as golang
 FROM ubuntu:20.10
 
 ENV DEBIAN_FRONTEND=noninteractive
-RUN  apt-get update && apt-get install -y \
+RUN  apt-get update && apt-get install --fix-missing -y \
         ca-certificates \
         curl \
         openssh-server \
diff --git a/util/argo/argo_test.go b/util/argo/argo_test.go
index c7d6b13cf..880616338 100644
--- a/util/argo/argo_test.go
+++ b/util/argo/argo_test.go
@@ -151,7 +151,7 @@ func TestValidatePermissionsEmptyDestination(t *testing.T) {
 
 func TestValidateChartWithoutRevision(t *testing.T) {
 	conditions, err := ValidatePermissions(context.Background(), &argoappv1.ApplicationSpec{
-		Source: argoappv1.ApplicationSource{RepoURL: "https://kubernetes-charts-incubator.storage.googleapis.com/", Chart: "myChart", TargetRevision: ""},
+		Source: argoappv1.ApplicationSource{RepoURL: "https://charts.helm.sh/incubator/", Chart: "myChart", TargetRevision: ""},
 		Destination: argoappv1.ApplicationDestination{
 			Server: "https://kubernetes.default.svc", Namespace: "default",
 		},
@@ -743,3 +743,9 @@ func TestFilterByName(t *testing.T) {
 		assert.Len(t, res, 0)
 	})
 }
+
+func TestTestRepoOCI(t *testing.T) {
+	err := TestRepo(&argoappv1.Repository{Repo: "https://demo.goharbor.io", Type: "helm", EnableOCI: true})
+	assert.Error(t, err)
+	assert.Equal(t, "OCI Helm repository URL should include hostname and port only", err.Error())
+}
diff --git a/util/helm/client_test.go b/util/helm/client_test.go
index 9d869667a..7ac853422 100644
--- a/util/helm/client_test.go
+++ b/util/helm/client_test.go
@@ -5,7 +5,6 @@ import (
 	"testing"
 	"time"
 
-	"github.com/Masterminds/semver"
 	"github.com/stretchr/testify/assert"
 
 	"github.com/argoproj/argo-cd/util/io"
@@ -50,7 +49,7 @@ func TestIndex(t *testing.T) {
 
 func Test_nativeHelmChart_ExtractChart(t *testing.T) {
 	client := NewClient("https://argoproj.github.io/argo-helm", Creds{}, false)
-	path, closer, err := client.ExtractChart("argo-cd", semver.MustParse("0.7.1"))
+	path, closer, err := client.ExtractChart("argo-cd", "0.7.1")
 	assert.NoError(t, err)
 	defer io.Close(closer)
 	info, err := os.Stat(path)
@@ -88,3 +87,10 @@ func Test_normalizeChartName(t *testing.T) {
 		assert.Equal(t, n, "myorg/..")
 	})
 }
+
+func TestIsHelmOciRepo(t *testing.T) {
+	assert.True(t, IsHelmOciRepo("demo.goharbor.io"))
+	assert.True(t, IsHelmOciRepo("demo.goharbor.io:8080"))
+	assert.False(t, IsHelmOciRepo("https://demo.goharbor.io"))
+	assert.False(t, IsHelmOciRepo("https://demo.goharbor.io:8080"))
+}