From cfd113c4238107ad68e1ecfa6ed600567841b5bf Mon Sep 17 00:00:00 2001 From: Jonathan VUILLEMIN Date: Wed, 10 Jan 2024 12:54:12 +0100 Subject: [PATCH] feat(generate): Provided module (#5) --- .github/workflows/coverage.yml | 1 + .github/workflows/generate-ci.yml | 31 +++++++++ README.md | 2 +- generate/.golangci.yml | 66 ++++++++++++++++++ generate/README.md | 72 ++++++++++++++++++++ generate/generatetest/uuid/generator.go | 27 ++++++++ generate/generatetest/uuid/generator_test.go | 38 +++++++++++ generate/go.mod | 14 ++++ generate/go.sum | 12 ++++ generate/uuid/factory.go | 22 ++++++ generate/uuid/factory_test.go | 40 +++++++++++ generate/uuid/generator.go | 23 +++++++ generate/uuid/generator_test.go | 40 +++++++++++ release-please-config.json | 5 ++ 14 files changed, 392 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/generate-ci.yml create mode 100644 generate/.golangci.yml create mode 100644 generate/README.md create mode 100644 generate/generatetest/uuid/generator.go create mode 100644 generate/generatetest/uuid/generator_test.go create mode 100644 generate/go.mod create mode 100644 generate/go.sum create mode 100644 generate/uuid/factory.go create mode 100644 generate/uuid/factory_test.go create mode 100644 generate/uuid/generator.go create mode 100644 generate/uuid/generator_test.go diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index db8ea76..8d5138d 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -21,6 +21,7 @@ jobs: matrix: module: - "config" + - "generate" - "log" runs-on: ubuntu-latest diff --git a/.github/workflows/generate-ci.yml b/.github/workflows/generate-ci.yml new file mode 100644 index 0000000..5b944f5 --- /dev/null +++ b/.github/workflows/generate-ci.yml @@ -0,0 +1,31 @@ +name: "generate-ci" + +on: + push: + branches: + - "feat**" + - "fix**" + - "hotfix**" + - "chore**" + paths: + - "generate/**.go" + - "generate/go.mod" + - "generate/go.sum" + pull_request: + types: + - opened + - synchronize + - reopened + branches: + - main + paths: + - "generate/**.go" + - "generate/go.mod" + - "generate/go.sum" + +jobs: + ci: + uses: ./.github/workflows/common-ci.yml + secrets: inherit + with: + module: "generate" diff --git a/README.md b/README.md index b8a67a2..596ce01 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Yokai -[![Go version](https://img.shields.io/badge/go-%3E%3D1.20-blue)](https://go.dev/) +[![Go version](https://img.shields.io/badge/Go-1.20-blue)](https://go.dev/) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) > Simple, modular, and observable Go framework. diff --git a/generate/.golangci.yml b/generate/.golangci.yml new file mode 100644 index 0000000..edf0e9e --- /dev/null +++ b/generate/.golangci.yml @@ -0,0 +1,66 @@ +run: + timeout: 5m + concurrency: 8 + +linters: + enable: + - asasalint + - asciicheck + - bidichk + - bodyclose + - containedctx + - contextcheck + - cyclop + - decorder + - dogsled + - dupl + - durationcheck + - errcheck + - errchkjson + - errname + - errorlint + - exhaustive + - forbidigo + - forcetypeassert + - gocognit + - goconst + - gocritic + - gocyclo + - godot + - godox + - gofmt + - goheader + - gomoddirectives + - gomodguard + - goprintffuncname + - gosec + - gosimple + - govet + - grouper + - importas + - ineffassign + - interfacebloat + - logrlint + - maintidx + - makezero + - misspell + - nestif + - nilerr + - nilnil + - nlreturn + - nolintlint + - nosprintfhostport + - prealloc + - predeclared + - promlinter + - reassign + - staticcheck + - tenv + - thelper + - tparallel + - typecheck + - unconvert + - unparam + - unused + - usestdlibvars + - whitespace diff --git a/generate/README.md b/generate/README.md new file mode 100644 index 0000000..b7dfa4f --- /dev/null +++ b/generate/README.md @@ -0,0 +1,72 @@ +# Generate Module + +[![ci](https://github.com/ankorstore/yokai/actions/workflows/generate-ci.yml/badge.svg)](https://github.com/ankorstore/yokai/actions/workflows/generate-ci.yml) +[![go report](https://goreportcard.com/badge/github.com/ankorstore/yokai/generate)](https://goreportcard.com/report/github.com/ankorstore/yokai/generate) +[![codecov](https://codecov.io/gh/ankorstore/yokai/graph/badge.svg?token=5s0g5WyseS&flag=generate)](https://app.codecov.io/gh/ankorstore/yokai/tree/main/generate) +[![PkgGoDev](https://pkg.go.dev/badge/github.com/ankorstore/yokai/generate)](https://pkg.go.dev/github.com/ankorstore/yokai/generate) + +> Generation module based on [Google UUID](https://github.com/google/uuid). + + + +* [Installation](#installation) +* [Documentation](#documentation) + * [UUID](#uuid) + + + +## Installation + +```shell +go get github.com/ankorstore/yokai/generate +``` + +## Documentation + +### UUID + +This module provides an [UuidGenerator](uuid/generator.go) interface, allowing to generate UUIDs. + +The `DefaultUuidGenerator` is based on [Google UUID](https://github.com/google/uuid). + +```go +package main + +import ( + "fmt" + + "github.com/ankorstore/yokai/generate/uuid" + uuidtest "github.com/ankorstore/yokai/generate/generatetest/uuid" +) + +func main() { + // default UUID generator + generator := uuid.NewDefaultUuidGenerator() + fmt.Printf("uuid: %s", generator.Generate()) // uuid: dcb5d8b3-4517-4957-a42c-604d11758561 + + // test UUID generator (with deterministic value for testing) + testGenerator := uuidtest.NewTestUuidGenerator("test") + fmt.Printf("uuid: %s", testGenerator.Generate()) // uuid: test +} +``` + +The module also provides a [UuidGeneratorFactory](uuid/factory.go) interface, to create +the [UuidGenerator](uuid/generator.go) instances. + +The `DefaultUuidGeneratorFactory` generates `DefaultUuidGenerator` instances. + +```go +package main + +import ( + "fmt" + + "github.com/ankorstore/yokai/generate/uuid" +) + +func main() { + // default UUID generator factory + generator := uuid.NewDefaultUuidGeneratorFactory().Create() + fmt.Printf("uuid: %s", generator.Generate()) // uuid: dcb5d8b3-4517-4957-a42c-604d11758561 +} +``` \ No newline at end of file diff --git a/generate/generatetest/uuid/generator.go b/generate/generatetest/uuid/generator.go new file mode 100644 index 0000000..594e44f --- /dev/null +++ b/generate/generatetest/uuid/generator.go @@ -0,0 +1,27 @@ +package uuid + +// TestUuidGenerator is a [UuidGenerator] implementation allowing deterministic generations (for testing). +type TestUuidGenerator struct { + value string +} + +// NewTestUuidGenerator returns a [TestUuidGenerator], implementing [UuidGenerator]. +// +// It accepts a value that will be used for deterministic generation results. +func NewTestUuidGenerator(value string) *TestUuidGenerator { + return &TestUuidGenerator{ + value: value, + } +} + +// SetValue sets the value to use for deterministic generations. +func (g *TestUuidGenerator) SetValue(value string) *TestUuidGenerator { + g.value = value + + return g +} + +// Generate returns the configured deterministic value. +func (g *TestUuidGenerator) Generate() string { + return g.value +} diff --git a/generate/generatetest/uuid/generator_test.go b/generate/generatetest/uuid/generator_test.go new file mode 100644 index 0000000..0105509 --- /dev/null +++ b/generate/generatetest/uuid/generator_test.go @@ -0,0 +1,38 @@ +package uuid_test + +import ( + "testing" + + uuidtest "github.com/ankorstore/yokai/generate/generatetest/uuid" + "github.com/ankorstore/yokai/generate/uuid" + "github.com/stretchr/testify/assert" +) + +func TestNewTestUuidGenerator(t *testing.T) { + t.Parallel() + + generator := uuidtest.NewTestUuidGenerator("random") + + assert.IsType(t, &uuidtest.TestUuidGenerator{}, generator) + assert.Implements(t, (*uuid.UuidGenerator)(nil), generator) +} + +func TestGenerate(t *testing.T) { + t.Parallel() + + generator := uuidtest.NewTestUuidGenerator("test") + + value1 := generator.Generate() + value2 := generator.Generate() + + assert.Equal(t, "test", value1) + assert.Equal(t, "test", value2) + + generator.SetValue("other test") + + value1 = generator.Generate() + value2 = generator.Generate() + + assert.Equal(t, "other test", value1) + assert.Equal(t, "other test", value2) +} diff --git a/generate/go.mod b/generate/go.mod new file mode 100644 index 0000000..7db6a43 --- /dev/null +++ b/generate/go.mod @@ -0,0 +1,14 @@ +module github.com/ankorstore/yokai/generate + +go 1.20 + +require ( + github.com/google/uuid v1.3.0 + github.com/stretchr/testify v1.8.4 +) + +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/generate/go.sum b/generate/go.sum new file mode 100644 index 0000000..8d8b455 --- /dev/null +++ b/generate/go.sum @@ -0,0 +1,12 @@ +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/generate/uuid/factory.go b/generate/uuid/factory.go new file mode 100644 index 0000000..bb58818 --- /dev/null +++ b/generate/uuid/factory.go @@ -0,0 +1,22 @@ +package uuid + +// UuidGeneratorFactory is the interface for [UuidGenerator] factories. +type UuidGeneratorFactory interface { + Create() UuidGenerator +} + +// DefaultUuidGeneratorFactory is the default [UuidGeneratorFactory] implementation. +type DefaultUuidGeneratorFactory struct{} + +// NewDefaultUuidGeneratorFactory returns a [DefaultUuidGeneratorFactory], implementing [UuidGeneratorFactory]. +func NewDefaultUuidGeneratorFactory() UuidGeneratorFactory { + return &DefaultUuidGeneratorFactory{} +} + +// Create returns a new [UuidGenerator]. +// For example: +// +// var generator, _ = uuid.NewDefaultConfigFactory().Create() +func (g *DefaultUuidGeneratorFactory) Create() UuidGenerator { + return NewDefaultUuidGenerator() +} diff --git a/generate/uuid/factory_test.go b/generate/uuid/factory_test.go new file mode 100644 index 0000000..165a7ee --- /dev/null +++ b/generate/uuid/factory_test.go @@ -0,0 +1,40 @@ +package uuid_test + +import ( + "testing" + + "github.com/ankorstore/yokai/generate/uuid" + googleuuid "github.com/google/uuid" + "github.com/stretchr/testify/assert" +) + +func TestNewDefaultUuidGeneratorFactory(t *testing.T) { + t.Parallel() + + factory := uuid.NewDefaultUuidGeneratorFactory() + + assert.IsType(t, &uuid.DefaultUuidGeneratorFactory{}, factory) + assert.Implements(t, (*uuid.UuidGeneratorFactory)(nil), factory) +} + +func TestCreate(t *testing.T) { + t.Parallel() + + generator := uuid.NewDefaultUuidGeneratorFactory().Create() + + value1 := generator.Generate() + value2 := generator.Generate() + + assert.NotEqual(t, value1, value2) + + parsedValue1, err := googleuuid.Parse(value1) + assert.NoError(t, err) + + parsedValue2, err := googleuuid.Parse(value2) + assert.NoError(t, err) + + assert.NotEqual(t, parsedValue1.String(), parsedValue2.String()) + + assert.Equal(t, value1, parsedValue1.String()) + assert.Equal(t, value2, parsedValue2.String()) +} diff --git a/generate/uuid/generator.go b/generate/uuid/generator.go new file mode 100644 index 0000000..3138097 --- /dev/null +++ b/generate/uuid/generator.go @@ -0,0 +1,23 @@ +package uuid + +import googleuuid "github.com/google/uuid" + +// UuidGenerator is the interface for UUID generators. +type UuidGenerator interface { + Generate() string +} + +// DefaultUuidGenerator is the default [UuidGenerator] implementation. +type DefaultUuidGenerator struct{} + +// NewDefaultUuidGenerator returns a [DefaultUuidGenerator], implementing [UuidGenerator]. +func NewDefaultUuidGenerator() *DefaultUuidGenerator { + return &DefaultUuidGenerator{} +} + +// Generate returns a new UUID, using [Google UUID]. +// +// [Google UUID]: https://github.com/google/uuid +func (g *DefaultUuidGenerator) Generate() string { + return googleuuid.New().String() +} diff --git a/generate/uuid/generator_test.go b/generate/uuid/generator_test.go new file mode 100644 index 0000000..0b6c5a2 --- /dev/null +++ b/generate/uuid/generator_test.go @@ -0,0 +1,40 @@ +package uuid_test + +import ( + "testing" + + "github.com/ankorstore/yokai/generate/uuid" + googleuuid "github.com/google/uuid" + "github.com/stretchr/testify/assert" +) + +func TestNewDefaultUuidGenerator(t *testing.T) { + t.Parallel() + + generator := uuid.NewDefaultUuidGenerator() + + assert.IsType(t, &uuid.DefaultUuidGenerator{}, generator) + assert.Implements(t, (*uuid.UuidGenerator)(nil), generator) +} + +func TestGenerate(t *testing.T) { + t.Parallel() + + generator := uuid.NewDefaultUuidGenerator() + + value1 := generator.Generate() + value2 := generator.Generate() + + assert.NotEqual(t, value1, value2) + + parsedValue1, err := googleuuid.Parse(value1) + assert.NoError(t, err) + + parsedValue2, err := googleuuid.Parse(value2) + assert.NoError(t, err) + + assert.NotEqual(t, parsedValue1.String(), parsedValue2.String()) + + assert.Equal(t, value1, parsedValue1.String()) + assert.Equal(t, value2, parsedValue2.String()) +} diff --git a/release-please-config.json b/release-please-config.json index 12fc6b8..42325f6 100644 --- a/release-please-config.json +++ b/release-please-config.json @@ -6,6 +6,11 @@ "component": "config", "tag-separator": "/" }, + "generate": { + "release-type": "go", + "component": "generate", + "tag-separator": "/" + }, "log": { "release-type": "go", "component": "log",