Compare commits
4 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
84dff4f708 | ||
|
|
280f920410 | ||
|
|
d89e859323 | ||
|
|
0dcafa988f |
10 changed files with 153 additions and 10 deletions
12
.editorconfig
Normal file
12
.editorconfig
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
indent_style = tab
|
||||||
|
indent_size = 4
|
||||||
|
insert_final_newline = true
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
|
[*.{md,yml,yaml,json,txt}]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
22
.golangci.yml
Normal file
22
.golangci.yml
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
run:
|
||||||
|
timeout: 5m
|
||||||
|
go: "1.26"
|
||||||
|
|
||||||
|
linters:
|
||||||
|
enable:
|
||||||
|
- govet
|
||||||
|
- errcheck
|
||||||
|
- staticcheck
|
||||||
|
- unused
|
||||||
|
- gosimple
|
||||||
|
- ineffassign
|
||||||
|
- typecheck
|
||||||
|
- gocritic
|
||||||
|
- gofmt
|
||||||
|
disable:
|
||||||
|
- exhaustive
|
||||||
|
- wrapcheck
|
||||||
|
|
||||||
|
issues:
|
||||||
|
exclude-use-default: false
|
||||||
|
max-same-issues: 0
|
||||||
35
CONTRIBUTING.md
Normal file
35
CONTRIBUTING.md
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
# Contributing
|
||||||
|
|
||||||
|
Thank you for your interest in contributing!
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
- **Go Version**: 1.26 or higher is required.
|
||||||
|
- **Tools**: `golangci-lint` and `task` (Taskfile.dev) are recommended.
|
||||||
|
|
||||||
|
## Development Workflow
|
||||||
|
1. **Testing**: Ensure all tests pass before submitting changes.
|
||||||
|
```bash
|
||||||
|
go test ./...
|
||||||
|
```
|
||||||
|
2. **Code Style**: All code must follow standard Go formatting.
|
||||||
|
```bash
|
||||||
|
gofmt -w .
|
||||||
|
go vet ./...
|
||||||
|
```
|
||||||
|
3. **Linting**: We use `golangci-lint` to maintain code quality.
|
||||||
|
```bash
|
||||||
|
golangci-lint run ./...
|
||||||
|
```
|
||||||
|
|
||||||
|
## Commit Message Format
|
||||||
|
We follow the [Conventional Commits](https://www.conventionalcommits.org/) specification:
|
||||||
|
- `feat`: A new feature
|
||||||
|
- `fix`: A bug fix
|
||||||
|
- `docs`: Documentation changes
|
||||||
|
- `refactor`: A code change that neither fixes a bug nor adds a feature
|
||||||
|
- `chore`: Changes to the build process or auxiliary tools and libraries
|
||||||
|
|
||||||
|
Example: `feat: add new endpoint for health check`
|
||||||
|
|
||||||
|
## License
|
||||||
|
By contributing to this project, you agree that your contributions will be licensed under the **European Union Public Licence (EUPL-1.2)**.
|
||||||
|
|
@ -1,3 +1,7 @@
|
||||||
|
[](https://pkg.go.dev/forge.lthn.ai/core/go-api)
|
||||||
|
[](LICENSE.md)
|
||||||
|
[](go.mod)
|
||||||
|
|
||||||
# go-api
|
# go-api
|
||||||
|
|
||||||
REST framework + OpenAPI SDK generation for the Lethean Go ecosystem.
|
REST framework + OpenAPI SDK generation for the Lethean Go ecosystem.
|
||||||
|
|
|
||||||
46
Taskfile.yml
Normal file
46
Taskfile.yml
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
version: '3'
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
test:
|
||||||
|
desc: Run all tests
|
||||||
|
cmds:
|
||||||
|
- go test ./...
|
||||||
|
|
||||||
|
lint:
|
||||||
|
desc: Run golangci-lint
|
||||||
|
cmds:
|
||||||
|
- golangci-lint run ./...
|
||||||
|
|
||||||
|
fmt:
|
||||||
|
desc: Format all Go files
|
||||||
|
cmds:
|
||||||
|
- gofmt -w .
|
||||||
|
|
||||||
|
vet:
|
||||||
|
desc: Run go vet
|
||||||
|
cmds:
|
||||||
|
- go vet ./...
|
||||||
|
|
||||||
|
build:
|
||||||
|
desc: Build all Go packages
|
||||||
|
cmds:
|
||||||
|
- go build ./...
|
||||||
|
|
||||||
|
cov:
|
||||||
|
desc: Run tests with coverage and open HTML report
|
||||||
|
cmds:
|
||||||
|
- go test -coverprofile=coverage.out ./...
|
||||||
|
- go tool cover -html=coverage.out
|
||||||
|
|
||||||
|
tidy:
|
||||||
|
desc: Tidy go.mod
|
||||||
|
cmds:
|
||||||
|
- go mod tidy
|
||||||
|
|
||||||
|
check:
|
||||||
|
desc: Run fmt, vet, lint, and test in sequence
|
||||||
|
cmds:
|
||||||
|
- task: fmt
|
||||||
|
- task: vet
|
||||||
|
- task: lint
|
||||||
|
- task: test
|
||||||
7
go.mod
7
go.mod
|
|
@ -3,7 +3,7 @@ module forge.lthn.ai/core/go-api
|
||||||
go 1.26.0
|
go 1.26.0
|
||||||
|
|
||||||
require (
|
require (
|
||||||
forge.lthn.ai/core/cli v0.0.3
|
forge.lthn.ai/core/cli v0.1.0
|
||||||
github.com/99designs/gqlgen v0.17.87
|
github.com/99designs/gqlgen v0.17.87
|
||||||
github.com/andybalholm/brotli v1.2.0
|
github.com/andybalholm/brotli v1.2.0
|
||||||
github.com/casbin/casbin/v2 v2.135.0
|
github.com/casbin/casbin/v2 v2.135.0
|
||||||
|
|
@ -35,8 +35,8 @@ require (
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
forge.lthn.ai/core/go v0.0.1 // indirect
|
forge.lthn.ai/core/go v0.1.0 // indirect
|
||||||
forge.lthn.ai/core/go-crypt v0.0.2 // indirect
|
forge.lthn.ai/core/go-crypt v0.1.0 // indirect
|
||||||
github.com/KyleBanks/depth v1.2.1 // indirect
|
github.com/KyleBanks/depth v1.2.1 // indirect
|
||||||
github.com/ProtonMail/go-crypto v1.3.0 // indirect
|
github.com/ProtonMail/go-crypto v1.3.0 // indirect
|
||||||
github.com/agnivade/levenshtein v1.2.1 // indirect
|
github.com/agnivade/levenshtein v1.2.1 // indirect
|
||||||
|
|
@ -113,7 +113,6 @@ require (
|
||||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||||
golang.org/x/arch v0.23.0 // indirect
|
golang.org/x/arch v0.23.0 // indirect
|
||||||
golang.org/x/crypto v0.48.0 // indirect
|
golang.org/x/crypto v0.48.0 // indirect
|
||||||
golang.org/x/exp v0.0.0-20260218203240-3dfff04db8fa // indirect
|
|
||||||
golang.org/x/mod v0.33.0 // indirect
|
golang.org/x/mod v0.33.0 // indirect
|
||||||
golang.org/x/net v0.50.0 // indirect
|
golang.org/x/net v0.50.0 // indirect
|
||||||
golang.org/x/oauth2 v0.35.0 // indirect
|
golang.org/x/oauth2 v0.35.0 // indirect
|
||||||
|
|
|
||||||
12
go.sum
12
go.sum
|
|
@ -1,9 +1,9 @@
|
||||||
forge.lthn.ai/core/cli v0.0.3 h1:Qd/ACf8as4cwWoqAzkLIPF86NhXzfkkt1t/6xmgznVw=
|
forge.lthn.ai/core/cli v0.1.0 h1:2XRiEMVzUElnQlZnHYDyfKIKQVPcCzGuYHlnz55GjsM=
|
||||||
forge.lthn.ai/core/cli v0.0.3/go.mod h1:xa3Nqw3sUtYYJ1k+1jYul18tgs6sBevCUsGsHJI1hHA=
|
forge.lthn.ai/core/cli v0.1.0/go.mod h1:mZ7dzccfzo0BP2dE7Mwuw9dXuIowiEd1G5ZGMoLuxVc=
|
||||||
forge.lthn.ai/core/go v0.0.1 h1:ubk4nmkA3treOUNgPS28wKd1jB6cUlEQUV7jDdGa3zM=
|
forge.lthn.ai/core/go v0.1.0 h1:Ow/1NTajrrNPO0zgkskEyEGdx4SKpiNqTaqM0txNOYI=
|
||||||
forge.lthn.ai/core/go v0.0.1/go.mod h1:59YsnuMaAGQUxIhX68oK2/HnhQJEPWL1iEZhDTrNCbY=
|
forge.lthn.ai/core/go v0.1.0/go.mod h1:lwi0tccAlg5j3k6CfoNJEueBc5l9mUeSBX/x6uY8ZbQ=
|
||||||
forge.lthn.ai/core/go-crypt v0.0.2 h1:m8mCIrmC0tserVx9bfmrB8h4GtgAgQeedBPeNBvCxx0=
|
forge.lthn.ai/core/go-crypt v0.1.0 h1:92gwdQi7iAwktpvZhL/8Cu+QS6xKCtGP4FJfyInPGnw=
|
||||||
forge.lthn.ai/core/go-crypt v0.0.2/go.mod h1:+JoZ4mwjzTklysI/DI7f6/0iocdJoJG2ZF/nQy6HTuI=
|
forge.lthn.ai/core/go-crypt v0.1.0/go.mod h1:zVAgx6ZiGtC+dbX4R/VKvEPqsEqjyuLl4gQZH9SXBUw=
|
||||||
github.com/99designs/gqlgen v0.17.87 h1:pSnCIMhBQezAE8bc1GNmfdLXFmnWtWl1GRDFEE/nHP8=
|
github.com/99designs/gqlgen v0.17.87 h1:pSnCIMhBQezAE8bc1GNmfdLXFmnWtWl1GRDFEE/nHP8=
|
||||||
github.com/99designs/gqlgen v0.17.87/go.mod h1:fK05f1RqSNfQpd4CfW5qk/810Tqi4/56Wf6Nem0khAg=
|
github.com/99designs/gqlgen v0.17.87/go.mod h1:fK05f1RqSNfQpd4CfW5qk/810Tqi4/56Wf6Nem0khAg=
|
||||||
github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc=
|
github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc=
|
||||||
|
|
|
||||||
6
norace_test.go
Normal file
6
norace_test.go
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
// SPDX-License-Identifier: EUPL-1.2
|
||||||
|
//go:build !race
|
||||||
|
|
||||||
|
package api_test
|
||||||
|
|
||||||
|
const raceDetectorEnabled = false
|
||||||
6
race_test.go
Normal file
6
race_test.go
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
// SPDX-License-Identifier: EUPL-1.2
|
||||||
|
//go:build race
|
||||||
|
|
||||||
|
package api_test
|
||||||
|
|
||||||
|
const raceDetectorEnabled = true
|
||||||
|
|
@ -14,6 +14,16 @@ import (
|
||||||
api "forge.lthn.ai/core/go-api"
|
api "forge.lthn.ai/core/go-api"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// skipIfRaceDetector skips the test when the race detector is enabled.
|
||||||
|
// gin-contrib/timeout@v1.1.0 has a known data race on Context.index
|
||||||
|
// between the timeout goroutine and the handler goroutine.
|
||||||
|
func skipIfRaceDetector(t *testing.T) {
|
||||||
|
t.Helper()
|
||||||
|
if raceDetectorEnabled {
|
||||||
|
t.Skip("skipping: gin-contrib/timeout has known data race (upstream bug)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ── Helpers ─────────────────────────────────────────────────────────────
|
// ── Helpers ─────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
// slowGroup provides a route that sleeps longer than the test timeout.
|
// slowGroup provides a route that sleeps longer than the test timeout.
|
||||||
|
|
@ -57,6 +67,7 @@ func TestWithTimeout_Good_FastRequestSucceeds(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestWithTimeout_Good_SlowRequestTimesOut(t *testing.T) {
|
func TestWithTimeout_Good_SlowRequestTimesOut(t *testing.T) {
|
||||||
|
skipIfRaceDetector(t)
|
||||||
gin.SetMode(gin.TestMode)
|
gin.SetMode(gin.TestMode)
|
||||||
e, _ := api.New(api.WithTimeout(50 * time.Millisecond))
|
e, _ := api.New(api.WithTimeout(50 * time.Millisecond))
|
||||||
e.Register(&slowGroup{})
|
e.Register(&slowGroup{})
|
||||||
|
|
@ -72,6 +83,7 @@ func TestWithTimeout_Good_SlowRequestTimesOut(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestWithTimeout_Good_TimeoutResponseEnvelope(t *testing.T) {
|
func TestWithTimeout_Good_TimeoutResponseEnvelope(t *testing.T) {
|
||||||
|
skipIfRaceDetector(t)
|
||||||
gin.SetMode(gin.TestMode)
|
gin.SetMode(gin.TestMode)
|
||||||
e, _ := api.New(api.WithTimeout(50 * time.Millisecond))
|
e, _ := api.New(api.WithTimeout(50 * time.Millisecond))
|
||||||
e.Register(&slowGroup{})
|
e.Register(&slowGroup{})
|
||||||
|
|
@ -136,6 +148,7 @@ func TestWithTimeout_Good_CombinesWithOtherMiddleware(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestWithTimeout_Ugly_ZeroDurationDoesNotPanic(t *testing.T) {
|
func TestWithTimeout_Ugly_ZeroDurationDoesNotPanic(t *testing.T) {
|
||||||
|
skipIfRaceDetector(t)
|
||||||
gin.SetMode(gin.TestMode)
|
gin.SetMode(gin.TestMode)
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue