# Development Workflow Guide

This document outlines the recommended development workflows, coding practices, testing strategies, and debugging techniques for the provisioning project.

## Table of Contents

1. [Overview](#overview)
2. [Development Setup](#development-setup)
3. [Daily Development Workflow](#daily-development-workflow)
4. [Code Organization](#code-organization)
5. [Testing Strategies](#testing-strategies)
6. [Debugging Techniques](#debugging-techniques)
7. [Integration Workflows](#integration-workflows)
8. [Collaboration Guidelines](#collaboration-guidelines)
9. [Quality Assurance](#quality-assurance)
10. [Best Practices](#best-practices)

## Overview

The provisioning project employs a multi-language, multi-component architecture requiring specific development workflows to maintain consistency, quality, and efficiency.

**Key Technologies**:

- **Nushell**: Primary scripting and automation language
- **Rust**: High-performance system components
- **KCL**: Configuration language and schemas
- **TOML**: Configuration files
- **Jinja2**: Template engine

**Development Principles**:

- **Configuration-Driven**: Never hardcode, always configure
- **Hybrid Architecture**: Rust for performance, Nushell for flexibility
- **Test-First**: Comprehensive testing at all levels
- **Documentation-Driven**: Code and APIs are self-documenting

## Development Setup

### Initial Environment Setup

**1. Clone and Navigate**:

```bash
# Clone repository
git clone https://github.com/company/provisioning-system.git
cd provisioning-system

# Navigate to workspace
cd workspace/tools
```plaintext

**2. Initialize Workspace**:

```bash
# Initialize development workspace
nu workspace.nu init --user-name $USER --infra-name dev-env

# Check workspace health
nu workspace.nu health --detailed --fix-issues
```plaintext

**3. Configure Development Environment**:

```bash
# Create user configuration
cp workspace/config/local-overrides.toml.example workspace/config/$USER.toml

# Edit configuration for development
$EDITOR workspace/config/$USER.toml
```plaintext

**4. Set Up Build System**:

```bash
# Navigate to build tools
cd src/tools

# Check build prerequisites
make info

# Perform initial build
make dev-build
```plaintext

### Tool Installation

**Required Tools**:

```bash
# Install Nushell
cargo install nu

# Install Nickel
cargo install nickel

# Install additional tools
cargo install cross          # Cross-compilation
cargo install cargo-audit    # Security auditing
cargo install cargo-watch    # File watching
```plaintext

**Optional Development Tools**:

```bash
# Install development enhancers
cargo install nu_plugin_tera    # Template plugin
cargo install sops              # Secrets management
brew install k9s                # Kubernetes management
```plaintext

### IDE Configuration

**VS Code Setup** (`.vscode/settings.json`):

```json
{
  "files.associations": {
    "*.nu": "shellscript",
    "*.ncl": "nickel",
    "*.toml": "toml"
  },
  "nushell.shellPath": "/usr/local/bin/nu",
  "rust-analyzer.cargo.features": "all",
  "editor.formatOnSave": true,
  "editor.rulers": [100],
  "files.trimTrailingWhitespace": true
}
```plaintext

**Recommended Extensions**:

- Nushell Language Support
- Rust Analyzer
- Nickel Language Support
- TOML Language Support
- Better TOML

## Daily Development Workflow

### Morning Routine

**1. Sync and Update**:

```bash
# Sync with upstream
git pull origin main

# Update workspace
cd workspace/tools
nu workspace.nu health --fix-issues

# Check for updates
nu workspace.nu status --detailed
```plaintext

**2. Review Current State**:

```bash
# Check current infrastructure
provisioning show servers
provisioning show settings

# Review workspace status
nu workspace.nu status
```plaintext

### Development Cycle

**1. Feature Development**:

```bash
# Create feature branch
git checkout -b feature/new-provider-support

# Start development environment
cd workspace/tools
nu workspace.nu init --workspace-type development

# Begin development
$EDITOR workspace/extensions/providers/new-provider/nulib/provider.nu
```plaintext

**2. Incremental Testing**:

```bash
# Test syntax during development
nu --check workspace/extensions/providers/new-provider/nulib/provider.nu

# Run unit tests
nu workspace/extensions/providers/new-provider/tests/unit/basic-test.nu

# Integration testing
nu workspace.nu tools test-extension providers/new-provider
```plaintext

**3. Build and Validate**:

```bash
# Quick development build
cd src/tools
make dev-build

# Validate changes
make validate-all

# Test distribution
make test-dist
```plaintext

### Testing During Development

**Unit Testing**:

```nushell
# Add test examples to functions
def create-server [name: string] -> record {
    # @test: "test-server" -> {name: "test-server", status: "created"}
    # Implementation here
}
```plaintext

**Integration Testing**:

```bash
# Test with real infrastructure
nu workspace/extensions/providers/new-provider/nulib/provider.nu \
    create-server test-server --dry-run

# Test with workspace isolation
PROVISIONING_WORKSPACE_USER=$USER provisioning server create test-server --check
```plaintext

### End-of-Day Routine

**1. Commit Progress**:

```bash
# Stage changes
git add .

# Commit with descriptive message
git commit -m "feat(provider): add new cloud provider support

- Implement basic server creation
- Add configuration schema
- Include unit tests
- Update documentation"

# Push to feature branch
git push origin feature/new-provider-support
```plaintext

**2. Workspace Maintenance**:

```bash
# Clean up development data
nu workspace.nu cleanup --type cache --age 1d

# Backup current state
nu workspace.nu backup --auto-name --components config,extensions

# Check workspace health
nu workspace.nu health
```plaintext

## Code Organization

### Nushell Code Structure

**File Organization**:

```plaintext
Extension Structure:
├── nulib/
│   ├── main.nu              # Main entry point
│   ├── core/                # Core functionality
│   │   ├── api.nu           # API interactions
│   │   ├── config.nu        # Configuration handling
│   │   └── utils.nu         # Utility functions
│   ├── commands/            # User commands
│   │   ├── create.nu        # Create operations
│   │   ├── delete.nu        # Delete operations
│   │   └── list.nu          # List operations
│   └── tests/               # Test files
│       ├── unit/            # Unit tests
│       └── integration/     # Integration tests
└── templates/               # Template files
    ├── config.j2            # Configuration templates
    └── manifest.j2          # Manifest templates
```plaintext

**Function Naming Conventions**:

```nushell
# Use kebab-case for commands
def create-server [name: string] -> record { ... }
def validate-config [config: record] -> bool { ... }

# Use snake_case for internal functions
def get_api_client [] -> record { ... }
def parse_config_file [path: string] -> record { ... }

# Use descriptive prefixes
def check-server-status [server: string] -> string { ... }
def get-server-info [server: string] -> record { ... }
def list-available-zones [] -> list<string> { ... }
```plaintext

**Error Handling Pattern**:

```nushell
def create-server [
    name: string
    --dry-run: bool = false
] -> record {
    # 1. Validate inputs
    if ($name | str length) == 0 {
        error make {
            msg: "Server name cannot be empty"
            label: {
                text: "empty name provided"
                span: (metadata $name).span
            }
        }
    }

    # 2. Check prerequisites
    let config = try {
        get-provider-config
    } catch {
        error make {msg: "Failed to load provider configuration"}
    }

    # 3. Perform operation
    if $dry_run {
        return {action: "create", server: $name, status: "dry-run"}
    }

    # 4. Return result
    {server: $name, status: "created", id: (generate-id)}
}
```plaintext

### Rust Code Structure

**Project Organization**:

```plaintext
src/
├── lib.rs                   # Library root
├── main.rs                  # Binary entry point
├── config/                  # Configuration handling
│   ├── mod.rs
│   ├── loader.rs            # Config loading
│   └── validation.rs        # Config validation
├── api/                     # HTTP API
│   ├── mod.rs
│   ├── handlers.rs          # Request handlers
│   └── middleware.rs        # Middleware components
└── orchestrator/            # Orchestration logic
    ├── mod.rs
    ├── workflow.rs          # Workflow management
    └── task_queue.rs        # Task queue management
```plaintext

**Error Handling**:

```rust
use anyhow::{Context, Result};
use thiserror::Error;

#[derive(Error, Debug)]
pub enum ProvisioningError {
    #[error("Configuration error: {message}")]
    Config { message: String },

    #[error("Network error: {source}")]
    Network {
        #[from]
        source: reqwest::Error,
    },

    #[error("Validation failed: {field}")]
    Validation { field: String },
}

pub fn create_server(name: &str) -> Result<ServerInfo> {
    let config = load_config()
        .context("Failed to load configuration")?;

    validate_server_name(name)
        .context("Server name validation failed")?;

    let server = provision_server(name, &config)
        .context("Failed to provision server")?;

    Ok(server)
}
```plaintext

### Nickel Schema Organization

**Schema Structure**:

```nickel
# Base schema definitions
let ServerConfig = {
    name | string,
    plan | string,
    zone | string,
    tags | { } | default = {},
} in
ServerConfig

# Provider-specific extensions
let UpCloudServerConfig = {
    template | string | default = "Ubuntu Server 22.04 LTS (Jammy Jellyfish)",
    storage | number | default = 25,
} in
UpCloudServerConfig

# Composition schemas
let InfrastructureConfig = {
    servers | array,
    networks | array | default = [],
    load_balancers | array | default = [],
} in
InfrastructureConfig
```plaintext

## Testing Strategies

### Test-Driven Development

**TDD Workflow**:

1. **Write Test First**: Define expected behavior
2. **Run Test (Fail)**: Confirm test fails as expected
3. **Write Code**: Implement minimal code to pass
4. **Run Test (Pass)**: Confirm test now passes
5. **Refactor**: Improve code while keeping tests green

### Nushell Testing

**Unit Test Pattern**:

```nushell
# Function with embedded test
def validate-server-name [name: string] -> bool {
    # @test: "valid-name" -> true
    # @test: "" -> false
    # @test: "name-with-spaces" -> false

    if ($name | str length) == 0 {
        return false
    }

    if ($name | str contains " ") {
        return false
    }

    true
}

# Separate test file
# tests/unit/server-validation-test.nu
def test_validate_server_name [] {
    # Valid cases
    assert (validate-server-name "valid-name")
    assert (validate-server-name "server123")

    # Invalid cases
    assert not (validate-server-name "")
    assert not (validate-server-name "name with spaces")
    assert not (validate-server-name "name@with!special")

    print "✅ validate-server-name tests passed"
}
```plaintext

**Integration Test Pattern**:

```nushell
# tests/integration/server-lifecycle-test.nu
def test_complete_server_lifecycle [] {
    # Setup
    let test_server = "test-server-" + (date now | format date "%Y%m%d%H%M%S")

    try {
        # Test creation
        let create_result = (create-server $test_server --dry-run)
        assert ($create_result.status == "dry-run")

        # Test validation
        let validate_result = (validate-server-config $test_server)
        assert $validate_result

        print $"✅ Server lifecycle test passed for ($test_server)"
    } catch { |e|
        print $"❌ Server lifecycle test failed: ($e.msg)"
        exit 1
    }
}
```plaintext

### Rust Testing

**Unit Testing**:

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

    #[test]
    fn test_validate_server_name() {
        assert!(validate_server_name("valid-name"));
        assert!(validate_server_name("server123"));

        assert!(!validate_server_name(""));
        assert!(!validate_server_name("name with spaces"));
        assert!(!validate_server_name("name@special"));
    }

    #[tokio::test]
    async fn test_server_creation() {
        let config = test_config();
        let result = create_server("test-server", &config).await;

        assert!(result.is_ok());
        let server = result.unwrap();
        assert_eq!(server.name, "test-server");
        assert_eq!(server.status, "created");
    }
}
```plaintext

**Integration Testing**:

```rust
#[cfg(test)]
mod integration_tests {
    use super::*;
    use testcontainers::*;

    #[tokio::test]
    async fn test_full_workflow() {
        // Setup test environment
        let docker = clients::Cli::default();
        let postgres = docker.run(images::postgres::Postgres::default());

        let config = TestConfig {
            database_url: format!("postgresql://localhost:{}/test",
                                 postgres.get_host_port_ipv4(5432))
        };

        // Test complete workflow
        let workflow = create_workflow(&config).await.unwrap();
        let result = execute_workflow(workflow).await.unwrap();

        assert_eq!(result.status, WorkflowStatus::Completed);
    }
}
```plaintext

### Nickel Testing

**Schema Validation Testing**:

```bash
# Test Nickel schemas
nickel check schemas/

# Validate specific schemas
nickel typecheck schemas/server.ncl

# Test with examples
nickel eval schemas/server.ncl
```plaintext

### Test Automation

**Continuous Testing**:

```bash
# Watch for changes and run tests
cargo watch -x test -x check

# Watch Nushell files
find . -name "*.nu" | entr -r nu tests/run-all-tests.nu

# Automated testing in workspace
nu workspace.nu tools test-all --watch
```plaintext

## Debugging Techniques

### Debug Configuration

**Enable Debug Mode**:

```bash
# Environment variables
export PROVISIONING_DEBUG=true
export PROVISIONING_LOG_LEVEL=debug
export RUST_LOG=debug
export RUST_BACKTRACE=1

# Workspace debug
export PROVISIONING_WORKSPACE_USER=$USER
```plaintext

### Nushell Debugging

**Debug Techniques**:

```nushell
# Debug prints
def debug-server-creation [name: string] {
    print $"🐛 Creating server: ($name)"

    let config = get-provider-config
    print $"🐛 Config loaded: ($config | to json)"

    let result = try {
        create-server-api $name $config
    } catch { |e|
        print $"🐛 API call failed: ($e.msg)"
        $e
    }

    print $"🐛 Result: ($result | to json)"
    $result
}

# Conditional debugging
def create-server [name: string] {
    if $env.PROVISIONING_DEBUG? == "true" {
        print $"Debug: Creating server ($name)"
    }

    # Implementation
}

# Interactive debugging
def debug-interactive [] {
    print "🐛 Entering debug mode..."
    print "Available commands: $env.PATH"
    print "Current config: " (get-config | to json)

    # Drop into interactive shell
    nu --interactive
}
```plaintext

**Error Investigation**:

```nushell
# Comprehensive error handling
def safe-server-creation [name: string] {
    try {
        create-server $name
    } catch { |e|
        # Log error details
        {
            timestamp: (date now | format date "%Y-%m-%d %H:%M:%S"),
            operation: "create-server",
            input: $name,
            error: $e.msg,
            debug: $e.debug?,
            env: {
                user: $env.USER,
                workspace: $env.PROVISIONING_WORKSPACE_USER?,
                debug: $env.PROVISIONING_DEBUG?
            }
        } | save --append logs/error-debug.json

        # Re-throw with context
        error make {
            msg: $"Server creation failed: ($e.msg)",
            label: {text: "failed here", span: $e.span?}
        }
    }
}
```plaintext

### Rust Debugging

**Debug Logging**:

```rust
use tracing::{debug, info, warn, error, instrument};

#[instrument]
pub async fn create_server(name: &str) -> Result<ServerInfo> {
    debug!("Starting server creation for: {}", name);

    let config = load_config()
        .map_err(|e| {
            error!("Failed to load config: {:?}", e);
            e
        })?;

    info!("Configuration loaded successfully");
    debug!("Config details: {:?}", config);

    let server = provision_server(name, &config).await
        .map_err(|e| {
            error!("Provisioning failed for {}: {:?}", name, e);
            e
        })?;

    info!("Server {} created successfully", name);
    Ok(server)
}
```plaintext

**Interactive Debugging**:

```rust
// Use debugger breakpoints
#[cfg(debug_assertions)]
{
    println!("Debug: server creation starting");
    dbg!(&config);
    // Add breakpoint here in IDE
}
```plaintext

### Log Analysis

**Log Monitoring**:

```bash
# Follow all logs
tail -f workspace/runtime/logs/$USER/*.log

# Filter for errors
grep -i error workspace/runtime/logs/$USER/*.log

# Monitor specific component
tail -f workspace/runtime/logs/$USER/orchestrator.log | grep -i workflow

# Structured log analysis
jq '.level == "ERROR"' workspace/runtime/logs/$USER/structured.jsonl
```plaintext

**Debug Log Levels**:

```bash
# Different verbosity levels
PROVISIONING_LOG_LEVEL=trace provisioning server create test
PROVISIONING_LOG_LEVEL=debug provisioning server create test
PROVISIONING_LOG_LEVEL=info provisioning server create test
```plaintext

## Integration Workflows

### Existing System Integration

**Working with Legacy Components**:

```bash
# Test integration with existing system
provisioning --version                    # Legacy system
src/core/nulib/provisioning --version    # New system

# Test workspace integration
PROVISIONING_WORKSPACE_USER=$USER provisioning server list

# Validate configuration compatibility
provisioning validate config
nu workspace.nu config validate
```plaintext

### API Integration Testing

**REST API Testing**:

```bash
# Test orchestrator API
curl -X GET http://localhost:9090/health
curl -X GET http://localhost:9090/tasks

# Test workflow creation
curl -X POST http://localhost:9090/workflows/servers/create \
  -H "Content-Type: application/json" \
  -d '{"name": "test-server", "plan": "2xCPU-4 GB"}'

# Monitor workflow
curl -X GET http://localhost:9090/workflows/batch/status/workflow-id
```plaintext

### Database Integration

**SurrealDB Integration**:

```nushell
# Test database connectivity
use core/nulib/lib_provisioning/database/surreal.nu
let db = (connect-database)
(test-connection $db)

# Workflow state testing
let workflow_id = (create-workflow-record "test-workflow")
let status = (get-workflow-status $workflow_id)
assert ($status.status == "pending")
```plaintext

### External Tool Integration

**Container Integration**:

```bash
# Test with Docker
docker run --rm -v $(pwd):/work provisioning:dev provisioning --version

# Test with Kubernetes
kubectl apply -f manifests/test-pod.yaml
kubectl logs test-pod

# Validate in different environments
make test-dist PLATFORM=docker
make test-dist PLATFORM=kubernetes
```plaintext

## Collaboration Guidelines

### Branch Strategy

**Branch Naming**:

- `feature/description` - New features
- `fix/description` - Bug fixes
- `docs/description` - Documentation updates
- `refactor/description` - Code refactoring
- `test/description` - Test improvements

**Workflow**:

```bash
# Start new feature
git checkout main
git pull origin main
git checkout -b feature/new-provider-support

# Regular commits
git add .
git commit -m "feat(provider): implement server creation API"

# Push and create PR
git push origin feature/new-provider-support
gh pr create --title "Add new provider support" --body "..."
```plaintext

### Code Review Process

**Review Checklist**:

- [ ] Code follows project conventions
- [ ] Tests are included and passing
- [ ] Documentation is updated
- [ ] No hardcoded values
- [ ] Error handling is comprehensive
- [ ] Performance considerations addressed

**Review Commands**:

```bash
# Test PR locally
gh pr checkout 123
cd src/tools && make ci-test

# Run specific tests
nu workspace/extensions/providers/new-provider/tests/run-all.nu

# Check code quality
cargo clippy -- -D warnings
nu --check $(find . -name "*.nu")
```plaintext

### Documentation Requirements

**Code Documentation**:

```nushell
# Function documentation
def create-server [
    name: string        # Server name (must be unique)
    plan: string        # Server plan (for example, "2xCPU-4 GB")
    --dry-run: bool     # Show what would be created without doing it
] -> record {           # Returns server creation result
    # Creates a new server with the specified configuration
    #
    # Examples:
    #   create-server "web-01" "2xCPU-4 GB"
    #   create-server "test" "1xCPU-2 GB" --dry-run

    # Implementation
}
```plaintext

### Communication

**Progress Updates**:

- Daily standup participation
- Weekly architecture reviews
- PR descriptions with context
- Issue tracking with details

**Knowledge Sharing**:

- Technical blog posts
- Architecture decision records
- Code review discussions
- Team documentation updates

## Quality Assurance

### Code Quality Checks

**Automated Quality Gates**:

```bash
# Pre-commit hooks
pre-commit install

# Manual quality check
cd src/tools
make validate-all

# Security audit
cargo audit
```plaintext

**Quality Metrics**:

- Code coverage > 80%
- No critical security vulnerabilities
- All tests passing
- Documentation coverage complete
- Performance benchmarks met

### Performance Monitoring

**Performance Testing**:

```bash
# Benchmark builds
make benchmark

# Performance profiling
cargo flamegraph --bin provisioning-orchestrator

# Load testing
ab -n 1000 -c 10 http://localhost:9090/health
```plaintext

**Resource Monitoring**:

```bash
# Monitor during development
nu workspace/tools/runtime-manager.nu monitor --duration 5m

# Check resource usage
du -sh workspace/runtime/
df -h
```plaintext

## Best Practices

### Configuration Management

**Never Hardcode**:

```nushell
# Bad
def get-api-url [] { "https://api.upcloud.com" }

# Good
def get-api-url [] {
    get-config-value "providers.upcloud.api_url" "https://api.upcloud.com"
}
```plaintext

### Error Handling

**Comprehensive Error Context**:

```nushell
def create-server [name: string] {
    try {
        validate-server-name $name
    } catch { |e|
        error make {
            msg: $"Invalid server name '($name)': ($e.msg)",
            label: {text: "server name validation failed", span: $e.span?}
        }
    }

    try {
        provision-server $name
    } catch { |e|
        error make {
            msg: $"Server provisioning failed for '($name)': ($e.msg)",
            help: "Check provider credentials and quota limits"
        }
    }
}
```plaintext

### Resource Management

**Clean Up Resources**:

```nushell
def with-temporary-server [name: string, action: closure] {
    let server = (create-server $name)

    try {
        do $action $server
    } catch { |e|
        # Clean up on error
        delete-server $name
        $e
    }

    # Clean up on success
    delete-server $name
}
```plaintext

### Testing Best Practices

**Test Isolation**:

```nushell
def test-with-isolation [test_name: string, test_action: closure] {
    let test_workspace = $"test-($test_name)-(date now | format date '%Y%m%d%H%M%S')"

    try {
        # Set up isolated environment
        $env.PROVISIONING_WORKSPACE_USER = $test_workspace
        nu workspace.nu init --user-name $test_workspace

        # Run test
        do $test_action

        print $"✅ Test ($test_name) passed"
    } catch { |e|
        print $"❌ Test ($test_name) failed: ($e.msg)"
        exit 1
    } finally {
        # Clean up test environment
        nu workspace.nu cleanup --user-name $test_workspace --type all --force
    }
}
```plaintext

This development workflow provides a comprehensive framework for efficient, quality-focused development while maintaining the project's architectural principles and ensuring smooth collaboration across the team.
