octopize.deploy_tool 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- octopize_avatar_deploy/__init__.py +26 -0
- octopize_avatar_deploy/cli_test_harness.py +217 -0
- octopize_avatar_deploy/configure.py +705 -0
- octopize_avatar_deploy/defaults.yaml +63 -0
- octopize_avatar_deploy/download_templates.py +251 -0
- octopize_avatar_deploy/input_gatherer.py +324 -0
- octopize_avatar_deploy/printer.py +216 -0
- octopize_avatar_deploy/state_manager.py +136 -0
- octopize_avatar_deploy/steps/__init__.py +25 -0
- octopize_avatar_deploy/steps/authentik.py +46 -0
- octopize_avatar_deploy/steps/authentik_blueprint.py +79 -0
- octopize_avatar_deploy/steps/base.py +199 -0
- octopize_avatar_deploy/steps/database.py +37 -0
- octopize_avatar_deploy/steps/email.py +88 -0
- octopize_avatar_deploy/steps/logging.py +32 -0
- octopize_avatar_deploy/steps/required.py +81 -0
- octopize_avatar_deploy/steps/storage.py +32 -0
- octopize_avatar_deploy/steps/telemetry.py +58 -0
- octopize_avatar_deploy/steps/user.py +89 -0
- octopize_avatar_deploy/version_compat.py +344 -0
- octopize_deploy_tool-0.1.0.dist-info/METADATA +346 -0
- octopize_deploy_tool-0.1.0.dist-info/RECORD +24 -0
- octopize_deploy_tool-0.1.0.dist-info/WHEEL +4 -0
- octopize_deploy_tool-0.1.0.dist-info/entry_points.txt +2 -0
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Version compatibility checking for Avatar deployment tool.
|
|
3
|
+
|
|
4
|
+
Ensures that the script version is compatible with template and config versions.
|
|
5
|
+
Prevents old scripts from modifying new templates (forward compatibility).
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import re
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
|
|
11
|
+
# Script version (semantic versioning: MAJOR.MINOR.PATCH)
|
|
12
|
+
SCRIPT_VERSION = "2.1.0"
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class VersionError(Exception):
|
|
16
|
+
"""Raised when version compatibility check fails."""
|
|
17
|
+
|
|
18
|
+
pass
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def parse_version(version_str: str) -> tuple[int, int, int]:
|
|
22
|
+
"""
|
|
23
|
+
Parse semantic version string into tuple.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
version_str: Version string like "1.2.3"
|
|
27
|
+
|
|
28
|
+
Returns:
|
|
29
|
+
Tuple of (major, minor, patch)
|
|
30
|
+
|
|
31
|
+
Raises:
|
|
32
|
+
ValueError: If version string is invalid
|
|
33
|
+
"""
|
|
34
|
+
match = re.match(r"^(\d+)\.(\d+)\.(\d+)$", version_str.strip())
|
|
35
|
+
if not match:
|
|
36
|
+
raise ValueError(f"Invalid version string: {version_str}")
|
|
37
|
+
return (int(match.group(1)), int(match.group(2)), int(match.group(3)))
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def parse_version_constraint(constraint: str) -> tuple[str, tuple[int, int, int]]:
|
|
41
|
+
"""
|
|
42
|
+
Parse version constraint like ">=1.0.0" or "<2.0.0".
|
|
43
|
+
|
|
44
|
+
Args:
|
|
45
|
+
constraint: Version constraint string
|
|
46
|
+
|
|
47
|
+
Returns:
|
|
48
|
+
Tuple of (operator, version_tuple)
|
|
49
|
+
"""
|
|
50
|
+
match = re.match(r"^([><=]+)([\d.]+)$", constraint.strip())
|
|
51
|
+
if not match:
|
|
52
|
+
raise ValueError(f"Invalid constraint: {constraint}")
|
|
53
|
+
|
|
54
|
+
operator, version_str = match.groups()
|
|
55
|
+
version = parse_version(version_str)
|
|
56
|
+
return operator, version
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def check_constraint(
|
|
60
|
+
version: tuple[int, int, int],
|
|
61
|
+
operator: str,
|
|
62
|
+
constraint_version: tuple[int, int, int],
|
|
63
|
+
) -> bool:
|
|
64
|
+
"""
|
|
65
|
+
Check if version satisfies constraint.
|
|
66
|
+
|
|
67
|
+
Args:
|
|
68
|
+
version: Version tuple to check
|
|
69
|
+
operator: Comparison operator (>=, <, >, <=, ==)
|
|
70
|
+
constraint_version: Version tuple to compare against
|
|
71
|
+
|
|
72
|
+
Returns:
|
|
73
|
+
True if constraint is satisfied
|
|
74
|
+
"""
|
|
75
|
+
if operator == ">=":
|
|
76
|
+
return version >= constraint_version
|
|
77
|
+
elif operator == ">":
|
|
78
|
+
return version > constraint_version
|
|
79
|
+
elif operator == "<=":
|
|
80
|
+
return version <= constraint_version
|
|
81
|
+
elif operator == "<":
|
|
82
|
+
return version < constraint_version
|
|
83
|
+
elif operator == "==":
|
|
84
|
+
return version == constraint_version
|
|
85
|
+
else:
|
|
86
|
+
raise ValueError(f"Unknown operator: {operator}")
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def check_version_compatibility(script_version: str, required_version: str) -> bool:
|
|
90
|
+
"""
|
|
91
|
+
Check if script version satisfies requirement.
|
|
92
|
+
|
|
93
|
+
Args:
|
|
94
|
+
script_version: Current script version (e.g., "1.0.0")
|
|
95
|
+
required_version: Required version spec (e.g., ">=1.0.0,<2.0.0")
|
|
96
|
+
|
|
97
|
+
Returns:
|
|
98
|
+
True if compatible
|
|
99
|
+
|
|
100
|
+
Raises:
|
|
101
|
+
VersionError: If versions are incompatible
|
|
102
|
+
"""
|
|
103
|
+
script_ver = parse_version(script_version)
|
|
104
|
+
|
|
105
|
+
# Parse requirement (can be comma-separated constraints)
|
|
106
|
+
constraints = [c.strip() for c in required_version.split(",")]
|
|
107
|
+
|
|
108
|
+
for constraint in constraints:
|
|
109
|
+
operator, required_ver = parse_version_constraint(constraint)
|
|
110
|
+
if not check_constraint(script_ver, operator, required_ver):
|
|
111
|
+
return False
|
|
112
|
+
|
|
113
|
+
return True
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def extract_template_version(template_path: Path) -> str | None:
|
|
117
|
+
"""
|
|
118
|
+
Extract version from template file header.
|
|
119
|
+
|
|
120
|
+
Expected format:
|
|
121
|
+
# Template Version: 1.0.0
|
|
122
|
+
# Compatible with octopize-avatar-deploy: >=1.0.0,<2.0.0
|
|
123
|
+
|
|
124
|
+
Args:
|
|
125
|
+
template_path: Path to template file
|
|
126
|
+
|
|
127
|
+
Returns:
|
|
128
|
+
Version string or None if not found
|
|
129
|
+
"""
|
|
130
|
+
try:
|
|
131
|
+
content = template_path.read_text()
|
|
132
|
+
|
|
133
|
+
# Look for version in first 20 lines
|
|
134
|
+
lines = content.split("\n")[:20]
|
|
135
|
+
|
|
136
|
+
for line in lines:
|
|
137
|
+
# Match: # Template Version: 1.0.0
|
|
138
|
+
if "template version:" in line.lower():
|
|
139
|
+
match = re.search(r"(\d+\.\d+\.\d+)", line)
|
|
140
|
+
if match:
|
|
141
|
+
return match.group(1)
|
|
142
|
+
|
|
143
|
+
return None
|
|
144
|
+
except Exception:
|
|
145
|
+
return None
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def extract_compatibility_spec(template_path: Path) -> str | None:
|
|
149
|
+
"""
|
|
150
|
+
Extract compatibility spec from template file header.
|
|
151
|
+
|
|
152
|
+
Args:
|
|
153
|
+
template_path: Path to template file
|
|
154
|
+
|
|
155
|
+
Returns:
|
|
156
|
+
Compatibility spec string or None if not found
|
|
157
|
+
"""
|
|
158
|
+
try:
|
|
159
|
+
content = template_path.read_text()
|
|
160
|
+
lines = content.split("\n")[:20]
|
|
161
|
+
|
|
162
|
+
for line in lines:
|
|
163
|
+
# Match: # Compatible with octopize-avatar-deploy: >=1.0.0,<2.0.0
|
|
164
|
+
if "compatible with" in line.lower():
|
|
165
|
+
match = re.search(r":\s*([\d\s.,<>=]+)$", line)
|
|
166
|
+
if match:
|
|
167
|
+
return match.group(1).strip()
|
|
168
|
+
|
|
169
|
+
return None
|
|
170
|
+
except Exception:
|
|
171
|
+
return None
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
def validate_template_compatibility(
|
|
175
|
+
template_path: Path, script_version: str = SCRIPT_VERSION, verbose: bool = False
|
|
176
|
+
) -> bool:
|
|
177
|
+
"""
|
|
178
|
+
Validate that script version is compatible with template.
|
|
179
|
+
|
|
180
|
+
Args:
|
|
181
|
+
template_path: Path to template file
|
|
182
|
+
script_version: Script version to check
|
|
183
|
+
verbose: Print validation details
|
|
184
|
+
|
|
185
|
+
Returns:
|
|
186
|
+
True if compatible or no version info found
|
|
187
|
+
|
|
188
|
+
Raises:
|
|
189
|
+
VersionError: If versions are incompatible
|
|
190
|
+
"""
|
|
191
|
+
template_version = extract_template_version(template_path)
|
|
192
|
+
compatibility_spec = extract_compatibility_spec(template_path)
|
|
193
|
+
|
|
194
|
+
if verbose:
|
|
195
|
+
print(f"Validating {template_path.name}:")
|
|
196
|
+
print(f" Template version: {template_version or 'not specified'}")
|
|
197
|
+
print(f" Compatibility: {compatibility_spec or 'not specified'}")
|
|
198
|
+
print(f" Script version: {script_version}")
|
|
199
|
+
|
|
200
|
+
# If no version info in template, assume compatible (legacy template)
|
|
201
|
+
if not compatibility_spec:
|
|
202
|
+
if verbose:
|
|
203
|
+
print(" ✓ No version constraints (assuming compatible)")
|
|
204
|
+
return True
|
|
205
|
+
|
|
206
|
+
# Check compatibility
|
|
207
|
+
try:
|
|
208
|
+
compatible = check_version_compatibility(script_version, compatibility_spec)
|
|
209
|
+
|
|
210
|
+
if compatible:
|
|
211
|
+
if verbose:
|
|
212
|
+
print(" ✓ Compatible")
|
|
213
|
+
return True
|
|
214
|
+
else:
|
|
215
|
+
raise VersionError(
|
|
216
|
+
f"Script version {script_version} is not compatible with "
|
|
217
|
+
f"{template_path.name} (requires {compatibility_spec}). "
|
|
218
|
+
f"Please upgrade octopize-avatar-deploy: "
|
|
219
|
+
f"pip install --upgrade octopize-avatar-deploy"
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
except ValueError as e:
|
|
223
|
+
if verbose:
|
|
224
|
+
print(f" ⚠ Warning: Invalid version spec: {e}")
|
|
225
|
+
# If version spec is invalid, assume compatible to avoid breaking
|
|
226
|
+
return True
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
def validate_all_templates(
|
|
230
|
+
templates_dir: Path, script_version: str = SCRIPT_VERSION, verbose: bool = False
|
|
231
|
+
) -> bool:
|
|
232
|
+
"""
|
|
233
|
+
Validate all templates in directory.
|
|
234
|
+
|
|
235
|
+
Args:
|
|
236
|
+
templates_dir: Directory containing templates
|
|
237
|
+
script_version: Script version to check
|
|
238
|
+
verbose: Print validation details
|
|
239
|
+
|
|
240
|
+
Returns:
|
|
241
|
+
True if all templates are compatible
|
|
242
|
+
|
|
243
|
+
Raises:
|
|
244
|
+
VersionError: If any template is incompatible
|
|
245
|
+
"""
|
|
246
|
+
if verbose:
|
|
247
|
+
print("\nValidating template compatibility...")
|
|
248
|
+
print("=" * 60)
|
|
249
|
+
|
|
250
|
+
templates = list(templates_dir.glob("*.template"))
|
|
251
|
+
|
|
252
|
+
if not templates:
|
|
253
|
+
if verbose:
|
|
254
|
+
print("No templates found")
|
|
255
|
+
return True
|
|
256
|
+
|
|
257
|
+
for template in templates:
|
|
258
|
+
validate_template_compatibility(template, script_version, verbose)
|
|
259
|
+
|
|
260
|
+
if verbose:
|
|
261
|
+
print(f"\n✓ All {len(templates)} templates are compatible")
|
|
262
|
+
|
|
263
|
+
return True
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
def validate_template_version(
|
|
267
|
+
version_file: Path, script_version: str = SCRIPT_VERSION, verbose: bool = False
|
|
268
|
+
) -> None:
|
|
269
|
+
"""
|
|
270
|
+
Validate that the template version is compatible with the script version.
|
|
271
|
+
|
|
272
|
+
This reads the .template-version file which should contain:
|
|
273
|
+
- First line: template version (e.g., "0.1.0")
|
|
274
|
+
- Optional second line: compatibility constraint (e.g., ">=1.0.0,<2.0.0")
|
|
275
|
+
|
|
276
|
+
Args:
|
|
277
|
+
version_file: Path to .template-version file
|
|
278
|
+
script_version: Script version to check against
|
|
279
|
+
verbose: Print validation details
|
|
280
|
+
|
|
281
|
+
Raises:
|
|
282
|
+
VersionError: If template version is incompatible with script version
|
|
283
|
+
"""
|
|
284
|
+
try:
|
|
285
|
+
content = version_file.read_text().strip().split("\n")
|
|
286
|
+
|
|
287
|
+
if not content or not content[0].strip():
|
|
288
|
+
raise VersionError(
|
|
289
|
+
f"Invalid .template-version file: {version_file} (empty or missing version)"
|
|
290
|
+
)
|
|
291
|
+
|
|
292
|
+
template_version = content[0].strip()
|
|
293
|
+
|
|
294
|
+
# Parse template version to validate format
|
|
295
|
+
try:
|
|
296
|
+
parse_version(template_version)
|
|
297
|
+
except ValueError as e:
|
|
298
|
+
raise VersionError(
|
|
299
|
+
f"Invalid template version format in {version_file}: {template_version}"
|
|
300
|
+
) from e
|
|
301
|
+
|
|
302
|
+
# Check for compatibility constraint (optional second line)
|
|
303
|
+
compatibility_spec = None
|
|
304
|
+
if len(content) > 1 and content[1].strip():
|
|
305
|
+
compatibility_spec = content[1].strip()
|
|
306
|
+
|
|
307
|
+
if verbose:
|
|
308
|
+
print(f"\nValidating template version from {version_file.name}:")
|
|
309
|
+
print(f" Template version: {template_version}")
|
|
310
|
+
print(f" Compatibility spec: {compatibility_spec or 'not specified'}")
|
|
311
|
+
print(f" Script version: {script_version}")
|
|
312
|
+
|
|
313
|
+
# If no compatibility spec, accept any script version
|
|
314
|
+
if not compatibility_spec:
|
|
315
|
+
if verbose:
|
|
316
|
+
print(" ✓ No version constraints (compatible)")
|
|
317
|
+
return
|
|
318
|
+
|
|
319
|
+
# Check compatibility
|
|
320
|
+
try:
|
|
321
|
+
compatible = check_version_compatibility(script_version, compatibility_spec)
|
|
322
|
+
|
|
323
|
+
if compatible:
|
|
324
|
+
if verbose:
|
|
325
|
+
print(" ✓ Compatible")
|
|
326
|
+
else:
|
|
327
|
+
raise VersionError(
|
|
328
|
+
f"Script version {script_version} is not compatible with "
|
|
329
|
+
f"template version {template_version} (requires {compatibility_spec}). "
|
|
330
|
+
f"Please upgrade octopize-avatar-deploy: "
|
|
331
|
+
f"pip install --upgrade octopize-avatar-deploy"
|
|
332
|
+
)
|
|
333
|
+
|
|
334
|
+
except ValueError as e:
|
|
335
|
+
# Invalid constraint format - log warning but don't fail
|
|
336
|
+
if verbose:
|
|
337
|
+
print(f" ⚠ Warning: Invalid compatibility spec: {e}")
|
|
338
|
+
|
|
339
|
+
except FileNotFoundError:
|
|
340
|
+
raise VersionError(f"Template version file not found: {version_file}") from None
|
|
341
|
+
except Exception as e:
|
|
342
|
+
if isinstance(e, VersionError):
|
|
343
|
+
raise
|
|
344
|
+
raise VersionError(f"Failed to validate template version: {e}") from e
|
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: octopize.deploy_tool
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Deployment configuration tool for Octopize Avatar platform
|
|
5
|
+
Project-URL: Homepage, https://octopize.io
|
|
6
|
+
Project-URL: Documentation, https://docs.octopize.io/docs/deploying/self-hosted
|
|
7
|
+
Project-URL: Repository, https://github.com/octopize/avatar-deployment
|
|
8
|
+
Project-URL: Issues, https://github.com/octopize/avatar-deployment/issues
|
|
9
|
+
Author-email: Octopize <contact@octopize.io>
|
|
10
|
+
License: MIT
|
|
11
|
+
Keywords: avatar,configuration,deployment,octopize
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Intended Audience :: System Administrators
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Topic :: System :: Installation/Setup
|
|
19
|
+
Classifier: Topic :: System :: Systems Administration
|
|
20
|
+
Requires-Python: >=3.13
|
|
21
|
+
Requires-Dist: jinja2>=3.1.0
|
|
22
|
+
Requires-Dist: pyyaml>=6.0
|
|
23
|
+
Requires-Dist: rich>=13.0.0
|
|
24
|
+
Provides-Extra: dev
|
|
25
|
+
Requires-Dist: mypy; extra == 'dev'
|
|
26
|
+
Requires-Dist: pytest>=7.0; extra == 'dev'
|
|
27
|
+
Requires-Dist: ruff>=0.1.0; extra == 'dev'
|
|
28
|
+
Description-Content-Type: text/markdown
|
|
29
|
+
|
|
30
|
+
# Octopize Avatar Deployment Tool
|
|
31
|
+
|
|
32
|
+
Automated configuration tool for deploying Octopize Avatar platform using Docker Compose.
|
|
33
|
+
|
|
34
|
+
## Overview
|
|
35
|
+
|
|
36
|
+
This tool simplifies Avatar deployment by:
|
|
37
|
+
- **📦 Standalone package** - No need to clone the entire repository
|
|
38
|
+
- **⬇️ Downloads templates** automatically from GitHub
|
|
39
|
+
- **🎯 Deployment presets** - dev-mode, production, airgapped configurations
|
|
40
|
+
- **🔐 Secure secrets generation** - Automatic creation of encryption keys
|
|
41
|
+
- **✅ Stateless by design** - Minimal bundled dependencies
|
|
42
|
+
- **🔄 Resumable configuration** - State management for interrupted setups
|
|
43
|
+
|
|
44
|
+
## Architecture
|
|
45
|
+
|
|
46
|
+
### What's Bundled vs Downloaded
|
|
47
|
+
|
|
48
|
+
**Bundled in PyPI Package:**
|
|
49
|
+
- `configure.py` - Main configuration logic
|
|
50
|
+
- `state_manager.py` - State management for resuming
|
|
51
|
+
- `download_templates.py` - Template downloader
|
|
52
|
+
- `defaults.yaml` - Default values and presets
|
|
53
|
+
|
|
54
|
+
**Downloaded from GitHub (on-demand):**
|
|
55
|
+
- `.env.template` - Environment configuration template
|
|
56
|
+
- `nginx.conf.template` - Nginx configuration template
|
|
57
|
+
- `docker-compose.yml` - Docker services definition
|
|
58
|
+
- `.template-version` - Template version information
|
|
59
|
+
- Other deployment files
|
|
60
|
+
|
|
61
|
+
These templates are located in `docker/templates/` in the avatar-deployment repository.
|
|
62
|
+
|
|
63
|
+
This design means you can install and run the tool without cloning the repository!
|
|
64
|
+
|
|
65
|
+
## Quick Start
|
|
66
|
+
|
|
67
|
+
### Option 1: Using uvx (Recommended - After PyPI Publication)
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
uvx octopize-avatar-deploy --output-dir /app/avatar
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Option 2: Using pip
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
pip install octopize-avatar-deploy
|
|
77
|
+
octopize-avatar-deploy --output-dir /app/avatar
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Option 3: From Source with uv
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
# Sparse clone (only deployment-tool directory)
|
|
84
|
+
git clone --depth 1 --filter=blob:none --sparse https://github.com/octopize/avatar-deployment
|
|
85
|
+
cd avatar-deployment
|
|
86
|
+
git sparse-checkout set deployment-tool
|
|
87
|
+
|
|
88
|
+
# Run with uv
|
|
89
|
+
cd deployment-tool
|
|
90
|
+
uv run configure.py --output-dir /app/avatar
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Deployment Presets
|
|
94
|
+
|
|
95
|
+
Choose a preset to quickly configure for your environment:
|
|
96
|
+
|
|
97
|
+
### `default` - Production Configuration
|
|
98
|
+
- Console logging: **disabled** (use structured logs)
|
|
99
|
+
- Sentry monitoring: **enabled**
|
|
100
|
+
- Telemetry: **enabled**
|
|
101
|
+
- Best for: Production deployments with monitoring
|
|
102
|
+
|
|
103
|
+
### `dev-mode` - Development Configuration
|
|
104
|
+
- Console logging: **enabled** (see logs in terminal)
|
|
105
|
+
- Sentry monitoring: **disabled**
|
|
106
|
+
- Telemetry: **disabled**
|
|
107
|
+
- Best for: Local development and testing
|
|
108
|
+
|
|
109
|
+
### `airgapped` - Air-Gapped Deployment
|
|
110
|
+
- Console logging: **disabled**
|
|
111
|
+
- Sentry monitoring: **disabled** (no external connections)
|
|
112
|
+
- Telemetry: **disabled** (no external connections)
|
|
113
|
+
- Best for: Secure, isolated environments
|
|
114
|
+
|
|
115
|
+
### `custom` - Manual Configuration
|
|
116
|
+
- Configure all options interactively
|
|
117
|
+
- Best for: Specific requirements
|
|
118
|
+
|
|
119
|
+
## Usage
|
|
120
|
+
|
|
121
|
+
### Interactive Mode with Preset
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
octopize-avatar-deploy --output-dir /app/avatar --preset dev-mode
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
The tool will:
|
|
128
|
+
1. Download latest templates from GitHub
|
|
129
|
+
2. Apply preset configuration
|
|
130
|
+
3. Prompt for required values (PUBLIC_URL, ENV_NAME)
|
|
131
|
+
4. Generate configuration files
|
|
132
|
+
|
|
133
|
+
### Non-Interactive Mode
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
# Create config file
|
|
137
|
+
cat > my-config.yaml << EOF
|
|
138
|
+
PUBLIC_URL: avatar.mycompany.com
|
|
139
|
+
ENV_NAME: mycompany-prod
|
|
140
|
+
AVATAR_API_VERSION: 2.20.1
|
|
141
|
+
AVATAR_WEB_VERSION: 0.40.0
|
|
142
|
+
MAIL_PROVIDER: smtp
|
|
143
|
+
SMTP_HOST: mail.mycompany.com
|
|
144
|
+
EOF
|
|
145
|
+
|
|
146
|
+
# Run with config
|
|
147
|
+
octopize-avatar-deploy \
|
|
148
|
+
--config my-config.yaml \
|
|
149
|
+
--preset default \
|
|
150
|
+
--non-interactive \
|
|
151
|
+
--output-dir /app/avatar
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Advanced Options
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
octopize-avatar-deploy \
|
|
158
|
+
--output-dir /app/avatar \
|
|
159
|
+
--preset dev-mode \
|
|
160
|
+
--download-branch main \ # Git branch to download from
|
|
161
|
+
--skip-download \ # Use cached templates
|
|
162
|
+
--save-config \ # Save config to deployment-config.yaml
|
|
163
|
+
--verbose # Show detailed progress
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Command Line Options
|
|
167
|
+
|
|
168
|
+
```
|
|
169
|
+
--output-dir DIR Output directory (default: current directory)
|
|
170
|
+
--preset NAME Use preset: default, dev-mode, airgapped
|
|
171
|
+
--config FILE YAML configuration file
|
|
172
|
+
--non-interactive Non-interactive mode (use config/defaults)
|
|
173
|
+
--auth-type TYPE Authentication: email or username (default: email)
|
|
174
|
+
--save-config Save config to deployment-config.yaml
|
|
175
|
+
--download-branch BRANCH Git branch for templates (default: main)
|
|
176
|
+
--skip-download Use cached templates
|
|
177
|
+
--verbose Detailed output
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
## What Gets Generated
|
|
181
|
+
|
|
182
|
+
After running the tool, you'll have:
|
|
183
|
+
|
|
184
|
+
```
|
|
185
|
+
/app/avatar/
|
|
186
|
+
├── .env # Environment configuration
|
|
187
|
+
├── nginx.conf # Nginx reverse proxy config
|
|
188
|
+
├── .secrets/ # Generated secrets (gitignored)
|
|
189
|
+
│ ├── db_password
|
|
190
|
+
│ ├── authentik_secret_key
|
|
191
|
+
│ ├── avatar_api_encryption_key
|
|
192
|
+
│ └── ...
|
|
193
|
+
├── docker-compose.yml # Downloaded from GitHub
|
|
194
|
+
└── .avatar-templates/ # Cached templates (auto-downloaded)
|
|
195
|
+
├── .env.template
|
|
196
|
+
├── nginx.conf.template
|
|
197
|
+
├── docker-compose.yml
|
|
198
|
+
└── .template-version
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
## Configuration Presets in Detail
|
|
202
|
+
|
|
203
|
+
Presets are defined in `defaults.yaml`:
|
|
204
|
+
|
|
205
|
+
```yaml
|
|
206
|
+
presets:
|
|
207
|
+
default:
|
|
208
|
+
description: "Production-ready with telemetry and monitoring"
|
|
209
|
+
application:
|
|
210
|
+
use_console_logging: "false"
|
|
211
|
+
sentry_enabled: "true"
|
|
212
|
+
telemetry:
|
|
213
|
+
enabled: true
|
|
214
|
+
|
|
215
|
+
dev-mode:
|
|
216
|
+
description: "Development with console logging"
|
|
217
|
+
application:
|
|
218
|
+
use_console_logging: "true"
|
|
219
|
+
sentry_enabled: "false"
|
|
220
|
+
telemetry:
|
|
221
|
+
enabled: false
|
|
222
|
+
|
|
223
|
+
airgapped:
|
|
224
|
+
description: "No external monitoring/telemetry"
|
|
225
|
+
application:
|
|
226
|
+
use_console_logging: "false"
|
|
227
|
+
sentry_enabled: "false"
|
|
228
|
+
telemetry:
|
|
229
|
+
enabled: false
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
You can override preset values during interactive configuration.
|
|
233
|
+
|
|
234
|
+
## Template Download Mechanism
|
|
235
|
+
|
|
236
|
+
Templates are downloaded from GitHub on first run:
|
|
237
|
+
|
|
238
|
+
1. **Check cache** - `.avatar-templates/` directory
|
|
239
|
+
2. **Download if needed** - From `github.com/octopize/avatar-deployment`
|
|
240
|
+
3. **Use cached** - On subsequent runs (unless `--skip-download` is used)
|
|
241
|
+
|
|
242
|
+
This ensures:
|
|
243
|
+
- ✅ Always get latest templates (from specified branch)
|
|
244
|
+
- ✅ Offline support (once cached)
|
|
245
|
+
- ✅ No repository cloning required
|
|
246
|
+
- ✅ Minimal package size
|
|
247
|
+
|
|
248
|
+
## State Management
|
|
249
|
+
|
|
250
|
+
The tool saves progress to `.deployment-state.yaml` allowing you to:
|
|
251
|
+
|
|
252
|
+
- **Resume interrupted configurations**
|
|
253
|
+
- **Track which steps completed**
|
|
254
|
+
- **Avoid re-entering values**
|
|
255
|
+
|
|
256
|
+
Steps:
|
|
257
|
+
1. Collect required config
|
|
258
|
+
2. Collect optional config
|
|
259
|
+
3. Generate .env file
|
|
260
|
+
4. Generate nginx.conf
|
|
261
|
+
5. Generate secrets
|
|
262
|
+
6. Prompt for user secrets (optional)
|
|
263
|
+
7. Finalize
|
|
264
|
+
|
|
265
|
+
```bash
|
|
266
|
+
# If interrupted, just run again:
|
|
267
|
+
octopize-avatar-deploy --output-dir /app/avatar
|
|
268
|
+
|
|
269
|
+
# Tool will ask: "Continue from where you left off? [Y/n]"
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
## Troubleshooting
|
|
273
|
+
|
|
274
|
+
### Templates not downloading
|
|
275
|
+
|
|
276
|
+
```bash
|
|
277
|
+
# Force re-download
|
|
278
|
+
rm -rf .avatar-templates/
|
|
279
|
+
octopize-avatar-deploy --output-dir /app/avatar --verbose
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
### Use specific Git branch
|
|
283
|
+
|
|
284
|
+
```bash
|
|
285
|
+
# Download from development branch
|
|
286
|
+
octopize-avatar-deploy \
|
|
287
|
+
--output-dir /app/avatar \
|
|
288
|
+
--download-branch develop \
|
|
289
|
+
--verbose
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
### Offline mode
|
|
293
|
+
|
|
294
|
+
```bash
|
|
295
|
+
# Download templates once
|
|
296
|
+
octopize-avatar-deploy --output-dir /app/avatar
|
|
297
|
+
|
|
298
|
+
# Then use cached versions
|
|
299
|
+
octopize-avatar-deploy --output-dir /app/avatar --skip-download
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
## Development
|
|
303
|
+
|
|
304
|
+
### Project Structure
|
|
305
|
+
|
|
306
|
+
```
|
|
307
|
+
deployment-tool/
|
|
308
|
+
├── configure.py # Main script (bundled)
|
|
309
|
+
├── state_manager.py # State management (bundled)
|
|
310
|
+
├── download_templates.py # Template downloader (bundled)
|
|
311
|
+
├── defaults.yaml # Defaults and presets (bundled)
|
|
312
|
+
├── tests/ # Test suite
|
|
313
|
+
├── README.md
|
|
314
|
+
└── pyproject.toml # Package configuration
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
### Running Tests
|
|
318
|
+
|
|
319
|
+
```bash
|
|
320
|
+
cd deployment-tool
|
|
321
|
+
pytest tests/
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
### Building Package
|
|
325
|
+
|
|
326
|
+
```bash
|
|
327
|
+
pip install build
|
|
328
|
+
python -m build
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
## Related Documentation
|
|
332
|
+
|
|
333
|
+
- [Deployment Guide](../deploying-on-single-instance.md)
|
|
334
|
+
- [Docker Compose Configuration](../docker-compose.yml)
|
|
335
|
+
- [Migration Guide](../MIGRATION_GUIDE.md)
|
|
336
|
+
|
|
337
|
+
## Support
|
|
338
|
+
|
|
339
|
+
For issues and questions:
|
|
340
|
+
- Email: help@octopize.io
|
|
341
|
+
- Documentation: https://docs.octopize.io
|
|
342
|
+
- Repository: https://github.com/octopize/avatar-deployment
|
|
343
|
+
|
|
344
|
+
## License
|
|
345
|
+
|
|
346
|
+
Apache License v2.0
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
octopize_avatar_deploy/__init__.py,sha256=5RK4GI9PpEGMfABm3nZ2rEDyohQ0W_Hvn_cHQBBnAsw,651
|
|
2
|
+
octopize_avatar_deploy/cli_test_harness.py,sha256=wIMKQ3VPuJDg6LVQcJVQA8WYbKOEwNwUPBD2swl5WkU,6703
|
|
3
|
+
octopize_avatar_deploy/configure.py,sha256=BTyX0gzp-L3XpCR81VsCS5oubv6m57ltwqf7pUFVyks,24657
|
|
4
|
+
octopize_avatar_deploy/defaults.yaml,sha256=-64srbym-Ex_kPCFq6DkZet8icBCkjadOrycEDAQUas,1649
|
|
5
|
+
octopize_avatar_deploy/download_templates.py,sha256=x5ylpv1TfgbHga2AM1qZpJYrT8PxNlL2bLMj9tCsxJA,7152
|
|
6
|
+
octopize_avatar_deploy/input_gatherer.py,sha256=HztvV1_nK2ZWjtZWVoQcwQNjAtJbPJT0dDQ5l_GpSWU,11287
|
|
7
|
+
octopize_avatar_deploy/printer.py,sha256=3MdaL_eXk283z7BmZM94buvYeGfEvE9hAgaBgq0MoNs,6659
|
|
8
|
+
octopize_avatar_deploy/state_manager.py,sha256=dEZF8pSifHdlyF8_YNQLzXPpFFSx5fDk4hhUcKJHuxA,4893
|
|
9
|
+
octopize_avatar_deploy/version_compat.py,sha256=0TlsBr7zWUD9TsTuNpLkKmshrbWpyPb1pL1Z0MKtqlc,10559
|
|
10
|
+
octopize_avatar_deploy/steps/__init__.py,sha256=bITxXeDG9bvAyJ4EGUESb_uX0UTLHou98Jd8TjBrO_o,626
|
|
11
|
+
octopize_avatar_deploy/steps/authentik.py,sha256=6iSJUb18GRmz0SRYR0VzZGqPmhFRV1YZb1M9kS5XUUk,1460
|
|
12
|
+
octopize_avatar_deploy/steps/authentik_blueprint.py,sha256=fWM7F9V2gCv7Lq9vRE4YKdOfD4Bw7PTn8Iakc8FkMpw,2786
|
|
13
|
+
octopize_avatar_deploy/steps/base.py,sha256=91Ph8bGJRFa2ceKrpXlN3IOsFEX2F7hR3p6ttnR3tn0,6086
|
|
14
|
+
octopize_avatar_deploy/steps/database.py,sha256=9-RKxz0h2HdTSJyPdoW3iQ6veHVLH8aSfKxiAGUsqU4,1182
|
|
15
|
+
octopize_avatar_deploy/steps/email.py,sha256=9yz9qx7vBSt8Dfg-7CZ3yM2kfIoWimyyUyiGmAUP7LQ,3139
|
|
16
|
+
octopize_avatar_deploy/steps/logging.py,sha256=ks10nx0Mf0ZX9lygdIG4zoWFmAupJ528DbDRGM-PQnU,856
|
|
17
|
+
octopize_avatar_deploy/steps/required.py,sha256=cKAZsgmtNJ7xQ9txza3TaJ1e562iTJpg5MsjK7US9Kk,3103
|
|
18
|
+
octopize_avatar_deploy/steps/storage.py,sha256=4-GVz8cMFY_fP4m1XR0yakGXfqpAGT3ZCY-lGB2uBG4,972
|
|
19
|
+
octopize_avatar_deploy/steps/telemetry.py,sha256=Xo5sNDROBJGeZyLzum6aYCCYovebbNQvxeQVmILp54A,1878
|
|
20
|
+
octopize_avatar_deploy/steps/user.py,sha256=3FSeEVjTHFieLGN2PqUwKzwIqe4vcx5eTw651Vg66ug,2825
|
|
21
|
+
octopize_deploy_tool-0.1.0.dist-info/METADATA,sha256=C3w4-GaxFR59B7VGxnaTcLsnfLA_jR57fc89Yq4GVK0,9502
|
|
22
|
+
octopize_deploy_tool-0.1.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
23
|
+
octopize_deploy_tool-0.1.0.dist-info/entry_points.txt,sha256=owTMr4VgBceyp-KPS3f4CEsiKkVQJAx84PRpjS8G5cw,81
|
|
24
|
+
octopize_deploy_tool-0.1.0.dist-info/RECORD,,
|