Repository: kubevela/kubevela

Issue:
In multicluster addon does not gets applied to newly added clusters
**Describe the bug**
<!--
A clear and concise description of what the bug is.
-->
We’ve observed that when a new cluster is added, any existing addon enabled via an application is not automatically applied to the new cluster during application reconciliation.  We believe this is a bug. If an application has a topology policy set to apply across all clusters, it should ensure that the addon is also applied to any newly added clusters.
**To Reproduce**
1. Enable the addon.
`vela addon enable fluxcd`
2. Join a new cluster.
`vela cluster join ~/.kube/slave1.yaml`

Observe that addon does not get enabled in newly joined cluster.
<!--
Steps to reproduce the behavior:
1. The YAML files of Component/Trait I used.
2. The YAML file of Application I applied.
3. Other operations I have done.
4. See error
-->

**Expected behavior**
<!--
A clear and concise description of what you expected to happen.
-->
Addon should get enabled in newly joined cluster as the application has topology policy set to be deployed on all clusters.
**Screenshots**
<!--
If applicable, add screenshots to help explain your problem.
-->

**KubeVela Version**

<!--
Describe your KubeVela controller or CLI version information.
-->

**Cluster information**
<!--
Describe your kubernetes cluster information.
- Kubernetes Version [e.g. 1.16.9]
-->
CLI Version: 1.10.1
Core Version: 1.10.2
GitRevision: git-711c9f00
GolangVersion: go1.22.11
**Additional context**
<!--
Add any other context about the problem here.
-->


Discussion:

Solution patch:
diff --git a/.github/workflows/core-api-test.yml b/.github/workflows/core-api-test.yml
index 5f6371a6..0df90aa5 100644
--- a/.github/workflows/core-api-test.yml
+++ b/.github/workflows/core-api-test.yml
@@ -16,10 +16,10 @@ jobs:
   core-api-test:
     runs-on: ubuntu-22.04
     steps:
-      - name: Set up Go 1.22
-        uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491
+      - name: Set up Go 1.23.8
+        uses: actions/setup-go@v5
         env:
-          GO_VERSION: '1.22'
+          GO_VERSION: '1.23.8'
         with:
           go-version: ${{ env.GO_VERSION }}
         id: go
diff --git a/.github/workflows/definition-lint.yml b/.github/workflows/definition-lint.yml
index 3616c00c..f8e46a34 100644
--- a/.github/workflows/definition-lint.yml
+++ b/.github/workflows/definition-lint.yml
@@ -16,7 +16,7 @@ permissions:
 
 env:
   # Common versions
-  GO_VERSION: '1.22'
+  GO_VERSION: '1.23.8'
 
 jobs:
   definition-doc:
diff --git a/.github/workflows/e2e-multicluster-test.yml b/.github/workflows/e2e-multicluster-test.yml
index 42058fed..611536d6 100644
--- a/.github/workflows/e2e-multicluster-test.yml
+++ b/.github/workflows/e2e-multicluster-test.yml
@@ -18,7 +18,7 @@ permissions:
 
 env:
   # Common versions
-  GO_VERSION: '1.22'
+  GO_VERSION: '1.23.8'
 
 jobs:
 
diff --git a/.github/workflows/e2e-test.yml b/.github/workflows/e2e-test.yml
index a10a42d0..6d62fed3 100644
--- a/.github/workflows/e2e-test.yml
+++ b/.github/workflows/e2e-test.yml
@@ -18,7 +18,7 @@ permissions:
 
 env:
   # Common versions
-  GO_VERSION: '1.22'
+  GO_VERSION: '1.23.8'
 
 jobs:
 
diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml
index a8158ad2..8495f6ea 100644
--- a/.github/workflows/go.yml
+++ b/.github/workflows/go.yml
@@ -16,8 +16,8 @@ permissions: # added using https://github.com/step-security/secure-workflows
 
 env:
   # Common versions
-  GO_VERSION: "1.22"
-  GOLANGCI_VERSION: "v1.54.2"
+  GO_VERSION: "1.23.8"
+  GOLANGCI_VERSION: "v1.60.1"
 
 jobs:
   detect-noop:
@@ -82,7 +82,7 @@ jobs:
       # version, but we prefer this action because it leaves 'annotations' (i.e.
       # it comments on PRs to point out linter violations).
       - name: Lint
-        uses: golangci/golangci-lint-action@2226d7cb06a077cd73e56eedd38eecad18e5d837 # v6.5.0
+        uses: golangci/golangci-lint-action@v6
         with:
           version: ${{ env.GOLANGCI_VERSION }}
 
@@ -200,4 +200,4 @@ jobs:
         uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4 # v6.15.0
         with:
           context: .
-          file: Dockerfile.cli
+          file: Dockerfile.cli
\ No newline at end of file
diff --git a/.github/workflows/issue-commands.yml b/.github/workflows/issue-commands.yml
index cdc73ca7..e6324965 100644
--- a/.github/workflows/issue-commands.yml
+++ b/.github/workflows/issue-commands.yml
@@ -25,15 +25,15 @@ jobs:
       - name: Setup Node.js
         uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b
         with:
-          node-version: '14'
-          cache: 'npm'
+          node-version: "14"
+          cache: "npm"
           cache-dependency-path: ./actions/package-lock.json
       - name: Install Dependencies
         run: npm ci --production --prefix ./actions
       - name: Run Commands
         uses: ./actions/commands
         with:
-          token: ${{ secrets.GITHUB_TOKEN }}
+          token: ${{ secrets.GH_KUBEVELA_COMMAND_WORKFLOW }}
           configPath: issue-commands
 
   backport:
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 874320e8..1420c0d5 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -37,7 +37,7 @@ jobs:
       - name: Set up Go
         uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491
         with:
-          go-version: 1.22
+          go-version: 1.23.8
           cache: true
 
       - name: Install Cosign
diff --git a/.github/workflows/sdk-test.yml b/.github/workflows/sdk-test.yml
index 868219e0..64ef7986 100644
--- a/.github/workflows/sdk-test.yml
+++ b/.github/workflows/sdk-test.yml
@@ -18,8 +18,8 @@ permissions:
 
 env:
   # Common versions
-  GO_VERSION: '1.22'
-  GOLANGCI_VERSION: 'v1.54.2'
+  GO_VERSION: '1.23.8'
+  GOLANGCI_VERSION: 'v1.60.1'
 
 jobs:
   sdk-tests:
diff --git a/.github/workflows/sync-api.yml b/.github/workflows/sync-api.yml
index 7a86f851..359d92e4 100644
--- a/.github/workflows/sync-api.yml
+++ b/.github/workflows/sync-api.yml
@@ -11,7 +11,7 @@ permissions:
   contents: read
 
 env:
-  GO_VERSION: '1.22'
+  GO_VERSION: '1.23.8'
 
 jobs:
   sync-core-api:
diff --git a/.github/workflows/sync-sdk.yaml b/.github/workflows/sync-sdk.yaml
index 1afe8151..ef21596a 100644
--- a/.github/workflows/sync-sdk.yaml
+++ b/.github/workflows/sync-sdk.yaml
@@ -15,7 +15,7 @@ permissions:
   contents: read
 
 env:
-  GO_VERSION: '1.22'
+  GO_VERSION: '1.23.8'
 
 jobs:
   sync_sdk:
diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml
index 93c27038..837e1503 100644
--- a/.github/workflows/unit-test.yml
+++ b/.github/workflows/unit-test.yml
@@ -16,7 +16,7 @@ permissions:
 
 env:
   # Common versions
-  GO_VERSION: "1.22"
+  GO_VERSION: "1.23.8"
 
 jobs:
   detect-noop:
diff --git a/.golangci.yml b/.golangci.yml
index 9d29ee1a..3b889f2b 100644
--- a/.golangci.yml
+++ b/.golangci.yml
@@ -1,18 +1,6 @@
 run:
   timeout: 10m
 
-  skip-files:
-    - "zz_generated\\..+\\.go$"
-    - ".*_test.go$"
-
-  skip-dirs:
-    - "hack"
-    - "e2e"
-
-output:
-  # colored-line-number|line-number|json|tab|checkstyle|code-climate, default is "colored-line-number"
-  format: colored-line-number
-
 linters-settings:
   errcheck:
     # report about not checking of errors in type assetions: `a := b.(MyStruct)`;
@@ -23,24 +11,12 @@ linters-settings:
     # default is false: such cases aren't reported by default.
     check-blank: false
 
-    # [deprecated] comma-separated list of pairs of the form pkg:regex
-    # the regex is used to ignore names within pkg. (default "fmt:.*").
-    # see https://github.com/kisielk/errcheck#the-deprecated-method for details
-    ignore: fmt:.*,io/ioutil:^Read.*
-
   exhaustive:
     # indicates that switch statements are to be considered exhaustive if a
     # 'default' case is present, even if all enum members aren't listed in the
     # switch
     default-signifies-exhaustive: true
 
-  govet:
-    # report about shadowed variables
-    check-shadowing: false
-
-  revive:
-    # minimal confidence for issues, default is 0.8
-    min-confidence: 0.8
 
   gofmt:
     # simplify code: gofmt with `-s` option, true by default
@@ -55,9 +31,6 @@ linters-settings:
     # minimal code complexity to report, 30 by default (but we recommend 10-20)
     min-complexity: 30
 
-  maligned:
-    # print struct with more effective memory layout or not, false by default
-    suggest-new: true
 
   dupl:
     # tokens count to trigger issue, 150 by default
@@ -73,13 +46,6 @@ linters-settings:
     # tab width in spaces. Default to 1.
     tab-width: 1
 
-  unused:
-    # treat code as a program (not a library) and report unused exported identifiers; default is false.
-    # XXX: if you enable this setting, unused will report a lot of false-positives in text editors:
-    # if it's called for subdir of a project it can't find funcs usages. All text editor integrations
-    # with golangci-lint call it on a directory with the changed file.
-    check-exported: false
-
   unparam:
     # Inspect exported functions, default is false. Set to true if no external program/library imports your code.
     # XXX: if you enable this setting, unparam will report a lot of false-positives in text editors:
@@ -107,9 +73,13 @@ linters-settings:
     # Allow only slices initialized with a length of zero. Default is false.
     always: false
 
+  revive:
+    rules:
+      - name: unused-parameter
+        disabled: true
+
 linters:
   enable:
-    - megacheck
     - govet
     - gocyclo
     - gocritic
@@ -121,11 +91,10 @@ linters:
     - misspell
     - nakedret
     - exportloopref
+    - unused
+    - gosimple
+    - staticcheck
   disable:
-    - deadcode
-    - scopelint
-    - structcheck
-    - varcheck
     - rowserrcheck
     - sqlclosecheck
     - errchkjson
@@ -137,8 +106,28 @@ linters:
 
 
 issues:
+
+  exclude-files:
+    - "zz_generated\\..+\\.go$"
+    - ".*_test.go$"
+
+  exclude-dirs:
+    - "hack"
+    - "e2e"
+
   # Excluding configuration per-path and per-linter
   exclude-rules:
+    - path: .*\.go
+      linters:
+        - errcheck
+      text: "fmt\\."
+
+    # Ignore unchecked errors from io/ioutil functions starting with Read
+    - path: .*\.go
+      linters:
+        - errcheck
+      text: "io/ioutil.*Read"
+      
     # Exclude some linters from running on tests files.
     - path: _test(ing)?\.go
       linters:
@@ -227,7 +216,7 @@ issues:
   new: false
 
   # Maximum issues count per one linter. Set to 0 to disable. Default is 50.
-  max-per-linter: 0
+  max-issues-per-linter: 0
 
   # Maximum count of issues with the same text. Set to 0 to disable. Default is 3.
-  max-same-issues: 0
+  max-same-issues: 0
\ No newline at end of file
diff --git a/Dockerfile b/Dockerfile
index af89b1a4..7a1ebbbf 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,6 +1,6 @@
 ARG BASE_IMAGE
 # Build the manager binary
-FROM golang:1.22-alpine3.18 as builder
+FROM golang:1.23.8-alpine@sha256:b7486658b87d34ecf95125e5b97e8dfe86c21f712aa36fc0c702e5dc41dc63e1 AS builder
 
 WORKDIR /workspace
 # Copy the Go Modules manifests
diff --git a/Dockerfile.cli b/Dockerfile.cli
index 0c5929ce..17a55a52 100644
--- a/Dockerfile.cli
+++ b/Dockerfile.cli
@@ -1,6 +1,6 @@
 ARG BASE_IMAGE
 # Build the cli binary
-FROM --platform=${BUILDPLATFORM:-linux/amd64} golang:1.22-alpine@sha256:d1a601b64de09e2fa38c95e55838961811d5ca11062a8f4230a5c434b3ae2a34 as builder
+FROM --platform=${BUILDPLATFORM:-linux/amd64} golang:1.23.8-alpine@sha256:b7486658b87d34ecf95125e5b97e8dfe86c21f712aa36fc0c702e5dc41dc63e1 AS builder
 ARG GOPROXY
 ENV GOPROXY=${GOPROXY:-https://proxy.golang.org}
 WORKDIR /workspace
diff --git a/Dockerfile.e2e b/Dockerfile.e2e
index 65d1682f..30ebab0c 100644
--- a/Dockerfile.e2e
+++ b/Dockerfile.e2e
@@ -1,6 +1,6 @@
 ARG BASE_IMAGE
 # Build the manager binary
-FROM --platform=${BUILDPLATFORM:-linux/amd64} golang:1.22-alpine@sha256:d1a601b64de09e2fa38c95e55838961811d5ca11062a8f4230a5c434b3ae2a34 as builder
+FROM --platform=${BUILDPLATFORM:-linux/amd64} golang:1.23.8-alpine@sha256:b7486658b87d34ecf95125e5b97e8dfe86c21f712aa36fc0c702e5dc41dc63e1 AS builder
 
 WORKDIR /workspace
 # Copy the Go Modules manifests
diff --git a/Makefile b/Makefile
index 9edd0be0..93545f9a 100644
--- a/Makefile
+++ b/Makefile
@@ -61,7 +61,7 @@ staticcheck: staticchecktool
 ## lint: Run the golangci-lint
 lint: golangci
 	@$(INFO) lint
-	@$(GOLANGCILINT) run --fix --verbose --skip-dirs 'scaffold'
+	@$(GOLANGCILINT) run --fix --verbose --exclude-dirs 'scaffold'
 
 ## reviewable: Run the reviewable
 reviewable: manifests fmt vet lint staticcheck helm-doc-gen sdk_fmt
diff --git a/charts/vela-core/templates/admission-webhooks/job-patch/job-createSecret.yaml b/charts/vela-core/templates/admission-webhooks/job-patch/job-createSecret.yaml
index f3eeef97..dd02a14a 100644
--- a/charts/vela-core/templates/admission-webhooks/job-patch/job-createSecret.yaml
+++ b/charts/vela-core/templates/admission-webhooks/job-patch/job-createSecret.yaml
@@ -2,7 +2,7 @@
 apiVersion: batch/v1
 kind: Job
 metadata:
-  name:  {{ template "kubevela.fullname" . }}-admission-create
+  name: {{ template "kubevela.fullname" . }}-admission-create
   namespace: {{ .Release.Namespace }}
   annotations:
     "helm.sh/hook": pre-install,pre-upgrade
@@ -17,7 +17,7 @@ spec:
   {{- end }}
   template:
     metadata:
-      name:  {{ template "kubevela.fullname" . }}-admission-create
+      name: {{ template "kubevela.fullname" . }}-admission-create
       labels:
         app: {{ template "kubevela.name" . }}-admission-create
         {{- include "kubevela.labels" . | nindent 8 }}
@@ -39,17 +39,26 @@ spec:
             - --cert-name=tls.crt
       restartPolicy: OnFailure
       serviceAccountName: {{ template "kubevela.fullname" . }}-admission
-      {{- with .Values.admissionWebhooks.patch.nodeSelector }}
+      {{- if .Values.admissionWebhooks.patch.nodeSelector }}
       nodeSelector:
-      {{- toYaml . | nindent 8 }}
+      {{- toYaml .Values.admissionWebhooks.patch.nodeSelector | nindent 8 }}
+      {{- else if .Values.nodeSelector }}
+      nodeSelector:
+      {{- toYaml .Values.nodeSelector | nindent 8 }}
       {{- end }}
-      {{- with .Values.admissionWebhooks.patch.affinity }}
+      {{- if .Values.admissionWebhooks.patch.affinity }}
       affinity:
-{{ toYaml . | indent 8 }}
+      {{- toYaml .Values.admissionWebhooks.patch.affinity | nindent 8 }}
+      {{- else if .Values.affinity }}
+      affinity:
+      {{- toYaml .Values.affinity | nindent 8 }}
       {{- end }}
-      {{- with .Values.admissionWebhooks.patch.tolerations }}
+      {{- if .Values.admissionWebhooks.patch.tolerations }}
+      tolerations:
+      {{- toYaml .Values.admissionWebhooks.patch.tolerations | nindent 8 }}
+      {{- else if .Values.tolerations }}
       tolerations:
-{{ toYaml . | indent 8 }}
+      {{- toYaml .Values.tolerations | nindent 8 }}
       {{- end }}
       securityContext:
         runAsGroup: 2000
diff --git a/charts/vela-core/templates/admission-webhooks/job-patch/job-patchWebhook.yaml b/charts/vela-core/templates/admission-webhooks/job-patch/job-patchWebhook.yaml
index 7b8b60aa..eb2e9847 100644
--- a/charts/vela-core/templates/admission-webhooks/job-patch/job-patchWebhook.yaml
+++ b/charts/vela-core/templates/admission-webhooks/job-patch/job-patchWebhook.yaml
@@ -2,7 +2,7 @@
 apiVersion: batch/v1
 kind: Job
 metadata:
-  name:  {{ template "kubevela.fullname" . }}-admission-patch
+  name: {{ template "kubevela.fullname" . }}-admission-patch
   namespace: {{ .Release.Namespace }}
   annotations:
     "helm.sh/hook": post-install,post-upgrade
@@ -17,7 +17,7 @@ spec:
   {{- end }}
   template:
     metadata:
-      name:  {{ template "kubevela.fullname" . }}-admission-patch
+      name: {{ template "kubevela.fullname" . }}-admission-patch
       labels:
         app: {{ template "kubevela.name" . }}-admission-patch
         {{- include "kubevela.labels" . | nindent 8 }}
@@ -41,13 +41,26 @@ spec:
             {{- end }}
       restartPolicy: OnFailure
       serviceAccountName: {{ template "kubevela.fullname" . }}-admission
-      {{- with .Values.admissionWebhooks.patch.affinity }}
+      {{- if .Values.admissionWebhooks.patch.nodeSelector }}
+      nodeSelector:
+      {{- toYaml .Values.admissionWebhooks.patch.nodeSelector | nindent 8 }}
+      {{- else if .Values.nodeSelector }}
+      nodeSelector:
+      {{- toYaml .Values.nodeSelector | nindent 8 }}
+      {{- end }}
+      {{- if .Values.admissionWebhooks.patch.affinity }}
+      affinity:
+      {{- toYaml .Values.admissionWebhooks.patch.affinity | nindent 8 }}
+      {{- else if .Values.affinity }}
       affinity:
-{{ toYaml . | indent 8 }}
+      {{- toYaml .Values.affinity | nindent 8 }}
       {{- end }}
-      {{- with .Values.admissionWebhooks.patch.tolerations }}
+      {{- if .Values.admissionWebhooks.patch.tolerations }}
+      tolerations:
+      {{- toYaml .Values.admissionWebhooks.patch.tolerations | nindent 8 }}
+      {{- else if .Values.tolerations }}
       tolerations:
-{{ toYaml . | indent 8 }}
+      {{- toYaml .Values.tolerations | nindent 8 }}
       {{- end }}
       securityContext:
         runAsGroup: 2000
diff --git a/charts/vela-core/templates/cluster-gateway/cluster-gateway.yaml b/charts/vela-core/templates/cluster-gateway/cluster-gateway.yaml
index c02d85ec..99d2cc32 100644
--- a/charts/vela-core/templates/cluster-gateway/cluster-gateway.yaml
+++ b/charts/vela-core/templates/cluster-gateway/cluster-gateway.yaml
@@ -190,4 +190,4 @@ subjects:
   - kind: ServiceAccount
     name: {{ include "kubevela.serviceAccountName" . }}
     namespace: {{ .Release.Namespace }}
-{{ end }}
\ No newline at end of file
+{{ end }}
diff --git a/charts/vela-core/templates/cluster-gateway/job-patch.yaml b/charts/vela-core/templates/cluster-gateway/job-patch.yaml
index 23956465..f2190a6a 100644
--- a/charts/vela-core/templates/cluster-gateway/job-patch.yaml
+++ b/charts/vela-core/templates/cluster-gateway/job-patch.yaml
@@ -95,6 +95,18 @@ spec:
         runAsGroup: 2000
         runAsNonRoot: true
         runAsUser: 2000
+      {{- with .Values.nodeSelector }}
+      nodeSelector:
+        {{- toYaml . | nindent 8 }}
+      {{- end }}
+      {{- with .Values.affinity }}
+      affinity:
+        {{- toYaml . | nindent 8 }}
+      {{- end }}
+      {{- with .Values.tolerations }}
+      tolerations:
+        {{- toYaml . | nindent 8 }}
+      {{- end }}
 ---
 apiVersion: batch/v1
 kind: Job
@@ -138,4 +150,16 @@ spec:
         runAsGroup: 2000
         runAsNonRoot: true
         runAsUser: 2000
-{{ end }}
\ No newline at end of file
+      {{- with .Values.nodeSelector }}
+      nodeSelector:
+      {{- toYaml . | nindent 8 }}
+      {{- end }}
+      {{- with .Values.affinity }}
+      affinity:
+      {{- toYaml . | nindent 8 }}
+      {{- end }}
+      {{- with .Values.tolerations }}
+      tolerations:
+      {{- toYaml . | nindent 8 }}
+      {{- end }}
+{{ end }}
diff --git a/charts/vela-core/templates/defwithtemplate/podsecuritycontext.yaml b/charts/vela-core/templates/defwithtemplate/podsecuritycontext.yaml
index 7707a50c..23aaee5f 100644
--- a/charts/vela-core/templates/defwithtemplate/podsecuritycontext.yaml
+++ b/charts/vela-core/templates/defwithtemplate/podsecuritycontext.yaml
@@ -39,8 +39,9 @@ spec:
         parameter: {
         	// +usage=Specify the AppArmor profile for the pod
         	appArmorProfile?: {
-        		type:             "RuntimeDefault" | "Unconfined" | "Localhost"
-        		localhostProfile: string
+        		type: "RuntimeDefault" | "Unconfined" | "Localhost"
+        		// +usage:  localhostProfile is required when type is 'Localhost'
+        		localhostProfile?: string
         	}
         	fsGroup?:    int
         	runAsGroup?: int
@@ -50,8 +51,9 @@ spec:
         	runAsNonRoot: *true | bool
         	// +usage=Specify the seccomp profile for the pod
         	seccompProfile?: {
-        		type:             "RuntimeDefault" | "Unconfined" | "Localhost"
-        		localhostProfile: string
+        		type: "RuntimeDefault" | "Unconfined" | "Localhost"
+        		// +usage:  localhostProfile is required when type is 'Localhost'
+        		localhostProfile?: string
         	}
         }
 
diff --git a/go.mod b/go.mod
index 58a6b5a7..ce77426f 100644
--- a/go.mod
+++ b/go.mod
@@ -1,6 +1,6 @@
 module github.com/oam-dev/kubevela
 
-go 1.22.0
+go 1.23.8
 
 require (
 	cuelang.org/go v0.9.2
@@ -67,12 +67,12 @@ require (
 	github.com/xlab/treeprint v1.2.0
 	gitlab.com/gitlab-org/api/client-go v0.127.0
 	go.uber.org/multierr v1.11.0
-	golang.org/x/crypto v0.33.0
+	golang.org/x/crypto v0.37.0
 	golang.org/x/mod v0.19.0
-	golang.org/x/oauth2 v0.26.0
-	golang.org/x/sync v0.11.0
-	golang.org/x/term v0.29.0
-	golang.org/x/text v0.22.0
+	golang.org/x/oauth2 v0.29.0
+	golang.org/x/sync v0.13.0
+	golang.org/x/term v0.31.0
+	golang.org/x/text v0.24.0
 	golang.org/x/tools v0.23.0
 	gomodules.xyz/jsonpatch/v2 v2.4.0
 	gopkg.in/yaml.v3 v3.0.1
@@ -274,8 +274,8 @@ require (
 	go.uber.org/automaxprocs v1.5.3 // indirect
 	go.uber.org/zap v1.26.0 // indirect
 	golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect
-	golang.org/x/net v0.35.0 // indirect
-	golang.org/x/sys v0.30.0 // indirect
+	golang.org/x/net v0.39.0 // indirect
+	golang.org/x/sys v0.32.0 // indirect
 	golang.org/x/time v0.10.0 // indirect
 	google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect
 	google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de // indirect
diff --git a/go.sum b/go.sum
index 51c73f28..72f23621 100644
--- a/go.sum
+++ b/go.sum
@@ -1150,8 +1150,8 @@ golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0
 golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
 golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
 golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
-golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus=
-golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M=
+golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE=
+golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
@@ -1228,8 +1228,8 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
 golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
 golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
 golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
-golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8=
-golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk=
+golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY=
+golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -1241,8 +1241,8 @@ golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ
 golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
 golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
 golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
-golang.org/x/oauth2 v0.26.0 h1:afQXWNNaeC4nvZ0Ed9XvCCzXM6UHJG7iCg0W4fPqSBE=
-golang.org/x/oauth2 v0.26.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
+golang.org/x/oauth2 v0.29.0 h1:WdYw2tdTK1S8olAzWHdgeqfy+Mtm9XNhv/xJsY65d98=
+golang.org/x/oauth2 v0.29.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
 golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -1255,8 +1255,8 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJ
 golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
-golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
+golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610=
+golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
 golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -1328,8 +1328,8 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
-golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
+golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
 golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
@@ -1341,8 +1341,8 @@ golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
 golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
 golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
 golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
-golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU=
-golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s=
+golang.org/x/term v0.31.0 h1:erwDkOK1Msy6offm1mOgvspSkslFnIGsFnxOKoufg3o=
+golang.org/x/term v0.31.0/go.mod h1:R4BeIy7D95HzImkxGkTW1UQTtP54tio2RyHz7PwK0aw=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
@@ -1354,8 +1354,8 @@ golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
 golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
 golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
 golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
-golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
-golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
+golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
+golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
 golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
diff --git a/hack/docgen/cli/gen.go b/hack/docgen/cli/gen.go
index e8292675..2111073b 100644
--- a/hack/docgen/cli/gen.go
+++ b/hack/docgen/cli/gen.go
@@ -18,7 +18,6 @@ package main
 
 import (
 	"fmt"
-	"io"
 	"io/fs"
 	"log"
 	"os"
@@ -69,23 +68,23 @@ func GenMarkdownTreeForIndex(cmd *cobra.Command, dir string) error {
 	}
 	defer f.Close()
 
-	if _, err = io.WriteString(f, "---\ntitle: CLI Commands\n---\n\n\n"); err != nil {
+	if _, err = f.WriteString("---\ntitle: CLI Commands\n---\n\n\n"); err != nil {
 		return err
 	}
 	for _, tp := range []string{types.TypeStart, types.TypeApp, types.TypeCD, types.TypeExtension, types.TypeSystem} {
 		// write header of type
-		_, err = io.WriteString(f, "## "+tp+"\n\n")
+		_, err = f.WriteString("## " + tp + "\n\n")
 		if err != nil {
 			return err
 		}
 		str := PrintCLIByTag(cmd, cmd.Commands(), tp)
 		// write header of type
-		_, err = io.WriteString(f, str)
+		_, err = f.WriteString(str)
 		if err != nil {
 			return err
 		}
 	}
-	_, err = io.WriteString(f, "###### Auto generated by [script in KubeVela](https://github.com/kubevela/kubevela/tree/master/hack/docgen).")
+	_, err = f.WriteString("###### Auto generated by [script in KubeVela](https://github.com/kubevela/kubevela/tree/master/hack/docgen).")
 	if err != nil {
 		return err
 	}
diff --git a/makefiles/dependency.mk b/makefiles/dependency.mk
index 27ae97f0..f7c2d15c 100644
--- a/makefiles/dependency.mk
+++ b/makefiles/dependency.mk
@@ -1,7 +1,7 @@
 LOCALBIN ?= $(shell pwd)/bin
 $(LOCALBIN):
 	mkdir -p $(LOCALBIN)
-GOLANGCILINT_VERSION ?= 1.54.2
+GOLANGCILINT_VERSION ?= 1.60.1
 GLOBAL_GOLANGCILINT := $(shell which golangci-lint)
 GOBIN_GOLANGCILINT:= $(shell which $(GOBIN)/golangci-lint)
 ENVTEST_K8S_VERSION = 1.29.0
@@ -31,7 +31,7 @@ ifeq (, $(shell which staticcheck))
 	@{ \
 	set -e ;\
 	echo 'installing honnef.co/go/tools/cmd/staticcheck ' ;\
-	go install honnef.co/go/tools/cmd/staticcheck@v0.4.7 ;\
+	go install honnef.co/go/tools/cmd/staticcheck@v0.5.1 ;\
 	}
 STATICCHECK=$(GOBIN)/staticcheck
 else
diff --git a/pkg/addon/push.go b/pkg/addon/push.go
index 4c227d46..92f63115 100644
--- a/pkg/addon/push.go
+++ b/pkg/addon/push.go
@@ -158,7 +158,7 @@ func (p *PushCmd) Push(ctx context.Context) error {
 	}
 
 	_, _ = fmt.Fprintf(os.Stderr, "Pushing %s to %s... ",
-		color.New(color.Bold).Sprintf(filepath.Base(chartPackagePath)),
+		color.New(color.Bold).Sprintf("%s", filepath.Base(chartPackagePath)),
 		formatRepoNameAndURL(p.RepoName, repo.Config.URL),
 	)
 
@@ -294,7 +294,7 @@ func formatRepoNameAndURL(name, url string) string {
 	}
 
 	return fmt.Sprintf("%s(%s)",
-		color.New(color.Bold).Sprintf(name),
+		color.New(color.Bold).Sprintf("%s", name),
 		color.BlueString(url),
 	)
 }
diff --git a/pkg/cue/definition/template.go b/pkg/cue/definition/template.go
index 8cec8be4..d50a75e1 100644
--- a/pkg/cue/definition/template.go
+++ b/pkg/cue/definition/template.go
@@ -398,7 +398,7 @@ func parseErrors(errs cue.Value) error {
 	if it, e := errs.List(); e == nil {
 		for it.Next() {
 			if s, err := it.Value().String(); err == nil && s != "" {
-				return errors.Errorf(s)
+				return errors.Errorf("%s", s)
 			}
 		}
 	}
diff --git a/pkg/definition/gen_sdk/go.go b/pkg/definition/gen_sdk/go.go
index 8745e876..9b18c471 100644
--- a/pkg/definition/gen_sdk/go.go
+++ b/pkg/definition/gen_sdk/go.go
@@ -251,7 +251,7 @@ func (m *GoModuleModifier) addSubGoMod() error {
 			"--rm",
 			"-v", m.apiDir+":/api",
 			"-w", "/api",
-			"golang:1.22-alpine3.18",
+			"golang:1.23.8-alpine@sha256:b7486658b87d34ecf95125e5b97e8dfe86c21f712aa36fc0c702e5dc41dc63e1",
 			"go", "get", fmt.Sprintf("%s@%s", m.Package, m.LangArgs.Get(mainModuleVersionKey)),
 		))
 	}
@@ -261,7 +261,7 @@ func (m *GoModuleModifier) addSubGoMod() error {
 		"-v", m.apiDir+":/api",
 		"-w", "/api",
 		"--env", "GOPROXY="+m.LangArgs.Get(goProxyKey),
-		"golang:1.22-alpine3.18",
+		"golang:1.23.8-alpine@sha256:b7486658b87d34ecf95125e5b97e8dfe86c21f712aa36fc0c702e5dc41dc63e1",
 		"go", "mod", "tidy",
 	))
 	for _, cmd := range cmds {
@@ -293,7 +293,7 @@ func (m *GoModuleModifier) tidyMainMod() error {
 		"--rm",
 		"-v", outDir+":/api",
 		"-w", "/api",
-		"golang:1.22-alpine3.18",
+		"golang:1.23.8-alpine@sha256:b7486658b87d34ecf95125e5b97e8dfe86c21f712aa36fc0c702e5dc41dc63e1",
 		"go", "mod", "tidy",
 	)
 	if m.Verbose {
diff --git a/pkg/workflow/providers/legacy/query/handler.go b/pkg/workflow/providers/legacy/query/handler.go
index 06eff15b..3661dfee 100644
--- a/pkg/workflow/providers/legacy/query/handler.go
+++ b/pkg/workflow/providers/legacy/query/handler.go
@@ -297,7 +297,7 @@ func CollectLogsInPod(ctx context.Context, params *LogParams) (*LogResult, error
 		}
 	}
 	if errMsg != "" {
-		klog.Warningf(errMsg)
+		klog.Warningf("%s", errMsg)
 		defaultOutputs["err"] = errMsg
 	}
 	return &LogResult{Outputs: defaultOutputs}, nil
diff --git a/pkg/workflow/providers/query/handler.go b/pkg/workflow/providers/query/handler.go
index c728780e..521328a1 100644
--- a/pkg/workflow/providers/query/handler.go
+++ b/pkg/workflow/providers/query/handler.go
@@ -303,7 +303,7 @@ func CollectLogsInPod(ctx context.Context, params *LogParams) (*LogReturns, erro
 		}
 	}
 	if errMsg != "" {
-		klog.Warningf(errMsg)
+		klog.Warningf("%s", errMsg)
 		defaultOutputs["err"] = errMsg
 	}
 	return &LogReturns{Returns: LogReturnVars{Outputs: defaultOutputs}}, nil
diff --git a/references/cli/addon.go b/references/cli/addon.go
index ec8b14e5..9f5ebcf9 100644
--- a/references/cli/addon.go
+++ b/references/cli/addon.go
@@ -179,7 +179,7 @@ func NewAddonEnableCommand(c common.Args, ioStream cmdutil.IOStreams) *cobra.Com
 				if !file.IsDir() {
 					return fmt.Errorf("%s is not addon dir", addonOrDir)
 				}
-				ioStream.Infof(color.New(color.FgYellow).Sprintf("enabling addon by local dir: %s \n", addonOrDir))
+				ioStream.Infof("%s", color.New(color.FgYellow).Sprintf("enabling addon by local dir: %s \n", addonOrDir))
 				// args[0] is a local path install with local dir, use base dir name as addonName
 				abs, err := filepath.Abs(addonOrDir)
 				if err != nil {
@@ -300,7 +300,7 @@ non-empty new arg
 				if !file.IsDir() {
 					return fmt.Errorf("%s is not addon dir", addonOrDir)
 				}
-				ioStream.Infof(color.New(color.FgYellow).Sprintf("enabling addon by local dir: %s \n", addonOrDir))
+				ioStream.Infof("%s", color.New(color.FgYellow).Sprintf("enabling addon by local dir: %s \n", addonOrDir))
 				// args[0] is a local path install with local dir
 				abs, err := filepath.Abs(addonOrDir)
 				if err != nil {
diff --git a/references/cli/cluster.go b/references/cli/cluster.go
index 17db981c..b36e5e85 100644
--- a/references/cli/cluster.go
+++ b/references/cli/cluster.go
@@ -18,9 +18,11 @@ package cli
 
 import (
 	"context"
+	"encoding/json"
 	"fmt"
 	"sort"
 	"strings"
+	"time"
 
 	"github.com/crossplane/crossplane-runtime/pkg/meta"
 	"github.com/fatih/color"
@@ -37,9 +39,17 @@ import (
 	"k8s.io/utils/ptr"
 	"sigs.k8s.io/controller-runtime/pkg/client"
 
+	"github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha1"
+	"github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
+
+	apierrors "k8s.io/apimachinery/pkg/api/errors"
+	apitypes "k8s.io/apimachinery/pkg/types"
+
 	"github.com/oam-dev/kubevela/apis/types"
 	velacmd "github.com/oam-dev/kubevela/pkg/cmd"
 	"github.com/oam-dev/kubevela/pkg/multicluster"
+	"github.com/oam-dev/kubevela/pkg/oam"
+	"github.com/oam-dev/kubevela/pkg/oam/util"
 	"github.com/oam-dev/kubevela/pkg/utils/common"
 	cmdutil "github.com/oam-dev/kubevela/pkg/utils/util"
 )
@@ -213,11 +223,17 @@ func NewClusterJoinCommand(c *common.Args, ioStreams cmdutil.IOStreams) *cobra.C
 			if err != nil {
 				return err
 			}
-			cmd.Printf("Successfully add cluster %s, endpoint: %s.\n", clusterName, clusterConfig.Cluster.Server)
 
 			if len(labels) > 0 {
-				return addClusterLabels(cmd, c, clusterName, labels)
+				if err := addClusterLabels(cmd, c, clusterName, labels); err != nil {
+					return fmt.Errorf("error in adding cluster labels: %w", err)
+				}
+			}
+			if err := updateAppsWithTopologyPolicy(ctx, cmd, client); err != nil {
+				return fmt.Errorf("error in updating apps with topology policy: %w", err)
 			}
+
+			cmd.Printf("Successfully add cluster %s, endpoint: %s.\n", clusterName, clusterConfig.Cluster.Server)
 			return nil
 		},
 	}
@@ -232,6 +248,97 @@ func NewClusterJoinCommand(c *common.Args, ioStreams cmdutil.IOStreams) *cobra.C
 	return cmd
 }
 
+// updateAppsWithTopologyPolicy iterates through all Application resources in the cluster,
+// and updates those that have a cluster-level label selector defined in topology policy.
+// For each matching application, it sets or updates publish version annotation.
+func updateAppsWithTopologyPolicy(ctx context.Context, cmd *cobra.Command, k8sClient client.Client) error {
+	var continueToken string
+	const pageSize = 100 // Adjust based on performance needs
+	for {
+		// List every Application once, update only those with a cluster label selector.
+		applicationList := &v1beta1.ApplicationList{}
+		listOpts := &client.ListOptions{
+			Limit:    pageSize,
+			Continue: continueToken,
+		}
+		if err := k8sClient.List(ctx, applicationList, listOpts); err != nil {
+			return fmt.Errorf("failed to list applications: %w", err)
+		}
+
+		for i := range applicationList.Items { // index-based to avoid copies
+			app := &applicationList.Items[i]
+
+			matched, err := hasClusterLabelSelector(app.Spec.Policies)
+			if err != nil {
+				return fmt.Errorf("failed to check clusterlabelselector for application %s in namespace %s: %w", app.Name, app.Namespace, err)
+			}
+			if !matched {
+				continue
+			}
+
+			// Retry loop for conflict handling
+			const maxRetries = 5
+			for attempt := 0; attempt < maxRetries; attempt++ {
+				// Refresh the object to get the latest resourceVersion (only after 1st attempt)
+				if attempt > 0 {
+					key := apitypes.NamespacedName{Namespace: app.Namespace, Name: app.Name}
+					if err := k8sClient.Get(ctx, key, app); err != nil {
+						return fmt.Errorf("failed to refetch app %s in namespace %s: %w", app.Name, app.Namespace, err)
+					}
+				}
+
+				// Update logic
+				oam.SetPublishVersion(app, util.GenerateVersion("clusterjoin"))
+
+				if err := k8sClient.Update(ctx, app); err != nil {
+					if apierrors.IsConflict(err) {
+						// Retry if there's a conflict
+						if attempt == maxRetries-1 {
+							return fmt.Errorf("conflict error updating app %s in namespace %s after %d retries: %w", app.Name, app.Namespace, maxRetries, err)
+						}
+						cmd.Printf("Conflict updating app %s in namespace %s, retrying (%d/%d)...\n", app.Name, app.Namespace, attempt+1, maxRetries)
+						time.Sleep(500 * time.Millisecond)
+						continue
+					}
+					// Non-conflict error, return it
+					return fmt.Errorf("error updating app %s in namespace %s: %w", app.Name, app.Namespace, err)
+				}
+
+				if attempt > 0 {
+					cmd.Printf("Successfully updated app %s in namespace %s after %d retries.\n", app.Name, app.Namespace, attempt)
+				}
+				// Successful update
+				break
+			}
+		}
+		continueToken = applicationList.Continue
+		if continueToken == "" {
+			break // No more pages
+		}
+	}
+	return nil
+}
+
+// hasClusterLabelSelector returns true when at least one topology policy
+// has an explicit clusterLabelSelector.
+func hasClusterLabelSelector(policies []v1beta1.AppPolicy) (bool, error) {
+	for _, p := range policies {
+		if p.Type != "topology" || p.Properties == nil || len(p.Properties.Raw) == 0 {
+			continue
+		}
+
+		var tp v1alpha1.Placement
+		if err := json.Unmarshal(p.Properties.Raw, &tp); err != nil {
+			return false, fmt.Errorf("error in unmarshalling policy %v: %w", p, err)
+		}
+
+		if tp.ClusterLabelSelector != nil {
+			return true, nil
+		}
+	}
+	return false, nil
+}
+
 // NewClusterRenameCommand create command to help user rename cluster
 func NewClusterRenameCommand(c *common.Args) *cobra.Command {
 	cmd := &cobra.Command{
diff --git a/references/cli/def.go b/references/cli/def.go
index b5d47255..56b8b0a7 100644
--- a/references/cli/def.go
+++ b/references/cli/def.go
@@ -101,9 +101,9 @@ func DefinitionCommandGroup(c common.Args, order string, ioStreams util.IOStream
 }
 
 func getPrompt(cmd *cobra.Command, reader *bufio.Reader, description string, prompt string, validate func(string) error) (string, error) {
-	cmd.Printf(description)
+	cmd.Printf("%s", description)
 	for {
-		cmd.Printf(prompt)
+		cmd.Printf("%s", prompt)
 		resp, err := reader.ReadString('\n')
 		resp = strings.TrimSpace(resp)
 		if err != nil {
@@ -1142,7 +1142,7 @@ func NewDefinitionGenAPICommand(c common.Args) *cobra.Command {
 		}
 	}
 	cmd.Flags().StringSliceVar(&languageArgs, "language-args", []string{},
-		fmt.Sprintf("language-specific arguments to pass to the go generator, available options: \n"+langArgsDescStr),
+		fmt.Sprintf("language-specific arguments to pass to the go generator, available options: \n%s", langArgsDescStr),
 	)
 
 	return cmd
diff --git a/references/cli/install.go b/references/cli/install.go
index 8a32bff1..14697611 100644
--- a/references/cli/install.go
+++ b/references/cli/install.go
@@ -82,7 +82,7 @@ func NewInstallCommand(c common.Args, order string, ioStreams util.IOStreams) *c
 		Short: "Installs or Upgrades Kubevela control plane on a Kubernetes cluster.",
 		Long:  "The Kubevela CLI allows installing Kubevela on any Kubernetes derivative to which your kube config is pointing to.",
 		Args:  cobra.ExactArgs(0),
-		PreRunE: func(cmd *cobra.Command, args []string) error {
+		PreRunE: func(_ *cobra.Command, args []string) error {
 			// CheckRequirements
 			ioStreams.Info("Check Requirements ...")
 			restConfig, err := c.GetConfig()
diff --git a/references/cli/status.go b/references/cli/status.go
index fd7262a2..72434aff 100644
--- a/references/cli/status.go
+++ b/references/cli/status.go
@@ -353,8 +353,8 @@ func loopCheckStatus(c client.Client, ioStreams cmdutil.IOStreams, appName strin
 		if comp.Namespace != "" {
 			nsStat = "Namespace: " + comp.Namespace
 		}
-		ioStreams.Infof(fmt.Sprintf("  - Name: %s  %s\n", compName, envStat))
-		ioStreams.Infof(fmt.Sprintf("    Cluster: %s  %s\n", comp.Cluster, nsStat))
+		ioStreams.Infof("%s", fmt.Sprintf("  - Name: %s  %s\n", compName, envStat))
+		ioStreams.Infof("%s", fmt.Sprintf("    Cluster: %s  %s\n", comp.Cluster, nsStat))
 		ioStreams.Infof("    Type: %s\n", getComponentType(remoteApp, compName))
 		healthColor := getHealthStatusColor(comp.Healthy)
 		healthInfo := strings.ReplaceAll(comp.Message, "\n", "\n\t") // format healthInfo output
@@ -385,7 +385,7 @@ func loopCheckStatus(c client.Client, ioStreams cmdutil.IOStreams, appName strin
 			if tr.Message != "" {
 				traitBase += ": " + tr.Message
 			}
-			ioStreams.Infof(traitBase)
+			ioStreams.Infof("%s", traitBase)
 		}
 		ioStreams.Info("")
 	}
diff --git a/references/cli/velaql.go b/references/cli/velaql.go
index 0eea908a..56e9c7f2 100644
--- a/references/cli/velaql.go
+++ b/references/cli/velaql.go
@@ -275,7 +275,7 @@ func GetServiceEndpoints(ctx context.Context, appName string, namespace string,
 		return nil, err
 	}
 	if response.Error != "" {
-		return nil, fmt.Errorf(response.Error)
+		return nil, fmt.Errorf("%s", response.Error)
 	}
 	return response.Endpoints, nil
 }
@@ -305,7 +305,7 @@ func GetApplicationPods(ctx context.Context, appName string, namespace string, v
 		return nil, err
 	}
 	if response.Error != "" {
-		return nil, fmt.Errorf(response.Error)
+		return nil, fmt.Errorf("%s", response.Error)
 	}
 	return response.Pods, nil
 }
@@ -334,7 +334,7 @@ func GetApplicationServices(ctx context.Context, appName string, namespace strin
 		return nil, err
 	}
 	if response.Error != "" {
-		return nil, fmt.Errorf(response.Error)
+		return nil, fmt.Errorf("%s", response.Error)
 	}
 	return response.Services, nil
 }
diff --git a/references/common/application.go b/references/common/application.go
index 6cc193d1..fee936d1 100644
--- a/references/common/application.go
+++ b/references/common/application.go
@@ -224,7 +224,7 @@ func (o *AppfileOptions) ApplyApp(app *corev1beta1.Application, scopes []oam.Obj
 	if err := o.apply(app, scopes); err != nil {
 		return err
 	}
-	o.IO.Infof(Info(app))
+	o.IO.Infof("%s", Info(app))
 	return nil
 }
 
@@ -262,7 +262,7 @@ func ApplyApplication(app corev1beta1.Application, ioStream cmdutil.IOStreams, c
 	if err != nil {
 		return err
 	}
-	ioStream.Infof(Info(&app))
+	ioStream.Infof("%s", Info(&app))
 	return nil
 }
 
diff --git a/vela-templates/definitions/internal/trait/podsecuritycontext.cue b/vela-templates/definitions/internal/trait/podsecuritycontext.cue
index 09d2ba49..055b987b 100644
--- a/vela-templates/definitions/internal/trait/podsecuritycontext.cue
+++ b/vela-templates/definitions/internal/trait/podsecuritycontext.cue
@@ -33,8 +33,9 @@ template: {
 	parameter: {
 		// +usage=Specify the AppArmor profile for the pod
 		appArmorProfile?: {
-			type:             "RuntimeDefault" | "Unconfined" | "Localhost"
-			localhostProfile: string
+			type: "RuntimeDefault" | "Unconfined" | "Localhost"
+			// +usage:  localhostProfile is required when type is 'Localhost'
+			localhostProfile?: string
 		}
 		fsGroup?:    int
 		runAsGroup?: int
@@ -44,8 +45,9 @@ template: {
 		runAsNonRoot: *true | bool
 		// +usage=Specify the seccomp profile for the pod
 		seccompProfile?: {
-			type:             "RuntimeDefault" | "Unconfined" | "Localhost"
-			localhostProfile: string
+			type: "RuntimeDefault" | "Unconfined" | "Localhost"
+			// +usage:  localhostProfile is required when type is 'Localhost'
+			localhostProfile?: string
 		}
 	}
 }



Test patch:
diff --git a/charts/vela-core/templates/test/test-application.yaml b/charts/vela-core/templates/test/test-application.yaml
index 5b3e8027..4cebf5ae 100644
--- a/charts/vela-core/templates/test/test-application.yaml
+++ b/charts/vela-core/templates/test/test-application.yaml
@@ -48,3 +48,15 @@ spec:
 
           echo "Application and its components are created"
   restartPolicy: Never
+  {{- with .Values.nodeSelector }}
+  nodeSelector:
+  {{- toYaml . | nindent 4 }}
+  {{- end }}
+  {{- with .Values.affinity }}
+  affinity:
+  {{- toYaml . | nindent 4 }}
+  {{- end }}
+  {{- with .Values.tolerations }}
+  tolerations:
+  {{- toYaml . | nindent 4 }}
+  {{- end }}
diff --git a/references/cli/cluster_test.go b/references/cli/cluster_test.go
new file mode 100644
index 00000000..01b7616c
--- /dev/null
+++ b/references/cli/cluster_test.go
@@ -0,0 +1,189 @@
+/*
+Copyright 2022 The KubeVela Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+	http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package cli
+
+import (
+	"context"
+	"fmt"
+
+	. "github.com/onsi/ginkgo/v2"
+	. "github.com/onsi/gomega"
+	"github.com/spf13/cobra"
+	"k8s.io/apimachinery/pkg/types"
+	"sigs.k8s.io/yaml"
+
+	"github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
+	"github.com/oam-dev/kubevela/pkg/oam"
+)
+
+var (
+	appWithoutTopologyPolicyYaml = `
+apiVersion: core.oam.dev/v1beta1
+kind: Application
+metadata:
+  name: app-without-policies
+  namespace: vela-system
+spec:
+  components:
+    - name: nginx-basic
+      type: webservice
+      properties:
+        image: nginx
+`
+	appWithTopologyClustersYaml = `
+apiVersion: core.oam.dev/v1beta1
+kind: Application
+metadata:
+  name: basic-topology
+  namespace: default
+spec:
+  components:
+    - name: nginx-basic
+      type: webservice
+      properties:
+        image: nginx
+  policies:
+    - name: topology-hangzhou-clusters
+      type: topology
+      properties:
+        clusters: ["hangzhou-1", "hangzhou-2"]
+`
+	appWithTopologyClusterLabelSelectorYaml = `
+apiVersion: core.oam.dev/v1beta1
+kind: Application
+metadata:
+  name: region-selector
+  namespace: vela-system
+spec:
+  components:
+    - name: nginx-basic
+      type: webservice
+      properties:
+        image: nginx
+  policies:
+    - name: topology-hangzhou-clusters
+      type: topology
+      properties:
+        clusterLabelSelector:
+          region: hangzhou
+`
+	appWithEmptyTopologyClusterLabelSelectorYaml = `
+apiVersion: core.oam.dev/v1beta1
+kind: Application
+metadata:
+  name: empty-cluster-selector
+  namespace: default
+spec:
+  components:
+    - name: nginx-basic
+      type: webservice
+      properties:
+        image: nginx
+  policies:
+    - name: topology-hangzhou-clusters
+      type: topology
+      properties:
+        clusterLabelSelector: {}
+`
+)
+
+var _ = Describe("Test updateAppsWithTopologyPolicy", func() {
+
+	var _ = When("app does not have topology policy", func() {
+		It("app should not have publish version annotation set", func() {
+			err := createApplication(appWithoutTopologyPolicyYaml)
+			Expect(err).Should(BeNil())
+
+			cmd := &cobra.Command{}
+			err = updateAppsWithTopologyPolicy(context.Background(), cmd, k8sClient)
+			Expect(err).Should(BeNil())
+
+			matched, err := hasPublishVersionAnnotation("app-without-policies", "vela-system")
+			Expect(err).Should(BeNil())
+			Expect(matched).Should(BeFalse())
+		})
+	})
+
+	var _ = When("app has topology policy without clusterLabelSelector", func() {
+		It("app should not have publish version annotation set", func() {
+			err := createApplication(appWithTopologyClustersYaml)
+			Expect(err).Should(BeNil())
+
+			cmd := &cobra.Command{}
+			err = updateAppsWithTopologyPolicy(context.Background(), cmd, k8sClient)
+			Expect(err).Should(BeNil())
+
+			matched, err := hasPublishVersionAnnotation("basic-topology", "default")
+			Expect(err).Should(BeNil())
+			Expect(matched).Should(BeFalse())
+		})
+	})
+
+	var _ = When("app has topology policy with clusterLabelSelector", func() {
+		It("app should have publish version annotation set", func() {
+			err := createApplication(appWithTopologyClusterLabelSelectorYaml)
+			Expect(err).Should(BeNil())
+
+			cmd := &cobra.Command{}
+			err = updateAppsWithTopologyPolicy(context.Background(), cmd, k8sClient)
+			Expect(err).Should(BeNil())
+
+			matched, err := hasPublishVersionAnnotation("region-selector", "vela-system")
+			Expect(err).Should(BeNil())
+			Expect(matched).Should(BeTrue())
+		})
+	})
+
+	var _ = When("app has topology policy with empty clusterLabelSelector", func() {
+		It("app should have publish version annotation set", func() {
+			err := createApplication(appWithEmptyTopologyClusterLabelSelectorYaml)
+			Expect(err).Should(BeNil())
+
+			cmd := &cobra.Command{}
+			err = updateAppsWithTopologyPolicy(context.Background(), cmd, k8sClient)
+			Expect(err).Should(BeNil())
+
+			matched, err := hasPublishVersionAnnotation("empty-cluster-selector", "default")
+			Expect(err).Should(BeNil())
+			Expect(matched).Should(BeTrue())
+		})
+	})
+
+})
+
+func createApplication(appYaml string) error {
+	app := v1beta1.Application{}
+	if err := yaml.Unmarshal([]byte(appYaml), &app); err != nil {
+		return fmt.Errorf("unmarshal error for yaml %s: %w", appYaml, err)
+	}
+	if err := k8sClient.Create(context.Background(), &app); err != nil {
+		return fmt.Errorf("error in creating app %s in namespace %s: %w", app.Name, app.Namespace, err)
+	}
+	return nil
+}
+
+func hasPublishVersionAnnotation(name, namespace string) (bool, error) {
+	app := &v1beta1.Application{}
+	if err := k8sClient.Get(context.Background(), types.NamespacedName{Name: name, Namespace: namespace}, app); err != nil {
+		return false, fmt.Errorf("error in getting application %s in namespace %s: %w", name, namespace, err)
+	}
+	annotations := app.GetAnnotations()
+	if annotations != nil && annotations[oam.AnnotationPublishVersion] != "" {
+		return true, nil
+	}
+	return false, nil
+}
diff --git a/test/e2e-multicluster-test/multicluster_standalone_test.go b/test/e2e-multicluster-test/multicluster_standalone_test.go
index 0aa419b7..0e17e72e 100644
--- a/test/e2e-multicluster-test/multicluster_standalone_test.go
+++ b/test/e2e-multicluster-test/multicluster_standalone_test.go
@@ -299,7 +299,7 @@ var _ = Describe("Test multicluster standalone scenario", func() {
 			revs, err := application.GetSortedAppRevisions(hubCtx, k8sClient, app.Name, namespace)
 			g.Expect(err).Should(Succeed())
 			g.Expect(len(revs)).Should(Equal(1))
-		}).WithTimeout(time.Minute).WithPolling(2 * time.Second).Should(Succeed())
+		}).WithTimeout(5 * time.Minute).WithPolling(2 * time.Second).Should(Succeed())
 	})
 
 	It("Test large application parallel apply and delete", func() {