apicurio-cli 0.1.2

A powerful CLI tool for managing schema artifacts from Apicurio Registry with lockfile-based dependency management
# Development Guide

This guide covers how to set up a development environment, run tests, and contribute to the Apicurio CLI.

## Prerequisites

- **Rust 1.70+** with Cargo
- **Docker & Docker Compose** (for local registry)
- **Git** for version control

## Environment Setup

### 1. Clone and Build

```bash
git clone https://github.com/YassineElbouchaibi/apicurio-cli.git
cd apicurio-cli
cargo build
```

### 2. Start Local Registry

For development and testing, start a local Apicurio Registry:

```bash
# Start registry with in-memory storage
docker-compose -f examples/docker-compose.yaml up -d

# Verify registry is running
curl http://localhost:8080/apis/registry/v2/system/info
```

### 3. Run the CLI

```bash
# Build and run
cargo run -- --help

# Or build once and use the binary
cargo build
./target/debug/apicurio --help
```

## Testing

### Unit Tests

```bash
# Run all tests
cargo test

# Run tests with output
cargo test -- --nocapture

# Run specific test module
cargo test config

# Run with debug logging
RUST_LOG=debug cargo test
```

### Integration Tests

The integration tests require a running Apicurio Registry on `localhost:8080`:

```bash
# Start local registry
docker-compose -f examples/docker-compose.yaml up -d

# Run integration tests
cargo test lockfile_integration

# Run all tests including integration
cargo test
```

### Manual Testing

```bash
# Initialize a test project
mkdir test-project
cd test-project
cargo run -- init

# Add a test dependency (requires running registry)
cargo run -- add local/com.example/test-schema@1.0.0

# Pull dependencies
cargo run -- pull

# Check status
cargo run -- status
```

## Code Organization

```
src/
├── main.rs              # CLI entry point and argument parsing
├── commands/            # Command implementations
│   ├── mod.rs          # Command routing and definitions
│   ├── init.rs         # Project initialization
│   ├── pull.rs         # Dependency fetching
│   ├── add.rs          # Interactive dependency addition
│   ├── remove.rs       # Dependency removal
│   ├── list.rs         # List dependencies and registries
│   ├── status.rs       # Check for outdated dependencies
│   ├── update.rs       # Update dependencies
│   ├── lock.rs         # Lock file generation
│   ├── publish.rs      # Artifact publishing
│   ├── registry.rs     # Registry management
│   ├── verify.rs       # Integrity verification
│   ├── doctor.rs       # Configuration validation
│   └── completions.rs  # Shell completion generation
├── config.rs           # Configuration loading and merging
├── lockfile.rs         # Lock file operations
├── registry.rs         # Registry client implementation
├── dependency.rs       # Dependency resolution logic
├── identifier.rs       # Identifier parsing utilities
└── constants.rs        # Shared constants
```

## Architecture Overview

### Configuration Management

The tool uses a hierarchical configuration system:

1. **Global registries** (`~/.config/apicurio/registries.yaml`)
2. **External registries** (specified by `externalRegistriesFile`)
3. **Repository config** (`apicurioconfig.yaml`)

Configurations are merged with later definitions overriding earlier ones.

### Dependency Resolution

1. **Parse version ranges** using semver crate
2. **Query registry** for available versions
3. **Select best match** based on semver constraints
4. **Generate lock file** with exact versions and checksums

### Authentication

Supports multiple auth types:
- **None**: Anonymous access
- **Basic**: Username + password from env var
- **Token**: Custom token header from env var  
- **Bearer**: OAuth/JWT bearer token from env var

## Contributing

### Code Style

- Follow Rust conventions and `cargo fmt`
- Add documentation for public APIs
- Include examples in doc comments where helpful
- Use `clippy` to catch common issues

```bash
# Format code
cargo fmt

# Run linter
cargo clippy

# Check documentation
cargo doc --open
```

### Adding New Commands

1. Create new module in `src/commands/`
2. Add module declaration in `src/commands/mod.rs`
3. Add command variant to `Commands` enum
4. Add command handler to `run()` function
5. Add tests for the new functionality

Example command structure:

```rust
// src/commands/mycommand.rs
use anyhow::Result;

/// Implementation of the my-command functionality
pub async fn run(arg: String) -> Result<()> {
    // Command implementation
    println!("Running my command with arg: {}", arg);
    Ok(())
}

#[cfg(test)]
mod tests {
    use super::*;

    #[tokio::test]
    async fn test_my_command() {
        let result = run("test".to_string()).await;
        assert!(result.is_ok());
    }
}
```

### Testing Guidelines

- Add unit tests for new functionality
- Include integration tests for registry operations
- Test error conditions and edge cases
- Use `tempfile` crate for temporary test files
- Mock network calls when appropriate

### Documentation

- Add rustdoc comments to public APIs
- Include examples in documentation
- Update README.md for user-facing changes
- Add usage examples for new commands

## Debugging

### Enable Debug Logging

```bash
# Debug level logging
RUST_LOG=debug cargo run -- pull

# Trace level for network requests
RUST_LOG=reqwest=trace cargo run -- pull

# Module-specific logging
RUST_LOG=apicurio_cli::registry=debug cargo run -- pull
```

### Common Development Issues

**1. Registry Connection Failures**
```bash
# Check if registry is running
curl http://localhost:8080/apis/registry/v2/system/info

# Restart registry
docker-compose -f examples/docker-compose.yaml restart
```

**2. Lock File Issues**
```bash
# Delete and regenerate lock file
rm apicuriolock.yaml
cargo run -- lock
```

**3. Authentication Problems**
```bash
# Check environment variables
echo $APICURIO_TOKEN

# Test registry access manually
curl -H "Authorization: Bearer $APICURIO_TOKEN" \
  http://localhost:8080/apis/registry/v2/groups
```

## Release Process

1. Update version in `Cargo.toml`
2. Update `CHANGELOG.md`
3. Run full test suite
4. Create git tag
5. Build release binary
6. Publish to cargo (if applicable)

```bash
# Update version and test
cargo test
cargo build --release

# Tag release
git tag v0.2.0
git push origin v0.2.0

# Build release artifacts
cargo build --release --target x86_64-unknown-linux-gnu
cargo build --release --target x86_64-apple-darwin
cargo build --release --target x86_64-pc-windows-gnu
```

## Performance Considerations

- Use async/await for network operations
- Implement connection pooling for multiple requests
- Cache registry metadata when possible
- Use streaming for large file downloads
- Implement retry logic with backoff

## Security Considerations

- Never log authentication tokens
- Store credentials only in environment variables
- Validate downloaded file checksums
- Use HTTPS for all registry communications
- Implement proper error handling to avoid information leaks