Thank you for your interest in contributing to catapulte! This document outlines contribution opportunities and guidelines for getting started.
- Rust (latest stable)
# Clone the repository
git clone https://github.com/jdrouet/catapulte.git
cd catapulte
# Build the project
cargo build
# Run tests
cargo test
# Run with development config
cargo runBefore submitting a PR, ensure your code passes all checks:
cargo fmt # Format code
cargo clippy # Lint
cargo test # Run tests
cargo audit # Security auditBelow are areas where contributions would be valuable.
- Testing Improvements
- Documentation Improvements
- Follow standard Rust conventions (
rustfmt) - Use
anyhow::Resultfor error handling - Add tracing instrumentation to new functions
- Write tests for new functionality
- Keep functions small and focused
- Document public APIs
- Test function names should follow the pattern
fn should_do_this_when_that()#[test] fn should_return_empty_list_when_no_packages_found() { ... } #[test] fn should_fail_when_database_connection_lost() { ... }
-
Do not use single letters for error variables
-
Use
errorerrorinstead ofefor readability// Bad .map_err(|e| anyhow::anyhow!("Failed: {e}")) // Good .map_err(|err| anyhow::anyhow!("Failed: {err}"))
-
When defining error enums with
thiserror, preserve error context by wrappinganyhow::Errorinstead of converting toString:// Bad - loses error chain context #[derive(Debug, thiserror::Error)] pub enum SendError { #[error("failed to send email: {0}")] TransportError(String), } // Good - preserves full error chain #[derive(Debug, thiserror::Error)] pub enum SendError { #[error("failed to send email")] TransportError(#[source] anyhow::Error), }
-
Use
#[source]attribute instead of{0}in error messages to enable proper error chain traversal. This allows tools and logging to display the full causal chain:// Bad - embeds source in message, breaks error chain #[error("failed to parse template: {0}")] Parse(SomeError), // Good - proper error chain with #[source] #[error("failed to parse template")] Parse(#[source] SomeError),
Generate code coverage reports with:
cargo llvm-covcatapulte follows a hexagonal (ports & adapters) architecture:
- Domain Layer: Core business logic, independent of external systems
- Adapters: Implementations for external systems (HTTP, Mrml, etc.)
- Traits: Interfaces that adapters implement
When adding new features:
- Define any new traits in the domain layer
- Implement adapters for external integrations
- Keep the domain layer free of framework dependencies
- Fork the repository
- Create a feature branch (
git checkout -b feature/my-feature) - Make your changes
- Run all checks (
cargo fmt && cargo clippy && cargo test) - Commit with a descriptive message
- Push to your fork
- Open a Pull Request
Use conventional commits:
feat:New featuresfix:Bug fixesdocs:Documentation changestest:Test additions or fixesrefactor:Code refactoringchore:Maintenance tasks
Pull request titles must follow the conventional commits format:
feat: add health check endpointfix: handle empty package list gracefullydocs: update configuration reference
This ensures consistent changelog generation and release notes.
Feel free to open an issue for discussion before starting work on larger features. This helps ensure your contribution aligns with the project direction and avoids duplicate effort.