From 2760046e50ec5ebbae2660106da2ff26e2e52f80 Mon Sep 17 00:00:00 2001 From: Mridul Gain Date: Wed, 19 Aug 2026 11:28:00 +0530 Subject: [PATCH 1/2] fix(lint): migrate golangci-lint config to v2, bump tool to v2.12.2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit golangci-lint v1.64.5 (pinned in Makefile) was built with Go 1.24 and refuses to lint a module targeting a newer Go version: Error: can't load config: the Go language version (go1.24) used to build golangci-lint is lower than the targeted Go version (1.25.0) This became a hard failure once go.mod's go directive was bumped to 1.25.0 (see the grpc CVE fix on the parent branch). golangci-lint's v1 line is discontinued, so there is no newer v1.x build to pin instead — migrated to v2.12.2. - Ran `golangci-lint migrate` to convert .golangci.yml to the v2 schema. gosimple/stylecheck are now folded into v2's staticcheck meta-linter (same checks, no behavior change intended). - Bumped Makefile's GOLANGCI_VERSION to 2.12.2. - Fixed the new findings the newer staticcheck/prealloc checks surfaced, all pre-existing and mechanical: - Removed embedded-field redundancy (`x.Embedded.Field` -> `x.Field`) in server/oauth2.go, server/rotation.go, and several storage/kubernetes files. - Converted an equality-chain switch to a tagged switch in server/oauth2.go. - Preallocated a slice with known capacity in storage/conformance/conformance.go. - Removed two `//nolint:prealloc` directives in connector/keystone/keystone.go that prealloc no longer flags. - Simplified `c.Config.Field` to `c.Field` in connector/atlassiancrowd/atlassiancrowd_test.go (embedded Config). Verified: `golangci-lint run` reports 0 issues; go build/vet/test pass (the one remaining test failure is the pre-existing, unrelated SAML fixture-cert-expiry issue fixed on a separate branch, PR #72). Co-Authored-By: Claude Sonnet 5 --- .golangci.yml | 152 +++++++----------- Makefile | 2 +- .../atlassiancrowd/atlassiancrowd_test.go | 8 +- connector/keystone/keystone.go | 4 +- server/oauth2.go | 12 +- server/rotation.go | 2 +- storage/conformance/conformance.go | 2 +- storage/kubernetes/lock.go | 6 +- storage/kubernetes/storage.go | 32 ++-- storage/kubernetes/types.go | 12 +- 10 files changed, 98 insertions(+), 134 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index d54dcb183f..2b894c11ab 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,97 +1,61 @@ -run: - timeout: 4m - -linters-settings: +version: "2" +linters: + default: none + enable: + - depguard + - dogsled + - exhaustive + - gochecknoinits + - gocritic + - goprintffuncname + - govet + - ineffassign + - misspell + - nakedret + - nolintlint + - prealloc + - staticcheck + - unconvert + - unused + - whitespace + settings: depguard: - rules: - deprecated: - deny: - - pkg: "io/ioutil" - desc: "The 'io/ioutil' package is deprecated. Use corresponding 'os' or 'io' functions instead." + rules: + deprecated: + deny: + - pkg: io/ioutil + desc: The 'io/ioutil' package is deprecated. Use corresponding 'os' or 'io' functions instead. + exclusions: + generated: lax + presets: + - comments + - common-false-positives + - legacy + - std-error-handling + paths: + - storage/ent/db + - third_party$ + - builtin$ + - examples$ +formatters: + enable: + - gci + - gofmt + - gofumpt + - goimports + settings: gci: - sections: - - standard - - default - - prefix(github.com/dexidp/dex) + sections: + - standard + - default + - prefix(github.com/dexidp/dex) goimports: - local-prefixes: github.com/dexidp/dex - -linters: - disable-all: true - enable: - - depguard - - dogsled - - exhaustive - - gci - - gochecknoinits - - gocritic - - gofmt - - gofumpt - - goimports - - goprintffuncname - - gosimple - - govet - - ineffassign - - misspell - - nakedret - - nolintlint - - prealloc - # - revive - # - sqlclosecheck - - staticcheck - - stylecheck - - unconvert - - unused - - whitespace - - # Disable temporarily until everything works with Go 1.20 - # - bodyclose - # - rowserrcheck - # - tparallel - # - unparam - - # Disable temporarily until everything works with Go 1.18 - - typecheck - - # Disable temporarily until the following issue is resolved: https://github.com/golangci/golangci-lint/issues/3086 - # - sqlclosecheck - - # TODO: fix linter errors before enabling - # - exhaustivestruct - # - gochecknoglobals - # - errorlint - # - gocognit - # - godot - # - nlreturn - # - noctx - # - revive - # - wrapcheck - - # TODO: fix linter errors before enabling (from original config) - # - dupl - # - errcheck - # - goconst - # - gocyclo - # - gosec - # - lll - # - scopelint - - # unused - # - goheader - # - gomodguard - - # don't enable: - # - asciicheck - # - funlen - # - godox - # - goerr113 - # - gomnd - # - interfacer - # - maligned - # - nestif - # - testpackage - # - wsl - -issues: - exclude-dirs: - - storage/ent/db # generated ent code + local-prefixes: + - github.com/dexidp/dex + exclusions: + generated: lax + paths: + - storage/ent/db + - third_party$ + - builtin$ + - examples$ diff --git a/Makefile b/Makefile index ccdefac12a..ba1001ed39 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ export GOBIN=$(PWD)/bin LD_FLAGS="-w -X main.version=$(VERSION)" # Dependency versions -GOLANGCI_VERSION = 1.64.5 +GOLANGCI_VERSION = 2.12.2 GOTESTSUM_VERSION ?= 1.12.0 PROTOC_VERSION = 29.3 diff --git a/connector/atlassiancrowd/atlassiancrowd_test.go b/connector/atlassiancrowd/atlassiancrowd_test.go index 9471fb80c0..d2970bb23c 100644 --- a/connector/atlassiancrowd/atlassiancrowd_test.go +++ b/connector/atlassiancrowd/atlassiancrowd_test.go @@ -124,19 +124,19 @@ func TestIdentityFromCrowdUser(t *testing.T) { // unset expectEquals(t, i.PreferredUsername, "") - c.Config.PreferredUsernameField = "key" + c.PreferredUsernameField = "key" i = c.identityFromCrowdUser(user) expectEquals(t, i.PreferredUsername, "12345") - c.Config.PreferredUsernameField = "name" + c.PreferredUsernameField = "name" i = c.identityFromCrowdUser(user) expectEquals(t, i.PreferredUsername, "testuser") - c.Config.PreferredUsernameField = "email" + c.PreferredUsernameField = "email" i = c.identityFromCrowdUser(user) expectEquals(t, i.PreferredUsername, "testuser@example.com") - c.Config.PreferredUsernameField = "invalidstring" + c.PreferredUsernameField = "invalidstring" i = c.identityFromCrowdUser(user) expectEquals(t, i.PreferredUsername, "") } diff --git a/connector/keystone/keystone.go b/connector/keystone/keystone.go index bb58c4aed5..794bea44f4 100644 --- a/connector/keystone/keystone.go +++ b/connector/keystone/keystone.go @@ -491,8 +491,8 @@ func getUser(ctx context.Context, client *http.Client, baseURL, userID, token st // getAllGroupsForUser returns all groups for a user (local groups + SSO groups + role groups) func getAllGroupsForUser(ctx context.Context, client *http.Client, baseURL, token, customerName, domainID string, tokenInfo *tokenInfo, logger *slog.Logger) ([]string, error) { - var userGroups []string //nolint:prealloc - var userGroupIDs []string //nolint:prealloc + var userGroups []string + var userGroupIDs []string allGroups, err := getAllKeystoneGroups(ctx, client, baseURL, token) if err != nil { diff --git a/server/oauth2.go b/server/oauth2.go index b48ac477a8..224a1645e0 100644 --- a/server/oauth2.go +++ b/server/oauth2.go @@ -402,16 +402,16 @@ func (s *Server) newIDToken(ctx context.Context, clientID string, claims storage } for _, scope := range scopes { - switch { - case scope == scopeEmail: + switch scope { + case scopeEmail: tok.Email = claims.Email tok.EmailVerified = &claims.EmailVerified - case scope == scopeGroups: + case scopeGroups: tok.Groups = claims.Groups - case scope == scopeProfile: + case scopeProfile: tok.Name = claims.Username tok.PreferredUsername = claims.PreferredUsername - case scope == scopeFederatedID: + case scopeFederatedID: tok.FederatedIDClaims = &federatedIDClaims{ ConnectorID: connID, UserID: claims.UserID, @@ -720,7 +720,7 @@ func (s *storageKeySet) VerifySignature(ctx context.Context, jwt string) (payloa break } - skeys, err := s.Storage.GetKeys(ctx) + skeys, err := s.GetKeys(ctx) if err != nil { return nil, err } diff --git a/server/rotation.go b/server/rotation.go index 286b4b57af..49ba7f27f6 100644 --- a/server/rotation.go +++ b/server/rotation.go @@ -128,7 +128,7 @@ func (k keyRotator) rotate() error { } var nextRotation time.Time - err = k.Storage.UpdateKeys(context.Background(), func(keys storage.Keys) (storage.Keys, error) { + err = k.UpdateKeys(context.Background(), func(keys storage.Keys) (storage.Keys, error) { tNow := k.now() // if you are running multiple instances of dex, another instance diff --git a/storage/conformance/conformance.go b/storage/conformance/conformance.go index 58ae3d958d..c3f22be82a 100644 --- a/storage/conformance/conformance.go +++ b/storage/conformance/conformance.go @@ -508,7 +508,7 @@ func testPasswordCRUD(t *testing.T, s storage.Storage) { password1.Username = "jane doe" getAndCompare("jane@example.com", password1) - var passwordList []storage.Password + passwordList := make([]storage.Password, 0, 2) passwordList = append(passwordList, password1, password2) listAndCompare := func(want []storage.Password) { diff --git a/storage/kubernetes/lock.go b/storage/kubernetes/lock.go index c67380dcc0..ddb3499751 100644 --- a/storage/kubernetes/lock.go +++ b/storage/kubernetes/lock.go @@ -58,7 +58,7 @@ func (l *refreshTokenLock) Unlock(id string) { } r.Annotations = nil - err = l.cli.put(resourceRefreshToken, r.ObjectMeta.Name, r) + err = l.cli.put(resourceRefreshToken, r.Name, r) if err != nil { l.cli.logger.Debug("failed to release lock for refresh token", "token_id", id, "err", err) } @@ -82,7 +82,7 @@ func (l *refreshTokenLock) setLockAnnotation(id string) (bool, error) { } r.Annotations = lockData - err := l.cli.put(resourceRefreshToken, r.ObjectMeta.Name, r) + err := l.cli.put(resourceRefreshToken, r.Name, r) if err == nil { return false, nil } @@ -108,7 +108,7 @@ func (l *refreshTokenLock) setLockAnnotation(id string) (bool, error) { // Lock time is out, lets break the lock and take the advantage r.Annotations = lockData - err = l.cli.put(resourceRefreshToken, r.ObjectMeta.Name, r) + err = l.cli.put(resourceRefreshToken, r.Name, r) if err == nil { // break lock annotation return false, nil diff --git a/storage/kubernetes/storage.go b/storage/kubernetes/storage.go index 24f91c698e..00771815c3 100644 --- a/storage/kubernetes/storage.go +++ b/storage/kubernetes/storage.go @@ -155,16 +155,16 @@ func (cli *client) registerCustomResources() (ok bool) { r := definitions[i] var i interface{} - cli.logger.Info("checking if custom resource has already been created...", "object", r.ObjectMeta.Name) + cli.logger.Info("checking if custom resource has already been created...", "object", r.Name) if err := cli.listN(r.Spec.Names.Plural, &i, 1); err == nil { - cli.logger.Info("the custom resource already available, skipping create", "object", r.ObjectMeta.Name) + cli.logger.Info("the custom resource already available, skipping create", "object", r.Name) continue } else { - cli.logger.Info("failed to list custom resource, attempting to create", "object", r.ObjectMeta.Name, "err", err) + cli.logger.Info("failed to list custom resource, attempting to create", "object", r.Name, "err", err) } err = cli.postResource(cli.crdAPIVersion, "", "customresourcedefinitions", r) - resourceName = r.ObjectMeta.Name + resourceName = r.Name if err != nil { switch err { @@ -423,7 +423,7 @@ func (cli *client) DeleteClient(ctx context.Context, id string) error { if err != nil { return err } - return cli.delete(resourceClient, c.ObjectMeta.Name) + return cli.delete(resourceClient, c.Name) } func (cli *client) DeleteRefresh(ctx context.Context, id string) error { @@ -436,7 +436,7 @@ func (cli *client) DeletePassword(ctx context.Context, email string) error { if err != nil { return err } - return cli.delete(resourcePassword, p.ObjectMeta.Name) + return cli.delete(resourcePassword, p.Name) } func (cli *client) DeleteOfflineSessions(ctx context.Context, userID string, connID string) error { @@ -445,7 +445,7 @@ func (cli *client) DeleteOfflineSessions(ctx context.Context, userID string, con if err != nil { return err } - return cli.delete(resourceOfflineSessions, o.ObjectMeta.Name) + return cli.delete(resourceOfflineSessions, o.Name) } func (cli *client) DeleteConnector(ctx context.Context, id string) error { @@ -475,7 +475,7 @@ func (cli *client) UpdateRefreshToken(ctx context.Context, id string, updater fu newToken := cli.fromStorageRefreshToken(updated) newToken.ObjectMeta = r.ObjectMeta - return cli.put(resourceRefreshToken, r.ObjectMeta.Name, newToken) + return cli.put(resourceRefreshToken, r.Name, newToken) }) } @@ -493,7 +493,7 @@ func (cli *client) UpdateClient(ctx context.Context, id string, updater func(old newClient := cli.fromStorageClient(updated) newClient.ObjectMeta = c.ObjectMeta - return cli.put(resourceClient, c.ObjectMeta.Name, newClient) + return cli.put(resourceClient, c.Name, newClient) } func (cli *client) UpdatePassword(ctx context.Context, email string, updater func(old storage.Password) (storage.Password, error)) error { @@ -510,7 +510,7 @@ func (cli *client) UpdatePassword(ctx context.Context, email string, updater fun newPassword := cli.fromStoragePassword(updated) newPassword.ObjectMeta = p.ObjectMeta - return cli.put(resourcePassword, p.ObjectMeta.Name, newPassword) + return cli.put(resourcePassword, p.Name, newPassword) } func (cli *client) UpdateOfflineSessions(ctx context.Context, userID string, connID string, updater func(old storage.OfflineSessions) (storage.OfflineSessions, error)) error { @@ -527,7 +527,7 @@ func (cli *client) UpdateOfflineSessions(ctx context.Context, userID string, con newOfflineSessions := cli.fromStorageOfflineSessions(updated) newOfflineSessions.ObjectMeta = o.ObjectMeta - return cli.put(resourceOfflineSessions, o.ObjectMeta.Name, newOfflineSessions) + return cli.put(resourceOfflineSessions, o.Name, newOfflineSessions) }) } @@ -621,7 +621,7 @@ func (cli *client) GarbageCollect(ctx context.Context, now time.Time) (result st var delErr error for _, authRequest := range authRequests.AuthRequests { if now.After(authRequest.Expiry) { - if err := cli.delete(resourceAuthRequest, authRequest.ObjectMeta.Name); err != nil { + if err := cli.delete(resourceAuthRequest, authRequest.Name); err != nil { cli.logger.Error("failed to delete auth request", "err", err) delErr = fmt.Errorf("failed to delete auth request: %v", err) } @@ -639,7 +639,7 @@ func (cli *client) GarbageCollect(ctx context.Context, now time.Time) (result st for _, authCode := range authCodes.AuthCodes { if now.After(authCode.Expiry) { - if err := cli.delete(resourceAuthCode, authCode.ObjectMeta.Name); err != nil { + if err := cli.delete(resourceAuthCode, authCode.Name); err != nil { cli.logger.Error("failed to delete auth code", "err", err) delErr = fmt.Errorf("failed to delete auth code: %v", err) } @@ -654,7 +654,7 @@ func (cli *client) GarbageCollect(ctx context.Context, now time.Time) (result st for _, deviceRequest := range deviceRequests.DeviceRequests { if now.After(deviceRequest.Expiry) { - if err := cli.delete(resourceDeviceRequest, deviceRequest.ObjectMeta.Name); err != nil { + if err := cli.delete(resourceDeviceRequest, deviceRequest.Name); err != nil { cli.logger.Error("failed to delete device request", "err", err) delErr = fmt.Errorf("failed to delete device request: %v", err) } @@ -669,7 +669,7 @@ func (cli *client) GarbageCollect(ctx context.Context, now time.Time) (result st for _, deviceToken := range deviceTokens.DeviceTokens { if now.After(deviceToken.Expiry) { - if err := cli.delete(resourceDeviceToken, deviceToken.ObjectMeta.Name); err != nil { + if err := cli.delete(resourceDeviceToken, deviceToken.Name); err != nil { cli.logger.Error("failed to delete device token", "err", err) delErr = fmt.Errorf("failed to delete device token: %v", err) } @@ -726,7 +726,7 @@ func (cli *client) UpdateDeviceToken(ctx context.Context, deviceCode string, upd newToken := cli.fromStorageDeviceToken(updated) newToken.ObjectMeta = r.ObjectMeta - return cli.put(resourceDeviceToken, r.ObjectMeta.Name, newToken) + return cli.put(resourceDeviceToken, r.Name, newToken) }) } diff --git a/storage/kubernetes/types.go b/storage/kubernetes/types.go index c126ddc087..64ed489ec5 100644 --- a/storage/kubernetes/types.go +++ b/storage/kubernetes/types.go @@ -369,7 +369,7 @@ type AuthRequestList struct { func toStorageAuthRequest(req AuthRequest) storage.AuthRequest { a := storage.AuthRequest{ - ID: req.ObjectMeta.Name, + ID: req.Name, ClientID: req.ClientID, ResponseTypes: req.ResponseTypes, Scopes: req.Scopes, @@ -526,7 +526,7 @@ func (cli *client) fromStorageAuthCode(a storage.AuthCode) AuthCode { func toStorageAuthCode(a AuthCode) storage.AuthCode { return storage.AuthCode{ - ID: a.ObjectMeta.Name, + ID: a.Name, ClientID: a.ClientID, RedirectURI: a.RedirectURI, ConnectorID: a.ConnectorID, @@ -573,7 +573,7 @@ type RefreshList struct { func toStorageRefreshToken(r RefreshToken) storage.RefreshToken { return storage.RefreshToken{ - ID: r.ObjectMeta.Name, + ID: r.Name, Token: r.Token, ObsoleteToken: r.ObsoleteToken, CreatedAt: r.CreatedAt, @@ -733,7 +733,7 @@ func toStorageConnector(c Connector) storage.Connector { ID: c.ID, Type: c.Type, Name: c.Name, - ResourceVersion: c.ObjectMeta.ResourceVersion, + ResourceVersion: c.ResourceVersion, Config: c.Config, } } @@ -786,7 +786,7 @@ func (cli *client) fromStorageDeviceRequest(a storage.DeviceRequest) DeviceReque func toStorageDeviceRequest(req DeviceRequest) storage.DeviceRequest { return storage.DeviceRequest{ - UserCode: strings.ToUpper(req.ObjectMeta.Name), + UserCode: strings.ToUpper(req.Name), DeviceCode: req.DeviceCode, ClientID: req.ClientID, ClientSecret: req.ClientSecret, @@ -840,7 +840,7 @@ func (cli *client) fromStorageDeviceToken(t storage.DeviceToken) DeviceToken { func toStorageDeviceToken(t DeviceToken) storage.DeviceToken { return storage.DeviceToken{ - DeviceCode: t.ObjectMeta.Name, + DeviceCode: t.Name, Status: t.Status, Token: t.Token, Expiry: t.Expiry, From 525a2d372249060f8a6d139c0562ec107ded6840 Mon Sep 17 00:00:00 2001 From: Mridul Gain Date: Wed, 19 Aug 2026 11:33:48 +0530 Subject: [PATCH 2/2] fix(lint): pin golangci-lint to v2.11.0, v2.12.2's release asset is broken MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CI failed installing golangci-lint v2.12.2: err hash_sha256_verify checksum for '.../golangci-lint-2.12.2-linux-amd64.tar.gz' did not verify 8df580d2670fed8fa984aac0507099af8df275e665215f5c7a2ae3943893a553 vs fd3a137c7e722128143cc8932bcaa00bc73e10adadee18bdb0893453edb2c137 The computed hash (fd3a137c...) matches the checksum published for golangci-lint-2.12.2-linux-amd64.tar.gz.sbom.json, not the .tar.gz itself — install.sh's asset-matching picked the wrong file for this release. Reproduces the same way on darwin-arm64, so it's a bug in this specific release's assets/naming, not a platform issue. v2.11.0 installs correctly via the same script (verified locally), is built with go1.26.1 (satisfies the go1.25 language-version floor golangci-lint enforces against go.mod), and lints this repo with the migrated v2 config at 0 issues. Co-Authored-By: Claude Sonnet 5 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index ba1001ed39..53959b9f3a 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ export GOBIN=$(PWD)/bin LD_FLAGS="-w -X main.version=$(VERSION)" # Dependency versions -GOLANGCI_VERSION = 2.12.2 +GOLANGCI_VERSION = 2.11.0 GOTESTSUM_VERSION ?= 1.12.0 PROTOC_VERSION = 29.3