hvac-kia-content/test_production_deployment.py
Ben Reed a80af693ba Add comprehensive production documentation and testing
Documentation Added:
- ARCHITECTURE_DECISIONS.md: Explains why systemd over k8s (TikTok display requirements)
- DEPLOYMENT_CHECKLIST.md: Step-by-step deployment procedures
- ROLLBACK_PROCEDURES.md: Emergency rollback and recovery procedures
- test_production_deployment.py: Automated deployment verification script

Key Documentation Highlights:
- Detailed explanation of containerization limitations with browser automation
- Complete deployment checklist with pre/post verification steps
- Rollback scenarios with recovery time objectives
- Emergency contact templates and backup procedures
- Automated test script for production readiness

17 of 25 tasks completed (68% done)
Remaining work focuses on spec compliance and testing

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-18 20:20:52 -03:00

278 lines
No EOL
7.9 KiB
Python
Executable file

#!/usr/bin/env python3
"""
Production Deployment Test Script
Tests all components before going live
"""
import os
import sys
import json
import time
from pathlib import Path
from datetime import datetime
# Add project to path
sys.path.insert(0, str(Path(__file__).parent))
def test_environment():
"""Test environment variables are set"""
print("\n=== Testing Environment Variables ===")
required_vars = [
'WORDPRESS_USERNAME',
'WORDPRESS_API_KEY',
'YOUTUBE_CHANNEL_URL',
'INSTAGRAM_USERNAME',
'INSTAGRAM_PASSWORD',
'TIKTOK_TARGET',
'NAS_PATH'
]
missing = []
for var in required_vars:
value = os.getenv(var)
if value:
# Don't print sensitive values
if 'PASSWORD' in var or 'KEY' in var:
print(f"{var}: ***SET***")
else:
print(f"{var}: {value[:20]}..." if len(value) > 20 else f"{var}: {value}")
else:
print(f"{var}: MISSING")
missing.append(var)
if missing:
print(f"\n❌ Missing variables: {', '.join(missing)}")
return False
print("\n✅ All environment variables set")
return True
def test_directories():
"""Test required directories exist and are writable"""
print("\n=== Testing Directory Structure ===")
dirs_to_test = [
Path("/opt/hvac-kia-content"),
Path("/var/log/hvac-content"),
Path(os.getenv('NAS_PATH', '/mnt/nas/hvacknowitall'))
]
all_good = True
for dir_path in dirs_to_test:
if dir_path.exists():
# Test write permissions
test_file = dir_path / f"test_{datetime.now():%Y%m%d_%H%M%S}.txt"
try:
test_file.write_text("test")
test_file.unlink()
print(f"{dir_path}: Exists and writable")
except PermissionError:
print(f"{dir_path}: Exists but not writable")
all_good = False
else:
print(f"{dir_path}: Does not exist")
all_good = False
if all_good:
print("\n✅ All directories accessible")
else:
print("\n❌ Directory issues found")
return all_good
def test_config_validation():
"""Test configuration validation"""
print("\n=== Testing Configuration Validation ===")
try:
from run_production import validate_config
validate_config()
print("✅ Configuration validation passed")
return True
except Exception as e:
print(f"❌ Configuration validation failed: {e}")
return False
def test_scrapers():
"""Test each scraper can initialize"""
print("\n=== Testing Scraper Initialization ===")
from src.base_scraper import ScraperConfig
from pathlib import Path
test_config = ScraperConfig(
source_name="test",
brand_name="hvacknowitall",
data_dir=Path("/tmp/test_data"),
logs_dir=Path("/tmp/test_logs"),
timezone="America/Halifax"
)
scrapers_to_test = [
("WordPress", "src.wordpress_scraper", "WordPressScraper"),
("YouTube", "src.youtube_scraper", "YouTubeScraper"),
("Instagram", "src.instagram_scraper", "InstagramScraper"),
("TikTok", "src.tiktok_scraper_advanced", "TikTokScraperAdvanced"),
("MailChimp", "src.rss_scraper", "RSSScraperMailChimp"),
("Podcast", "src.rss_scraper", "RSSScraperPodcast")
]
all_good = True
for name, module_path, class_name in scrapers_to_test:
try:
module = __import__(module_path, fromlist=[class_name])
scraper_class = getattr(module, class_name)
scraper = scraper_class(test_config)
print(f"{name}: Initialized successfully")
except Exception as e:
print(f"{name}: Failed to initialize - {e}")
all_good = False
if all_good:
print("\n✅ All scrapers initialized")
else:
print("\n⚠️ Some scrapers failed to initialize")
return all_good
def test_systemd_files():
"""Test systemd service files exist"""
print("\n=== Testing Systemd Files ===")
systemd_files = [
Path("systemd/hvac-content-aggregator.service"),
Path("systemd/hvac-content-aggregator.timer"),
Path("systemd/hvac-content-aggregator@.service"),
Path("systemd/hvac-tiktok-captions.service"),
Path("systemd/hvac-tiktok-captions.timer")
]
all_good = True
for file_path in systemd_files:
if file_path.exists():
print(f"{file_path}: Exists")
else:
print(f"{file_path}: Missing")
all_good = False
if all_good:
print("\n✅ All systemd files present")
else:
print("\n❌ Some systemd files missing")
return all_good
def test_python_dependencies():
"""Test all required Python packages are installed"""
print("\n=== Testing Python Dependencies ===")
required_packages = [
"requests",
"pytz",
"python-dotenv",
"feedparser",
"markitdown",
"scrapling",
"instaloader",
"yt-dlp",
"tenacity"
]
all_good = True
for package in required_packages:
try:
__import__(package.replace("-", "_"))
print(f"{package}: Installed")
except ImportError:
print(f"{package}: Not installed")
all_good = False
if all_good:
print("\n✅ All dependencies installed")
else:
print("\n❌ Some dependencies missing")
print("Run: pip install -r requirements.txt")
return all_good
def test_dry_run():
"""Test a dry run of the production script"""
print("\n=== Testing Dry Run ===")
try:
# Import and test validation only
from run_production import validate_environment, validate_config
validate_environment()
print("✓ Environment validation passed")
validate_config()
print("✓ Configuration validation passed")
print("\n✅ Dry run successful")
return True
except Exception as e:
print(f"\n❌ Dry run failed: {e}")
return False
def main():
"""Run all tests"""
print("=" * 50)
print("HVAC Know It All - Production Deployment Test")
print("=" * 50)
# Load environment
from dotenv import load_dotenv
load_dotenv()
tests = [
("Environment Variables", test_environment),
("Python Dependencies", test_python_dependencies),
("Configuration Validation", test_config_validation),
("Scraper Initialization", test_scrapers),
("Systemd Files", test_systemd_files),
("Dry Run", test_dry_run)
]
# Don't test directories in development
if os.path.exists("/opt/hvac-kia-content"):
tests.insert(2, ("Directory Structure", test_directories))
results = []
for test_name, test_func in tests:
try:
result = test_func()
results.append((test_name, result))
except Exception as e:
print(f"\n{test_name} crashed: {e}")
results.append((test_name, False))
# Summary
print("\n" + "=" * 50)
print("TEST SUMMARY")
print("=" * 50)
passed = 0
failed = 0
for test_name, result in results:
status = "✅ PASS" if result else "❌ FAIL"
print(f"{status}: {test_name}")
if result:
passed += 1
else:
failed += 1
print(f"\nTotal: {passed} passed, {failed} failed")
if failed == 0:
print("\n🎉 READY FOR PRODUCTION DEPLOYMENT 🎉")
return 0
else:
print(f"\n⚠️ Fix {failed} issue(s) before deployment")
return 1
if __name__ == "__main__":
sys.exit(main())