From 520e8ad438b2c816efd5f8ff0262ec939f855762 Mon Sep 17 00:00:00 2001 From: Antonio Nesic Date: Thu, 26 Feb 2026 13:51:03 +0100 Subject: [PATCH 1/7] Add CI workflow with lint, test, and coverage --- .github/workflows/ci.yml | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..414b48e --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,40 @@ +name: CI + +on: + push: + branches: [main, develop] + pull_request: + branches: [main, develop] + +permissions: + contents: read + +jobs: + ci: + name: Lint, Test & Coverage + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Go + uses: actions/setup-go@v5 + with: + go-version: "1.25" + + - name: Lint + uses: golangci/golangci-lint-action@v7 + with: + version: latest + + - name: Vet + run: go vet ./... + + - name: Test + run: go test -race -coverprofile=coverage.out -covermode=atomic ./... + + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v5 + with: + token: ${{ secrets.CODECOV_TOKEN }} + files: coverage.out From 161e8aa99b06e478991dfebb6e59443bda134d56 Mon Sep 17 00:00:00 2001 From: Antonio Nesic Date: Thu, 26 Feb 2026 13:51:03 +0100 Subject: [PATCH 2/7] Add test Dockerfile for local testing --- Dockerfile.test | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 Dockerfile.test diff --git a/Dockerfile.test b/Dockerfile.test new file mode 100644 index 0000000..32bd65e --- /dev/null +++ b/Dockerfile.test @@ -0,0 +1,12 @@ +FROM golang:1.25-alpine + +RUN apk add --no-cache gcc musl-dev + +WORKDIR /src + +COPY go.mod go.sum ./ +RUN go mod download + +COPY . . + +CMD ["go", "test", "-race", "-v", "./..."] From 54fa67b406e54f95bbc150a74a49b89e4f1cef7b Mon Sep 17 00:00:00 2001 From: Antonio Nesic Date: Thu, 26 Feb 2026 13:51:05 +0100 Subject: [PATCH 3/7] Add release workflow and GoReleaser config --- .github/workflows/release.yml | 33 +++++++++++++++++++++++++++++++++ .goreleaser.yml | 26 ++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 .github/workflows/release.yml create mode 100644 .goreleaser.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..16071a3 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,33 @@ +name: Release + +on: + push: + tags: + - "v*" + +permissions: + contents: write + +jobs: + release: + name: Release + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Setup Go + uses: actions/setup-go@v5 + with: + go-version: "1.25" + + - name: Run GoReleaser + uses: goreleaser/goreleaser-action@v6 + with: + distribution: goreleaser + version: "~> v2" + args: release --clean + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.goreleaser.yml b/.goreleaser.yml new file mode 100644 index 0000000..936d613 --- /dev/null +++ b/.goreleaser.yml @@ -0,0 +1,26 @@ +version: 2 + +builds: + - skip: true + +changelog: + sort: asc + filters: + exclude: + - "^docs:" + - "^test:" + - "^chore:" + groups: + - title: Features + regexp: '^.*?feat(\([[:word:]]+\))??!?:.+$' + order: 0 + - title: Bug fixes + regexp: '^.*?fix(\([[:word:]]+\))??!?:.+$' + order: 1 + - title: Others + order: 999 + +release: + github: + owner: mutantkeyboard + name: spindle From dac87c3c49757a1f2e4f1ad7d66d2377f020063a Mon Sep 17 00:00:00 2001 From: Antonio Nesic Date: Thu, 26 Feb 2026 13:53:00 +0100 Subject: [PATCH 4/7] Add dev Dockerfile and VS Code devcontainer --- .devcontainer/devcontainer.json | 17 +++++++++++++++++ Dockerfile | 13 +++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 .devcontainer/devcontainer.json create mode 100644 Dockerfile diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..e8688e9 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,17 @@ +{ + "name": "Spindle Dev", + "build": { + "dockerfile": "../Dockerfile" + }, + "customizations": { + "vscode": { + "extensions": [ + "golang.go" + ], + "settings": { + "go.lintTool": "golangci-lint" + } + } + }, + "postCreateCommand": "go mod download" +} diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..bc63180 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,13 @@ +FROM golang:1.25-alpine + +RUN apk add --no-cache gcc musl-dev git curl + +# Install golangci-lint +RUN curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/HEAD/install.sh | sh -s -- -b /usr/local/bin + +WORKDIR /workspace + +COPY go.mod go.sum ./ +RUN go mod download + +COPY . . From c2454140f0ee0fad4b3affde47521e5bafff936b Mon Sep 17 00:00:00 2001 From: Antonio Nesic Date: Thu, 26 Feb 2026 13:53:55 +0100 Subject: [PATCH 5/7] Update README with badges and dev instructions --- .gitignore | 2 ++ README.md | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/.gitignore b/.gitignore index 77f12ae..6239cc8 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ docs/ +coverage.out +dist/ diff --git a/README.md b/README.md index cf0560c..b53e60c 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ # Spindle [![Go Reference](https://pkg.go.dev/badge/github.com/mutantkeyboard/spindle.svg)](https://pkg.go.dev/github.com/mutantkeyboard/spindle) +[![CI](https://github.com/mutantkeyboard/spindle/actions/workflows/ci.yml/badge.svg)](https://github.com/mutantkeyboard/spindle/actions/workflows/ci.yml) +[![codecov](https://codecov.io/gh/mutantkeyboard/spindle/branch/main/graph/badge.svg)](https://codecov.io/gh/mutantkeyboard/spindle) Pagination middleware for [Fiber](https://github.com/gofiber/fiber) v3. @@ -122,6 +124,25 @@ type PageInfo struct { - Negative offsets are reset to 0 - Sort fields are validated against `AllowedSorts` +## Development + +### Run tests locally + +```bash +go test -race -v ./... +``` + +### Run tests in Docker + +```bash +docker build -f Dockerfile.test -t spindle-test . +docker run --rm spindle-test +``` + +### Dev container + +Open this project in VS Code with the Dev Containers extension to get a pre-configured Go development environment. + ## Acknowledgements Heavily inspired by [fiberpaginate](https://github.com/garrettladley/fiberpaginate) by Garrett Ladley. From e76473204e788a2aea71e975bb5d44697c224bc6 Mon Sep 17 00:00:00 2001 From: Antonio Nesic Date: Thu, 26 Feb 2026 13:58:37 +0100 Subject: [PATCH 6/7] Add Makefile and fix errcheck lint error - Add Makefile with targets for test, lint, fmt, vet, docker, and check - Fix unchecked body.Close() in Test_PaginateWithQueries - Remove unused io import --- Makefile | 46 ++++++++++++++++++++++++++++++++++++++++++++++ paginate_test.go | 11 ++--------- 2 files changed, 48 insertions(+), 9 deletions(-) create mode 100644 Makefile diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..797aed8 --- /dev/null +++ b/Makefile @@ -0,0 +1,46 @@ +.PHONY: test lint vet fmt check docker-test docker-build clean + +## Testing + +test: ## Run tests with race detector + go test -race -v ./... + +test-cover: ## Run tests with coverage + go test -race -coverprofile=coverage.out -covermode=atomic ./... + go tool cover -func=coverage.out + +bench: ## Run benchmarks + go test -bench=. -benchmem ./... + +## Code quality + +lint: ## Run golangci-lint + golangci-lint run + +fmt: ## Format code + gofmt -w . + +vet: ## Run go vet + go vet ./... + +check: fmt vet lint test ## Run all checks (fmt, vet, lint, test) + +## Docker + +docker-test: ## Run tests in Docker + docker build -f Dockerfile.test -t spindle-test . + docker run --rm spindle-test + +docker-build: ## Build dev Docker image + docker build -t spindle-dev . + +## Cleanup + +clean: ## Remove build artifacts + rm -f coverage.out + rm -rf dist/ + +## Help + +help: ## Show this help + @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-15s\033[0m %s\n", $$1, $$2}' diff --git a/paginate_test.go b/paginate_test.go index c7c0a95..243fed8 100644 --- a/paginate_test.go +++ b/paginate_test.go @@ -2,7 +2,6 @@ package spindle import ( "encoding/json" - "io" "net/http/httptest" "reflect" "testing" @@ -53,16 +52,10 @@ func Test_PaginateWithQueries(t *testing.T) { t.Fatalf("status = %d, want %d", resp.StatusCode, fiber.StatusOK) } - body := resp.Body - defer body.Close() - - bodyBytes, err := io.ReadAll(body) - if err != nil { - t.Fatal(err) - } + defer resp.Body.Close() //nolint:errcheck var respBody Response - if err := json.Unmarshal(bodyBytes, &respBody); err != nil { + if err := json.NewDecoder(resp.Body).Decode(&respBody); err != nil { t.Fatal(err) } From c6f6673671fc130f1294276f624bb2909eb10763 Mon Sep 17 00:00:00 2001 From: Antonio Nesic Date: Thu, 26 Feb 2026 14:00:27 +0100 Subject: [PATCH 7/7] Download golangci-lint to local bin/ on first use --- .gitignore | 1 + Makefile | 13 ++++++++++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 6239cc8..27d13a2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ docs/ +bin/ coverage.out dist/ diff --git a/Makefile b/Makefile index 797aed8..5c15bd3 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,7 @@ -.PHONY: test lint vet fmt check docker-test docker-build clean +.PHONY: test lint vet fmt check docker-test docker-build clean help + +BIN := $(CURDIR)/bin +GOLANGCI_LINT := $(BIN)/golangci-lint ## Testing @@ -14,8 +17,12 @@ bench: ## Run benchmarks ## Code quality -lint: ## Run golangci-lint - golangci-lint run +$(GOLANGCI_LINT): + @mkdir -p $(BIN) + curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/HEAD/install.sh | sh -s -- -b $(BIN) + +lint: $(GOLANGCI_LINT) ## Run golangci-lint (downloads to ./bin if missing) + $(GOLANGCI_LINT) run fmt: ## Format code gofmt -w .