shipit-cli 0.14.0__py3-none-any.whl → 0.15.0__py3-none-any.whl
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/builders/__init__.py +9 -0
- shipit/builders/base.py +14 -0
- shipit/builders/docker.py +250 -0
- shipit/builders/local.py +161 -0
- shipit/cli.py +288 -1322
- shipit/generator.py +54 -36
- shipit/procfile.py +4 -72
- shipit/providers/base.py +49 -10
- shipit/providers/hugo.py +62 -12
- shipit/providers/jekyll.py +48 -21
- shipit/providers/laravel.py +38 -29
- shipit/providers/mkdocs.py +33 -18
- shipit/providers/node_static.py +205 -139
- shipit/providers/php.py +41 -37
- shipit/providers/python.py +282 -226
- shipit/providers/registry.py +0 -2
- shipit/providers/staticfile.py +44 -25
- shipit/providers/wordpress.py +25 -26
- shipit/runners/__init__.py +9 -0
- shipit/runners/base.py +17 -0
- shipit/runners/local.py +105 -0
- shipit/runners/wasmer.py +470 -0
- shipit/shipit_types.py +103 -0
- shipit/ui.py +14 -0
- shipit/utils.py +10 -0
- shipit/version.py +2 -2
- {shipit_cli-0.14.0.dist-info → shipit_cli-0.15.0.dist-info}/METADATA +6 -3
- shipit_cli-0.15.0.dist-info/RECORD +34 -0
- {shipit_cli-0.14.0.dist-info → shipit_cli-0.15.0.dist-info}/WHEEL +1 -1
- shipit_cli-0.14.0.dist-info/RECORD +0 -23
- {shipit_cli-0.14.0.dist-info → shipit_cli-0.15.0.dist-info}/entry_points.txt +0 -0
shipit/providers/registry.py
CHANGED
shipit/providers/staticfile.py
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
1
|
from pathlib import Path
|
|
4
2
|
from typing import Dict, Optional
|
|
5
3
|
import json
|
|
6
4
|
import yaml
|
|
5
|
+
from pydantic_settings import SettingsConfigDict
|
|
7
6
|
|
|
8
7
|
from .base import (
|
|
9
8
|
DetectResult,
|
|
@@ -13,69 +12,89 @@ from .base import (
|
|
|
13
12
|
MountSpec,
|
|
14
13
|
ServiceSpec,
|
|
15
14
|
VolumeSpec,
|
|
16
|
-
|
|
15
|
+
Config,
|
|
17
16
|
)
|
|
18
17
|
|
|
19
18
|
|
|
19
|
+
class StaticFileConfig(Config):
|
|
20
|
+
model_config = SettingsConfigDict(extra="ignore", env_prefix="SHIPIT_")
|
|
21
|
+
|
|
22
|
+
sws_version: Optional[str] = "2.38.0"
|
|
23
|
+
static_dir: Optional[str] = None
|
|
24
|
+
|
|
25
|
+
|
|
20
26
|
class StaticFileProvider:
|
|
21
27
|
config: Optional[dict] = None
|
|
22
28
|
path: Path
|
|
23
|
-
custom_commands: CustomCommands
|
|
24
29
|
|
|
25
|
-
def __init__(self, path: Path,
|
|
30
|
+
def __init__(self, path: Path, config: StaticFileConfig):
|
|
26
31
|
self.path = path
|
|
27
|
-
self.
|
|
28
|
-
|
|
32
|
+
self.config = config
|
|
33
|
+
|
|
34
|
+
@classmethod
|
|
35
|
+
def load_config(
|
|
36
|
+
cls, path: Path, base_config: Config
|
|
37
|
+
) -> StaticFileConfig:
|
|
38
|
+
if (path / "Staticfile").exists():
|
|
39
|
+
config = None
|
|
29
40
|
try:
|
|
30
|
-
|
|
41
|
+
config = yaml.safe_load((path / "Staticfile").read_text())
|
|
31
42
|
except yaml.YAMLError as e:
|
|
32
43
|
print(f"Error loading Staticfile: {e}")
|
|
33
44
|
pass
|
|
34
45
|
|
|
46
|
+
if config:
|
|
47
|
+
return StaticFileConfig(
|
|
48
|
+
**base_config.model_dump(),
|
|
49
|
+
static_dir=config.get("root"),
|
|
50
|
+
)
|
|
51
|
+
if _exists(path, "public/index.html") or _exists(path, "public/index.htm"):
|
|
52
|
+
return StaticFileConfig(static_dir="public", **base_config.model_dump())
|
|
53
|
+
|
|
54
|
+
return StaticFileConfig(**base_config.model_dump())
|
|
55
|
+
|
|
35
56
|
@classmethod
|
|
36
57
|
def name(cls) -> str:
|
|
37
58
|
return "staticfile"
|
|
38
59
|
|
|
39
60
|
@classmethod
|
|
40
61
|
def detect(
|
|
41
|
-
cls, path: Path,
|
|
62
|
+
cls, path: Path, config: Config
|
|
42
63
|
) -> Optional[DetectResult]:
|
|
64
|
+
is_python_php_js_project = _exists(
|
|
65
|
+
path, "package.json", "pyproject.toml", "composer.json"
|
|
66
|
+
)
|
|
43
67
|
if _exists(path, "Staticfile"):
|
|
44
68
|
return DetectResult(cls.name(), 50)
|
|
45
|
-
if
|
|
46
|
-
|
|
47
|
-
|
|
69
|
+
if not is_python_php_js_project:
|
|
70
|
+
if _exists(
|
|
71
|
+
path, "index.html", "index.htm", "public/index.htm", "public/index.html"
|
|
72
|
+
):
|
|
73
|
+
return DetectResult(cls.name(), 10)
|
|
48
74
|
return DetectResult(cls.name(), 10)
|
|
49
|
-
if
|
|
75
|
+
if config.commands.start and config.commands.start.startswith(
|
|
50
76
|
"static-web-server "
|
|
51
77
|
):
|
|
52
78
|
return DetectResult(cls.name(), 70)
|
|
53
79
|
return None
|
|
54
80
|
|
|
55
|
-
def initialize(self) -> None:
|
|
56
|
-
pass
|
|
57
|
-
|
|
58
81
|
def serve_name(self) -> Optional[str]:
|
|
59
82
|
return None
|
|
60
83
|
|
|
61
|
-
def platform(self) -> Optional[str]:
|
|
62
|
-
return None
|
|
63
|
-
|
|
64
84
|
def dependencies(self) -> list[DependencySpec]:
|
|
65
85
|
return [
|
|
66
86
|
DependencySpec(
|
|
67
87
|
"static-web-server",
|
|
68
|
-
|
|
69
|
-
default_version="2.38.0",
|
|
88
|
+
var_name="config.sws_version",
|
|
70
89
|
use_in_serve=True,
|
|
71
90
|
)
|
|
72
91
|
]
|
|
73
92
|
|
|
74
93
|
def build_steps(self) -> list[str]:
|
|
75
94
|
return [
|
|
76
|
-
'workdir(
|
|
95
|
+
'workdir(static_app.path)',
|
|
77
96
|
'copy({}, ".", ignore=[".git"])'.format(
|
|
78
|
-
json.dumps(self.config
|
|
97
|
+
json.dumps(self.config.static_dir or ".")
|
|
79
98
|
),
|
|
80
99
|
]
|
|
81
100
|
|
|
@@ -87,11 +106,11 @@ class StaticFileProvider:
|
|
|
87
106
|
|
|
88
107
|
def commands(self) -> Dict[str, str]:
|
|
89
108
|
return {
|
|
90
|
-
"start": '"static-web-server --root={} --log-level=info --port={}".format(
|
|
109
|
+
"start": '"static-web-server --root={} --log-level=info --port={}".format(static_app.serve_path, PORT)'
|
|
91
110
|
}
|
|
92
111
|
|
|
93
112
|
def mounts(self) -> list[MountSpec]:
|
|
94
|
-
return [MountSpec("
|
|
113
|
+
return [MountSpec("static_app")]
|
|
95
114
|
|
|
96
115
|
def volumes(self) -> list[VolumeSpec]:
|
|
97
116
|
return []
|
shipit/providers/wordpress.py
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
from shipit.providers.php import PhpProvider
|
|
3
|
-
|
|
4
1
|
from pathlib import Path
|
|
5
2
|
from typing import Dict, Optional
|
|
6
3
|
|
|
@@ -12,22 +9,33 @@ from .base import (
|
|
|
12
9
|
MountSpec,
|
|
13
10
|
ServiceSpec,
|
|
14
11
|
VolumeSpec,
|
|
15
|
-
|
|
12
|
+
Config,
|
|
16
13
|
)
|
|
17
|
-
from .php import PhpProvider
|
|
14
|
+
from .php import PhpConfig, PhpProvider
|
|
15
|
+
from pydantic_settings import SettingsConfigDict
|
|
18
16
|
|
|
19
17
|
|
|
20
|
-
class
|
|
21
|
-
|
|
22
|
-
|
|
18
|
+
class WordPressConfig(PhpConfig):
|
|
19
|
+
model_config = SettingsConfigDict(extra="ignore", env_prefix="SHIPIT_")
|
|
20
|
+
|
|
21
|
+
wp_cli_version: Optional[str] = None
|
|
23
22
|
|
|
23
|
+
|
|
24
|
+
class WordPressProvider(PhpProvider):
|
|
24
25
|
@classmethod
|
|
25
26
|
def name(cls) -> str:
|
|
26
27
|
return "wordpress"
|
|
27
28
|
|
|
29
|
+
@classmethod
|
|
30
|
+
def load_config(
|
|
31
|
+
cls, path: Path, config: Config
|
|
32
|
+
) -> WordPressConfig:
|
|
33
|
+
php_config = super().load_config(path, config)
|
|
34
|
+
return WordPressConfig(**php_config.model_dump())
|
|
35
|
+
|
|
28
36
|
@classmethod
|
|
29
37
|
def detect(
|
|
30
|
-
cls, path: Path,
|
|
38
|
+
cls, path: Path, config: Config
|
|
31
39
|
) -> Optional[DetectResult]:
|
|
32
40
|
if (
|
|
33
41
|
_exists(path, "wp-content")
|
|
@@ -37,15 +45,9 @@ class WordPressProvider(PhpProvider):
|
|
|
37
45
|
return DetectResult(cls.name(), 80)
|
|
38
46
|
return None
|
|
39
47
|
|
|
40
|
-
def initialize(self) -> None:
|
|
41
|
-
pass
|
|
42
|
-
|
|
43
48
|
def serve_name(self) -> Optional[str]:
|
|
44
49
|
return None
|
|
45
50
|
|
|
46
|
-
def platform(self) -> Optional[str]:
|
|
47
|
-
return None
|
|
48
|
-
|
|
49
51
|
def dependencies(self) -> list[DependencySpec]:
|
|
50
52
|
return [
|
|
51
53
|
*super().dependencies(),
|
|
@@ -54,21 +56,18 @@ class WordPressProvider(PhpProvider):
|
|
|
54
56
|
|
|
55
57
|
def declarations(self) -> Optional[str]:
|
|
56
58
|
return (super().declarations() or "") + (
|
|
57
|
-
|
|
58
|
-
"if wp_cli_version
|
|
59
|
-
' wp_cli_download_url = f"https://github.com/wp-cli/wp-cli/releases/download/v{wp_cli_version}/wp-cli-{wp_cli_version}.phar"\n'
|
|
60
|
-
"else:\n"
|
|
61
|
-
' wp_cli_download_url = "https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar"\n'
|
|
59
|
+
"wp_cli_version = config.wp_cli_version\n"
|
|
60
|
+
'wp_cli_download_url = f"https://github.com/wp-cli/wp-cli/releases/download/v{wp_cli_version}/wp-cli-{wp_cli_version}.phar" if wp_cli_version else "https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar"\n'
|
|
62
61
|
)
|
|
63
62
|
|
|
64
63
|
def build_steps(self) -> list[str]:
|
|
65
64
|
steps = [
|
|
66
|
-
'copy(wp_cli_download_url, "{}/wp-cli.phar".format(assets
|
|
67
|
-
'copy("wordpress/install.sh", "{}/setup-wp.sh".format(assets
|
|
65
|
+
'copy(wp_cli_download_url, "{}/wp-cli.phar".format(assets.path))',
|
|
66
|
+
'copy("wordpress/install.sh", "{}/setup-wp.sh".format(assets.path), base="assets")',
|
|
68
67
|
]
|
|
69
68
|
if not _exists(self.path, "wp-config.php"):
|
|
70
69
|
steps.append(
|
|
71
|
-
'copy("wordpress/wp-config.php", "{}/wp-config.php".format(app
|
|
70
|
+
'copy("wordpress/wp-config.php", "{}/wp-config.php".format(app.path), base="assets")'
|
|
72
71
|
)
|
|
73
72
|
return steps + super().build_steps()
|
|
74
73
|
|
|
@@ -78,8 +77,8 @@ class WordPressProvider(PhpProvider):
|
|
|
78
77
|
def commands(self) -> Dict[str, str]:
|
|
79
78
|
commands = super().commands()
|
|
80
79
|
return {
|
|
81
|
-
# "wp": '"php {}/wp-cli.phar --allow-root --path={}".format(assets
|
|
82
|
-
"after_deploy": '"bash {}/setup-wp.sh".format(assets
|
|
80
|
+
# "wp": '"php {}/wp-cli.phar --allow-root --path={}".format(assets.serve_path, app.serve_path)',
|
|
81
|
+
"after_deploy": '"bash {}/setup-wp.sh".format(assets.serve_path)',
|
|
83
82
|
**commands,
|
|
84
83
|
}
|
|
85
84
|
|
|
@@ -90,7 +89,7 @@ class WordPressProvider(PhpProvider):
|
|
|
90
89
|
return [
|
|
91
90
|
VolumeSpec(
|
|
92
91
|
name="wp-content",
|
|
93
|
-
serve_path='"{}/wp-content/".format(app
|
|
92
|
+
serve_path='"{}/wp-content/".format(app.serve_path)',
|
|
94
93
|
var_name="wp_content",
|
|
95
94
|
)
|
|
96
95
|
]
|
shipit/runners/base.py
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
from typing import Dict, List, Protocol, TYPE_CHECKING
|
|
3
|
+
|
|
4
|
+
from shipit.builders.base import BuildBackend
|
|
5
|
+
|
|
6
|
+
if TYPE_CHECKING:
|
|
7
|
+
from shipit.shipit_types import PrepareStep, Serve
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Runner(Protocol):
|
|
11
|
+
build_backend: BuildBackend
|
|
12
|
+
|
|
13
|
+
def prepare_config(self, provider_config: object) -> object: ...
|
|
14
|
+
def build(self, serve: "Serve") -> None: ...
|
|
15
|
+
def prepare(self, env: Dict[str, str], prepare: List["PrepareStep"]) -> None: ...
|
|
16
|
+
def run_serve_command(self, command: str) -> None: ...
|
|
17
|
+
def get_serve_mount_path(self, name: str) -> Path: ...
|
shipit/runners/local.py
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import shutil
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from typing import Dict, List, Optional
|
|
4
|
+
|
|
5
|
+
import sh # type: ignore[import-untyped]
|
|
6
|
+
from rich import box
|
|
7
|
+
from rich.panel import Panel
|
|
8
|
+
from rich.syntax import Syntax
|
|
9
|
+
|
|
10
|
+
from shipit.builders.base import BuildBackend
|
|
11
|
+
from shipit.runners.base import Runner
|
|
12
|
+
from shipit.shipit_types import PrepareStep, Serve
|
|
13
|
+
from shipit.ui import console, write_stderr, write_stdout
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class LocalRunner:
|
|
17
|
+
def __init__(self, build_backend: BuildBackend, src_dir: Path) -> None:
|
|
18
|
+
self.build_backend = build_backend
|
|
19
|
+
self.src_dir = src_dir
|
|
20
|
+
self.runner_path = self.src_dir / ".shipit" / "runner" / "local"
|
|
21
|
+
self.serve_bin_path = self.runner_path / "serve" / "bin"
|
|
22
|
+
self.prepare_bash_script = self.runner_path / "prepare" / "prepare.sh"
|
|
23
|
+
|
|
24
|
+
def prepare_config(self, provider_config: object) -> object:
|
|
25
|
+
return provider_config
|
|
26
|
+
|
|
27
|
+
def get_serve_mount_path(self, name: str) -> Path:
|
|
28
|
+
return self.build_backend.get_artifact_mount_path(name)
|
|
29
|
+
|
|
30
|
+
def build(self, serve: Serve) -> None:
|
|
31
|
+
self.build_prepare(serve)
|
|
32
|
+
self.build_serve(serve)
|
|
33
|
+
|
|
34
|
+
def build_prepare(self, serve: Serve) -> None:
|
|
35
|
+
if not serve.prepare:
|
|
36
|
+
return
|
|
37
|
+
self.prepare_bash_script.parent.mkdir(parents=True, exist_ok=True)
|
|
38
|
+
commands: List[str] = []
|
|
39
|
+
if serve.cwd:
|
|
40
|
+
commands.append(f"cd {serve.cwd}")
|
|
41
|
+
if serve.prepare:
|
|
42
|
+
for step in serve.prepare:
|
|
43
|
+
commands.append(step.command)
|
|
44
|
+
content = "#!/bin/bash\n{body}".format(body="\n".join(commands))
|
|
45
|
+
console.print(
|
|
46
|
+
f"\n[bold]Created prepare.sh script to run before packaging ✅[/bold]"
|
|
47
|
+
)
|
|
48
|
+
manifest_panel = Panel(
|
|
49
|
+
Syntax(
|
|
50
|
+
content,
|
|
51
|
+
"bash",
|
|
52
|
+
theme="monokai",
|
|
53
|
+
background_color="default",
|
|
54
|
+
line_numbers=True,
|
|
55
|
+
),
|
|
56
|
+
box=box.SQUARE,
|
|
57
|
+
border_style="bright_black",
|
|
58
|
+
expand=False,
|
|
59
|
+
)
|
|
60
|
+
console.print(manifest_panel, markup=False, highlight=True)
|
|
61
|
+
self.prepare_bash_script.write_text(content)
|
|
62
|
+
self.prepare_bash_script.chmod(0o755)
|
|
63
|
+
|
|
64
|
+
def build_serve(self, serve: Serve) -> None:
|
|
65
|
+
console.print("\n[bold]Building serve[/bold]")
|
|
66
|
+
shutil.rmtree(self.serve_bin_path.parent, ignore_errors=True)
|
|
67
|
+
self.serve_bin_path.mkdir(parents=True, exist_ok=True)
|
|
68
|
+
runtime_path = self.build_backend.get_runtime_path() or ""
|
|
69
|
+
path_prefix = f"PATH={runtime_path}:$PATH " if runtime_path else ""
|
|
70
|
+
console.print(f"[bold]Serve Commands:[/bold]")
|
|
71
|
+
for command in serve.commands:
|
|
72
|
+
console.print(f"* {command}")
|
|
73
|
+
command_path = self.serve_bin_path / command
|
|
74
|
+
env_vars = ""
|
|
75
|
+
if serve.env:
|
|
76
|
+
env_vars = " ".join([f"{k}={v}" for k, v in serve.env.items()])
|
|
77
|
+
lines = ["#!/bin/bash"]
|
|
78
|
+
if serve.cwd:
|
|
79
|
+
lines.append(f"cd {serve.cwd}")
|
|
80
|
+
cmd_body = f"{path_prefix}{env_vars} {serve.commands[command]}".strip()
|
|
81
|
+
lines.append(cmd_body)
|
|
82
|
+
content = "\n".join(lines) + "\n"
|
|
83
|
+
command_path.write_text(content)
|
|
84
|
+
manifest_panel = Panel(
|
|
85
|
+
Syntax(
|
|
86
|
+
content.strip(),
|
|
87
|
+
"bash",
|
|
88
|
+
theme="monokai",
|
|
89
|
+
background_color="default",
|
|
90
|
+
line_numbers=True,
|
|
91
|
+
),
|
|
92
|
+
box=box.SQUARE,
|
|
93
|
+
border_style="bright_black",
|
|
94
|
+
expand=False,
|
|
95
|
+
)
|
|
96
|
+
console.print(manifest_panel, markup=False, highlight=True)
|
|
97
|
+
command_path.chmod(0o755)
|
|
98
|
+
|
|
99
|
+
def prepare(self, env: Dict[str, str], prepare: List[PrepareStep]) -> None:
|
|
100
|
+
sh.Command(str(self.prepare_bash_script))(_out=write_stdout, _err=write_stderr)
|
|
101
|
+
|
|
102
|
+
def run_serve_command(self, command: str) -> None:
|
|
103
|
+
console.print(f"\n[bold]Running {command} command[/bold]")
|
|
104
|
+
command_path = self.serve_bin_path / command
|
|
105
|
+
sh.Command(str(command_path))(_out=write_stdout, _err=write_stderr)
|