Files
metaverseDubai/scripts/STANDARDS.md
2026-07-07 03:43:19 -07:00

9.7 KiB

Script Standards - Dubai Metaverse

Overview

This document defines standards and best practices for all scripts in the Dubai Metaverse project. All scripts should follow these guidelines for consistency, maintainability, and reliability.

Script Template

Bash Script Template

#!/bin/bash
#
# Script Name: script_name.sh
# Description: Brief description of what the script does
# Usage: ./script_name.sh [options] [arguments]
# Author: [Author Name]
# Date: 2024-11-21
# Version: 1.0
#
# Exit codes:
#   0: Success
#   1: General error
#   2: Invalid arguments
#   3: Missing dependencies
#   4: Permission denied
#   5: File/directory not found

set -euo pipefail  # Exit on error, undefined vars, pipe failures

# Configuration
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
LOG_FILE="${LOG_FILE:-$PROJECT_ROOT/logs/script_name.log}"

# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color

# Logging function
log() {
    local level="${1:-INFO}"
    shift
    local message="$*"
    local timestamp=$(date +'%Y-%m-%d %H:%M:%S')
    echo "[$timestamp] [$level] $message" | tee -a "$LOG_FILE"
}

# Error handling
error_exit() {
    log "ERROR" "$*"
    exit 1
}

# Warning function
warning() {
    log "WARNING" "$*"
}

# Success function
success() {
    log "SUCCESS" "$*"
}

# Validate prerequisites
validate_prerequisites() {
    local missing_deps=()
    
    # Check required commands
    local required_commands=("git" "python3")
    for cmd in "${required_commands[@]}"; do
        if ! command -v "$cmd" &> /dev/null; then
            missing_deps+=("$cmd")
        fi
    done
    
    if [ ${#missing_deps[@]} -gt 0 ]; then
        error_exit "Missing required commands: ${missing_deps[*]}"
    fi
    
    # Check required files
    local required_files=("$PROJECT_ROOT/README.md")
    for file in "${required_files[@]}"; do
        if [ ! -f "$file" ]; then
            error_exit "Required file not found: $file"
        fi
    done
    
    # Check environment
    if [ -z "${REQUIRED_ENV_VAR:-}" ]; then
        warning "Environment variable REQUIRED_ENV_VAR not set"
    fi
}

# Print usage information
usage() {
    cat << EOF
Usage: $0 [OPTIONS] [ARGUMENTS]

Description:
    Brief description of what the script does

Options:
    -h, --help          Show this help message
    -v, --verbose       Enable verbose output
    -q, --quiet         Suppress non-error output
    -d, --dry-run       Perform a dry run without making changes

Arguments:
    arg1                Description of first argument
    arg2                Description of second argument

Examples:
    $0 --verbose arg1 arg2
    $0 --dry-run

Exit codes:
    0   Success
    1   General error
    2   Invalid arguments
    3   Missing dependencies

EOF
}

# Parse command line arguments
parse_args() {
    while [[ $# -gt 0 ]]; do
        case $1 in
            -h|--help)
                usage
                exit 0
                ;;
            -v|--verbose)
                VERBOSE=true
                shift
                ;;
            -q|--quiet)
                QUIET=true
                shift
                ;;
            -d|--dry-run)
                DRY_RUN=true
                shift
                ;;
            *)
                error_exit "Unknown option: $1. Use --help for usage."
                ;;
        esac
    done
}

# Main function
main() {
    log "INFO" "Starting script_name.sh"
    
    # Parse arguments
    parse_args "$@"
    
    # Validate prerequisites
    validate_prerequisites
    
    # Create log directory if it doesn't exist
    mkdir -p "$(dirname "$LOG_FILE")"
    
    # Script logic here
    log "INFO" "Performing main operations..."
    
    # Example: Check if running as root (if needed)
    # if [ "$EUID" -eq 0 ]; then
    #     error_exit "This script should not be run as root"
    # fi
    
    # Example: Check if file exists
    # if [ ! -f "$file" ]; then
    #     error_exit "File not found: $file"
    # fi
    
    # Example: Execute command with error handling
    # if ! command_to_run; then
    #     error_exit "Command failed: command_to_run"
    # fi
    
    success "Script completed successfully"
}

# Run main if script is executed directly
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
    main "$@"
fi

Python Script Template

#!/usr/bin/env python3
"""
Script Name: script_name.py
Description: Brief description of what the script does
Usage: python3 script_name.py [options] [arguments]
Author: [Author Name]
Date: 2024-11-21
Version: 1.0
"""

import sys
import os
import argparse
import logging
from pathlib import Path
from typing import List, Optional

# Configuration
SCRIPT_DIR = Path(__file__).parent.resolve()
PROJECT_ROOT = SCRIPT_DIR.parent.resolve()
LOG_FILE = PROJECT_ROOT / "logs" / "script_name.log"

# Setup logging
logging.basicConfig(
    level=logging.INFO,
    format='[%(asctime)s] [%(levelname)s] %(message)s',
    handlers=[
        logging.FileHandler(LOG_FILE),
        logging.StreamHandler(sys.stdout)
    ]
)

logger = logging.getLogger(__name__)


def validate_prerequisites() -> None:
    """Validate that all prerequisites are met."""
    missing_deps = []
    
    # Check required commands
    required_commands = ["git", "python3"]
    for cmd in required_commands:
        if not shutil.which(cmd):
            missing_deps.append(cmd)
    
    if missing_deps:
        logger.error(f"Missing required commands: {', '.join(missing_deps)}")
        sys.exit(3)
    
    # Check required files
    required_files = [PROJECT_ROOT / "README.md"]
    for file in required_files:
        if not file.exists():
            logger.error(f"Required file not found: {file}")
            sys.exit(5)


def parse_args() -> argparse.Namespace:
    """Parse command line arguments."""
    parser = argparse.ArgumentParser(
        description="Brief description of what the script does",
        formatter_class=argparse.RawDescriptionHelpFormatter
    )
    
    parser.add_argument(
        "-v", "--verbose",
        action="store_true",
        help="Enable verbose output"
    )
    
    parser.add_argument(
        "-q", "--quiet",
        action="store_true",
        help="Suppress non-error output"
    )
    
    parser.add_argument(
        "-d", "--dry-run",
        action="store_true",
        help="Perform a dry run without making changes"
    )
    
    parser.add_argument(
        "arg1",
        help="Description of first argument"
    )
    
    return parser.parse_args()


def main() -> int:
    """Main function."""
    logger.info("Starting script_name.py")
    
    try:
        # Parse arguments
        args = parse_args()
        
        # Validate prerequisites
        validate_prerequisites()
        
        # Create log directory if it doesn't exist
        LOG_FILE.parent.mkdir(parents=True, exist_ok=True)
        
        # Script logic here
        logger.info("Performing main operations...")
        
        # Example: Check if file exists
        # file_path = Path("example.txt")
        # if not file_path.exists():
        #     logger.error(f"File not found: {file_path}")
        #     return 1
        
        logger.info("Script completed successfully")
        return 0
        
    except KeyboardInterrupt:
        logger.warning("Script interrupted by user")
        return 130
    except Exception as e:
        logger.error(f"Unexpected error: {e}", exc_info=True)
        return 1


if __name__ == "__main__":
    sys.exit(main())

Standards

Error Handling

  1. Always use set -euo pipefail in bash scripts
  2. Handle errors explicitly - don't ignore failures
  3. Provide meaningful error messages
  4. Use appropriate exit codes
  5. Log all errors to log file

Logging

  1. Log all important operations
  2. Use consistent log format: [timestamp] [level] message
  3. Log levels: INFO, WARNING, ERROR, SUCCESS
  4. Log to both file and console (tee)
  5. Create log directory if it doesn't exist

Input Validation

  1. Validate all user input
  2. Check prerequisites before execution
  3. Verify file/directory existence
  4. Check command availability
  5. Validate environment variables

Documentation

  1. Include header with description
  2. Document all functions
  3. Provide usage information
  4. Include examples
  5. Document exit codes

Code Quality

  1. Use meaningful variable names
  2. Add comments for complex logic
  3. Keep functions focused and small
  4. Avoid hardcoded paths (use variables)
  5. Follow consistent formatting

Exit Codes

Standard exit codes for all scripts:

  • 0: Success
  • 1: General error
  • 2: Invalid arguments
  • 3: Missing dependencies
  • 4: Permission denied
  • 5: File/directory not found
  • 130: Interrupted by user (Ctrl+C)

Testing

Before Committing

  1. Test with valid inputs
  2. Test with invalid inputs
  3. Test error conditions
  4. Test edge cases
  5. Verify exit codes

Test Checklist

  • Script runs without errors
  • Error handling works correctly
  • Logging functions properly
  • Help/usage information displays
  • Exit codes are correct
  • No hardcoded paths
  • Documentation is complete

Best Practices

  1. Fail fast - Check prerequisites early
  2. Be idempotent - Scripts should be safe to run multiple times
  3. Provide feedback - Inform user of progress
  4. Clean up - Remove temporary files
  5. Be portable - Avoid platform-specific code when possible

Examples

See existing scripts for examples:

  • scripts/setup/setup_project.sh - Setup script example
  • scripts/validation/validate_project.sh - Validation script example
  • scripts/data/import_osm_data.py - Python script example

Last Updated: 2024
Version: 1.0