Fix YAML linting issues and update system requirements to Debian 13+
- 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
This commit is contained in:
parent
ec0da91864
commit
3dec23f8f7
85 changed files with 12569 additions and 1088 deletions
623
docs/developer-guide.md
Normal file
623
docs/developer-guide.md
Normal file
|
|
@ -0,0 +1,623 @@
|
|||
# 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.*
|
||||
Loading…
Add table
Add a link
Reference in a new issue