Skip to content

Commit

Permalink
Add golangci-lint, hande errors in command directly
Browse files Browse the repository at this point in the history
  • Loading branch information
judimator committed May 23, 2024
1 parent eebd639 commit cc9163c
Show file tree
Hide file tree
Showing 23 changed files with 582 additions and 305 deletions.
11 changes: 11 additions & 0 deletions .githooks/pre-commit.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/bin/bash

set -e -o pipefail

# https://github.com/koalaman/shellcheck/wiki/SC2039#redirect-both-stdout-and-stderr
if ! command -v golangci-lint 2>&1 /dev/null; then
echo "golangci-lint is not installed"
exit 1
fi

exec golangci-lint --build-tags=race run "$@"
18 changes: 18 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,24 @@ on:
- '*'

jobs:
golangci-lint:
name: Golang-CI (lint)
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v4

- name: Set up Go
uses: actions/setup-go@v5 # action page: <https://github.com/actions/setup-go>
with:
go-version: stable

- name: Run linter
uses: golangci/[email protected]
with:
version: v1.58 # without patch version
only-new-issues: false # show only new issues if it's a pull request
args: -v --build-tags=race --timeout=10m
go-test:
name: Unit tests
runs-on: ubuntu-latest
Expand Down
80 changes: 80 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# Documentation: <https://github.com/golangci/golangci-lint#config-file>

run:
timeout: 1m
allow-parallel-runners: true

output:
formats:
- format: colored-line-number

linters-settings:
wsl:
allow-assign-and-anything: true
godot:
scope: declarations
capital: true
dupl:
threshold: 100
goconst:
min-len: 2
min-occurrences: 3
misspell:
locale: US
lll:
line-length: 120
prealloc:
simple: true
range-loops: true
for-loops: true
nolintlint:
require-specific: true

linters: # All available linters list: <https://golangci-lint.run/usage/linters/>
disable-all: true
enable:
- asciicheck # Simple linter to check that your code does not contain non-ASCII identifiers
- bodyclose # Checks whether HTTP response body is closed successfully
- dogsled # Checks assignments with too many blank identifiers (e.g. x, _, _, _, := f())
- dupl # Tool for code clone detection
- errcheck # Errcheck is a program for checking for unchecked errors in go programs. These unchecked errors can be critical bugs in some cases
- errorlint # find code that will cause problems with the error wrapping scheme introduced in Go 1.13
- exhaustive # check exhaustiveness of enum switch statements
- exportloopref # checks for pointers to enclosing loop variables
- goconst # Finds repeated strings that could be replaced by a constant
- gocritic # The most opinionated Go source code linter
- gofmt # Gofmt checks whether code was gofmt-ed. By default this tool runs with -s option to check for code simplification
- goimports # Goimports does everything that gofmt does. Additionally it checks unused imports
- revive
- goprintffuncname # Checks that printf-like functions are named with `f` at the end
- gosec # Inspects source code for security problems
- gosimple # Linter for Go source code that specializes in simplifying a code
- govet # Vet examines Go source code and reports suspicious constructs, such as Printf calls whose arguments do not align with the format string
- ineffassign # Detects when assignments to existing variables are not used
- misspell # Finds commonly misspelled English words in comments
- nakedret # Finds naked returns in functions greater than a specified function length
- nestif # Reports deeply nested if statements
- nlreturn # checks for a new line before return and branch statements to increase code clarity
- noctx # finds sending http request without context.Context
- nolintlint # Reports ill-formed or insufficient nolint directives
- prealloc # Finds slice declarations that could potentially be preallocated
- staticcheck # Staticcheck is a go vet on steroids, applying a ton of static analysis checks
- stylecheck # Stylecheck is a replacement for golint
- tparallel # detects inappropriate usage of t.Parallel() method in your Go test codes
- unconvert # Remove unnecessary type conversions
- unparam # Reports unused function parameters
- unused # Checks Go code for unused constants, variables, functions and types
- whitespace # Tool for detection of leading and trailing whitespace
- wsl # Whitespace Linter - Forces you to use empty lines!

issues:
exclude-dirs:
- .github
- .git
exclude-rules:
- path: _test\.go
linters:
- dupl
- funlen
- scopelint
- gocognit
24 changes: 21 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,28 @@
## [v1.3.0](https://github.com/judimator/augurken/tree/v1.3.0)

**Enhancements:**
- Handle command errors in another way
- Add golangci-lint into GitHub workflow

## [v1.2.0](https://github.com/judimator/augurken/tree/v1.2.0)

**Enhancements:**
- Add check command
- Add tests
- Refactoring

## [v1.1.3](https://github.com/judimator/augurken/tree/v1.1.3)

**Enhancements:**
- Add tests

## [v1.1.2](https://github.com/judimator/augurken/tree/v1.1.2)

**Enhancements:**
- Add tests to Github workflow
- Add CHANGELOG.md

## [v1.0.0](https://github.com/judimator/augurken/tree/v1.1.1)
## [v1.1.1](https://github.com/judimator/augurken/tree/v1.1.1)

**Enhancements:**
- Add Dependabot
Expand All @@ -14,8 +32,8 @@
**Enhancements:**
- Compact JSON in "Examples" table

## [v1.1.1](https://github.com/judimator/augurken/tree/v1.0.0)
## [v1.0.0](https://github.com/judimator/augurken/tree/v1.0.0)

**Enhancements:**
- Initial commit with the formatter
- Add Github workflow
- Add GitHub workflow
19 changes: 15 additions & 4 deletions cmd/check/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ import (
"errors"

"github.com/judimator/augurken/formatter"
"github.com/judimator/augurken/log"
"github.com/spf13/cobra"
)

func NewCommand(logger formatter.Log) *cobra.Command {
func NewCommand() *cobra.Command {
var indent int
cmd := &cobra.Command{
Use: "check [file or path]",
Expand All @@ -19,14 +20,24 @@ func NewCommand(logger formatter.Log) *cobra.Command {
}

indent, _ := cmd.Flags().GetInt("indent")
fileManager := formatter.NewFileManager(indent, logger)
if err := fileManager.Check(args[0]); err != nil {
return err
fileManager := formatter.NewFileManager(indent)
if result := fileManager.Check(args[0]); result != nil {
for _, r := range result {
if s, ok := r.(string); ok {
log.Success(s)

continue
}
if e, ok := r.(error); ok {
log.Error(e)
}
}
}

return nil
},
}
cmd.Flags().IntVarP(&indent, "indent", "i", 2, "set the indentation for Gherkin features (default 2)")

return cmd
}
61 changes: 16 additions & 45 deletions cmd/check/command_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,18 @@ package check

import (
"bytes"
"fmt"
"log"
"os"
"strings"
"testing"

"github.com/judimator/augurken/log"
"github.com/stretchr/testify/assert"
)

var (
buff bytes.Buffer
buffLogger = log.New(&buff, "", log.Lmsgprefix)
)

type BuffLogger struct{}

func (l BuffLogger) Print(str string) {
buffLogger.Println(str)
}
func (l BuffLogger) Error(err error) {
buffLogger.Println(err)
}
func (l BuffLogger) Success(str string) {
buffLogger.Println(str)
}

func TestCheckInvalidFile(t *testing.T) {
var buff bytes.Buffer
logger := log.GetLogger()
logger.SetOutput(&buff)

content := []byte(`Feature: test
test
Expand All @@ -43,21 +28,23 @@ hello world

assert.NoError(t, os.RemoveAll("tmp/"))
assert.NoError(t, os.MkdirAll("tmp/", 0o777))
assert.NoError(t, os.WriteFile("tmp/file1.feature", content, 0o777))
assert.NoError(t, os.WriteFile("tmp/file1.feature", content, 0o600))

command := NewCommand(BuffLogger{})
command := NewCommand()
command.SetArgs([]string{"tmp/file1.feature"})
err := command.Execute()

assert.Error(t, err)
assert.Empty(t, buff.String())
assert.EqualValues(t, `an error occurred with file "tmp/file1.feature" : file is not properly formatted`, err.Error())
assert.NoError(t, err)
assert.EqualValues(t, `an error occurred with file "tmp/file1.feature" : file is not properly formatted`+"\n", buff.String())
// Clean up
_ = os.RemoveAll("tmp/")
buff.Reset()
}

func TestCheckInvalidFolder(t *testing.T) {
var buff bytes.Buffer
logger := log.GetLogger()
logger.SetOutput(&buff)

content := []byte(`Feature: test
test
Expand All @@ -72,30 +59,14 @@ hello world

assert.NoError(t, os.RemoveAll("tmp/"))
assert.NoError(t, os.MkdirAll("tmp/", 0o777))
assert.NoError(t, os.WriteFile("tmp/file1.feature", content, 0o777))
assert.NoError(t, os.WriteFile("tmp/file1.feature", content, 0o600))

command := NewCommand(BuffLogger{})
command := NewCommand()
command.SetArgs([]string{"tmp", "-i", "4"})
err := command.Execute()

assert.NoError(t, err)

i := 0
errs := strings.Split(buff.String(), "\n")
expectedErrs := []string{
`an error occurred with file "tmp/file1.feature" : file is not properly formatted`,
}
for _, expectedErr := range expectedErrs {
for _, e := range errs {
if expectedErr == e {
i++
}
}
}
if l := len(expectedErrs); i != l {
assert.Fail(t, fmt.Sprintf("Must fail with %v files when formatting folder", l))
}
assert.EqualValues(t, `an error occurred with file "tmp/file1.feature" : file is not properly formatted`+"\n", buff.String())
// Clean up
_ = os.RemoveAll("tmp/")
buff.Reset()
}
20 changes: 16 additions & 4 deletions cmd/format/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ import (
"errors"

"github.com/judimator/augurken/formatter"
"github.com/judimator/augurken/log"
"github.com/spf13/cobra"
)

func NewCommand(logger formatter.Log) *cobra.Command {
func NewCommand() *cobra.Command {
var indent int
cmd := &cobra.Command{
Use: "format [file or path]",
Expand All @@ -19,13 +20,24 @@ func NewCommand(logger formatter.Log) *cobra.Command {
}

indent, _ := cmd.Flags().GetInt("indent")
fileManager := formatter.NewFileManager(indent, logger)
if err := fileManager.FormatAndReplace(args[0]); err != nil {
return err
fileManager := formatter.NewFileManager(indent)
result := fileManager.FormatAndReplace(args[0])

for _, r := range result {
if s, ok := r.(string); ok {
log.Success(s)

continue
}
if e, ok := r.(error); ok {
log.Error(e)
}
}

return nil
},
}
cmd.Flags().IntVarP(&indent, "indent", "i", 2, "set the indentation for Gherkin features (default 2)")

return cmd
}
27 changes: 4 additions & 23 deletions cmd/format/command_test.go
Original file line number Diff line number Diff line change
@@ -1,31 +1,12 @@
package format

import (
"bytes"
"log"
"os"
"testing"

"github.com/stretchr/testify/assert"
)

var (
buff bytes.Buffer
buffLogger = log.New(&buff, "", log.Lmsgprefix)
)

type BuffLogger struct{}

func (l BuffLogger) Print(str string) {
buffLogger.Println(str)
}
func (l BuffLogger) Error(err error) {
buffLogger.Println(err)
}
func (l BuffLogger) Success(str string) {
buffLogger.Println(str)
}

func TestFormatAndReplaceFile(t *testing.T) {
content := []byte(`Feature: test
test
Expand All @@ -41,9 +22,9 @@ hello world

assert.NoError(t, os.RemoveAll("tmp/"))
assert.NoError(t, os.MkdirAll("tmp/", 0o777))
assert.NoError(t, os.WriteFile("tmp/file1.feature", content, 0o777))
assert.NoError(t, os.WriteFile("tmp/file1.feature", content, 0o600))

command := NewCommand(BuffLogger{})
command := NewCommand()
command.SetArgs([]string{"tmp/file1.feature", "-i", "4"})
err := command.Execute()

Expand Down Expand Up @@ -84,9 +65,9 @@ hello world

assert.NoError(t, os.RemoveAll("tmp/"))
assert.NoError(t, os.MkdirAll("tmp/", 0o777))
assert.NoError(t, os.WriteFile("tmp/file1.feature", content, 0o777))
assert.NoError(t, os.WriteFile("tmp/file1.feature", content, 0o600))

command := NewCommand(BuffLogger{})
command := NewCommand()
command.SetArgs([]string{"tmp", "-i", "4"})
err := command.Execute()

Expand Down
Loading

0 comments on commit cc9163c

Please sign in to comment.