Contributing to DaemonEye
Thank you for your interest in contributing to DaemonEye! This guide will help you get started with contributing to the project.
Table of Contents
- Getting Started
- Development Environment
- Code Standards
- Testing Requirements
- Pull Request Process
- Issue Reporting
- Documentation
- Community Guidelines
- Development Workflow
- Getting Help
- License
Getting Started
Prerequisites
Before contributing to DaemonEye, ensure you have:
- Rust 1.85+: Latest stable Rust toolchain
- Git: Version control system
- Docker: For containerized testing (optional)
- Just: Task runner (install with
cargo install just
) - Editor: VS Code with Rust extension (recommended)
Fork and Clone
-
Fork the repository on GitHub
-
Clone your fork locally:
git clone https://github.com/your-username/daemoneye.git cd daemoneye
-
Add the upstream repository:
git remote add upstream https://github.com/EvilBit-Labs/daemoneye.git
Development Setup
-
Install dependencies:
just setup
-
Run tests to ensure everything works:
just test
-
Build the project:
just build
Development Environment
Project Structure
DaemonEye/
├── procmond/ # Process monitoring daemon
├── daemoneye-agent/ # Agent orchestrator
├── daemoneye-cli/ # CLI interface
├── daemoneye-lib/ # Shared library
├── docs/ # Documentation
├── tests/ # Integration tests
├── examples/ # Example configurations
├── justfile # Task runner
├── Cargo.toml # Workspace configuration
└── README.md # Project README
Workspace Configuration
DaemonEye uses a Cargo workspace with the following structure:
[workspace]
resolver = "2"
members = [
"procmond",
"daemoneye-agent",
"daemoneye-cli",
"daemoneye-lib",
]
[workspace.dependencies]
tokio = { version = "1.0", features = ["full"] }
clap = { version = "4.0", features = ["derive", "completion"] }
serde = { version = "1.0", features = ["derive"] }
sqlx = { version = "0.7", features = ["runtime-tokio-rustls", "sqlite"] }
sysinfo = "0.30"
tracing = "0.1"
thiserror = "1.0"
anyhow = "1.0"
Development Commands
Use the just
task runner for common development tasks:
# Setup development environment
just setup
# Build the project
just build
# Run tests
just test
# Run linting
just lint
# Format code
just fmt
# Run benchmarks
just bench
# Generate documentation
just docs
# Clean build artifacts
just clean
Code Standards
Rust Standards
DaemonEye follows strict Rust coding standards:
- Edition: Always use Rust 2024 Edition
- Linting: Zero warnings policy with
cargo clippy -- -D warnings
- Safety:
unsafe_code = "forbid"
enforced at workspace level - Formatting: Standard
rustfmt
with 119 character line length - Error Handling: Use
thiserror
for structured errors,anyhow
for error context
Code Style
// Use thiserror for library errors
#[derive(Debug, Error)]
pub enum CollectionError {
#[error("Permission denied accessing process {pid}")]
PermissionDenied { pid: u32 },
#[error("Process {pid} no longer exists")]
ProcessNotFound { pid: u32 },
#[error("I/O error: {0}")]
IoError(#[from] std::io::Error),
}
// Use anyhow for application error context
use anyhow::{Context, Result};
pub async fn collect_processes() -> Result<Vec<ProcessInfo>> {
let processes = sysinfo::System::new_all()
.processes()
.values()
.map(|p| ProcessInfo::from(p))
.collect::<Vec<_>>();
Ok(processes)
.context("Failed to collect process information")
}
// Document all public APIs
/// Collects information about all running processes.
///
/// # Returns
///
/// A vector of `ProcessInfo` structs containing details about each process.
///
/// # Errors
///
/// This function will return an error if:
/// - System information cannot be accessed
/// - Process enumeration fails
/// - Memory allocation fails
///
/// # Examples
///
/// ```rust
/// use daemoneye_lib::collector::ProcessCollector;
///
/// let collector = ProcessCollector::new();
/// let processes = collector.collect_processes().await?;
/// println!("Found {} processes", processes.len());
/// ```
pub async fn collect_processes() -> Result<Vec<ProcessInfo>, CollectionError> {
// Implementation
}
Naming Conventions
- Functions:
snake_case
- Variables:
snake_case
- Types:
PascalCase
- Constants:
SCREAMING_SNAKE_CASE
- Modules:
snake_case
- Files:
snake_case.rs
Documentation Standards
All public APIs must be documented with rustdoc comments:
/// A process information structure containing details about a running process.
///
/// This structure provides comprehensive information about a process including
/// its PID, name, executable path, command line arguments, and resource usage.
///
/// # Examples
///
/// ```rust
/// use daemoneye_lib::ProcessInfo;
///
/// let process = ProcessInfo {
/// pid: 1234,
/// name: "example".to_string(),
/// executable_path: Some("/usr/bin/example".to_string()),
/// command_line: Some("example --arg value".to_string()),
/// start_time: Some(Utc::now()),
/// cpu_usage: Some(0.5),
/// memory_usage: Some(1024),
/// status: ProcessStatus::Running,
/// executable_hash: Some("abc123".to_string()),
/// collection_time: Utc::now(),
/// };
/// ```
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct ProcessInfo {
/// The process ID (PID) of the process
pub pid: u32,
/// The name of the process
pub name: String,
/// The full path to the process executable
pub executable_path: Option<String>,
/// The command line arguments used to start the process
pub command_line: Option<String>,
/// The time when the process was started
pub start_time: Option<DateTime<Utc>>,
/// The current CPU usage percentage
pub cpu_usage: Option<f64>,
/// The current memory usage in bytes
pub memory_usage: Option<u64>,
/// The current status of the process
pub status: ProcessStatus,
/// The SHA-256 hash of the process executable
pub executable_hash: Option<String>,
/// The time when this information was collected
pub collection_time: DateTime<Utc>,
}
Testing Requirements
Test Coverage
All code must have comprehensive test coverage:
- Unit Tests: Test individual functions and methods
- Integration Tests: Test component interactions
- End-to-End Tests: Test complete workflows
- Property Tests: Test with random inputs
- Fuzz Tests: Test with malformed inputs
Test Structure
#[cfg(test)]
mod tests {
use super::*;
use insta::assert_snapshot;
use tempfile::TempDir;
#[tokio::test]
async fn test_process_collection() {
let collector = ProcessCollector::new();
let processes = collector.collect_processes().await.unwrap();
assert!(!processes.is_empty());
assert!(processes.iter().any(|p| p.pid > 0));
}
#[test]
fn test_process_info_serialization() {
let process = ProcessInfo::default();
let serialized = serde_json::to_string(&process).unwrap();
let deserialized: ProcessInfo = serde_json::from_str(&serialized).unwrap();
assert_eq!(process, deserialized);
}
}
Running Tests
# Run all tests
cargo test
# Run specific test
cargo test test_process_collection
# Run tests with output
cargo test -- --nocapture
# Run integration tests
cargo test --test integration
# Run benchmarks
cargo bench
# Run fuzz tests
cargo fuzz run process_info
Pull Request Process
Before Submitting
-
Sync with upstream:
git fetch upstream git checkout main git merge upstream/main
-
Create a feature branch:
git checkout -b feature/your-feature-name
-
Make your changes:
- Write code following the coding standards
- Add comprehensive tests
- Update documentation
- Run all tests and linting
-
Commit your changes:
git add . git commit -m "feat: add new feature description"
Commit Message Format
Use conventional commits format:
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]
Types:
feat
: New featurefix
: Bug fixdocs
: Documentation changesstyle
: Code style changesrefactor
: Code refactoringtest
: Test changeschore
: Build process or auxiliary tool changes
Examples:
feat(collector): add process filtering by name
Add ability to filter processes by name pattern using regex.
This improves performance when monitoring specific processes.
Closes #123
fix(database): resolve memory leak in query execution
Fix memory leak that occurred when executing large queries.
The issue was caused by not properly cleaning up prepared statements.
Fixes #456
Pull Request Guidelines
- Title: Clear, descriptive title
- Description: Detailed description of changes
- Tests: Ensure all tests pass
- Documentation: Update relevant documentation
- Breaking Changes: Clearly mark any breaking changes
- Related Issues: Link to related issues
Pull Request Template
## Description
Brief description of the changes made.
## Type of Change
- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [ ] Documentation update
- [ ] Performance improvement
- [ ] Code refactoring
## Testing
- [ ] Unit tests pass
- [ ] Integration tests pass
- [ ] End-to-end tests pass
- [ ] Manual testing completed
- [ ] Performance tests pass
## Checklist
- [ ] Code follows the project's style guidelines
- [ ] Self-review of code completed
- [ ] Code is properly commented
- [ ] Documentation updated
- [ ] No new warnings introduced
- [ ] Breaking changes documented
## Related Issues
Closes #123
Fixes #456
Issue Reporting
Bug Reports
When reporting bugs, please include:
- Environment: OS, Rust version, DaemonEye version
- Steps to Reproduce: Clear, numbered steps
- Expected Behavior: What should happen
- Actual Behavior: What actually happens
- Logs: Relevant log output
- Screenshots: If applicable
Feature Requests
When requesting features, please include:
- Use Case: Why is this feature needed?
- Proposed Solution: How should it work?
- Alternatives: Other solutions considered
- Additional Context: Any other relevant information
Issue Templates
Use the provided issue templates:
- Bug Report:
.github/ISSUE_TEMPLATE/bug_report.md
- Feature Request:
.github/ISSUE_TEMPLATE/feature_request.md
- Question:
.github/ISSUE_TEMPLATE/question.md
Documentation
Documentation Standards
- Keep documentation up to date
- Use clear, concise language
- Include code examples
- Follow markdown best practices
- Use consistent formatting
Documentation Structure
docs/
├── src/
│ ├── introduction.md
│ ├── getting-started.md
│ ├── architecture/
│ ├── technical/
│ ├── user-guides/
│ ├── api-reference/
│ ├── deployment/
│ ├── security.md
│ ├── testing.md
│ └── contributing.md
├── book.toml
└── README.md
Building Documentation
# Install mdbook
cargo install mdbook
# Build documentation
mdbook build
# Serve documentation locally
mdbook serve
Community Guidelines
Code of Conduct
We are committed to providing a welcoming and inclusive environment for all contributors. Please:
- Be respectful and constructive
- Focus on what is best for the community
- Show empathy towards other community members
- Accept constructive criticism gracefully
- Help others learn and grow
Communication
- GitHub Issues: For bug reports and feature requests
- GitHub Discussions: For questions and general discussion
- Pull Requests: For code contributions
- Discord: For real-time chat (invite link in README)
Recognition
Contributors are recognized in:
- CONTRIBUTORS.md file
- Release notes
- Project documentation
- Community highlights
Development Workflow
Branch Strategy
main
: Production-ready codedevelop
: Integration branch for featuresfeature/*
: Feature development branchesbugfix/*
: Bug fix brancheshotfix/*
: Critical bug fixes
Release Process
- Version Bumping: Update version numbers
- Changelog: Update CHANGELOG.md
- Documentation: Update documentation
- Testing: Run full test suite
- Release: Create GitHub release
- Distribution: Publish to package managers
Continuous Integration
All pull requests must pass:
- Unit tests
- Integration tests
- Linting checks
- Security scans
- Performance benchmarks
- Documentation builds
Getting Help
If you need help contributing:
- Check Documentation: Review this guide and other docs
- Search Issues: Look for similar issues or discussions
- Ask Questions: Use GitHub Discussions or Discord
- Contact Maintainers: Reach out to project maintainers
License
By contributing to DaemonEye, you agree that your contributions will be licensed under the same license as the project (Apache 2.0 for core features, commercial license for business/enterprise features).
Thank you for contributing to DaemonEye! Your contributions help make the project better for everyone.