#!/bin/bash # TLI CI/CD Integration Script # This script provides automated testing, benchmarking, and quality checks # for the TLI (Terminal Line Interface) component. set -euo pipefail # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # Configuration SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_DIR="$SCRIPT_DIR" CARGO_FLAGS="${CARGO_FLAGS:-}" RUST_LOG="${RUST_LOG:-info}" BENCHMARK_OUTPUT_DIR="${BENCHMARK_OUTPUT_DIR:-$PROJECT_DIR/benchmark-results}" # Functions log_info() { echo -e "${BLUE}[INFO]${NC} $1" } log_success() { echo -e "${GREEN}[SUCCESS]${NC} $1" } log_warning() { echo -e "${YELLOW}[WARNING]${NC} $1" } log_error() { echo -e "${RED}[ERROR]${NC} $1" } check_dependencies() { log_info "Checking dependencies..." # Check Rust toolchain if ! command -v cargo &> /dev/null; then log_error "Cargo not found. Please install Rust toolchain." exit 1 fi # Check required tools local required_tools=("git" "curl") for tool in "${required_tools[@]}"; do if ! command -v "$tool" &> /dev/null; then log_warning "$tool not found, some features may not work" fi done log_success "Dependencies check completed" } setup_environment() { log_info "Setting up environment..." # Set environment variables export RUST_LOG="$RUST_LOG" export RUST_BACKTRACE=1 # Create output directories mkdir -p "$BENCHMARK_OUTPUT_DIR" # Create test database directory mkdir -p "$PROJECT_DIR/test-data" log_success "Environment setup completed" } run_code_formatting() { log_info "Running code formatting checks..." # Check formatting if ! cargo fmt --all -- --check; then log_error "Code formatting issues found. Run 'cargo fmt' to fix." return 1 fi log_success "Code formatting check passed" } run_clippy() { log_info "Running Clippy lints..." # Run clippy with strict settings if ! cargo clippy --all-targets --all-features $CARGO_FLAGS -- -D warnings; then log_error "Clippy found issues" return 1 fi log_success "Clippy check passed" } run_unit_tests() { log_info "Running unit tests..." # Run tests with coverage if possible if command -v cargo-tarpaulin &> /dev/null; then log_info "Running tests with coverage..." cargo tarpaulin --out Html --output-dir "$PROJECT_DIR/coverage" $CARGO_FLAGS else log_info "Running tests without coverage (install cargo-tarpaulin for coverage)" cargo test --lib $CARGO_FLAGS fi log_success "Unit tests completed" } run_integration_tests() { log_info "Running integration tests..." # Set up test environment variables export TLI_TEST_MODE=1 export TLI_DATABASE_URL="sqlite:$PROJECT_DIR/test-data/test.db" # Run integration tests if ! cargo test --test integration $CARGO_FLAGS; then log_error "Integration tests failed" return 1 fi # Clean up test database rm -f "$PROJECT_DIR/test-data/test.db" log_success "Integration tests completed" } run_property_tests() { log_info "Running property-based tests..." # Run property tests with proptest if ! cargo test --features proptest $CARGO_FLAGS; then log_error "Property-based tests failed" return 1 fi log_success "Property-based tests completed" } run_benchmarks() { log_info "Running performance benchmarks..." # Create benchmark output directory mkdir -p "$BENCHMARK_OUTPUT_DIR" # Run benchmarks and save results local benchmark_date=$(date +"%Y-%m-%d_%H-%M-%S") local benchmark_file="$BENCHMARK_OUTPUT_DIR/benchmark_$benchmark_date.txt" log_info "Running configuration benchmarks..." cargo bench --bench configuration_benchmarks -- --output-format json > "$BENCHMARK_OUTPUT_DIR/config_$benchmark_date.json" 2>&1 || true log_info "Running client performance benchmarks..." cargo bench --bench client_performance -- --output-format json > "$BENCHMARK_OUTPUT_DIR/client_$benchmark_date.json" 2>&1 || true log_info "Running serialization benchmarks..." cargo bench --bench serialization_benchmarks -- --output-format json > "$BENCHMARK_OUTPUT_DIR/serialization_$benchmark_date.json" 2>&1 || true # Generate summary report echo "Benchmark Results - $benchmark_date" > "$benchmark_file" echo "=================================" >> "$benchmark_file" echo "" >> "$benchmark_file" if [ -f "$BENCHMARK_OUTPUT_DIR/config_$benchmark_date.json" ]; then echo "Configuration Benchmarks:" >> "$benchmark_file" echo "------------------------" >> "$benchmark_file" # Extract key metrics (simplified - in real use, parse JSON properly) grep -E "(timestamp_conversions|validation_operations)" "$BENCHMARK_OUTPUT_DIR/config_$benchmark_date.json" | head -10 >> "$benchmark_file" 2>/dev/null || echo "No config benchmark data" >> "$benchmark_file" echo "" >> "$benchmark_file" fi log_success "Benchmarks completed - Results saved to $BENCHMARK_OUTPUT_DIR" } run_doc_tests() { log_info "Running documentation tests..." # Test documentation examples if ! cargo test --doc $CARGO_FLAGS; then log_error "Documentation tests failed" return 1 fi log_success "Documentation tests completed" } run_security_audit() { log_info "Running security audit..." # Check for security vulnerabilities if command -v cargo-audit &> /dev/null; then if ! cargo audit; then log_warning "Security audit found issues" return 1 fi else log_warning "cargo-audit not installed, skipping security audit" log_info "Install with: cargo install cargo-audit" fi log_success "Security audit completed" } run_dependency_check() { log_info "Checking dependencies..." # Check for outdated dependencies if command -v cargo-outdated &> /dev/null; then log_info "Checking for outdated dependencies..." cargo outdated --exit-code 1 || log_warning "Some dependencies are outdated" else log_info "cargo-outdated not installed, install with: cargo install cargo-outdated" fi # Check dependency tree cargo tree --depth 3 > "$PROJECT_DIR/dependency-tree.txt" log_success "Dependency check completed" } build_release() { log_info "Building release version..." if ! cargo build --release $CARGO_FLAGS; then log_error "Release build failed" return 1 fi log_success "Release build completed" } run_examples() { log_info "Testing example applications..." # Test examples compile local examples=("basic_dashboard" "config_management" "real_time_streaming") for example in "${examples[@]}"; do log_info "Checking example: $example" if ! cargo check --example "$example" $CARGO_FLAGS; then log_error "Example $example failed to compile" return 1 fi done log_success "All examples compile successfully" } generate_reports() { log_info "Generating reports..." local report_dir="$PROJECT_DIR/reports" mkdir -p "$report_dir" # Generate test report echo "TLI Test Report - $(date)" > "$report_dir/test_report.txt" echo "==============================" >> "$report_dir/test_report.txt" echo "" >> "$report_dir/test_report.txt" # Add git information if command -v git &> /dev/null && [ -d .git ]; then echo "Git Information:" >> "$report_dir/test_report.txt" echo "- Commit: $(git rev-parse HEAD)" >> "$report_dir/test_report.txt" echo "- Branch: $(git branch --show-current)" >> "$report_dir/test_report.txt" echo "- Author: $(git log -1 --pretty=format:'%an <%ae>')" >> "$report_dir/test_report.txt" echo "- Date: $(git log -1 --pretty=format:'%cd')" >> "$report_dir/test_report.txt" echo "" >> "$report_dir/test_report.txt" fi # Add environment information echo "Environment Information:" >> "$report_dir/test_report.txt" echo "- Rust Version: $(rustc --version)" >> "$report_dir/test_report.txt" echo "- Cargo Version: $(cargo --version)" >> "$report_dir/test_report.txt" echo "- OS: $(uname -s)" >> "$report_dir/test_report.txt" echo "- Architecture: $(uname -m)" >> "$report_dir/test_report.txt" echo "" >> "$report_dir/test_report.txt" log_success "Reports generated in $report_dir" } cleanup() { log_info "Cleaning up temporary files..." # Remove test artifacts rm -rf "$PROJECT_DIR/test-data" # Clean cargo cache if requested if [ "${CLEAN_CACHE:-false}" = "true" ]; then cargo clean fi log_success "Cleanup completed" } # Main execution functions run_quick_check() { log_info "Running quick checks..." setup_environment run_code_formatting run_clippy run_unit_tests log_success "Quick checks completed successfully" } run_full_test_suite() { log_info "Running full test suite..." setup_environment run_code_formatting run_clippy run_unit_tests run_integration_tests run_property_tests run_doc_tests run_examples log_success "Full test suite completed successfully" } run_performance_suite() { log_info "Running performance test suite..." setup_environment build_release run_benchmarks generate_reports log_success "Performance test suite completed successfully" } run_security_suite() { log_info "Running security test suite..." setup_environment run_security_audit run_dependency_check log_success "Security test suite completed successfully" } run_ci_pipeline() { log_info "Running full CI pipeline..." check_dependencies setup_environment run_code_formatting run_clippy run_unit_tests run_integration_tests run_property_tests run_doc_tests run_examples run_security_audit run_dependency_check build_release generate_reports log_success "CI pipeline completed successfully" } run_cd_pipeline() { log_info "Running CD pipeline..." run_ci_pipeline run_benchmarks log_success "CD pipeline completed successfully" } # Help function show_help() { cat << EOF TLI CI/CD Script Usage: $0 [COMMAND] Commands: quick - Run quick checks (format, clippy, unit tests) test - Run full test suite perf - Run performance benchmarks security - Run security audits ci - Run full CI pipeline cd - Run full CD pipeline (CI + benchmarks) format - Run code formatting check clippy - Run clippy lints unit - Run unit tests only integration - Run integration tests only benchmarks - Run performance benchmarks only examples - Test example applications docs - Run documentation tests audit - Run security audit deps - Check dependencies build - Build release version clean - Clean up temporary files help - Show this help message Environment Variables: CARGO_FLAGS - Additional flags for cargo commands RUST_LOG - Log level (default: info) BENCHMARK_OUTPUT_DIR - Directory for benchmark results CLEAN_CACHE - Set to 'true' to clean cargo cache on cleanup Examples: $0 quick # Quick development checks $0 ci # Full CI pipeline $0 perf # Performance testing RUST_LOG=debug $0 test # Full tests with debug logging EOF } # Main script logic main() { local command="${1:-help}" case "$command" in "quick") run_quick_check ;; "test") run_full_test_suite ;; "perf") run_performance_suite ;; "security") run_security_suite ;; "ci") run_ci_pipeline ;; "cd") run_cd_pipeline ;; "format") setup_environment run_code_formatting ;; "clippy") setup_environment run_clippy ;; "unit") setup_environment run_unit_tests ;; "integration") setup_environment run_integration_tests ;; "benchmarks") setup_environment run_benchmarks ;; "examples") setup_environment run_examples ;; "docs") setup_environment run_doc_tests ;; "audit") setup_environment run_security_audit ;; "deps") setup_environment run_dependency_check ;; "build") setup_environment build_release ;; "clean") cleanup ;; "help"|"--help"|"-h") show_help ;; *) log_error "Unknown command: $command" show_help exit 1 ;; esac } # Trap cleanup on exit trap cleanup EXIT # Run main function with all arguments main "$@"