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.
- deployfilegen-0.1.21/LICENSE +21 -0
- deployfilegen-0.1.21/PKG-INFO +153 -0
- deployfilegen-0.1.21/README.md +112 -0
- deployfilegen-0.1.21/deployfilegen/__init__.py +1 -0
- deployfilegen-0.1.21/deployfilegen/analyzer/__init__.py +0 -0
- deployfilegen-0.1.21/deployfilegen/analyzer/detector.py +37 -0
- deployfilegen-0.1.21/deployfilegen/cli.py +185 -0
- deployfilegen-0.1.21/deployfilegen/config/__init__.py +0 -0
- deployfilegen-0.1.21/deployfilegen/config/env_loader.py +60 -0
- deployfilegen-0.1.21/deployfilegen/exceptions.py +19 -0
- deployfilegen-0.1.21/deployfilegen/generators/__init__.py +0 -0
- deployfilegen-0.1.21/deployfilegen/generators/backend.py +133 -0
- deployfilegen-0.1.21/deployfilegen/generators/compose.py +127 -0
- deployfilegen-0.1.21/deployfilegen/generators/frontend.py +54 -0
- deployfilegen-0.1.21/deployfilegen/generators/github.py +78 -0
- deployfilegen-0.1.21/deployfilegen/utils/__init__.py +0 -0
- deployfilegen-0.1.21/deployfilegen/utils/logger.py +15 -0
- deployfilegen-0.1.21/deployfilegen/utils/writer.py +50 -0
- deployfilegen-0.1.21/deployfilegen.egg-info/PKG-INFO +153 -0
- deployfilegen-0.1.21/deployfilegen.egg-info/SOURCES.txt +26 -0
- deployfilegen-0.1.21/deployfilegen.egg-info/dependency_links.txt +1 -0
- deployfilegen-0.1.21/deployfilegen.egg-info/entry_points.txt +2 -0
- deployfilegen-0.1.21/deployfilegen.egg-info/requires.txt +3 -0
- deployfilegen-0.1.21/deployfilegen.egg-info/top_level.txt +1 -0
- deployfilegen-0.1.21/pyproject.toml +32 -0
- deployfilegen-0.1.21/setup.cfg +4 -0
- deployfilegen-0.1.21/tests/test_cli.py +36 -0
- 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"
|
|
File without changes
|
|
@@ -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
|
|
File without changes
|