bake 0.1.0__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.
bake-0.1.0/.gitignore ADDED
@@ -0,0 +1,13 @@
1
+ # Python-generated files
2
+ __pycache__/
3
+ *.py[oc]
4
+ build/
5
+ dist/
6
+ wheels/
7
+ *.egg-info
8
+
9
+ # Virtual environments
10
+ .venv
11
+
12
+ .idea
13
+ .env
@@ -0,0 +1 @@
1
+ 3.11
bake-0.1.0/Makefile ADDED
@@ -0,0 +1,22 @@
1
+ install:
2
+ uv python install 3.11 && \
3
+ uv python pin 3.11 && \
4
+ uv venv --clear && \
5
+ uv sync
6
+
7
+ reinstall:
8
+ rm -Rf .venv && \
9
+ make install
10
+
11
+ clean-build:
12
+ rm -rf dist/ && \
13
+ rm -rf *.egg-info
14
+
15
+ build-package: clean-build
16
+ uv run --group dev python -m build
17
+
18
+ publish-test:
19
+ uv run --group dev python -m twine upload --repository testpypi dist/*
20
+
21
+ publish-prod:
22
+ uv run --group dev python -m twine upload --repository pypi dist/*
bake-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,87 @@
1
+ Metadata-Version: 2.4
2
+ Name: bake
3
+ Version: 0.1.0
4
+ Summary: Bake orchestrates internal CLI tools, setup scripts, and repeatable automation workflows.
5
+ Keywords: automation,cli,developer-tools,scripts,workflow
6
+ Classifier: Development Status :: 3 - Alpha
7
+ Classifier: Environment :: Console
8
+ Classifier: Intended Audience :: Developers
9
+ Classifier: Operating System :: OS Independent
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.11
12
+ Classifier: Programming Language :: Python :: 3.12
13
+ Classifier: Programming Language :: Python :: 3.13
14
+ Classifier: Topic :: Software Development :: Build Tools
15
+ Classifier: Topic :: Utilities
16
+ Requires-Python: >=3.11
17
+ Requires-Dist: python-dotenv>=1.1.1
18
+ Requires-Dist: rich>=14.1.0
19
+ Description-Content-Type: text/markdown
20
+
21
+ # Bake
22
+
23
+ Bake is a CLI automation orchestrator for managing internal tool repositories,
24
+ setup scripts, and reusable command workflows.
25
+
26
+ ## Why Bake
27
+
28
+ - Organize automation in one place instead of scattered shell scripts.
29
+ - Bootstrap and install tool repositories from JSON definitions.
30
+ - Expose runnable binaries in a shared `bin` directory.
31
+ - Keep local setup repeatable across developers.
32
+
33
+ ## Install
34
+
35
+ ```bash
36
+ uv venv
37
+ source .venv/bin/activate
38
+ uv pip install -e .
39
+ ```
40
+
41
+ After installation, the main command is:
42
+
43
+ ```bash
44
+ bake
45
+ ```
46
+
47
+ ## Commands
48
+
49
+ ### `bake install`
50
+
51
+ Interactive initialization flow that:
52
+
53
+ - Configures `BAKE_PATH` in `.env`.
54
+ - Creates `config`, `repositories`, and `bin` folders.
55
+ - Copies default configuration templates from `tools/config`.
56
+ - Optionally downloads and installs configured repositories.
57
+
58
+ ### `bake dpkg sync-config`
59
+
60
+ Synchronizes default configuration definitions from `tools/config` into
61
+ `$BAKE_PATH/config`.
62
+
63
+ ## Configuration Model
64
+
65
+ Bake uses JSON files in `tools/config`, for example:
66
+
67
+ ```json
68
+ {
69
+ "name": "aws-cli-toolkit",
70
+ "repo_url": "https://github.com/darioriverat/aws-cli-toolkit",
71
+ "description": "A comprehensive command-line toolkit for managing AWS services",
72
+ "scripts": {
73
+ "install": [
74
+ "uv venv",
75
+ "source .venv/bin/activate",
76
+ "uv pip install -e ."
77
+ ]
78
+ }
79
+ }
80
+ ```
81
+
82
+ Optional `binaries` entries can create symlinks/wrappers in `$BAKE_PATH/bin`.
83
+
84
+ ## Notes
85
+
86
+ - `BAKE_PATH` is the environment variable used by Bake.
87
+ - `bake` is the canonical command.
bake-0.1.0/README.md ADDED
@@ -0,0 +1,67 @@
1
+ # Bake
2
+
3
+ Bake is a CLI automation orchestrator for managing internal tool repositories,
4
+ setup scripts, and reusable command workflows.
5
+
6
+ ## Why Bake
7
+
8
+ - Organize automation in one place instead of scattered shell scripts.
9
+ - Bootstrap and install tool repositories from JSON definitions.
10
+ - Expose runnable binaries in a shared `bin` directory.
11
+ - Keep local setup repeatable across developers.
12
+
13
+ ## Install
14
+
15
+ ```bash
16
+ uv venv
17
+ source .venv/bin/activate
18
+ uv pip install -e .
19
+ ```
20
+
21
+ After installation, the main command is:
22
+
23
+ ```bash
24
+ bake
25
+ ```
26
+
27
+ ## Commands
28
+
29
+ ### `bake install`
30
+
31
+ Interactive initialization flow that:
32
+
33
+ - Configures `BAKE_PATH` in `.env`.
34
+ - Creates `config`, `repositories`, and `bin` folders.
35
+ - Copies default configuration templates from `tools/config`.
36
+ - Optionally downloads and installs configured repositories.
37
+
38
+ ### `bake dpkg sync-config`
39
+
40
+ Synchronizes default configuration definitions from `tools/config` into
41
+ `$BAKE_PATH/config`.
42
+
43
+ ## Configuration Model
44
+
45
+ Bake uses JSON files in `tools/config`, for example:
46
+
47
+ ```json
48
+ {
49
+ "name": "aws-cli-toolkit",
50
+ "repo_url": "https://github.com/darioriverat/aws-cli-toolkit",
51
+ "description": "A comprehensive command-line toolkit for managing AWS services",
52
+ "scripts": {
53
+ "install": [
54
+ "uv venv",
55
+ "source .venv/bin/activate",
56
+ "uv pip install -e ."
57
+ ]
58
+ }
59
+ }
60
+ ```
61
+
62
+ Optional `binaries` entries can create symlinks/wrappers in `$BAKE_PATH/bin`.
63
+
64
+ ## Notes
65
+
66
+ - `BAKE_PATH` is the environment variable used by Bake.
67
+ - `bake` is the canonical command.
@@ -0,0 +1 @@
1
+ """Bake package."""
bake-0.1.0/bake/cli.py ADDED
@@ -0,0 +1,40 @@
1
+ import sys
2
+
3
+ from dotenv import load_dotenv
4
+
5
+ from bake import dpkg, install
6
+
7
+ load_dotenv()
8
+
9
+
10
+ def main():
11
+ if len(sys.argv) < 2:
12
+ print("Error: No command provided")
13
+ print("Usage: bake <command> [args...]")
14
+ print("")
15
+ print("Available commands:")
16
+ print("")
17
+ print(" install Initialize Bake")
18
+ print(" dpkg Bake package manager")
19
+ print("")
20
+ sys.exit(1)
21
+
22
+ command = sys.argv[1]
23
+ command_args = sys.argv[2:]
24
+ original_argv = sys.argv
25
+ sys.argv = ["bake " + command] + command_args
26
+
27
+ try:
28
+ if command == "install":
29
+ install.main()
30
+ elif command == "dpkg":
31
+ dpkg.main()
32
+ else:
33
+ print(f"Error: Unknown command '{command}'")
34
+ sys.exit(1)
35
+ finally:
36
+ sys.argv = original_argv
37
+
38
+
39
+ if __name__ == "__main__":
40
+ main()
@@ -0,0 +1 @@
1
+ """Bake command modules."""
@@ -0,0 +1 @@
1
+ """Package management command modules for Bake."""
@@ -0,0 +1,45 @@
1
+ from pathlib import Path
2
+
3
+ from bake.exceptions import BakePathNotConfiguredException, ErrorCopyingException
4
+ from bake.output_style import OutputStyle
5
+ from bake.system.copy_subprocess import CopySubprocess
6
+ from bake.utils.bake_setup import BakeSetup
7
+
8
+
9
+ class BakeDpkgCommand:
10
+ def __init__(self, output_style: OutputStyle, bake_setup: BakeSetup):
11
+ self.output_style = output_style
12
+ self.bake_setup = bake_setup
13
+
14
+ def sync_configurations(self):
15
+ """Synchronize default bake definitions into BAKE_PATH."""
16
+ try:
17
+ bake_path = self.bake_setup.bake_path()
18
+ except BakePathNotConfiguredException:
19
+ self.output_style.writeln("No Bake path set", "error")
20
+ return
21
+
22
+ built_in_tools_dir = self._built_in_tools_dir()
23
+ try:
24
+ CopySubprocess().copy(
25
+ str(built_in_tools_dir), bake_path + "/", ["-Rf"]
26
+ )
27
+ except ErrorCopyingException as exc:
28
+ self.output_style.writeln(
29
+ "Error copying default configuration files: " + str(exc), "error"
30
+ )
31
+ return
32
+
33
+ self.output_style.writeln(
34
+ "Built-in tools directory copied successfully.", "success"
35
+ )
36
+
37
+ def _built_in_tools_dir(self) -> Path:
38
+ built_in_tools_dir = Path(__file__).resolve().parents[3] / "tools" / "config"
39
+ if not built_in_tools_dir.exists():
40
+ raise MissingBuiltInToolsDirException(
41
+ "No built-in tools directory found at "
42
+ + str(built_in_tools_dir.absolute())
43
+ )
44
+
45
+ return built_in_tools_dir
@@ -0,0 +1 @@
1
+ """Initialization command modules for Bake."""
@@ -0,0 +1,52 @@
1
+ import json
2
+
3
+ from bake.exceptions import (
4
+ BakeAlreadyExistsException,
5
+ ErrorReadingBakeConfigException,
6
+ MissingConfigurationKeysException,
7
+ )
8
+ from bake.output_style import OutputStyle
9
+ from bake.system.git_subprocess import GitSubprocess
10
+ from bake.utils.bake_setup import BakeSetup
11
+
12
+
13
+ class BakeDownloader:
14
+ """Download Bake-managed repositories from config definitions."""
15
+
16
+ def __init__(self):
17
+ self.output = OutputStyle()
18
+ self.git_subprocess = GitSubprocess()
19
+ self.bake_setup = BakeSetup()
20
+
21
+ def list_available_bakes(self):
22
+ bake_list = []
23
+ for config_file in self.bake_setup.config_path().glob("*.json"):
24
+ try:
25
+ with open(config_file, "r") as config_stream:
26
+ config = json.load(config_stream)
27
+ bake_list.append(config)
28
+ except Exception as exc:
29
+ raise ErrorReadingBakeConfigException(
30
+ "Error reading bake configuration "
31
+ + str(config_file.absolute())
32
+ + ": "
33
+ + str(exc)
34
+ ) from exc
35
+ return bake_list
36
+
37
+ def download_bake(self, config):
38
+ name = config.get("name")
39
+ repo_url = config.get("repo_url")
40
+
41
+ if not name or not repo_url:
42
+ raise MissingConfigurationKeysException(
43
+ "Invalid configuration: missing name or repo_url"
44
+ )
45
+
46
+ target_path = self.bake_setup.repositories_path() / name
47
+ if target_path.exists():
48
+ raise BakeAlreadyExistsException(
49
+ "Bake " + name + " already exists at " + str(target_path.absolute())
50
+ )
51
+
52
+ return self.git_subprocess.clone(repo_url, target_path)
@@ -0,0 +1,217 @@
1
+ from pathlib import Path
2
+
3
+ from bake.commands.init.bake_downloader import BakeDownloader
4
+ from bake.commands.init.bake_installer import BakeInstaller
5
+ from bake.commands.init.bake_path import BakePath
6
+ from bake.exceptions import (
7
+ BakeAlreadyExistsException,
8
+ BakePathNotConfiguredException,
9
+ ErrorCopyingException,
10
+ ErrorReadingBakeConfigException,
11
+ MissingConfigurationKeysException,
12
+ NoInstallableBakesException,
13
+ )
14
+ from bake.output_style import OutputStyle
15
+ from bake.system.copy_subprocess import CopySubprocess
16
+ from bake.utils.bake_setup import BakeSetup
17
+
18
+
19
+ class BakeInitCommand:
20
+ def __init__(self, bake_path: BakePath):
21
+ self.bake_path = bake_path
22
+ self.output = OutputStyle()
23
+ self.bake_setup = BakeSetup()
24
+
25
+ def execute(self):
26
+ self.set_bake_path()
27
+ self.setup_bake_directories()
28
+ self.download_bakes()
29
+ self.install_bakes()
30
+
31
+ def set_bake_path(self):
32
+ self.output.writeln("Initializing Bake...", "success")
33
+ self.output.writeln()
34
+
35
+ try:
36
+ current_path = self.bake_setup.bake_path()
37
+ except BakePathNotConfiguredException:
38
+ current_path = None
39
+
40
+ if current_path:
41
+ self.output.writeln(f"Current Bake path: {current_path}", "info")
42
+ else:
43
+ self.output.writeln("No Bake path configured yet.", "warning")
44
+ self.output.writeln("Suggested paths:")
45
+ for idx, path in enumerate(self.bake_path.get_suggested_paths(), 1):
46
+ self.output.writeln(f" {idx}. {path}", "info")
47
+
48
+ while True:
49
+ if current_path:
50
+ self.output.writeln("Press Enter to keep this path or enter a new one:")
51
+ else:
52
+ self.output.writeln("Enter the path where Bake repositories will live:")
53
+
54
+ new_path = input().strip()
55
+ final_path = new_path if new_path else current_path
56
+ if final_path:
57
+ break
58
+
59
+ self.output.writeln("Invalid path. Please try again.", "error")
60
+
61
+ if self.bake_path.path_exists(final_path):
62
+ self.output.writeln(f"Directory already exists: {final_path}", "success")
63
+ else:
64
+ success, message = self.bake_path.create_directory(final_path)
65
+ self.output.writeln(message, "success" if success else "error")
66
+ if not success:
67
+ return
68
+
69
+ self.bake_path.save_env_file("BAKE_PATH", final_path)
70
+ self.output.writeln(f"Bake path configured: {final_path}", "success")
71
+
72
+ def setup_bake_directories(self):
73
+ try:
74
+ bake_path = self.bake_setup.bake_path()
75
+ except BakePathNotConfiguredException:
76
+ self.output.writeln("Bake path not configured", "error")
77
+ return
78
+
79
+ self.output.writeln()
80
+ self.output.writeln("Setting up Bake directories...", "info")
81
+
82
+ if not self.bake_setup.config_dir_exists() or self.bake_setup.is_config_dir_empty():
83
+ self.bake_setup.setup_config_dir()
84
+ self.output.writeln("Config directory created", "success")
85
+
86
+ built_in_tools_dir = self._built_in_tools_dir()
87
+ try:
88
+ CopySubprocess().copy(
89
+ str(built_in_tools_dir), bake_path + "/", ["-R"]
90
+ )
91
+ except ErrorCopyingException as exc:
92
+ self.output.writeln(
93
+ "Error copying built-in tools: " + str(exc), "error"
94
+ )
95
+ return
96
+
97
+ self.output.writeln("Built-in tools directory copied", "success")
98
+
99
+ if not self.bake_setup.repositories_dir_exists():
100
+ self.bake_setup.setup_repositories_dir()
101
+ self.output.writeln("Repositories directory created", "success")
102
+
103
+ if not self.bake_setup.bin_dir_exists():
104
+ self.bake_setup.setup_bin_dir()
105
+ self.output.writeln("Bin directory created", "success")
106
+
107
+ def download_bakes(self):
108
+ try:
109
+ self.bake_setup.bake_path()
110
+ except BakePathNotConfiguredException:
111
+ self.output.writeln("Bake path not configured", "error")
112
+ return
113
+
114
+ downloader = BakeDownloader()
115
+ try:
116
+ bakes = downloader.list_available_bakes()
117
+ self.output.writeln()
118
+ self.output.writeln(f"Available bakes ({len(bakes)}):", "info")
119
+ for idx, config in enumerate(bakes, 1):
120
+ self.output.writeln(f" {idx}. {config.get('name', 'Unknown')}", "info")
121
+ self.output.writeln(
122
+ f" Description: {config.get('description', 'No description')}",
123
+ "info",
124
+ )
125
+ self.output.writeln(
126
+ f" Repository: {config.get('repo_url', 'No URL')}", "info"
127
+ )
128
+ except ErrorReadingBakeConfigException as exc:
129
+ self.output.writeln("Error listing available bakes: " + str(exc), "error")
130
+ return
131
+
132
+ self.output.writeln()
133
+ self.output.writeln("Download available bakes? (y/n):", "info")
134
+ if input().strip().lower() not in ["y", "yes"]:
135
+ return
136
+
137
+ self.output.writeln()
138
+ success_count = 0
139
+ for config in bakes:
140
+ name = config.get("name", "Unknown")
141
+ self.output.writeln(f"Processing: {name}", "info")
142
+ try:
143
+ downloader.download_bake(config)
144
+ success_count += 1
145
+ except BakeAlreadyExistsException:
146
+ self.output.writeln(f"{name} already exists", "info")
147
+ except MissingConfigurationKeysException as exc:
148
+ self.output.writeln(f"Error downloading {name}: {exc}", "error")
149
+
150
+ self.output.writeln()
151
+ self.output.writeln(
152
+ f"Successfully downloaded {success_count}/{len(bakes)} bakes", "success"
153
+ )
154
+
155
+ def install_bakes(self):
156
+ try:
157
+ self.bake_setup.bake_path()
158
+ except BakePathNotConfiguredException:
159
+ self.output.writeln("Bake path not configured", "error")
160
+ return
161
+
162
+ installer = BakeInstaller()
163
+ try:
164
+ installable_bakes = installer.list_installable_bakes()
165
+ self.output.writeln()
166
+ self.output.writeln(
167
+ f"Installable bakes ({len(installable_bakes)}):", "info"
168
+ )
169
+ for idx, bake_name in enumerate(installable_bakes, 1):
170
+ self.output.writeln(f" {idx}. {bake_name}", "info")
171
+ except NoInstallableBakesException as exc:
172
+ self.output.writeln(str(exc), "error")
173
+ return
174
+
175
+ self.output.writeln()
176
+ self.output.writeln("Install available bakes? (y/n):", "info")
177
+ if input().strip().lower() not in ["y", "yes"]:
178
+ return
179
+
180
+ self.output.writeln()
181
+ self.output.writeln("Installing bakes...", "info")
182
+ results = installer.install_all_bakes()
183
+ success_count = 0
184
+ failed_count = 0
185
+
186
+ for bake_name, result in results.items():
187
+ if result["success"]:
188
+ success_count += 1
189
+ self.output.writeln(f"{bake_name}: installed", "success")
190
+ else:
191
+ failed_count += 1
192
+ self.output.writeln(f"{bake_name}: failed", "error")
193
+ self.output.writeln(f" Error: {result.get('error', 'Unknown')}", "error")
194
+
195
+ self.output.writeln()
196
+ if failed_count == 0:
197
+ self.output.writeln("Bake initialization completed successfully!", "success")
198
+ self.output.writeln("Add this to your shell profile:", "info")
199
+ self.output.writeln(
200
+ f' export PATH="$PATH:{self.bake_setup.bin_path()}"', "warning"
201
+ )
202
+ else:
203
+ self.output.writeln(
204
+ f"{success_count} bakes installed successfully, {failed_count} failed.",
205
+ "warning",
206
+ )
207
+
208
+ def _built_in_tools_dir(self) -> Path:
209
+ # First look for packaged configs (works from wheel/sdist installs).
210
+ built_in_tools_dir = Path(__file__).resolve().parents[3] / "tools" / "config"
211
+ if not built_in_tools_dir.exists():
212
+ raise MissingBuiltInToolsDirException(
213
+ "No built-in tools directory found at "
214
+ + str(built_in_tools_dir.absolute())
215
+ )
216
+
217
+ return built_in_tools_dir