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.
@@ -1,5 +1,3 @@
1
- from __future__ import annotations
2
-
3
1
  from .base import Provider
4
2
  from .hugo import HugoProvider
5
3
  from .laravel import LaravelProvider
@@ -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
- CustomCommands,
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, custom_commands: CustomCommands):
30
+ def __init__(self, path: Path, config: StaticFileConfig):
26
31
  self.path = path
27
- self.custom_commands = custom_commands
28
- if (self.path / "Staticfile").exists():
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
- self.config = yaml.safe_load((self.path / "Staticfile").read_text())
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, custom_commands: CustomCommands
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 _exists(path, "index.html") and not _exists(
46
- path, "package.json", "pyproject.toml", "composer.json"
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 custom_commands.start and custom_commands.start.startswith(
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
- env_var="SHIPIT_SWS_VERSION",
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(app["build"])',
95
+ 'workdir(static_app.path)',
77
96
  'copy({}, ".", ignore=[".git"])'.format(
78
- json.dumps(self.config and self.config.get("root") or ".")
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(app["serve"], PORT)'
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("app")]
113
+ return [MountSpec("static_app")]
95
114
 
96
115
  def volumes(self) -> list[VolumeSpec]:
97
116
  return []
@@ -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
- CustomCommands,
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 WordPressProvider(PhpProvider):
21
- def __init__(self, path: Path, custom_commands: CustomCommands):
22
- super().__init__(path, custom_commands)
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, custom_commands: CustomCommands
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
- 'wp_cli_version = getenv("SHIPIT_WPCLI_VERSION")\n'
58
- "if wp_cli_version:\n"
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["build"]))',
67
- 'copy("wordpress/install.sh", "{}/setup-wp.sh".format(assets["build"]), base="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["build"]), base="assets")'
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["serve"], app["serve"])',
82
- "after_deploy": '"bash {}/setup-wp.sh".format(assets["serve"])',
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["serve"])',
92
+ serve_path='"{}/wp-content/".format(app.serve_path)',
94
93
  var_name="wp_content",
95
94
  )
96
95
  ]
@@ -0,0 +1,9 @@
1
+ from .base import Runner
2
+ from .local import LocalRunner
3
+ from .wasmer import WasmerRunner
4
+
5
+ __all__ = [
6
+ "Runner",
7
+ "LocalRunner",
8
+ "WasmerRunner",
9
+ ]
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: ...
@@ -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)