deployfilegen 0.1.21__tar.gz

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.
Files changed (28) hide show
  1. deployfilegen-0.1.21/LICENSE +21 -0
  2. deployfilegen-0.1.21/PKG-INFO +153 -0
  3. deployfilegen-0.1.21/README.md +112 -0
  4. deployfilegen-0.1.21/deployfilegen/__init__.py +1 -0
  5. deployfilegen-0.1.21/deployfilegen/analyzer/__init__.py +0 -0
  6. deployfilegen-0.1.21/deployfilegen/analyzer/detector.py +37 -0
  7. deployfilegen-0.1.21/deployfilegen/cli.py +185 -0
  8. deployfilegen-0.1.21/deployfilegen/config/__init__.py +0 -0
  9. deployfilegen-0.1.21/deployfilegen/config/env_loader.py +60 -0
  10. deployfilegen-0.1.21/deployfilegen/exceptions.py +19 -0
  11. deployfilegen-0.1.21/deployfilegen/generators/__init__.py +0 -0
  12. deployfilegen-0.1.21/deployfilegen/generators/backend.py +133 -0
  13. deployfilegen-0.1.21/deployfilegen/generators/compose.py +127 -0
  14. deployfilegen-0.1.21/deployfilegen/generators/frontend.py +54 -0
  15. deployfilegen-0.1.21/deployfilegen/generators/github.py +78 -0
  16. deployfilegen-0.1.21/deployfilegen/utils/__init__.py +0 -0
  17. deployfilegen-0.1.21/deployfilegen/utils/logger.py +15 -0
  18. deployfilegen-0.1.21/deployfilegen/utils/writer.py +50 -0
  19. deployfilegen-0.1.21/deployfilegen.egg-info/PKG-INFO +153 -0
  20. deployfilegen-0.1.21/deployfilegen.egg-info/SOURCES.txt +26 -0
  21. deployfilegen-0.1.21/deployfilegen.egg-info/dependency_links.txt +1 -0
  22. deployfilegen-0.1.21/deployfilegen.egg-info/entry_points.txt +2 -0
  23. deployfilegen-0.1.21/deployfilegen.egg-info/requires.txt +3 -0
  24. deployfilegen-0.1.21/deployfilegen.egg-info/top_level.txt +1 -0
  25. deployfilegen-0.1.21/pyproject.toml +32 -0
  26. deployfilegen-0.1.21/setup.cfg +4 -0
  27. deployfilegen-0.1.21/tests/test_cli.py +36 -0
  28. deployfilegen-0.1.21/tests/test_detector.py +30 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Shankarsan Sahoo
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,153 @@
1
+ Metadata-Version: 2.4
2
+ Name: deployfilegen
3
+ Version: 0.1.21
4
+ Summary: A production-grade CLI tool to generate deployment configuration files for Django/React projects.
5
+ Author-email: Shankarsan Sahoo <shankarsansahoo2001@gmail.com>
6
+ License: MIT License
7
+
8
+ Copyright (c) 2026 Shankarsan Sahoo
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+
28
+ Project-URL: Homepage, https://github.com/Shankarsan-Sahoo/deployfilegen
29
+ Project-URL: Repository, https://github.com/Shankarsan-Sahoo/deployfilegen.git
30
+ Project-URL: Issues, https://github.com/Shankarsan-Sahoo/deployfilegen/issues
31
+ Classifier: Programming Language :: Python :: 3
32
+ Classifier: License :: OSI Approved :: MIT License
33
+ Classifier: Operating System :: OS Independent
34
+ Requires-Python: >=3.9
35
+ Description-Content-Type: text/markdown
36
+ License-File: LICENSE
37
+ Requires-Dist: typer[all]
38
+ Requires-Dist: python-dotenv
39
+ Requires-Dist: pytest
40
+ Dynamic: license-file
41
+
42
+ # deployfilegen
43
+
44
+ **deployfilegen** is a production-grade Python CLI library designed to automatically generate production-ready deployment configuration files for full-stack applications (Django + React).
45
+
46
+ Writing Dockerfiles, Compose configs, and CI pipelines repeatedly is slow and error-prone. **deployfilegen** automates this process using secure, battle-tested defaults.
47
+
48
+ ## Quick Start
49
+
50
+ ```bash
51
+ # 1. Install the tool
52
+ pip install deployfilegen
53
+
54
+ # 2. Initialize your project
55
+ deployfilegen init
56
+
57
+ # 3. Deploy locally
58
+ docker compose -f docker-compose.prod.yml up --build
59
+ ```
60
+
61
+ ---
62
+
63
+ ## Why deployfilegen?
64
+
65
+ Standardizing deployment is hard. This tool ensures your project follows industry best practices out of the box:
66
+ - **Security**: All containers run as non-root users.
67
+ - **Reliability**: Automated healthchecks and dependency waiting.
68
+ - **CI/CD**: Complete GitHub Actions workflow with Docker layer caching.
69
+ - **Zero Hardcoding**: All configuration is derived from your `.env` files.
70
+
71
+ ---
72
+
73
+ ## Example Project Structure
74
+
75
+ The tool expects a standard full-stack layout:
76
+
77
+ ```text
78
+ my-cool-project/
79
+ ├── backend/ # Django project
80
+ │ └── manage.py
81
+ ├── frontend/ # React project
82
+ │ └── package.json
83
+ └── .env # Required environment variables
84
+ ```
85
+
86
+ ---
87
+
88
+ ## CLI Output Example
89
+
90
+ ```text
91
+ $ deployfilegen init
92
+ INFO: Initializing deployfilegen in /path/to/project (Mode: prod)
93
+ INFO: Detected Django backend.
94
+ INFO: Detected React frontend.
95
+ INFO: Loaded environment from: .env
96
+ INFO: Generating Backend Dockerfile...
97
+ INFO: Generated backend/Dockerfile
98
+ INFO: Generating Frontend Dockerfile...
99
+ INFO: Generated frontend/Dockerfile
100
+ INFO: Generating Docker Compose...
101
+ INFO: Generated docker-compose.prod.yml
102
+ INFO: Generating GitHub Actions workflow...
103
+ INFO: Generated .github/workflows/deploy.yml
104
+ INFO: Deployment configuration generated successfully!
105
+ ```
106
+
107
+ ---
108
+
109
+ ## Usage
110
+
111
+ Navigate to your project root and run:
112
+
113
+ ```bash
114
+ # Generate a boilerplate .env template
115
+ deployfilegen template
116
+
117
+ # Initialize your project
118
+ deployfilegen init [OPTIONS]
119
+ ```
120
+
121
+ ### Commands
122
+
123
+ * `init`: Initialize deployment configuration.
124
+ * `template`: Generate a boilerplate `.env` file.
125
+
126
+ ### Global Options
127
+ - `--version`, `-v`: Show the version and exit.
128
+ - `--help`: Show this message and exit.
129
+
130
+ ### `init` Command Options
131
+
132
+ | Option | Description |
133
+ | :--- | :--- |
134
+ | `--mode prod` | Generates `docker-compose.prod.yml` (Default). Optimized for servers. |
135
+ | `--mode dev` | Generates `docker-compose.dev.yml`. Optimized for local coding. |
136
+ | `--force`, `-f` | Overwrite existing files. (Default: skips existing files). |
137
+ | `--docker-only` | Generate only the Dockerfiles. |
138
+ | `--compose-only` | Generate only the Docker Compose files. |
139
+ | `--github-only` | Generate only the GitHub Actions workflow. |
140
+ | `--backend-only` | Filter generation to only Backend components. |
141
+ | `--frontend-only` | Filter generation to only Frontend components. |
142
+
143
+ ---
144
+
145
+ ## Requirements
146
+
147
+ - Python 3.9+
148
+ - A project structure with a Django-based `backend` and a React-based `frontend`.
149
+ - A `.env` file containing: `DOCKER_USERNAME`, `BACKEND_IMAGE_NAME`, `FRONTEND_IMAGE_NAME`, `DEPLOY_HOST`, and `DEPLOY_USER`.
150
+
151
+ ## License
152
+
153
+ MIT
@@ -0,0 +1,112 @@
1
+ # deployfilegen
2
+
3
+ **deployfilegen** is a production-grade Python CLI library designed to automatically generate production-ready deployment configuration files for full-stack applications (Django + React).
4
+
5
+ Writing Dockerfiles, Compose configs, and CI pipelines repeatedly is slow and error-prone. **deployfilegen** automates this process using secure, battle-tested defaults.
6
+
7
+ ## Quick Start
8
+
9
+ ```bash
10
+ # 1. Install the tool
11
+ pip install deployfilegen
12
+
13
+ # 2. Initialize your project
14
+ deployfilegen init
15
+
16
+ # 3. Deploy locally
17
+ docker compose -f docker-compose.prod.yml up --build
18
+ ```
19
+
20
+ ---
21
+
22
+ ## Why deployfilegen?
23
+
24
+ Standardizing deployment is hard. This tool ensures your project follows industry best practices out of the box:
25
+ - **Security**: All containers run as non-root users.
26
+ - **Reliability**: Automated healthchecks and dependency waiting.
27
+ - **CI/CD**: Complete GitHub Actions workflow with Docker layer caching.
28
+ - **Zero Hardcoding**: All configuration is derived from your `.env` files.
29
+
30
+ ---
31
+
32
+ ## Example Project Structure
33
+
34
+ The tool expects a standard full-stack layout:
35
+
36
+ ```text
37
+ my-cool-project/
38
+ ├── backend/ # Django project
39
+ │ └── manage.py
40
+ ├── frontend/ # React project
41
+ │ └── package.json
42
+ └── .env # Required environment variables
43
+ ```
44
+
45
+ ---
46
+
47
+ ## CLI Output Example
48
+
49
+ ```text
50
+ $ deployfilegen init
51
+ INFO: Initializing deployfilegen in /path/to/project (Mode: prod)
52
+ INFO: Detected Django backend.
53
+ INFO: Detected React frontend.
54
+ INFO: Loaded environment from: .env
55
+ INFO: Generating Backend Dockerfile...
56
+ INFO: Generated backend/Dockerfile
57
+ INFO: Generating Frontend Dockerfile...
58
+ INFO: Generated frontend/Dockerfile
59
+ INFO: Generating Docker Compose...
60
+ INFO: Generated docker-compose.prod.yml
61
+ INFO: Generating GitHub Actions workflow...
62
+ INFO: Generated .github/workflows/deploy.yml
63
+ INFO: Deployment configuration generated successfully!
64
+ ```
65
+
66
+ ---
67
+
68
+ ## Usage
69
+
70
+ Navigate to your project root and run:
71
+
72
+ ```bash
73
+ # Generate a boilerplate .env template
74
+ deployfilegen template
75
+
76
+ # Initialize your project
77
+ deployfilegen init [OPTIONS]
78
+ ```
79
+
80
+ ### Commands
81
+
82
+ * `init`: Initialize deployment configuration.
83
+ * `template`: Generate a boilerplate `.env` file.
84
+
85
+ ### Global Options
86
+ - `--version`, `-v`: Show the version and exit.
87
+ - `--help`: Show this message and exit.
88
+
89
+ ### `init` Command Options
90
+
91
+ | Option | Description |
92
+ | :--- | :--- |
93
+ | `--mode prod` | Generates `docker-compose.prod.yml` (Default). Optimized for servers. |
94
+ | `--mode dev` | Generates `docker-compose.dev.yml`. Optimized for local coding. |
95
+ | `--force`, `-f` | Overwrite existing files. (Default: skips existing files). |
96
+ | `--docker-only` | Generate only the Dockerfiles. |
97
+ | `--compose-only` | Generate only the Docker Compose files. |
98
+ | `--github-only` | Generate only the GitHub Actions workflow. |
99
+ | `--backend-only` | Filter generation to only Backend components. |
100
+ | `--frontend-only` | Filter generation to only Frontend components. |
101
+
102
+ ---
103
+
104
+ ## Requirements
105
+
106
+ - Python 3.9+
107
+ - A project structure with a Django-based `backend` and a React-based `frontend`.
108
+ - A `.env` file containing: `DOCKER_USERNAME`, `BACKEND_IMAGE_NAME`, `FRONTEND_IMAGE_NAME`, `DEPLOY_HOST`, and `DEPLOY_USER`.
109
+
110
+ ## License
111
+
112
+ MIT
@@ -0,0 +1 @@
1
+ __version__ = "0.1.21"
@@ -0,0 +1,37 @@
1
+ from pathlib import Path
2
+ from deployfilegen.exceptions import DetectionError, ProjectStructureError
3
+ from deployfilegen.utils.logger import logger
4
+
5
+ def detect_django_backend(project_root: Path) -> Path:
6
+ """
7
+ Detects Django backend by checking for manage.py.
8
+ Returns path to backend directory.
9
+ """
10
+ backend_path = project_root / "backend"
11
+ manage_py = backend_path / "manage.py"
12
+
13
+ if not backend_path.exists():
14
+ raise ProjectStructureError(f"Backend directory not found at: {backend_path}")
15
+
16
+ if not manage_py.exists():
17
+ raise DetectionError(f"Django not detected: {manage_py} is missing.")
18
+
19
+ logger.info("Detected Django backend.")
20
+ return backend_path
21
+
22
+ def detect_react_frontend(project_root: Path) -> Path:
23
+ """
24
+ Detects React frontend by checking for package.json.
25
+ Returns path to frontend directory.
26
+ """
27
+ frontend_path = project_root / "frontend"
28
+ package_json = frontend_path / "package.json"
29
+
30
+ if not frontend_path.exists():
31
+ raise ProjectStructureError(f"Frontend directory not found at: {frontend_path}")
32
+
33
+ if not package_json.exists():
34
+ raise DetectionError(f"React not detected: {package_json} is missing.")
35
+
36
+ logger.info("Detected React frontend.")
37
+ return frontend_path
@@ -0,0 +1,185 @@
1
+ import typer
2
+ from pathlib import Path
3
+ from typing import Optional
4
+
5
+ from deployfilegen.utils.logger import logger
6
+ from deployfilegen.utils.writer import FileWriter
7
+ from deployfilegen.config.env_loader import load_environment, validate_environment
8
+ from deployfilegen.analyzer.detector import detect_django_backend, detect_react_frontend
9
+ from deployfilegen.generators.backend import generate_backend_dockerfile, generate_entrypoint_script
10
+ from deployfilegen.generators.frontend import generate_frontend_dockerfile
11
+ from deployfilegen.generators.compose import generate_docker_compose
12
+ from deployfilegen.generators.github import generate_github_workflow
13
+ from deployfilegen.exceptions import DeployFileGenError, EnvConfigError
14
+ from deployfilegen import __version__
15
+
16
+ app = typer.Typer(no_args_is_help=True)
17
+
18
+ def version_callback(value: bool):
19
+ if value:
20
+ typer.echo(__version__)
21
+ raise typer.Exit()
22
+
23
+ @app.callback()
24
+ def main_callback(
25
+ version: Optional[bool] = typer.Option(
26
+ None, "--version", "-v", callback=version_callback, is_eager=True, help="Show the version and exit."
27
+ ),
28
+ ):
29
+ """
30
+ A production-grade CLI tool to generate deployment configuration files.
31
+ """
32
+ pass
33
+
34
+ @app.command(name="init")
35
+ def init(
36
+ mode: str = typer.Option("prod", help="Generation mode: 'prod' or 'dev'"),
37
+ force: bool = typer.Option(False, "--force", "-f", help="Overwrite existing files"),
38
+ docker_only: bool = typer.Option(False, "--docker-only", help="Generate only Dockerfiles"),
39
+ compose_only: bool = typer.Option(False, "--compose-only", help="Generate only Docker Compose"),
40
+ github_only: bool = typer.Option(False, "--github-only", help="Generate only GitHub Actions"),
41
+ backend_only: bool = typer.Option(False, "--backend-only", help="Generate only for Backend"),
42
+ frontend_only: bool = typer.Option(False, "--frontend-only", help="Generate only for Frontend"),
43
+ with_db: bool = typer.Option(False, "--with-db", help="Include a Postgres database service in Docker Compose"),
44
+ ):
45
+ """
46
+ Initialize deployment configuration for the current project.
47
+ """
48
+ try:
49
+ project_root = Path.cwd()
50
+ # 1. Config & Validation
51
+ load_environment(project_root)
52
+ config = validate_environment()
53
+
54
+ # 2. Detection
55
+ try:
56
+ backend_path = detect_django_backend(project_root)
57
+ backend_detected = True
58
+ except DeployFileGenError:
59
+ backend_path = None
60
+ backend_detected = False
61
+
62
+ try:
63
+ frontend_path = detect_react_frontend(project_root)
64
+ frontend_detected = True
65
+ except DeployFileGenError:
66
+ frontend_path = None
67
+ frontend_detected = False
68
+
69
+ # 3. Initialization
70
+ writer = FileWriter(force=force)
71
+
72
+ # Targeted Logic
73
+ any_type_flag = docker_only or compose_only or github_only
74
+ do_docker = docker_only or not any_type_flag
75
+ do_compose = compose_only or not any_type_flag
76
+ do_github = github_only or not any_type_flag
77
+
78
+ any_comp_flag = backend_only or frontend_only
79
+ do_backend = backend_only or not any_comp_flag
80
+ do_frontend = frontend_only or not any_comp_flag
81
+
82
+ # 4. Generate Backend Dockerfile
83
+ if do_docker and do_backend and backend_detected:
84
+ typer.echo("Generating Backend Dockerfile...")
85
+ backend_docker = generate_backend_dockerfile(mode, backend_path)
86
+ if writer.write(backend_path / "Dockerfile", backend_docker):
87
+ typer.echo("Generated backend/Dockerfile")
88
+ writer.write(backend_path / ".dockerignore", "venv/\n__pycache__/\n*.pyc\n.git/\n.env\nstatic/\ntests/\n")
89
+
90
+ # Generate entrypoint.sh for production
91
+ if mode == "prod":
92
+ entrypoint_content = generate_entrypoint_script()
93
+ if writer.write(backend_path / "entrypoint.sh", entrypoint_content):
94
+ typer.echo("Generated backend/entrypoint.sh")
95
+
96
+ # 5. Generate Frontend Dockerfile
97
+ if do_docker and do_frontend and frontend_detected:
98
+ typer.echo("Generating Frontend Dockerfile...")
99
+ frontend_docker = generate_frontend_dockerfile(mode)
100
+ if writer.write(frontend_path / "Dockerfile", frontend_docker):
101
+ typer.echo("Generated frontend/Dockerfile")
102
+ writer.write(frontend_path / ".dockerignore", "node_modules/\nbuild/\ncoverage/\n.git/\n.env\n")
103
+
104
+ # 6. Generate docker-compose.yml
105
+ if do_compose:
106
+ typer.echo("Generating Docker Compose...")
107
+ compose_content = generate_docker_compose(mode, config, with_db=with_db)
108
+ compose_filename = "docker-compose.prod.yml" if mode == "prod" else "docker-compose.dev.yml"
109
+ if writer.write(project_root / compose_filename, compose_content):
110
+ typer.echo(f"Generated {compose_filename}")
111
+
112
+ # 7. Generate GitHub Actions
113
+ if do_github:
114
+ typer.echo("Generating GitHub Actions workflow...")
115
+ github_workflow = generate_github_workflow(config)
116
+ github_dir = project_root / ".github" / "workflows"
117
+ if writer.write(github_dir / "deploy.yml", github_workflow):
118
+ typer.echo("Generated .github/workflows/deploy.yml")
119
+
120
+ typer.echo("Deployment configuration generated successfully!")
121
+
122
+ # Runtime Success Checklist
123
+ typer.echo("\n--- 🏁 Deployment Success Checklist ---")
124
+ typer.echo("1. Connection: Ensure your server can reach the internet and your Container Registry.")
125
+ if with_db:
126
+ typer.echo("2. Database: Configured for INTERNAL Postgres service.")
127
+ else:
128
+ typer.echo("2. Database: Configured for EXTERNAL database. Ensure DATABASE_URL is set.")
129
+
130
+ typer.echo(f"3. Environment: Confirm your server's .env matches the generated template.")
131
+ typer.echo("4. Images: Ensure build images are pushed to your Registry before deploying.")
132
+ typer.echo("--------------------------------------")
133
+
134
+ except EnvConfigError as e:
135
+ typer.echo(f"Error: {e}")
136
+ typer.echo("Tip: Run 'deployfilegen template' to generate a boilerplate .env file.")
137
+ raise typer.Exit(code=1)
138
+ except DeployFileGenError as e:
139
+ logger.info("Error: {e}")
140
+ raise typer.Exit(code=1)
141
+ except Exception as e:
142
+ logger.exception(f"Unexpected Error: {e}")
143
+ raise typer.Exit(code=1)
144
+
145
+ @app.command(name="template")
146
+ def generate_template(
147
+ force: bool = typer.Option(False, "--force", "-f", help="Overwrite existing .env file")
148
+ ):
149
+ """
150
+ Generate a boilerplate .env file with required placeholders.
151
+ """
152
+ try:
153
+ project_root = Path.cwd()
154
+ env_path = project_root / ".env"
155
+
156
+ template_content = """# deployfilegen Environment Template
157
+ # Fill in these values for production deployment
158
+
159
+ # Container Registry Credentials (e.g. Docker Hub, GHCR)
160
+ DOCKER_USERNAME=your_username
161
+
162
+ # Image Names (e.g. username/repo)
163
+ BACKEND_IMAGE_NAME=your_docker_username/backend_image
164
+ FRONTEND_IMAGE_NAME=your_docker_username/frontend_image
165
+
166
+ # Deployment Server
167
+ DEPLOY_HOST=your_server_ip
168
+ DEPLOY_USER=your_ssh_user
169
+ """
170
+ writer = FileWriter(force=force)
171
+ writer.write(env_path, template_content)
172
+ typer.echo("Generated boilerplate .env file. Please fill in the values.")
173
+
174
+ except DeployFileGenError as e:
175
+ logger.info(f"Error: {e}")
176
+ raise typer.Exit(code=1)
177
+ except Exception as e:
178
+ logger.exception(f"Unexpected Error: {e}")
179
+ raise typer.Exit(code=1)
180
+
181
+ def main():
182
+ app()
183
+
184
+ if __name__ == "__main__":
185
+ main()
File without changes
@@ -0,0 +1,60 @@
1
+ import os
2
+ from pathlib import Path
3
+ from dotenv import load_dotenv
4
+ from typing import List, Dict
5
+
6
+ from deployfilegen.exceptions import EnvConfigError
7
+ from deployfilegen.utils.logger import logger
8
+
9
+ REQUIRED_ENV_VARS = [
10
+ "DOCKER_USERNAME",
11
+ "BACKEND_IMAGE_NAME",
12
+ "FRONTEND_IMAGE_NAME",
13
+ "DEPLOY_HOST",
14
+ "DEPLOY_USER",
15
+ ]
16
+
17
+ def load_environment(project_root: Path) -> None:
18
+ """
19
+ Loads .env files in layered order:
20
+ 1. project-root/.env
21
+ 2. backend/.env
22
+ 3. frontend/.env
23
+
24
+ Later files override earlier ones.
25
+ """
26
+ env_files = [
27
+ project_root / ".env",
28
+ project_root / "backend" / ".env",
29
+ project_root / "frontend" / ".env",
30
+ ]
31
+
32
+ loaded = False
33
+ for env_file in env_files:
34
+ if env_file.exists():
35
+ load_dotenv(env_file, override=True)
36
+ logger.info(f"Loaded environment from: {env_file}")
37
+ loaded = True
38
+
39
+ if not loaded:
40
+ raise EnvConfigError("No .env files found in likely locations.")
41
+
42
+ def validate_environment() -> Dict[str, str]:
43
+ """
44
+ Validates that all required environment variables are set.
45
+ Returns a dictionary of the variables.
46
+ """
47
+ missing = []
48
+ config = {}
49
+
50
+ for var in REQUIRED_ENV_VARS:
51
+ value = os.getenv(var)
52
+ if not value:
53
+ missing.append(var)
54
+ else:
55
+ config[var] = value
56
+
57
+ if missing:
58
+ raise EnvConfigError(f"Missing required environment variables: {', '.join(missing)}")
59
+
60
+ return config
@@ -0,0 +1,19 @@
1
+ class DeployFileGenError(Exception):
2
+ """Base exception for deployfilegen."""
3
+ pass
4
+
5
+ class ProjectStructureError(DeployFileGenError):
6
+ """Raised when project structure is invalid (missing backend/frontend)."""
7
+ pass
8
+
9
+ class DetectionError(DeployFileGenError):
10
+ """Raised when framework detection fails."""
11
+ pass
12
+
13
+ class EnvConfigError(DeployFileGenError):
14
+ """Raised when .env configuration is missing or invalid."""
15
+ pass
16
+
17
+ class GenerationError(DeployFileGenError):
18
+ """Raised when file generation fails."""
19
+ pass