chore: commit untracked UE/scaffold files (repo cleanup triage 20260707)
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
419
scripts/STANDARDS.md
Normal file
419
scripts/STANDARDS.md
Normal file
@@ -0,0 +1,419 @@
|
||||
# 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
|
||||
|
||||
```bash
|
||||
#!/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
|
||||
|
||||
```python
|
||||
#!/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
|
||||
|
||||
Reference in New Issue
Block a user