From f67edd76e79fe930db7d2ebcd1369aecab9c179e Mon Sep 17 00:00:00 2001 From: Carlos Panato Date: Wed, 2 Jul 2025 18:18:09 +0200 Subject: [PATCH 1/2] clean up ci, use go 1.24, apply best practices for ci and general clean up Signed-off-by: Carlos Panato --- .github/workflows/ci.yml | 12 +++++-- .github/workflows/codeql.yml | 3 ++ .github/workflows/coverage.yml | 11 ++++-- .github/workflows/dco_merge_group.yaml | 4 ++- .go-version | 1 + .golangci.yml | 49 ++++++++++++++++++++++++++ .goreleaser.yaml | 15 ++++---- DEVELOPMENT.md | 3 +- 8 files changed, 82 insertions(+), 16 deletions(-) create mode 100644 .go-version create mode 100644 .golangci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 33eeeac..01efc8e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,10 +10,15 @@ on: - .gitignore merge_group: +permissions: {} + jobs: lint: runs-on: ubuntu-latest + permissions: + contents: read + env: GOPATH: /home/runner/go @@ -22,20 +27,21 @@ jobs: uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: submodules: recursive + persist-credentials: false - name: Setup Go uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: '1.21' + go-version-file: './.go-version' check-latest: true - name: Format check run: make fmt - name: golangci-lint - uses: golangci/golangci-lint-action@aaa42aa0628b4ae2578232a66b541047968fac86 # v6.1.0 + uses: golangci/golangci-lint-action@4afd733a84b1f43292c63897423277bb7f4313a9 # v8.0.0 with: - version: v1.59 + version: v2.2 args: --build-tags testonly - name: Check generated code diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 30122e0..86daf7c 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -8,6 +8,9 @@ on: schedule: - cron: '21 6 * * 6' + +permissions: {} + jobs: analyze: name: Analyze (${{ matrix.language }}) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 6b6b2eb..5a49ab3 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -13,15 +13,21 @@ on: - main merge_group: + +permissions: {} + jobs: coverage: runs-on: ubuntu-latest + permissions: + contents: read + strategy: matrix: go-version: - - '1.21' - - '1.22' + - '1.23' + - '1.24' env: GOPATH: /home/runner/go @@ -31,6 +37,7 @@ jobs: uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: submodules: recursive + persist-credentials: false - name: Setup Go uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 diff --git a/.github/workflows/dco_merge_group.yaml b/.github/workflows/dco_merge_group.yaml index e00eec9..8f90c0a 100644 --- a/.github/workflows/dco_merge_group.yaml +++ b/.github/workflows/dco_merge_group.yaml @@ -2,9 +2,11 @@ name: DCO on: merge_group: +permissions: {} + jobs: DCO: runs-on: ubuntu-latest if: ${{ github.actor != 'dependabot[bot]' }} steps: - - run: echo "dummy DCO workflow (it won't run any check actually) to trigger by merge_group in order to enable merge queue" \ No newline at end of file + - run: echo "dummy DCO workflow (it won't run any check actually) to trigger by merge_group in order to enable merge queue" diff --git a/.go-version b/.go-version new file mode 100644 index 0000000..7ad7fa0 --- /dev/null +++ b/.go-version @@ -0,0 +1 @@ +1.24.4 \ No newline at end of file diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 0000000..80b2fa3 --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,49 @@ +version: "2" +run: + issues-exit-code: 1 +linters: + enable: + - asciicheck + - errorlint + - gocritic + - gosec + - importas + - misspell + - prealloc + - revive + - staticcheck + - tparallel + - unconvert + - unparam + - whitespace + + exclusions: + generated: lax + presets: + - comments + - common-false-positives + - legacy + - std-error-handling + rules: + - linters: + - errcheck + - gosec + path: _test\.go + paths: + - third_party$ + - builtin$ + - examples$ +issues: + max-issues-per-linter: 0 + max-same-issues: 0 + uniq-by-line: false +formatters: + enable: + - gofmt + - goimports + exclusions: + generated: lax + paths: + - third_party$ + - builtin$ + - examples$ diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 228f884..41ce76d 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -1,6 +1,9 @@ +version: 2 + before: hooks: - go mod tidy + builds: - env: - CGO_ENABLED=0 @@ -8,17 +11,13 @@ builds: - linux - windows - darwin -archives: - - replacements: - darwin: Darwin - linux: Linux - windows: Windows - 386: i386 - amd64: x86_64 + checksum: name_template: 'checksums.txt' + snapshot: - name_template: "{{ incpatch .Version }}-next" + version_template: "{{ incpatch .Version }}-next" + changelog: sort: asc filters: diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index 269a657..d2f8aed 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -17,7 +17,7 @@ You must install these tools: 1. [`git`](https://help.github.com/articles/set-up-git/): For source control 1. [`go`](https://golang.org/doc/install): The language this SDK is built in. - > **Note** Golang [version v1.18](https://golang.org/dl/) or higher is required. + > **Note** Golang [version v1.23](https://golang.org/dl/) or higher is required. 1. [`make`](https://www.gnu.org/software/make/): not stricly required but handy to run tests with a single command. @@ -85,4 +85,3 @@ To run all targets, before creating a commit: ```shell make all ``` - From 1af9686a3f6c3e47de10f3701c28cf0e1e905c0e Mon Sep 17 00:00:00 2001 From: Carlos Panato Date: Thu, 3 Jul 2025 11:22:51 +0200 Subject: [PATCH 2/2] fix lints Signed-off-by: Carlos Panato --- .github/workflows/coverage.yml | 1 + .golangci.yml | 2 +- pkg/api/bindings.go | 6 +++--- pkg/api/bindings_test.go | 11 ++--------- pkg/api/factory.go | 2 +- pkg/api/types.go | 9 +++++---- pkg/api/types_test.go | 8 +------- pkg/api/v03/examples_test.go | 2 -- pkg/api/v03/factory_test.go | 1 - pkg/api/v04/conformance_test.go | 1 - pkg/api/v04/factory_test.go | 1 - tools/generator.go | 14 +++++++------- tools/generator_test.go | 4 +--- 13 files changed, 22 insertions(+), 40 deletions(-) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 5a49ab3..ed25d0b 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -24,6 +24,7 @@ jobs: contents: read strategy: + fail-fast: false matrix: go-version: - '1.23' diff --git a/.golangci.yml b/.golangci.yml index 80b2fa3..5deb73d 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -10,7 +10,7 @@ linters: - importas - misspell - prealloc - - revive + # - revive # disabled due becasue ask to change some variables and functions that might break the api compatibility - staticcheck - tparallel - unconvert diff --git a/pkg/api/bindings.go b/pkg/api/bindings.go index 95738b2..50a441a 100644 --- a/pkg/api/bindings.go +++ b/pkg/api/bindings.go @@ -108,7 +108,7 @@ func AsCloudEvent(event CDEventReader) (*cloudevents.Event, error) { // Validate the event err := Validate(event) if err != nil { - return nil, fmt.Errorf("cannot validate CDEvent %v", err) + return nil, fmt.Errorf("cannot validate CDEvent %w", err) } ce := cloudevents.NewEvent() ce.SetID(event.GetId()) @@ -149,10 +149,10 @@ func Validate(event CDEventReader) error { var v interface{} jsonString, err := AsJsonString(event) if err != nil { - return fmt.Errorf("cannot render the event %s as json %s", event, err) + return fmt.Errorf("cannot render the event %s as json %w", event, err) } if err := json.Unmarshal([]byte(jsonString), &v); err != nil { - return fmt.Errorf("cannot unmarshal event json: %v", err) + return fmt.Errorf("cannot unmarshal event json: %w", err) } // Validate the "validate" tags if err := validate.Struct(event); err != nil { diff --git a/pkg/api/bindings_test.go b/pkg/api/bindings_test.go index 81b1176..b22c25a 100644 --- a/pkg/api/bindings_test.go +++ b/pkg/api/bindings_test.go @@ -143,7 +143,7 @@ func setContext(event api.CDEventWriter, subjectId string) { event.SetSubjectId(subjectId) } -func setContextV04(event api.CDEventWriterV04, chainId, schemaUri bool) { +func setContextV04(event api.CDEventWriterV04, chainId, schemaUri bool) { //nolint: unparam if chainId { event.SetChainId(testChainId) } @@ -239,7 +239,6 @@ func init() { // TestAsCloudEvent produces a CloudEvent from a CDEvent using `AsCloudEvent` // and then attempts to parse the CloudEvent payload back into a specific CDEvent func TestAsCloudEvent(t *testing.T) { - tests := []struct { name string event api.CDEventReader @@ -309,7 +308,6 @@ func TestAsCloudEvent(t *testing.T) { } func TestAsCloudEventInvalid(t *testing.T) { - tests := []struct { name string event api.CDEventReader @@ -353,7 +351,6 @@ func TestAsCloudEventInvalid(t *testing.T) { // rendered JSON depends on a number of factors, and is not deterministic // so we must compare events unmarshalled to an interface func TestAsJsonBytes(t *testing.T) { - tests := []struct { name string event api.CDEvent @@ -393,7 +390,7 @@ func TestAsJsonBytes(t *testing.T) { if err != nil { t.Fatalf("didn't expected it to fail, but it did: %v", err) } - err = json.Unmarshal([]byte(obtainedJsonString), &obtainedInteface) + err = json.Unmarshal(obtainedJsonString, &obtainedInteface) if err != nil { t.Fatalf("didn't expected it to fail, but it did: %v", err) } @@ -409,7 +406,6 @@ func TestAsJsonBytes(t *testing.T) { } func TestInvalidEvent(t *testing.T) { - // mandatory source missing eventNoSource, _ := testapi.NewFooSubjectBarPredicateEvent() eventNoSource.SetSubjectId(testSubjectId) @@ -506,7 +502,6 @@ func TestAsJsonStringEmpty(t *testing.T) { } func TestNewFromJsonString(t *testing.T) { - tests := []struct { name string event api.CDEventV04 @@ -582,7 +577,6 @@ func TestNewFromJsonString(t *testing.T) { } func TestParseType(t *testing.T) { - tests := []struct { name string eventType string @@ -668,7 +662,6 @@ func testEventWithVersion(eventVersion string, specVersion string) *testapi.FooS } func TestNewFromJsonBytes(t *testing.T) { - minorVersion := testEventWithVersion("2.999.1", testapi.SpecVersion) patchVersion := testEventWithVersion("2.2.999", testapi.SpecVersion) pastPatchVersion := testEventWithVersion("2.2.0", testapi.SpecVersion) diff --git a/pkg/api/factory.go b/pkg/api/factory.go index db72fae..51c0560 100644 --- a/pkg/api/factory.go +++ b/pkg/api/factory.go @@ -28,7 +28,7 @@ import ( var timeNow = time.Now var uuidNewRandom = uuid.NewRandom -func initCDEvent(e CDEvent) (CDEvent, error) { +func initCDEvent(e CDEvent) (CDEvent, error) { //nolint: unparam eventUUID, err := uuidNewRandom() if err != nil { return nil, err diff --git a/pkg/api/types.go b/pkg/api/types.go index 87327db..00084e6 100644 --- a/pkg/api/types.go +++ b/pkg/api/types.go @@ -290,28 +290,29 @@ func (ela *EmbeddedLinksArray) UnmarshalJSON(b []byte) error { if err != nil { return err } - if m.LinkType == LinkTypeEnd { + switch m.LinkType { + case LinkTypeEnd: var e embeddedLinkEnd err = json.Unmarshal(*rawEmbeddedLink, &e) if err != nil { return err } receiver[index] = &e - } else if m.LinkType == LinkTypePath { + case LinkTypePath: var e embeddedLinkPath err = json.Unmarshal(*rawEmbeddedLink, &e) if err != nil { return err } receiver[index] = &e - } else if m.LinkType == LinkTypeRelation { + case LinkTypeRelation: var e embeddedLinkRelation err = json.Unmarshal(*rawEmbeddedLink, &e) if err != nil { return err } receiver[index] = &e - } else { + default: return fmt.Errorf("unsupported link type %s found", m.LinkType) } } diff --git a/pkg/api/types_test.go b/pkg/api/types_test.go index 180f6c6..d612cbd 100644 --- a/pkg/api/types_test.go +++ b/pkg/api/types_test.go @@ -76,7 +76,6 @@ type testWrongType struct { } func TestGetCustomDataAsNonJson(t *testing.T) { - receiver := &testType{} expectedError := "cannot unmarshal content-type application/xml" @@ -91,7 +90,6 @@ func TestGetCustomDataAsNonJson(t *testing.T) { } func TestGetCustomDataAsJson(t *testing.T) { - receiver := &testType{} expectedValue := "testValue" @@ -127,7 +125,6 @@ func TestGetCustomDataAsJson(t *testing.T) { } func TestGetCustomDataAsJsonInvalidReceiver(t *testing.T) { - receiver := &testWrongType{} expectedReceiver := &testWrongType{} @@ -163,7 +160,6 @@ func TestGetCustomDataAsJsonInvalidReceiver(t *testing.T) { } func TestSetCustomData(t *testing.T) { - tests := []struct { name string contentType string @@ -215,7 +211,6 @@ func TestSetCustomDataInvalid(t *testing.T) { } func TestGetCustomData(t *testing.T) { - tests := []struct { name string contentType string @@ -302,7 +297,6 @@ func TestGetCustomDataXmlNotBytes(t *testing.T) { } func TestGetCustomDataRaw(t *testing.T) { - tests := []struct { name string contentType string @@ -327,7 +321,7 @@ func TestGetCustomDataRaw(t *testing.T) { name: "json, interface", contentType: "application/json", data: testType{TestData: "testValue"}, - expectedData: []byte(testJsonString), + expectedData: testJsonString, }} for _, tc := range tests { diff --git a/pkg/api/v03/examples_test.go b/pkg/api/v03/examples_test.go index 9c43840..19103d0 100644 --- a/pkg/api/v03/examples_test.go +++ b/pkg/api/v03/examples_test.go @@ -376,7 +376,6 @@ func exampleTestOutputPublishedEvent(e *apiv03.TestOutputPublishedEvent) { } func init() { - // Load event examples from the spec examplesConsumed = make(map[string][]byte) @@ -394,7 +393,6 @@ func init() { // - it parses the examples into a CDEvent and // - it verifies that produced and consumed CDEvent match func TestExamples(t *testing.T) { - for name, exampleConsumed := range examplesConsumed { t.Run(name, func(t *testing.T) { produced, ok := examplesProduced[name] diff --git a/pkg/api/v03/factory_test.go b/pkg/api/v03/factory_test.go index eae6f0a..59a752c 100644 --- a/pkg/api/v03/factory_test.go +++ b/pkg/api/v03/factory_test.go @@ -129,7 +129,6 @@ func TestNewCDEvent(t *testing.T) { } func TestNewCDEventFailed(t *testing.T) { - _, err := cdevents.NewCDEvent(api.CDEventType{Subject: "not supported"}.String(), testSpecVersion) if err == nil { t.Fatalf("expected it to fail, but it didn't") diff --git a/pkg/api/v04/conformance_test.go b/pkg/api/v04/conformance_test.go index f26452f..ec5e285 100644 --- a/pkg/api/v04/conformance_test.go +++ b/pkg/api/v04/conformance_test.go @@ -562,7 +562,6 @@ func exampleCustomTypeEvent(e *apiv04.CustomTypeEvent) { // - it parses the examples into a CDEvent and // - it verifies that produced and consumed CDEvent match func TestExamples(t *testing.T) { - for name, exampleConsumed := range examplesConsumed { t.Run(name, func(t *testing.T) { produced, ok := examplesProduced[name] diff --git a/pkg/api/v04/factory_test.go b/pkg/api/v04/factory_test.go index c8c0f10..6b8e0ab 100644 --- a/pkg/api/v04/factory_test.go +++ b/pkg/api/v04/factory_test.go @@ -129,7 +129,6 @@ func TestNewCDEvent(t *testing.T) { } func TestNewCDEventFailed(t *testing.T) { - _, err := cdevents.NewCDEvent(api.CDEventType{Subject: "not supported"}.String(), testSpecVersion) if err == nil { t.Fatalf("expected it to fail, but it didn't") diff --git a/tools/generator.go b/tools/generator.go index 0871249..60cceed 100644 --- a/tools/generator.go +++ b/tools/generator.go @@ -329,7 +329,7 @@ func loadSchemas(schemaFolder string, schemas *Schemas) error { return nil } else { // Something else went wrong - return fmt.Errorf("error loading schemas from %s: %s", schemaFolder, err) + return fmt.Errorf("error loading schemas from %s: %w", schemaFolder, err) } } return fs.WalkDir(os.DirFS(schemaFolder), ".", getSchemasWalkProcessor(schemaFolder, schemas)) @@ -343,7 +343,7 @@ func generate(schemaFolders []string, genFolder, prefix, specVersion string, tem Slice: make([]Data, 0), SpecVersion: specVersion, SpecVersionShort: shortSpecVersion, - SpecVersionName: strings.Replace(shortSpecVersion, ".", "", -1), + SpecVersionName: strings.ReplaceAll(shortSpecVersion, ".", ""), IsTestData: isTestMode, } @@ -410,7 +410,7 @@ func executeTemplate(templates *template.Template, templateName, outputFileName } // Prepare the output file - return os.WriteFile(outputFileName, src, 0644) + return os.WriteFile(outputFileName, src, 0644) //nolint: gosec } func getSchemasWalkProcessor(rootDir string, schemas *Schemas) fs.WalkDirFunc { @@ -433,14 +433,14 @@ func getSchemasWalkProcessor(rootDir string, schemas *Schemas) fs.WalkDirFunc { schemaPath := filepath.Join(rootDir, path) schemaBytes, err := os.ReadFile(schemaPath) if err != nil { - return fmt.Errorf("cannot read schema file at %s: %v", schemaPath, err) + return fmt.Errorf("cannot read schema file at %s: %w", schemaPath, err) } schema := struct { Id string `json:"$id"` }{} // Load the jsonschema from the spec if err := json.Unmarshal(schemaBytes, &schema); err != nil { - return fmt.Errorf("cannot unmarshal schema file at %s: %v", schemaPath, err) + return fmt.Errorf("cannot unmarshal schema file at %s: %w", schemaPath, err) } // If no $id is defined ignore this file if schema.Id == "" { @@ -451,7 +451,7 @@ func getSchemasWalkProcessor(rootDir string, schemas *Schemas) fs.WalkDirFunc { for original, fixed := range JSON_SCHEMA_NAMES { schemaId = strings.Replace(schemaId, original, fixed, 1) } - (*schemas).Data[schemaId] = schemaBytes + schemas.Data[schemaId] = schemaBytes return nil } } @@ -578,7 +578,7 @@ func DataFromSchema(schema *jsonschema.Schema, mappings map[string]string, specV if eventTypeString == "" { return nil, fmt.Errorf("empty value defined for type in schema %s", eventTypeSchema.Location) } - eventType, err = cdeventTypeFromString(string(eventTypeString)) + eventType, err = cdeventTypeFromString(eventTypeString) if err != nil { return nil, err } diff --git a/tools/generator_test.go b/tools/generator_test.go index bc5f08f..8a8b507 100644 --- a/tools/generator_test.go +++ b/tools/generator_test.go @@ -72,7 +72,6 @@ func init() { } func TestDataFromSchema(t *testing.T) { - want := &Data{ Subject: testSubject, Predicate: testPredicate, @@ -121,7 +120,7 @@ func TestDataFromSchema(t *testing.T) { } got, err := DataFromSchema(testSchema, mappings, "0.1.2") if err != nil { - t.Fatalf(err.Error()) + t.Fatal(err.Error()) } less := func(a, b ContentField) bool { return a.Name < b.Name } if d := cmp.Diff(want, got, cmpopts.SortSlices(less)); d != "" { @@ -221,7 +220,6 @@ func TestExecuteTemplate_Error(t *testing.T) { // TestValidateStringEnumAnyOf tests the validation of the string enum anyOf case. func TestValidateStringEnumAnyOf(t *testing.T) { - var boolType jsonschema.Types = 4 var stringType jsonschema.Types = 32 tests := []struct {