Thank you for your interest in contributing to JaxBucket! This document provides guidelines for contributing to the project.
Before contributing, please:
- Read the README.md to understand the project
- Review DEVELOPMENT.md for setup instructions
- Check existing issues for open tasks
If you find a bug, please open an issue with:
- Clear title describing the problem
- Steps to reproduce the bug
- Expected behavior vs actual behavior
- Environment details (OS, Rust version, etc.)
- Logs if applicable (use
RUST_LOG=debug)
Feature requests are welcome! Please open an issue with:
- Use case - Why is this feature needed?
- Proposed solution - How should it work?
- Alternatives - Other approaches you considered
- Impact - Who would benefit from this?
We welcome code contributions! Here's the process:
# Fork the repo on GitHub, then clone your fork
git clone https://github.com/YOUR_USERNAME/jax-bucket.git
cd jax-bucketUse descriptive branch names:
# Feature branches
git checkout -b feature/add-conflict-resolution
# Bug fix branches
git checkout -b fix/sync-race-condition
# Documentation branches
git checkout -b docs/improve-api-docs- Follow the code style guide
- Add tests for new functionality
- Update documentation as needed
- Keep commits focused and atomic
We use conventional commits for clear history and automated changelog generation:
# Format: <type>: <description>
# Types:
git commit -m "feat: add streaming encryption for large files"
git commit -m "fix: prevent race condition in sync manager"
git commit -m "docs: add examples for bucket sharing"
git commit -m "refactor: simplify manifest serialization"
git commit -m "test: add integration tests for P2P sync"
git commit -m "chore: update dependencies"
git commit -m "perf: optimize blob storage"Commit types:
feat:- New feature (minor version bump)fix:- Bug fix (patch version bump)docs:- Documentation onlyrefactor:- Code restructuring (no behavior change)test:- Adding or updating testschore:- Maintenance tasksperf:- Performance improvements
Breaking changes:
git commit -m "feat!: change manifest format to support versioning"
# Or in commit body:
git commit -m "feat: redesign sync protocol
BREAKING CHANGE: sync protocol v2 is incompatible with v1"Before pushing, ensure:
# All tests pass
cargo test
# Code is formatted
cargo fmt
# No clippy warnings
cargo clippy -- -D warnings
# Optional: run specific tests
cargo test -p common
cargo test -p service# Push your branch
git push origin feature/add-conflict-resolution
# Create a pull request on GitHubUse the same format as commit messages:
feat: add conflict resolution for concurrent updates
fix: handle missing pinset gracefully
docs: improve protocol specification
Include:
- Summary - What does this PR do?
- Motivation - Why is this change needed?
- Changes - List of key changes
- Testing - How did you test this?
- Related Issues - Link to issues (e.g., "Fixes #123")
Example:
## Summary
Adds conflict resolution for concurrent updates to the same bucket.
## Motivation
Currently, concurrent updates cause sync failures. This implements automatic merge resolution using last-write-wins strategy.
## Changes
- Added `ConflictResolver` trait in `common/src/bucket/`
- Implemented LWW strategy in sync manager
- Added integration tests for concurrent writes
## Testing
- Unit tests in `test_conflict_resolution()`
- Integration test with two nodes updating simultaneously
- Manual testing with dev environment
Fixes #42Before submitting, verify:
- Tests pass (
cargo test) - Code is formatted (
cargo fmt) - No clippy warnings (
cargo clippy -- -D warnings) - Documentation updated (if applicable)
- Conventional commit format used
- PR description is clear and complete
Follow standard Rust conventions:
// Good: snake_case for functions and variables
fn create_bucket(name: String) -> Result<Bucket> { ... }
let bucket_id = uuid::Uuid::new_v4();
// Good: PascalCase for types
struct Manifest { ... }
enum SyncStatus { ... }
// Good: SCREAMING_SNAKE_CASE for constants
const MAX_BLOB_SIZE: usize = 1024 * 1024 * 10;
// Good: Document public APIs
/// Creates a new encrypted bucket.
///
/// # Arguments
///
/// * `name` - Human-readable bucket name
///
/// # Returns
///
/// The newly created manifest
pub fn create_bucket(name: String) -> Result<Manifest> {
// Implementation
}// Library crates: use custom error types
#[derive(Debug, thiserror::Error)]
pub enum BucketError {
#[error("bucket not found: {0}")]
NotFound(Uuid),
}
// Application code: use anyhow
use anyhow::{Context, Result};
fn load_bucket(id: Uuid) -> Result<Bucket> {
db.get_bucket(id)
.context("failed to load bucket")?
}Group imports logically:
// Standard library
use std::collections::HashMap;
use std::path::PathBuf;
// External crates
use anyhow::Result;
use serde::{Deserialize, Serialize};
use uuid::Uuid;
// Local crates
use common::bucket::Manifest;
use common::crypto::Secret;Write tests for new functionality:
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_create_bucket() {
let manifest = create_bucket("test".to_string()).unwrap();
assert_eq!(manifest.name, "test");
}
#[tokio::test]
async fn test_sync_workflow() {
// Integration test
}
}Document all public APIs:
/// Creates a new bucket with the given name.
///
/// The bucket is initialized with an empty root node and a randomly
/// generated encryption secret. The manifest is stored in the database
/// and the root node is written to the blob store.
///
/// # Arguments
///
/// * `name` - Human-readable name for the bucket
///
/// # Returns
///
/// The UUID of the newly created bucket
///
/// # Errors
///
/// Returns an error if:
/// - Database write fails
/// - Blob store is unavailable
///
/// # Example
///
/// ```
/// let bucket_id = create_bucket("my-files".to_string())?;
/// println!("Created bucket: {}", bucket_id);
/// ```
pub fn create_bucket(name: String) -> Result<Uuid> {
// Implementation
}When updating documentation:
- Keep it concise and clear
- Include examples
- Update all affected files (README, PROTOCOL, etc.)
- Verify links work
- Automated Checks: CI runs tests, formatting, and linting
- Review: Maintainers review your code
- Discussion: Address feedback and questions
- Approval: Once approved, PR is merged
- Be open to suggestions
- Ask questions if unclear
- Update your PR based on feedback
- Push additional commits (don't force-push during review)
- Be respectful and inclusive
- Welcome newcomers
- Focus on constructive feedback
- Assume good intentions
- Issues: For bugs and feature requests
- Discussions: For questions and ideas
- Pull Requests: For code contributions
Stuck? Need help? Ask!
- Open an issue with the
questionlabel - Start a discussion in GitHub Discussions
- Check existing docs and issues first
Update dependencies carefully:
# Update a specific dependency
cargo update -p iroh
# Check for outdated dependencies
cargo outdated
# Audit for security issues
cargo auditWhen optimizing:
- Profile before optimizing
- Add benchmarks for critical paths
- Document performance characteristics
- Consider memory usage and allocations
For security-related changes:
- Discuss in a private issue first (for vulnerabilities)
- Consider threat model implications
- Add tests for security properties
- Document security assumptions
By contributing to JaxBucket, you agree that your contributions will be licensed under the MIT License.
Your contributions make JaxBucket better for everyone. Thank you for taking the time to contribute!