cave-cli 3.5.0__tar.gz → 3.5.2__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.
- {cave_cli-3.5.0/cave_cli.egg-info → cave_cli-3.5.2}/PKG-INFO +44 -13
- {cave_cli-3.5.0 → cave_cli-3.5.2}/README.md +43 -12
- {cave_cli-3.5.0 → cave_cli-3.5.2}/cave_cli/cli.py +73 -20
- {cave_cli-3.5.0 → cave_cli-3.5.2}/cave_cli/commands/create.py +20 -19
- cave_cli-3.5.2/cave_cli/commands/doctor.py +170 -0
- cave_cli-3.5.2/cave_cli/commands/kill.py +36 -0
- {cave_cli-3.5.0 → cave_cli-3.5.2}/cave_cli/commands/list_cmd.py +11 -5
- {cave_cli-3.5.0 → cave_cli-3.5.2}/cave_cli/commands/list_versions.py +16 -9
- {cave_cli-3.5.0 → cave_cli-3.5.2}/cave_cli/commands/prettify.py +2 -2
- {cave_cli-3.5.0 → cave_cli-3.5.2}/cave_cli/commands/purge.py +18 -5
- {cave_cli-3.5.0 → cave_cli-3.5.2}/cave_cli/commands/reset.py +11 -4
- cave_cli-3.5.2/cave_cli/commands/run.py +343 -0
- {cave_cli-3.5.0 → cave_cli-3.5.2}/cave_cli/commands/sync_cmd.py +12 -12
- {cave_cli-3.5.0 → cave_cli-3.5.2}/cave_cli/commands/test.py +8 -7
- cave_cli-3.5.2/cave_cli/commands/theme.py +34 -0
- {cave_cli-3.5.0 → cave_cli-3.5.2}/cave_cli/commands/uninstall.py +18 -5
- cave_cli-3.5.2/cave_cli/commands/update.py +57 -0
- {cave_cli-3.5.0 → cave_cli-3.5.2}/cave_cli/commands/upgrade.py +10 -5
- {cave_cli-3.5.0 → cave_cli-3.5.2}/cave_cli/commands/version.py +9 -7
- {cave_cli-3.5.0 → cave_cli-3.5.2}/cave_cli/utils/cache.py +62 -0
- cave_cli-3.5.2/cave_cli/utils/display.py +969 -0
- {cave_cli-3.5.0 → cave_cli-3.5.2}/cave_cli/utils/docker.py +175 -69
- {cave_cli-3.5.0 → cave_cli-3.5.2}/cave_cli/utils/git.py +0 -2
- {cave_cli-3.5.0 → cave_cli-3.5.2}/cave_cli/utils/logger.py +28 -6
- {cave_cli-3.5.0 → cave_cli-3.5.2}/cave_cli/utils/validate.py +2 -2
- {cave_cli-3.5.0 → cave_cli-3.5.2/cave_cli.egg-info}/PKG-INFO +44 -13
- {cave_cli-3.5.0 → cave_cli-3.5.2}/cave_cli.egg-info/SOURCES.txt +3 -0
- {cave_cli-3.5.0 → cave_cli-3.5.2}/pyproject.toml +2 -2
- cave_cli-3.5.0/cave_cli/commands/kill.py +0 -23
- cave_cli-3.5.0/cave_cli/commands/run.py +0 -189
- cave_cli-3.5.0/cave_cli/commands/update.py +0 -38
- {cave_cli-3.5.0 → cave_cli-3.5.2}/LICENSE +0 -0
- {cave_cli-3.5.0 → cave_cli-3.5.2}/NOTICE.md +0 -0
- {cave_cli-3.5.0 → cave_cli-3.5.2}/cave_cli/__init__.py +0 -0
- {cave_cli-3.5.0 → cave_cli-3.5.2}/cave_cli/commands/__init__.py +0 -0
- {cave_cli-3.5.0 → cave_cli-3.5.2}/cave_cli/utils/__init__.py +0 -0
- {cave_cli-3.5.0 → cave_cli-3.5.2}/cave_cli/utils/constants.py +0 -0
- {cave_cli-3.5.0 → cave_cli-3.5.2}/cave_cli/utils/env.py +0 -0
- {cave_cli-3.5.0 → cave_cli-3.5.2}/cave_cli/utils/net.py +0 -0
- {cave_cli-3.5.0 → cave_cli-3.5.2}/cave_cli/utils/subprocess.py +0 -0
- {cave_cli-3.5.0 → cave_cli-3.5.2}/cave_cli/utils/sync.py +0 -0
- {cave_cli-3.5.0 → cave_cli-3.5.2}/cave_cli.egg-info/dependency_links.txt +0 -0
- {cave_cli-3.5.0 → cave_cli-3.5.2}/cave_cli.egg-info/entry_points.txt +0 -0
- {cave_cli-3.5.0 → cave_cli-3.5.2}/cave_cli.egg-info/top_level.txt +0 -0
- {cave_cli-3.5.0 → cave_cli-3.5.2}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cave_cli
|
|
3
|
-
Version: 3.5.
|
|
3
|
+
Version: 3.5.2
|
|
4
4
|
Summary: CLI for creating and managing Docker-based CAVE web applications.
|
|
5
5
|
Author-email: MIT-CAVE <cave-contact@mit.edu>
|
|
6
6
|
License: Apache-2.0
|
|
@@ -50,28 +50,49 @@ docker run hello-world
|
|
|
50
50
|
<details>
|
|
51
51
|
<summary>Windows</summary>
|
|
52
52
|
|
|
53
|
-
- Install Docker Desktop
|
|
54
|
-
- Install WSL2 with Ubuntu: https://learn.microsoft.com/en-us/windows/wsl/install
|
|
55
|
-
- Open your WSL Ubuntu terminal for all `cave` commands
|
|
53
|
+
- Install Docker Desktop: https://docs.docker.com/docker-for-windows/install/
|
|
56
54
|
|
|
57
55
|
</details>
|
|
58
56
|
|
|
59
57
|
## Installation
|
|
60
58
|
|
|
59
|
+
Install with [pipx](https://pipx.pypa.io/) (recommended — keeps the CLI isolated from your system Python):
|
|
60
|
+
|
|
61
61
|
```sh
|
|
62
|
-
|
|
62
|
+
pipx install cave_cli
|
|
63
63
|
```
|
|
64
64
|
|
|
65
|
-
|
|
65
|
+
If you don't have pipx, install it first:
|
|
66
|
+
|
|
67
|
+
<details>
|
|
68
|
+
<summary>macOS</summary>
|
|
66
69
|
|
|
67
70
|
```sh
|
|
68
|
-
|
|
71
|
+
# With Homebrew (recommended)
|
|
72
|
+
brew install pipx
|
|
73
|
+
pipx ensurepath
|
|
74
|
+
|
|
75
|
+
# Or with pip
|
|
76
|
+
pip3 install --user pipx
|
|
77
|
+
pipx ensurepath
|
|
69
78
|
```
|
|
70
79
|
|
|
71
|
-
|
|
80
|
+
</details>
|
|
81
|
+
<details>
|
|
82
|
+
<summary>Other Linux / Windows</summary>
|
|
72
83
|
|
|
73
84
|
```sh
|
|
74
|
-
|
|
85
|
+
python3 -m pip install --user pipx
|
|
86
|
+
pipx ensurepath
|
|
87
|
+
```
|
|
88
|
+
</details>
|
|
89
|
+
|
|
90
|
+
For more options see the [pipx installation guide](https://pipx.pypa.io/stable/installation/).
|
|
91
|
+
|
|
92
|
+
Verify the installation and check your environment health:
|
|
93
|
+
|
|
94
|
+
```sh
|
|
95
|
+
cave doctor
|
|
75
96
|
```
|
|
76
97
|
|
|
77
98
|
## Quick Start
|
|
@@ -94,7 +115,8 @@ cave --help
|
|
|
94
115
|
| Command | Description |
|
|
95
116
|
|---|---|
|
|
96
117
|
| `cave create <name>` | Create a new CAVE app from the template repository |
|
|
97
|
-
| `cave run` | Build Docker image and run the app |
|
|
118
|
+
| `cave run` | Build Docker image and run the app with a live TUI dashboard |
|
|
119
|
+
| `cave doctor` | Check the health of your Docker, Git, and Pipx environment |
|
|
98
120
|
|
|
99
121
|
### Peripheral Commands
|
|
100
122
|
|
|
@@ -114,6 +136,7 @@ cave --help
|
|
|
114
136
|
| `cave list` | List running CAVE apps |
|
|
115
137
|
| `cave kill` | Stop Docker containers for an app |
|
|
116
138
|
| `cave list-versions` | List available CAVE app versions |
|
|
139
|
+
| `cave theme <name>` | Set the CLI color theme (dark, light, solarized, monokai) |
|
|
117
140
|
| `cave update` | Update the CAVE CLI itself |
|
|
118
141
|
| `cave uninstall` | Remove the CAVE CLI |
|
|
119
142
|
| `cave version` | Print version information |
|
|
@@ -126,16 +149,24 @@ cave --help
|
|
|
126
149
|
| `--loglevel LEVEL` | Set log level: DEBUG, INFO, WARN, ERROR, SILENT |
|
|
127
150
|
| `-y`, `--yes` | Automatically answer confirmation prompts with yes |
|
|
128
151
|
|
|
152
|
+
### `cave run` Options
|
|
153
|
+
|
|
154
|
+
| Flag | Description |
|
|
155
|
+
|---|---|
|
|
156
|
+
| `--all` | Show raw container output instead of the TUI dashboard |
|
|
157
|
+
| `-it`, `--interactive` | Run in interactive mode (drops into a bash shell) |
|
|
158
|
+
| `ip:port` | Optional argument for LAN hosting (e.g. `192.168.1.1:8000`) |
|
|
159
|
+
|
|
129
160
|
## Updating
|
|
130
161
|
|
|
131
162
|
```sh
|
|
132
|
-
|
|
163
|
+
cave update
|
|
133
164
|
```
|
|
134
165
|
|
|
135
|
-
Or:
|
|
166
|
+
Or directly via pipx:
|
|
136
167
|
|
|
137
168
|
```sh
|
|
138
|
-
|
|
169
|
+
pipx upgrade cave_cli
|
|
139
170
|
```
|
|
140
171
|
|
|
141
172
|
## License Notice
|
|
@@ -33,28 +33,49 @@ docker run hello-world
|
|
|
33
33
|
<details>
|
|
34
34
|
<summary>Windows</summary>
|
|
35
35
|
|
|
36
|
-
- Install Docker Desktop
|
|
37
|
-
- Install WSL2 with Ubuntu: https://learn.microsoft.com/en-us/windows/wsl/install
|
|
38
|
-
- Open your WSL Ubuntu terminal for all `cave` commands
|
|
36
|
+
- Install Docker Desktop: https://docs.docker.com/docker-for-windows/install/
|
|
39
37
|
|
|
40
38
|
</details>
|
|
41
39
|
|
|
42
40
|
## Installation
|
|
43
41
|
|
|
42
|
+
Install with [pipx](https://pipx.pypa.io/) (recommended — keeps the CLI isolated from your system Python):
|
|
43
|
+
|
|
44
44
|
```sh
|
|
45
|
-
|
|
45
|
+
pipx install cave_cli
|
|
46
46
|
```
|
|
47
47
|
|
|
48
|
-
|
|
48
|
+
If you don't have pipx, install it first:
|
|
49
|
+
|
|
50
|
+
<details>
|
|
51
|
+
<summary>macOS</summary>
|
|
49
52
|
|
|
50
53
|
```sh
|
|
51
|
-
|
|
54
|
+
# With Homebrew (recommended)
|
|
55
|
+
brew install pipx
|
|
56
|
+
pipx ensurepath
|
|
57
|
+
|
|
58
|
+
# Or with pip
|
|
59
|
+
pip3 install --user pipx
|
|
60
|
+
pipx ensurepath
|
|
52
61
|
```
|
|
53
62
|
|
|
54
|
-
|
|
63
|
+
</details>
|
|
64
|
+
<details>
|
|
65
|
+
<summary>Other Linux / Windows</summary>
|
|
55
66
|
|
|
56
67
|
```sh
|
|
57
|
-
|
|
68
|
+
python3 -m pip install --user pipx
|
|
69
|
+
pipx ensurepath
|
|
70
|
+
```
|
|
71
|
+
</details>
|
|
72
|
+
|
|
73
|
+
For more options see the [pipx installation guide](https://pipx.pypa.io/stable/installation/).
|
|
74
|
+
|
|
75
|
+
Verify the installation and check your environment health:
|
|
76
|
+
|
|
77
|
+
```sh
|
|
78
|
+
cave doctor
|
|
58
79
|
```
|
|
59
80
|
|
|
60
81
|
## Quick Start
|
|
@@ -77,7 +98,8 @@ cave --help
|
|
|
77
98
|
| Command | Description |
|
|
78
99
|
|---|---|
|
|
79
100
|
| `cave create <name>` | Create a new CAVE app from the template repository |
|
|
80
|
-
| `cave run` | Build Docker image and run the app |
|
|
101
|
+
| `cave run` | Build Docker image and run the app with a live TUI dashboard |
|
|
102
|
+
| `cave doctor` | Check the health of your Docker, Git, and Pipx environment |
|
|
81
103
|
|
|
82
104
|
### Peripheral Commands
|
|
83
105
|
|
|
@@ -97,6 +119,7 @@ cave --help
|
|
|
97
119
|
| `cave list` | List running CAVE apps |
|
|
98
120
|
| `cave kill` | Stop Docker containers for an app |
|
|
99
121
|
| `cave list-versions` | List available CAVE app versions |
|
|
122
|
+
| `cave theme <name>` | Set the CLI color theme (dark, light, solarized, monokai) |
|
|
100
123
|
| `cave update` | Update the CAVE CLI itself |
|
|
101
124
|
| `cave uninstall` | Remove the CAVE CLI |
|
|
102
125
|
| `cave version` | Print version information |
|
|
@@ -109,16 +132,24 @@ cave --help
|
|
|
109
132
|
| `--loglevel LEVEL` | Set log level: DEBUG, INFO, WARN, ERROR, SILENT |
|
|
110
133
|
| `-y`, `--yes` | Automatically answer confirmation prompts with yes |
|
|
111
134
|
|
|
135
|
+
### `cave run` Options
|
|
136
|
+
|
|
137
|
+
| Flag | Description |
|
|
138
|
+
|---|---|
|
|
139
|
+
| `--all` | Show raw container output instead of the TUI dashboard |
|
|
140
|
+
| `-it`, `--interactive` | Run in interactive mode (drops into a bash shell) |
|
|
141
|
+
| `ip:port` | Optional argument for LAN hosting (e.g. `192.168.1.1:8000`) |
|
|
142
|
+
|
|
112
143
|
## Updating
|
|
113
144
|
|
|
114
145
|
```sh
|
|
115
|
-
|
|
146
|
+
cave update
|
|
116
147
|
```
|
|
117
148
|
|
|
118
|
-
Or:
|
|
149
|
+
Or directly via pipx:
|
|
119
150
|
|
|
120
151
|
```sh
|
|
121
|
-
|
|
152
|
+
pipx upgrade cave_cli
|
|
122
153
|
```
|
|
123
154
|
|
|
124
155
|
## License Notice
|
|
@@ -142,6 +142,13 @@ def main():
|
|
|
142
142
|
default=False,
|
|
143
143
|
help="Run in interactive mode (entrypoint set to bash)",
|
|
144
144
|
)
|
|
145
|
+
p_run.add_argument(
|
|
146
|
+
"--all",
|
|
147
|
+
dest="show_all",
|
|
148
|
+
action="store_true",
|
|
149
|
+
default=False,
|
|
150
|
+
help="Show raw container output instead of the TUI dashboard (also enabled by --verbose)",
|
|
151
|
+
)
|
|
145
152
|
|
|
146
153
|
# ------------------------------------------------------------------ #
|
|
147
154
|
# reset #
|
|
@@ -265,6 +272,13 @@ def main():
|
|
|
265
272
|
help="Stop Docker containers for a CAVE app",
|
|
266
273
|
)
|
|
267
274
|
add_global_args(p_kill)
|
|
275
|
+
p_kill.add_argument(
|
|
276
|
+
"name",
|
|
277
|
+
nargs="?",
|
|
278
|
+
default=None,
|
|
279
|
+
metavar="app-name",
|
|
280
|
+
help="Name of the CAVE app to kill",
|
|
281
|
+
)
|
|
268
282
|
p_kill.add_argument(
|
|
269
283
|
"-a",
|
|
270
284
|
"--all",
|
|
@@ -309,6 +323,15 @@ def main():
|
|
|
309
323
|
help="Glob pattern to filter versions (e.g. v3.*, v3.4.*)",
|
|
310
324
|
)
|
|
311
325
|
|
|
326
|
+
# ------------------------------------------------------------------ #
|
|
327
|
+
# doctor #
|
|
328
|
+
# ------------------------------------------------------------------ #
|
|
329
|
+
p_doctor = subparsers.add_parser(
|
|
330
|
+
"doctor",
|
|
331
|
+
help="Check the health of the CAVE environment",
|
|
332
|
+
)
|
|
333
|
+
add_global_args(p_doctor)
|
|
334
|
+
|
|
312
335
|
# ------------------------------------------------------------------ #
|
|
313
336
|
# update #
|
|
314
337
|
# ------------------------------------------------------------------ #
|
|
@@ -342,6 +365,22 @@ def main():
|
|
|
342
365
|
)
|
|
343
366
|
add_global_args(p_version)
|
|
344
367
|
|
|
368
|
+
# ------------------------------------------------------------------ #
|
|
369
|
+
# theme #
|
|
370
|
+
# ------------------------------------------------------------------ #
|
|
371
|
+
p_theme = subparsers.add_parser(
|
|
372
|
+
"theme",
|
|
373
|
+
help="Set the CLI color theme",
|
|
374
|
+
)
|
|
375
|
+
add_global_args(p_theme)
|
|
376
|
+
p_theme.add_argument(
|
|
377
|
+
"name",
|
|
378
|
+
nargs="?",
|
|
379
|
+
default=None,
|
|
380
|
+
metavar="THEME",
|
|
381
|
+
help="Name of the theme to apply (dark, light, solarized, monokai)",
|
|
382
|
+
)
|
|
383
|
+
|
|
345
384
|
# ------------------------------------------------------------------ #
|
|
346
385
|
# Dispatch #
|
|
347
386
|
# ------------------------------------------------------------------ #
|
|
@@ -371,85 +410,99 @@ def main():
|
|
|
371
410
|
# Command dispatch #
|
|
372
411
|
# ------------------------------------------------------------------ #
|
|
373
412
|
if args.command == "create":
|
|
374
|
-
from cave_cli.
|
|
413
|
+
from cave_cli.commands.doctor import check_all
|
|
375
414
|
from cave_cli.commands.create import create
|
|
376
415
|
|
|
377
|
-
|
|
416
|
+
check_all()
|
|
378
417
|
create(args)
|
|
379
418
|
|
|
380
419
|
elif args.command == "run":
|
|
381
|
-
from cave_cli.
|
|
420
|
+
from cave_cli.commands.doctor import check_all
|
|
382
421
|
from cave_cli.commands.run import run
|
|
383
422
|
|
|
384
|
-
|
|
423
|
+
check_all()
|
|
385
424
|
run(args)
|
|
386
425
|
|
|
387
426
|
elif args.command == "reset":
|
|
388
|
-
from cave_cli.
|
|
427
|
+
from cave_cli.commands.doctor import check_all
|
|
389
428
|
from cave_cli.commands.reset import reset
|
|
390
429
|
|
|
391
|
-
|
|
430
|
+
check_all()
|
|
392
431
|
reset(args)
|
|
393
432
|
|
|
394
433
|
elif args.command == "upgrade":
|
|
395
|
-
from cave_cli.
|
|
434
|
+
from cave_cli.commands.doctor import check_all
|
|
396
435
|
from cave_cli.commands.upgrade import upgrade
|
|
397
436
|
|
|
398
|
-
|
|
437
|
+
check_all()
|
|
399
438
|
upgrade(args)
|
|
400
439
|
|
|
401
440
|
elif args.command == "sync":
|
|
402
|
-
from cave_cli.
|
|
441
|
+
from cave_cli.commands.doctor import check_all
|
|
403
442
|
from cave_cli.commands.sync_cmd import sync_cmd
|
|
404
443
|
|
|
405
|
-
|
|
444
|
+
check_all()
|
|
406
445
|
sync_cmd(args)
|
|
407
446
|
|
|
408
447
|
elif args.command == "test":
|
|
409
|
-
from cave_cli.
|
|
448
|
+
from cave_cli.commands.doctor import check_all
|
|
410
449
|
from cave_cli.commands.test import test
|
|
411
450
|
|
|
412
|
-
|
|
451
|
+
check_all()
|
|
413
452
|
test(args)
|
|
414
453
|
|
|
415
454
|
elif args.command == "prettify":
|
|
416
|
-
from cave_cli.
|
|
455
|
+
from cave_cli.commands.doctor import check_all
|
|
417
456
|
from cave_cli.commands.prettify import prettify
|
|
418
457
|
|
|
419
|
-
|
|
458
|
+
check_all()
|
|
420
459
|
prettify(args)
|
|
421
460
|
|
|
422
461
|
elif args.command == "list":
|
|
423
|
-
from cave_cli.
|
|
462
|
+
from cave_cli.commands.doctor import check_all
|
|
424
463
|
from cave_cli.commands.list_cmd import list_cmd
|
|
425
464
|
|
|
426
|
-
|
|
465
|
+
check_all()
|
|
427
466
|
list_cmd(args)
|
|
428
467
|
|
|
429
468
|
elif args.command == "kill":
|
|
430
|
-
from cave_cli.
|
|
469
|
+
from cave_cli.commands.doctor import check_all
|
|
431
470
|
from cave_cli.commands.kill import kill
|
|
432
471
|
|
|
433
|
-
|
|
472
|
+
check_all()
|
|
434
473
|
kill(args)
|
|
435
474
|
|
|
436
475
|
elif args.command == "purge":
|
|
437
|
-
from cave_cli.
|
|
476
|
+
from cave_cli.commands.doctor import check_all
|
|
438
477
|
from cave_cli.commands.purge import purge
|
|
439
478
|
|
|
440
|
-
|
|
479
|
+
check_all()
|
|
441
480
|
purge(args)
|
|
442
481
|
|
|
443
482
|
elif args.command == "list-versions":
|
|
483
|
+
from cave_cli.commands.doctor import check_all
|
|
444
484
|
from cave_cli.commands.list_versions import list_versions
|
|
445
485
|
|
|
486
|
+
check_all()
|
|
446
487
|
list_versions(args)
|
|
447
488
|
|
|
448
489
|
elif args.command == "update":
|
|
490
|
+
from cave_cli.commands.doctor import check_all
|
|
449
491
|
from cave_cli.commands.update import update
|
|
450
492
|
|
|
493
|
+
check_all()
|
|
451
494
|
update(args)
|
|
452
495
|
|
|
496
|
+
elif args.command == "doctor":
|
|
497
|
+
from cave_cli.commands.doctor import doctor
|
|
498
|
+
|
|
499
|
+
doctor(args)
|
|
500
|
+
|
|
501
|
+
elif args.command == "theme":
|
|
502
|
+
from cave_cli.commands.theme import theme_cmd
|
|
503
|
+
|
|
504
|
+
theme_cmd(args)
|
|
505
|
+
|
|
453
506
|
elif args.command == "uninstall":
|
|
454
507
|
from cave_cli.commands.uninstall import uninstall
|
|
455
508
|
|
|
@@ -8,6 +8,7 @@ from pathlib import Path
|
|
|
8
8
|
from cave_cli.commands.reset import reset
|
|
9
9
|
from cave_cli.commands.run import run_cave
|
|
10
10
|
from cave_cli.utils.constants import HTTPS_URL
|
|
11
|
+
from cave_cli.utils.display import print_section, step_done, step_fail, step_start
|
|
11
12
|
from cave_cli.utils.docker import build_image, check_docker, generate_secret_key
|
|
12
13
|
from cave_cli.utils.env import create_env_interactive
|
|
13
14
|
from cave_cli.utils.git import add, branch_rename, clone, commit, init
|
|
@@ -37,29 +38,31 @@ def create(args: argparse.Namespace) -> None:
|
|
|
37
38
|
clone_url = getattr(args, "url", None) or HTTPS_URL
|
|
38
39
|
version = getattr(args, "version", None)
|
|
39
40
|
|
|
40
|
-
|
|
41
|
-
logger.info("Downloading the app template...")
|
|
41
|
+
print_section("App Creation")
|
|
42
42
|
|
|
43
|
+
step_start("Downloading app template")
|
|
43
44
|
success = clone(clone_url, app_name, branch=version)
|
|
44
45
|
if not success or not os.path.isdir(app_name):
|
|
46
|
+
step_fail("Downloading app template")
|
|
45
47
|
logger.error("Clone failed. Ensure you used a valid version.")
|
|
46
48
|
logger.error(
|
|
47
49
|
f"The version must be a tag (or branch) listed at {clone_url}."
|
|
48
50
|
)
|
|
49
51
|
sys.exit(1)
|
|
50
|
-
|
|
51
|
-
logger.info("Done")
|
|
52
|
+
step_done("Downloading app template")
|
|
52
53
|
|
|
53
54
|
app_dir = os.path.abspath(app_name)
|
|
54
55
|
remove_licence_info(app_dir)
|
|
55
|
-
|
|
56
56
|
Path(os.path.join(app_dir, ".env")).touch()
|
|
57
57
|
|
|
58
58
|
example_env = os.path.join(app_dir, "example.env")
|
|
59
59
|
env_path = os.path.join(app_dir, ".env")
|
|
60
60
|
|
|
61
61
|
build_image(app_name, app_dir)
|
|
62
|
+
|
|
63
|
+
step_start("Generating secret key")
|
|
62
64
|
secret_key = generate_secret_key(app_name)
|
|
65
|
+
step_done("Generating secret key")
|
|
63
66
|
|
|
64
67
|
create_env_interactive(
|
|
65
68
|
app_name=app_name,
|
|
@@ -73,10 +76,11 @@ def create(args: argparse.Namespace) -> None:
|
|
|
73
76
|
verbose=getattr(args, "verbose", False),
|
|
74
77
|
loglevel=getattr(args, "loglevel", "INFO"),
|
|
75
78
|
)
|
|
76
|
-
reset(reset_args, app_dir=app_dir, app_name=app_name)
|
|
79
|
+
reset(reset_args, app_dir=app_dir, app_name=app_name, skip_build=True)
|
|
77
80
|
|
|
78
|
-
|
|
79
|
-
|
|
81
|
+
print_section("Version Control")
|
|
82
|
+
|
|
83
|
+
step_start("Configuring git repository")
|
|
80
84
|
git_dir = os.path.join(app_dir, ".git")
|
|
81
85
|
if os.path.isdir(git_dir):
|
|
82
86
|
rmtree_force(git_dir)
|
|
@@ -97,9 +101,9 @@ def create(args: argparse.Namespace) -> None:
|
|
|
97
101
|
add(app_dir)
|
|
98
102
|
commit(app_dir, "Initialize CAVE App")
|
|
99
103
|
branch_rename(app_dir, "main")
|
|
100
|
-
|
|
104
|
+
step_done("Configuring git repository")
|
|
101
105
|
|
|
102
|
-
|
|
106
|
+
step_start("Generating LLM docs")
|
|
103
107
|
docs_args = argparse.Namespace(
|
|
104
108
|
entrypoint="./utils/generate_docs.sh",
|
|
105
109
|
interactive=False,
|
|
@@ -110,15 +114,12 @@ def create(args: argparse.Namespace) -> None:
|
|
|
110
114
|
verbose=getattr(args, "verbose", False),
|
|
111
115
|
loglevel=getattr(args, "loglevel", "INFO"),
|
|
112
116
|
)
|
|
113
|
-
run_cave(app_dir, app_name, docs_args)
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
f"Created variables and additional configuration options "
|
|
120
|
-
f"are available in {app_name}/.env"
|
|
121
|
-
)
|
|
117
|
+
run_cave(app_dir, app_name, docs_args, skip_header=True, skip_build=True)
|
|
118
|
+
step_done("Generating LLM docs")
|
|
119
|
+
|
|
120
|
+
print_section("Done")
|
|
121
|
+
step_done(f"App '{app_name}' created successfully!")
|
|
122
|
+
step_done(f"Configuration options available in {app_name}/.env")
|
|
122
123
|
|
|
123
124
|
|
|
124
125
|
def force_remove(func, path, exc):
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
import sys
|
|
3
|
+
|
|
4
|
+
from cave_cli.utils.display import (
|
|
5
|
+
print_section,
|
|
6
|
+
step_done,
|
|
7
|
+
step_fail,
|
|
8
|
+
step_start,
|
|
9
|
+
)
|
|
10
|
+
from cave_cli.utils.logger import logger
|
|
11
|
+
from cave_cli.utils.subprocess import run, version_tuple
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def check_git() -> tuple[bool, str]:
|
|
15
|
+
"""
|
|
16
|
+
Usage:
|
|
17
|
+
|
|
18
|
+
- Validates that git is installed
|
|
19
|
+
|
|
20
|
+
Returns:
|
|
21
|
+
|
|
22
|
+
- ``success``: bool
|
|
23
|
+
- ``message``: str remediation or version
|
|
24
|
+
"""
|
|
25
|
+
try:
|
|
26
|
+
result = run(["git", "--version"])
|
|
27
|
+
if result.returncode == 0:
|
|
28
|
+
return True, result.stdout.strip()
|
|
29
|
+
except FileNotFoundError:
|
|
30
|
+
pass
|
|
31
|
+
return (
|
|
32
|
+
False,
|
|
33
|
+
"git is not installed. Please install git: https://git-scm.com/",
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def check_pipx() -> tuple[bool, str]:
|
|
38
|
+
"""
|
|
39
|
+
Usage:
|
|
40
|
+
|
|
41
|
+
- Validates that pipx is installed
|
|
42
|
+
|
|
43
|
+
Returns:
|
|
44
|
+
|
|
45
|
+
- ``success``: bool
|
|
46
|
+
- ``message``: str remediation or version
|
|
47
|
+
"""
|
|
48
|
+
import shutil
|
|
49
|
+
|
|
50
|
+
pipx = shutil.which("pipx")
|
|
51
|
+
if pipx:
|
|
52
|
+
try:
|
|
53
|
+
result = run([pipx, "--version"])
|
|
54
|
+
if result.returncode == 0:
|
|
55
|
+
return True, f"pipx version {result.stdout.strip()}"
|
|
56
|
+
except Exception:
|
|
57
|
+
pass
|
|
58
|
+
return (
|
|
59
|
+
False,
|
|
60
|
+
"pipx is not installed. Please install pipx: https://pipx.pypa.io/",
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def check_docker() -> tuple[bool, str]:
|
|
65
|
+
"""
|
|
66
|
+
Usage:
|
|
67
|
+
|
|
68
|
+
- Validates that Docker is installed, running, and meets the minimum version
|
|
69
|
+
|
|
70
|
+
Returns:
|
|
71
|
+
|
|
72
|
+
- ``success``: bool
|
|
73
|
+
- ``message``: str remediation or version
|
|
74
|
+
"""
|
|
75
|
+
from cave_cli.utils.constants import MIN_DOCKER_VERSION
|
|
76
|
+
|
|
77
|
+
try:
|
|
78
|
+
result = run(["docker", "--version"])
|
|
79
|
+
except FileNotFoundError:
|
|
80
|
+
return (
|
|
81
|
+
False,
|
|
82
|
+
f"Docker is not installed. "
|
|
83
|
+
f"Please install Docker version {MIN_DOCKER_VERSION} or greater: "
|
|
84
|
+
f"https://docs.docker.com/get-docker/",
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
if result.returncode != 0 or not result.stdout:
|
|
88
|
+
return (
|
|
89
|
+
False,
|
|
90
|
+
f"Could determine Docker version. "
|
|
91
|
+
f"Please install Docker version {MIN_DOCKER_VERSION} or greater.",
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
version_str = result.stdout.strip()
|
|
95
|
+
import re
|
|
96
|
+
|
|
97
|
+
match = re.search(r"(\d+\.\d+\.\d+)", version_str)
|
|
98
|
+
if not match:
|
|
99
|
+
return False, f"Could not parse Docker version from: {version_str}"
|
|
100
|
+
|
|
101
|
+
current = match.group(1)
|
|
102
|
+
if version_tuple(current) < version_tuple(MIN_DOCKER_VERSION):
|
|
103
|
+
return (
|
|
104
|
+
False,
|
|
105
|
+
f"Your current Docker version ({current}) is too old. "
|
|
106
|
+
f"Please install Docker version {MIN_DOCKER_VERSION} or greater.",
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
info_result = run(["docker", "info"])
|
|
110
|
+
if info_result.returncode != 0:
|
|
111
|
+
return False, "Docker is not running... Please start Docker."
|
|
112
|
+
|
|
113
|
+
return True, version_str
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def check_all(exit_on_fail: bool = True) -> dict[str, tuple[bool, str]]:
|
|
117
|
+
"""
|
|
118
|
+
Usage:
|
|
119
|
+
|
|
120
|
+
- Runs all environment checks
|
|
121
|
+
|
|
122
|
+
Optional:
|
|
123
|
+
|
|
124
|
+
- ``exit_on_fail``: bool - Exits the process if any check fails
|
|
125
|
+
"""
|
|
126
|
+
results = {
|
|
127
|
+
"Docker": check_docker(),
|
|
128
|
+
"Git": check_git(),
|
|
129
|
+
"Pipx": check_pipx(),
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if exit_on_fail:
|
|
133
|
+
failed = False
|
|
134
|
+
for name, (success, message) in results.items():
|
|
135
|
+
if not success:
|
|
136
|
+
logger.error(message)
|
|
137
|
+
failed = True
|
|
138
|
+
if failed:
|
|
139
|
+
sys.exit(1)
|
|
140
|
+
|
|
141
|
+
return results
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def doctor(args: argparse.Namespace) -> None:
|
|
145
|
+
"""
|
|
146
|
+
Usage:
|
|
147
|
+
|
|
148
|
+
- Checks the health of the CAVE environment (Docker, Git, Pipx)
|
|
149
|
+
"""
|
|
150
|
+
print_section("CAVE Doctor")
|
|
151
|
+
|
|
152
|
+
results = check_all(exit_on_fail=False)
|
|
153
|
+
|
|
154
|
+
all_pass = True
|
|
155
|
+
for name, (success, message) in results.items():
|
|
156
|
+
if success:
|
|
157
|
+
step_done(f"{name}: {message}")
|
|
158
|
+
else:
|
|
159
|
+
step_fail(f"{name}: {message}")
|
|
160
|
+
all_pass = False
|
|
161
|
+
|
|
162
|
+
print_section("Status")
|
|
163
|
+
if all_pass:
|
|
164
|
+
logger.success("Your environment is healthy and ready to CAVE!")
|
|
165
|
+
else:
|
|
166
|
+
logger.error(
|
|
167
|
+
"Some issues were found in your environment. "
|
|
168
|
+
"Please follow the remediation steps above."
|
|
169
|
+
)
|
|
170
|
+
sys.exit(1)
|