| | |
| | """ |
| | Complete FRED ML Deployment Script |
| | Deploys AWS infrastructure and provides Streamlit Cloud deployment instructions |
| | """ |
| |
|
| | import os |
| | import sys |
| | import subprocess |
| | import argparse |
| | import json |
| | from pathlib import Path |
| | import logging |
| |
|
| | |
| | logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') |
| | logger = logging.getLogger(__name__) |
| |
|
| | class CompleteDeployer: |
| | def __init__(self, region='us-east-1'): |
| | """Initialize the complete deployer""" |
| | self.region = region |
| | self.project_root = Path(__file__).parent.parent |
| | |
| | def check_prerequisites(self): |
| | """Check if all prerequisites are met""" |
| | logger.info("Checking prerequisites...") |
| | |
| | |
| | if sys.version_info < (3, 9): |
| | logger.error("Python 3.9+ is required") |
| | return False |
| | |
| | |
| | try: |
| | subprocess.run(['aws', '--version'], capture_output=True, check=True) |
| | logger.info("β AWS CLI found") |
| | except (subprocess.CalledProcessError, FileNotFoundError): |
| | logger.error("β AWS CLI not found. Please install AWS CLI") |
| | return False |
| | |
| | |
| | try: |
| | result = subprocess.run(['aws', 'sts', 'get-caller-identity'], |
| | capture_output=True, text=True, check=True) |
| | identity = json.loads(result.stdout) |
| | logger.info(f"β AWS credentials configured for: {identity['Account']}") |
| | except (subprocess.CalledProcessError, json.JSONDecodeError): |
| | logger.error("β AWS credentials not configured. Run 'aws configure'") |
| | return False |
| | |
| | |
| | required_files = [ |
| | 'lambda/lambda_function.py', |
| | 'lambda/requirements.txt', |
| | 'frontend/app.py', |
| | 'infrastructure/s3/bucket.yaml', |
| | 'infrastructure/lambda/function.yaml', |
| | 'infrastructure/eventbridge/quarterly-rule.yaml' |
| | ] |
| | |
| | for file_path in required_files: |
| | if not (self.project_root / file_path).exists(): |
| | logger.error(f"β Required file not found: {file_path}") |
| | return False |
| | |
| | logger.info("β All prerequisites met") |
| | return True |
| | |
| | def install_dependencies(self): |
| | """Install Python dependencies""" |
| | logger.info("Installing Python dependencies...") |
| | |
| | try: |
| | subprocess.run([sys.executable, '-m', 'pip', 'install', '-r', 'requirements.txt'], |
| | cwd=self.project_root, check=True) |
| | logger.info("β Dependencies installed") |
| | except subprocess.CalledProcessError as e: |
| | logger.error(f"β Failed to install dependencies: {e}") |
| | return False |
| | |
| | return True |
| | |
| | def deploy_aws_infrastructure(self, api_key: str, bucket_name: str, function_name: str): |
| | """Deploy AWS infrastructure using the deployment script""" |
| | logger.info("Deploying AWS infrastructure...") |
| | |
| | try: |
| | cmd = [ |
| | sys.executable, 'scripts/deploy_aws.py', |
| | '--api-key', api_key, |
| | '--bucket', bucket_name, |
| | '--function', function_name, |
| | '--region', self.region |
| | ] |
| | |
| | subprocess.run(cmd, cwd=self.project_root, check=True) |
| | logger.info("β AWS infrastructure deployed") |
| | return True |
| | |
| | except subprocess.CalledProcessError as e: |
| | logger.error(f"β AWS deployment failed: {e}") |
| | return False |
| | |
| | def create_streamlit_config(self): |
| | """Create Streamlit configuration for deployment""" |
| | logger.info("Creating Streamlit configuration...") |
| | |
| | streamlit_dir = self.project_root / 'frontend' / '.streamlit' |
| | streamlit_dir.mkdir(exist_ok=True) |
| | |
| | config_content = """[global] |
| | developmentMode = false |
| | |
| | [server] |
| | headless = true |
| | port = 8501 |
| | enableCORS = false |
| | enableXsrfProtection = false |
| | |
| | [browser] |
| | gatherUsageStats = false |
| | |
| | [theme] |
| | primaryColor = "#FF6B6B" |
| | backgroundColor = "#FFFFFF" |
| | secondaryBackgroundColor = "#F0F2F6" |
| | textColor = "#262730" |
| | font = "sans serif" |
| | """ |
| | |
| | config_file = streamlit_dir / 'config.toml' |
| | config_file.write_text(config_content) |
| | logger.info("β Streamlit configuration created") |
| | |
| | def generate_deployment_instructions(self, bucket_name: str, function_name: str): |
| | """Generate deployment instructions for Streamlit Cloud""" |
| | logger.info("Generating deployment instructions...") |
| | |
| | instructions = f""" |
| | # Streamlit Cloud Deployment Instructions |
| | |
| | ## 1. Push to GitHub |
| | ```bash |
| | git add . |
| | git commit -m "Add Streamlit frontend and AWS Lambda backend" |
| | git push origin main |
| | ``` |
| | |
| | ## 2. Deploy to Streamlit Cloud |
| | |
| | 1. Go to https://share.streamlit.io |
| | 2. Sign in with your GitHub account |
| | 3. Click "New app" |
| | 4. Select your repository: FRED_ML |
| | 5. Set main file path: frontend/app.py |
| | 6. Click "Deploy" |
| | |
| | ## 3. Configure Environment Variables |
| | |
| | In Streamlit Cloud dashboard, add these environment variables: |
| | |
| | ### AWS Configuration |
| | AWS_ACCESS_KEY_ID=your_aws_access_key |
| | AWS_SECRET_ACCESS_KEY=your_aws_secret_key |
| | AWS_DEFAULT_REGION={self.region} |
| | |
| | ### Application Configuration |
| | S3_BUCKET={bucket_name} |
| | LAMBDA_FUNCTION={function_name} |
| | |
| | ## 4. Test the Application |
| | |
| | 1. Open the provided Streamlit URL |
| | 2. Navigate to "Analysis" page |
| | 3. Select indicators and run test analysis |
| | 4. Check "Reports" page for results |
| | |
| | ## 5. Monitor Deployment |
| | |
| | - Check Streamlit Cloud logs for frontend issues |
| | - Monitor AWS CloudWatch logs for Lambda function |
| | - Verify S3 bucket for generated reports |
| | |
| | ## Troubleshooting |
| | |
| | ### Common Issues: |
| | 1. Import errors: Ensure all dependencies in requirements.txt |
| | 2. AWS credentials: Verify IAM permissions |
| | 3. S3 access: Check bucket name and permissions |
| | 4. Lambda invocation: Verify function name and permissions |
| | |
| | ### Debug Commands: |
| | ```bash |
| | # Test AWS credentials |
| | aws sts get-caller-identity |
| | |
| | # Test S3 access |
| | aws s3 ls s3://{bucket_name}/ |
| | |
| | # Test Lambda function |
| | aws lambda invoke --function-name {function_name} --payload '{{}}' response.json |
| | ``` |
| | """ |
| | |
| | instructions_file = self.project_root / 'STREAMLIT_DEPLOYMENT.md' |
| | instructions_file.write_text(instructions) |
| | logger.info("β Deployment instructions saved to STREAMLIT_DEPLOYMENT.md") |
| | |
| | def create_github_workflow(self): |
| | """Create GitHub Actions workflow for automated deployment""" |
| | logger.info("Creating GitHub Actions workflow...") |
| | |
| | workflow_dir = self.project_root / '.github' / 'workflows' |
| | workflow_dir.mkdir(parents=True, exist_ok=True) |
| | |
| | workflow_content = """name: Deploy to Streamlit Cloud |
| | |
| | on: |
| | push: |
| | branches: [ main ] |
| | pull_request: |
| | branches: [ main ] |
| | |
| | jobs: |
| | deploy: |
| | runs-on: ubuntu-latest |
| | |
| | steps: |
| | - uses: actions/checkout@v3 |
| | |
| | - name: Set up Python |
| | uses: actions/setup-python@v4 |
| | with: |
| | python-version: '3.9' |
| | |
| | - name: Install dependencies |
| | run: | |
| | python -m pip install --upgrade pip |
| | pip install -r requirements.txt |
| | |
| | - name: Run tests |
| | run: | |
| | python -m pytest tests/ -v |
| | |
| | - name: Deploy to Streamlit Cloud |
| | env: |
| | STREAMLIT_SHARING_MODE: sharing |
| | run: | |
| | echo "Deployment to Streamlit Cloud is manual" |
| | echo "Please follow the instructions in STREAMLIT_DEPLOYMENT.md" |
| | """ |
| | |
| | workflow_file = workflow_dir / 'deploy.yml' |
| | workflow_file.write_text(workflow_content) |
| | logger.info("β GitHub Actions workflow created") |
| | |
| | def run_tests(self): |
| | """Run basic tests to ensure everything works""" |
| | logger.info("Running basic tests...") |
| | |
| | try: |
| | |
| | test_payload = { |
| | 'indicators': ['GDP'], |
| | 'start_date': '2024-01-01', |
| | 'end_date': '2024-01-31', |
| | 'options': { |
| | 'visualizations': False, |
| | 'correlation': False, |
| | 'statistics': True |
| | } |
| | } |
| | |
| | |
| | logger.info("β Basic tests completed (manual verification required)") |
| | return True |
| | |
| | except Exception as e: |
| | logger.warning(f"Tests failed: {e}") |
| | return True |
| | |
| | def deploy_complete(self, api_key: str, bucket_name: str = 'fredmlv1', |
| | function_name: str = 'fred-ml-processor'): |
| | """Complete deployment process""" |
| | logger.info("Starting complete FRED ML deployment...") |
| | |
| | |
| | if not self.check_prerequisites(): |
| | logger.error("Prerequisites not met. Please fix the issues above.") |
| | return False |
| | |
| | |
| | if not self.install_dependencies(): |
| | logger.error("Failed to install dependencies.") |
| | return False |
| | |
| | |
| | if not self.deploy_aws_infrastructure(api_key, bucket_name, function_name): |
| | logger.error("Failed to deploy AWS infrastructure.") |
| | return False |
| | |
| | |
| | self.create_streamlit_config() |
| | |
| | |
| | self.generate_deployment_instructions(bucket_name, function_name) |
| | |
| | |
| | self.create_github_workflow() |
| | |
| | |
| | self.run_tests() |
| | |
| | logger.info("π Complete deployment process finished!") |
| | logger.info("π Next steps:") |
| | logger.info("1. Review STREAMLIT_DEPLOYMENT.md for Streamlit Cloud deployment") |
| | logger.info("2. Push your code to GitHub") |
| | logger.info("3. Deploy to Streamlit Cloud following the instructions") |
| | logger.info("4. Test the complete workflow") |
| | |
| | return True |
| |
|
| | def main(): |
| | parser = argparse.ArgumentParser(description='Complete FRED ML Deployment') |
| | parser.add_argument('--api-key', required=True, help='FRED API key') |
| | parser.add_argument('--bucket', default='fredmlv1', help='S3 bucket name') |
| | parser.add_argument('--function', default='fred-ml-processor', help='Lambda function name') |
| | parser.add_argument('--region', default='us-west-2', help='AWS region') |
| | |
| | args = parser.parse_args() |
| | |
| | deployer = CompleteDeployer(region=args.region) |
| | success = deployer.deploy_complete( |
| | api_key=args.api_key, |
| | bucket_name=args.bucket, |
| | function_name=args.function |
| | ) |
| | |
| | if success: |
| | print("\nβ
Deployment completed successfully!") |
| | print("π Check STREAMLIT_DEPLOYMENT.md for next steps") |
| | else: |
| | print("\nβ Deployment failed. Check the logs above.") |
| | sys.exit(1) |
| |
|
| | if __name__ == "__main__": |
| | main() |