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.
@@ -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,,