diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 029a12ecc..f9c3dc149 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,7 +1,7 @@ name: CI env: - go-version: '1.19' + go-version: "1.19" on: pull_request: @@ -12,7 +12,7 @@ on: jobs: quicktests: env: - execute: 'true' + execute: "true" runs-on: ubuntu-latest timeout-minutes: 5 steps: @@ -30,11 +30,25 @@ jobs: make install make test-tidy make test-fmt - # make lint - name: Mark the job as succeeded if: env.execute == 'false' run: exit 0 + lint: + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - name: checkout + uses: actions/checkout@v3 + - name: set up go + uses: actions/setup-go@v3 + with: + go-version: ${{ env.go-version }} + - name: setup env + run: make install + - name: lint + run: make lint-github-action + unittests: runs-on: ${{ matrix.os }} timeout-minutes: 15 diff --git a/.gitignore b/.gitignore index e738be62b..95936b2e6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .idea libgpu-setup-* build +bin diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 000000000..48de90899 --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,262 @@ +# This file contains all available configuration options +# Modified for linting cmd/ and pkg/ + +# options for analysis running +run: + # default concurrency is a available CPU number + # concurrency: 4 + + # timeout for analysis, e.g. 30s, 5m, default is 1m + deadline: 3m + + # exit code when at least one issue was found, default is 1 + issues-exit-code: 1 + + # include test files or not, default is true + tests: true + + # list of build tags, all linters use it. Default is empty list. + # build-tags: + + # which dirs to skip: they won't be analyzed; + # can use regexp here: generated.*, regexp is applied on full path; + # default value is empty list, but next dirs are always skipped independently + # from this option's value: + # vendor$, third_party$, testdata$, examples$, Godeps$, builtin$ + # skip-dirs: + + # which files to skip: they will be analyzed, but issues from them + # won't be reported. Default value is empty list, but there is + # no need to include all autogenerated files, we confidently recognize + # autogenerated files. If it's not please let us know. + skip-files: + - "^mock_*\\.go$" + + # by default isn't set. If set we pass it to "go list -mod={option}". From "go help modules": + # If invoked with -mod=readonly, the go command is disallowed from the implicit + # automatic updating of go.mod described above. Instead, it fails when any changes + # to go.mod are needed. This setting is most useful to check that go.mod does + # not need updates, such as in a continuous integration and testing system. + # If invoked with -mod=vendor, the go command assumes that the vendor + # directory holds the correct copies of dependencies and ignores + # the dependency descriptions in go.mod. + modules-download-mode: mod + +# output configuration options +output: + # colored-line-number|line-number|json|tab|checkstyle, default is "colored-line-number" + format: colored-line-number + + # print lines of code with issue, default is true + print-issued-lines: true + + # print linter name in the end of issue text, default is true + print-linter-name: true + +# all available settings of specific linters +linters-settings: + staticcheck: + # Select the Go version to target. The default is '1.13'. + go: "1.19" + # https://staticcheck.io/docs/options#checks + checks: ["all"] + + errcheck: + # report about not checking of errors in type assertions: `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: true + govet: + # report about shadowed variables + check-shadowing: true + + # Obtain type information from installed (to $GOPATH/pkg) package files: + # golangci-lint will execute `go install -i` and `go test -i` for analyzed packages + # before analyzing them. + # By default this option is disabled and govet gets type information by loader from source code. + # Loading from source code is slow, but it's done only once for all linters. + # Go-installing of packages first time is much slower than loading them from source code, + # therefore this option is disabled by default. + # But repeated installation is fast in go >= 1.10 because of build caching. + # Enable this option only if all conditions are met: + # 1. you use only "fast" linters (--fast e.g.): no program loading occurs + # 2. you use go >= 1.10 + # 3. you do repeated runs (false for CI) or cache $GOPATH/pkg or `go env GOCACHE` dir in CI. + use-installed-packages: false + revive: + # Sets the default failure confidence. + # This means that linting errors with less than 0.8 confidence will be ignored. + # Default: 0.8 + confidence: 0.8 + gofmt: + # simplify code: gofmt with `-s` option, true by default + simplify: true + gocyclo: + # minimal code complexity to report, 30 by default (but we recommend 10-20) + min-complexity: 10 + maligned: + # print struct with more effective memory layout or not, false by default + suggest-new: true + dupl: + # tokens count to trigger issue, 150 by default + threshold: 100 + goconst: + # minimal length of string constant, 3 by default + min-len: 3 + # minimal occurrences count to trigger, 3 by default + min-occurrences: 3 + depguard: + list-type: blacklist + include-go-root: false + packages: + - github.com/pkg/errors + misspell: + # Correct spellings using locale preferences for US or UK. + # Default is to use a neutral variety of English. + # Setting locale to US will correct the British spelling of 'colour' to 'color'. + locale: US + lll: + # max line length, lines longer will be reported. Default is 120. + # '\t' is counted as 1 character by default, and can be changed with the tab-width option + line-length: 120 + # tab width in spaces. Default to 1. + tab-width: 1 + unused: + # treat code as a program (not a library) and report unused exported identifiers; default is false. + # XXX: if you enable this setting, unused will report a lot of false-positives in text editors: + # if it's called for subdir of a project it can't find funcs usages. All text editor integrations + # with golangci-lint call it on a directory with the changed file. + check-exported: false + unparam: + # call graph construction algorithm (cha, rta). In general, use cha for libraries, + # and rta for programs with main packages. Default is cha. + algo: cha + + # Inspect exported functions, default is false. Set to true if no external program/library imports your code. + # XXX: if you enable this setting, unparam will report a lot of false-positives in text editors: + # if it's called for subdir of a project it can't find external interfaces. All text editor integrations + # with golangci-lint call it on a directory with the changed file. + check-exported: false + nakedret: + # make an issue if func has more lines of code than this setting and it has naked returns; default is 30 + max-func-lines: 30 + prealloc: + # XXX: we don't recommend using this linter before doing performance profiling. + # For most programs usage of prealloc will be a premature optimization. + + # Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them. + # True by default. + simple: true + range-loops: true # Report preallocation suggestions on range loops, true by default + for-loops: false # Report preallocation suggestions on for loops, false by default + goimports: + local-prefixes: github.com/spacemeshos/go-spacemesh + gci: + sections: + - standard + - default + - prefix(github.com/spacemeshos/go-spacemesh) + godot: + # comments to be checked: `declarations`, `toplevel`, or `all` + scope: declarations + # list of regexps for excluding particular comment lines from check + exclude: [] + # example: exclude comments which contain numbers + # - '[0-9]+' + # check that each sentence starts with a capital letter + capital: false + gofumpt: + # Select the Go version to target. The default is `1.15`. + lang-version: "1.19" + # Choose whether or not to use the extra rules that are disabled + # by default + extra-rules: 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 + wrapcheck: + # An array of strings that specify substrings of signatures to ignore. + # If this set, it will override the default set of ignored signatures. + # See https://github.com/tomarrell/wrapcheck#configuration for more information. + ignoreSigs: + # Default sigs + - .Errorf( + - errors.New( + - errors.Unwrap( + - .Wrap( + - .Wrapf( + - .WithMessage( + - .WithMessagef( + - .WithStack( + # Custom sigs + - .Error( + - .Err( + ignorePackageGlobs: + - encoding/* + - github.com/pkg/* + +linters: + # TODO(nkryuchkov): enable needed linters + enable: + - gci + - godot + - gofmt + - gofumpt + - revive + - misspell + - staticcheck + - whitespace + # - wrapcheck + # - varcheck + # - unparam + # - deadcode + # - structcheck + # - errcheck + # - gosimple + # - unused + # - ineffassign + # - typecheck + # - gosec + # - megacheck + # - nakedret + # - depguard + enable-all: false + # disable: + disable-all: true + # presets: + fast: false + +issues: + # List of regexps of issue texts to exclude, empty list by default. + # But independently from this option we use default exclude patterns, + # it can be disabled by `exclude-use-default: false`. To list all + # excluded by default patterns execute `golangci-lint run --help` + # exclude: + + exclude-rules: + - linters: + - staticcheck + text: SA1019 + + # Independently from option `exclude` we use default exclude patterns, + # it can be disabled by this option. To list all + # excluded by default patterns execute `golangci-lint run --help`. + # Default value for this option is true. + exclude-use-default: false + + # Maximum issues count per one linter. Set to 0 to disable. Default is 50. + max-per-linter: 0 + + # Maximum count of issues with the same text. Set to 0 to disable. Default is 3. + max-same: 0 + + # Show only new issues: if there are unstaged changes or untracked files, + # only those changes are analyzed, else only changes in HEAD~ are analyzed. + # It's a super-useful option for integration of golangci-lint into existing + # large codebase. It's not practical to fix all existing issues at the moment + # of integration: much better don't allow issues in new code. + # Default is false. + new: false diff --git a/Makefile b/Makefile index fe148d2f3..575ac5845 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ endif install: get-gpu-setup go mod download - GO111MODULE=off go get golang.org/x/lint/golint + curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s v1.50.0 .PHONY: install tidy: @@ -39,7 +39,17 @@ test-fmt: git diff --exit-code || (git --no-pager diff && git checkout . && exit 1) .PHONY: test-fmt -lint: - golint --set_exit_status ./... +lint: get-gpu-setup go vet ./... + ./bin/golangci-lint run --config .golangci.yml .PHONY: lint + +# Auto-fixes golangci-lint issues where possible. +lint-fix: get-gpu-setup + ./bin/golangci-lint run --config .golangci.yml --fix +.PHONY: lint-fix + +lint-github-action: get-gpu-setup + go vet ./... + ./bin/golangci-lint run --config .golangci.yml --out-format=github-actions +.PHONY: lint-github-action diff --git a/Makefile.Inc b/Makefile.Inc index b7adfb365..43ad8d044 100644 --- a/Makefile.Inc +++ b/Makefile.Inc @@ -47,7 +47,9 @@ else endif endif -$(info "OS: $(OS), HOST_OS: $(HOST_OS), GOOS: $(GOOS), GOARCH: $(GOARH), BIN_DIR: $(BIN_DIR), platform: $(platform)") +ifneq ($(VERBOSE),) + $(info "OS: $(OS), HOST_OS: $(HOST_OS), GOOS: $(GOOS), GOARCH: $(GOARH), BIN_DIR: $(BIN_DIR), platform: $(platform)") +endif GPU_SETUP_REV = 0.1.24 GPU_SETUP_ZIP = libgpu-setup-$(platform)-$(GPU_SETUP_REV).zip diff --git a/gpu/bridge.go b/gpu/bridge.go index df6900be1..d231dd424 100644 --- a/gpu/bridge.go +++ b/gpu/bridge.go @@ -64,7 +64,7 @@ func (s StopResult) String() string { case StopResultErrorAlready: return "already stopped" case StopResultErrorCancelled: - return "cancelled" + return "canceled" default: panic("unreachable") } diff --git a/initialization/initialization_test.go b/initialization/initialization_test.go index 1b85a843c..6ba05ca23 100644 --- a/initialization/initialization_test.go +++ b/initialization/initialization_test.go @@ -292,6 +292,7 @@ func TestValidateMetadata(t *testing.T) { m, err := init.loadMetadata() r.Equal(ErrStateMetadataFileMissing, err) + r.Nil(m) err = init.Initialize() r.NoError(err) diff --git a/persistence/filewriter.go b/persistence/filewriter.go index 75a8a447a..4f44236aa 100644 --- a/persistence/filewriter.go +++ b/persistence/filewriter.go @@ -53,7 +53,7 @@ func (w *FileWriter) NumLabelsWritten() (uint64, error) { func (w *FileWriter) Truncate(numLabels uint64) error { bitSize := numLabels * uint64(w.bitsPerLabel) if bitSize%8 != 0 { - return fmt.Errorf("invalid `numLabels`; expected: evenly divisible by 8 (alone, or when multipled by `labelSize`), given: %d", numLabels) + return fmt.Errorf("invalid `numLabels`; expected: evenly divisible by 8 (alone, or when multiplied by `labelSize`), given: %d", numLabels) } size := int64(bitSize / 8) diff --git a/proving/proving.go b/proving/proving.go index 4acd4de97..f3343ab01 100644 --- a/proving/proving.go +++ b/proving/proving.go @@ -189,7 +189,7 @@ func (p *Prover) tryNonce(ctx context.Context, numLabels uint64, ch Challenge, n for { select { case <-ctx.Done(): - return nil, fmt.Errorf("cancelled: tried: %v, passed: %v, needed: %v", index, passed, p.cfg.K2) + return nil, fmt.Errorf("canceled: tried: %v, passed: %v, needed: %v", index, passed, p.cfg.K2) case label, more := <-readerChan: if !more { return nil, fmt.Errorf("exhausted all labels; tried: %v, passed: %v, needed: %v", index, passed, p.cfg.K2) diff --git a/shared/granularity_specific_io_test.go b/shared/granularity_specific_io_test.go index b0b20b0b9..36ec3d852 100644 --- a/shared/granularity_specific_io_test.go +++ b/shared/granularity_specific_io_test.go @@ -10,8 +10,8 @@ import ( var NewGranSpecificReader = shared.NewGranSpecificReader -// change to simple array instead of file writing func TestGranSpecificReader_BitGranular(t *testing.T) { + // TODO(moshababo): change to simple array instead of file writing req := require.New(t) // Write one byte ([0b11111111]) diff --git a/shared/proof.go b/shared/proof.go index b8b91ed73..6c38e906d 100644 --- a/shared/proof.go +++ b/shared/proof.go @@ -11,10 +11,10 @@ type Proof struct { // Encode encodes Proof according to the following format: // -// +-----------+-------------------+ -// | nonce | indices | -// | (4 bytes) | (remaining bytes) | -// +-----------+-------------------+ +// +-----------+-------------------+ +// | nonce | indices | +// | (4 bytes) | (remaining bytes) | +// +-----------+-------------------+ func (p *Proof) Encode() []byte { size := 4 + len(p.Indices) b := make([]byte, size) diff --git a/shared/shared.go b/shared/shared.go index f4cf8057d..f5551d953 100644 --- a/shared/shared.go +++ b/shared/shared.go @@ -52,7 +52,7 @@ func Size(itemBitSize uint, numItems uint) uint { return (bitSize + 7) / 8 // Integer ceil of (indicesBitSize / 8). } -// PutUintBE +// PutUintBE encodes a uint64 into a big-endian byte slice. func PutUintBE(b []byte, v uint64) { numBits := len(b) * 8 diff --git a/shared/version.go b/shared/version.go index 4b37118a8..624689425 100644 --- a/shared/version.go +++ b/shared/version.go @@ -10,7 +10,7 @@ import ( "strings" ) -// semanticAlphabet +// semanticAlphabet is the alphabet of characters used for normalization. const semanticAlphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-" // These constants define the application version and follow the semantic diff --git a/verifying/verifying_test.go b/verifying/verifying_test.go index 50f8f22ab..986bc5dbc 100644 --- a/verifying/verifying_test.go +++ b/verifying/verifying_test.go @@ -105,7 +105,6 @@ func TestLabelsCorrectness(t *testing.T) { req.NoError(err) err = writer.Write(labels) req.NoError(err) - } _, err = writer.Close() req.NoError(err) @@ -113,9 +112,9 @@ func TestLabelsCorrectness(t *testing.T) { // Read. reader, err := persistence.NewLabelsReader(datadir, uint(bitsPerLabel)) + req.NoError(err) defer reader.Close() gsReader := shared.NewGranSpecificReader(reader, uint(bitsPerLabel)) - req.NoError(err) var position uint64 for { label, err := gsReader.ReadNext()