shipit-cli 0.5.2__tar.gz → 0.6.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.
Files changed (23) hide show
  1. {shipit_cli-0.5.2 → shipit_cli-0.6.0}/PKG-INFO +1 -1
  2. {shipit_cli-0.5.2 → shipit_cli-0.6.0}/pyproject.toml +1 -1
  3. {shipit_cli-0.5.2 → shipit_cli-0.6.0}/src/shipit/cli.py +82 -4
  4. {shipit_cli-0.5.2 → shipit_cli-0.6.0}/src/shipit/generator.py +10 -0
  5. {shipit_cli-0.5.2 → shipit_cli-0.6.0}/src/shipit/providers/base.py +9 -1
  6. {shipit_cli-0.5.2 → shipit_cli-0.6.0}/src/shipit/providers/gatsby.py +4 -1
  7. {shipit_cli-0.5.2 → shipit_cli-0.6.0}/src/shipit/providers/hugo.py +4 -1
  8. {shipit_cli-0.5.2 → shipit_cli-0.6.0}/src/shipit/providers/laravel.py +4 -1
  9. {shipit_cli-0.5.2 → shipit_cli-0.6.0}/src/shipit/providers/mkdocs.py +4 -1
  10. {shipit_cli-0.5.2 → shipit_cli-0.6.0}/src/shipit/providers/node_static.py +4 -1
  11. {shipit_cli-0.5.2 → shipit_cli-0.6.0}/src/shipit/providers/php.py +4 -1
  12. {shipit_cli-0.5.2 → shipit_cli-0.6.0}/src/shipit/providers/python.py +18 -1
  13. {shipit_cli-0.5.2 → shipit_cli-0.6.0}/src/shipit/providers/staticfile.py +4 -1
  14. shipit_cli-0.6.0/src/shipit/version.py +5 -0
  15. shipit_cli-0.5.2/src/shipit/version.py +0 -5
  16. {shipit_cli-0.5.2 → shipit_cli-0.6.0}/.gitignore +0 -0
  17. {shipit_cli-0.5.2 → shipit_cli-0.6.0}/README.md +0 -0
  18. {shipit_cli-0.5.2 → shipit_cli-0.6.0}/src/shipit/__init__.py +0 -0
  19. {shipit_cli-0.5.2 → shipit_cli-0.6.0}/src/shipit/assets/php/php.ini +0 -0
  20. {shipit_cli-0.5.2 → shipit_cli-0.6.0}/src/shipit/providers/registry.py +0 -0
  21. {shipit_cli-0.5.2 → shipit_cli-0.6.0}/tests/test_examples_build.py +0 -0
  22. {shipit_cli-0.5.2 → shipit_cli-0.6.0}/tests/test_generate_shipit_examples.py +0 -0
  23. {shipit_cli-0.5.2 → shipit_cli-0.6.0}/tests/test_version.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: shipit-cli
3
- Version: 0.5.2
3
+ Version: 0.6.0
4
4
  Summary: Add your description here
5
5
  Project-URL: homepage, https://wasmer.io
6
6
  Project-URL: repository, https://github.com/wasmerio/shipit
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "shipit-cli"
3
- version = "0.5.2"
3
+ version = "0.6.0"
4
4
  description = "Add your description here"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
@@ -16,6 +16,7 @@ from typing import (
16
16
  Set,
17
17
  TypedDict,
18
18
  Union,
19
+ Literal,
19
20
  cast,
20
21
  )
21
22
  from shutil import copy, copytree, ignore_patterns
@@ -48,6 +49,12 @@ class Mount:
48
49
  serve_path: Path
49
50
 
50
51
 
52
+ @dataclass
53
+ class Service:
54
+ name: str
55
+ provider: Literal["postgres", "mysql", "redis"] # Right now we only support postgres and mysql
56
+
57
+
51
58
  @dataclass
52
59
  class Serve:
53
60
  name: str
@@ -61,6 +68,7 @@ class Serve:
61
68
  workers: Optional[List[str]] = None
62
69
  mounts: Optional[List[Mount]] = None
63
70
  env: Optional[Dict[str, str]] = None
71
+ services: Optional[List[Service]] = None
64
72
 
65
73
 
66
74
  @dataclass
@@ -624,20 +632,31 @@ class LocalBuilder:
624
632
 
625
633
  def build_serve(self, serve: Serve) -> None:
626
634
  console.print("\n[bold]Building serve[/bold]")
627
- build_path = self.get_build_path()
628
635
  serve_command_path = self.get_serve_path() / "bin"
629
636
  serve_command_path.mkdir(parents=True, exist_ok=False)
630
637
  path = self.get_path() / ".path"
631
- # path_resolved = [str((build_path/path).resolve()) for path in path.read_text().split(os.pathsep) if path]
632
- # path_text = os.pathsep.join(path_resolved)
633
638
  path_text = path.read_text()
634
639
  console.print(f"[bold]Serve Commands:[/bold]")
635
640
  for command in serve.commands:
636
641
  console.print(f"* {command}")
637
642
  command_path = serve_command_path / command
643
+ content = f"#!/bin/bash\ncd {serve.cwd}\nPATH={path_text}:$PATH {serve.commands[command]}"
638
644
  command_path.write_text(
639
- f"#!/bin/bash\ncd {build_path}\nPATH={path_text}:$PATH {serve.commands[command]}"
645
+ content
640
646
  )
647
+ manifest_panel = Panel(
648
+ Syntax(
649
+ content.strip(),
650
+ "bash",
651
+ theme="monokai",
652
+ background_color="default",
653
+ line_numbers=True,
654
+ ),
655
+ box=box.SQUARE,
656
+ border_style="bright_black",
657
+ expand=False,
658
+ )
659
+ console.print(manifest_panel, markup=False, highlight=True)
641
660
  command_path.chmod(0o755)
642
661
 
643
662
  def run_serve_command(self, command: str) -> None:
@@ -686,6 +705,13 @@ class WasmerBuilder:
686
705
  },
687
706
  "scripts": {"pandoc"},
688
707
  },
708
+ "ffmpeg": {
709
+ "dependencies": {
710
+ "latest": "wasmer/ffmpeg@=1.0.5",
711
+ "N-111519": "wasmer/ffmpeg@=1.0.5",
712
+ },
713
+ "scripts": {"ffmpeg"},
714
+ },
689
715
  "php": {
690
716
  "dependencies": {
691
717
  "latest": "php/php-32@=8.3.2104",
@@ -943,8 +969,46 @@ class WasmerBuilder:
943
969
  }
944
970
  # Update the app to use the new package
945
971
  yaml_config["package"] = "."
972
+ if serve.services:
973
+ capabilities = yaml_config.get("capabilities", {})
974
+ has_mysql = any(service.provider == "mysql" for service in serve.services)
975
+ # has_postgres = any(service.provider == "postgres" for service in serve.services)
976
+ # has_redis = any(service.provider == "redis" for service in serve.services)
977
+ if has_mysql:
978
+ capabilities["database"] = {
979
+ "engine": "mysql"
980
+ }
981
+ yaml_config["capabilities"] = capabilities
982
+
983
+ if "after_deploy" in serve.commands:
984
+ jobs = yaml_config.get("jobs", [])
985
+ jobs.append({
986
+ "name": "after_deploy",
987
+ "trigger": "post-deployment",
988
+ "action": {
989
+ "execute": {
990
+ "command": "after_deploy"
991
+ }
992
+ }
993
+ })
994
+ yaml_config["jobs"] = jobs
946
995
 
947
996
  app_yaml = yaml.dump(yaml_config)
997
+
998
+ console.print(f"\n[bold]Created app.yaml manifest ✅[/bold]")
999
+ app_yaml_panel = Panel(
1000
+ Syntax(
1001
+ app_yaml.strip(),
1002
+ "yaml",
1003
+ theme="monokai",
1004
+ background_color="default",
1005
+ line_numbers=True,
1006
+ ),
1007
+ box=box.SQUARE,
1008
+ border_style="bright_black",
1009
+ expand=False,
1010
+ )
1011
+ console.print(app_yaml_panel, markup=False, highlight=True)
948
1012
  (self.wasmer_dir_path / "app.yaml").write_text(app_yaml)
949
1013
 
950
1014
  # self.inner_builder.build_serve(serve)
@@ -1026,12 +1090,17 @@ class Ctx:
1026
1090
  self.steps: List[Step] = []
1027
1091
  self.serves: Dict[str, Serve] = {}
1028
1092
  self.mounts: List[Mount] = []
1093
+ self.services: Dict[str, Service] = {}
1029
1094
 
1030
1095
  def add_package(self, package: Package) -> str:
1031
1096
  index = f"{package.name}@{package.version}" if package.version else package.name
1032
1097
  self.packages[index] = package
1033
1098
  return f"ref:package:{index}"
1034
1099
 
1100
+ def add_service(self, service: Service) -> str:
1101
+ self.services[service.name] = service
1102
+ return f"ref:service:{service.name}"
1103
+
1035
1104
  def get_ref(self, index: str) -> Any:
1036
1105
  if index.startswith("ref:package:"):
1037
1106
  return self.packages[index[len("ref:package:") :]]
@@ -1043,6 +1112,8 @@ class Ctx:
1043
1112
  return self.steps[int(index[len("ref:step:") :])]
1044
1113
  elif index.startswith("ref:mount:"):
1045
1114
  return self.mounts[int(index[len("ref:mount:") :])]
1115
+ elif index.startswith("ref:service:"):
1116
+ return self.services[index[len("ref:service:") :]]
1046
1117
  else:
1047
1118
  raise Exception(f"Invalid reference: {index}")
1048
1119
 
@@ -1072,6 +1143,10 @@ class Ctx:
1072
1143
  def dep(self, name: str, version: Optional[str] = None) -> str:
1073
1144
  package = Package(name, version)
1074
1145
  return self.add_package(package)
1146
+
1147
+ def service(self, name: str, provider: Literal["postgres", "mysql", "redis"]) -> str:
1148
+ service = Service(name, provider)
1149
+ return self.add_service(service)
1075
1150
 
1076
1151
  def serve(
1077
1152
  self,
@@ -1086,6 +1161,7 @@ class Ctx:
1086
1161
  workers: Optional[List[str]] = None,
1087
1162
  mounts: Optional[List[Mount]] = None,
1088
1163
  env: Optional[Dict[str, str]] = None,
1164
+ services: Optional[List[str]] = None,
1089
1165
  ) -> str:
1090
1166
  build_refs = [cast(Step, r) for r in self.get_refs(build)]
1091
1167
  prepare_steps: Optional[List[PrepareStep]] = None
@@ -1110,6 +1186,7 @@ class Ctx:
1110
1186
  if mounts
1111
1187
  else None,
1112
1188
  env=env,
1189
+ services=self.get_refs(services) if services else None,
1113
1190
  )
1114
1191
  return self.add_serve(serve)
1115
1192
 
@@ -1435,6 +1512,7 @@ def build(
1435
1512
  glb = sl.Globals.standard()
1436
1513
  mod = sl.Module()
1437
1514
 
1515
+ mod.add_callable("service", ctx.service)
1438
1516
  mod.add_callable("getenv", ctx.getenv)
1439
1517
  mod.add_callable("dep", ctx.dep)
1440
1518
  mod.add_callable("serve", ctx.serve)
@@ -89,6 +89,7 @@ def generate_shipit(path: Path) -> str:
89
89
  dependencies=provider.dependencies(),
90
90
  build_steps=provider.build_steps(),
91
91
  prepare=provider.prepare_steps(),
92
+ services=provider.services(),
92
93
  commands=provider.commands(),
93
94
  env=provider.env(),
94
95
  )
@@ -127,6 +128,10 @@ def generate_shipit(path: Path) -> str:
127
128
  out.append("")
128
129
  for m in plan.mounts:
129
130
  out.append(f"{m.name} = mount(\"{m.name}\")")
131
+ if plan.services:
132
+ for s in plan.services:
133
+ out.append(f"{s.name} = service(\n name=\"{s.name}\",\n provider=\"{s.provider}\"\n)")
134
+
130
135
  if plan.declarations:
131
136
  out.append(plan.declarations)
132
137
  out.append("")
@@ -157,6 +162,11 @@ def generate_shipit(path: Path) -> str:
157
162
  out.append(" commands = {")
158
163
  out.append(commands_lines)
159
164
  out.append(" },")
165
+ if plan.services:
166
+ out.append(" services=[")
167
+ for s in plan.services:
168
+ out.append(f" {s.name},")
169
+ out.append(" ],")
160
170
  if mounts_block:
161
171
  out.append(" mounts=[")
162
172
  out.append(mounts_block)
@@ -2,7 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  from dataclasses import dataclass, field
4
4
  from pathlib import Path
5
- from typing import Dict, List, Optional, Protocol
5
+ from typing import Dict, List, Optional, Protocol, Literal
6
6
 
7
7
 
8
8
  @dataclass
@@ -28,6 +28,7 @@ class Provider(Protocol):
28
28
  def prepare_steps(self) -> Optional[List[str]]: ...
29
29
  def commands(self) -> Dict[str, str]: ...
30
30
  def assets(self) -> Optional[Dict[str, str]]: ...
31
+ def services(self) -> List["ServiceSpec"]: ...
31
32
  def mounts(self) -> List["MountSpec"]: ...
32
33
  def env(self) -> Optional[Dict[str, str]]: ...
33
34
 
@@ -49,6 +50,12 @@ class MountSpec:
49
50
  attach_to_serve: bool = True
50
51
 
51
52
 
53
+ @dataclass
54
+ class ServiceSpec:
55
+ name: str
56
+ provider: Literal["postgres", "mysql", "redis"]
57
+
58
+
52
59
  @dataclass
53
60
  class ProviderPlan:
54
61
  serve_name: str
@@ -58,6 +65,7 @@ class ProviderPlan:
58
65
  dependencies: List[DependencySpec] = field(default_factory=list)
59
66
  build_steps: List[str] = field(default_factory=list)
60
67
  prepare: Optional[List[str]] = None
68
+ services: List[ServiceSpec] = field(default_factory=list)
61
69
  commands: Dict[str, str] = field(default_factory=dict)
62
70
  assets: Optional[Dict[str, str]] = None
63
71
  env: Optional[Dict[str, str]] = None
@@ -3,7 +3,7 @@ from __future__ import annotations
3
3
  from pathlib import Path
4
4
  from typing import Dict, Optional
5
5
 
6
- from .base import DetectResult, DependencySpec, Provider, _exists, _has_dependency, MountSpec
6
+ from .base import DetectResult, DependencySpec, Provider, _exists, _has_dependency, MountSpec, ServiceSpec
7
7
 
8
8
 
9
9
  class GatsbyProvider:
@@ -70,3 +70,6 @@ class GatsbyProvider:
70
70
 
71
71
  def env(self) -> Optional[Dict[str, str]]:
72
72
  return None
73
+
74
+ def services(self) -> list[ServiceSpec]:
75
+ return []
@@ -3,7 +3,7 @@ from __future__ import annotations
3
3
  from pathlib import Path
4
4
  from typing import Dict, Optional
5
5
 
6
- from .base import DetectResult, DependencySpec, Provider, _exists
6
+ from .base import DetectResult, DependencySpec, Provider, _exists, ServiceSpec
7
7
  from .staticfile import StaticFileProvider
8
8
 
9
9
  class HugoProvider(StaticFileProvider):
@@ -45,3 +45,6 @@ class HugoProvider(StaticFileProvider):
45
45
  'copy(".", ".", ignore=[".git"])',
46
46
  'run("hugo build --destination={}".format(app["build"]), group="build")',
47
47
  ]
48
+
49
+ def services(self) -> list[ServiceSpec]:
50
+ return []
@@ -3,7 +3,7 @@ from __future__ import annotations
3
3
  from pathlib import Path
4
4
  from typing import Dict, Optional
5
5
 
6
- from .base import DetectResult, DependencySpec, Provider, _exists, MountSpec
6
+ from .base import DetectResult, DependencySpec, Provider, _exists, MountSpec, ServiceSpec
7
7
 
8
8
 
9
9
  class LaravelProvider:
@@ -81,3 +81,6 @@ class LaravelProvider:
81
81
 
82
82
  def env(self) -> Optional[Dict[str, str]]:
83
83
  return None
84
+
85
+ def services(self) -> list[ServiceSpec]:
86
+ return []
@@ -3,7 +3,7 @@ from __future__ import annotations
3
3
  from pathlib import Path
4
4
  from typing import Dict, Optional
5
5
 
6
- from .base import DetectResult, DependencySpec, Provider, _exists, MountSpec
6
+ from .base import DetectResult, DependencySpec, Provider, _exists, MountSpec, ServiceSpec
7
7
  from .staticfile import StaticFileProvider
8
8
  from .python import PythonProvider
9
9
 
@@ -58,3 +58,6 @@ class MkdocsProvider(StaticFileProvider):
58
58
 
59
59
  def env(self) -> Optional[Dict[str, str]]:
60
60
  return self.python_provider.env()
61
+
62
+ def services(self) -> list[ServiceSpec]:
63
+ return []
@@ -3,7 +3,7 @@ from __future__ import annotations
3
3
  from pathlib import Path
4
4
  from typing import Dict, Optional
5
5
 
6
- from .base import DetectResult, DependencySpec, Provider, _exists, _has_dependency, MountSpec
6
+ from .base import DetectResult, DependencySpec, Provider, _exists, _has_dependency, MountSpec, ServiceSpec
7
7
 
8
8
 
9
9
  class NodeStaticProvider:
@@ -71,3 +71,6 @@ class NodeStaticProvider:
71
71
 
72
72
  def env(self) -> Optional[Dict[str, str]]:
73
73
  return None
74
+
75
+ def services(self) -> list[ServiceSpec]:
76
+ return []
@@ -3,7 +3,7 @@ from __future__ import annotations
3
3
  from pathlib import Path
4
4
  from typing import Dict, Optional
5
5
 
6
- from .base import DetectResult, DependencySpec, Provider, _exists, MountSpec
6
+ from .base import DetectResult, DependencySpec, Provider, _exists, MountSpec, ServiceSpec
7
7
 
8
8
 
9
9
  class PhpProvider:
@@ -80,3 +80,6 @@ class PhpProvider:
80
80
 
81
81
  def env(self) -> Optional[Dict[str, str]]:
82
82
  return None
83
+
84
+ def services(self) -> list[ServiceSpec]:
85
+ return []
@@ -11,6 +11,7 @@ from .base import (
11
11
  Provider,
12
12
  _exists,
13
13
  MountSpec,
14
+ ServiceSpec,
14
15
  )
15
16
 
16
17
 
@@ -74,7 +75,7 @@ class PythonProvider:
74
75
  "psycopg-binary",
75
76
  "psycopg2-binary",
76
77
  }
77
- mysql_deps = {"mysqlclient", "pymysql", "mysql-connector-python", "aiomysql"}
78
+ mysql_deps = {"mysqlclient", "pymysql", "mysql-connector-python", "aiomysql", "asyncmy"}
78
79
  found_deps = self.check_deps(
79
80
  "file://", # This is not really a dependency, but as a way to check if the install script requires all files
80
81
  "streamlit",
@@ -238,6 +239,15 @@ class PythonProvider:
238
239
  use_in_serve=True,
239
240
  )
240
241
  )
242
+ if self.uses_ffmpeg:
243
+ deps.append(
244
+ DependencySpec(
245
+ "ffmpeg",
246
+ env_var="SHIPIT_FFMPEG_VERSION",
247
+ use_in_build=False,
248
+ use_in_serve=True,
249
+ )
250
+ )
241
251
  return deps
242
252
 
243
253
  def declarations(self) -> Optional[str]:
@@ -438,6 +448,13 @@ class PythonProvider:
438
448
  env_vars["FASTMCP_HOST"] = '"0.0.0.0"'
439
449
  env_vars["FASTMCP_PORT"] = '"8000"'
440
450
  return env_vars
451
+
452
+ def services(self) -> list[ServiceSpec]:
453
+ if self.database == DatabaseType.MySQL:
454
+ return [ServiceSpec(name="database", provider="mysql")]
455
+ elif self.database == DatabaseType.PostgreSQL:
456
+ return [ServiceSpec(name="database", provider="postgres")]
457
+ return []
441
458
 
442
459
 
443
460
  def format_app_import(asgi_application: str) -> str:
@@ -3,7 +3,7 @@ from __future__ import annotations
3
3
  from pathlib import Path
4
4
  from typing import Dict, Optional
5
5
 
6
- from .base import DetectResult, DependencySpec, Provider, _exists, MountSpec
6
+ from .base import DetectResult, DependencySpec, Provider, _exists, MountSpec, ServiceSpec
7
7
 
8
8
 
9
9
  class StaticFileProvider:
@@ -68,3 +68,6 @@ class StaticFileProvider:
68
68
 
69
69
  def env(self) -> Optional[Dict[str, str]]:
70
70
  return None
71
+
72
+ def services(self) -> list[ServiceSpec]:
73
+ return []
@@ -0,0 +1,5 @@
1
+ __all__ = ["version", "version_info"]
2
+
3
+
4
+ version = "0.6.0"
5
+ version_info = (0, 6, 0, "final", 0)
@@ -1,5 +0,0 @@
1
- __all__ = ["version", "version_info"]
2
-
3
-
4
- version = "0.5.2"
5
- version_info = (0, 5, 2, "final", 0)
File without changes
File without changes