-
Notifications
You must be signed in to change notification settings - Fork 280
Expand file tree
/
Copy pathsetup.py
More file actions
executable file
·177 lines (140 loc) · 4.94 KB
/
setup.py
File metadata and controls
executable file
·177 lines (140 loc) · 4.94 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
#!/usr/bin/env python3
"""
FastAPI Boilerplate Setup Script
Automates copying the correct configuration files for different deployment scenarios.
"""
import shutil
import sys
from pathlib import Path
DEPLOYMENTS = {
"local": {
"name": "Local development with Uvicorn",
"description": "Auto-reload enabled, development-friendly",
"path": "scripts/local_with_uvicorn",
},
"staging": {
"name": "Staging with Gunicorn managing Uvicorn workers",
"description": "Production-like setup for testing",
"path": "scripts/gunicorn_managing_uvicorn_workers",
},
"production": {
"name": "Production with NGINX",
"description": "Full production setup with reverse proxy",
"path": "scripts/production_with_nginx",
},
}
def show_help():
"""Display help information"""
print("FastAPI Boilerplate Setup")
print("=" * 25)
print()
print("Usage: python setup.py <deployment-type>")
print()
print("Available deployment types:")
for key, config in DEPLOYMENTS.items():
print(f" {key:12} - {config['name']}")
print(f" {' ' * 12} {config['description']}")
print()
print("Examples:")
print(" python setup.py local # Set up for local development")
print(" python setup.py staging # Set up for staging environment")
print(" python setup.py production # Set up for production deployment")
def copy_files(deployment_type: str):
"""Copy configuration files for the specified deployment type"""
if deployment_type not in DEPLOYMENTS:
print(f"❌ Unknown deployment type: {deployment_type}")
print()
show_help()
return False
config = DEPLOYMENTS[deployment_type]
source_path = Path(config["path"])
if not source_path.exists():
print(f"❌ Configuration path not found: {source_path}")
return False
print(f"🚀 Setting up {config['name']}...")
print(f" {config['description']}")
print()
files_to_copy = [
("Dockerfile", "Dockerfile"),
("docker-compose.yml", "docker-compose.yml"),
(".env.example", "src/.env"),
]
success = True
for source_file, dest_file in files_to_copy:
source = source_path / source_file
dest = Path(dest_file)
if not source.exists():
print(f"⚠️ Warning: {source} not found, skipping...")
continue
try:
dest.parent.mkdir(parents=True, exist_ok=True)
shutil.copy2(source, dest)
print(f"✅ Copied {source} → {dest}")
except Exception as e:
print(f"❌ Failed to copy {source} → {dest}: {e}")
success = False
if success:
print()
print("🎉 Setup complete!")
print()
if deployment_type in ["staging", "production"]:
print("⚠️ IMPORTANT: Update the .env file with your production values:")
print(" - Generate a new SECRET_KEY: openssl rand -hex 32")
print(" - Change all passwords and sensitive values")
print()
print("Next steps:")
print(" docker compose up")
if deployment_type == "local":
print(" open http://127.0.0.1:8000/docs")
elif deployment_type == "production":
print(" open http://localhost")
return True
return False
def interactive_setup():
"""Interactive setup when no arguments provided"""
print("FastAPI Boilerplate Setup")
print("=" * 25)
print()
print("Choose your deployment type:")
print()
options = list(DEPLOYMENTS.keys())
for i, key in enumerate(options, 1):
config = DEPLOYMENTS[key]
print(f" {i}. {config['name']}")
print(f" {config['description']}")
print()
while True:
try:
choice = input(f"Enter your choice (1-{len(options)}): ").strip()
if choice.isdigit():
choice_num = int(choice)
if 1 <= choice_num <= len(options):
return options[choice_num - 1]
if choice.lower() in DEPLOYMENTS:
return choice.lower()
print(f"❌ Invalid choice. Please enter 1-{len(options)} or the deployment name.")
except KeyboardInterrupt:
print("\n\n👋 Setup cancelled.")
return None
except EOFError:
print("\n\n👋 Setup cancelled.")
return None
def main():
"""Main entry point"""
if len(sys.argv) > 1 and sys.argv[1] in ["-h", "--help", "help"]:
show_help()
return
if len(sys.argv) == 2:
deployment_type = sys.argv[1].lower()
elif len(sys.argv) == 1:
deployment_type = interactive_setup()
if deployment_type is None:
return
else:
show_help()
return
success = copy_files(deployment_type)
if not success:
sys.exit(1)
if __name__ == "__main__":
main()