diff --git a/CLAUDE.md b/CLAUDE.md index ee551f9..c6e6747 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -48,85 +48,115 @@ The codebase uses extensive object pooling for performance optimization: ## Development Commands +This project uses [Task](https://taskfile.dev) as the task runner. Install with: +```bash +go install github.com/go-task/task/v3/cmd/task@latest +# Or: brew install go-task (macOS) +``` + ### Building and Testing ```bash -# Build the project -make build -go build -v ./... +# Show all available tasks +task + +# Build all packages +task build -# Build the CLI tool -go build -o gosqlx ./cmd/gosqlx +# Build the CLI binary +task build:cli + +# Build CLI for all platforms +task build:cli:all + +# Install CLI globally +task install # Run all tests -make test -go test -v ./... +task test -# Run a single test by pattern -go test -v -run TestTokenizer_SimpleSelect ./pkg/sql/tokenizer/ -go test -v -run TestParser_.*Window.* ./pkg/sql/parser/ +# Run tests with race detection (CRITICAL) +task test:race -# Run tests for specific packages -go test -v ./pkg/sql/tokenizer/ -go test -v ./pkg/sql/parser/ -go test -v ./pkg/sql/ast/ -go test -v ./pkg/models/ -go test -v ./pkg/errors/ +# Run tests for specific package +task test:pkg PKG=./pkg/sql/parser + +# Run tests in short mode +task test:short # Run tests with coverage report -make coverage -go test -cover -coverprofile=coverage.out ./... -go tool cover -html=coverage.out -o coverage.html +task coverage -# Generate text coverage report for specific package -go test -coverprofile=coverage.out ./pkg/models/ -go tool cover -func=coverage.out +# Show coverage by function +task coverage:func # Run benchmarks -go test -bench=. -benchmem ./... -go test -bench=BenchmarkTokenizer -benchmem ./pkg/sql/tokenizer/ -go test -bench=BenchmarkParser -benchmem ./pkg/sql/parser/ +task bench + +# Run benchmarks with CPU profiling +task bench:cpu + +# Run fuzz tests +task fuzz ``` ### Code Quality ```bash # Format code -make fmt -go fmt ./... +task fmt + +# Check formatting (fails if not formatted) +task fmt:check + +# Run go vet +task vet + +# Run golangci-lint +task lint -# Vet code -make vet -go vet ./... +# Run golangci-lint with auto-fix +task lint:fix -# Run linting (requires golint installation) -make lint -golint ./... +# Run staticcheck +task staticcheck -# Run all quality checks -make quality +# Run all quality checks (fmt, vet, lint) +task quality + +# Full check suite (format, vet, lint, test:race) +task check # CRITICAL: Always run race detection during development -go test -race ./... -go test -race -benchmem ./... -go test -race -timeout 30s ./pkg/... +task test:race ``` -### Running Examples +### Security +```bash +# Run security vulnerability scan +task security:scan + +# Validate security setup +task security:validate +``` + +### CI/CD ```bash -# Basic example (demonstrates tokenization and parsing) -cd examples/cmd/ -go run example.go +# Run full CI pipeline +task ci -# SQL validator example -cd examples/sql-validator/ -go run main.go +# Quick CI check (no race detection) +task ci:quick +``` -# SQL formatter example -cd examples/sql-formatter/ -go run main.go +### Running Examples +```bash +# Run basic example +task examples # Run example tests -cd examples/cmd/ -go test -v example_test.go +task examples:test + +# Or run directly: +go run ./examples/cmd/example.go ``` ### CLI Tool Usage (v1.4.0+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 74ce44a..b3517cd 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -38,7 +38,7 @@ GoSQLX aims to be the **fastest, most reliable, and most comprehensive SQL parsi ### Prerequisites - **Go 1.19+** (latest stable version recommended) - **Git** for version control -- **Make** for build automation (optional) +- **Task** for task automation (optional) - Install with `go install github.com/go-task/task/v3/cmd/task@latest` ### Getting Started ```bash @@ -60,7 +60,7 @@ go test ./... go test -race ./... # 7. Install Git hooks (RECOMMENDED) -make install-hooks +task hooks:install # or ./scripts/install-hooks.sh ``` @@ -70,8 +70,8 @@ make install-hooks GoSQLX provides pre-commit hooks to catch code quality issues before they reach CI/CD: ```bash -# Install hooks using Make -make install-hooks +# Install hooks using Task +task hooks:install # Or run the script directly ./scripts/install-hooks.sh @@ -393,7 +393,7 @@ Many applications use PostgreSQL's JSON features extensively... ## 📋 Pull Request Checklist ### Before Submitting -- [ ] **Git Hooks**: Pre-commit hooks installed and passing (`make install-hooks`) +- [ ] **Git Hooks**: Pre-commit hooks installed and passing (`task hooks:install`) - [ ] **Tests**: All tests pass with `go test -race ./...` - [ ] **Coverage**: New code has >95% test coverage - [ ] **Performance**: No performance regression diff --git a/Makefile b/Makefile deleted file mode 100644 index 8b7d927..0000000 --- a/Makefile +++ /dev/null @@ -1,69 +0,0 @@ -.PHONY: build test clean lint fmt vet coverage install-hooks help - -# Default target -all: build - -# Build the application -build: - @echo "Building..." - @go build -v ./... - -# Run all tests -test: - @echo "Running tests..." - @go test -v ./... - -# Run tests with coverage -coverage: - @echo "Running tests with coverage..." - @go test -cover -coverprofile=coverage.out ./... - @go tool cover -html=coverage.out -o coverage.html - @echo "Coverage report generated at coverage.html" - -# Clean build artifacts -clean: - @echo "Cleaning..." - @rm -f coverage.out coverage.html - @go clean - -# Run go fmt -fmt: - @echo "Formatting code..." - @go fmt ./... - -# Run go vet -vet: - @echo "Vetting code..." - @go vet ./... - -# Run golint if installed -lint: - @echo "Linting code..." - @if command -v golint > /dev/null; then \ - golint ./...; \ - else \ - echo "golint not installed. Run: go install golang.org/x/lint/golint@latest"; \ - fi - -# Run all quality checks -quality: fmt vet lint - -# Install Git hooks -install-hooks: - @echo "Installing Git hooks..." - @./scripts/install-hooks.sh - -# Show help -help: - @echo "Available targets:" - @echo " all - Build the application (default)" - @echo " build - Build the application" - @echo " test - Run tests" - @echo " coverage - Run tests with coverage report" - @echo " clean - Clean build artifacts" - @echo " fmt - Run go fmt" - @echo " vet - Run go vet" - @echo " lint - Run golint (if installed)" - @echo " quality - Run all quality checks (fmt, vet, lint)" - @echo " install-hooks - Install Git pre-commit hooks" - @echo " help - Show this help message" diff --git a/README.md b/README.md index 80c29fe..163895f 100644 --- a/README.md +++ b/README.md @@ -691,39 +691,62 @@ GoSQLX/ ### Prerequisites - Go 1.19+ -- Make (optional, for Makefile targets) -- golint, staticcheck (for code quality) +- [Task](https://taskfile.dev) - task runner (install: `go install github.com/go-task/task/v3/cmd/task@latest`) +- golangci-lint, staticcheck (for code quality, install: `task deps:tools`) + +### Task Runner + +This project uses [Task](https://taskfile.dev) as the task runner. Install with: +```bash +go install github.com/go-task/task/v3/cmd/task@latest +# Or: brew install go-task (macOS) +``` ### Building ```bash +# Show all available tasks +task + # Build the project -make build +task build -# Run quality checks -make quality +# Build the CLI binary +task build:cli + +# Install CLI globally +task install + +# Run all quality checks +task quality # Run all tests -make test +task test + +# Run tests with race detection (recommended) +task test:race # Clean build artifacts -make clean +task clean ``` ### Code Quality ```bash # Format code -go fmt ./... +task fmt + +# Run go vet +task vet -# Vet code -go vet ./... +# Run golangci-lint +task lint -# Run linter -golint ./... +# Run all quality checks (fmt, vet, lint) +task quality -# Static analysis -staticcheck ./... +# Full CI check (format, vet, lint, test:race) +task check ``` ## 🤝 Contributing diff --git a/Taskfile.yml b/Taskfile.yml new file mode 100644 index 0000000..e2a8012 --- /dev/null +++ b/Taskfile.yml @@ -0,0 +1,471 @@ +# https://taskfile.dev +version: '3' + +vars: + BINARY_NAME: gosqlx + BUILD_DIR: build + COVERAGE_FILE: coverage.out + COVERAGE_HTML: coverage.html + GO_PACKAGES: + sh: go list ./... + GO_FILES: + sh: find . -type f -name '*.go' -not -path './vendor/*' + +env: + CGO_ENABLED: '0' + +tasks: + # ============================================================================= + # DEFAULT + # ============================================================================= + default: + desc: Show available tasks + cmds: + - task --list-all + + # ============================================================================= + # BUILD TASKS + # ============================================================================= + build: + desc: Build all packages + cmds: + - echo "Building packages..." + - go build -v ./... + + build:cli: + desc: Build the CLI binary + cmds: + - echo "Building CLI binary..." + - go build -v -o {{.BUILD_DIR}}/{{.BINARY_NAME}} ./cmd/gosqlx + generates: + - '{{.BUILD_DIR}}/{{.BINARY_NAME}}' + + build:cli:all: + desc: Build CLI for all platforms (linux, darwin, windows) + cmds: + - echo "Building for Linux amd64..." + - GOOS=linux GOARCH=amd64 go build -o {{.BUILD_DIR}}/{{.BINARY_NAME}}-linux-amd64 ./cmd/gosqlx + - echo "Building for Linux arm64..." + - GOOS=linux GOARCH=arm64 go build -o {{.BUILD_DIR}}/{{.BINARY_NAME}}-linux-arm64 ./cmd/gosqlx + - echo "Building for macOS amd64..." + - GOOS=darwin GOARCH=amd64 go build -o {{.BUILD_DIR}}/{{.BINARY_NAME}}-darwin-amd64 ./cmd/gosqlx + - echo "Building for macOS arm64..." + - GOOS=darwin GOARCH=arm64 go build -o {{.BUILD_DIR}}/{{.BINARY_NAME}}-darwin-arm64 ./cmd/gosqlx + - echo "Building for Windows amd64..." + - GOOS=windows GOARCH=amd64 go build -o {{.BUILD_DIR}}/{{.BINARY_NAME}}-windows-amd64.exe ./cmd/gosqlx + + install: + desc: Install the CLI globally + cmds: + - echo "Installing gosqlx CLI..." + - go install ./cmd/gosqlx + + # ============================================================================= + # TEST TASKS + # ============================================================================= + test: + desc: Run all tests + cmds: + - echo "Running tests..." + - go test -v ./... + + test:short: + desc: Run tests in short mode + cmds: + - echo "Running short tests..." + - go test -short ./... + + test:race: + desc: Run tests with race detection (CRITICAL for production) + cmds: + - echo "Running tests with race detection..." + - go test -race -timeout 60s ./... + + test:pkg: + desc: Run tests for a specific package (use PKG=./pkg/sql/parser) + cmds: + - echo "Running tests for {{.PKG}}..." + - go test -v -race {{.PKG}} + vars: + PKG: '{{default "./..." .PKG}}' + + # ============================================================================= + # COVERAGE TASKS + # ============================================================================= + coverage: + desc: Generate test coverage report + cmds: + - echo "Running tests with coverage..." + - go test -cover -coverprofile={{.COVERAGE_FILE}} ./... + - go tool cover -html={{.COVERAGE_FILE}} -o {{.COVERAGE_HTML}} + - echo "Coverage report generated at {{.COVERAGE_HTML}}" + generates: + - '{{.COVERAGE_FILE}}' + - '{{.COVERAGE_HTML}}' + + coverage:func: + desc: Show coverage by function + deps: [coverage] + cmds: + - go tool cover -func={{.COVERAGE_FILE}} + + coverage:pkg: + desc: Generate coverage for specific package (use PKG=./pkg/models) + cmds: + - go test -coverprofile={{.COVERAGE_FILE}} {{.PKG}} + - go tool cover -func={{.COVERAGE_FILE}} + vars: + PKG: '{{default "./pkg/models" .PKG}}' + + # ============================================================================= + # BENCHMARK TASKS + # ============================================================================= + bench: + desc: Run all benchmarks + cmds: + - echo "Running benchmarks..." + - go test -bench=. -benchmem ./... + + bench:pkg: + desc: Run benchmarks for specific package (use PKG=./pkg/sql/parser) + cmds: + - echo "Running benchmarks for {{.PKG}}..." + - go test -bench=. -benchmem {{.PKG}} + vars: + PKG: '{{default "./pkg/sql/parser" .PKG}}' + + bench:cpu: + desc: Run benchmarks with CPU profiling + cmds: + - echo "Running benchmarks with CPU profile..." + - go test -bench=. -benchmem -cpuprofile=cpu.prof ./pkg/sql/parser + - echo "CPU profile saved to cpu.prof - use 'go tool pprof cpu.prof'" + + bench:mem: + desc: Run benchmarks with memory profiling + cmds: + - echo "Running benchmarks with memory profile..." + - go test -bench=. -benchmem -memprofile=mem.prof ./pkg/sql/parser + - echo "Memory profile saved to mem.prof - use 'go tool pprof mem.prof'" + + # ============================================================================= + # FUZZ TESTING + # ============================================================================= + fuzz: + desc: Run fuzz tests (duration configurable via FUZZ_TIME, default 30s) + cmds: + - echo "Running fuzz tests for {{.FUZZ_TIME}}..." + - | + if [ -f "./scripts/run_fuzz_tests.sh" ]; then + ./scripts/run_fuzz_tests.sh + else + echo "Error: scripts/run_fuzz_tests.sh not found" + echo "You can run fuzz tests directly with: go test -fuzz=FuzzTokenizer -fuzztime={{.FUZZ_TIME}} ./pkg/sql/tokenizer" + exit 1 + fi + vars: + FUZZ_TIME: '{{default "30s" .FUZZ_TIME}}' + + fuzz:tokenizer: + desc: Run tokenizer fuzz tests + cmds: + - echo "Fuzzing tokenizer..." + - go test -fuzz=FuzzTokenizer -fuzztime={{.FUZZ_TIME}} ./pkg/sql/tokenizer + vars: + FUZZ_TIME: '{{default "30s" .FUZZ_TIME}}' + + # ============================================================================= + # CODE QUALITY TASKS + # ============================================================================= + fmt: + desc: Format Go code + cmds: + - echo "Formatting code..." + - go fmt ./... + + fmt:check: + desc: Check if code is formatted (fails if not) + cmds: + - echo "Checking code formatting..." + - test -z "$(gofmt -l .)" + silent: true + + vet: + desc: Run go vet + cmds: + - echo "Running go vet..." + - go vet ./... + + lint: + desc: Run golangci-lint + cmds: + - echo "Running golangci-lint..." + - | + if command -v golangci-lint > /dev/null; then + golangci-lint run + else + echo "golangci-lint not installed. Run: go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest" + exit 1 + fi + + lint:fix: + desc: Run golangci-lint with auto-fix + cmds: + - echo "Running golangci-lint with auto-fix..." + - | + if command -v golangci-lint > /dev/null; then + golangci-lint run --fix + else + echo "golangci-lint not installed. Run: go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest" + exit 1 + fi + + staticcheck: + desc: Run staticcheck + cmds: + - echo "Running staticcheck..." + - | + if command -v staticcheck > /dev/null; then + staticcheck ./... + else + echo "staticcheck not installed. Run: go install honnef.co/go/tools/cmd/staticcheck@latest" + exit 1 + fi + + quality: + desc: Run all quality checks (fmt, vet, lint) + deps: [fmt, vet, lint] + + check: + desc: Run full check suite (format check, vet, lint, test with race) + cmds: + - task: fmt:check + - task: vet + - task: lint + - task: test:race + + # ============================================================================= + # SECURITY TASKS + # ============================================================================= + security:scan: + desc: Run security vulnerability scan + cmds: + - echo "Running security scan..." + - | + if command -v govulncheck > /dev/null; then + govulncheck ./... + else + echo "govulncheck not installed. Run: go install golang.org/x/vuln/cmd/govulncheck@latest" + exit 1 + fi + + security:validate: + desc: Validate security setup + cmds: + - | + if [ -f "./scripts/validate-security-setup.sh" ]; then + ./scripts/validate-security-setup.sh + else + echo "Error: scripts/validate-security-setup.sh not found" + exit 1 + fi + + # ============================================================================= + # DOCUMENTATION + # ============================================================================= + docs: + desc: Generate documentation + cmds: + - echo "Generating documentation..." + - | + if command -v godoc > /dev/null; then + echo "Starting godoc server at http://localhost:6060/pkg/github.com/ajitpratap0/GoSQLX/" + godoc -http=:6060 + else + echo "godoc not installed. Run: go install golang.org/x/tools/cmd/godoc@latest" + fi + + # ============================================================================= + # LSP SERVER + # ============================================================================= + lsp: + desc: Start the LSP server + cmds: + - go run ./cmd/gosqlx lsp + + lsp:debug: + desc: Start LSP server with debug logging + cmds: + - go run ./cmd/gosqlx lsp --log /tmp/gosqlx-lsp.log + + # ============================================================================= + # EXAMPLES + # ============================================================================= + examples: + desc: Run example programs + cmds: + - echo "Running basic example..." + - go run ./examples/cmd/example.go + + examples:test: + desc: Run example tests + dir: examples/cmd + cmds: + - go test -v example_test.go + + # ============================================================================= + # DEPENDENCIES + # ============================================================================= + deps: + desc: Download and verify dependencies + cmds: + - echo "Downloading dependencies..." + - go mod download + - go mod verify + + deps:tidy: + desc: Tidy go.mod and go.sum + cmds: + - echo "Tidying dependencies..." + - go mod tidy + + deps:update: + desc: Update all dependencies + cmds: + - echo "Updating dependencies..." + - go get -u ./... + - go mod tidy + + deps:tools: + desc: Install development tools + cmds: + - echo "Installing development tools..." + - go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest + - go install honnef.co/go/tools/cmd/staticcheck@latest + - go install golang.org/x/vuln/cmd/govulncheck@latest + - go install golang.org/x/tools/cmd/godoc@latest + - echo "Installing task runner..." + - go install github.com/go-task/task/v3/cmd/task@latest + - echo "" + - echo "All Go tools installed!" + - echo "" + - echo "Optional - For task dev watch mode, install watchexec" + - echo " via Homebrew - brew install watchexec" + - echo " via Cargo - cargo install watchexec-cli" + + # ============================================================================= + # GIT HOOKS + # ============================================================================= + hooks:install: + desc: Install Git pre-commit hooks + cmds: + - echo "Installing Git hooks..." + - | + if [ -f "./scripts/install-hooks.sh" ]; then + ./scripts/install-hooks.sh + else + echo "Error: scripts/install-hooks.sh not found" + exit 1 + fi + + # ============================================================================= + # CLEAN + # ============================================================================= + clean: + desc: Clean build artifacts + cmds: + - echo "Cleaning..." + - rm -rf {{.BUILD_DIR}} + - rm -f {{.COVERAGE_FILE}} {{.COVERAGE_HTML}} + - rm -f cpu.prof mem.prof + - go clean -cache -testcache + + clean:all: + desc: Deep clean including module cache + cmds: + - task: clean + - go clean -modcache + + # ============================================================================= + # CI/CD + # ============================================================================= + ci: + desc: Run full CI pipeline (used in GitHub Actions) + cmds: + - echo "=== CI Pipeline Starting ===" + - task: deps + - task: fmt:check + - task: vet + - task: lint + - task: test:race + - task: build + - echo "=== CI Pipeline Complete ===" + + ci:quick: + desc: Quick CI check (no race detection) + cmds: + - task: deps + - task: vet + - task: test:short + - task: build + + # ============================================================================= + # RELEASE + # ============================================================================= + release:dry: + desc: Dry-run release with goreleaser + cmds: + - echo "Running goreleaser dry-run..." + - | + if command -v goreleaser > /dev/null; then + goreleaser release --snapshot --clean + else + echo "goreleaser not installed. Install from: https://goreleaser.com/install/" + exit 1 + fi + + release:check: + desc: Check goreleaser configuration + cmds: + - | + if command -v goreleaser > /dev/null; then + goreleaser check + else + echo "goreleaser not installed. Install from: https://goreleaser.com/install/" + exit 1 + fi + + # ============================================================================= + # DEVELOPMENT HELPERS + # ============================================================================= + dev: + desc: Start development mode (watch for changes) + cmds: + - echo "Development mode - run tests on file changes" + - | + if command -v watchexec > /dev/null; then + watchexec -e go -- go test -short ./... + else + echo "watchexec not installed. Install via: brew install watchexec or cargo install watchexec-cli" + fi + + validate: + desc: Validate SQL via CLI (use SQL="SELECT * FROM users") + cmds: + - go run ./cmd/gosqlx validate "{{.SQL}}" + vars: + SQL: '{{default "SELECT * FROM users" .SQL}}' + + format:sql: + desc: Format SQL via CLI (use SQL="select * from users") + cmds: + - go run ./cmd/gosqlx format "{{.SQL}}" + vars: + SQL: '{{default "select * from users" .SQL}}' + + analyze: + desc: Analyze SQL via CLI (use SQL="SELECT * FROM users") + cmds: + - go run ./cmd/gosqlx analyze "{{.SQL}}" + vars: + SQL: '{{default "SELECT * FROM users WHERE id = 1" .SQL}}' diff --git a/docs/CLI_GUIDE.md b/docs/CLI_GUIDE.md index 2548574..ebe18ee 100644 --- a/docs/CLI_GUIDE.md +++ b/docs/CLI_GUIDE.md @@ -510,20 +510,29 @@ gosqlx validate current_file.sql ``` ### Build Tools Integration -```makefile -# Makefile example -.PHONY: sql-lint sql-format sql-check +```yaml +# Taskfile.yml example (using go-task) +version: '3' -sql-lint: - gosqlx validate src/**/*.sql +tasks: + sql:lint: + desc: Validate SQL files + cmds: + - gosqlx validate src/**/*.sql -sql-format: - gosqlx format -i src/**/*.sql + sql:format: + desc: Format SQL files in place + cmds: + - gosqlx format -i src/**/*.sql -sql-check: - gosqlx format --check src/**/*.sql + sql:check: + desc: Check SQL formatting + cmds: + - gosqlx format --check src/**/*.sql ``` +Run with: `task sql:lint`, `task sql:format`, or `task sql:check` + ## Troubleshooting ### Common Issues diff --git a/docs/PRODUCTION_GUIDE.md b/docs/PRODUCTION_GUIDE.md index 2d0dacf..a119283 100644 --- a/docs/PRODUCTION_GUIDE.md +++ b/docs/PRODUCTION_GUIDE.md @@ -19,7 +19,7 @@ GoSQLX is **production-ready** for enterprise deployment with validated performa ### Dependencies - **Core Library**: Zero external dependencies - **Optional Tools**: Standard library only -- **Build Tools**: Go toolchain, make (optional) +- **Build Tools**: Go toolchain, Task (optional) - `go install github.com/go-task/task/v3/cmd/task@latest` ## Installation Methods diff --git a/scripts/install-hooks.sh b/scripts/install-hooks.sh index af2b0a8..c2bd043 100755 --- a/scripts/install-hooks.sh +++ b/scripts/install-hooks.sh @@ -51,7 +51,7 @@ if [ -n "$UNFORMATTED" ]; then echo "$UNFORMATTED" echo "" echo "To fix, run: gofmt -w ." - echo "Or use: make fmt" + echo "Or use: task fmt" exit 1 fi echo "✓ Code formatting check passed"