pyforge-deploy 0.1.7__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 (30) hide show
  1. pyforge_deploy-0.1.7/LICENSE +25 -0
  2. pyforge_deploy-0.1.7/MANIFEST.in +21 -0
  3. pyforge_deploy-0.1.7/PKG-INFO +154 -0
  4. pyforge_deploy-0.1.7/README.md +111 -0
  5. pyforge_deploy-0.1.7/pyproject.toml +107 -0
  6. pyforge_deploy-0.1.7/requirements-dev.txt +15 -0
  7. pyforge_deploy-0.1.7/setup.cfg +4 -0
  8. pyforge_deploy-0.1.7/src/pyforge_deploy/__about__.py +1 -0
  9. pyforge_deploy-0.1.7/src/pyforge_deploy/__init__.py +0 -0
  10. pyforge_deploy-0.1.7/src/pyforge_deploy/builders/__init__.py +0 -0
  11. pyforge_deploy-0.1.7/src/pyforge_deploy/builders/docker.py +170 -0
  12. pyforge_deploy-0.1.7/src/pyforge_deploy/builders/docker_engine.py +259 -0
  13. pyforge_deploy-0.1.7/src/pyforge_deploy/builders/pypi.py +175 -0
  14. pyforge_deploy-0.1.7/src/pyforge_deploy/builders/version_engine.py +237 -0
  15. pyforge_deploy-0.1.7/src/pyforge_deploy/cli.py +140 -0
  16. pyforge_deploy-0.1.7/src/pyforge_deploy/colors.py +24 -0
  17. pyforge_deploy-0.1.7/src/pyforge_deploy/py.typed +0 -0
  18. pyforge_deploy-0.1.7/src/pyforge_deploy/templates/Dockerfile.j2 +27 -0
  19. pyforge_deploy-0.1.7/src/pyforge_deploy.egg-info/PKG-INFO +154 -0
  20. pyforge_deploy-0.1.7/src/pyforge_deploy.egg-info/SOURCES.txt +28 -0
  21. pyforge_deploy-0.1.7/src/pyforge_deploy.egg-info/dependency_links.txt +1 -0
  22. pyforge_deploy-0.1.7/src/pyforge_deploy.egg-info/entry_points.txt +2 -0
  23. pyforge_deploy-0.1.7/src/pyforge_deploy.egg-info/requires.txt +17 -0
  24. pyforge_deploy-0.1.7/src/pyforge_deploy.egg-info/top_level.txt +1 -0
  25. pyforge_deploy-0.1.7/tests/test_cli.py +104 -0
  26. pyforge_deploy-0.1.7/tests/test_colors.py +23 -0
  27. pyforge_deploy-0.1.7/tests/test_docker.py +212 -0
  28. pyforge_deploy-0.1.7/tests/test_docker_engine.py +166 -0
  29. pyforge_deploy-0.1.7/tests/test_pypi.py +173 -0
  30. pyforge_deploy-0.1.7/tests/test_version_engine.py +215 -0
@@ -0,0 +1,25 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Ertan Tunç Türk
4
+
5
+ Permission is hereby granted, free of charge, to any person
6
+ obtaining a copy of this software and associated documentation
7
+ files (the "Software"), to deal in the Software without
8
+ restriction, including without limitation the rights to use,
9
+ copy, modify, merge, publish, distribute, sublicense, and/or
10
+ sell copies of the Software, and to permit persons to whom
11
+ the Software is furnished to do so, subject to the following
12
+ conditions:
13
+
14
+ The above copyright notice and this permission notice shall
15
+ be included in all copies or substantial portions of the
16
+ Software.
17
+
18
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
19
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
20
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
21
+ PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
22
+ OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23
+ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
24
+ OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,21 @@
1
+ # Include documentation files in source distribution
2
+ include LICENSE
3
+ include README.md
4
+ include pyproject.toml
5
+ include requirements-dev.txt
6
+
7
+ # Include scripts
8
+ include scripts/setup.py
9
+
10
+
11
+ # Include Jinja2 templates
12
+ include src/pyforge_deploy/templates/*
13
+
14
+ # Include type stubs marker
15
+ include src/pyforge_deploy/py.typed
16
+
17
+ # Exclude development/test artifacts
18
+ prune .github
19
+ global-exclude __pycache__
20
+ global-exclude *.py[cod]
21
+ global-exclude *.egg-info
@@ -0,0 +1,154 @@
1
+ Metadata-Version: 2.4
2
+ Name: pyforge-deploy
3
+ Version: 0.1.7
4
+ Summary: Lightweight automation tool designed to streamline the transition from development to distribution.
5
+ Author-email: Ertan Tunç Türk <ertantuncturk61@gmail.com>
6
+ Maintainer-email: Ertan Tunç Türk <ertantuncturk61@gmail.com>
7
+ License-Expression: MIT
8
+ Project-URL: Homepage, https://github.com/ertanturk/pyforge-deploy
9
+ Project-URL: Repository, https://github.com/ertanturk/pyforge-deploy
10
+ Project-URL: Documentation, https://github.com/ertanturk/pyforge-deploy#readme
11
+ Project-URL: Issues, https://github.com/ertanturk/pyforge-deploy/issues
12
+ Keywords: python,docker,pypi,cli,devops,automation,workflow,packaging
13
+ Classifier: Development Status :: 3 - Alpha
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Intended Audience :: Education
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Typing :: Typed
20
+ Classifier: Topic :: Software Development :: Libraries
21
+ Classifier: Topic :: Software Development :: Testing
22
+ Classifier: Topic :: Software Development :: Build Tools
23
+ Requires-Python: >=3.12
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE
26
+ Requires-Dist: toml
27
+ Requires-Dist: jinja2
28
+ Requires-Dist: packaging
29
+ Requires-Dist: python-dotenv
30
+ Requires-Dist: build
31
+ Requires-Dist: twine
32
+ Provides-Extra: dev
33
+ Requires-Dist: ruff; extra == "dev"
34
+ Requires-Dist: mypy; extra == "dev"
35
+ Requires-Dist: pytest; extra == "dev"
36
+ Requires-Dist: pytest-cov; extra == "dev"
37
+ Requires-Dist: bandit; extra == "dev"
38
+ Requires-Dist: pip-audit; extra == "dev"
39
+ Requires-Dist: pre-commit; extra == "dev"
40
+ Requires-Dist: coverage; extra == "dev"
41
+ Requires-Dist: types-toml; extra == "dev"
42
+ Dynamic: license-file
43
+
44
+ # pyforge-deploy
45
+
46
+ > **Note:** This is a personal/educational project. It is not intended to compete with established
47
+ > tools
48
+
49
+ [![PyPI version](https://img.shields.io/pypi/v/pyforge-deploy.svg)](https://pypi.org/project/pyforge-deploy/)
50
+ [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
51
+
52
+
53
+ > **pyforge-deploy** is a lightweight automation CLI for Python projects, streamlining the transition from development to distribution. It automates Docker image creation, version management, and PyPI publishing with a simple, intelligent interface.
54
+
55
+ ---
56
+
57
+ ## Features
58
+
59
+ * **Docker Integration:** Generates a project-specific Dockerfile from a Jinja2 template and detects the required Python version and dependencies.
60
+ * **Version Management:** Increments the project version (patch, minor, major) and verifies the new version is greater than the latest release on PyPI.
61
+ * **PyPI Deployment:** Builds source and wheel distributions and uploads them to PyPI or TestPyPI using token authentication.
62
+ * **Dependency Detection:** Scans for dependencies using pyproject.toml, requirements.txt, or import analysis.
63
+ * **CLI Commands:** Provides commands for building, deploying, and inspecting the project.
64
+
65
+ ---
66
+
67
+ ## Installation
68
+
69
+ Available on PyPI: https://pypi.org/project/pyforge-deploy/.
70
+
71
+ ```bash
72
+ pip install pyforge-deploy
73
+ ```
74
+
75
+ > **Note:** Docker must be installed and running for Docker-related features.
76
+
77
+ ---
78
+
79
+ ## Usage
80
+
81
+ Get a list of all available commands and options:
82
+
83
+ ```bash
84
+ pyforge-deploy --help
85
+ ```
86
+
87
+ ### Common Commands
88
+
89
+ - **Build a Docker Image:**
90
+
91
+ ```bash
92
+ pyforge-deploy docker-build --entry-point src/pyforge_deploy/cli.py --image-tag my-app:1.0.0
93
+ ```
94
+
95
+ - **Deploy to PyPI (Test):**
96
+
97
+ ```bash
98
+ pyforge-deploy deploy-pypi --test --bump patch
99
+ ```
100
+
101
+ - **Deploy a Specific Version:**
102
+
103
+ ```bash
104
+ pyforge-deploy deploy-pypi --version 2.1.0
105
+ ```
106
+
107
+ - **Show Detected Dependencies:**
108
+
109
+ ```bash
110
+ pyforge-deploy show-deps
111
+ ```
112
+
113
+ - **Show Project Version:**
114
+
115
+ ```bash
116
+ pyforge-deploy show-version
117
+ ```
118
+
119
+ ---
120
+
121
+ ## Configuration
122
+
123
+ For PyPI publishing, provide an API token. Create a `.env` file in your project root:
124
+
125
+ ```
126
+ PYPI_TOKEN=pypi-your-token-here
127
+ ```
128
+
129
+ Or export `PYPI_TOKEN` as an environment variable in your shell or CI/CD system.
130
+
131
+ ---
132
+
133
+ ## How It Works
134
+
135
+ - **Version Engine:** Resolves project version from `pyproject.toml`, `__about__.py`, or `.version_cache`. Fetches latest PyPI version to avoid conflicts, writes final version to `src/<package_name>/__about__.py`.
136
+ - **Docker Builder:** Detects dependencies and Python version, renders `Dockerfile.j2`, and builds the image.
137
+ - **PyPI Distributor:** Cleans build artifacts, runs `python -m build`, uploads distributions with `twine`.
138
+
139
+ ---
140
+
141
+ ## Testing
142
+
143
+ Run the full test suite with:
144
+
145
+ ```bash
146
+ pytest
147
+ ```
148
+
149
+ Unit tests cover the CLI and builder components, located in the `tests/` directory.
150
+
151
+
152
+ ## License
153
+
154
+ MIT License. See [LICENSE](LICENSE) for details..
@@ -0,0 +1,111 @@
1
+ # pyforge-deploy
2
+
3
+ > **Note:** This is a personal/educational project. It is not intended to compete with established
4
+ > tools
5
+
6
+ [![PyPI version](https://img.shields.io/pypi/v/pyforge-deploy.svg)](https://pypi.org/project/pyforge-deploy/)
7
+ [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
8
+
9
+
10
+ > **pyforge-deploy** is a lightweight automation CLI for Python projects, streamlining the transition from development to distribution. It automates Docker image creation, version management, and PyPI publishing with a simple, intelligent interface.
11
+
12
+ ---
13
+
14
+ ## Features
15
+
16
+ * **Docker Integration:** Generates a project-specific Dockerfile from a Jinja2 template and detects the required Python version and dependencies.
17
+ * **Version Management:** Increments the project version (patch, minor, major) and verifies the new version is greater than the latest release on PyPI.
18
+ * **PyPI Deployment:** Builds source and wheel distributions and uploads them to PyPI or TestPyPI using token authentication.
19
+ * **Dependency Detection:** Scans for dependencies using pyproject.toml, requirements.txt, or import analysis.
20
+ * **CLI Commands:** Provides commands for building, deploying, and inspecting the project.
21
+
22
+ ---
23
+
24
+ ## Installation
25
+
26
+ Available on PyPI: https://pypi.org/project/pyforge-deploy/.
27
+
28
+ ```bash
29
+ pip install pyforge-deploy
30
+ ```
31
+
32
+ > **Note:** Docker must be installed and running for Docker-related features.
33
+
34
+ ---
35
+
36
+ ## Usage
37
+
38
+ Get a list of all available commands and options:
39
+
40
+ ```bash
41
+ pyforge-deploy --help
42
+ ```
43
+
44
+ ### Common Commands
45
+
46
+ - **Build a Docker Image:**
47
+
48
+ ```bash
49
+ pyforge-deploy docker-build --entry-point src/pyforge_deploy/cli.py --image-tag my-app:1.0.0
50
+ ```
51
+
52
+ - **Deploy to PyPI (Test):**
53
+
54
+ ```bash
55
+ pyforge-deploy deploy-pypi --test --bump patch
56
+ ```
57
+
58
+ - **Deploy a Specific Version:**
59
+
60
+ ```bash
61
+ pyforge-deploy deploy-pypi --version 2.1.0
62
+ ```
63
+
64
+ - **Show Detected Dependencies:**
65
+
66
+ ```bash
67
+ pyforge-deploy show-deps
68
+ ```
69
+
70
+ - **Show Project Version:**
71
+
72
+ ```bash
73
+ pyforge-deploy show-version
74
+ ```
75
+
76
+ ---
77
+
78
+ ## Configuration
79
+
80
+ For PyPI publishing, provide an API token. Create a `.env` file in your project root:
81
+
82
+ ```
83
+ PYPI_TOKEN=pypi-your-token-here
84
+ ```
85
+
86
+ Or export `PYPI_TOKEN` as an environment variable in your shell or CI/CD system.
87
+
88
+ ---
89
+
90
+ ## How It Works
91
+
92
+ - **Version Engine:** Resolves project version from `pyproject.toml`, `__about__.py`, or `.version_cache`. Fetches latest PyPI version to avoid conflicts, writes final version to `src/<package_name>/__about__.py`.
93
+ - **Docker Builder:** Detects dependencies and Python version, renders `Dockerfile.j2`, and builds the image.
94
+ - **PyPI Distributor:** Cleans build artifacts, runs `python -m build`, uploads distributions with `twine`.
95
+
96
+ ---
97
+
98
+ ## Testing
99
+
100
+ Run the full test suite with:
101
+
102
+ ```bash
103
+ pytest
104
+ ```
105
+
106
+ Unit tests cover the CLI and builder components, located in the `tests/` directory.
107
+
108
+
109
+ ## License
110
+
111
+ MIT License. See [LICENSE](LICENSE) for details..
@@ -0,0 +1,107 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "pyforge-deploy"
7
+ dynamic = ["version"]
8
+ description = "Lightweight automation tool designed to streamline the transition from development to distribution."
9
+ readme = "README.md"
10
+ requires-python = ">=3.12"
11
+ license = "MIT"
12
+ dependencies = [
13
+ "toml",
14
+ "jinja2",
15
+ "packaging",
16
+ "python-dotenv",
17
+ "build",
18
+ "twine"
19
+ ]
20
+ keywords = [
21
+ "python",
22
+ "docker",
23
+ "pypi",
24
+ "cli",
25
+ "devops",
26
+ "automation",
27
+ "workflow",
28
+ "packaging",
29
+ ]
30
+
31
+ authors = [
32
+ { name = "Ertan Tunç Türk", email = "ertantuncturk61@gmail.com" },
33
+ ]
34
+
35
+ maintainers = [
36
+ { name = "Ertan Tunç Türk", email = "ertantuncturk61@gmail.com" },
37
+ ]
38
+
39
+ classifiers = [
40
+ "Development Status :: 3 - Alpha",
41
+ "Intended Audience :: Developers",
42
+ "Intended Audience :: Education",
43
+ "Operating System :: OS Independent",
44
+ "Programming Language :: Python :: 3",
45
+ "Programming Language :: Python :: 3.12",
46
+ "Typing :: Typed",
47
+ "Topic :: Software Development :: Libraries",
48
+ "Topic :: Software Development :: Testing",
49
+ "Topic :: Software Development :: Build Tools",
50
+ ]
51
+
52
+ [tool.setuptools.dynamic]
53
+ version = {attr = "pyforge_deploy.__about__.__version__"}
54
+
55
+ [project.optional-dependencies]
56
+ dev = [
57
+ "ruff",
58
+ "mypy",
59
+ "pytest",
60
+ "pytest-cov",
61
+ "bandit",
62
+ "pip-audit",
63
+ "pre-commit",
64
+ "coverage",
65
+ "types-toml"
66
+ ]
67
+
68
+ [project.urls]
69
+ Homepage = "https://github.com/ertanturk/pyforge-deploy"
70
+ Repository = "https://github.com/ertanturk/pyforge-deploy"
71
+ Documentation = "https://github.com/ertanturk/pyforge-deploy#readme"
72
+ Issues = "https://github.com/ertanturk/pyforge-deploy/issues"
73
+
74
+ [project.scripts]
75
+ pyforge-deploy = "pyforge_deploy.cli:main"
76
+
77
+ [tool.ruff]
78
+ line-length = 88
79
+ target-version = "py312"
80
+
81
+ [tool.ruff.lint]
82
+ select = ["E", "F", "I", "B", "UP"]
83
+ ignore = []
84
+
85
+ [tool.mypy]
86
+ python_version = "3.12"
87
+ strict = true
88
+ ignore_missing_imports = true
89
+ warn_unused_configs = true
90
+
91
+ [tool.pytest.ini_options]
92
+ addopts = "-v --tb=short"
93
+ testpaths = ["tests"]
94
+ minversion = "7.0"
95
+
96
+ [tool.coverage.run]
97
+ branch = true
98
+ source = ["."]
99
+ omit = ["tests/*", ".venv/*"]
100
+
101
+ [tool.coverage.report]
102
+ show_missing = true
103
+ fail_under = 70
104
+
105
+ [tool.bandit]
106
+ exclude_dirs = ["tests", ".venv"]
107
+ skips = ["B101"]
@@ -0,0 +1,15 @@
1
+ toml
2
+ jinja2
3
+ packaging
4
+ python-dotenv
5
+ build
6
+ twine
7
+ ruff
8
+ mypy
9
+ pytest
10
+ pytest-cov
11
+ bandit
12
+ pip-audit
13
+ pre-commit
14
+ coverage
15
+ types-toml
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1 @@
1
+ __version__ = "0.1.7"
File without changes
@@ -0,0 +1,170 @@
1
+ # nosec B404: subprocess usage is safe, no shell=True, command is a list
2
+ import subprocess # nosec
3
+ import sys as _sys
4
+ from pathlib import Path
5
+ from typing import Any
6
+
7
+ from jinja2 import Environment, FileSystemLoader, select_autoescape
8
+
9
+ from pyforge_deploy.colors import color_text, is_ci_environment
10
+
11
+ from .docker_engine import detect_dependencies, get_python_version
12
+
13
+ _sys.modules.setdefault("src.pyforge_deploy.builders.docker", _sys.modules[__name__])
14
+
15
+
16
+ class DockerBuilder:
17
+ """Main class responsible for rendering the Dockerfile template
18
+ and building the Docker image.
19
+ """
20
+
21
+ def __init__(
22
+ self,
23
+ entry_point: str | None = None,
24
+ image_tag: str | None = None,
25
+ verbose: bool = False,
26
+ ) -> None:
27
+ self.base_dir: Path = Path.cwd()
28
+ self.verbose: bool = verbose
29
+ if (
30
+ entry_point is not None
31
+ and not entry_point.replace("_", "").replace("-", "").isalnum()
32
+ ):
33
+ raise ValueError(
34
+ color_text(
35
+ "Error: entry_point must be alphanumeric, underscore, or hyphen.",
36
+ "red",
37
+ )
38
+ )
39
+ self.entry_point: str | None = entry_point
40
+ # Validate image_tag for Docker safety
41
+ valid_chars = "-./_:"
42
+ sanitized_tag = image_tag if image_tag else ""
43
+ for char in valid_chars:
44
+ sanitized_tag = sanitized_tag.replace(char, "")
45
+
46
+ if image_tag is not None and not sanitized_tag.isalnum():
47
+ raise ValueError(
48
+ color_text(
49
+ "Error: image_tag must be alphanumeric or contain safe characters (- . / _ :).", # noqa: E501
50
+ "red",
51
+ )
52
+ )
53
+ self.image_tag: str = image_tag or self.base_dir.name.lower().replace(" ", "-")
54
+ self.dockerfile_path: Path = self.base_dir / "Dockerfile"
55
+ self.req_docker_path: Path = self.base_dir / "requirements-docker.txt"
56
+
57
+ def _generate_docker_requirements(self, final_list: list[str]) -> None:
58
+ """Writes the detected dependencies to requirements-docker.txt."""
59
+ try:
60
+ with open(self.req_docker_path, "w", encoding="utf-8") as f:
61
+ f.write("# Auto-generated by pyforge-deploy AST/Venv scan\n")
62
+ if final_list:
63
+ for pkg in final_list:
64
+ f.write(f"{pkg}\n")
65
+
66
+ if self.verbose or is_ci_environment():
67
+ print(color_text("\n--- Detected Docker Requirements ---", "blue"))
68
+ if final_list:
69
+ for pkg in final_list:
70
+ print(f" -> {pkg}")
71
+ else:
72
+ print(" (No external dependencies needed!)")
73
+ print(color_text("------------------------------------\n", "blue"))
74
+
75
+ except Exception as err:
76
+ raise RuntimeError(
77
+ color_text(
78
+ f"Error: Failed to write requirements-docker.txt: {err}", "red"
79
+ )
80
+ ) from err
81
+
82
+ def render_template(self) -> None:
83
+ """Renders the Dockerfile template based on detected dependencies."""
84
+ python_version: str = get_python_version()
85
+
86
+ try:
87
+ report: dict[str, Any] = detect_dependencies(str(self.base_dir))
88
+ self._generate_docker_requirements(report.get("final_list", []))
89
+ except Exception:
90
+ report = {
91
+ "has_pyproject": False,
92
+ "requirement_files": [],
93
+ "final_list": [],
94
+ "detected_imports": [],
95
+ "dev_tools": [],
96
+ }
97
+ self._generate_docker_requirements([])
98
+
99
+ current_module_dir: Path = Path(__file__).parent
100
+ templates_dir: Path = current_module_dir.parent / "templates"
101
+
102
+ if not templates_dir.exists():
103
+ raise FileNotFoundError(
104
+ color_text(
105
+ f"Error: Templates directory not found at {templates_dir}", "red"
106
+ )
107
+ )
108
+
109
+ env: Environment = Environment(
110
+ loader=FileSystemLoader(str(templates_dir)),
111
+ autoescape=select_autoescape(["j2", "html", "xml"]),
112
+ )
113
+
114
+ try:
115
+ template = env.get_template("Dockerfile.j2")
116
+ rendered_content: str = template.render(
117
+ python_version=python_version,
118
+ report=report,
119
+ entry_point=self.entry_point,
120
+ )
121
+ except Exception as err:
122
+ raise RuntimeError(
123
+ color_text(f"Error: Failed to render Dockerfile template: {err}", "red")
124
+ ) from err
125
+
126
+ try:
127
+ with open(self.dockerfile_path, "w", encoding="utf-8") as f:
128
+ f.write(rendered_content)
129
+ except Exception as err:
130
+ raise RuntimeError(
131
+ color_text(f"Error: Failed to write Dockerfile: {err}", "red")
132
+ ) from err
133
+
134
+ def build_image(self) -> None:
135
+ """Builds the Docker image using the rendered Dockerfile."""
136
+ print(
137
+ color_text(f"Building Docker image with tag: '{self.image_tag}'...", "blue")
138
+ )
139
+
140
+ cmd: list[str] = ["docker", "build", "-t", self.image_tag, "."] # nosec B603: no user input, safe
141
+
142
+ try:
143
+ subprocess.run(cmd, check=True, cwd=str(self.base_dir)) # nosec B603
144
+ print(
145
+ color_text(
146
+ f"Docker image '{self.image_tag}' built successfully!", "green"
147
+ )
148
+ )
149
+
150
+ if self.req_docker_path.exists():
151
+ self.req_docker_path.unlink()
152
+
153
+ except subprocess.CalledProcessError as err:
154
+ print(color_text(f"Error: Docker build failed: {err}", "red"))
155
+ raise RuntimeError(
156
+ color_text("Docker build process failed. Check the logs above.", "red")
157
+ ) from err
158
+ except FileNotFoundError as err:
159
+ print(color_text(f"Error: Docker executable not found: {err}", "red"))
160
+ raise RuntimeError(
161
+ color_text(
162
+ "Docker executable not found. Please ensure Docker is installed and available in your PATH.", # noqa: E501
163
+ "red",
164
+ )
165
+ ) from err
166
+
167
+ def deploy(self) -> None:
168
+ """Main method to render Dockerfile and build the image."""
169
+ self.render_template()
170
+ self.build_image()