shipit-cli 0.20.2__tar.gz → 0.21.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.
- {shipit_cli-0.20.2 → shipit_cli-0.21.0}/PKG-INFO +1 -1
- {shipit_cli-0.20.2 → shipit_cli-0.21.0}/pyproject.toml +1 -1
- {shipit_cli-0.20.2 → shipit_cli-0.21.0}/src/shipit/assets/wordpress/install.sh +4 -1
- {shipit_cli-0.20.2 → shipit_cli-0.21.0}/src/shipit/builders/docker.py +9 -0
- {shipit_cli-0.20.2 → shipit_cli-0.21.0}/src/shipit/builders/local.py +25 -5
- {shipit_cli-0.20.2 → shipit_cli-0.21.0}/src/shipit/cli.py +292 -48
- {shipit_cli-0.20.2 → shipit_cli-0.21.0}/src/shipit/generator.py +15 -7
- {shipit_cli-0.20.2 → shipit_cli-0.21.0}/src/shipit/providers/base.py +23 -0
- {shipit_cli-0.20.2 → shipit_cli-0.21.0}/src/shipit/providers/go.py +47 -14
- shipit_cli-0.21.0/src/shipit/providers/install_context.py +635 -0
- {shipit_cli-0.20.2 → shipit_cli-0.21.0}/src/shipit/providers/node.py +130 -18
- {shipit_cli-0.20.2 → shipit_cli-0.21.0}/src/shipit/providers/node_static.py +5 -1
- {shipit_cli-0.20.2 → shipit_cli-0.21.0}/src/shipit/providers/python.py +72 -35
- {shipit_cli-0.20.2 → shipit_cli-0.21.0}/src/shipit/providers/staticfile.py +7 -3
- {shipit_cli-0.20.2 → shipit_cli-0.21.0}/src/shipit/runners/base.py +1 -0
- {shipit_cli-0.20.2 → shipit_cli-0.21.0}/src/shipit/runners/local.py +7 -1
- {shipit_cli-0.20.2 → shipit_cli-0.21.0}/src/shipit/runners/wasmer.py +18 -16
- shipit_cli-0.21.0/src/shipit/version.py +5 -0
- {shipit_cli-0.20.2 → shipit_cli-0.21.0}/tests/test_cli_after_deploy.py +70 -0
- {shipit_cli-0.20.2 → shipit_cli-0.21.0}/tests/test_generate_shipit_examples.py +21 -5
- shipit_cli-0.21.0/tests/test_install_context.py +233 -0
- {shipit_cli-0.20.2 → shipit_cli-0.21.0}/tests/test_node_provider.py +22 -0
- shipit_cli-0.21.0/tests/test_subdir.py +555 -0
- {shipit_cli-0.20.2 → shipit_cli-0.21.0}/tests/test_wasmer_annotations.py +27 -5
- shipit_cli-0.20.2/src/shipit/version.py +0 -5
- {shipit_cli-0.20.2 → shipit_cli-0.21.0}/.gitignore +0 -0
- {shipit_cli-0.20.2 → shipit_cli-0.21.0}/README.md +0 -0
- {shipit_cli-0.20.2 → shipit_cli-0.21.0}/src/shipit/__init__.py +0 -0
- {shipit_cli-0.20.2 → shipit_cli-0.21.0}/src/shipit/assets/node/optimize-node-modules.sh +0 -0
- {shipit_cli-0.20.2 → shipit_cli-0.21.0}/src/shipit/assets/php/php.ini +0 -0
- {shipit_cli-0.20.2 → shipit_cli-0.21.0}/src/shipit/assets/wordpress/.htaccess +0 -0
- {shipit_cli-0.20.2 → shipit_cli-0.21.0}/src/shipit/assets/wordpress/start.php +0 -0
- {shipit_cli-0.20.2 → shipit_cli-0.21.0}/src/shipit/assets/wordpress/wp-config.php +0 -0
- {shipit_cli-0.20.2 → shipit_cli-0.21.0}/src/shipit/builders/__init__.py +0 -0
- {shipit_cli-0.20.2 → shipit_cli-0.21.0}/src/shipit/builders/base.py +0 -0
- {shipit_cli-0.20.2 → shipit_cli-0.21.0}/src/shipit/procfile.py +0 -0
- {shipit_cli-0.20.2 → shipit_cli-0.21.0}/src/shipit/providers/hugo.py +0 -0
- {shipit_cli-0.20.2 → shipit_cli-0.21.0}/src/shipit/providers/jekyll.py +0 -0
- {shipit_cli-0.20.2 → shipit_cli-0.21.0}/src/shipit/providers/laravel.py +0 -0
- {shipit_cli-0.20.2 → shipit_cli-0.21.0}/src/shipit/providers/mkdocs.py +0 -0
- {shipit_cli-0.20.2 → shipit_cli-0.21.0}/src/shipit/providers/php.py +0 -0
- {shipit_cli-0.20.2 → shipit_cli-0.21.0}/src/shipit/providers/registry.py +0 -0
- {shipit_cli-0.20.2 → shipit_cli-0.21.0}/src/shipit/providers/wordpress.py +0 -0
- {shipit_cli-0.20.2 → shipit_cli-0.21.0}/src/shipit/runners/__init__.py +0 -0
- {shipit_cli-0.20.2 → shipit_cli-0.21.0}/src/shipit/shipit_types.py +0 -0
- {shipit_cli-0.20.2 → shipit_cli-0.21.0}/src/shipit/ui.py +0 -0
- {shipit_cli-0.20.2 → shipit_cli-0.21.0}/src/shipit/utils.py +0 -0
- {shipit_cli-0.20.2 → shipit_cli-0.21.0}/src/shipit/volumes.py +0 -0
- {shipit_cli-0.20.2 → shipit_cli-0.21.0}/tests/test_e2e.py +0 -0
- {shipit_cli-0.20.2 → shipit_cli-0.21.0}/tests/test_node_static_provider.py +0 -0
- {shipit_cli-0.20.2 → shipit_cli-0.21.0}/tests/test_php_provider.py +0 -0
- {shipit_cli-0.20.2 → shipit_cli-0.21.0}/tests/test_staticfile_provider.py +0 -0
- {shipit_cli-0.20.2 → shipit_cli-0.21.0}/tests/test_version.py +0 -0
- {shipit_cli-0.20.2 → shipit_cli-0.21.0}/tests/test_volumes.py +0 -0
- {shipit_cli-0.20.2 → shipit_cli-0.21.0}/tests/test_wordpress_phpix.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: shipit-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.21.0
|
|
4
4
|
Summary: Shipit CLI is the best way to build, serve and deploy your projects anywhere.
|
|
5
5
|
Project-URL: homepage, https://wasmer.io
|
|
6
6
|
Project-URL: repository, https://github.com/wasmerio/shipit
|
|
@@ -19,7 +19,10 @@ mkdir -p wp-content/upgrade
|
|
|
19
19
|
|
|
20
20
|
if [ -n "${WPCONTENT_BASE_PATH:-}" ] && [ -d "${WPCONTENT_BASE_PATH}" ]; then
|
|
21
21
|
shopt -s dotglob nullglob
|
|
22
|
-
|
|
22
|
+
# Note: change this back to copy all, once using the WP Zip files.
|
|
23
|
+
# cp -R "${WPCONTENT_BASE_PATH}"/* /app/wp-content || true
|
|
24
|
+
cp -R "${WPCONTENT_BASE_PATH}"/plugins/* /app/wp-content/plugins || true
|
|
25
|
+
cp -R "${WPCONTENT_BASE_PATH}"/themes/twentytwenty* /app/wp-content/themes || true
|
|
23
26
|
shopt -u dotglob nullglob
|
|
24
27
|
fi
|
|
25
28
|
|
|
@@ -162,6 +162,15 @@ RUN curl https://mise.run | sh
|
|
|
162
162
|
docker_file_contents += f"WORKDIR {step.path.absolute()}\n"
|
|
163
163
|
elif isinstance(step, RunStep):
|
|
164
164
|
if step.inputs:
|
|
165
|
+
parents = sorted(
|
|
166
|
+
{
|
|
167
|
+
Path(input).parent.as_posix()
|
|
168
|
+
for input in step.inputs
|
|
169
|
+
if Path(input).parent != Path(".")
|
|
170
|
+
}
|
|
171
|
+
)
|
|
172
|
+
for parent in parents:
|
|
173
|
+
docker_file_contents += f"RUN mkdir -p {parent}\n"
|
|
165
174
|
pre = "\\\n " + "".join(
|
|
166
175
|
[
|
|
167
176
|
f"--mount=type=bind,source={input},target={input} \\\n "
|
|
@@ -62,8 +62,14 @@ class LocalBuildBackend:
|
|
|
62
62
|
extra = ""
|
|
63
63
|
if step.inputs:
|
|
64
64
|
for input in step.inputs:
|
|
65
|
-
|
|
66
|
-
|
|
65
|
+
source = self.src_dir / input
|
|
66
|
+
target = build_path / input
|
|
67
|
+
console.print(f"Copying {input} to {target}")
|
|
68
|
+
target.parent.mkdir(parents=True, exist_ok=True)
|
|
69
|
+
if source.is_dir():
|
|
70
|
+
shutil.copytree(source, target, dirs_exist_ok=True)
|
|
71
|
+
else:
|
|
72
|
+
shutil.copy(source, target)
|
|
67
73
|
all_inputs = ", ".join(step.inputs)
|
|
68
74
|
extra = f" [bright_black]# using {all_inputs}[/bright_black]"
|
|
69
75
|
console.print(
|
|
@@ -113,11 +119,25 @@ class LocalBuildBackend:
|
|
|
113
119
|
raise Exception(f"Unknown base: {step.base}")
|
|
114
120
|
|
|
115
121
|
console.print(
|
|
116
|
-
|
|
122
|
+
"[bold]Copy to "
|
|
123
|
+
f"{step.target} from {step.source}[/bold]{ignore_extra}"
|
|
117
124
|
)
|
|
118
125
|
|
|
119
|
-
|
|
120
|
-
|
|
126
|
+
source_path = Path(step.source)
|
|
127
|
+
target_path = Path(step.target)
|
|
128
|
+
source = (
|
|
129
|
+
source_path
|
|
130
|
+
if source_path.is_absolute()
|
|
131
|
+
else base / source_path
|
|
132
|
+
)
|
|
133
|
+
target = (
|
|
134
|
+
target_path
|
|
135
|
+
if target_path.is_absolute()
|
|
136
|
+
else build_path / target_path
|
|
137
|
+
)
|
|
138
|
+
if source.resolve(strict=False) == target.resolve(strict=False):
|
|
139
|
+
return
|
|
140
|
+
target.parent.mkdir(parents=True, exist_ok=True)
|
|
121
141
|
if source.is_dir():
|
|
122
142
|
shutil.copytree(
|
|
123
143
|
source,
|
|
@@ -2,6 +2,7 @@ import tempfile
|
|
|
2
2
|
import os
|
|
3
3
|
import sys
|
|
4
4
|
import json
|
|
5
|
+
import re
|
|
5
6
|
from pathlib import Path
|
|
6
7
|
from dataclasses import dataclass
|
|
7
8
|
from typing import Any, Dict, List, Optional, Tuple, cast, Literal
|
|
@@ -57,6 +58,148 @@ class CtxMount:
|
|
|
57
58
|
serve_path: str
|
|
58
59
|
|
|
59
60
|
|
|
61
|
+
@dataclass(frozen=True)
|
|
62
|
+
class ProjectPaths:
|
|
63
|
+
workspace_root: Path
|
|
64
|
+
app_path: Path
|
|
65
|
+
subdir: Optional[str] = None
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def shipit_subdir_slug(subdir: str) -> str:
|
|
69
|
+
slug = re.sub(r"[^A-Za-z0-9._-]+", "-", subdir.replace("/", "-"))
|
|
70
|
+
return slug.strip("-") or "app"
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def default_shipit_path(project_paths: ProjectPaths) -> Path:
|
|
74
|
+
if project_paths.subdir is None:
|
|
75
|
+
return project_paths.workspace_root / "Shipit"
|
|
76
|
+
return (
|
|
77
|
+
project_paths.workspace_root
|
|
78
|
+
/ f"Shipit.{shipit_subdir_slug(project_paths.subdir)}"
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def resolve_project_paths(path: Path, subdir: Optional[Path] = None) -> ProjectPaths:
|
|
83
|
+
workspace_root = path.resolve()
|
|
84
|
+
if subdir is None:
|
|
85
|
+
return ProjectPaths(workspace_root, workspace_root)
|
|
86
|
+
|
|
87
|
+
if subdir.is_absolute():
|
|
88
|
+
raise ValueError("--subdir must be relative to the project path")
|
|
89
|
+
|
|
90
|
+
subdir_text = subdir.as_posix().strip("/")
|
|
91
|
+
if not subdir_text or subdir_text == ".":
|
|
92
|
+
return ProjectPaths(workspace_root, workspace_root)
|
|
93
|
+
|
|
94
|
+
app_path = (workspace_root / subdir_text).resolve()
|
|
95
|
+
try:
|
|
96
|
+
app_path.relative_to(workspace_root)
|
|
97
|
+
except ValueError:
|
|
98
|
+
raise ValueError("--subdir must stay inside the project path") from None
|
|
99
|
+
|
|
100
|
+
if not app_path.exists():
|
|
101
|
+
raise ValueError(f"--subdir does not exist: {subdir_text}")
|
|
102
|
+
if not app_path.is_dir():
|
|
103
|
+
raise ValueError(f"--subdir is not a directory: {subdir_text}")
|
|
104
|
+
|
|
105
|
+
normalized_subdir = app_path.relative_to(workspace_root).as_posix()
|
|
106
|
+
return ProjectPaths(workspace_root, app_path, normalized_subdir)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def read_shipit_subdir(shipit_file: Path) -> Optional[Path]:
|
|
110
|
+
if not shipit_file.exists():
|
|
111
|
+
return None
|
|
112
|
+
match = re.search(
|
|
113
|
+
r"^app_subdir\s*=\s*(\"(?:\\.|[^\"])*\")\s*$",
|
|
114
|
+
shipit_file.read_text(),
|
|
115
|
+
re.MULTILINE,
|
|
116
|
+
)
|
|
117
|
+
if not match:
|
|
118
|
+
return None
|
|
119
|
+
value = json.loads(match.group(1))
|
|
120
|
+
return Path(value) if value else None
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def load_env_files(
|
|
124
|
+
project_paths: ProjectPaths,
|
|
125
|
+
env_name: Optional[str],
|
|
126
|
+
target: Dict[str, str],
|
|
127
|
+
) -> None:
|
|
128
|
+
env_dirs = [project_paths.workspace_root]
|
|
129
|
+
if project_paths.subdir:
|
|
130
|
+
env_dirs.append(project_paths.app_path)
|
|
131
|
+
|
|
132
|
+
env_names = [".env"]
|
|
133
|
+
if env_name:
|
|
134
|
+
env_names.append(f".env.{env_name}")
|
|
135
|
+
|
|
136
|
+
for env_dir in env_dirs:
|
|
137
|
+
for env_file_name in env_names:
|
|
138
|
+
env_file = env_dir / env_file_name
|
|
139
|
+
if env_file.exists():
|
|
140
|
+
target.update(dotenv_values(env_file))
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def _rewrite_package_manager_command(
|
|
144
|
+
command: Optional[str],
|
|
145
|
+
old_manager: Any,
|
|
146
|
+
new_manager: Any,
|
|
147
|
+
) -> Optional[str]:
|
|
148
|
+
if not command:
|
|
149
|
+
return command
|
|
150
|
+
old_run = f"{old_manager.value} run "
|
|
151
|
+
if command.startswith(old_run):
|
|
152
|
+
return f"{new_manager.value} run {command[len(old_run):]}"
|
|
153
|
+
return command
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def apply_subdir_workspace_config(
|
|
157
|
+
project_paths: ProjectPaths,
|
|
158
|
+
provider_config: Any,
|
|
159
|
+
) -> None:
|
|
160
|
+
if not project_paths.subdir or not hasattr(provider_config, "package_manager"):
|
|
161
|
+
return
|
|
162
|
+
if not (project_paths.app_path / "package.json").exists():
|
|
163
|
+
return
|
|
164
|
+
|
|
165
|
+
from shipit.providers.node import NodeProvider, PackageManager
|
|
166
|
+
|
|
167
|
+
app_has_lockfile = any(
|
|
168
|
+
(project_paths.app_path / manager.lockfile()).exists()
|
|
169
|
+
for manager in PackageManager
|
|
170
|
+
)
|
|
171
|
+
if app_has_lockfile:
|
|
172
|
+
return
|
|
173
|
+
|
|
174
|
+
workspace_manager = NodeProvider.detect_package_manager(
|
|
175
|
+
project_paths.workspace_root
|
|
176
|
+
)
|
|
177
|
+
current_manager = provider_config.package_manager
|
|
178
|
+
if current_manager == workspace_manager:
|
|
179
|
+
return
|
|
180
|
+
|
|
181
|
+
provider_config.package_manager = workspace_manager
|
|
182
|
+
provider_config.build_command = _rewrite_package_manager_command(
|
|
183
|
+
getattr(provider_config, "build_command", None),
|
|
184
|
+
current_manager,
|
|
185
|
+
workspace_manager,
|
|
186
|
+
)
|
|
187
|
+
if provider_config.commands:
|
|
188
|
+
provider_config.commands.build = _rewrite_package_manager_command(
|
|
189
|
+
provider_config.commands.build,
|
|
190
|
+
current_manager,
|
|
191
|
+
workspace_manager,
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
def apply_subdir_provider_config(
|
|
196
|
+
project_paths: ProjectPaths,
|
|
197
|
+
provider_config: Any,
|
|
198
|
+
) -> None:
|
|
199
|
+
if hasattr(provider_config, "app_subdir"):
|
|
200
|
+
provider_config.app_subdir = project_paths.subdir
|
|
201
|
+
|
|
202
|
+
|
|
60
203
|
class Ctx:
|
|
61
204
|
def __init__(self, build_backend: BuildBackend, runner: Runner) -> None:
|
|
62
205
|
self.build_backend = build_backend
|
|
@@ -350,6 +493,11 @@ def auto(
|
|
|
350
493
|
help="Project path (defaults to current directory).",
|
|
351
494
|
show_default=False,
|
|
352
495
|
),
|
|
496
|
+
subdir: Optional[Path] = typer.Option(
|
|
497
|
+
None,
|
|
498
|
+
"--subdir",
|
|
499
|
+
help="App subdirectory relative to the project path.",
|
|
500
|
+
),
|
|
353
501
|
wasmer: bool = typer.Option(
|
|
354
502
|
False,
|
|
355
503
|
help="Use Wasmer to build and run the project.",
|
|
@@ -405,7 +553,7 @@ def auto(
|
|
|
405
553
|
),
|
|
406
554
|
shipit_path: Optional[Path] = typer.Option(
|
|
407
555
|
None,
|
|
408
|
-
help="The path to the Shipit file (defaults to Shipit
|
|
556
|
+
help="The path to the Shipit file (defaults to Shipit or Shipit.<subdir>).",
|
|
409
557
|
),
|
|
410
558
|
temp_shipit: bool = typer.Option(
|
|
411
559
|
False,
|
|
@@ -469,6 +617,7 @@ def auto(
|
|
|
469
617
|
|
|
470
618
|
if not path.exists():
|
|
471
619
|
raise Exception(f"The path {path} does not exist")
|
|
620
|
+
project_paths = resolve_project_paths(path, subdir)
|
|
472
621
|
|
|
473
622
|
if temp_shipit:
|
|
474
623
|
if shipit_path:
|
|
@@ -481,12 +630,13 @@ def auto(
|
|
|
481
630
|
if not regenerate:
|
|
482
631
|
if shipit_path and not shipit_path.exists():
|
|
483
632
|
regenerate = True
|
|
484
|
-
elif not
|
|
633
|
+
elif not shipit_path and not default_shipit_path(project_paths).exists():
|
|
485
634
|
regenerate = True
|
|
486
635
|
|
|
487
636
|
if regenerate:
|
|
488
637
|
generate(
|
|
489
|
-
|
|
638
|
+
project_paths.workspace_root,
|
|
639
|
+
subdir=Path(project_paths.subdir) if project_paths.subdir else None,
|
|
490
640
|
out=shipit_path,
|
|
491
641
|
install_command=install_command,
|
|
492
642
|
build_command=build_command,
|
|
@@ -496,7 +646,8 @@ def auto(
|
|
|
496
646
|
)
|
|
497
647
|
|
|
498
648
|
build(
|
|
499
|
-
|
|
649
|
+
project_paths.workspace_root,
|
|
650
|
+
subdir=Path(project_paths.subdir) if project_paths.subdir else None,
|
|
500
651
|
shipit_path=shipit_path,
|
|
501
652
|
install_command=install_command,
|
|
502
653
|
build_command=build_command,
|
|
@@ -521,7 +672,7 @@ def auto(
|
|
|
521
672
|
or after_deploy
|
|
522
673
|
):
|
|
523
674
|
run(
|
|
524
|
-
|
|
675
|
+
project_paths.workspace_root,
|
|
525
676
|
wasmer=wasmer,
|
|
526
677
|
wasmer_bin=wasmer_bin,
|
|
527
678
|
docker=docker,
|
|
@@ -532,11 +683,12 @@ def auto(
|
|
|
532
683
|
start=start,
|
|
533
684
|
after_deploy=after_deploy,
|
|
534
685
|
wasmer_registry=wasmer_registry,
|
|
686
|
+
serve_port=serve_port,
|
|
535
687
|
)
|
|
536
688
|
|
|
537
689
|
if wasmer_deploy or wasmer_deploy_config:
|
|
538
690
|
deploy(
|
|
539
|
-
|
|
691
|
+
project_paths.workspace_root,
|
|
540
692
|
wasmer_deploy=wasmer_deploy,
|
|
541
693
|
wasmer_deploy_config=wasmer_deploy_config,
|
|
542
694
|
wasmer_bin=wasmer_bin,
|
|
@@ -554,13 +706,18 @@ def generate(
|
|
|
554
706
|
help="Project path (defaults to current directory).",
|
|
555
707
|
show_default=False,
|
|
556
708
|
),
|
|
709
|
+
subdir: Optional[Path] = typer.Option(
|
|
710
|
+
None,
|
|
711
|
+
"--subdir",
|
|
712
|
+
help="App subdirectory relative to the project path.",
|
|
713
|
+
),
|
|
557
714
|
out: Optional[Path] = typer.Option(
|
|
558
715
|
None,
|
|
559
716
|
"-o",
|
|
560
717
|
"--out",
|
|
561
718
|
"--output",
|
|
562
719
|
"--shipit-path",
|
|
563
|
-
help="Output path (defaults to
|
|
720
|
+
help="Output path (defaults to Shipit or Shipit.<subdir>).",
|
|
564
721
|
),
|
|
565
722
|
install_command: Optional[str] = typer.Option(
|
|
566
723
|
None,
|
|
@@ -585,24 +742,38 @@ def generate(
|
|
|
585
742
|
):
|
|
586
743
|
if not path.exists():
|
|
587
744
|
raise Exception(f"The path {path} does not exist")
|
|
745
|
+
project_paths = resolve_project_paths(path, subdir)
|
|
588
746
|
|
|
589
747
|
if out is None:
|
|
590
|
-
out =
|
|
748
|
+
out = default_shipit_path(project_paths)
|
|
591
749
|
|
|
592
750
|
base_config = Config()
|
|
593
|
-
base_config.commands.enrich_from_path(
|
|
751
|
+
base_config.commands.enrich_from_path(project_paths.app_path)
|
|
594
752
|
if start_command:
|
|
595
753
|
base_config.commands.start = start_command
|
|
596
754
|
if install_command:
|
|
597
755
|
base_config.commands.install = install_command
|
|
598
756
|
if build_command:
|
|
599
757
|
base_config.commands.build = build_command
|
|
600
|
-
provider_cls = load_provider(
|
|
758
|
+
provider_cls = load_provider(
|
|
759
|
+
project_paths.app_path,
|
|
760
|
+
base_config,
|
|
761
|
+
use_provider=provider,
|
|
762
|
+
)
|
|
601
763
|
provider_config = load_provider_config(
|
|
602
|
-
provider_cls,
|
|
764
|
+
provider_cls,
|
|
765
|
+
project_paths.app_path,
|
|
766
|
+
base_config,
|
|
767
|
+
config=config,
|
|
768
|
+
)
|
|
769
|
+
apply_subdir_provider_config(project_paths, provider_config)
|
|
770
|
+
apply_subdir_workspace_config(project_paths, provider_config)
|
|
771
|
+
provider = provider_cls(project_paths.app_path, provider_config)
|
|
772
|
+
content = generate_shipit(
|
|
773
|
+
project_paths.app_path,
|
|
774
|
+
provider,
|
|
775
|
+
subdir=project_paths.subdir,
|
|
603
776
|
)
|
|
604
|
-
provider = provider_cls(path, provider_config)
|
|
605
|
-
content = generate_shipit(path, provider)
|
|
606
777
|
config_json = provider_config.model_dump_json(indent=2, exclude_defaults=True)
|
|
607
778
|
if config_json and config_json != "{}":
|
|
608
779
|
manifest_panel = Panel(
|
|
@@ -737,6 +908,10 @@ def run(
|
|
|
737
908
|
None,
|
|
738
909
|
help="Wasmer registry.",
|
|
739
910
|
),
|
|
911
|
+
serve_port: Optional[int] = typer.Option(
|
|
912
|
+
None,
|
|
913
|
+
help="The port to use (defaults to 8080).",
|
|
914
|
+
),
|
|
740
915
|
) -> None:
|
|
741
916
|
if not path.exists():
|
|
742
917
|
raise Exception(f"The path {path} does not exist")
|
|
@@ -765,7 +940,13 @@ def run(
|
|
|
765
940
|
)
|
|
766
941
|
|
|
767
942
|
if commands_to_run:
|
|
768
|
-
run_serve_commands(
|
|
943
|
+
run_serve_commands(
|
|
944
|
+
path,
|
|
945
|
+
runner,
|
|
946
|
+
commands_to_run,
|
|
947
|
+
volume_specs=volume_specs,
|
|
948
|
+
env=runtime_serve_env(serve_port),
|
|
949
|
+
)
|
|
769
950
|
else:
|
|
770
951
|
console.print("[bold]No commands specified. Use `--command` to run a command.[/bold]")
|
|
771
952
|
|
|
@@ -776,6 +957,11 @@ def plan(
|
|
|
776
957
|
help="Project path (defaults to current directory).",
|
|
777
958
|
show_default=False,
|
|
778
959
|
),
|
|
960
|
+
subdir: Optional[Path] = typer.Option(
|
|
961
|
+
None,
|
|
962
|
+
"--subdir",
|
|
963
|
+
help="App subdirectory relative to the project path.",
|
|
964
|
+
),
|
|
779
965
|
out: Optional[Path] = typer.Option(
|
|
780
966
|
None,
|
|
781
967
|
"-o",
|
|
@@ -793,7 +979,7 @@ def plan(
|
|
|
793
979
|
),
|
|
794
980
|
shipit_path: Optional[Path] = typer.Option(
|
|
795
981
|
None,
|
|
796
|
-
help="The path to the Shipit file (defaults to Shipit
|
|
982
|
+
help="The path to the Shipit file (defaults to Shipit or Shipit.<subdir>).",
|
|
797
983
|
),
|
|
798
984
|
wasmer: bool = typer.Option(
|
|
799
985
|
False,
|
|
@@ -846,6 +1032,7 @@ def plan(
|
|
|
846
1032
|
) -> None:
|
|
847
1033
|
if not path.exists():
|
|
848
1034
|
raise Exception(f"The path {path} does not exist")
|
|
1035
|
+
project_paths = resolve_project_paths(path, subdir)
|
|
849
1036
|
|
|
850
1037
|
if temp_shipit:
|
|
851
1038
|
if shipit_path:
|
|
@@ -858,12 +1045,13 @@ def plan(
|
|
|
858
1045
|
if not regenerate:
|
|
859
1046
|
if shipit_path and not shipit_path.exists():
|
|
860
1047
|
regenerate = True
|
|
861
|
-
elif not
|
|
1048
|
+
elif not shipit_path and not default_shipit_path(project_paths).exists():
|
|
862
1049
|
regenerate = True
|
|
863
1050
|
|
|
864
1051
|
if regenerate:
|
|
865
1052
|
generate(
|
|
866
|
-
|
|
1053
|
+
project_paths.workspace_root,
|
|
1054
|
+
subdir=Path(project_paths.subdir) if project_paths.subdir else None,
|
|
867
1055
|
out=shipit_path,
|
|
868
1056
|
install_command=install_command,
|
|
869
1057
|
build_command=build_command,
|
|
@@ -872,27 +1060,32 @@ def plan(
|
|
|
872
1060
|
config=config,
|
|
873
1061
|
)
|
|
874
1062
|
|
|
875
|
-
shipit_file = get_shipit_path(
|
|
1063
|
+
shipit_file = get_shipit_path(project_paths, shipit_path)
|
|
1064
|
+
if project_paths.subdir is None:
|
|
1065
|
+
project_paths = resolve_project_paths(
|
|
1066
|
+
project_paths.workspace_root,
|
|
1067
|
+
read_shipit_subdir(shipit_file),
|
|
1068
|
+
)
|
|
876
1069
|
|
|
877
1070
|
if docker or docker_client:
|
|
878
1071
|
build_backend: BuildBackend = DockerBuildBackend(
|
|
879
|
-
|
|
1072
|
+
project_paths.workspace_root, ASSETS_PATH, docker_client
|
|
880
1073
|
)
|
|
881
1074
|
else:
|
|
882
|
-
build_backend = LocalBuildBackend(
|
|
1075
|
+
build_backend = LocalBuildBackend(project_paths.workspace_root, ASSETS_PATH)
|
|
883
1076
|
if wasmer:
|
|
884
1077
|
runner: Runner = WasmerRunner(
|
|
885
1078
|
build_backend,
|
|
886
|
-
|
|
1079
|
+
project_paths.workspace_root,
|
|
887
1080
|
registry=wasmer_registry,
|
|
888
1081
|
token=wasmer_token,
|
|
889
1082
|
bin=wasmer_bin,
|
|
890
1083
|
)
|
|
891
1084
|
else:
|
|
892
|
-
runner = LocalRunner(build_backend,
|
|
1085
|
+
runner = LocalRunner(build_backend, project_paths.workspace_root)
|
|
893
1086
|
|
|
894
1087
|
base_config = Config()
|
|
895
|
-
base_config.commands.enrich_from_path(
|
|
1088
|
+
base_config.commands.enrich_from_path(project_paths.app_path)
|
|
896
1089
|
if install_command:
|
|
897
1090
|
base_config.commands.install = install_command
|
|
898
1091
|
if build_command:
|
|
@@ -901,10 +1094,19 @@ def plan(
|
|
|
901
1094
|
base_config.commands.start = start_command
|
|
902
1095
|
if serve_port:
|
|
903
1096
|
base_config.port = serve_port
|
|
904
|
-
provider_cls = load_provider(
|
|
1097
|
+
provider_cls = load_provider(
|
|
1098
|
+
project_paths.app_path,
|
|
1099
|
+
base_config,
|
|
1100
|
+
use_provider=provider,
|
|
1101
|
+
)
|
|
905
1102
|
provider_config = load_provider_config(
|
|
906
|
-
provider_cls,
|
|
1103
|
+
provider_cls,
|
|
1104
|
+
project_paths.app_path,
|
|
1105
|
+
base_config,
|
|
1106
|
+
config=config,
|
|
907
1107
|
)
|
|
1108
|
+
apply_subdir_provider_config(project_paths, provider_config)
|
|
1109
|
+
apply_subdir_workspace_config(project_paths, provider_config)
|
|
908
1110
|
# provider_config = runner.prepare_config(provider_config)
|
|
909
1111
|
ctx, serve = evaluate_shipit(shipit_file, build_backend, runner, provider_config)
|
|
910
1112
|
|
|
@@ -955,9 +1157,14 @@ def build(
|
|
|
955
1157
|
help="Project path (defaults to current directory).",
|
|
956
1158
|
show_default=False,
|
|
957
1159
|
),
|
|
1160
|
+
subdir: Optional[Path] = typer.Option(
|
|
1161
|
+
None,
|
|
1162
|
+
"--subdir",
|
|
1163
|
+
help="App subdirectory relative to the project path.",
|
|
1164
|
+
),
|
|
958
1165
|
shipit_path: Optional[Path] = typer.Option(
|
|
959
1166
|
None,
|
|
960
|
-
help="The path to the Shipit file (defaults to Shipit
|
|
1167
|
+
help="The path to the Shipit file (defaults to Shipit or Shipit.<subdir>).",
|
|
961
1168
|
),
|
|
962
1169
|
start_command: Optional[str] = typer.Option(
|
|
963
1170
|
None,
|
|
@@ -1027,27 +1234,39 @@ def build(
|
|
|
1027
1234
|
if not path.exists():
|
|
1028
1235
|
raise Exception(f"The path {path} does not exist")
|
|
1029
1236
|
|
|
1030
|
-
|
|
1237
|
+
project_paths = resolve_project_paths(
|
|
1238
|
+
path,
|
|
1239
|
+
subdir,
|
|
1240
|
+
)
|
|
1241
|
+
shipit_file = get_shipit_path(project_paths, shipit_path)
|
|
1242
|
+
if project_paths.subdir is None:
|
|
1243
|
+
project_paths = resolve_project_paths(
|
|
1244
|
+
path,
|
|
1245
|
+
read_shipit_subdir(shipit_file),
|
|
1246
|
+
)
|
|
1031
1247
|
|
|
1032
1248
|
if docker or docker_client:
|
|
1033
1249
|
build_backend: BuildBackend = DockerBuildBackend(
|
|
1034
|
-
|
|
1250
|
+
project_paths.workspace_root,
|
|
1251
|
+
ASSETS_PATH,
|
|
1252
|
+
docker_client,
|
|
1253
|
+
docker_opts=docker_opts,
|
|
1035
1254
|
)
|
|
1036
1255
|
else:
|
|
1037
|
-
build_backend = LocalBuildBackend(
|
|
1256
|
+
build_backend = LocalBuildBackend(project_paths.workspace_root, ASSETS_PATH)
|
|
1038
1257
|
if wasmer:
|
|
1039
1258
|
runner: Runner = WasmerRunner(
|
|
1040
1259
|
build_backend,
|
|
1041
|
-
|
|
1260
|
+
project_paths.workspace_root,
|
|
1042
1261
|
registry=wasmer_registry,
|
|
1043
1262
|
token=wasmer_token,
|
|
1044
1263
|
bin=wasmer_bin,
|
|
1045
1264
|
)
|
|
1046
1265
|
else:
|
|
1047
|
-
runner = LocalRunner(build_backend,
|
|
1266
|
+
runner = LocalRunner(build_backend, project_paths.workspace_root)
|
|
1048
1267
|
|
|
1049
1268
|
base_config = Config()
|
|
1050
|
-
base_config.commands.enrich_from_path(
|
|
1269
|
+
base_config.commands.enrich_from_path(project_paths.app_path)
|
|
1051
1270
|
if start_command:
|
|
1052
1271
|
base_config.commands.start = start_command
|
|
1053
1272
|
if install_command:
|
|
@@ -1058,10 +1277,19 @@ def build(
|
|
|
1058
1277
|
if serve_port:
|
|
1059
1278
|
base_config.port = serve_port
|
|
1060
1279
|
|
|
1061
|
-
provider_cls = load_provider(
|
|
1280
|
+
provider_cls = load_provider(
|
|
1281
|
+
project_paths.app_path,
|
|
1282
|
+
base_config,
|
|
1283
|
+
use_provider=provider,
|
|
1284
|
+
)
|
|
1062
1285
|
provider_config = load_provider_config(
|
|
1063
|
-
provider_cls,
|
|
1286
|
+
provider_cls,
|
|
1287
|
+
project_paths.app_path,
|
|
1288
|
+
base_config,
|
|
1289
|
+
config=config,
|
|
1064
1290
|
)
|
|
1291
|
+
apply_subdir_provider_config(project_paths, provider_config)
|
|
1292
|
+
apply_subdir_workspace_config(project_paths, provider_config)
|
|
1065
1293
|
provider_config = runner.prepare_config(provider_config)
|
|
1066
1294
|
ctx, serve = evaluate_shipit(shipit_file, build_backend, runner, provider_config)
|
|
1067
1295
|
env = {
|
|
@@ -1081,7 +1309,10 @@ def build(
|
|
|
1081
1309
|
f"[bold]ℹ️ Building locally instead of Docker to speed up the build, as all commands are safe to run locally[/bold]"
|
|
1082
1310
|
)
|
|
1083
1311
|
return build(
|
|
1084
|
-
|
|
1312
|
+
project_paths.workspace_root,
|
|
1313
|
+
subdir=Path(project_paths.subdir)
|
|
1314
|
+
if project_paths.subdir
|
|
1315
|
+
else None,
|
|
1085
1316
|
shipit_path=shipit_path,
|
|
1086
1317
|
install_command=install_command,
|
|
1087
1318
|
build_command=build_command,
|
|
@@ -1102,13 +1333,7 @@ def build(
|
|
|
1102
1333
|
)
|
|
1103
1334
|
|
|
1104
1335
|
serve.env = serve.env or {}
|
|
1105
|
-
|
|
1106
|
-
env_vars = dotenv_values(path / ".env")
|
|
1107
|
-
serve.env.update(env_vars)
|
|
1108
|
-
|
|
1109
|
-
if (path / f".env.{env_name}").exists():
|
|
1110
|
-
env_vars = dotenv_values(path / f".env.{env_name}")
|
|
1111
|
-
serve.env.update(env_vars)
|
|
1336
|
+
load_env_files(project_paths, env_name, serve.env)
|
|
1112
1337
|
|
|
1113
1338
|
assert serve.commands.get("start"), (
|
|
1114
1339
|
"No start command could be found, please provide a start command"
|
|
@@ -1119,23 +1344,29 @@ def build(
|
|
|
1119
1344
|
|
|
1120
1345
|
# Build and serve
|
|
1121
1346
|
build_backend.build(serve.name, env, serve.mounts or [], build_steps)
|
|
1122
|
-
build_volumes(
|
|
1347
|
+
build_volumes(project_paths.workspace_root, serve)
|
|
1123
1348
|
runner.build(serve)
|
|
1124
1349
|
if serve.prepare and not skip_prepare:
|
|
1125
1350
|
console.print("\n[bold]Running prepare step[/bold]")
|
|
1126
1351
|
runner.prepare(env, serve.prepare)
|
|
1127
1352
|
|
|
1128
1353
|
|
|
1129
|
-
def get_shipit_path(
|
|
1354
|
+
def get_shipit_path(
|
|
1355
|
+
project_paths: ProjectPaths,
|
|
1356
|
+
shipit_path: Optional[Path] = None,
|
|
1357
|
+
) -> Path:
|
|
1130
1358
|
if shipit_path is None:
|
|
1131
|
-
shipit_path =
|
|
1359
|
+
shipit_path = default_shipit_path(project_paths)
|
|
1132
1360
|
if not shipit_path.exists():
|
|
1361
|
+
command = f"shipit generate {project_paths.workspace_root}"
|
|
1362
|
+
if project_paths.subdir:
|
|
1363
|
+
command = f"{command} --subdir={project_paths.subdir}"
|
|
1133
1364
|
raise Exception(
|
|
1134
|
-
f"Shipit file not found at {shipit_path}. Run `
|
|
1365
|
+
f"Shipit file not found at {shipit_path}. Run `{command}` to create it."
|
|
1135
1366
|
)
|
|
1136
1367
|
elif not shipit_path.exists():
|
|
1137
1368
|
raise Exception(
|
|
1138
|
-
f"Shipit file not found at {shipit_path}. Run `shipit generate {
|
|
1369
|
+
f"Shipit file not found at {shipit_path}. Run `shipit generate {project_paths.workspace_root} -o {shipit_path}` to create it."
|
|
1139
1370
|
)
|
|
1140
1371
|
return shipit_path
|
|
1141
1372
|
|
|
@@ -1158,6 +1389,7 @@ def run_serve_commands(
|
|
|
1158
1389
|
runner: Runner,
|
|
1159
1390
|
commands: List[str],
|
|
1160
1391
|
volume_specs: Optional[List[str]] = None,
|
|
1392
|
+
env: Optional[Dict[str, str]] = None,
|
|
1161
1393
|
) -> None:
|
|
1162
1394
|
volume_mappings = merge_volume_mappings(
|
|
1163
1395
|
load_volume_mappings(path),
|
|
@@ -1167,7 +1399,19 @@ def run_serve_commands(
|
|
|
1167
1399
|
if command in OPTIONAL_RUN_COMMANDS and not runner.has_serve_command(command):
|
|
1168
1400
|
continue
|
|
1169
1401
|
console.print(f"\nRunning command [bold]{command}[/bold]")
|
|
1170
|
-
runner.run_serve_command(
|
|
1402
|
+
runner.run_serve_command(
|
|
1403
|
+
command,
|
|
1404
|
+
volume_mappings=volume_mappings,
|
|
1405
|
+
env=env,
|
|
1406
|
+
)
|
|
1407
|
+
|
|
1408
|
+
|
|
1409
|
+
def runtime_serve_env(serve_port: Optional[int]) -> Dict[str, str]:
|
|
1410
|
+
if serve_port is not None:
|
|
1411
|
+
port = str(serve_port)
|
|
1412
|
+
else:
|
|
1413
|
+
port = os.environ.get("PORT", "8080")
|
|
1414
|
+
return {"PORT": port}
|
|
1171
1415
|
|
|
1172
1416
|
def main() -> None:
|
|
1173
1417
|
args = sys.argv[1:]
|