shipit-cli 0.15.2__tar.gz → 0.16.1__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 (39) hide show
  1. {shipit_cli-0.15.2 → shipit_cli-0.16.1}/PKG-INFO +1 -1
  2. {shipit_cli-0.15.2 → shipit_cli-0.16.1}/pyproject.toml +1 -1
  3. {shipit_cli-0.15.2 → shipit_cli-0.16.1}/src/shipit/assets/wordpress/wp-config.php +69 -11
  4. {shipit_cli-0.15.2 → shipit_cli-0.16.1}/src/shipit/builders/docker.py +10 -3
  5. {shipit_cli-0.15.2 → shipit_cli-0.16.1}/src/shipit/cli.py +20 -3
  6. shipit_cli-0.16.1/src/shipit/providers/go.py +110 -0
  7. {shipit_cli-0.15.2 → shipit_cli-0.16.1}/src/shipit/providers/registry.py +2 -0
  8. {shipit_cli-0.15.2 → shipit_cli-0.16.1}/src/shipit/runners/base.py +2 -1
  9. {shipit_cli-0.15.2 → shipit_cli-0.16.1}/src/shipit/runners/local.py +7 -1
  10. {shipit_cli-0.15.2 → shipit_cli-0.16.1}/src/shipit/runners/wasmer.py +79 -12
  11. shipit_cli-0.16.1/src/shipit/version.py +5 -0
  12. shipit_cli-0.15.2/src/shipit/version.py +0 -5
  13. {shipit_cli-0.15.2 → shipit_cli-0.16.1}/.gitignore +0 -0
  14. {shipit_cli-0.15.2 → shipit_cli-0.16.1}/README.md +0 -0
  15. {shipit_cli-0.15.2 → shipit_cli-0.16.1}/src/shipit/__init__.py +0 -0
  16. {shipit_cli-0.15.2 → shipit_cli-0.16.1}/src/shipit/assets/php/php.ini +0 -0
  17. {shipit_cli-0.15.2 → shipit_cli-0.16.1}/src/shipit/assets/wordpress/install.sh +0 -0
  18. {shipit_cli-0.15.2 → shipit_cli-0.16.1}/src/shipit/builders/__init__.py +0 -0
  19. {shipit_cli-0.15.2 → shipit_cli-0.16.1}/src/shipit/builders/base.py +0 -0
  20. {shipit_cli-0.15.2 → shipit_cli-0.16.1}/src/shipit/builders/local.py +0 -0
  21. {shipit_cli-0.15.2 → shipit_cli-0.16.1}/src/shipit/generator.py +0 -0
  22. {shipit_cli-0.15.2 → shipit_cli-0.16.1}/src/shipit/procfile.py +0 -0
  23. {shipit_cli-0.15.2 → shipit_cli-0.16.1}/src/shipit/providers/base.py +0 -0
  24. {shipit_cli-0.15.2 → shipit_cli-0.16.1}/src/shipit/providers/hugo.py +0 -0
  25. {shipit_cli-0.15.2 → shipit_cli-0.16.1}/src/shipit/providers/jekyll.py +0 -0
  26. {shipit_cli-0.15.2 → shipit_cli-0.16.1}/src/shipit/providers/laravel.py +0 -0
  27. {shipit_cli-0.15.2 → shipit_cli-0.16.1}/src/shipit/providers/mkdocs.py +0 -0
  28. {shipit_cli-0.15.2 → shipit_cli-0.16.1}/src/shipit/providers/node_static.py +0 -0
  29. {shipit_cli-0.15.2 → shipit_cli-0.16.1}/src/shipit/providers/php.py +0 -0
  30. {shipit_cli-0.15.2 → shipit_cli-0.16.1}/src/shipit/providers/python.py +0 -0
  31. {shipit_cli-0.15.2 → shipit_cli-0.16.1}/src/shipit/providers/staticfile.py +0 -0
  32. {shipit_cli-0.15.2 → shipit_cli-0.16.1}/src/shipit/providers/wordpress.py +0 -0
  33. {shipit_cli-0.15.2 → shipit_cli-0.16.1}/src/shipit/runners/__init__.py +0 -0
  34. {shipit_cli-0.15.2 → shipit_cli-0.16.1}/src/shipit/shipit_types.py +0 -0
  35. {shipit_cli-0.15.2 → shipit_cli-0.16.1}/src/shipit/ui.py +0 -0
  36. {shipit_cli-0.15.2 → shipit_cli-0.16.1}/src/shipit/utils.py +0 -0
  37. {shipit_cli-0.15.2 → shipit_cli-0.16.1}/tests/test_e2e.py +0 -0
  38. {shipit_cli-0.15.2 → shipit_cli-0.16.1}/tests/test_generate_shipit_examples.py +0 -0
  39. {shipit_cli-0.15.2 → shipit_cli-0.16.1}/tests/test_version.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: shipit-cli
3
- Version: 0.15.2
3
+ Version: 0.16.1
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.15.2"
3
+ version = "0.16.1"
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"
@@ -21,12 +21,55 @@ define( 'WP_AUTO_UPDATE_CORE', false); // Disable automatic aupdates and checks
21
21
  * @package WordPress
22
22
  */
23
23
 
24
+ // Deserialize the value from the environment variable value
25
+ function env_var_deserialize(string $value) {
26
+ $v = trim($value);
27
+ if ($v === '') {
28
+ return '';
29
+ }
30
+ $len = strlen($v);
31
+ if ($len >= 2 && ($v[0] === '"' || $v[0] === "'") && $v[0] === $v[$len - 1]) {
32
+ return substr($v, 1, -1);
33
+ }
34
+ $lower = strtolower($v);
35
+ static $scalarMap = [
36
+ 'true' => true,
37
+ 'yes' => true,
38
+ 'on' => true,
39
+ 'y' => true,
40
+ 'false' => false,
41
+ 'no' => false,
42
+ 'off' => false,
43
+ 'n' => false,
44
+ 'null' => null,
45
+ ];
46
+ if (array_key_exists($lower, $scalarMap)) {
47
+ return $scalarMap[$lower];
48
+ }
49
+ if (ctype_digit($v) || ($v[0] === '-' && ctype_digit(substr($v, 1)))) {
50
+ return (int) $v;
51
+ }
52
+ if (is_numeric($v)) {
53
+ return (float) $v;
54
+ }
55
+ if (strpos($v, '://') !== false && filter_var($v, FILTER_VALIDATE_URL)) {
56
+ return $v;
57
+ }
58
+ if (strpos($v, ',') !== false) {
59
+ if (strncmp($v, 'http://', 7) === 0 || strncmp($v, 'https://', 8) === 0) {
60
+ return $v;
61
+ }
62
+ return array_map('trim', explode(',', $v));
63
+ }
64
+ return $v;
65
+ }
24
66
 
25
- function get_env_var(string $name, string $default = ''): string
67
+
68
+ function get_env_var(string $name, string $default = '')
26
69
  {
27
70
  $value = getenv($name);
28
71
  if ($value !== false) {
29
- return $value;
72
+ return env_var_deserialize($value);
30
73
  }
31
74
 
32
75
  if ($default === '') {
@@ -36,11 +79,6 @@ function get_env_var(string $name, string $default = ''): string
36
79
  return $default;
37
80
  }
38
81
 
39
- function get_env_var_bool(string $name, bool $default = false): bool
40
- {
41
- return in_array(get_env_var($name, $default ? "1" : "0"), ["1", "true", "yes", "on", "y"], true);
42
- }
43
-
44
82
  // ** Database settings - You can get this info from your web host ** //
45
83
  /** The name of the database for WordPress */
46
84
  define( 'DB_NAME', get_env_var('DB_NAME', 'wordpress') );
@@ -98,7 +136,7 @@ define( 'WP_SITEURL', get_env_var('WP_SITEURL', WP_HOME . '/') );
98
136
 
99
137
  define( 'WP_MEMORY_LIMIT', get_env_var('WP_MEMORY_LIMIT', '256M') );
100
138
  define( 'WP_MAX_MEMORY_LIMIT', get_env_var('WP_MAX_MEMORY_LIMIT', '256M') );
101
- define( 'WP_POST_REVISIONS', get_env_var_bool('WP_POST_REVISIONS', false));
139
+ define( 'WP_POST_REVISIONS', get_env_var('WP_POST_REVISIONS', false));
102
140
 
103
141
  /**#@-*/
104
142
 
@@ -122,7 +160,7 @@ $table_prefix = 'wp_';
122
160
  *
123
161
  * @link https://wordpress.org/support/article/debugging-in-wordpress/
124
162
  */
125
- define( 'WP_DEBUG', get_env_var_bool('WP_DEBUG', false) );
163
+ define( 'WP_DEBUG', get_env_var('WP_DEBUG', false) );
126
164
 
127
165
  /* Add any custom values between this line and the "stop editing" line. */
128
166
 
@@ -137,12 +175,32 @@ if ( getenv('WP_ADDITIONAL_CONFIG') ) {
137
175
  }
138
176
  }
139
177
 
140
- /* That's all, stop editing! Happy publishing. */
141
-
142
178
  /** Absolute path to the WordPress directory. */
143
179
  if ( ! defined( 'ABSPATH' ) ) {
144
180
  define( 'ABSPATH', __DIR__ . '/' );
145
181
  }
146
182
 
183
+ function wpdefine_load_env_defines(string $prefix = 'WPDEFINE_'): void {
184
+ $env = $_ENV + $_SERVER;
185
+ $prefixLen = strlen($prefix);
186
+ foreach ($env as $key => $rawValue) {
187
+ if (!is_string($key) || strncmp($key, $prefix, $prefixLen) !== 0) {
188
+ continue;
189
+ }
190
+ $const = substr($key, $prefixLen);
191
+ if ($const === '' || defined($const)) {
192
+ continue;
193
+ }
194
+ if (!preg_match('/^[A-Z_][A-Z0-9_]*$/', $const)) {
195
+ continue;
196
+ }
197
+ define($const, env_var_deserialize((string) $rawValue));
198
+ }
199
+ }
200
+
201
+ wpdefine_load_env_defines();
202
+
203
+ /* That's all, stop editing! Happy publishing. */
204
+
147
205
  /** Sets up WordPress vars and included files. */
148
206
  require_once ABSPATH . 'wp-settings.php';
@@ -31,6 +31,9 @@ class DockerBuildBackend:
31
31
  "php": {
32
32
  "source": "ubi:adwinying/php",
33
33
  },
34
+ "go-wasix": {
35
+ "source": "ubi:wasix-org/go[extract_all=true,bin_path=bin/]",
36
+ },
34
37
  "composer": {
35
38
  "source": "ubi:composer/composer",
36
39
  "postinstall": """composer_dir=$(mise where ubi:composer/composer); ln -s "$composer_dir/composer.phar" /usr/local/bin/composer""",
@@ -38,7 +41,8 @@ class DockerBuildBackend:
38
41
  }
39
42
 
40
43
  def __init__(
41
- self, src_dir: Path, assets_path: Path, docker_client: Optional[str] = None
44
+ self, src_dir: Path, assets_path: Path, docker_client: Optional[str] = None,
45
+ docker_opts: Optional[str] = None
42
46
  ) -> None:
43
47
  self.src_dir = src_dir
44
48
  self.assets_path = assets_path
@@ -50,6 +54,7 @@ class DockerBuildBackend:
50
54
  self.docker_ignore_path = self.docker_path / "Dockerfile.dockerignore"
51
55
  self.shipit_docker_path = Path("/shipit")
52
56
  self.docker_client = docker_client or "docker"
57
+ self.docker_opts = docker_opts
53
58
  self.env = {
54
59
  "HOME": "/root",
55
60
  }
@@ -76,6 +81,8 @@ class DockerBuildBackend:
76
81
  self.docker_name_path.write_text(image_name)
77
82
  self.print_dockerfile(contents)
78
83
  extra_args: List[str] = []
84
+ if self.docker_opts:
85
+ extra_args.append(self.docker_opts)
79
86
  sh.Command(self.docker_client)(
80
87
  "build",
81
88
  "-f",
@@ -217,10 +224,10 @@ RUN curl https://mise.run | sh
217
224
  mapped_dependency = self.mise_mapper.get(dependency.name, {})
218
225
  package_name = mapped_dependency.get("source", dependency.name)
219
226
  if dependency.version:
220
- docker_file_contents += f"RUN mise use --global {package_name}@{dependency.version}\n"
227
+ docker_file_contents += f"RUN mise use --global \"{package_name}@{dependency.version}\"\n"
221
228
  else:
222
229
  docker_file_contents += (
223
- f"RUN mise use --global {package_name}\n"
230
+ f"RUN mise use --global \"{package_name}\"\n"
224
231
  )
225
232
  if mapped_dependency.get("postinstall"):
226
233
  docker_file_contents += (
@@ -347,6 +347,10 @@ def auto(
347
347
  None,
348
348
  help="Use a specific Docker client (such as depot, podman, etc.)",
349
349
  ),
350
+ docker_opts: Optional[str] = typer.Option(
351
+ None,
352
+ help="Additional options to pass to the Docker client.",
353
+ ),
350
354
  skip_docker_if_safe_build: Optional[bool] = typer.Option(
351
355
  True,
352
356
  help="Skip Docker if the build can be done safely locally (only copy commands).",
@@ -464,6 +468,7 @@ def auto(
464
468
  wasmer=wasmer,
465
469
  docker=docker,
466
470
  docker_client=docker_client,
471
+ docker_opts=docker_opts,
467
472
  skip_docker_if_safe_build=skip_docker_if_safe_build,
468
473
  wasmer_registry=wasmer_registry,
469
474
  wasmer_token=wasmer_token,
@@ -610,6 +615,10 @@ def serve(
610
615
  None,
611
616
  help="Use a specific Docker client (such as depot, podman, etc.)",
612
617
  ),
618
+ docker_opts: Optional[str] = typer.Option(
619
+ None,
620
+ help="Additional options to pass to the Docker client.",
621
+ ),
613
622
  start: Optional[bool] = typer.Option(
614
623
  True,
615
624
  help="Run the start command after building.",
@@ -647,7 +656,7 @@ def serve(
647
656
 
648
657
  if docker or docker_client:
649
658
  build_backend: BuildBackend = DockerBuildBackend(
650
- path, ASSETS_PATH, docker_client
659
+ path, ASSETS_PATH, docker_client, docker_opts
651
660
  )
652
661
  else:
653
662
  build_backend = LocalBuildBackend(path, ASSETS_PATH)
@@ -905,6 +914,10 @@ def build(
905
914
  None,
906
915
  help="Use a specific Docker client (such as depot, podman, etc.)",
907
916
  ),
917
+ docker_opts: Optional[str] = typer.Option(
918
+ None,
919
+ help="Additional options to pass to the Docker client.",
920
+ ),
908
921
  skip_docker_if_safe_build: Optional[bool] = typer.Option(
909
922
  True,
910
923
  help="Skip Docker if the build can be done safely locally (only copy commands).",
@@ -933,7 +946,7 @@ def build(
933
946
 
934
947
  if docker or docker_client:
935
948
  build_backend: BuildBackend = DockerBuildBackend(
936
- path, ASSETS_PATH, docker_client
949
+ path, ASSETS_PATH, docker_client, docker_opts=docker_opts
937
950
  )
938
951
  else:
939
952
  build_backend = LocalBuildBackend(path, ASSETS_PATH)
@@ -995,6 +1008,7 @@ def build(
995
1008
  wasmer_token=wasmer_token,
996
1009
  docker=False,
997
1010
  docker_client=None,
1011
+ docker_opts=None,
998
1012
  skip_docker_if_safe_build=False,
999
1013
  env_name=env_name,
1000
1014
  serve_port=serve_port,
@@ -1015,8 +1029,11 @@ def build(
1015
1029
  "No start command could be found, please provide a start command"
1016
1030
  )
1017
1031
 
1032
+ # Prepare the build steps (sometimes the runners need to adapt the dependencies)
1033
+ build_steps = runner.prepare_build_steps(serve.build)
1034
+
1018
1035
  # Build and serve
1019
- build_backend.build(serve.name, env, serve.mounts or [], serve.build)
1036
+ build_backend.build(serve.name, env, serve.mounts or [], build_steps)
1020
1037
  runner.build(serve)
1021
1038
  if serve.prepare and not skip_prepare:
1022
1039
  runner.prepare(env, serve.prepare)
@@ -0,0 +1,110 @@
1
+ from pathlib import Path
2
+ from typing import Dict, Optional
3
+
4
+ from .base import (
5
+ DetectResult,
6
+ DependencySpec,
7
+ Provider,
8
+ _exists,
9
+ ServiceSpec,
10
+ VolumeSpec,
11
+ MountSpec,
12
+ Config,
13
+ )
14
+ from .base import Config, Provider
15
+ from pydantic_settings import SettingsConfigDict
16
+
17
+
18
+ class GoConfig(Config):
19
+ model_config = SettingsConfigDict(extra="ignore", env_prefix="SHIPIT_")
20
+
21
+ go_version: Optional[str] = "1.25.5"
22
+ go_build_file: Optional[str] = None
23
+ serve_binary: Optional[str] = None
24
+
25
+
26
+ class GoProvider(Provider):
27
+ def __init__(self, path: Path, config: GoConfig):
28
+ self.path = path
29
+ self.config = config
30
+
31
+ @classmethod
32
+ def load_config(cls, path: Path, base_config: Config) -> GoConfig:
33
+ config = GoConfig()
34
+ if not config.go_build_file:
35
+ build_file = cls.get_build_file(path)
36
+ config.go_build_file = build_file
37
+ if not config.go_build_file:
38
+ raise Exception("No build file for go found")
39
+ if not config.serve_binary:
40
+ config.serve_binary = config.go_build_file.replace("/", "_").lower().lstrip("_").replace(".go", "")
41
+ if not config.serve_binary:
42
+ raise Exception("No serve binary for go found")
43
+ return config
44
+
45
+ @classmethod
46
+ def name(cls) -> str:
47
+ return "go"
48
+
49
+ @classmethod
50
+ def get_build_file(cls, root_path: Path) -> str:
51
+ paths_to_try = ["main.go", "server.go", "serve.go", "api.go", "web.go"]
52
+ for path in paths_to_try:
53
+ if "*" in path:
54
+ continue # This is for the glob finder
55
+ if _exists(root_path, path):
56
+ return path
57
+ if _exists(root_path, f"src/{path}"):
58
+ return f"src/{path}"
59
+ for path in paths_to_try:
60
+ found_path = next(root_path.glob(f"*/{path}"), None)
61
+ if not found_path:
62
+ found_path = next(root_path.glob(f"*/*/{path}"), None)
63
+ if found_path:
64
+ return str(found_path.relative_to(root_path))
65
+ return None
66
+
67
+ @classmethod
68
+ def detect(cls, path: Path, config: Config) -> Optional[DetectResult]:
69
+ if _exists(path, "go.mod", "go.sum"):
70
+ return DetectResult(cls.name(), 80)
71
+ return None
72
+
73
+ def serve_name(self) -> Optional[str]:
74
+ return None
75
+
76
+ def dependencies(self) -> list[DependencySpec]:
77
+ return [
78
+ DependencySpec(
79
+ "go",
80
+ var_name="config.go_version",
81
+ use_in_build=True,
82
+ ),
83
+ ]
84
+
85
+ def build_steps(self) -> list[str]:
86
+ return [
87
+ "workdir(temp.path)",
88
+ "use(go)",
89
+ 'copy(".", ".", ignore=[".git"])',
90
+ 'env(GOCACHE="/tmp/.cache/go-build", GOPATH=temp.path)',
91
+ 'run("go build -o {} {}".format(config.serve_binary, config.go_build_file), group="build")',
92
+ 'run("cp {}/{} {}/{}".format(temp.path, config.serve_binary, app.path, config.serve_binary))',
93
+ ]
94
+
95
+ def mounts(self) -> list[MountSpec]:
96
+ return [
97
+ MountSpec("temp", attach_to_serve=False),
98
+ MountSpec("app", attach_to_serve=True),
99
+ ]
100
+
101
+ def commands(self) -> Dict[str, str]:
102
+ return {
103
+ "start": '"{}/{}".format(app.serve_path, config.serve_binary)',
104
+ }
105
+
106
+ def services(self) -> list[ServiceSpec]:
107
+ return []
108
+
109
+ def volumes(self) -> list[VolumeSpec]:
110
+ return []
@@ -7,6 +7,7 @@ from .wordpress import WordPressProvider
7
7
  from .php import PhpProvider
8
8
  from .python import PythonProvider
9
9
  from .jekyll import JekyllProvider
10
+ from .go import GoProvider
10
11
  from .staticfile import StaticFileProvider
11
12
 
12
13
 
@@ -21,5 +22,6 @@ def providers() -> list[type[Provider]]:
21
22
  PhpProvider,
22
23
  NodeStaticProvider,
23
24
  JekyllProvider,
25
+ GoProvider,
24
26
  StaticFileProvider,
25
27
  ]
@@ -4,13 +4,14 @@ from typing import Dict, List, Protocol, TYPE_CHECKING
4
4
  from shipit.builders.base import BuildBackend
5
5
 
6
6
  if TYPE_CHECKING:
7
- from shipit.shipit_types import PrepareStep, Serve
7
+ from shipit.shipit_types import PrepareStep, Serve, Step
8
8
 
9
9
 
10
10
  class Runner(Protocol):
11
11
  build_backend: BuildBackend
12
12
 
13
13
  def prepare_config(self, provider_config: object) -> object: ...
14
+ def prepare_build_steps(self, build_steps: List["Step"]) -> List["Step"]: ...
14
15
  def build(self, serve: "Serve") -> None: ...
15
16
  def prepare(self, env: Dict[str, str], prepare: List["PrepareStep"]) -> None: ...
16
17
  def run_serve_command(self, command: str) -> None: ...
@@ -1,6 +1,6 @@
1
1
  import shutil
2
2
  from pathlib import Path
3
- from typing import Dict, List, Optional
3
+ from typing import Dict, List, TYPE_CHECKING
4
4
 
5
5
  import sh # type: ignore[import-untyped]
6
6
  from rich import box
@@ -12,6 +12,9 @@ from shipit.runners.base import Runner
12
12
  from shipit.shipit_types import PrepareStep, Serve
13
13
  from shipit.ui import console, write_stderr, write_stdout
14
14
 
15
+ if TYPE_CHECKING:
16
+ from shipit.shipit_types import Step
17
+
15
18
 
16
19
  class LocalRunner:
17
20
  def __init__(self, build_backend: BuildBackend, src_dir: Path) -> None:
@@ -24,6 +27,9 @@ class LocalRunner:
24
27
  def prepare_config(self, provider_config: object) -> object:
25
28
  return provider_config
26
29
 
30
+ def prepare_build_steps(self, build_steps: List["Step"]) -> List["Step"]:
31
+ return build_steps
32
+
27
33
  def get_serve_mount_path(self, name: str) -> Path:
28
34
  return self.build_backend.get_artifact_mount_path(name)
29
35
 
@@ -1,9 +1,11 @@
1
+ from shipit.shipit_types import EnvStep
2
+ from shipit.shipit_types import UseStep
1
3
  import hashlib
2
4
  import json
3
5
  import os
4
6
  import shlex
5
7
  from pathlib import Path
6
- from typing import Any, Dict, List, Optional, Set, TypedDict, cast
8
+ from typing import Any, Dict, List, Optional, Set, TypedDict, TYPE_CHECKING
7
9
 
8
10
  import sh # type: ignore[import-untyped]
9
11
  import yaml
@@ -14,10 +16,12 @@ from tomlkit import array, aot, comment, document, nl, string, table
14
16
 
15
17
  from shipit.builders.base import BuildBackend
16
18
  from shipit.runners.base import Runner
17
- from shipit.shipit_types import Package, PrepareStep, RunStep, Serve, WorkdirStep
19
+ from shipit.shipit_types import Package, PrepareStep, Serve
18
20
  from shipit.ui import console, write_stderr, write_stdout
19
21
  from shipit.version import version as shipit_version
20
22
 
23
+ if TYPE_CHECKING:
24
+ from shipit.shipit_types import Step
21
25
 
22
26
  class MapperItem(TypedDict, total=False):
23
27
  dependencies: Dict[str, str]
@@ -149,6 +153,30 @@ class WasmerRunner:
149
153
  provider_config.precompile_python = True
150
154
  return provider_config
151
155
 
156
+ def prepare_build_steps(self, build_steps: List["Step"]) -> List["Step"]:
157
+ new_build_steps: List["Step"] = []
158
+ for step in build_steps:
159
+ if isinstance(step, UseStep):
160
+ deps = []
161
+ found_go = False
162
+ for package in step.dependencies:
163
+ if package.name == "go":
164
+ deps.append(Package(name="go-wasix"))
165
+ found_go = True
166
+ else:
167
+ deps.append(package)
168
+ if found_go:
169
+ step = UseStep(dependencies=deps)
170
+ new_build_steps.append(step)
171
+ if found_go:
172
+ new_build_steps.append(EnvStep(variables={
173
+ "GOOS": "wasip1",
174
+ "GOARCH": "wasm",
175
+ }))
176
+ else:
177
+ new_build_steps.append(step)
178
+ return new_build_steps
179
+
152
180
  def build(self, serve: Serve) -> None:
153
181
  self.build_prepare(serve)
154
182
  self.build_serve(serve)
@@ -211,6 +239,17 @@ class WasmerRunner:
211
239
  ],
212
240
  )
213
241
 
242
+ def find_file_in_mounts(self, serve: Serve, program: str) -> Optional[Path]:
243
+ program_path = Path(program)
244
+ for mount in serve.mounts:
245
+ if program.startswith(str(mount.serve_path.absolute())):
246
+ module_path = program_path.relative_to(mount.serve_path).as_posix()
247
+ full_module_path = self.build_backend.get_artifact_mount_path(
248
+ mount.name
249
+ ) / module_path
250
+ return full_module_path
251
+ return None
252
+
214
253
  def build_serve(self, serve: Serve) -> None:
215
254
  doc = document()
216
255
  doc.add(comment(f"Wasmer manifest generated with Shipit v{shipit_version}"))
@@ -278,7 +317,8 @@ class WasmerRunner:
278
317
  ),
279
318
  )
280
319
 
281
- doc.add(nl())
320
+ modules = None
321
+
282
322
  if serve.commands:
283
323
  commands = aot()
284
324
  doc.add("command", commands)
@@ -287,27 +327,54 @@ class WasmerRunner:
287
327
  commands.append(command)
288
328
  parts = shlex.split(command_line)
289
329
  program = parts[0]
330
+ command_env = {}
331
+ command_module = None
290
332
  if program in self.rewrite_binaries:
291
333
  rewritten_program = shlex.split(self.rewrite_binaries[program])
292
334
  program = rewritten_program[0]
293
335
  parts[:1] = rewritten_program
294
336
  elif program not in binaries:
295
- raise Exception(f"Binary {program} not runable in Wasmer yet")
337
+ if program.startswith("/"):
338
+ # It's an executable
339
+ full_module_path = self.find_file_in_mounts(serve, program)
340
+ if not full_module_path:
341
+ raise Exception(f"Could not find {program} in the mounts or in the binaries list")
342
+ # Check if is a WebAssembly module by checking the contents
343
+ if not full_module_path.read_bytes().startswith(b"\0asm"):
344
+ raise Exception(f"Wasmer can only execute WebAssembly modules, binary {program} is not.")
345
+
346
+ if not modules:
347
+ modules = aot()
348
+ doc.add("module", modules)
349
+
350
+ module = table()
351
+ modules.append(module)
352
+ module_name = program.replace("/", "_").lower().lstrip("_")
353
+ module.add("name", module_name)
354
+ module.add("source", str(full_module_path.absolute()))
355
+
356
+ command_module = module_name
357
+ else:
358
+ raise Exception(f"Binary {program} not runable in Wasmer yet")
359
+
360
+ if not command_module:
361
+ program_binary = binaries.get(program)
362
+ if not program_binary:
363
+ raise Exception(f"Command {command_name} is trying to run {program} but it is not available (dependencies: {', '.join(dependencies.keys())}, programs: {', '.join(binaries.keys())})")
364
+ command_module = program_binary["script"]
365
+ command_env.update(program_binary.get("env") or {})
366
+
296
367
  command.add("name", command_name)
297
- program_binary = binaries.get(program)
298
- if not program_binary:
299
- raise Exception(f"Command {command_name} is trying to run {program} but it is not available (dependencies: {', '.join(dependencies.keys())}, programs: {', '.join(binaries.keys())})")
300
- command.add("module", program_binary["script"])
368
+ command.add("module", command_module)
301
369
  command.add("runner", "wasi")
302
370
  wasi_args = table()
303
371
  if serve.cwd:
304
372
  wasi_args.add("cwd", serve.cwd)
305
373
  wasi_args.add("main-args", array(parts[1:]).multiline(True))
306
- env = program_binary.get("env") or {}
307
374
  if serve.env:
308
- env.update(serve.env)
309
- if env:
310
- arr = array([f"{k}={v}" for k, v in env.items()]).multiline(True)
375
+ command_env.update(serve.env)
376
+ if command_env:
377
+ arr = array([f"{k}={v}" for k, v in command_env.items()]).multiline(True)
311
378
  wasi_args.add("env", arr)
312
379
  title = string("annotations.wasi", literal=False)
313
380
  command.add(title, wasi_args)
@@ -0,0 +1,5 @@
1
+ __all__ = ["version", "version_info"]
2
+
3
+
4
+ version = "0.16.1"
5
+ version_info = (0, 16, 1, "final", 0)
@@ -1,5 +0,0 @@
1
- __all__ = ["version", "version_info"]
2
-
3
-
4
- version = "0.15.2"
5
- version_info = (0, 15, 2, "final", 0)
File without changes
File without changes