diff --git a/.codecov.yml b/.codecov.yml deleted file mode 100644 index 0e9b4e1..0000000 --- a/.codecov.yml +++ /dev/null @@ -1,26 +0,0 @@ -# Docs: - -coverage: - # coverage lower than 50 is red, higher than 90 green - range: 30..80 - - status: - project: - default: - # Choose a minimum coverage ratio that the commit must meet to be considered a success. - # - # `auto` will use the coverage from the base commit (pull request base or parent commit) coverage to compare - # against. - target: auto - - # Allow the coverage to drop by X%, and posting a success status. - threshold: 5% - - # Resulting status will pass no matter what the coverage is or what other settings are specified. - informational: true - - patch: - default: - target: auto - threshold: 5% - informational: true diff --git a/.editorconfig b/.editorconfig index df1c513..27a58b5 100644 --- a/.editorconfig +++ b/.editorconfig @@ -10,5 +10,9 @@ indent_style = space indent_size = 2 trim_trailing_whitespace = true +[{*.yml,*.yaml}] +ij_any_spaces_within_braces = false +ij_any_spaces_within_brackets = false + [{Makefile,go.mod,*.go}] indent_style = tab diff --git a/.github/release.yml b/.github/release.yml new file mode 100644 index 0000000..2a0b405 --- /dev/null +++ b/.github/release.yml @@ -0,0 +1,13 @@ +# yaml-language-server: $schema=https://json.schemastore.org/github-release-config.json +# docs: https://docs.github.com/en/repositories/releasing-projects-on-github/automatically-generated-release-notes + +changelog: + categories: + - title: ๐Ÿ›  Fixes + labels: [type:fix, type:bug] + - title: ๐Ÿš€ Features + labels: [type:feature, type:feature_request] + - title: ๐Ÿ“ฆ Dependency updates + labels: [dependencies] + - title: Other Changes + labels: ['*'] diff --git a/.github/workflows/dependabot.yml b/.github/workflows/dependabot.yml index 1a9f9cc..53955f6 100644 --- a/.github/workflows/dependabot.yml +++ b/.github/workflows/dependabot.yml @@ -1,4 +1,7 @@ -name: dependabot +# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json +# docs: https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions + +name: ๐Ÿค– Dependabot on: pull_request: {} @@ -9,6 +12,7 @@ permissions: jobs: dependabot: # https://tinyurl.com/e69djmen + name: Enable auto-merge for Dependabot PRs runs-on: ubuntu-latest if: ${{ github.actor == 'dependabot[bot]' }} steps: @@ -16,10 +20,8 @@ jobs: id: metadata with: {github-token: "${{ secrets.GITHUB_TOKEN }}"} - - name: Enable auto-merge for Dependabot PRs - if: ${{ contains(fromJSON('["version-update:semver-minor", "version-update:semver-patch"]'), steps.metadata.outputs.update-type) }} + - if: ${{ contains(fromJSON('["version-update:semver-minor", "version-update:semver-patch"]'), steps.metadata.outputs.update-type) }} run: gh pr merge --auto --merge "$PR_URL" - continue-on-error: true env: PR_URL: ${{ github.event.pull_request.html_url }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml index 8de6f77..bfcd498 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/documentation.yml @@ -1,4 +1,7 @@ -name: documentation +# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json +# docs: https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions + +name: ๐Ÿ“š Documentation on: push: @@ -12,7 +15,7 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: peter-evans/dockerhub-description@v4 # Action page: + - uses: peter-evans/dockerhub-description@v4 with: username: ${{ secrets.DOCKER_LOGIN }} password: ${{ secrets.DOCKER_USER_PASSWORD }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 996aed4..02e6d17 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,4 +1,7 @@ -name: release +# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json +# docs: https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions + +name: ๐Ÿš€ Release on: release: # Docs: @@ -20,24 +23,16 @@ jobs: arch: 386 steps: - uses: actions/checkout@v4 - - - uses: gacts/setup-go-with-cache@v1 - with: {go-version-file: go.mod} - + - {uses: actions/setup-go@v5, with: {go-version-file: go.mod}} - {uses: gacts/github-slug@v1, id: slug} - - - name: Generate builder values - id: values + - id: values run: echo "binary-name=tinifier-${{ matrix.os }}-${{ matrix.arch }}`[ ${{ matrix.os }} = 'windows' ] && echo '.exe'`" >> $GITHUB_OUTPUT - - - name: Build application - env: + - env: GOOS: ${{ matrix.os }} GOARCH: ${{ matrix.arch }} CGO_ENABLED: 0 LDFLAGS: -s -w -X gh.tarampamp.am/tinifier/v4/internal/version.version=${{ steps.slug.outputs.version }} run: go build -trimpath -ldflags "$LDFLAGS" -o "./${{ steps.values.outputs.binary-name }}" ./cmd/tinifier/ - - uses: svenstaro/upload-release-action@v2 with: repo_token: ${{ secrets.GITHUB_TOKEN }} @@ -50,24 +45,18 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - {uses: gacts/github-slug@v1, id: slug} - - uses: docker/setup-qemu-action@v3 - - uses: docker/setup-buildx-action@v3 - - uses: docker/login-action@v3 with: username: ${{ secrets.DOCKER_LOGIN }} password: ${{ secrets.DOCKER_PASSWORD }} - - uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - - uses: docker/build-push-action@v6 with: context: . @@ -93,11 +82,8 @@ jobs: - https://goproxy.dev steps: - uses: actions/setup-go@v5 - - {uses: gacts/github-slug@v1, id: slug} - - run: go mod init example - - name: Get the module using proxy env: {GOPROXY: '${{ matrix.proxy }}'} run: go get -v -x -u "gh.tarampamp.am/tinifier/v4@${{ steps.slug.outputs.tag-name }}" diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 6c78c4c..29b3531 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -1,4 +1,7 @@ -name: tests +# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json +# docs: https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions + +name: ๐Ÿงช Tests on: push: @@ -14,43 +17,27 @@ concurrency: jobs: gitleaks: - name: Gitleaks + name: Check for GitLeaks runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - with: {fetch-depth: 0} - + - {uses: actions/checkout@v4, with: {fetch-depth: 0}} - uses: gacts/gitleaks@v1 golangci-lint: - name: Golang-CI (lint) + name: Run golangci-lint runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - - uses: gacts/setup-go-with-cache@v1 - - - uses: golangci/golangci-lint-action@v6 # Action page: - with: {skip-pkg-cache: true, skip-build-cache: true} + - {uses: actions/setup-go@v5, with: {go-version-file: go.mod}} + - uses: golangci/golangci-lint-action@v6 go-test: name: Unit tests runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - with: {fetch-depth: 2} # Fixes codecov error 'Issue detecting commit SHA' - - - uses: gacts/setup-go-with-cache@v1 - with: {go-version-file: go.mod} - - - run: go test -race -covermode=atomic -coverprofile /tmp/coverage.txt ./... - - - continue-on-error: true - uses: codecov/codecov-action@v4 # https://github.com/codecov/codecov-action - with: - token: ${{ secrets.CODECOV_TOKEN }} - file: /tmp/coverage.txt - fail_ci_if_error: false + - {uses: actions/setup-go@v5, with: {go-version-file: go.mod}} + - run: go test -race ./... build: name: Build for ${{ matrix.os }} (${{ matrix.arch }}) @@ -66,24 +53,17 @@ jobs: needs: [golangci-lint, go-test] steps: - uses: actions/checkout@v4 - - - uses: gacts/setup-go-with-cache@v1 - with: {go-version-file: go.mod} - + - {uses: actions/setup-go@v5, with: {go-version-file: go.mod}} - {uses: gacts/github-slug@v1, id: slug} - - - name: Build application - env: + - env: GOOS: ${{ matrix.os }} GOARCH: ${{ matrix.arch }} CGO_ENABLED: 0 LDFLAGS: -s -w -X gh.tarampamp.am/tinifier/v4/internal/version.version=${{ steps.slug.outputs.branch-name-slug }}@${{ steps.slug.outputs.commit-hash-short }} run: go build -trimpath -ldflags "$LDFLAGS" -o /tmp/tinifier ./cmd/tinifier/ - - name: Try to execute if: matrix.os == 'linux' run: /tmp/tinifier --version && /tmp/tinifier -h - - uses: actions/upload-artifact@v4 with: name: tinifier-${{ matrix.os }}-${{ matrix.arch }} @@ -97,14 +77,10 @@ jobs: needs: [golangci-lint, go-test] steps: - uses: actions/checkout@v4 - - {uses: gacts/github-slug@v1, id: slug} - - - name: Build image + - name: Build the image run: docker build -t tinifier:local --build-arg "APP_VERSION=${{ steps.slug.outputs.branch-name-slug }}@${{ steps.slug.outputs.commit-hash-short }}" -f ./Dockerfile . - - run: docker run --rm tinifier:local --version - - uses: anchore/scan-action@v4 # action page: with: image: tinifier:local diff --git a/.golangci.yml b/.golangci.yml index f597fef..93a5c47 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,26 +1,32 @@ -# Documentation: +# yaml-language-server: $schema=https://golangci-lint.run/jsonschema/golangci.jsonschema.json +# docs: https://github.com/golangci/golangci-lint#config-file run: - timeout: 1m - skip-dirs: - - .github - - .git - - tmp - - temp + timeout: 2m modules-download-mode: readonly allow-parallel-runners: true output: - format: colored-line-number # colored-line-number|line-number|json|tab|checkstyle|code-climate + formats: [{format: colored-line-number}] # colored-line-number|line-number|json|tab|checkstyle|code-climate linters-settings: + gci: + sections: + - standard + - default + - prefix(gh.tarampamp.am/tinifier) + gofmt: + simplify: false + rewrite-rules: + - { pattern: 'interface{}', replacement: 'any' } govet: - check-shadowing: true + enable: + - shadow gocyclo: min-complexity: 15 godot: scope: declarations - capital: true + capital: false dupl: threshold: 100 goconst: @@ -28,6 +34,7 @@ linters-settings: min-occurrences: 3 misspell: locale: US + ignore-words: [cancelled] lll: line-length: 120 forbidigo: @@ -38,8 +45,11 @@ linters-settings: range-loops: true for-loops: true nolintlint: - allow-leading-space: false require-specific: true + nakedret: + # Make an issue if func has more lines of code than this setting, and it has naked returns. + # Default: 30 + max-func-lines: 100 linters: # All available linters list: disable-all: true @@ -51,17 +61,19 @@ linters: # All available linters list: + image: golang:1.22-buster # Image page: working_dir: /src environment: HOME: /tmp @@ -20,7 +15,7 @@ services: security_opt: [no-new-privileges:true] golint: - image: golangci/golangci-lint:v1.59-alpine # Image page: + image: golangci/golangci-lint:v1.60-alpine # Image page: environment: GOLANGCI_LINT_CACHE: /tmp/golint # volumes: @@ -29,3 +24,8 @@ services: - golint-cache:/tmp/golint:rw working_dir: /src security_opt: [no-new-privileges:true] + +volumes: + tmp-data: {} + golint-go: {} + golint-cache: {} diff --git a/go.mod b/go.mod index b381fb1..94acb64 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module gh.tarampamp.am/tinifier/v4 -go 1.21 +go 1.22 require ( github.com/dustin/go-humanize v1.0.1 diff --git a/internal/cli/compress/command.go b/internal/cli/compress/command.go index 048e204..4aec33f 100644 --- a/internal/cli/compress/command.go +++ b/internal/cli/compress/command.go @@ -12,7 +12,7 @@ import ( "sync" "time" - humanize "github.com/dustin/go-humanize" + "github.com/dustin/go-humanize" "github.com/jedib0t/go-pretty/v6/progress" "github.com/jedib0t/go-pretty/v6/table" "github.com/pkg/errors" @@ -98,13 +98,13 @@ func NewCommand() *cli.Command { //nolint:funlen Name: threadsCountFlagName, Aliases: []string{"t"}, Usage: "threads count", - Value: uint(runtime.NumCPU() * 6), //nolint:gomnd + Value: uint(runtime.NumCPU() * 6), //nolint:mnd EnvVars: []string{env.ThreadsCount.String()}, }, &cli.UintFlag{ Name: maxErrorsToStopFlagName, Usage: "maximum errors count to stop the process (set 0 to disable)", - Value: 10, //nolint:gomnd + Value: 10, //nolint:mnd // EnvVars: []string{}, // TODO implement }, &cli.BoolFlag{ @@ -559,5 +559,5 @@ func (*command) FindFiles(ctx context.Context, where, filesExt []string, recursi // percentageDiff calculates difference between passed values in percentage representation. func (*command) percentageDiff(from, to float64) string { - return fmt.Sprintf("%0.2f%%", math.Abs(((from-to)/to)*100)) //nolint:gomnd + return fmt.Sprintf("%0.2f%%", math.Abs(((from-to)/to)*100)) //nolint:mnd } diff --git a/internal/cli/compress/errors_watcher_test.go b/internal/cli/compress/errors_watcher_test.go index 052fb03..953c4e3 100644 --- a/internal/cli/compress/errors_watcher_test.go +++ b/internal/cli/compress/errors_watcher_test.go @@ -6,6 +6,7 @@ import ( "runtime" "sync/atomic" "testing" + "time" "github.com/stretchr/testify/require" @@ -39,6 +40,7 @@ func TestErrorsWatcher(t *testing.T) { watcher <- testErr + <-time.After(10 * time.Millisecond) runtime.Gosched() require.True(t, onErrorHandled.Load().(bool)) @@ -46,6 +48,7 @@ func TestErrorsWatcher(t *testing.T) { watcher <- testErr + <-time.After(10 * time.Millisecond) runtime.Gosched() require.True(t, onErrorHandled.Load().(bool)) diff --git a/internal/cli/compress/statistics.go b/internal/cli/compress/statistics.go index 6124467..8ece0de 100644 --- a/internal/cli/compress/statistics.go +++ b/internal/cli/compress/statistics.go @@ -85,7 +85,7 @@ func (s *StatsStorage) TotalSavedBytes() (total int64) { func (s *StatsStorage) TotalFiles() (total uint32) { s.mu.Lock() - total = uint32(len(s.history)) + total = uint32(len(s.history)) //nolint:gosec s.mu.Unlock() return @@ -109,7 +109,7 @@ func (s *StatsStorage) Watch(ctx context.Context) { s.history = append(s.history, stat) s.totalOriginalSize += stat.OriginalSize s.totalCompressedSize += stat.CompressedSize - s.totalSavedBytes += int64(stat.OriginalSize) - int64(stat.CompressedSize) + s.totalSavedBytes += int64(stat.OriginalSize) - int64(stat.CompressedSize) //nolint:gosec s.mu.Unlock() } } diff --git a/internal/cli/compress/styles.go b/internal/cli/compress/styles.go index 3b92258..bea9512 100644 --- a/internal/cli/compress/styles.go +++ b/internal/cli/compress/styles.go @@ -49,7 +49,7 @@ func newProgressBar(expectedTrackersNum int, withOverall bool) progress.Writer { pw.SetNumTrackersExpected(expectedTrackersNum) pw.SetTrackerPosition(progress.PositionRight) pw.SetStyle(progressStyleDefault) - pw.SetUpdateFrequency(time.Millisecond * 100) //nolint:gomnd + pw.SetUpdateFrequency(time.Millisecond * 100) //nolint:mnd pw.Style().Visibility.Value = false pw.Style().Visibility.Percentage = false diff --git a/internal/cli/quota/command.go b/internal/cli/quota/command.go index 67803b7..a1bb275 100644 --- a/internal/cli/quota/command.go +++ b/internal/cli/quota/command.go @@ -76,10 +76,10 @@ func NewCommand() *cli.Command { //nolint:funlen var color = text.FgRed switch { - case count <= 300: //nolint:gomnd + case count <= 300: //nolint:mnd color = text.FgGreen - case count <= 400: //nolint:gomnd + case count <= 400: //nolint:mnd color = text.FgYellow } @@ -106,9 +106,9 @@ func NewCommand() *cli.Command { //nolint:funlen func maskString(s string) string { var length = utf8.RuneCountInString(s) - if length <= 8 { //nolint:gomnd + if length <= 8 { //nolint:mnd return s } - return s[:4] + strings.Repeat("*", length-8) + s[length-4:] //nolint:gomnd + return s[:4] + strings.Repeat("*", length-8) + s[length-4:] //nolint:mnd } diff --git a/internal/env/env.go b/internal/env/env.go index 7eb1ac8..c252b82 100644 --- a/internal/env/env.go +++ b/internal/env/env.go @@ -12,7 +12,7 @@ const ( ThreadsCount envVariable = "THREADS_COUNT" // Threads count - TinyPngAPIKey envVariable = "TINYPNG_API_KEY" //nolint:gosec // TinyPNG API key + TinyPngAPIKey envVariable = "TINYPNG_API_KEY" // TinyPNG API key ) // String returns environment variable name in the string representation. diff --git a/internal/env/env_test.go b/internal/env/env_test.go index e1b8837..3efd39b 100644 --- a/internal/env/env_test.go +++ b/internal/env/env_test.go @@ -24,7 +24,6 @@ func TestEnvVariable_Lookup(t *testing.T) { } for _, tt := range cases { - tt := tt t.Run(tt.giveEnv.String(), func(t *testing.T) { require.NoError(t, os.Unsetenv(tt.giveEnv.String())) // make sure that env is unset for test diff --git a/internal/files/finder.go b/internal/files/finder.go index acfff6c..b8286de 100644 --- a/internal/files/finder.go +++ b/internal/files/finder.go @@ -48,7 +48,7 @@ func WithFilesExt(filesExt ...string) FinderOption { // FindFiles finds all files in the given locations (without duplicates). // Important note - for the direct files' extension checking will be ignored. -// TODO fn should returns bool (shouldStop) +// TODO fn should returns bool (shouldStop). func FindFiles(ctx context.Context, where []string, fn func(absPath string), opts ...FinderOption) error { //nolint:funlen,gocognit,gocyclo,lll if len(where) == 0 { // fast terminator return nil diff --git a/internal/files/finder_test.go b/internal/files/finder_test.go index 1670f1f..00b3d02 100644 --- a/internal/files/finder_test.go +++ b/internal/files/finder_test.go @@ -2,7 +2,6 @@ package files_test import ( "context" - "io/ioutil" "os" "path/filepath" "testing" @@ -83,7 +82,7 @@ func TestFindFiles(t *testing.T) { for name, tt := range cases { t.Run(name, func(t *testing.T) { - tmpDir, tmpDirErr := ioutil.TempDir("", "test-") + tmpDir, tmpDirErr := os.MkdirTemp("", "test-") require.NoError(t, tmpDirErr) defer func(d string) { require.NoError(t, os.RemoveAll(d)) }(tmpDir) diff --git a/internal/retry/retry.go b/internal/retry/retry.go index b029efb..da6cce4 100644 --- a/internal/retry/retry.go +++ b/internal/retry/retry.go @@ -76,7 +76,7 @@ func Do(fn func(attemptNum uint) error, options ...Option) (limitExceeded bool, if err := cfg.ctx.Err(); err != nil { lastErr = err - return //nolint:nakedret + return } // execute passed function @@ -84,14 +84,14 @@ func Do(fn func(attemptNum uint) error, options ...Option) (limitExceeded bool, // if function executed without any error - stop the loop if lastErr == nil { - return //nolint:nakedret + return } // otherwise, if "errors to stop" is defined and one of them is occurred - stop the loop if len(cfg.stopOnErrors) > 0 { for i := 0; i < len(cfg.stopOnErrors); i++ { if errors.Is(lastErr, cfg.stopOnErrors[i]) { // checking using errors.Is(...) is important - return //nolint:nakedret + return } } } @@ -109,7 +109,7 @@ func Do(fn func(attemptNum uint) error, options ...Option) (limitExceeded bool, case <-cfg.ctx.Done(): lastErr = cfg.ctx.Err() - return //nolint:nakedret + return case <-timer.C: } diff --git a/internal/validate/image.go b/internal/validate/image.go index 7511d90..93afe24 100644 --- a/internal/validate/image.go +++ b/internal/validate/image.go @@ -10,7 +10,7 @@ import ( // IsImage checks for passed content is image or not. // Do not forget to reset the source (offset will be changed after this function calling). func IsImage(src io.Reader) (bool, error) { - buf := make([]byte, 32) //nolint:gomnd // 32 bytes are enough for "first bytes" checking + buf := make([]byte, 32) //nolint:mnd // 32 bytes are enough for "first bytes" checking if _, err := io.ReadFull(src, buf); err != nil && !errors.Is(err, io.EOF) && !errors.Is(err, io.ErrUnexpectedEOF) { return false, err diff --git a/internal/validate/image_test.go b/internal/validate/image_test.go index 15cf50e..83d4c0d 100644 --- a/internal/validate/image_test.go +++ b/internal/validate/image_test.go @@ -4,7 +4,7 @@ import ( "bytes" "errors" "io" - "io/ioutil" + "os" "testing" "github.com/stretchr/testify/assert" @@ -22,7 +22,7 @@ func TestIsImage(t *testing.T) { fromFile := func(path string) io.Reader { t.Helper() - data, err := ioutil.ReadFile(path) + data, err := os.ReadFile(path) assert.NoError(t, err) return bytes.NewReader(data) diff --git a/pkg/tinypng/client_test.go b/pkg/tinypng/client_test.go index fc26edf..3d3b2bb 100644 --- a/pkg/tinypng/client_test.go +++ b/pkg/tinypng/client_test.go @@ -8,7 +8,6 @@ import ( "errors" "fmt" "io" - "io/ioutil" "net/http" "os" "testing" @@ -66,7 +65,7 @@ func TestClient_UsedQuota_Success(t *testing.T) { Header: http.Header{ "Compression-Count": {"123454321", "any", "values"}, }, - Body: ioutil.NopCloser(bytes.NewReader([]byte{})), + Body: io.NopCloser(bytes.NewReader([]byte{})), }, nil } @@ -85,7 +84,7 @@ func TestClient_UsedQuota_WrongHeaderValue(t *testing.T) { Header: http.Header{ "Compression-Count": {"foo bar"}, // <-- wrong value }, - Body: ioutil.NopCloser(bytes.NewReader([]byte{})), + Body: io.NopCloser(bytes.NewReader([]byte{})), }, nil } @@ -102,7 +101,7 @@ func TestClient_UsedQuota_MissingHeader(t *testing.T) { Header: http.Header{ // "Compression-Count": {"123454321", "any", "values"}, // <-- nothing is here }, - Body: ioutil.NopCloser(bytes.NewReader([]byte{})), + Body: io.NopCloser(bytes.NewReader([]byte{})), }, nil } @@ -129,7 +128,7 @@ func TestClient_UsedQuota_Unauthorized(t *testing.T) { var httpMock httpClientFunc = func(req *http.Request) (*http.Response, error) { return &http.Response{ Header: http.Header{}, - Body: ioutil.NopCloser(bytes.NewReader([]byte{})), + Body: io.NopCloser(bytes.NewReader([]byte{})), StatusCode: http.StatusUnauthorized, // <-- important }, nil } @@ -159,13 +158,13 @@ func TestClient_Compress_Successful(t *testing.T) { require.Equal(t, "https://api.tinify.com/shrink", req.URL.String()) require.Equal(t, authHeaderValue(t, "bar-key"), req.Header.Get("Authorization")) - body, _ := ioutil.ReadAll(req.Body) + body, _ := io.ReadAll(req.Body) assert.Equal(t, srcImage, body) return &http.Response{ StatusCode: http.StatusCreated, Header: http.Header{"Compression-Count": {"123454321"}}, - Body: ioutil.NopCloser(bytes.NewReader([]byte(`{ + Body: io.NopCloser(bytes.NewReader([]byte(`{ "input":{ "size":4633, "type":"image/png" @@ -201,7 +200,7 @@ func TestClient_Compress_WrongJsonResponse(t *testing.T) { return &http.Response{ StatusCode: http.StatusCreated, Header: http.Header{"Compression-Count": {"123454321"}}, - Body: ioutil.NopCloser(bytes.NewReader([]byte(`{"broken json']`))), + Body: io.NopCloser(bytes.NewReader([]byte(`{"broken json']`))), }, nil } @@ -217,7 +216,7 @@ func TestClient_Compress_Unauthorized(t *testing.T) { var httpMock httpClientFunc = func(req *http.Request) (*http.Response, error) { return &http.Response{ Header: http.Header{}, - Body: ioutil.NopCloser(bytes.NewReader([]byte{})), + Body: io.NopCloser(bytes.NewReader([]byte{})), StatusCode: http.StatusUnauthorized, // <-- important }, nil } @@ -233,7 +232,7 @@ func TestClient_Compress_TooManyRequests(t *testing.T) { var httpMock httpClientFunc = func(req *http.Request) (*http.Response, error) { return &http.Response{ Header: http.Header{}, - Body: ioutil.NopCloser(bytes.NewReader([]byte{})), + Body: io.NopCloser(bytes.NewReader([]byte{})), StatusCode: http.StatusTooManyRequests, // <-- important }, nil } @@ -249,7 +248,7 @@ func TestClient_Compress_BadRequests(t *testing.T) { var httpMock httpClientFunc = func(req *http.Request) (*http.Response, error) { return &http.Response{ Header: http.Header{}, - Body: ioutil.NopCloser(bytes.NewReader([]byte{})), + Body: io.NopCloser(bytes.NewReader([]byte{})), StatusCode: http.StatusBadRequest, // <-- important }, nil } @@ -265,7 +264,7 @@ func TestClient_Compress_HTTPErrorAbove599(t *testing.T) { var httpMock httpClientFunc = func(req *http.Request) (*http.Response, error) { return &http.Response{ Header: http.Header{}, - Body: ioutil.NopCloser(bytes.NewReader([]byte{})), + Body: io.NopCloser(bytes.NewReader([]byte{})), StatusCode: 600, // <-- important }, nil } @@ -282,7 +281,7 @@ func TestClient_Compress_4xxError(t *testing.T) { var httpMock httpClientFunc = func(req *http.Request) (*http.Response, error) { return &http.Response{ Header: http.Header{"Compression-Count": {"123"}}, - Body: ioutil.NopCloser(bytes.NewReader([]byte(`{"error":"Foo","message":"bar baz."}`))), + Body: io.NopCloser(bytes.NewReader([]byte(`{"error":"Foo","message":"bar baz."}`))), StatusCode: http.StatusTeapot, // <-- can be any (instead 401, 429 and 400) }, nil } @@ -299,7 +298,7 @@ func TestClient_Compress_4xxErrorWithWrongJson(t *testing.T) { var httpMock httpClientFunc = func(req *http.Request) (*http.Response, error) { return &http.Response{ Header: http.Header{"Compression-Count": {"123"}}, - Body: ioutil.NopCloser(bytes.NewReader([]byte(`{"error":"broken json']`))), + Body: io.NopCloser(bytes.NewReader([]byte(`{"error":"broken json']`))), StatusCode: http.StatusLocked, // <-- can be any (instead 401, 429 and 400) }, nil } @@ -335,7 +334,7 @@ func TestClient_Compressed_Download_Success(t *testing.T) { return &http.Response{ StatusCode: http.StatusCreated, Header: http.Header{"Compression-Count": {"123454321"}}, - Body: ioutil.NopCloser(bytes.NewReader([]byte(`{ + Body: io.NopCloser(bytes.NewReader([]byte(`{ "input":{ "size":4633, "type":"image/png" @@ -383,7 +382,7 @@ func TestClient_Compressed_Download_Unauthorized(t *testing.T) { return &http.Response{ StatusCode: http.StatusCreated, Header: http.Header{"Compression-Count": {"123454321"}}, - Body: ioutil.NopCloser(bytes.NewReader([]byte(`{ + Body: io.NopCloser(bytes.NewReader([]byte(`{ "output":{ "url":"https://api.tinify.com/output/someRandomResultImageHash123" } @@ -421,7 +420,7 @@ func TestClient_Compressed_Download_TooManyRequests(t *testing.T) { return &http.Response{ StatusCode: http.StatusCreated, Header: http.Header{"Compression-Count": {"123454321"}}, - Body: ioutil.NopCloser(bytes.NewReader([]byte(`{ + Body: io.NopCloser(bytes.NewReader([]byte(`{ "output":{ "url":"https://api.tinify.com/output/someRandomResultImageHash321" } @@ -459,7 +458,7 @@ func TestClient_DownloadImage4xxError(t *testing.T) { return &http.Response{ StatusCode: http.StatusCreated, Header: http.Header{"Compression-Count": {"123454321"}}, - Body: ioutil.NopCloser(bytes.NewReader([]byte(`{ + Body: io.NopCloser(bytes.NewReader([]byte(`{ "output":{ "url":"https://api.tinify.com/output/someRandomResultImageHash111" } @@ -468,7 +467,7 @@ func TestClient_DownloadImage4xxError(t *testing.T) { case "https://api.tinify.com/output/someRandomResultImageHash111": return &http.Response{ - Body: ioutil.NopCloser(bytes.NewReader([]byte(`{"error":"Foo","message":"bar baz."}`))), + Body: io.NopCloser(bytes.NewReader([]byte(`{"error":"Foo","message":"bar baz."}`))), StatusCode: http.StatusTeapot, // <-- can be any 4xx error }, nil diff --git a/pkg/tinypng/errors.go b/pkg/tinypng/errors.go index 13b39a3..9479fda 100644 --- a/pkg/tinypng/errors.go +++ b/pkg/tinypng/errors.go @@ -45,9 +45,7 @@ func (err Error) Error() string { return buf.String() } -func newError(message string) error { - return fmt.Errorf(errorsPrefix + " " + message) -} +func newError(message string) error { return fmt.Errorf(errorsPrefix + " " + message) } //nolint:govet func newErrorf(format string, args ...any) error { return errors.New(errorsPrefix + " " + fmt.Errorf(format, args...).Error())