From 291496316f4a7db69a3727dd9dfd77a4b2c39f1f Mon Sep 17 00:00:00 2001 From: RW Date: Fri, 21 Nov 2025 10:22:22 +0100 Subject: [PATCH 1/5] Update golangci-lint to v2.6.2 --- .github/workflows/linter.yml | 2 +- Makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml index a651bca..f64491a 100644 --- a/.github/workflows/linter.yml +++ b/.github/workflows/linter.yml @@ -36,6 +36,6 @@ jobs: uses: golangci/golangci-lint-action@v9 with: # NOTE: Keep this in sync with the version from .golangci.yml - version: v1.64.7 + version: v2.6.2 # NOTE(ldez): temporary workaround install-mode: goinstall diff --git a/Makefile b/Makefile index ad57fea..891960d 100644 --- a/Makefile +++ b/Makefile @@ -39,7 +39,7 @@ markdown: ## lint: 🚨 Run lint checks .PHONY: lint lint: - GOTOOLCHAIN=$(TOOLCHAIN) go run github.com/golangci/golangci-lint/cmd/golangci-lint@v1.62.0 run ./... +GOTOOLCHAIN=$(TOOLCHAIN) go run github.com/golangci/golangci-lint/cmd/golangci-lint@v2.6.2 run ./... ## test: 🚦 Execute all tests .PHONY: test From e33b23664a2ab27890ef6a446642711e0756d6e7 Mon Sep 17 00:00:00 2001 From: RW Date: Fri, 21 Nov 2025 10:40:45 +0100 Subject: [PATCH 2/5] Fix golangci-lint v2 integration --- .golangci.yml | 16 ++++++++++------ Makefile | 2 +- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 3ce087c..7d9958d 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,5 +1,7 @@ # v1.2.0. Created based on golangci-lint v1.57.1 +version: 2 + run: timeout: 5m modules-download-mode: readonly @@ -297,7 +299,6 @@ linters: - forbidigo - forcetypeassert # - funlen - - gci - ginkgolinter # - gocheckcompilerdirectives # TODO: Enable # - gochecknoglobals # TODO: Enable @@ -310,8 +311,6 @@ linters: # - godot # - godox - err113 - - gofmt - - gofumpt # - goheader # - goimports # - mnd # TODO: Enable @@ -319,7 +318,8 @@ linters: # - gomodguard - goprintffuncname - gosec - - gosimple + # Staticcheck bundles the checks previously exposed as gosimple/stylecheck + # so we keep only the main linter enabled here. # - gosmopolitan # TODO: Enable - govet - grouper @@ -361,7 +361,6 @@ linters: - spancheck - sqlclosecheck - staticcheck - - stylecheck # - tagalign # TODO: Enable - tagliatelle - testableexamples @@ -369,7 +368,6 @@ linters: # - testpackage # TODO: Enable - thelper - tparallel - - typecheck - unconvert - unparam - unused @@ -380,3 +378,9 @@ linters: - wrapcheck # - wsl - zerologlint + +formatters: + enable: + - gofmt + - gofumpt + - gci diff --git a/Makefile b/Makefile index 891960d..4bb2c87 100644 --- a/Makefile +++ b/Makefile @@ -39,7 +39,7 @@ markdown: ## lint: 🚨 Run lint checks .PHONY: lint lint: -GOTOOLCHAIN=$(TOOLCHAIN) go run github.com/golangci/golangci-lint/cmd/golangci-lint@v2.6.2 run ./... + GOTOOLCHAIN=$(TOOLCHAIN) go run github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.6.2 run ./... ## test: 🚦 Execute all tests .PHONY: test From a3f6aba02dd948bfb649971e267be7655e43c16d Mon Sep 17 00:00:00 2001 From: RW Date: Fri, 21 Nov 2025 11:08:22 +0100 Subject: [PATCH 3/5] Fix golangci-lint v2 config schema --- .golangci.yml | 518 +++++++++++++++++++++++++------------------------- 1 file changed, 254 insertions(+), 264 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 7d9958d..86d92ff 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,6 +1,6 @@ # v1.2.0. Created based on golangci-lint v1.57.1 -version: 2 +version: "2" run: timeout: 5m @@ -8,272 +8,223 @@ run: allow-serial-runners: true output: - sort-results: true + sort-order: + - linter + - severity + - file -linters-settings: - depguard: - rules: - all: - list-mode: lax - deny: - - pkg: "flag" - desc: '`flag` package is only allowed in main.go' - - pkg: "io/ioutil" - desc: '`io/ioutil` package is deprecated, use the `io` and `os` package instead' - # TODO: Prevent using these without a reason - # - pkg: "reflect" - # desc: '`reflect` package is dangerous to use' - # - pkg: "unsafe" - # desc: '`unsafe` package is dangerous to use' - - errcheck: - check-type-assertions: true - check-blank: true - disable-default-exclusions: true - exclude-functions: - - '(*bytes.Buffer).Write' # always returns nil error - - '(*github.com/valyala/bytebufferpool.ByteBuffer).Write' # always returns nil error - - '(*github.com/valyala/bytebufferpool.ByteBuffer).WriteByte' # always returns nil error - - '(*github.com/valyala/bytebufferpool.ByteBuffer).WriteString' # always returns nil error - - errchkjson: - report-no-exported: true - - exhaustive: - check-generated: true - default-signifies-exhaustive: true - - forbidigo: - forbid: - - ^print(ln)?$ - - ^fmt\.Print(f|ln)?$ - - ^http\.Default(Client|ServeMux|Transport)$ - # TODO: Eventually enable these patterns - # - ^panic$ - # - ^time\.Sleep$ - analyze-types: true - - gci: - sections: - - standard - - default - - blank - - dot - #- alias - - prefix(github.com/gofiber) - custom-order: true - - goconst: - numbers: true - - gocritic: - # TODO: Uncomment the following lines - enabled-tags: - - diagnostic - # - style - # - performance - # - experimental - # - opinionated - settings: - captLocal: - paramsOnly: false - elseif: - skipBalanced: false - underef: - skipRecvDeref: false - # NOTE: Set this option to false if other projects rely on this project's code - # unnamedResult: - # checkExported: false - - gofumpt: - module-path: github.com/gofiber/cli - extra-rules: true - - gosec: - excludes: - - G104 # TODO: Enable this again. Mostly provided by errcheck - config: - global: - # show-ignored: true # TODO: Enable this - audit: true - - govet: - enable-all: true - disable: - - shadow - - grouper: - # const-require-grouping: true # TODO: Enable this - import-require-single-import: true - import-require-grouping: true - # var-require-grouping: true # TODO: Conflicts with gofumpt - - loggercheck: - require-string-key: true - no-printf-like: true - - misspell: - locale: US - - nolintlint: - require-explanation: true - require-specific: true - - nonamedreturns: - report-error-in-defer: true - - perfsprint: - err-error: true - - predeclared: - q: true - - promlinter: - strict: true - - # TODO: Enable this - # reassign: - # patterns: - # - '.*' - - revive: - enable-all-rules: true - rules: - # Provided by gomnd linter - - name: add-constant - disabled: true - - name: argument-limit - disabled: true - # Provided by bidichk - - name: banned-characters - disabled: true - - name: cognitive-complexity - disabled: true - - name: confusing-results - disabled: true - - name: comment-spacings - arguments: - - nolint - disabled: true # TODO: Do not disable - - name: cyclomatic - disabled: true - # TODO: Enable this check. Currently disabled due to upstream bug. - # - name: enforce-repeated-arg-type-style - # arguments: - # - short - - name: enforce-slice-style - arguments: - - make - disabled: true # TODO: Do not disable - - name: exported - disabled: true - - name: flag-parameter - disabled: true - - name: file-header - disabled: true - - name: function-result-limit - arguments: [3] - - name: function-length - disabled: true - - name: line-length-limit - disabled: true - - name: max-public-structs - disabled: true - - name: modifies-parameter - disabled: true - - name: nested-structs - disabled: true # TODO: Do not disable - - name: package-comments - disabled: true - - name: optimize-operands-order - disabled: true - - name: unchecked-type-assertion - disabled: true # TODO: Do not disable - - name: unhandled-error - disabled: true - - stylecheck: - checks: - - all - - -ST1000 - - -ST1020 - - -ST1021 - - -ST1022 - - tagalign: - strict: true - - tagliatelle: - case: +linters: + settings: + depguard: rules: - json: snake - - tenv: - all: true - - testifylint: - enable-all: true - - testpackage: - skip-regexp: "^$" - - unparam: - # NOTE: Set this option to false if other projects rely on this project's code - check-exported: false - - unused: - # TODO: Uncomment these two lines - # parameters-are-used: false - # local-variables-are-used: false - # NOTE: Set these options to true if other projects rely on this project's code - field-writes-are-uses: true - # exported-is-used: true # TODO: Fix issues with this option (upstream) - exported-fields-are-used: true - - usestdlibvars: - http-method: true - http-status-code: true - time-weekday: false # TODO: Set to true - time-month: false # TODO: Set to true - time-layout: false # TODO: Set to true - crypto-hash: true - default-rpc-path: true - sql-isolation-level: true - tls-signature-scheme: true - constant-kind: true - - wrapcheck: - ignorePackageGlobs: - - github.com/gofiber/fiber/* - - github.com/valyala/fasthttp - -issues: - exclude-use-default: false - exclude-case-sensitive: true - max-issues-per-linter: 0 - max-same-issues: 0 - exclude-files: - - '_msgp\.go' - - '_msgp_test\.go' - exclude-rules: - - linters: - - err113 - text: 'do not define dynamic errors, use wrapped static errors instead*' - - path: log/.*\.go - linters: - - depguard - # Exclude some linters from running on tests files. - - path: _test\.go - linters: - - bodyclose - - err113 - - revive - - source: 'fmt.Fprintf?' - linters: - - errcheck - - revive + all: + list-mode: lax + deny: + - pkg: "flag" + desc: '`flag` package is only allowed in main.go' + - pkg: "io/ioutil" + desc: '`io/ioutil` package is deprecated, use the `io` and `os` package instead' + # TODO: Prevent using these without a reason + # - pkg: "reflect" + # desc: '`reflect` package is dangerous to use' + # - pkg: "unsafe" + # desc: '`unsafe` package is dangerous to use' + + errcheck: + check-type-assertions: true + check-blank: true + disable-default-exclusions: true + exclude-functions: + - '(*bytes.Buffer).Write' # always returns nil error + - '(*github.com/valyala/bytebufferpool.ByteBuffer).Write' # always returns nil error + - '(*github.com/valyala/bytebufferpool.ByteBuffer).WriteByte' # always returns nil error + - '(*github.com/valyala/bytebufferpool.ByteBuffer).WriteString' # always returns nil error + + errchkjson: + report-no-exported: true + + exhaustive: + default-signifies-exhaustive: true + + forbidigo: + forbid: + - pattern: ^print(ln)?$ + - pattern: ^fmt\.Print(f|ln)?$ + - pattern: ^http\.Default(Client|ServeMux|Transport)$ + # TODO: Eventually enable these patterns + # - pattern: ^panic$ + # - pattern: ^time\.Sleep$ + analyze-types: true + + goconst: + numbers: true + + gocritic: + # TODO: Uncomment the following lines + enabled-tags: + - diagnostic + # - style + # - performance + # - experimental + # - opinionated + settings: + captLocal: + paramsOnly: false + elseif: + skipBalanced: false + underef: + skipRecvDeref: false + # NOTE: Set this option to false if other projects rely on this project's code + # unnamedResult: + # checkExported: false + + gosec: + excludes: + - G104 # TODO: Enable this again. Mostly provided by errcheck + config: + global: + # show-ignored: true # TODO: Enable this + audit: true + + govet: + enable-all: true + disable: + - shadow + + grouper: + # const-require-grouping: true # TODO: Enable this + import-require-single-import: true + import-require-grouping: true + # var-require-grouping: true # TODO: Conflicts with gofumpt + + loggercheck: + require-string-key: true + no-printf-like: true + + misspell: + locale: US + + nolintlint: + require-explanation: true + require-specific: true + + nonamedreturns: + report-error-in-defer: true + + perfsprint: + err-error: true + + predeclared: + qualified-name: true + + promlinter: + strict: true + + # TODO: Enable this + # reassign: + # patterns: + # - '.*' + + revive: + enable-all-rules: true + rules: + # Provided by gomnd linter + - name: add-constant + disabled: true + - name: argument-limit + disabled: true + # Provided by bidichk + - name: banned-characters + disabled: true + - name: cognitive-complexity + disabled: true + - name: confusing-results + disabled: true + - name: comment-spacings + arguments: + - nolint + disabled: true # TODO: Do not disable + - name: cyclomatic + disabled: true + # TODO: Enable this check. Currently disabled due to upstream bug. + # - name: enforce-repeated-arg-type-style + # arguments: + # - short + - name: enforce-slice-style + arguments: + - make + disabled: true # TODO: Do not disable + - name: exported + disabled: true + - name: flag-parameter + disabled: true + - name: file-header + disabled: true + - name: function-result-limit + arguments: [3] + - name: function-length + disabled: true + - name: line-length-limit + disabled: true + - name: max-public-structs + disabled: true + - name: modifies-parameter + disabled: true + - name: nested-structs + disabled: true # TODO: Do not disable + - name: package-comments + disabled: true + - name: optimize-operands-order + disabled: true + - name: unchecked-type-assertion + disabled: true # TODO: Do not disable + - name: unhandled-error + disabled: true + + tagalign: + strict: true + + tagliatelle: + case: + rules: + json: snake + + testifylint: + enable-all: true + + testpackage: + skip-regexp: "^$" + + unparam: + # NOTE: Set this option to false if other projects rely on this project's code + check-exported: false + + unused: + # TODO: Uncomment these two lines + # parameters-are-used: false + # local-variables-are-used: false + # NOTE: Set these options to true if other projects rely on this project's code + field-writes-are-uses: true + # exported-is-used: true # TODO: Fix issues with this option (upstream) + exported-fields-are-used: true + + usestdlibvars: + http-method: true + http-status-code: true + time-weekday: false # TODO: Set to true + time-month: false # TODO: Set to true + time-layout: false # TODO: Set to true + crypto-hash: true + default-rpc-path: true + sql-isolation-level: true + tls-signature-scheme: true + constant-kind: true + + wrapcheck: + ignore-package-globs: + - github.com/gofiber/fiber/* + - github.com/valyala/fasthttp -linters: enable: - asasalint - asciicheck @@ -379,8 +330,47 @@ linters: # - wsl - zerologlint + exclusions: + paths: + - '_msgp\.go' + - '_msgp_test\.go' + rules: + - linters: + - err113 + text: 'do not define dynamic errors, use wrapped static errors instead*' + - path: log/.*\.go + linters: + - depguard + # Exclude some linters from running on tests files. + - path: _test\.go + linters: + - bodyclose + - err113 + - revive + - source: 'fmt.Fprintf?' + linters: + - errcheck + - revive + +issues: + max-issues-per-linter: 0 + max-same-issues: 0 + formatters: enable: - gofmt - gofumpt - gci + settings: + gofumpt: + module-path: github.com/gofiber/cli + extra-rules: true + gci: + sections: + - standard + - default + - blank + - dot + #- alias + - prefix(github.com/gofiber) + custom-order: true From ffaa0bb8249f3dd7995c98cb0d0f666494d5a1cd Mon Sep 17 00:00:00 2001 From: RW Date: Fri, 21 Nov 2025 11:40:48 +0100 Subject: [PATCH 4/5] Fix lint findings for golangci-lint v2 --- cmd/dev_test.go | 52 +++++++++---------- cmd/fileserver/app/app.go | 2 +- cmd/fileserver/app/app_test.go | 2 +- cmd/internal/migrations/exec_stub_test.go | 3 +- cmd/internal/migrations/lists_test.go | 2 +- cmd/internal/migrations/v3/add_method.go | 2 +- cmd/internal/migrations/v3/common.go | 10 +++- .../migrations/v3/config_listener_fields.go | 4 +- cmd/internal/migrations/v3/listen_methods.go | 2 +- cmd/internal/migrations/v3/parser_methods.go | 8 +-- cmd/internal/prompt.go | 6 +-- cmd/migrate.go | 2 + cmd/migrate_test.go | 9 ++-- cmd/root.go | 2 + cmd/root_test.go | 2 +- cmd/tester_test.go | 3 +- 16 files changed, 62 insertions(+), 49 deletions(-) diff --git a/cmd/dev_test.go b/cmd/dev_test.go index 0cf9a71..b7df490 100644 --- a/cmd/dev_test.go +++ b/cmd/dev_test.go @@ -68,7 +68,7 @@ func Test_Dev_Escort_RunBin(t *testing.T) { e := getEscort() - e.bin = exec.Command("go", "version") + e.bin = exec.CommandContext(e.ctx, "go", "version") _, err := e.bin.CombinedOutput() require.NoError(t, err) @@ -83,7 +83,7 @@ func Test_Dev_Escort_WatchingPipes(t *testing.T) { t.Parallel() e := getEscort() - e.bin = exec.Command("go", "version") + e.bin = exec.CommandContext(e.ctx, "go", "version") _, err := e.bin.CombinedOutput() require.NoError(t, err) e.watchingPipes() @@ -235,20 +235,20 @@ func Test_Dev_IsRemoved(t *testing.T) { t.Parallel() cases := []struct { - fsnotify.Op + op fsnotify.Op bool }{ - {fsnotify.Create, false}, - {fsnotify.Write, false}, - {fsnotify.Remove, true}, - {fsnotify.Rename, false}, - {fsnotify.Chmod, false}, + {op: fsnotify.Create, bool: false}, + {op: fsnotify.Write, bool: false}, + {op: fsnotify.Remove, bool: true}, + {op: fsnotify.Rename, bool: false}, + {op: fsnotify.Chmod, bool: false}, } for _, tc := range cases { - t.Run(tc.Op.String(), func(t *testing.T) { + t.Run(tc.op.String(), func(t *testing.T) { t.Parallel() - assert.Equal(t, tc.bool, isRemoved(tc.Op)) + assert.Equal(t, tc.bool, isRemoved(tc.op)) }) } } @@ -257,20 +257,20 @@ func Test_Dev_IsCreated(t *testing.T) { t.Parallel() cases := []struct { - fsnotify.Op + op fsnotify.Op bool }{ - {fsnotify.Create, true}, - {fsnotify.Write, false}, - {fsnotify.Remove, false}, - {fsnotify.Rename, false}, - {fsnotify.Chmod, false}, + {op: fsnotify.Create, bool: true}, + {op: fsnotify.Write, bool: false}, + {op: fsnotify.Remove, bool: false}, + {op: fsnotify.Rename, bool: false}, + {op: fsnotify.Chmod, bool: false}, } for _, tc := range cases { - t.Run(tc.Op.String(), func(t *testing.T) { + t.Run(tc.op.String(), func(t *testing.T) { t.Parallel() - assert.Equal(t, tc.bool, isCreated(tc.Op)) + assert.Equal(t, tc.bool, isCreated(tc.op)) }) } } @@ -279,20 +279,20 @@ func Test_Dev_IsChmoded(t *testing.T) { t.Parallel() cases := []struct { - fsnotify.Op + op fsnotify.Op bool }{ - {fsnotify.Create, false}, - {fsnotify.Write, false}, - {fsnotify.Remove, false}, - {fsnotify.Rename, false}, - {fsnotify.Chmod, true}, + {op: fsnotify.Create, bool: false}, + {op: fsnotify.Write, bool: false}, + {op: fsnotify.Remove, bool: false}, + {op: fsnotify.Rename, bool: false}, + {op: fsnotify.Chmod, bool: true}, } for _, tc := range cases { - t.Run(tc.Op.String(), func(t *testing.T) { + t.Run(tc.op.String(), func(t *testing.T) { t.Parallel() - assert.Equal(t, tc.bool, isChmoded(tc.Op)) + assert.Equal(t, tc.bool, isChmoded(tc.op)) }) } } diff --git a/cmd/fileserver/app/app.go b/cmd/fileserver/app/app.go index 510acf4..9a98ff1 100644 --- a/cmd/fileserver/app/app.go +++ b/cmd/fileserver/app/app.go @@ -1,4 +1,4 @@ -package fileserver +package app import ( "strings" diff --git a/cmd/fileserver/app/app_test.go b/cmd/fileserver/app/app_test.go index bec4846..5f0c59c 100644 --- a/cmd/fileserver/app/app_test.go +++ b/cmd/fileserver/app/app_test.go @@ -1,4 +1,4 @@ -package fileserver +package app import ( "io" diff --git a/cmd/internal/migrations/exec_stub_test.go b/cmd/internal/migrations/exec_stub_test.go index e24ea13..9c06f41 100644 --- a/cmd/internal/migrations/exec_stub_test.go +++ b/cmd/internal/migrations/exec_stub_test.go @@ -1,6 +1,7 @@ package migrations_test import ( + "context" "fmt" "os" "os/exec" @@ -18,7 +19,7 @@ func stubFiberDownload(t *testing.T, fiberGoMod string) func() { orig := migrations.ExecCommand out := fmt.Sprintf(`{"GoMod":%q}`, filepath.ToSlash(fiberGoMod)) migrations.ExecCommand = func(string, ...string) *exec.Cmd { - cmd := exec.Command(os.Args[0], "-test.run=TestHelperProcess", "--") // #nosec G204 -- test helper + cmd := exec.CommandContext(context.Background(), os.Args[0], "-test.run=TestHelperProcess", "--") // #nosec G204 -- test helper cmd.Env = []string{ "GO_WANT_HELPER_PROCESS=1", "GO_HELPER_STDOUT=" + out, diff --git a/cmd/internal/migrations/lists_test.go b/cmd/internal/migrations/lists_test.go index 40e48a4..53aaad3 100644 --- a/cmd/internal/migrations/lists_test.go +++ b/cmd/internal/migrations/lists_test.go @@ -27,7 +27,7 @@ func Test_DoMigration_Verbose(t *testing.T) { cmd := &cobra.Command{} cmd.SetOut(&buf) require.NoError(t, migrations.DoMigration(cmd, dir, curr, target, true, false, nil, nil)) - assert.Equal(t, "", buf.String()) + assert.Empty(t, buf.String()) }) t.Run("verbose", func(t *testing.T) { diff --git a/cmd/internal/migrations/v3/add_method.go b/cmd/internal/migrations/v3/add_method.go index 8c2e538..76ca692 100644 --- a/cmd/internal/migrations/v3/add_method.go +++ b/cmd/internal/migrations/v3/add_method.go @@ -37,7 +37,7 @@ func MigrateAddMethod(cmd *cobra.Command, cwd string, _, _ *semver.Version) erro identStart := startCall - 1 for identStart >= 0 { ch := content[identStart] - if !((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9') || ch == '_') { + if !isIdentifierChar(ch) { break } identStart-- diff --git a/cmd/internal/migrations/v3/common.go b/cmd/internal/migrations/v3/common.go index 82996e8..7a99f81 100644 --- a/cmd/internal/migrations/v3/common.go +++ b/cmd/internal/migrations/v3/common.go @@ -12,6 +12,10 @@ var ( b64Re = regexp.MustCompile(`^[A-Za-z0-9+/]{43}=?$`) ) +func isIdentifierChar(ch byte) bool { + return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9') || ch == '_' +} + // skipCommaSuffix advances the index past a comma and any trailing // whitespace, comments, or newline characters. func skipCommaSuffix(src string, i int) int { @@ -34,7 +38,7 @@ func skipCommaSuffix(src string, i int) int { } if src[i+1] == '*' { // block comment i += 2 - for i+1 < len(src) && !(src[i] == '*' && src[i+1] == '/') { + for i+1 < len(src) && (src[i] != '*' || src[i+1] != '/') { i++ } if i+1 < len(src) { @@ -134,6 +138,7 @@ func removeConfigField(src, field string) string { i++ src = src[:start] + src[i:] goto nextField + default: } i++ } @@ -238,6 +243,7 @@ func splitArgs(src string) []string { args = append(args, strings.TrimSpace(src[start:i])) start = i + 1 } + default: } } @@ -278,6 +284,7 @@ func extractCall(src string, start int) (int, string) { if depth == 0 { return i + 1, src[start:i] } + default: } } return len(src), src[start:] @@ -318,6 +325,7 @@ func extractBlock(src string, start int, open, closeDelim byte) int { if depth == 0 { return i + 1 } + default: } } return len(src) diff --git a/cmd/internal/migrations/v3/config_listener_fields.go b/cmd/internal/migrations/v3/config_listener_fields.go index c6dd888..9da7a21 100644 --- a/cmd/internal/migrations/v3/config_listener_fields.go +++ b/cmd/internal/migrations/v3/config_listener_fields.go @@ -45,6 +45,8 @@ func MigrateConfigListenerFields(cmd *cobra.Command, cwd string, _, _ *semver.Ve if enablePrint == "" { enablePrint = val } + default: + // no-op } return "" } @@ -151,7 +153,7 @@ func MigrateConfigListenerFields(cmd *cobra.Command, cwd string, _, _ *semver.Ve if err != nil { return fmt.Errorf("failed to migrate listener related listen calls: %w", err) } - if !(changed1 || changed2) { + if !changed1 && !changed2 { return nil } diff --git a/cmd/internal/migrations/v3/listen_methods.go b/cmd/internal/migrations/v3/listen_methods.go index 7957e55..ad14c92 100644 --- a/cmd/internal/migrations/v3/listen_methods.go +++ b/cmd/internal/migrations/v3/listen_methods.go @@ -38,7 +38,7 @@ func MigrateListenMethods(cmd *cobra.Command, cwd string, _, _ *semver.Version) identStart := startCall - 1 for identStart >= 0 { ch := content[identStart] - if !((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9') || ch == '_') { + if !isIdentifierChar(ch) { break } identStart-- diff --git a/cmd/internal/migrations/v3/parser_methods.go b/cmd/internal/migrations/v3/parser_methods.go index 64bb10a..5964b26 100644 --- a/cmd/internal/migrations/v3/parser_methods.go +++ b/cmd/internal/migrations/v3/parser_methods.go @@ -38,7 +38,7 @@ func MigrateParserMethods(cmd *cobra.Command, cwd string, _, _ *semver.Version) identStart := startCall - 1 for identStart >= 0 { ch := content[identStart] - if !((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9') || ch == '_') { + if !isIdentifierChar(ch) { break } identStart-- @@ -49,16 +49,16 @@ func MigrateParserMethods(cmd *cobra.Command, cwd string, _, _ *semver.Version) if isFiberCtx(orig, ident) { var repl string switch method { - case "AllParams": + case "AllParams", "ParamsParser": repl = ".Bind().URI(" case "BodyParser": repl = ".Bind().Body(" case "CookieParser": repl = ".Bind().Cookie(" - case "ParamsParser": - repl = ".Bind().URI(" case "QueryParser": repl = ".Bind().Query(" + default: + return content } if _, err := b.WriteString(repl + inner + ")"); err != nil { return content diff --git a/cmd/internal/prompt.go b/cmd/internal/prompt.go index 72bf145..eab1189 100644 --- a/cmd/internal/prompt.go +++ b/cmd/internal/prompt.go @@ -81,11 +81,7 @@ func (p *Prompt) Update(msg tea.Msg) (tea.Model, tea.Cmd) { switch msg := msg.(type) { case tea.KeyMsg: switch msg.Type { - case tea.KeyCtrlC: - fallthrough - case tea.KeyEsc: - fallthrough - case tea.KeyEnter: + case tea.KeyCtrlC, tea.KeyEsc, tea.KeyEnter: p.answer = p.textInput.Value() return p, tea.Quit default: diff --git a/cmd/migrate.go b/cmd/migrate.go index 2ee2472..49bc1de 100644 --- a/cmd/migrate.go +++ b/cmd/migrate.go @@ -164,6 +164,8 @@ func migrateRunE(cmd *cobra.Command, opts MigrateOptions) error { changed, err = refreshStorage(cmd, wd, tp.Hash) case "template", "templates": changed, err = refreshTemplates(cmd, wd, tp.Hash) + default: + continue } if err != nil { return fmt.Errorf("refresh %s packages: %w", tp.Name, err) diff --git a/cmd/migrate_test.go b/cmd/migrate_test.go index df62cdd..540cb59 100644 --- a/cmd/migrate_test.go +++ b/cmd/migrate_test.go @@ -1,6 +1,7 @@ package cmd import ( + "context" "fmt" "net/http" "os" @@ -41,7 +42,7 @@ require github.com/valyala/fasthttp v1.0.0` } migrations.ExecCommand = func(string, ...string) *exec.Cmd { - cmd := exec.Command(os.Args[0], "-test.run=TestHelperProcess", "--", "go", "mod", "download") // #nosec G204 -- test helper + cmd := exec.CommandContext(context.Background(), os.Args[0], "-test.run=TestHelperProcess", "--", "go", "mod", "download") // #nosec G204 -- test helper cmd.Env = []string{ "GO_WANT_HELPER_PROCESS=1", "GO_HELPER_STDOUT=" + fmt.Sprintf(`{"GoMod":%q}`, filepath.ToSlash(fiberGoMod)), @@ -215,7 +216,7 @@ require github.com/gofiber/fiber/v2 v2.0.0` var cmds []*exec.Cmd cmdinternal.ExecCommand = func(name string, args ...string) *exec.Cmd { cs := append([]string{"-test.run=TestHelperProcess", "--", name}, args...) - cmd := exec.Command(os.Args[0], cs...) // #nosec G204 -- safe for test + cmd := exec.CommandContext(context.Background(), os.Args[0], cs...) // #nosec G204 -- safe for test env := []string{"GO_WANT_HELPER_PROCESS=1"} if needError { env = append(env, "GO_WANT_HELPER_NEED_ERR=1") @@ -273,7 +274,7 @@ require github.com/gofiber/fiber/v3 v3.0.0 var cmds []*exec.Cmd fake := func(name string, args ...string) *exec.Cmd { cs := append([]string{"-test.run=TestHelperProcess", "--", name}, args...) - cmd := exec.Command(os.Args[0], cs...) // #nosec G204 -- safe for test + cmd := exec.CommandContext(context.Background(), os.Args[0], cs...) // #nosec G204 -- safe for test cmd.Env = []string{"GO_WANT_HELPER_PROCESS=1"} cmds = append(cmds, cmd) return cmd @@ -299,7 +300,7 @@ require github.com/gofiber/fiber/v3 v3.0.0 var cmds []*exec.Cmd fake := func(name string, args ...string) *exec.Cmd { cs := append([]string{"-test.run=TestHelperProcess", "--", name}, args...) - cmd := exec.Command(os.Args[0], cs...) // #nosec G204 -- safe for test + cmd := exec.CommandContext(context.Background(), os.Args[0], cs...) // #nosec G204 -- safe for test cmd.Env = []string{"GO_WANT_HELPER_PROCESS=1"} cmds = append(cmds, cmd) return cmd diff --git a/cmd/root.go b/cmd/root.go index c98cb35..3e12fa1 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -52,6 +52,8 @@ func getVersion() string { version = setting.Value[:7] // short commit hash return version } + default: + continue } } diff --git a/cmd/root_test.go b/cmd/root_test.go index c91bd10..bcaa148 100644 --- a/cmd/root_test.go +++ b/cmd/root_test.go @@ -173,7 +173,7 @@ func Test_GetVersionFallback(t *testing.T) { v := getVersion() // With runtime/debug.ReadBuildInfo(), the result depends on how the test is built // It could be module version, VCS tag, VCS revision, or "unknown" - assert.NotEqual(t, "", v) + assert.NotEmpty(t, v) // Test that caching works version = "cached-version" diff --git a/cmd/tester_test.go b/cmd/tester_test.go index c962588..c945ff1 100644 --- a/cmd/tester_test.go +++ b/cmd/tester_test.go @@ -2,6 +2,7 @@ package cmd import ( "bytes" + "context" "errors" "fmt" "os" @@ -24,7 +25,7 @@ func fakeExecCommand(command string, args ...string) *exec.Cmd { cs := []string{"-test.run=TestHelperProcess", "--", command} cs = append(cs, args...) // #nosec G204 -- safe for test, args are controlled - cmd := exec.Command(os.Args[0], cs...) + cmd := exec.CommandContext(context.Background(), os.Args[0], cs...) cmd.Env = []string{"GO_WANT_HELPER_PROCESS=1"} if needError { cmd.Env = append(cmd.Env, "GO_WANT_HELPER_NEED_ERR=1") From 8f002424e7b4aab0cd843fd571da54e7fb13ce99 Mon Sep 17 00:00:00 2001 From: RW Date: Fri, 21 Nov 2025 12:09:14 +0100 Subject: [PATCH 5/5] Add no-change monitor import test --- .../migrations/v3/contrib_packages_test.go | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 cmd/internal/migrations/v3/contrib_packages_test.go diff --git a/cmd/internal/migrations/v3/contrib_packages_test.go b/cmd/internal/migrations/v3/contrib_packages_test.go new file mode 100644 index 0000000..76ccad6 --- /dev/null +++ b/cmd/internal/migrations/v3/contrib_packages_test.go @@ -0,0 +1,33 @@ +package v3_test + +import ( + "bytes" + "os" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/gofiber/cli/cmd/internal/migrations/v3" +) + +func Test_MigrateMonitorImport_NoChanges(t *testing.T) { + t.Parallel() + + dir, err := os.MkdirTemp("", "contrib") + require.NoError(t, err) + defer func() { require.NoError(t, os.RemoveAll(dir)) }() + + file := writeTempFile(t, dir, `package main +import "github.com/gofiber/contrib/monitor" +var _ = monitor.New()`) + initial := readFile(t, file) + + var buf bytes.Buffer + cmd := newCmd(&buf) + + require.NoError(t, v3.MigrateMonitorImport(cmd, dir, nil, nil)) + + assert.Equal(t, initial, readFile(t, file)) + assert.Empty(t, buf.String()) +}