Contributing to Relica
March 5, 2026 ยท View on GitHub
Thank you for your interest in contributing to Relica! We appreciate your help in making this database query builder better.
๐ Quick Start
Prerequisites
- Go 1.25+ - Install Go
- golangci-lint - Install golangci-lint
- Git - Install Git
Setup Development Environment
# Fork the repository on GitHub first!
# Clone your fork
git clone https://github.com/YOUR_USERNAME/relica.git
cd relica
# Add upstream remote
git remote add upstream https://github.com/coregx/relica.git
# Install dependencies
go mod download
go mod verify
# Run tests to verify setup
go test ./...
๐ ๏ธ Development Workflow
Running Tests
# Run all tests
go test ./...
# Run with coverage
go test -cover ./...
# Run with verbose output
go test -v ./...
# Run specific package tests
go test ./core/...
go test ./cache/...
# Run integration tests (requires databases)
cd test
go test -v ./...
Code Quality
# Format code
gofmt -w .
# Check formatting
gofmt -l .
# Run static analysis
go vet ./...
# Run linter
golangci-lint run --timeout=5m ./...
# Fix auto-fixable issues
golangci-lint run --fix ./...
Benchmarks
# Run all benchmarks
go test -bench=. -benchmem ./benchmark/...
# Run specific benchmark
go test -bench=BenchmarkBatchInsert ./benchmark/...
# Compare benchmarks
go test -bench=. -benchmem ./benchmark/... > new.txt
# Make changes...
go test -bench=. -benchmem ./benchmark/... > old.txt
benchstat old.txt new.txt
๐ Before You Submit
Pre-Commit Checklist
Before submitting a pull request, ensure:
- Code is formatted:
gofmt -w . - Tests pass:
go test ./... - Linter passes:
golangci-lint run ./... - Coverage maintained or improved
- Documentation updated (if needed)
- Examples updated (if API changed)
- CHANGELOG.md updated (for significant changes)
Writing Tests
All new code must include tests:
func TestNewFeature(t *testing.T) {
// Arrange
db := setupTestDB(t)
defer db.Close()
// Act
result, err := db./* your code */
// Assert
require.NoError(t, err)
assert.Equal(t, expected, result)
}
Coverage requirements:
- Minimum: 70% overall coverage
- Target: 80%+ for business logic
- Core package: 80%+ required
Code Style
Follow these guidelines:
-
Naming:
- Use
PascalCasefor exported functions/types - Use
camelCasefor unexported functions/types - Use descriptive names (avoid abbreviations)
- Use
-
Comments:
- All exported functions must have godoc comments
- Comments must start with the function/type name
- Comments must end with a period
- Use full sentences
-
Error Handling:
- Always handle errors explicitly
- Use
fmt.Errorfwith%wfor error wrapping - Return errors, don't panic (except in tests)
-
Imports:
- Group imports: stdlib, external, internal
- Use
goimportsfor automatic formatting
Example:
// BatchInsert creates a batch INSERT query for multiple rows.
// It returns a BatchInsertQuery that can be executed with Execute().
// The columns parameter specifies which columns to insert.
func (qb *QueryBuilder) BatchInsert(table string, columns []string) *BatchInsertQuery {
if len(columns) == 0 {
return &BatchInsertQuery{err: ErrNoColumns}
}
// ...
}
๐ Git Workflow
Branch Naming
Use descriptive branch names:
feature/batch-operations- New featuresfix/cache-memory-leak- Bug fixesdocs/update-readme- Documentation updatesrefactor/query-builder- Code refactoringtest/add-integration-tests- Test improvements
Commit Messages
Follow Conventional Commits:
<type>(<scope>): <description>
[optional body]
[optional footer]
Types:
feat: New featurefix: Bug fixdocs: Documentation onlystyle: Code style (formatting, missing semicolons, etc.)refactor: Code refactoringtest: Adding or updating testschore: Maintenance tasks
Examples:
git commit -m "feat(batch): add batch UPDATE support"
git commit -m "fix(cache): prevent memory leak in LRU eviction"
git commit -m "docs: update README with UPSERT examples"
git commit -m "test(core): add integration tests for transactions"
Creating a Pull Request
-
Create feature branch:
git checkout main git pull upstream main git checkout -b feature/my-feature -
Make changes and commit:
# Make changes... gofmt -w . go test ./... git add . git commit -m "feat: add my feature" -
Push to your fork:
git push origin feature/my-feature -
Create PR on GitHub:
- Go to: https://github.com/coregx/relica/compare
- Select
mainas base branch - Select your feature branch
- Fill in PR template
- Request review
Pull Request Guidelines
PR Title: Use conventional commit format
feat(batch): add batch UPDATE support
PR Description must include:
- Summary: What does this PR do?
- Motivation: Why is this change needed?
- Changes: List of changes made
- Testing: How was this tested?
- Breaking Changes: Any breaking changes? (if yes, must be major version)
Example PR Description:
## Summary
Adds batch UPDATE support for updating multiple rows with different values in a single query.
## Motivation
Users need to update many rows efficiently without individual UPDATE queries.
## Changes
- Added BatchUpdateQuery type
- Implemented CASE-WHEN SQL generation for all 3 dialects
- Added 25 unit tests
- Added 8 integration tests
- Updated README with examples
## Testing
- Unit tests: 25 new tests, all passing
- Integration tests: tested on PostgreSQL, MySQL, SQLite
- Benchmarks: 2.5x faster than individual UPDATEs
## Breaking Changes
None - backward compatible addition.
๐ Reporting Bugs
Before Reporting
- Check existing issues
- Verify it's not already fixed in
main - Try with latest version
Bug Report Template
**Describe the bug**
A clear description of the bug.
**To Reproduce**
Steps to reproduce:
1. Create DB connection with...
2. Execute query...
3. See error
**Expected behavior**
What you expected to happen.
**Actual behavior**
What actually happened.
**Code Sample**
```go
// Minimal reproducible example
db, _ := relica.Open("postgres", dsn)
// ...
Environment:
- Relica version: v0.1.0-beta
- Go version: 1.25.0
- OS: Ubuntu 22.04
- Database: PostgreSQL 15
Additional context Any other relevant information.
---
## ๐ก Feature Requests
### Before Requesting
1. Check [existing issues](https://github.com/coregx/relica/issues)
2. Check [ROADMAP.md](ROADMAP.md) for planned features
3. Consider if it fits Relica's scope (lightweight, zero-dependency)
### Feature Request Template
```markdown
**Problem Statement**
What problem does this feature solve?
**Proposed Solution**
How should this feature work?
**Alternatives Considered**
What other approaches did you consider?
**Use Case**
Real-world example of how this would be used.
**Breaking Changes**
Would this require breaking changes?
๐ Documentation
Documentation Guidelines
- README.md: High-level overview, quick start, examples
- Godoc comments: All exported functions, types, constants
- CHANGELOG.md: All user-facing changes
- docs/reports/: Detailed implementation reports
Writing Good Documentation
- Use clear, concise language
- Include code examples
- Explain why, not just what
- Keep examples up-to-date with code
- Test code examples (they should compile and run)
๐ฆ Internal Packages
Relica uses Go's internal/ package structure to maintain a clear public API boundary.
Understanding Internal Packages
What you need to know:
-
Only import the main package:
// โ Correct - Public API import "github.com/coregx/relica" // โ Wrong - Internal package (will not compile) import "github.com/coregx/relica/internal/core" -
All functionality is available through the main
relicapackage via re-exports indb.go -
Internal packages are not part of the public API:
- Changes to
internal/do NOT require major version bumps - We can refactor freely without breaking user code
- Documentation on pkg.go.dev only shows the public API
- Changes to
Working with Internal Packages (Contributors)
When developing Relica:
- Internal packages CAN import each other
- Tests CAN import internal packages
- Benchmarks CAN import internal packages
- Only
db.goshould re-export to public API
Example internal import (in contributor code):
// internal/core/builder.go
package core
import (
"github.com/coregx/relica/internal/cache" // โ
OK
"github.com/coregx/relica/internal/dialects" // โ
OK
)
Adding new public functionality:
- Implement in
internal/core/(or appropriate package) - Export through
db.go:// db.go type ( NewType = core.NewType // Re-export ) var ( NewFunc = core.NewFunc // Re-export ) - Document in README.md
- Add example to docs/
Why Internal Packages?
- API Stability: Changes to implementation don't break user code
- Freedom to Refactor: Reorganize code without semver implications
- Clear Documentation: pkg.go.dev shows only public API
- Go Best Practice: Standard pattern for Go libraries (used by GORM, stdlib packages, etc.)
See docs/reports/INTERNAL_VS_NO_INTERNAL_2025.md for detailed analysis.
๐ฏ Release Process
See RELEASE_GUIDE.md for detailed release process.
Summary:
- Feature branches created from
main - PRs merged to
main - CI passes on
main - Triple-check: branch, tag order, CHANGELOG
- Create tag:
git tag -a v0.X.X - Push tag:
git push origin v0.X.X
Only maintainers can create releases.
๐ Recognition
Contributors are recognized in:
- CHANGELOG.md (for significant contributions)
- GitHub contributors page
- Release notes
โ Questions?
- Issues: GitHub Issues
- Discussions: GitHub Discussions
- Email: support@coregx.dev
๐ Code of Conduct
See CODE_OF_CONDUCT.md for community guidelines.
Thank you for contributing to Relica! ๐
Every contribution, no matter how small, helps make Relica better for everyone.