diff --git a/.github/workflows/ci-build.yaml b/.github/workflows/ci-build.yaml index 4ee870bdcccdf..78c7856f0e2aa 100644 --- a/.github/workflows/ci-build.yaml +++ b/.github/workflows/ci-build.yaml @@ -14,7 +14,7 @@ on: env: # Golang version to use across CI steps # renovate: datasource=golang-version packageName=golang - GOLANG_VERSION: '1.24.6' + GOLANG_VERSION: '1.25.5' concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -103,16 +103,16 @@ jobs: - changes steps: - name: Checkout code - uses: actions/checkout@8410ad0602e1e429cee44a835ae9f77f654a6694 # v4.0.0 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - name: Setup Golang - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 + uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 with: go-version: ${{ env.GOLANG_VERSION }} - name: Run golangci-lint - uses: golangci/golangci-lint-action@4afd733a84b1f43292c63897423277bb7f4313a9 # v8.0.0 + uses: golangci/golangci-lint-action@1e7e51e771db61008b38414a730f564565cf7c20 # v9.2.0 with: # renovate: datasource=go packageName=github.com/golangci/golangci-lint versioning=regex:^v(?\d+)\.(?\d+)\.(?\d+)?$ - version: v2.1.6 + version: v2.5.0 args: --verbose test-go: diff --git a/.github/workflows/image.yaml b/.github/workflows/image.yaml index 8389f703f9656..cc368b91e8792 100644 --- a/.github/workflows/image.yaml +++ b/.github/workflows/image.yaml @@ -53,7 +53,7 @@ jobs: with: # Note: cannot use env variables to set go-version (https://docs.github.com/en/actions/using-workflows/reusing-workflows#limitations) # renovate: datasource=golang-version packageName=golang - go-version: 1.24.6 + go-version: 1.25.5 platforms: ${{ needs.set-vars.outputs.platforms }} push: false @@ -70,7 +70,7 @@ jobs: ghcr_image_name: ghcr.io/argoproj/argo-cd/argocd:${{ needs.set-vars.outputs.image-tag }} # Note: cannot use env variables to set go-version (https://docs.github.com/en/actions/using-workflows/reusing-workflows#limitations) # renovate: datasource=golang-version packageName=golang - go-version: 1.24.6 + go-version: 1.25.5 platforms: ${{ needs.set-vars.outputs.platforms }} push: true secrets: diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index e927652a39326..7af152e1274eb 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -11,7 +11,7 @@ permissions: {} env: # renovate: datasource=golang-version packageName=golang - GOLANG_VERSION: '1.24.6' # Note: go-version must also be set in job argocd-image.with.go-version + GOLANG_VERSION: '1.25.5' # Note: go-version must also be set in job argocd-image.with.go-version jobs: argocd-image: @@ -25,7 +25,7 @@ jobs: quay_image_name: quay.io/argoproj/argocd:${{ github.ref_name }} # Note: cannot use env variables to set go-version (https://docs.github.com/en/actions/using-workflows/reusing-workflows#limitations) # renovate: datasource=golang-version packageName=golang - go-version: 1.24.6 + go-version: 1.25.5 platforms: linux/amd64,linux/arm64,linux/s390x,linux/ppc64le push: true secrets: diff --git a/Dockerfile b/Dockerfile index 1a4c881061500..e86dee15267c4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,7 +4,7 @@ ARG BASE_IMAGE=docker.io/library/ubuntu:24.04@sha256:80dd3c3b9c6cecb9f1667e9290b # 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 docker.io/library/golang:1.24.6@sha256:2c89c41fb9efc3807029b59af69645867cfe978d2b877d475be0d72f6c6ce6f6 AS builder +FROM docker.io/library/golang:1.25.5@sha256:6cc2338c038bc20f96ab32848da2b5c0641bb9bb5363f2c33e9b7c8838f9a208 AS builder WORKDIR /tmp @@ -103,7 +103,7 @@ RUN HOST_ARCH=$TARGETARCH NODE_ENV='production' NODE_ONLINE_ENV='online' NODE_OP #################################################################################################### # Argo CD Build stage which performs the actual build of Argo CD binaries #################################################################################################### -FROM --platform=$BUILDPLATFORM docker.io/library/golang:1.24.6@sha256:2c89c41fb9efc3807029b59af69645867cfe978d2b877d475be0d72f6c6ce6f6 AS argocd-build +FROM --platform=$BUILDPLATFORM docker.io/library/golang:1.25.5@sha256:6cc2338c038bc20f96ab32848da2b5c0641bb9bb5363f2c33e9b7c8838f9a208 AS argocd-build WORKDIR /go/src/github.com/argoproj/argo-cd diff --git a/cmd/argocd/commands/tree.go b/cmd/argocd/commands/tree.go index ae87b82770be8..a7e7a19e29554 100644 --- a/cmd/argocd/commands/tree.go +++ b/cmd/argocd/commands/tree.go @@ -24,7 +24,7 @@ func extractHealthStatusAndReason(node v1alpha1.ResourceNode) (healthStatus heal healthStatus = node.Health.Status reason = node.Health.Message } - return + return healthStatus, reason } func treeViewAppGet(prefix string, uidToNodeMap map[string]v1alpha1.ResourceNode, parentToChildMap map[string][]string, parent v1alpha1.ResourceNode, mapNodeNameToResourceState map[string]*resourceState, w *tabwriter.Writer) { diff --git a/controller/appcontroller.go b/controller/appcontroller.go index 72a6c0835f375..104cd7f7e3a64 100644 --- a/controller/appcontroller.go +++ b/controller/appcontroller.go @@ -996,7 +996,7 @@ func (ctrl *ApplicationController) processAppOperationQueueItem() (processNext b appKey, shutdown := ctrl.appOperationQueue.Get() if shutdown { processNext = false - return + return processNext } processNext = true defer func() { @@ -1009,16 +1009,16 @@ func (ctrl *ApplicationController) processAppOperationQueueItem() (processNext b obj, exists, err := ctrl.appInformer.GetIndexer().GetByKey(appKey) if err != nil { log.Errorf("Failed to get application '%s' from informer index: %+v", appKey, err) - return + return processNext } if !exists { // This happens after app was deleted, but the work queue still had an entry for it. - return + return processNext } origApp, ok := obj.(*appv1.Application) if !ok { log.Warnf("Key '%s' in index is not an application", appKey) - return + return processNext } app := origApp.DeepCopy() logCtx := log.WithFields(applog.GetAppLogFields(app)) @@ -1038,7 +1038,7 @@ func (ctrl *ApplicationController) processAppOperationQueueItem() (processNext b freshApp, err := ctrl.applicationClientset.ArgoprojV1alpha1().Applications(app.ObjectMeta.Namespace).Get(context.Background(), app.Name, metav1.GetOptions{}) if err != nil { logCtx.Errorf("Failed to retrieve latest application state: %v", err) - return + return processNext } app = freshApp } @@ -1060,7 +1060,7 @@ func (ctrl *ApplicationController) processAppOperationQueueItem() (processNext b } ts.AddCheckpoint("finalize_application_deletion_ms") } - return + return processNext } func (ctrl *ApplicationController) processAppComparisonTypeQueueItem() (processNext bool) { @@ -1075,7 +1075,7 @@ func (ctrl *ApplicationController) processAppComparisonTypeQueueItem() (processN }() if shutdown { processNext = false - return + return processNext } if parts := strings.Split(key, "/"); len(parts) != 3 { @@ -1084,11 +1084,11 @@ func (ctrl *ApplicationController) processAppComparisonTypeQueueItem() (processN compareWith, err := strconv.Atoi(parts[2]) if err != nil { log.Warnf("Unable to parse comparison type: %v", err) - return + return processNext } ctrl.requestAppRefresh(ctrl.toAppQualifiedName(parts[1], parts[0]), CompareWith(compareWith).Pointer(), nil) } - return + return processNext } func (ctrl *ApplicationController) processProjectQueueItem() (processNext bool) { @@ -1103,21 +1103,21 @@ func (ctrl *ApplicationController) processProjectQueueItem() (processNext bool) }() if shutdown { processNext = false - return + return processNext } obj, exists, err := ctrl.projInformer.GetIndexer().GetByKey(key) if err != nil { log.Errorf("Failed to get project '%s' from informer index: %+v", key, err) - return + return processNext } if !exists { // This happens after appproj was deleted, but the work queue still had an entry for it. - return + return processNext } origProj, ok := obj.(*appv1.AppProject) if !ok { log.Warnf("Key '%s' in index is not an appproject", key) - return + return processNext } if origProj.DeletionTimestamp != nil && origProj.HasFinalizer() { @@ -1125,7 +1125,7 @@ func (ctrl *ApplicationController) processProjectQueueItem() (processNext bool) log.Warnf("Failed to finalize project deletion: %v", err) } } - return + return processNext } func (ctrl *ApplicationController) finalizeProjectDeletion(proj *appv1.AppProject) error { @@ -1618,7 +1618,7 @@ func (ctrl *ApplicationController) processAppRefreshQueueItem() (processNext boo appKey, shutdown := ctrl.appRefreshQueue.Get() if shutdown { processNext = false - return + return processNext } processNext = true defer func() { @@ -1633,22 +1633,22 @@ func (ctrl *ApplicationController) processAppRefreshQueueItem() (processNext boo obj, exists, err := ctrl.appInformer.GetIndexer().GetByKey(appKey) if err != nil { log.Errorf("Failed to get application '%s' from informer index: %+v", appKey, err) - return + return processNext } if !exists { // This happens after app was deleted, but the work queue still had an entry for it. - return + return processNext } origApp, ok := obj.(*appv1.Application) if !ok { log.Warnf("Key '%s' in index is not an application", appKey) - return + return processNext } origApp = origApp.DeepCopy() needRefresh, refreshType, comparisonLevel := ctrl.needRefreshAppStatus(origApp, ctrl.statusRefreshTimeout, ctrl.statusHardRefreshTimeout) if !needRefresh { - return + return processNext } app := origApp.DeepCopy() logCtx := log.WithFields(applog.GetAppLogFields(app)).WithFields(log.Fields{ @@ -1691,12 +1691,12 @@ func (ctrl *ApplicationController) processAppRefreshQueueItem() (processNext boo app.Status.Summary = tree.GetSummary(app) if err := ctrl.cache.SetAppResourcesTree(app.InstanceName(ctrl.namespace), tree); err != nil { logCtx.Errorf("Failed to cache resources tree: %v", err) - return + return processNext } } patchDuration = ctrl.persistAppStatus(origApp, &app.Status) - return + return processNext } logCtx.Warnf("Failed to get cached managed resources for tree reconciliation, fall back to full reconciliation") } @@ -1718,14 +1718,14 @@ func (ctrl *ApplicationController) processAppRefreshQueueItem() (processNext boo logCtx.Warnf("failed to set app managed resources tree: %v", err) } ts.AddCheckpoint("process_refresh_app_conditions_errors_ms") - return + return processNext } destCluster, err = argo.GetDestinationCluster(context.Background(), app.Spec.Destination, ctrl.db) if err != nil { logCtx.Errorf("Failed to get destination cluster: %v", err) // exit the reconciliation. ctrl.refreshAppConditions should have caught the error - return + return processNext } var localManifests []string @@ -1766,7 +1766,7 @@ func (ctrl *ApplicationController) processAppRefreshQueueItem() (processNext boo if stderrors.Is(err, ErrCompareStateRepo) { logCtx.Warnf("Ignoring temporary failed attempt to compare app state against repo: %v", err) - return // short circuit if git error is encountered + return processNext // short circuit if git error is encountered } for k, v := range compareResult.timings { @@ -1835,14 +1835,14 @@ func (ctrl *ApplicationController) processAppRefreshQueueItem() (processNext boo } } ts.AddCheckpoint("process_finalizers_ms") - return + return processNext } func (ctrl *ApplicationController) processAppHydrateQueueItem() (processNext bool) { appKey, shutdown := ctrl.appHydrateQueue.Get() if shutdown { processNext = false - return + return processNext } processNext = true defer func() { @@ -1854,29 +1854,29 @@ func (ctrl *ApplicationController) processAppHydrateQueueItem() (processNext boo obj, exists, err := ctrl.appInformer.GetIndexer().GetByKey(appKey) if err != nil { log.Errorf("Failed to get application '%s' from informer index: %+v", appKey, err) - return + return processNext } if !exists { // This happens after app was deleted, but the work queue still had an entry for it. - return + return processNext } origApp, ok := obj.(*appv1.Application) if !ok { log.Warnf("Key '%s' in index is not an application", appKey) - return + return processNext } ctrl.hydrator.ProcessAppHydrateQueueItem(origApp) log.WithFields(applog.GetAppLogFields(origApp)).Debug("Successfully processed app hydrate queue item") - return + return processNext } func (ctrl *ApplicationController) processHydrationQueueItem() (processNext bool) { hydrationKey, shutdown := ctrl.hydrationQueue.Get() if shutdown { processNext = false - return + return processNext } processNext = true defer func() { @@ -1897,7 +1897,7 @@ func (ctrl *ApplicationController) processHydrationQueueItem() (processNext bool ctrl.hydrator.ProcessHydrationQueueItem(hydrationKey) logCtx.Debug("Successfully processed hydration queue item") - return + return processNext } func resourceStatusKey(res appv1.ResourceStatus) string { @@ -2060,11 +2060,11 @@ func (ctrl *ApplicationController) persistAppStatus(orig *appv1.Application, new &appv1.Application{ObjectMeta: metav1.ObjectMeta{Annotations: newAnnotations}, Status: *newStatus}) if err != nil { logCtx.Errorf("Error constructing app status patch: %v", err) - return + return patchDuration } if !modified { logCtx.Infof("No status changes. Skipping patch") - return + return patchDuration } // calculate time for path call start := time.Now() diff --git a/controller/hydrator/hydrator.go b/controller/hydrator/hydrator.go index 7bf1db289355a..8e9055a0ba4ad 100644 --- a/controller/hydrator/hydrator.go +++ b/controller/hydrator/hydrator.go @@ -146,7 +146,7 @@ func (h *Hydrator) ProcessHydrationQueueItem(hydrationKey HydrationQueueKey) (pr logCtx = logCtx.WithFields(applog.GetAppLogFields(app)) logCtx.Errorf("Failed to hydrate app: %v", err) } - return + return processNext } logCtx.WithField("appCount", len(relevantApps)).Debug("Successfully hydrated apps") finishedAt := metav1.Now() @@ -174,7 +174,7 @@ func (h *Hydrator) ProcessHydrationQueueItem(hydrationKey HydrationQueueKey) (pr logCtx.WithField("app", app.QualifiedName()).WithError(err).Error("Failed to request app refresh after hydration") } } - return + return processNext } func (h *Hydrator) hydrateAppsLatestCommit(logCtx *log.Entry, hydrationKey HydrationQueueKey) ([]*appv1.Application, string, string, error) { diff --git a/go.mod b/go.mod index 04d11b1a33db8..2682c64e255a8 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( github.com/dlclark/regexp2 v1.11.5 github.com/dustin/go-humanize v1.0.1 github.com/evanphx/json-patch v5.9.11+incompatible - github.com/expr-lang/expr v1.17.5 + github.com/expr-lang/expr v1.17.7 github.com/felixge/httpsnoop v1.0.4 github.com/fsnotify/fsnotify v1.9.0 github.com/gfleury/go-bitbucket-v1 v0.0.0-20240917142304-df385efaac68 diff --git a/go.sum b/go.sum index e6866daaac585..231e0338c85c7 100644 --- a/go.sum +++ b/go.sum @@ -257,8 +257,8 @@ github.com/evanphx/json-patch/v5 v5.9.11 h1:/8HVnzMq13/3x9TPvjG08wUGqBTmZBsCWzjT github.com/evanphx/json-patch/v5 v5.9.11/go.mod h1:3j+LviiESTElxA4p3EMKAB9HXj3/XEtnUf6OZxqIQTM= github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f h1:Wl78ApPPB2Wvf/TIe2xdyJxTlb6obmF18d8QdkxNDu4= github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f/go.mod h1:OSYXu++VVOHnXeitef/D8n/6y4QV8uLHSFXX4NeXMGc= -github.com/expr-lang/expr v1.17.5 h1:i1WrMvcdLF249nSNlpQZN1S6NXuW9WaOfF5tPi3aw3k= -github.com/expr-lang/expr v1.17.5/go.mod h1:8/vRC7+7HBzESEqt5kKpYXxrxkr31SaO8r40VO/1IT4= +github.com/expr-lang/expr v1.17.7 h1:Q0xY/e/2aCIp8g9s/LGvMDCC5PxYlvHgDZRQ4y16JX8= +github.com/expr-lang/expr v1.17.7/go.mod h1:8/vRC7+7HBzESEqt5kKpYXxrxkr31SaO8r40VO/1IT4= github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51/go.mod h1:Yg+htXGokKKdzcwhuNDwVvN+uBxDGXJ7G/VN1d8fa64= github.com/facebookgo/stack v0.0.0-20160209184415-751773369052/go.mod h1:UbMTZqLaRiH3MsBH8va0n7s1pQYcu3uTb8G4tygF4Zg= github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0= diff --git a/hack/installers/install-lint-tools.sh b/hack/installers/install-lint-tools.sh index 09caae63d04bf..69ed2ca2ada7c 100755 --- a/hack/installers/install-lint-tools.sh +++ b/hack/installers/install-lint-tools.sh @@ -2,6 +2,6 @@ set -eux -o pipefail # renovate: datasource=go packageName=github.com/golangci/golangci-lint -GOLANGCI_LINT_VERSION=2.1.6 +GOLANGCI_LINT_VERSION=2.8.0 -GO111MODULE=on go install "github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v${GOLANGCI_LINT_VERSION}" +GO111MODULE=on go install "github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v${GOLANGCI_LINT_VERSION}" \ No newline at end of file diff --git a/server/application/application.go b/server/application/application.go index 09cbdd8b7f535..2545c6d1f2135 100644 --- a/server/application/application.go +++ b/server/application/application.go @@ -2482,7 +2482,7 @@ func (s *Server) getUnstructuredLiveResourceOrApp(ctx context.Context, rbacReque if err != nil { return nil, nil, nil, nil, fmt.Errorf("error getting resource: %w", err) } - return + return obj, res, app, config, err } func (s *Server) getAvailableActions(resourceOverrides map[string]v1alpha1.ResourceOverride, obj *unstructured.Unstructured) ([]v1alpha1.ResourceAction, error) { diff --git a/util/argo/argo.go b/util/argo/argo.go index 805d72a782c23..6d896438f98c0 100644 --- a/util/argo/argo.go +++ b/util/argo/argo.go @@ -1159,7 +1159,7 @@ func parseName(qualifiedName string, defaultNs string, delim string) (name strin namespace = defaultNs name = t[0] } - return + return name, namespace } // ParseAppNamespacedName parses a namespaced name in the format namespace/name diff --git a/util/git/client.go b/util/git/client.go index 557dc584488bd..d17509aac7c4e 100644 --- a/util/git/client.go +++ b/util/git/client.go @@ -670,7 +670,7 @@ func (m *nativeGitClient) LsRemote(revision string) (res string, err error) { for attempt := 0; attempt < maxAttemptsCount; attempt++ { res, err = m.lsRemote(revision) if err == nil { - return + return res, nil } else if apierrors.IsInternalError(err) || apierrors.IsTimeout(err) || apierrors.IsServerTimeout(err) || apierrors.IsTooManyRequests(err) || utilnet.IsProbableEOF(err) || utilnet.IsConnectionReset(err) { // Formula: timeToWait = duration * factor^retry_number @@ -683,7 +683,7 @@ func (m *nativeGitClient) LsRemote(revision string) (res string, err error) { time.Sleep(time.Duration(timeToWait)) } } - return + return res, err } func getGitTags(refs []*plumbing.Reference) []string { diff --git a/util/io/componsablefs.go b/util/io/componsablefs.go index 5e00ed5262839..91cb39b760e8c 100644 --- a/util/io/componsablefs.go +++ b/util/io/componsablefs.go @@ -19,5 +19,5 @@ func (c composableFS) Open(name string) (f fs.File, err error) { break } } - return + return f, err } diff --git a/util/lua/lua_test.go b/util/lua/lua_test.go index 0459d66031e91..d97b6ca64f8a7 100644 --- a/util/lua/lua_test.go +++ b/util/lua/lua_test.go @@ -109,7 +109,8 @@ func TestFailExternalLibCall(t *testing.T) { vm := VM{} _, err := vm.ExecuteHealthLua(testObj, osLuaScript) require.Error(t, err) - assert.IsType(t, &lua.ApiError{}, err) + var apiErr *lua.ApiError + assert.ErrorAs(t, err, &apiErr) } const returnInt = `return 1` @@ -183,7 +184,8 @@ func TestHandleInfiniteLoop(t *testing.T) { testObj := StrToUnstructured(objJSON) vm := VM{} _, err := vm.ExecuteHealthLua(testObj, infiniteLoop) - assert.IsType(t, &lua.ApiError{}, err) + var apiErr *lua.ApiError + assert.ErrorAs(t, err, &apiErr) } func TestGetHealthScriptWithOverride(t *testing.T) { @@ -954,7 +956,8 @@ return hs` testObj := StrToUnstructured(testSA) overrides := getHealthOverride(false) status, err := overrides.GetResourceHealth(testObj) - assert.IsType(t, &lua.ApiError{}, err) + var apiErr *lua.ApiError + require.ErrorAs(t, err, &apiErr) expectedErr := ":4: attempt to index a non-table object(nil) with key 'find'" require.EqualError(t, err, expectedErr) assert.Nil(t, status) diff --git a/util/password/password.go b/util/password/password.go index 6faeaf9412558..41f34f079e068 100644 --- a/util/password/password.go +++ b/util/password/password.go @@ -70,7 +70,7 @@ func HashPassword(password string) (string, error) { // VerifyPassword verifies an entered password against a hashed password and returns whether the hash is "stale" (i.e., was verified using the FIRST preferred hasher above). func VerifyPassword(password, hashedPassword string) (valid, stale bool) { valid, stale = verifyPasswordWithHashers(password, hashedPassword, preferredHashers) - return + return valid, stale } // HashPassword creates a one-way digest ("hash") of a password. In the case of Bcrypt, a pseudorandom salt is included automatically by the underlying library.