shipit-cli 0.13.3__tar.gz → 0.14.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 (27) hide show
  1. {shipit_cli-0.13.3 → shipit_cli-0.14.0}/PKG-INFO +1 -1
  2. {shipit_cli-0.13.3 → shipit_cli-0.14.0}/pyproject.toml +1 -1
  3. {shipit_cli-0.13.3 → shipit_cli-0.14.0}/src/shipit/assets/wordpress/install.sh +1 -1
  4. {shipit_cli-0.13.3 → shipit_cli-0.14.0}/src/shipit/cli.py +4 -2
  5. {shipit_cli-0.13.3 → shipit_cli-0.14.0}/src/shipit/generator.py +3 -1
  6. {shipit_cli-0.13.3 → shipit_cli-0.14.0}/src/shipit/providers/base.py +1 -1
  7. {shipit_cli-0.13.3 → shipit_cli-0.14.0}/src/shipit/providers/hugo.py +2 -2
  8. shipit_cli-0.14.0/src/shipit/providers/jekyll.py +96 -0
  9. {shipit_cli-0.13.3 → shipit_cli-0.14.0}/src/shipit/providers/laravel.py +2 -2
  10. {shipit_cli-0.13.3 → shipit_cli-0.14.0}/src/shipit/providers/mkdocs.py +2 -2
  11. {shipit_cli-0.13.3 → shipit_cli-0.14.0}/src/shipit/providers/node_static.py +56 -39
  12. {shipit_cli-0.13.3 → shipit_cli-0.14.0}/src/shipit/providers/php.py +2 -2
  13. {shipit_cli-0.13.3 → shipit_cli-0.14.0}/src/shipit/providers/python.py +2 -2
  14. {shipit_cli-0.13.3 → shipit_cli-0.14.0}/src/shipit/providers/registry.py +2 -0
  15. {shipit_cli-0.13.3 → shipit_cli-0.14.0}/src/shipit/providers/staticfile.py +2 -2
  16. {shipit_cli-0.13.3 → shipit_cli-0.14.0}/src/shipit/providers/wordpress.py +2 -2
  17. shipit_cli-0.14.0/src/shipit/version.py +5 -0
  18. shipit_cli-0.13.3/src/shipit/version.py +0 -5
  19. {shipit_cli-0.13.3 → shipit_cli-0.14.0}/.gitignore +0 -0
  20. {shipit_cli-0.13.3 → shipit_cli-0.14.0}/README.md +0 -0
  21. {shipit_cli-0.13.3 → shipit_cli-0.14.0}/src/shipit/__init__.py +0 -0
  22. {shipit_cli-0.13.3 → shipit_cli-0.14.0}/src/shipit/assets/php/php.ini +0 -0
  23. {shipit_cli-0.13.3 → shipit_cli-0.14.0}/src/shipit/assets/wordpress/wp-config.php +0 -0
  24. {shipit_cli-0.13.3 → shipit_cli-0.14.0}/src/shipit/procfile.py +0 -0
  25. {shipit_cli-0.13.3 → shipit_cli-0.14.0}/tests/test_e2e.py +0 -0
  26. {shipit_cli-0.13.3 → shipit_cli-0.14.0}/tests/test_generate_shipit_examples.py +0 -0
  27. {shipit_cli-0.13.3 → shipit_cli-0.14.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.13.3
3
+ Version: 0.14.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
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "shipit-cli"
3
- version = "0.13.3"
3
+ version = "0.14.0"
4
4
  description = "Shipit CLI is the best way to build, serve and deploy your projects anywhere."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
@@ -94,7 +94,7 @@ fi
94
94
 
95
95
  if [ -n "${WP_LOCALE:-}" ]; then
96
96
  echo "Setting locale: $WP_LOCALE"
97
- wp language install "$WP_LOCALE"
97
+ wp language core install "$WP_LOCALE"
98
98
  wp language theme install --all "$WP_LOCALE"
99
99
  wp language plugin install --all "$WP_LOCALE"
100
100
  wp site switch-language "$WP_LOCALE"
@@ -387,7 +387,7 @@ RUN apt-get update \\
387
387
  dpkg-dev pkg-config re2c locate \\
388
388
  libmariadb-dev libmariadb-dev-compat libpq-dev \\
389
389
  libvips-dev default-libmysqlclient-dev libmagickwand-dev \\
390
- libicu-dev libxml2-dev libxslt-dev \\
390
+ libicu-dev libxml2-dev libxslt-dev libyaml-dev \\
391
391
  sudo curl ca-certificates \\
392
392
  && rm -rf /var/lib/apt/lists/*
393
393
 
@@ -1337,10 +1337,12 @@ class Ctx:
1337
1337
  def copy(
1338
1338
  self,
1339
1339
  source: str,
1340
- target: str,
1340
+ target: Optional[str] = None,
1341
1341
  ignore: Optional[List[str]] = None,
1342
1342
  base: Optional[Literal["source", "assets"]] = None,
1343
1343
  ) -> Optional[str]:
1344
+ if target is None:
1345
+ target = source
1344
1346
  step = CopyStep(source, target, ignore, base or "source")
1345
1347
  return self.add_step(step)
1346
1348
 
@@ -92,9 +92,11 @@ def generate_shipit(path: Path, custom_commands: CustomCommands, use_provider: O
92
92
  provider_cls = detect_provider(path, custom_commands)
93
93
  provider = provider_cls(path, custom_commands)
94
94
 
95
+ default_serve_name = path.absolute().name
96
+
95
97
  # Collect parts
96
98
  plan = ProviderPlan(
97
- serve_name=provider.serve_name(),
99
+ serve_name=provider.serve_name() or default_serve_name,
98
100
  provider=provider.name(),
99
101
  platform=provider.platform(),
100
102
  mounts=provider.mounts(),
@@ -27,7 +27,7 @@ class Provider(Protocol):
27
27
  def detect(cls, path: Path, custom_commands: CustomCommands) -> Optional[DetectResult]: ...
28
28
  def initialize(self) -> None: ...
29
29
  # Structured plan steps (no path args; use self.path)
30
- def serve_name(self) -> str: ...
30
+ def serve_name(self) -> Optional[str]: ...
31
31
  def platform(self) -> Optional[str]: ...
32
32
  def dependencies(self) -> list["DependencySpec"]: ...
33
33
  def declarations(self) -> Optional[str]: ...
@@ -24,8 +24,8 @@ class HugoProvider(StaticFileProvider):
24
24
  return DetectResult(cls.name(), 40)
25
25
  return None
26
26
 
27
- def serve_name(self) -> str:
28
- return self.path.name
27
+ def serve_name(self) -> Optional[str]:
28
+ return None
29
29
 
30
30
  def platform(self) -> Optional[str]:
31
31
  return "hugo"
@@ -0,0 +1,96 @@
1
+ from __future__ import annotations
2
+
3
+ from pathlib import Path
4
+ from typing import Dict, Optional
5
+
6
+ from .base import (
7
+ DetectResult,
8
+ DependencySpec,
9
+ Provider,
10
+ _exists,
11
+ MountSpec,
12
+ ServiceSpec,
13
+ VolumeSpec,
14
+ CustomCommands,
15
+ )
16
+ from .staticfile import StaticFileProvider
17
+
18
+
19
+ class JekyllProvider(StaticFileProvider):
20
+ def __init__(self, path: Path, custom_commands: CustomCommands):
21
+ self.path = path
22
+
23
+ @classmethod
24
+ def name(cls) -> str:
25
+ return "jekyll"
26
+
27
+ @classmethod
28
+ def detect(
29
+ cls, path: Path, custom_commands: CustomCommands
30
+ ) -> Optional[DetectResult]:
31
+ if _exists(path, "_config.yml", "_config.yaml"):
32
+ if _exists(path, "Gemfile"):
33
+ return DetectResult(cls.name(), 85)
34
+ return DetectResult(cls.name(), 40)
35
+ if custom_commands.build and custom_commands.build.startswith("jekyll "):
36
+ return DetectResult(cls.name(), 85)
37
+ return None
38
+
39
+ def initialize(self) -> None:
40
+ pass
41
+
42
+ def serve_name(self) -> Optional[str]:
43
+ return None
44
+
45
+ def platform(self) -> Optional[str]:
46
+ return None
47
+
48
+ def dependencies(self) -> list[DependencySpec]:
49
+ return [
50
+ DependencySpec(
51
+ "ruby",
52
+ env_var="SHIPIT_RUBY_VERSION",
53
+ use_in_build=True,
54
+ use_in_serve=False,
55
+ ),
56
+ *super().dependencies(),
57
+ ]
58
+
59
+ def declarations(self) -> Optional[str]:
60
+ return 'jekyll_version = getenv("SHIPIT_JEKYLL_VERSION") or "1.6.1"\n'
61
+
62
+ def build_steps(self) -> list[str]:
63
+ if _exists(self.path, "Gemfile"):
64
+ install_deps = ["Gemfile"]
65
+ install_deps_str = ", ".join([f'"{dep}"' for dep in install_deps])
66
+ install_commands = [
67
+ f'run("bundle install", inputs=[{install_deps_str}], group="build")'
68
+ ]
69
+ if _exists(self.path, "Gemfile.lock"):
70
+ install_commands = [
71
+ 'copy("Gemfile.lock")',
72
+ *install_commands,
73
+ ]
74
+ else:
75
+ install_commands = ['run("gem install jekyll", group="build")']
76
+ return [
77
+ 'workdir(temp["build"])',
78
+ 'copy(".", ignore=[".git"])',
79
+ *install_commands,
80
+ 'run("jekyll build --destination={}".format(app["build"]), outputs=["."], group="build")',
81
+ ]
82
+
83
+ def prepare_steps(self) -> Optional[list[str]]:
84
+ return None
85
+
86
+ def mounts(self) -> list[MountSpec]:
87
+ return [MountSpec("temp", attach_to_serve=False), *super().mounts()]
88
+
89
+ def volumes(self) -> list[VolumeSpec]:
90
+ return []
91
+
92
+ def env(self) -> Optional[Dict[str, str]]:
93
+ return None
94
+
95
+ def services(self) -> list[ServiceSpec]:
96
+ return []
@@ -33,8 +33,8 @@ class LaravelProvider:
33
33
  def initialize(self) -> None:
34
34
  pass
35
35
 
36
- def serve_name(self) -> str:
37
- return self.path.name
36
+ def serve_name(self) -> Optional[str]:
37
+ return None
38
38
 
39
39
  def platform(self) -> Optional[str]:
40
40
  return "laravel"
@@ -37,8 +37,8 @@ class MkdocsProvider(StaticFileProvider):
37
37
  def initialize(self) -> None:
38
38
  pass
39
39
 
40
- def serve_name(self) -> str:
41
- return self.path.name
40
+ def serve_name(self) -> Optional[str]:
41
+ return None
42
42
 
43
43
  def platform(self) -> Optional[str]:
44
44
  return None
@@ -78,8 +78,8 @@ class PackageManager(Enum):
78
78
  def install_command(self, has_lockfile: bool = False) -> str:
79
79
  return {
80
80
  PackageManager.NPM: f"npm {'ci' if has_lockfile else 'install'}",
81
- PackageManager.PNPM: f"pnpm install{' --frozen-lockfile' if has_lockfile else ''}",
82
- PackageManager.YARN: f"yarn install{' --frozen-lockfile' if has_lockfile else ''}",
81
+ PackageManager.PNPM: "pnpm install",
82
+ PackageManager.YARN: "yarn install",
83
83
  PackageManager.BUN: f"bun install{' --no-save' if has_lockfile else ''}",
84
84
  }[self]
85
85
 
@@ -105,6 +105,7 @@ class StaticGenerator(Enum):
105
105
  VITE = "vite"
106
106
  NEXT = "next"
107
107
  GATSBY = "gatsby"
108
+ DOCUSAURUS_OLD = "docusaurus-old"
108
109
  DOCUSAURUS = "docusaurus"
109
110
  SVELTE = "svelte"
110
111
  REMIX = "remix"
@@ -119,6 +120,7 @@ class NodeStaticProvider(StaticFileProvider):
119
120
  package_json: Optional[Dict[str, Any]]
120
121
  extra_dependencies: Set[str]
121
122
  static_generator: Optional[StaticGenerator] = None
123
+ build_command: Optional[str] = None
122
124
 
123
125
  def __init__(self, path: Path, custom_commands: CustomCommands):
124
126
  super().__init__(path, custom_commands)
@@ -139,6 +141,8 @@ class NodeStaticProvider(StaticFileProvider):
139
141
  self.static_generator = StaticGenerator.GATSBY
140
142
  elif self.has_dependency(self.package_json, "astro"):
141
143
  self.static_generator = StaticGenerator.ASTRO
144
+ elif self.has_dependency(self.package_json, "docusaurus"):
145
+ self.static_generator = StaticGenerator.DOCUSAURUS_OLD
142
146
  elif self.has_dependency(self.package_json, "@docusaurus/core"):
143
147
  self.static_generator = StaticGenerator.DOCUSAURUS
144
148
  elif self.has_dependency(self.package_json, "svelte"):
@@ -160,6 +164,8 @@ class NodeStaticProvider(StaticFileProvider):
160
164
  elif self.has_dependency(self.package_json, "nuxt"):
161
165
  self.static_generator = StaticGenerator.NUXT_V3
162
166
 
167
+ self.build_command = self.get_build_command(self.package_json, self.package_manager, self.static_generator)
168
+
163
169
  # if self.has_dependency(self.package_json, "sharp"):
164
170
  # self.extra_dependencies.add("libvips")
165
171
 
@@ -217,6 +223,7 @@ class NodeStaticProvider(StaticFileProvider):
217
223
  "nuxt",
218
224
  "gatsby",
219
225
  "svelte",
226
+ "docusaurus",
220
227
  "@docusaurus/core",
221
228
  "@remix-run/dev",
222
229
  ]
@@ -227,8 +234,8 @@ class NodeStaticProvider(StaticFileProvider):
227
234
  def initialize(self) -> None:
228
235
  pass
229
236
 
230
- def serve_name(self) -> str:
231
- return self.path.name
237
+ def serve_name(self) -> Optional[str]:
238
+ return None
232
239
 
233
240
  def platform(self) -> Optional[str]:
234
241
  return self.static_generator.value if self.static_generator else None
@@ -248,7 +255,10 @@ class NodeStaticProvider(StaticFileProvider):
248
255
  ]
249
256
 
250
257
  def declarations(self) -> Optional[str]:
251
- return None
258
+ output_dir = self.get_output_dir()
259
+ return (
260
+ f'shipit_static_dir = getenv("SHIPIT_STATIC_DIR") or "{output_dir}"\n'
261
+ )
252
262
 
253
263
  def get_output_dir(self) -> str:
254
264
  if self.static_generator == StaticGenerator.NEXT:
@@ -267,60 +277,67 @@ class NodeStaticProvider(StaticFileProvider):
267
277
  return "build/client"
268
278
  elif self.static_generator in [
269
279
  StaticGenerator.DOCUSAURUS,
280
+ StaticGenerator.DOCUSAURUS_OLD,
270
281
  StaticGenerator.SVELTE,
271
282
  ]:
272
283
  return "build"
273
284
  else:
274
285
  return "dist"
275
286
 
276
- def get_build_command(self) -> bool:
277
- if not self.package_json:
278
- return False
279
- build_command = self.package_json.get("scripts", {}).get("build")
280
- if build_command:
281
- return self.package_manager.run_command("build")
282
- if self.static_generator == StaticGenerator.GATSBY:
283
- return self.package_manager.run_execute_command("gatsby build")
284
- if self.static_generator == StaticGenerator.ASTRO:
285
- return self.package_manager.run_execute_command("astro build")
286
- elif self.static_generator == StaticGenerator.REMIX_OLD:
287
- return self.package_manager.run_execute_command("remix-ssg build")
288
- elif self.static_generator == StaticGenerator.REMIX_V2:
289
- return self.package_manager.run_execute_command("vite build")
290
- elif self.static_generator == StaticGenerator.DOCUSAURUS:
291
- return self.package_manager.run_execute_command("docusaurus build")
292
- elif self.static_generator == StaticGenerator.SVELTE:
293
- return self.package_manager.run_execute_command("svelte-kit build")
294
- elif self.static_generator == StaticGenerator.VITE:
295
- return self.package_manager.run_execute_command("vite build")
296
- elif self.static_generator == StaticGenerator.NEXT:
297
- return self.package_manager.run_execute_command("next export")
298
- elif self.static_generator == StaticGenerator.NUXT_V3:
299
- return self.package_manager.run_execute_command("nuxi generate")
300
- elif self.static_generator == StaticGenerator.NUXT_OLD:
301
- return self.package_manager.run_execute_command("nuxt generate")
302
- return False
287
+ @classmethod
288
+ def get_build_command(cls, package_json: Optional[Dict[str, Any]], package_manager: PackageManager, static_generator: StaticGenerator) -> Optional[str]:
289
+ if package_json:
290
+ build_command = package_json.get("scripts", {}).get("build")
291
+ if build_command:
292
+ return package_manager.run_command("build")
293
+ if static_generator == StaticGenerator.GATSBY:
294
+ return package_manager.run_execute_command("gatsby build")
295
+ elif static_generator == StaticGenerator.ASTRO:
296
+ return package_manager.run_execute_command("astro build")
297
+ elif static_generator == StaticGenerator.REMIX_OLD:
298
+ return package_manager.run_execute_command("remix-ssg build")
299
+ elif static_generator == StaticGenerator.REMIX_V2:
300
+ return package_manager.run_execute_command("vite build")
301
+ elif static_generator == StaticGenerator.DOCUSAURUS:
302
+ return package_manager.run_execute_command("docusaurus build")
303
+ elif static_generator == StaticGenerator.DOCUSAURUS_OLD:
304
+ return package_manager.run_execute_command("docusaurus build")
305
+ elif static_generator == StaticGenerator.SVELTE:
306
+ return package_manager.run_execute_command("svelte-kit build")
307
+ elif static_generator == StaticGenerator.VITE:
308
+ return package_manager.run_execute_command("vite build")
309
+ elif static_generator == StaticGenerator.NEXT:
310
+ return package_manager.run_execute_command("next export")
311
+ elif static_generator == StaticGenerator.NUXT_V3:
312
+ return package_manager.run_execute_command("nuxi generate")
313
+ elif static_generator == StaticGenerator.NUXT_OLD:
314
+ return package_manager.run_execute_command("nuxt generate")
315
+ return None
303
316
 
304
317
  def build_steps(self) -> list[str]:
305
- output_dir = self.get_output_dir()
306
- get_build_command = self.get_build_command()
307
318
  lockfile = self.package_manager.lockfile()
308
319
  has_lockfile = (self.path / lockfile).exists()
309
320
  install_command = self.package_manager.install_command(
310
321
  has_lockfile=has_lockfile
311
322
  )
312
323
  input_files = ["package.json"]
313
- if has_lockfile:
314
- input_files.append(lockfile)
324
+ # if has_lockfile:
325
+ # input_files.append(lockfile)
315
326
  inputs_install_files = ", ".join([f'"{file}"' for file in input_files])
316
327
 
328
+ ignored_files = ["node_modules", ".git"]
329
+ if has_lockfile:
330
+ ignored_files.append(lockfile)
331
+ all_ignored_files = ", ".join([f'"{file}"' for file in ignored_files])
332
+
317
333
  return [
318
334
  'workdir(temp["build"])',
335
+ f'copy("{lockfile}")' if has_lockfile else None,
319
336
  # 'run("npx corepack enable", inputs=["package.json"], group="install")',
320
337
  f'run("{install_command}", inputs=[{inputs_install_files}], group="install")',
321
- 'copy(".", ".", ignore=["node_modules", ".git"])',
322
- f'run("{get_build_command}", outputs=["{output_dir}"], group="build")',
323
- f'run("cp -R {output_dir}/* {{}}/".format(app["build"]))',
338
+ f'copy(".", ignore=[{all_ignored_files}])',
339
+ f'run("{self.build_command}", outputs=[shipit_static_dir], group="build")',
340
+ f'run("cp -R {{}}/* {{}}/".format(shipit_static_dir, app["build"]))',
324
341
  ]
325
342
 
326
343
  def prepare_steps(self) -> Optional[list[str]]:
@@ -49,8 +49,8 @@ class PhpProvider:
49
49
  def initialize(self) -> None:
50
50
  pass
51
51
 
52
- def serve_name(self) -> str:
53
- return self.path.name
52
+ def serve_name(self) -> Optional[str]:
53
+ return None
54
54
 
55
55
  def platform(self) -> Optional[str]:
56
56
  return None
@@ -225,8 +225,8 @@ class PythonProvider:
225
225
  def initialize(self) -> None:
226
226
  pass
227
227
 
228
- def serve_name(self) -> str:
229
- return self.path.name
228
+ def serve_name(self) -> Optional[str]:
229
+ return None
230
230
 
231
231
  def platform(self) -> Optional[str]:
232
232
  return self.framework.value if self.framework else None
@@ -8,6 +8,7 @@ from .node_static import NodeStaticProvider
8
8
  from .wordpress import WordPressProvider
9
9
  from .php import PhpProvider
10
10
  from .python import PythonProvider
11
+ from .jekyll import JekyllProvider
11
12
  from .staticfile import StaticFileProvider
12
13
 
13
14
 
@@ -21,5 +22,6 @@ def providers() -> list[type[Provider]]:
21
22
  WordPressProvider,
22
23
  PhpProvider,
23
24
  NodeStaticProvider,
25
+ JekyllProvider,
24
26
  StaticFileProvider,
25
27
  ]
@@ -55,8 +55,8 @@ class StaticFileProvider:
55
55
  def initialize(self) -> None:
56
56
  pass
57
57
 
58
- def serve_name(self) -> str:
59
- return self.path.name
58
+ def serve_name(self) -> Optional[str]:
59
+ return None
60
60
 
61
61
  def platform(self) -> Optional[str]:
62
62
  return None
@@ -40,8 +40,8 @@ class WordPressProvider(PhpProvider):
40
40
  def initialize(self) -> None:
41
41
  pass
42
42
 
43
- def serve_name(self) -> str:
44
- return self.path.name
43
+ def serve_name(self) -> Optional[str]:
44
+ return None
45
45
 
46
46
  def platform(self) -> Optional[str]:
47
47
  return None
@@ -0,0 +1,5 @@
1
+ __all__ = ["version", "version_info"]
2
+
3
+
4
+ version = "0.14.0"
5
+ version_info = (0, 14, 0, "final", 0)
@@ -1,5 +0,0 @@
1
- __all__ = ["version", "version_info"]
2
-
3
-
4
- version = "0.13.3"
5
- version_info = (0, 13, 3, "final", 0)
File without changes
File without changes