Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

12 add api documentation #7

Open
wants to merge 87 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
87 commits
Select commit Hold shift + click to select a range
4d7a7dd
remove core limitation
matheuspolitano Dec 23, 2024
6c29e2f
fix main bugs
matheuspolitano Dec 24, 2024
1601264
fix main bugs
matheuspolitano Dec 24, 2024
1310b7b
down go version
matheuspolitano Dec 24, 2024
aa08816
add release file
matheuspolitano Dec 24, 2024
8e08e34
add release info in readme
matheuspolitano Dec 24, 2024
70f5b75
Merge pull request #1 from matheuspolitano/1-fix-main-bugs
matheuspolitano Dec 24, 2024
0982ac0
add new pipeline
matheuspolitano Dec 24, 2024
011b3a8
Merge pull request #2 from matheuspolitano/1-fix-main-bugs-1
matheuspolitano Dec 24, 2024
fee950d
fix pipeline
matheuspolitano Dec 24, 2024
6df7c14
Merge pull request #3 from matheuspolitano/1-fix-main-bugs-2
matheuspolitano Dec 24, 2024
3690243
Add new release file release_20241224104515.toml
github-actions[bot] Dec 24, 2024
4285907
improve the pipeline
matheuspolitano Dec 24, 2024
015183f
update release
matheuspolitano Dec 24, 2024
9a12574
Merge pull request #4 from matheuspolitano/2-improve-the-pipeline
matheuspolitano Dec 24, 2024
e8914ac
Add new release file release_20241224105329.toml
github-actions[bot] Dec 24, 2024
a363d78
pipeline adjust
matheuspolitano Dec 24, 2024
c9c86ad
Merge pull request #5 from matheuspolitano/3-remove-release-file
matheuspolitano Dec 24, 2024
d51f15e
Add new release file release_20241224111005.toml
github-actions[bot] Dec 24, 2024
d766a84
improve errors messages
matheuspolitano Dec 24, 2024
375a284
ädd local env and extras check in config
matheuspolitano Dec 24, 2024
a4e8ec9
change main go file
matheuspolitano Dec 24, 2024
497f3c8
add config
matheuspolitano Dec 24, 2024
4b0ed73
add config test
matheuspolitano Dec 24, 2024
e904542
run in sequence de config test and improve the config
matheuspolitano Dec 24, 2024
29e68c4
fix type error in port
matheuspolitano Dec 24, 2024
314338f
add note in release
matheuspolitano Dec 24, 2024
90991ca
improve task detail
matheuspolitano Dec 24, 2024
858c708
Merge pull request #6 from matheuspolitano/5-improve-config
matheuspolitano Dec 24, 2024
55ba43f
Add new release file release_20241224141902.toml
github-actions[bot] Dec 24, 2024
8a9556d
update readme
matheuspolitano Dec 24, 2024
049a9af
update readme
matheuspolitano Dec 24, 2024
0a5b0ce
update readme
matheuspolitano Dec 24, 2024
be3a5b7
update readme
matheuspolitano Dec 24, 2024
76b5c7f
add myduration
matheuspolitano Dec 25, 2024
6fc90b0
add test
matheuspolitano Dec 25, 2024
29092dc
add release
matheuspolitano Dec 25, 2024
ecb6071
Merge pull request #8 from matheuspolitano/7-improve-time-alive
matheuspolitano Dec 25, 2024
3e48f98
Add new release file release_20241225114904.toml
github-actions[bot] Dec 25, 2024
650acee
improve main.go and server start and shutdown
matheuspolitano Dec 25, 2024
dadf977
improve readme
matheuspolitano Dec 25, 2024
37eecea
Merge pull request #9 from matheuspolitano/6-improve-main.go
matheuspolitano Dec 25, 2024
81a767c
Add new release file release_20241225141728.toml
github-actions[bot] Dec 25, 2024
f6d55be
add env as type
matheuspolitano Dec 25, 2024
c99942f
add new pacakge and set new test
matheuspolitano Dec 25, 2024
d7b3d96
add production mod
matheuspolitano Dec 25, 2024
a94b47f
remove useless comments
matheuspolitano Dec 25, 2024
798ec5a
add max age
matheuspolitano Dec 25, 2024
e2dfaa5
improve response
matheuspolitano Dec 25, 2024
aa4a2f6
improve config and add new config
matheuspolitano Dec 25, 2024
1e16f01
update dockerimage
matheuspolitano Dec 25, 2024
4c3e893
add in readme
matheuspolitano Dec 25, 2024
2ad6d1f
add release
matheuspolitano Dec 25, 2024
aa6389b
update go version
matheuspolitano Dec 25, 2024
d355e9b
update pipeline and go version
matheuspolitano Dec 25, 2024
e1b534d
ignore scripts
matheuspolitano Dec 26, 2024
57f302b
improve release pipeline
matheuspolitano Dec 26, 2024
215b9c5
add ignore
matheuspolitano Dec 26, 2024
6a874e9
improve the validate release
matheuspolitano Dec 26, 2024
088cedf
improve release
matheuspolitano Dec 26, 2024
da84809
add response
matheuspolitano Dec 26, 2024
bdc9bbe
improve format
matheuspolitano Dec 26, 2024
49429e7
update release
matheuspolitano Dec 26, 2024
79b53c0
fix test
matheuspolitano Dec 26, 2024
c2db65b
Merge pull request #10 from matheuspolitano/7-improve-gin-api
matheuspolitano Dec 26, 2024
0b2c8a2
Add new release file release_20241226171013.toml
github-actions[bot] Dec 26, 2024
f203a84
improve memdb
matheuspolitano Dec 26, 2024
1cea555
Merge pull request #11 from matheuspolitano/8-improve-repository
matheuspolitano Dec 26, 2024
a8acdba
Add new release file release_20241226174317.toml
github-actions[bot] Dec 26, 2024
caa30ad
add docker
matheuspolitano Dec 26, 2024
69069d6
add release
matheuspolitano Dec 26, 2024
aad42e9
add release
matheuspolitano Dec 26, 2024
80eccc2
Merge pull request #12 from matheuspolitano/9-setup-docker
matheuspolitano Dec 27, 2024
c245e41
Release: Add release_20241227000208.toml
github-actions[bot] Dec 27, 2024
64c930a
cicd adjust
matheuspolitano Dec 27, 2024
ebc0cf5
Merge pull request #13 from matheuspolitano/10-migrate-deploy-file
matheuspolitano Dec 27, 2024
dedcac4
Release: Add release_20241227122723.toml
github-actions[bot] Dec 27, 2024
5166895
11 improve service #major (#14)
matheuspolitano Dec 27, 2024
06ac48a
Release: Add release_20241227124702.toml
github-actions[bot] Dec 27, 2024
cde0067
add doc
matheuspolitano Dec 27, 2024
e5c9e4b
improve readme
matheuspolitano Dec 27, 2024
9fa2a51
improve readme
matheuspolitano Dec 27, 2024
12d5bb3
improve readme
matheuspolitano Dec 27, 2024
10af987
improve readme
matheuspolitano Dec 27, 2024
89cbe2a
improve readme
matheuspolitano Dec 27, 2024
94d8b9a
add latest push in docker
matheuspolitano Dec 27, 2024
5704f8e
go mod tidy
matheuspolitano Dec 27, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,7 @@ docs/generated/

# Cache directories
.cache/


# Ignore personal test file
test2.go
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
test:
go test -v -cover -short ./...
44 changes: 40 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,56 @@

This repository was created from the repository at https://github.com/SchwarzIT/go-code-review to make corrections and improvements

## Releases
## 📦 Configuration

Configure the application using environment variables with support for a `.env` file and default values.

### Environment Variables

- **`API_PORT`**
- **required**
- **`API_ENV`**
- **Default:** `dev`
- **`API_TIMEALIVE`**
- **Format:** Specify the duration using units like s (seconds), m (minutes), h (hours), d (days), w (weeks), or y (years). Example: 10d 10w 1y.
- **Without value:** API will run without duration

### `.env` File

Create a `.env` file in the project root to set default values:

```dotenv
API_PORT=9090
API_ENV=production
API_TIMEALIVE=1y
```

### Precedence

1. **System Environment Variables** override `.env` values.
2. **`.env` File** provides defaults.
3. **Struct Defaults** apply if neither is set.

**Example:**

- `.env` has `API_PORT=9090`
- System sets `API_PORT=7070`
- **Effective `API_PORT`:** `7070`

## 📄 Releases

The releases folder is used to store version-specific metadata for project updates, such as features, improvements, and bug fixes. Each release file is structured using the standard template located at ./templates/release.toml.

Workflow Automation
The repository includes a CI/CD pipeline to validate and manage release files:

1. Validation:
When a pull request is opened or updated, the pipeline validates the release.toml file using the script scripts/validate_release.go to ensure it follows the required structure.
When a pull request is opened or updated, the pipeline validates the release.toml file using the script `scripts/validate_release.go` to ensure it follows the required structure.
2. Merge Handling:
When a pull request is merged, the pipeline automatically moves the validated release.toml file into the releases folder, renaming it with a timestamp for unique identification.
When a pull request is merged, the pipeline automatically moves the validated `release.toml` file into the releases folder, renaming it with a timestamp for unique identification.

### How to Add a New Release:

1. Use the provided template at ./templates/release.toml to create a new release file.
1. Use the provided template at `./templates/release.toml` to create a new release file.
2. Ensure the file is added to your pull request and follows the required structure.
3. Upon merging, the CI/CD pipeline will handle validation and placement in the releases folder.
12 changes: 9 additions & 3 deletions cmd/coupon_service/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,28 @@ import (
"coupon_service/internal/service"
"fmt"
"log"
"os"
"syscall"
"time"
)

var (
repo = memdb.New()
)
var interruptSignals = []os.Signal{
os.Interrupt,
syscall.SIGTERM,
syscall.SIGINT,
}

func main() {
cfg, err := config.New()
if err != nil {
log.Fatal(err)
}

repo := memdb.New()
svc := service.New(repo)

server := api.New(cfg.API, svc)

server.Start()
fmt.Println("Starting Coupon service server")
<-time.After(1 * time.Hour * 24 * 365)
Expand Down
14 changes: 9 additions & 5 deletions internal/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package api

import (
"context"
"coupon_service/internal/myduration"
"coupon_service/internal/service/entity"
"fmt"
"log"
Expand All @@ -18,8 +19,9 @@ type Service interface {
}

type Config struct {
Port string `env:"API_PORT" default:"8080"`
Env string `env:"API_ENV" default:"dev"`
Port string `env:"API_PORT"`
Env string `env:"API_ENV"`
TimeAlive myduration.MyDuration `env:"API_TIMEALIVE"`
}

type API struct {
Expand Down Expand Up @@ -54,10 +56,12 @@ func (a API) withRoutes() API {
return a
}

func (a API) Start() {
if err := a.srv.ListenAndServe(); err != nil {
log.Fatal(err)
func (a API) Start() (err error) {
err = a.srv.ListenAndServe()
if err != nil {
return
}
return
}

func (a API) Close() {
Expand Down
8 changes: 6 additions & 2 deletions internal/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ package config_test

import (
"coupon_service/internal/config"
"coupon_service/internal/myduration"
"os"
"path/filepath"
"testing"
"time"

"github.com/stretchr/testify/assert"
)
Expand Down Expand Up @@ -46,16 +48,16 @@ func TestNewConfig(t *testing.T) {
clearEnvVars(t)

// Create a temporary .env file
envContent := "API_PORT=9090\nAPI_ENV=production\n"
envContent := "API_PORT=9090\nAPI_ENV=production\nAPI_TIME_ALIVE=1y\nAPI_TIMEALIVE=1y\n"
envPath := createTempEnvFile(t, envContent)

// Load the .env file
cfg, err := config.New(envPath)
assert.NoError(t, err, "Expected no error when loading config from .env")

// Assert the values loaded from .env
assert.Equal(t, "9090", cfg.API.Port, "API.Port should be loaded from .env")
assert.Equal(t, "production", cfg.API.Env, "API.Env should be loaded from .env")
assert.Equal(t, time.Duration(1)*time.Hour*myduration.HoursInDay*myduration.DaysInYear, cfg.API.TimeAlive.ParseTimeDuration(), "API.TIMEALIVE should be loaded from system environment")

// Cleanup: Unset environment variables set by .env
t.Cleanup(func() {
Expand All @@ -72,6 +74,7 @@ func TestNewConfig(t *testing.T) {
// Set environment variables using t.Setenv for automatic cleanup
t.Setenv("API_PORT", "7070")
t.Setenv("API_ENV", "staging")
t.Setenv("API_TIMEALIVE", "1y")

// Load config without a .env file
cfg, err := config.New("")
Expand All @@ -80,6 +83,7 @@ func TestNewConfig(t *testing.T) {
// Assert the values loaded from system environment
assert.Equal(t, "7070", cfg.API.Port, "API.Port should be loaded from system environment")
assert.Equal(t, "staging", cfg.API.Env, "API.Env should be loaded from system environment")
assert.Equal(t, time.Duration(1)*time.Hour*myduration.HoursInDay*myduration.DaysInYear, cfg.API.TimeAlive.ParseTimeDuration(), "API.TIMEALIVE should be loaded from system environment")
},
},
{
Expand Down
75 changes: 75 additions & 0 deletions internal/myduration/time.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package myduration

import (
"fmt"
"regexp"
"strconv"
"time"
)

const (
HoursInDay = 24
DaysInWeek = 7
DaysInYear = 365
)

// MyDuration is a custom duration type that handles extended time units
type MyDuration time.Duration

// ParseDuration convert MyDuration to time.Duration
func (md MyDuration) ParseTimeDuration() time.Duration {
return time.Duration(md)
}

// UnmarshalText implements the encoding.TextUnmarshaler interface.
// This allows configuration libraries to parse duration strings directly into MyDuration.
func (md *MyDuration) UnmarshalText(text []byte) error {
duration, err := ParseDuration(string(text))
if err != nil {
return err
}
*md = MyDuration(duration)
return nil
}

// ParseMyDuration parses a duration string with units like s, m, h, d, w, y.
func ParseDuration(sdurantion string) (time.Duration, error) {
re := regexp.MustCompile(`(-?\d+)([smhdwy])`)
matches := re.FindAllStringSubmatch(sdurantion, -1)

if matches == nil {
return 0, fmt.Errorf("invalid duration format")
}

var totalDuration time.Duration
for _, match := range matches {
value, err := strconv.Atoi(match[1])
if err != nil {
return 0, fmt.Errorf("invalid number: %v", match[1])
}

if value < 0 {
return 0, fmt.Errorf("invalid value value is negative: %v", match[1])
}

unit := match[2]
switch unit {
case "s":
totalDuration += time.Duration(value) * time.Second
case "m":
totalDuration += time.Duration(value) * time.Minute
case "h":
totalDuration += time.Duration(value) * time.Hour
case "d":
totalDuration += time.Duration(value) * time.Hour * HoursInDay
case "w":
totalDuration += time.Duration(value) * time.Hour * HoursInDay * DaysInWeek
case "y":
totalDuration += time.Duration(value) * time.Hour * HoursInDay * DaysInYear
default:
return 0, fmt.Errorf("unknown time unit: %v", unit)
}
}

return totalDuration, nil
}
58 changes: 58 additions & 0 deletions internal/myduration/time_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package myduration

import (
"testing"
"time"

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

// TestParseMyDuration tests the ParseMyDuration function with various inputs.
func TestParseMyDuration(t *testing.T) {
tests := []struct {
name string
input string
expected time.Duration
expectingError bool
}{
// Valid duration strings
{"Single seconds", "10s", 10 * time.Second, false},
{"Single minutes", "5m", 5 * time.Minute, false},
{"Single hours", "2h", 2 * time.Hour, false},
{"Single days", "1d", 24 * time.Hour, false},
{"Single weeks", "3w", 3 * 7 * 24 * time.Hour, false},
{"Single years", "1y", 365 * 24 * time.Hour, false},
{"Mixed hours and minutes", "1h30m", time.Hour + 30*time.Minute, false},
{"Mixed days and hours", "2d4h", 2*24*time.Hour + 4*time.Hour, false},
{"Complex mixed units", "1w2d3h4m5s", (1 * 7 * 24 * time.Hour) + (2 * 24 * time.Hour) + (3 * time.Hour) + (4 * time.Minute) + (5 * time.Second), false},
// Invalid duration strings
{"Empty string", "", 0, true},
{"Missing unit", "10", 0, true},
{"Unknown unit", "10x", 0, true},
{"Negative duration", "-5m", 0, true}, // Assuming negative durations are invalid

}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result, err := ParseDuration(tt.input)
if tt.expectingError {
assert.Error(t, err, "Expected an error for input: %s", tt.input)
} else {
assert.NoError(t, err, "Did not expect an error for input: %s", tt.input)
assert.Equal(t, tt.expected, result, "Parsed duration mismatch for input: %s", tt.input)
}
})
}
}

// BenchmarkParseMyDuration benchmarks the ParseMyDuration function.
func BenchmarkParseMyDuration(b *testing.B) {
input := "1w2d3h4m5s"
for i := 0; i < b.N; i++ {
_, err := ParseDuration(input)
if err != nil {
b.Fatalf("Unexpected error: %v", err)
}
}
}
20 changes: 20 additions & 0 deletions release.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
[Metadata]

Author = "Matheus Politano"
Release_file_version = "2.1"

[Description]

Notes = """
Improve the method to setup the time alive
"""


[[Digest.Improvements]]
Name = "7-improve-time-alive"
Issue = 7
Description = """
Add the time alive as configuration
"""