Contributing¶
Guide for contributing to brix development.
Development Setup¶
Prerequisites¶
- Python 3.10+
- uv package manager
- Git
Clone and Install¶
Verify Setup¶
Development Workflow¶
Task Runner¶
Use poethepoet for common tasks:
uv run poe lint # Run ruff linting
uv run poe format # Run ruff formatting
uv run poe typecheck # Run ty type checking
uv run poe test # Run all tests
uv run poe test-unit # Run unit tests only
uv run poe test-integration # Run integration tests
uv run poe test-e2e # Run e2e tests
uv run poe check # Run lint + typecheck
uv run poe pre-commit # Run pre-commit hooks
Running the CLI¶
Running Tests¶
# All tests
uv run poe test
# Specific test file
uv run pytest tests/unit/test_profile_models.py -v
# Specific test
uv run pytest tests/unit/test_profile_models.py::test_duckdb_output -v
# With coverage
uv run pytest --cov=brix
Code Style¶
Linting and Formatting¶
Brix uses ruff for linting and formatting:
Type Hints¶
All public functions require type hints (ANN rules enforced):
def init_profile(
profile_path: Path,
force: bool = False,
template_name: str = "profiles.yml",
) -> ProfileInitResult:
...
Docstrings¶
Use Google-style docstrings:
def init_profile(profile_path: Path, force: bool = False) -> ProfileInitResult:
"""Initialize a dbt profile from template.
Creates a profiles.yml file at the specified path with a DuckDB
configuration for local development.
Args:
profile_path: Path where profiles.yml will be created.
force: If True, overwrite existing file.
Returns:
ProfileInitResult with success status and message.
Raises:
ProfileExistsError: If file exists and force is False.
"""
Line Length¶
Maximum 120 characters per line.
Pre-commit Hooks¶
Always run pre-commit before committing:
Or install hooks to run automatically:
Pull Request Process¶
- Fork the repository
- Create a branch from
main - Make changes following code style guidelines
- Add tests for new functionality
- Run checks:
uv run poe check && uv run poe test - Run pre-commit:
uv run poe pre-commit - Create PR with clear description
Commit Messages¶
Follow conventional commits:
feat: add snowflake adapter support
fix: handle empty profiles.yml gracefully
docs: update installation instructions
test: add integration tests for project init
refactor: extract validation logic to separate module
PR Description¶
Include: - Summary of changes - Related issues - Test coverage - Breaking changes (if any)
Adding Features¶
Adding a New Command¶
- Create command file in
commands/dbt/:
# commands/dbt/new_command.py
import typer
app = typer.Typer()
@app.command()
def action(name: str) -> None:
"""Command description."""
from brix.modules.dbt.new_feature import do_action
result = do_action(name)
typer.echo(result.message)
- Register in
commands/dbt/__init__.py:
from brix.commands.dbt.new_command import app as new_command_app
app.add_typer(new_command_app, name="new-command")
- Add business logic in
modules/dbt/new_feature/
Adding Tests¶
Place tests in the appropriate directory:
tests/unit/- No external dependencies, mocked I/Otests/integration/- May require dbt, real file operationstests/e2e/- Full dbt execution, real commands
Use markers for non-unit tests:
import pytest
@pytest.mark.integration
def test_profile_creation():
...
@pytest.mark.e2e
def test_full_workflow():
...
Release Process¶
Releases are automated via semantic-release:
- Merge PR to
main - GitHub Action analyzes commits
- Bumps version based on commit types
- Creates GitHub release
- Publishes to PyPI
Version bumps:
- fix: → patch (1.0.x)
- feat: → minor (1.x.0)
- BREAKING CHANGE: → major (x.0.0)