diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 66f76aeda..f585ff6ec 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -8,6 +8,9 @@ on: branches: - master +env: + GOTOOLCHAIN: local + jobs: lint: @@ -18,26 +21,27 @@ jobs: platform: [ubuntu-latest] runs-on: ${{ matrix.platform }} steps: - - uses: actions/checkout@v2 - - uses: golangci/golangci-lint-action@v2 + - name: Install Go + uses: actions/setup-go@v5 with: - # must be specified without patch version - version: v1.46 + go-version: stable + - uses: actions/checkout@v4 + - uses: golangci/golangci-lint-action@v8 cross: name: Cross timeout-minutes: 10 strategy: matrix: - go-version: [1.17.x] + go-version: [stable] platform: [ubuntu-latest] runs-on: ${{ matrix.platform }} steps: - name: Install Go - uses: actions/setup-go@v2 + uses: actions/setup-go@v5 with: go-version: ${{ matrix.go-version }} - name: Checkout code - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Cross working-directory: ci run: go run mage.go -v -w ../ crossBuild @@ -47,15 +51,15 @@ jobs: timeout-minutes: 10 strategy: matrix: - go-version: [1.17.x] + go-version: [stable, oldstable, 1.17.x] platform: [ubuntu-latest, windows-latest] runs-on: ${{ matrix.platform }} steps: - name: Install Go - uses: actions/setup-go@v2 + uses: actions/setup-go@v5 with: go-version: ${{ matrix.go-version }} - name: Checkout code - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Test run: go test -race -v ./... diff --git a/.github/workflows/stale.yaml b/.github/workflows/stale.yaml index 246c34d31..a7e06df93 100644 --- a/.github/workflows/stale.yaml +++ b/.github/workflows/stale.yaml @@ -10,7 +10,7 @@ jobs: issues: write pull-requests: write steps: - - uses: actions/stale@v3 + - uses: actions/stale@v9 with: days-before-issue-stale: 30 days-before-issue-close: 14 diff --git a/.golangci.yml b/.golangci.yml index 65dc28503..792db3618 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,40 +1,67 @@ +version: "2" run: - # do not run on test files yet tests: false - -# all available settings of specific linters -linters-settings: - errcheck: - # report about not checking of errors in type assetions: `a := b.(MyStruct)`; - # default is false: such cases aren't reported by default. - check-type-assertions: false - - # report about assignment of errors to blank identifier: `num, _ := strconv.Atoi(numStr)`; - # default is false: such cases aren't reported by default. - check-blank: false - - lll: - line-length: 100 - tab-width: 4 - - prealloc: - simple: false - range-loops: false - for-loops: false - - whitespace: - multi-if: false # Enforces newlines (or comments) after every multi-line if statement - multi-func: false # Enforces newlines (or comments) after every multi-line function signature - linters: enable: - - megacheck - - govet + - asasalint + - asciicheck + - bidichk + - bodyclose + - contextcheck + - durationcheck + - errchkjson + - errorlint + - exhaustive + - gocheckcompilerdirectives + - gochecksumtype + - gosec + - gosmopolitan + - loggercheck + - makezero + - musttag + - nilerr + - nilnesserr + - noctx + - protogetter + - reassign + - recvcheck + - rowserrcheck + - spancheck + - sqlclosecheck + - testifylint + - unparam + - zerologlint disable: - - maligned - prealloc - disable-all: false - presets: - - bugs - - unused - fast: false + settings: + errcheck: + check-type-assertions: false + check-blank: false + lll: + line-length: 100 + tab-width: 4 + prealloc: + simple: false + range-loops: false + for-loops: false + whitespace: + multi-if: false + multi-func: false + exclusions: + generated: lax + presets: + - comments + - common-false-positives + - legacy + - std-error-handling + paths: + - third_party$ + - builtin$ + - examples$ +formatters: + exclusions: + generated: lax + paths: + - third_party$ + - builtin$ + - examples$ diff --git a/entry.go b/entry.go index 71cdbbc35..13922cde3 100644 --- a/entry.go +++ b/entry.go @@ -41,6 +41,8 @@ var ErrorKey = "error" // the fields passed with WithField{,s}. It's finally logged when Trace, Debug, // Info, Warn, Error, Fatal or Panic is called on it. These objects can be // reused and passed around as much as you wish to avoid field duplication. +// +//nolint:recvcheck // the methods of "Entry" use pointer receiver and non-pointer receiver. type Entry struct { Logger *Logger @@ -204,7 +206,7 @@ func getCaller() *runtime.Frame { // If the caller isn't part of this package, we're done if pkg != logrusPackage { - return &f //nolint:scopelint + return &f } } diff --git a/internal/testutils/testutils.go b/internal/testutils/testutils.go index 6e3a6203e..a0ace27f5 100644 --- a/internal/testutils/testutils.go +++ b/internal/testutils/testutils.go @@ -7,7 +7,7 @@ import ( "strings" "testing" - . "github.com/sirupsen/logrus" + . "github.com/sirupsen/logrus" //nolint:staticcheck "github.com/stretchr/testify/require" ) @@ -23,7 +23,7 @@ func LogAndAssertJSON(t *testing.T, log func(*Logger), assertions func(fields Fi log(logger) err := json.Unmarshal(buffer.Bytes(), &fields) - require.Nil(t, err) + require.NoError(t, err) assertions(fields) } diff --git a/logrus.go b/logrus.go index 2f16224cb..457a60d4b 100644 --- a/logrus.go +++ b/logrus.go @@ -10,6 +10,8 @@ import ( type Fields map[string]interface{} // Level type +// +//nolint:recvcheck // the methods of "Entry" use pointer receiver and non-pointer receiver. type Level uint32 // Convert the Level to a string. E.g. PanicLevel becomes "panic". diff --git a/text_formatter.go b/text_formatter.go index be2c6efe5..6dfeb18b1 100644 --- a/text_formatter.go +++ b/text_formatter.go @@ -306,6 +306,7 @@ func (f *TextFormatter) needsQuoting(text string) bool { return false } for _, ch := range text { + //nolint:staticcheck // QF1001: could apply De Morgan's law if !((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9') || @@ -334,6 +335,6 @@ func (f *TextFormatter) appendValue(b *bytes.Buffer, value interface{}) { if !f.needsQuoting(stringVal) { b.WriteString(stringVal) } else { - b.WriteString(fmt.Sprintf("%q", stringVal)) + fmt.Fprintf(b, "%q", stringVal) } } diff --git a/writer_test.go b/writer_test.go index 5b6261bd1..d01f0bfc8 100644 --- a/writer_test.go +++ b/writer_test.go @@ -6,6 +6,7 @@ import ( "log" "net/http" "strings" + "sync" "testing" "time" @@ -39,8 +40,33 @@ func ExampleLogger_Writer_stdlib() { log.SetOutput(logger.Writer()) } +type bufferWithMu struct { + buf *bytes.Buffer + mu sync.RWMutex +} + +func (b *bufferWithMu) Write(p []byte) (int, error) { + b.mu.Lock() + defer b.mu.Unlock() + return b.buf.Write(p) +} + +func (b *bufferWithMu) Read(p []byte) (int, error) { + b.mu.RLock() + defer b.mu.RUnlock() + return b.buf.Read(p) +} + +func (b *bufferWithMu) String() string { + b.mu.RLock() + defer b.mu.RUnlock() + return b.buf.String() +} + func TestWriterSplitNewlines(t *testing.T) { - buf := bytes.NewBuffer(nil) + buf := &bufferWithMu{ + buf: bytes.NewBuffer(nil), + } logger := logrus.New() logger.Formatter = &logrus.TextFormatter{ DisableColors: true, @@ -65,7 +91,9 @@ func TestWriterSplitNewlines(t *testing.T) { } func TestWriterSplitsMax64KB(t *testing.T) { - buf := bytes.NewBuffer(nil) + buf := &bufferWithMu{ + buf: bytes.NewBuffer(nil), + } logger := logrus.New() logger.Formatter = &logrus.TextFormatter{ DisableColors: true,