Guidelines for contributing to Strait project.
We welcome contributions to Strait! This document provides instructions on how to set up your development environment and the standards we follow.
Getting Started
Prerequisites
To build and run Strait locally, you need:
- Go 1.26+
- Docker (for running PostgreSQL, Redis, and Sequin)
- Bun (workspace package manager)
- golangci-lint (for linting)
- lefthook (for pre-commit hooks)
Setup Instructions
-
Clone the repository:
git clone https://github.com/leonardomso/strait.git cd strait -
Start infrastructure: Use Docker Compose to start the required services:
docker compose -f apps/strait/docker-compose.yml up -d -
Install workspace dependencies:
bun install -
Install pre-commit hooks:
lefthook install -
Run the application:
export DATABASE_URL=postgres://strait:strait@localhost:5432/strait?sslmode=disable export REDIS_URL=redis://localhost:6379 export INTERNAL_SECRET=your-secret export JWT_SIGNING_KEY=your-jwt-key-at-least-32-chars-long go run ./apps/strait/cmd/strait --mode all
Code Style
We follow idiomatic Go patterns and specific project conventions:
- Raw SQL: We use
pgx/v5and raw SQL for all database operations. Do not use an ORM. - Interface Segregation: Define small, focused interfaces at the consumer side.
- Error Handling: Wrap errors using
%wto provide context while preserving the original error type. - Collections: Use
samber/lofor collection operations (Map, Filter, KeyBy, Keys) instead of hand-written loops. - Concurrency: Use
sourcegraph/concfor goroutines (WaitGroup, pool). Never use baregostatements orsync.WaitGroupdirectly. - Worker Pool: Use the
apps/strait/internal/workerpond/v2 pool. Do not create custom goroutine pools. - Test Assertions: Use
testutil.AssertEqual(powered bygoogle/go-cmp) for structural comparisons with rich diffs. Avoid manual field-by-field assertions. - No Emojis: Avoid using emojis in code, comments, or documentation.
Linting
We use golangci-lint with a strict set of 18+ linters configured in apps/strait/.golangci.yml.
To run the linter manually:
cd apps/strait && golangci-lint run ./...The linter checks for code duplication, unhandled errors, security vulnerabilities, and style consistency.
Pre-commit Hooks
We use lefthook to run checks automatically before every commit. This ensures that all code entering the repository meets our quality standards.
Current pre-commit checks include:
golangci-lint- OpenAPI parity check (
apps/strait/scripts/check-openapi-parity/main.go) to ensureapps/strait/internal/api/routes.go,apps/strait/internal/api/openapi.yaml, anddocs/openapi.yamlstay in sync.
Manual parity check command:
cd apps/strait && go run ./scripts/check-openapi-parityIf lefthook fails, you must fix the issues before you can commit your changes.
Pull Request Guidelines
- One Logical Change: Each PR should focus on a single feature, bug fix, or refactoring.
- Tests Required: All new features and bug fixes must include corresponding tests (unit, integration, or E2E).
- Documentation: Update relevant documentation if your changes affect the public API or configuration.
- Clean History: Ensure your commit history is clean and messages are descriptive.
Project Structure
apps/strait/cmd/strait/: Entry point for the CLI and server. Contains command definitions.apps/strait/internal/: Private application code.api/: HTTP handlers and routing.domain/: Core business logic and FSM definitions.store/: Database access layer (raw SQL).worker/: Job execution and pond/v2 worker pool with backpressure and OTel metrics.scheduler/: Background tasks and polling (uses conc for structured concurrency).testutil/: Shared testing helpers, go-cmp assertion utilities, and data factories.
apps/strait/migrations/: SQL migration files embedded into the binary.packages/: Shared workspace packages (UI, SDKs, utilities, etc.).