diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml index b534f5c..6d14e1a 100644 --- a/.github/workflows/lint.yaml +++ b/.github/workflows/lint.yaml @@ -10,19 +10,17 @@ permissions: jobs: build: - strategy: - fail-fast: false runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - uses: actions/setup-go@v6 with: - go-version: "1.18.5" + go-version: "1.24.7" - name: golangci-lint - uses: golangci/golangci-lint-action@2226d7cb06a077cd73e56eedd38eecad18e5d837 + uses: golangci/golangci-lint-action@1e7e51e771db61008b38414a730f564565cf7c20 with: - version: v1.47.3 + version: v2.11.4 args: --verbose --config .golangci.yaml skip-cache: true diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index dcdba63..c5957c6 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -11,15 +11,13 @@ permissions: jobs: test: - strategy: - fail-fast: false runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - uses: actions/setup-go@v6 with: - go-version: "1.18.5" + go-version: "1.24.7" - name: Build program run: go build ./... diff --git a/.golangci.yaml b/.golangci.yaml index 4149076..ad095cc 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -1,48 +1,27 @@ # prerequisite: # [install golangci-lint](https://golangci-lint.run/usage/install/#local-installation) -run: - # timeout for analysis, e.g. 30s, 5m, default is 1m - timeout: 5m - - skip-files: - - .peg\.go - - .*\.pb\.go - skip-dirs: - - vendor - +version: "2" linters: enable: - - deadcode - - depguard - errcheck - - exportloopref - gocritic - gocyclo - - gofmt - - goimports - gosec - - gosimple - govet - ineffassign - misspell - nakedret - - prealloc - revive - staticcheck - - structcheck - - typecheck - unconvert - unused - - varcheck disable: - gochecknoglobals # we allow global variables in packages - gochecknoinits # we allow inits in packages - goconst # we allow repeated values to go un-const'd - lll # we allow any line length - unparam # we allow function calls to name unused parameters - -issues: - exclude-rules: - # Probably some broken linter for generics? - - linters: [ revive ] - text: 'receiver-naming: receiver name \S+ should be consistent with previous receiver name \S+ for invalid-type' +formatters: + enable: + - gofmt + - goimports diff --git a/cmd/spdx-validate/main.go b/cmd/spdx-validate/main.go index d31bf2d..d386f25 100644 --- a/cmd/spdx-validate/main.go +++ b/cmd/spdx-validate/main.go @@ -1,3 +1,4 @@ +// Package main validates newline-separated SPDX expressions from stdin or a file. package main import ( @@ -26,14 +27,17 @@ Examples: echo "MIT" | spdx-validate printf "MIT\nApache-2.0\n" | spdx-validate spdx-validate -f licenses.txt`, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, _ []string) error { var r io.Reader = os.Stdin if filePath != "" { + // #nosec G304 -- file path is an explicit CLI input for this command. f, err := os.Open(filePath) if err != nil { return fmt.Errorf("unable to open file: %w", err) } - defer f.Close() + defer func() { + _ = f.Close() + }() r = f } ok, err := validateExpressions(r, os.Stderr) @@ -71,7 +75,7 @@ func validateExpressions(r io.Reader, w io.Writer) (bool, error) { valid, _ := spdxexp.ValidateLicenses([]string{line}) if !valid { failures++ - fmt.Fprintf(w, "line %d: invalid SPDX expression: %q\n", lineNum, line) + _, _ = fmt.Fprintf(w, "line %d: invalid SPDX expression: %q\n", lineNum, line) } } @@ -84,7 +88,7 @@ func validateExpressions(r io.Reader, w io.Writer) (bool, error) { } if failures > 0 { - fmt.Fprintf(w, "%d of %d expressions failed validation\n", failures, lineNum) + _, _ = fmt.Fprintf(w, "%d of %d expressions failed validation\n", failures, lineNum) return false, nil } diff --git a/cmd/spdx-validate/main_test.go b/cmd/spdx-validate/main_test.go index 9fe7388..a0c4d46 100644 --- a/cmd/spdx-validate/main_test.go +++ b/cmd/spdx-validate/main_test.go @@ -166,11 +166,14 @@ func TestValidateExpressions_FromTempFile(t *testing.T) { t.Fatalf("failed to write temp file: %v", err) } + // #nosec G304 -- path is created within t.TempDir for this test. f, err := os.Open(path) if err != nil { t.Fatalf("failed to open temp file: %v", err) } - defer f.Close() + defer func() { + _ = f.Close() + }() var w bytes.Buffer ok, err := validateExpressions(f, &w) @@ -191,11 +194,14 @@ func TestValidateExpressions_FromTempFileWithFailures(t *testing.T) { t.Fatalf("failed to write temp file: %v", err) } + // #nosec G304 -- path is created within t.TempDir for this test. f, err := os.Open(path) if err != nil { t.Fatalf("failed to open temp file: %v", err) } - defer f.Close() + defer func() { + _ = f.Close() + }() var w bytes.Buffer ok, err := validateExpressions(f, &w) diff --git a/spdxexp/benchmark_setup_test.go b/spdxexp/benchmark_setup_test.go index 85bab37..33e3303 100644 --- a/spdxexp/benchmark_setup_test.go +++ b/spdxexp/benchmark_setup_test.go @@ -41,10 +41,10 @@ func TestMain(m *testing.M) { _ = benchFlag.Value.Set("$^") } - fmt.Fprintln(os.Stdout, "Benchmark summary tables:") - fmt.Fprintln(os.Stdout, "- ns/op average: average time per operation") - fmt.Fprintln(os.Stdout, "- Scale: relative to a fixed baseline per table") - fmt.Fprintln(os.Stdout, "") + _, _ = fmt.Fprintln(os.Stdout, "Benchmark summary tables:") + _, _ = fmt.Fprintln(os.Stdout, "- ns/op average: average time per operation") + _, _ = fmt.Fprintln(os.Stdout, "- Scale: relative to a fixed baseline per table") + _, _ = fmt.Fprintln(os.Stdout, "") } code := m.Run() @@ -148,10 +148,10 @@ func printBenchmarkTable(w *os.File, title string, rows []benchmarkTableRow, ben } line := func() { - fmt.Fprintf(w, "+-%s-+-%s-+-%s-+\n", strings.Repeat("-", col1), strings.Repeat("-", col2), strings.Repeat("-", col3)) + _, _ = fmt.Fprintf(w, "+-%s-+-%s-+-%s-+\n", strings.Repeat("-", col1), strings.Repeat("-", col2), strings.Repeat("-", col3)) } row := func(c1, c2, c3 string) { - fmt.Fprintf(w, "| %-*s | %-*s | %-*s |\n", col1, c1, col2, c2, col3, c3) + _, _ = fmt.Fprintf(w, "| %-*s | %-*s | %-*s |\n", col1, c1, col2, c2, col3, c3) } line() @@ -162,7 +162,7 @@ func printBenchmarkTable(w *os.File, title string, rows []benchmarkTableRow, ben row(r.label, ns, r.scale) } line() - fmt.Fprintln(w, "") + _, _ = fmt.Fprintln(w, "") } func nsNumberString(ns float64) string { diff --git a/spdxexp/doc.go b/spdxexp/doc.go index f487539..04ba228 100644 --- a/spdxexp/doc.go +++ b/spdxexp/doc.go @@ -1,6 +1,7 @@ /* -Spdxexp package validates licenses and determines if a license expression is satisfied by a list of licenses. -Validity of a license is determined by the [SPDX license list]. +Package spdxexp validates licenses and determines if a license expression is +satisfied by a list of licenses. Validity of a license is determined by the +[SPDX license list]. [SPDX license list]: https://spdx.org/licenses/ */ diff --git a/spdxexp/spdxlicenses/doc.go b/spdxexp/spdxlicenses/doc.go index 81d3860..0d6725f 100644 --- a/spdxexp/spdxlicenses/doc.go +++ b/spdxexp/spdxlicenses/doc.go @@ -1,8 +1,10 @@ /* -Spdxlicenses package provides functions to get licenses, deprecated licenses, and exceptions. These are auto-generated and should not be modified directly. +Package spdxlicenses provides functions to get licenses, deprecated licenses, +and exceptions. These are auto-generated and should not be modified directly. Licenses are generated from the [SPDX official machine readable license list]. -In addition, this package includes a function to return license ranges for sequential licenses and ranges including modifiers (i.e. -only, -or-later). +In addition, this package includes a function to return license ranges for +sequential licenses and ranges including modifiers (i.e. -only, -or-later). [SPDX official machine readable license list]: https://github.com/spdx/license-list-data */ diff --git a/spdxexp/spdxlicenses/license_ranges.go b/spdxexp/spdxlicenses/license_ranges.go index 4fb87da..e5b01be 100644 --- a/spdxexp/spdxlicenses/license_ranges.go +++ b/spdxexp/spdxlicenses/license_ranges.go @@ -1,6 +1,6 @@ package spdxlicenses -// licenseRanges returns a list of license ranges. +// LicenseRanges returns a list of license ranges. // // Ranges are organized into groups (referred to as license groups) of the same base license (e.g. GPL). // Groups have sub-groups of license versions (referred to as the range) where each member is considered