- Fix trailing spaces and blank lines in Forgejo workflows - Update system requirements from Ubuntu Jammy/Bookworm to Debian 13+ (Trixie) - Update test treefile to use Debian Trixie instead of Ubuntu Jammy - Update documentation to reflect modern system requirements - Fix yamllint errors for CI/CD functionality - Ensure compatibility with modern OSTree and libapt versions
623 lines
15 KiB
Markdown
623 lines
15 KiB
Markdown
# apt-ostree Developer Guide
|
|
|
|
## Table of Contents
|
|
1. [Architecture Overview](#architecture-overview)
|
|
2. [Development Setup](#development-setup)
|
|
3. [Code Organization](#code-organization)
|
|
4. [API Documentation](#api-documentation)
|
|
5. [Development Workflow](#development-workflow)
|
|
6. [Testing and Debugging](#testing-and-debugging)
|
|
7. [Contributing Guidelines](#contributing-guidelines)
|
|
|
|
## Architecture Overview
|
|
|
|
### System Components
|
|
apt-ostree consists of several key components:
|
|
|
|
```
|
|
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
|
|
│ CLI Client │ │ System Daemon │ │ OSTree Repo │
|
|
│ (apt-ostree) │◄──►│ (apt-ostreed) │◄──►│ (/ostree/) │
|
|
└─────────────────┘ └──────────────────┘ └─────────────────┘
|
|
│ │ │
|
|
│ │ │
|
|
▼ ▼ ▼
|
|
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
|
|
│ APT System │ │ D-Bus Layer │ │ File System │
|
|
│ (Package Mgmt)│ │ (IPC Interface) │ │ (Deployments) │
|
|
└─────────────────┘ └──────────────────┘ └─────────────────┘
|
|
```
|
|
|
|
### Component Responsibilities
|
|
|
|
#### CLI Client (apt-ostree)
|
|
- **Command parsing**: Uses `clap` for argument parsing
|
|
- **User interface**: Provides user-friendly command interface
|
|
- **Command dispatch**: Routes commands to appropriate handlers
|
|
- **Output formatting**: Formats results for user consumption
|
|
|
|
#### System Daemon (apt-ostreed)
|
|
- **Background processing**: Handles long-running operations
|
|
- **D-Bus interface**: Provides IPC for system operations
|
|
- **Transaction management**: Manages atomic system changes
|
|
- **Security**: Implements Polkit authentication
|
|
|
|
#### OSTree Integration
|
|
- **Repository management**: Manages OSTree repositories
|
|
- **Deployment handling**: Handles system deployments
|
|
- **Atomic operations**: Ensures system consistency
|
|
- **Rollback support**: Provides system recovery
|
|
|
|
#### APT Integration
|
|
- **Package resolution**: Resolves package dependencies
|
|
- **Repository management**: Manages APT repositories
|
|
- **Transaction handling**: Handles package transactions
|
|
- **Conflict resolution**: Resolves package conflicts
|
|
|
|
## Development Setup
|
|
|
|
### Prerequisites
|
|
- **Rust toolchain**: Rust 1.75+ with Cargo
|
|
- **System dependencies**: See installation guide
|
|
- **Development tools**: Git, make, pkg-config
|
|
- **Documentation tools**: rustdoc, cargo-doc
|
|
|
|
### Environment Setup
|
|
```bash
|
|
# Clone repository
|
|
git clone https://github.com/robojerk/apt-ostree.git
|
|
cd apt-ostree
|
|
|
|
# Install Rust toolchain
|
|
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
|
|
source ~/.cargo/env
|
|
|
|
# Install system dependencies
|
|
sudo apt-get install build-essential pkg-config \
|
|
libostree-dev libapt-pkg-dev libpolkit-gobject-1-dev \
|
|
libdbus-1-dev libsystemd-dev
|
|
|
|
# Install development tools
|
|
cargo install cargo-outdated cargo-audit cargo-tarpaulin
|
|
```
|
|
|
|
### Build Configuration
|
|
```bash
|
|
# Development build with all features
|
|
cargo build --features development,dev-full
|
|
|
|
# Release build
|
|
cargo build --release
|
|
|
|
# Documentation
|
|
cargo doc --open --features development
|
|
|
|
# Run tests
|
|
cargo test --features development
|
|
```
|
|
|
|
## Code Organization
|
|
|
|
### Directory Structure
|
|
```
|
|
src/
|
|
├── main.rs # CLI entry point
|
|
├── cli.rs # Command-line interface definitions
|
|
├── commands/ # Command implementations
|
|
│ ├── mod.rs # Command registry
|
|
│ ├── package.rs # Package management commands
|
|
│ ├── system.rs # System management commands
|
|
│ ├── testutils.rs # Development utilities
|
|
│ ├── shlib_backend.rs # Shared library backend
|
|
│ └── internals.rs # Internal diagnostics
|
|
├── lib/ # Core library code
|
|
│ ├── mod.rs # Library entry point
|
|
│ ├── apt.rs # APT integration
|
|
│ ├── ostree.rs # OSTree integration
|
|
│ ├── security.rs # Security and authentication
|
|
│ ├── system.rs # System operations
|
|
│ ├── transaction.rs # Transaction management
|
|
│ └── logging.rs # Logging and metrics
|
|
├── daemon/ # Daemon implementation
|
|
│ ├── main.rs # Daemon entry point
|
|
│ ├── dbus.rs # D-Bus interface
|
|
│ ├── polkit.rs # Polkit integration
|
|
│ └── systemd.rs # systemd integration
|
|
└── tests/ # Test suite
|
|
├── integration_tests.rs
|
|
└── common/
|
|
```
|
|
|
|
### Key Modules
|
|
|
|
#### Command System
|
|
The command system uses a trait-based approach for extensibility:
|
|
|
|
```rust
|
|
pub trait Command {
|
|
fn execute(&self, args: &[String]) -> Result<(), Box<dyn std::error::Error>>;
|
|
fn help(&self) -> String;
|
|
fn usage(&self) -> String;
|
|
}
|
|
|
|
pub struct CommandRegistry {
|
|
commands: HashMap<String, Box<dyn Command>>,
|
|
}
|
|
```
|
|
|
|
#### Library Interface
|
|
The library provides a clean API for external consumers:
|
|
|
|
```rust
|
|
pub struct AptOstree {
|
|
apt_manager: AptManager,
|
|
ostree_manager: OstreeManager,
|
|
security_manager: SecurityManager,
|
|
}
|
|
|
|
impl AptOstree {
|
|
pub fn new() -> Result<Self, Error> { /* ... */ }
|
|
pub fn install_packages(&self, packages: &[String]) -> Result<(), Error> { /* ... */ }
|
|
pub fn remove_packages(&self, packages: &[String]) -> Result<(), Error> { /* ... */ }
|
|
}
|
|
```
|
|
|
|
## API Documentation
|
|
|
|
### Core Types
|
|
|
|
#### Package Management
|
|
```rust
|
|
pub struct Package {
|
|
pub name: String,
|
|
pub version: String,
|
|
pub architecture: String,
|
|
pub dependencies: Vec<String>,
|
|
pub conflicts: Vec<String>,
|
|
}
|
|
|
|
pub struct PackageTransaction {
|
|
pub packages: Vec<Package>,
|
|
pub operation: TransactionOperation,
|
|
pub status: TransactionStatus,
|
|
}
|
|
```
|
|
|
|
#### OSTree Integration
|
|
```rust
|
|
pub struct Deployment {
|
|
pub id: String,
|
|
pub branch: String,
|
|
pub commit: String,
|
|
pub timestamp: DateTime<Utc>,
|
|
pub packages: Vec<String>,
|
|
}
|
|
|
|
pub struct OSTreeRepository {
|
|
pub path: PathBuf,
|
|
pub mode: RepositoryMode,
|
|
pub remotes: HashMap<String, Remote>,
|
|
}
|
|
```
|
|
|
|
#### Security
|
|
```rust
|
|
pub struct SecurityContext {
|
|
pub user: String,
|
|
pub groups: Vec<String>,
|
|
pub permissions: Permissions,
|
|
}
|
|
|
|
pub struct AuthenticationResult {
|
|
pub authenticated: bool,
|
|
pub user: Option<String>,
|
|
pub permissions: Permissions,
|
|
}
|
|
```
|
|
|
|
### Public API
|
|
|
|
#### High-Level Operations
|
|
```rust
|
|
impl AptOstree {
|
|
/// Install packages atomically
|
|
pub fn install_packages(&self, packages: &[String]) -> Result<(), Error>
|
|
|
|
/// Remove packages atomically
|
|
pub fn remove_packages(&self, packages: &[String]) -> Result<(), Error>
|
|
|
|
/// Upgrade all packages
|
|
pub fn upgrade_system(&self) -> Result<(), Error>
|
|
|
|
/// Rollback to previous deployment
|
|
pub fn rollback(&self) -> Result<(), Error>
|
|
}
|
|
```
|
|
|
|
#### Transaction Management
|
|
```rust
|
|
impl TransactionManager {
|
|
/// Start a new transaction
|
|
pub fn start_transaction(&mut self, operation: TransactionOperation) -> Result<TransactionId, Error>
|
|
|
|
/// Add packages to transaction
|
|
pub fn add_packages(&mut self, transaction_id: TransactionId, packages: &[String]) -> Result<(), Error>
|
|
|
|
/// Commit transaction
|
|
pub fn commit_transaction(&mut self, transaction_id: TransactionId) -> Result<(), Error>
|
|
|
|
/// Rollback transaction
|
|
pub fn rollback_transaction(&mut self, transaction_id: TransactionId) -> Result<(), Error>
|
|
}
|
|
```
|
|
|
|
#### System Operations
|
|
```rust
|
|
impl SystemManager {
|
|
/// Get system status
|
|
pub fn get_system_status(&self) -> SystemStatus
|
|
|
|
/// Manage kernel arguments
|
|
pub fn set_kernel_args(&self, args: &[String]) -> Result<(), Error>
|
|
|
|
/// Regenerate initramfs
|
|
pub fn regenerate_initramfs(&self) -> Result<(), Error>
|
|
}
|
|
```
|
|
|
|
## Development Workflow
|
|
|
|
### Adding New Commands
|
|
|
|
#### 1. Define Command Structure
|
|
```rust
|
|
// src/cli.rs
|
|
#[derive(Subcommand)]
|
|
pub enum Commands {
|
|
// ... existing commands ...
|
|
NewCommand(NewCommandArgs),
|
|
}
|
|
|
|
#[derive(Args)]
|
|
pub struct NewCommandArgs {
|
|
#[arg(long)]
|
|
option: Option<String>,
|
|
|
|
#[arg(value_name = "TARGET")]
|
|
target: String,
|
|
}
|
|
```
|
|
|
|
#### 2. Implement Command Logic
|
|
```rust
|
|
// src/commands/new_command.rs
|
|
pub struct NewCommand;
|
|
|
|
impl Command for NewCommand {
|
|
fn execute(&self, args: &[String]) -> Result<(), Box<dyn std::error::Error>> {
|
|
// Implementation here
|
|
Ok(())
|
|
}
|
|
|
|
fn help(&self) -> String {
|
|
"Help text for new command".to_string()
|
|
}
|
|
|
|
fn usage(&self) -> String {
|
|
"new-command [OPTIONS] TARGET".to_string()
|
|
}
|
|
}
|
|
```
|
|
|
|
#### 3. Register Command
|
|
```rust
|
|
// src/commands/mod.rs
|
|
pub mod new_command;
|
|
|
|
// In CommandRegistry::new()
|
|
self.commands.insert("new-command".to_string(), Box::new(NewCommand));
|
|
```
|
|
|
|
#### 4. Add to Main Dispatch
|
|
```rust
|
|
// src/main.rs
|
|
match cli.command {
|
|
Commands::NewCommand(args) => {
|
|
// Handle new command
|
|
}
|
|
}
|
|
```
|
|
|
|
### Adding New Features
|
|
|
|
#### 1. Library Implementation
|
|
```rust
|
|
// src/lib/new_feature.rs
|
|
pub struct NewFeature {
|
|
// Feature implementation
|
|
}
|
|
|
|
impl NewFeature {
|
|
pub fn new() -> Self {
|
|
// Constructor
|
|
}
|
|
|
|
pub fn execute(&self) -> Result<(), Error> {
|
|
// Feature logic
|
|
}
|
|
}
|
|
```
|
|
|
|
#### 2. Integration
|
|
```rust
|
|
// src/lib/mod.rs
|
|
pub mod new_feature;
|
|
|
|
// In main library struct
|
|
pub struct AptOstree {
|
|
// ... existing fields ...
|
|
new_feature: NewFeature,
|
|
}
|
|
```
|
|
|
|
#### 3. Testing
|
|
```rust
|
|
// tests/new_feature_tests.rs
|
|
#[test]
|
|
fn test_new_feature() {
|
|
let feature = NewFeature::new();
|
|
assert!(feature.execute().is_ok());
|
|
}
|
|
```
|
|
|
|
## Testing and Debugging
|
|
|
|
### Unit Testing
|
|
```bash
|
|
# Run all tests
|
|
cargo test
|
|
|
|
# Run specific test module
|
|
cargo test commands::package
|
|
|
|
# Run tests with output
|
|
cargo test -- --nocapture
|
|
|
|
# Run tests with specific feature
|
|
cargo test --features development
|
|
```
|
|
|
|
### Integration Testing
|
|
```bash
|
|
# Run integration tests
|
|
cargo test --test integration_tests
|
|
|
|
# Run specific integration test
|
|
cargo test --test integration_tests test_package_installation
|
|
```
|
|
|
|
### Development Commands
|
|
```bash
|
|
# Run diagnostics
|
|
cargo run --features development -- internals diagnostics
|
|
|
|
# Validate system state
|
|
cargo run --features development -- internals validate-state
|
|
|
|
# Dump debug information
|
|
cargo run --features development -- internals debug-dump
|
|
```
|
|
|
|
### Debugging Tools
|
|
|
|
#### Logging
|
|
```rust
|
|
use tracing::{info, warn, error, debug};
|
|
|
|
// Set log level
|
|
std::env::set_var("RUST_LOG", "debug");
|
|
|
|
// Use in code
|
|
debug!("Debug information");
|
|
info!("Information message");
|
|
warn!("Warning message");
|
|
error!("Error message");
|
|
```
|
|
|
|
#### Profiling
|
|
```bash
|
|
# Install profiling tools
|
|
cargo install flamegraph
|
|
|
|
# Generate flamegraph
|
|
cargo flamegraph --bin apt-ostree -- install nginx
|
|
|
|
# Memory profiling
|
|
cargo install cargo-valgrind
|
|
cargo valgrind test
|
|
```
|
|
|
|
### Code Quality Tools
|
|
|
|
#### Clippy
|
|
```bash
|
|
# Run Clippy
|
|
cargo clippy
|
|
|
|
# Run with specific rules
|
|
cargo clippy -- -D warnings -A clippy::too_many_arguments
|
|
```
|
|
|
|
#### Formatting
|
|
```bash
|
|
# Check formatting
|
|
cargo fmt -- --check
|
|
|
|
# Format code
|
|
cargo fmt
|
|
```
|
|
|
|
#### Security Audit
|
|
```bash
|
|
# Check for vulnerabilities
|
|
cargo audit
|
|
|
|
# Update dependencies
|
|
cargo update
|
|
```
|
|
|
|
## Contributing Guidelines
|
|
|
|
### Code Style
|
|
- **Rust conventions**: Follow Rust style guide and idioms
|
|
- **Documentation**: Document all public APIs with doc comments
|
|
- **Error handling**: Use proper error types and Result handling
|
|
- **Testing**: Include tests for new functionality
|
|
- **Logging**: Use appropriate log levels for debugging
|
|
|
|
### Pull Request Process
|
|
1. **Fork repository**: Create your own fork
|
|
2. **Create feature branch**: `git checkout -b feature/new-feature`
|
|
3. **Implement changes**: Follow coding guidelines
|
|
4. **Add tests**: Include unit and integration tests
|
|
5. **Update documentation**: Update relevant documentation
|
|
6. **Submit PR**: Create pull request with clear description
|
|
|
|
### Commit Guidelines
|
|
```
|
|
type(scope): description
|
|
|
|
[optional body]
|
|
|
|
[optional footer]
|
|
```
|
|
|
|
**Types**: feat, fix, docs, style, refactor, test, chore
|
|
**Scope**: cli, daemon, lib, commands, etc.
|
|
|
|
### Review Process
|
|
- **Code review**: All changes require review
|
|
- **Testing**: Ensure all tests pass
|
|
- **Documentation**: Verify documentation is updated
|
|
- **Integration**: Test integration with existing features
|
|
|
|
### Issue Reporting
|
|
When reporting issues, include:
|
|
- **Environment**: OS, version, dependencies
|
|
- **Steps to reproduce**: Clear reproduction steps
|
|
- **Expected behavior**: What should happen
|
|
- **Actual behavior**: What actually happens
|
|
- **Logs**: Relevant error logs and output
|
|
|
|
## Advanced Development
|
|
|
|
### Custom Builds
|
|
```bash
|
|
# Build with specific features
|
|
cargo build --features development,dev-full
|
|
|
|
# Build for specific target
|
|
cargo build --target x86_64-unknown-linux-gnu
|
|
|
|
# Cross-compilation
|
|
cargo build --target aarch64-unknown-linux-gnu
|
|
```
|
|
|
|
### Performance Optimization
|
|
```rust
|
|
// Use appropriate data structures
|
|
use std::collections::HashMap; // O(1) lookup
|
|
use std::collections::BTreeMap; // Ordered, O(log n) lookup
|
|
|
|
// Avoid unnecessary allocations
|
|
let result = if condition { "value" } else { "default" };
|
|
// Instead of
|
|
let result = if condition { "value".to_string() } else { "default".to_string() };
|
|
|
|
// Use iterators efficiently
|
|
let sum: u64 = items.iter().map(|x| x.value).sum();
|
|
```
|
|
|
|
### Memory Management
|
|
```rust
|
|
// Use Arc for shared ownership
|
|
use std::sync::Arc;
|
|
|
|
let shared_data = Arc::new(SharedData::new());
|
|
let clone1 = Arc::clone(&shared_data);
|
|
let clone2 = Arc::clone(&shared_data);
|
|
|
|
// Use Box for trait objects
|
|
let commands: Vec<Box<dyn Command>> = vec![
|
|
Box::new(PackageCommand),
|
|
Box::new(SystemCommand),
|
|
];
|
|
```
|
|
|
|
### Async Programming
|
|
```rust
|
|
use tokio::runtime::Runtime;
|
|
|
|
#[tokio::main]
|
|
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
let result = async_operation().await?;
|
|
Ok(())
|
|
}
|
|
|
|
async fn async_operation() -> Result<String, Error> {
|
|
// Async implementation
|
|
Ok("result".to_string())
|
|
}
|
|
```
|
|
|
|
## Troubleshooting Development Issues
|
|
|
|
### Common Problems
|
|
|
|
#### Build Failures
|
|
```bash
|
|
# Clean and rebuild
|
|
cargo clean
|
|
cargo build
|
|
|
|
# Check Rust version
|
|
rustc --version
|
|
cargo --version
|
|
|
|
# Update Rust toolchain
|
|
rustup update
|
|
```
|
|
|
|
#### Dependency Issues
|
|
```bash
|
|
# Check dependency tree
|
|
cargo tree
|
|
|
|
# Update dependencies
|
|
cargo update
|
|
|
|
# Check for conflicts
|
|
cargo check
|
|
```
|
|
|
|
#### Test Failures
|
|
```bash
|
|
# Run specific failing test
|
|
cargo test test_name -- --nocapture
|
|
|
|
# Check test environment
|
|
cargo test --features development
|
|
|
|
# Debug test setup
|
|
RUST_LOG=debug cargo test
|
|
```
|
|
|
|
### Getting Help
|
|
- **Documentation**: Check inline documentation and rustdoc
|
|
- **Issues**: Search existing GitHub issues
|
|
- **Discussions**: Use GitHub Discussions for questions
|
|
- **Community**: Join project community channels
|
|
|
|
---
|
|
|
|
*This guide covers development aspects of apt-ostree. For user documentation, refer to the User Guide.*
|