Thank you for your interest in contributing to Rustmail. This guide explains how to contribute effectively.
- Fork the repository on GitHub
- Clone your fork locally
- Set up the development environment (see Building)
- Create a branch for your changes
git clone https://github.com/YOUR_USERNAME/rustmail.git
cd rustmail
git checkout -b feature/your-feature-name- Check existing issues for something to work on
- For new features, open an issue first to discuss the approach
- Bug fixes can go directly to a pull request
- Write clean, readable code
- Follow existing patterns in the codebase
- Add tests for new functionality
- Update documentation as needed
# Run tests
cargo test --workspace
# Check formatting
cargo fmt --all --check
# Run linter
cargo clippy --workspaceWrite clear commit messages:
feat: add snippet management command
- Add /snippet command for using saved responses
- Add snippet CRUD operations in database
- Include tests for snippet operations
Commit message prefixes:
feat:- New featurefix:- Bug fixdocs:- Documentation changesrefactor:- Code refactoringtest:- Test additions/changeschore:- Build/tooling changes
- Push your branch to your fork
- Open a pull request against
main - Fill out the PR template
- Wait for review
- Follow standard Rust conventions
- Use
cargo fmtfor formatting - Address
cargo clippywarnings - Prefer explicit types over inference when it aids readability
// Good
let thread_id: u64 = message.channel_id.get();
// Also acceptable when obvious
let content = message.content.clone();- Document public APIs with doc comments
- Include examples for complex functions
- Keep comments current with code
/// Creates a new ticket for the specified user.
///
/// # Arguments
///
/// * `user_id` - Discord user ID
/// * `initial_message` - Optional first message content
///
/// # Returns
///
/// The created thread's channel ID.
pub async fn create_ticket(user_id: u64, initial_message: Option<&str>) -> Result<u64> {
// ...
}- Create a module in
rustmail/src/commands/ - Implement the command handler
- Add slash command definition
- Add text command parser
- Register in
commands/mod.rs - Add to documentation
- Create handler in
rustmail/src/api/handler/ - Define route in
rustmail/src/api/routes/ - Add authentication/authorization as needed
- Document in
docs/reference/api.md
- Create migration in
migrations/ - Update relevant structs in
rustmail_types - Add database functions
- Test migration up and down
- Code compiles without errors
- All tests pass
- Code is formatted (
cargo fmt) - No clippy warnings
- Documentation updated
- Commit messages are clear
Include:
- What the change does
- Why it's needed
- How to test it
- Any breaking changes
- Maintainers will review the PR
- Address feedback with additional commits
- Once approved, the PR will be merged
Place tests in the same file as the code:
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse_duration() {
assert_eq!(parse_duration("1h"), Some(3600));
assert_eq!(parse_duration("30m"), Some(1800));
}
}For tests requiring multiple components, use tests/ directory.
# Single test
cargo test test_name
# Tests in a module
cargo test module_name::
# With output
cargo test -- --nocapture- Add variant to
Languageenum inrustmail/src/i18n/ - Create translation module
- Add JSON file for panel in
rustmail_panel/src/i18n/translations/ - Test all strings render correctly
- Keep all languages in sync
- Use English as the source
- Maintain consistency in terminology
Include:
- Rustmail version
- Operating system
- Steps to reproduce
- Expected vs actual behavior
- Relevant logs
Include:
- Use case description
- Proposed solution
- Alternative approaches considered
- GitHub Issues - Bug reports, feature requests
- GitHub Discussions - Questions, ideas
- Discord Server - Real-time chat
By contributing, you agree that your contributions will be licensed under the AGPLv3 license.
Contributors are recognized in:
- Git history
- Release notes for significant contributions
- README acknowledgments for major features