|
|
|
""" |
|
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() |