shipit-cli 0.15.2__tar.gz → 0.16.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.
- {shipit_cli-0.15.2 → shipit_cli-0.16.0}/PKG-INFO +1 -1
- {shipit_cli-0.15.2 → shipit_cli-0.16.0}/pyproject.toml +1 -1
- {shipit_cli-0.15.2 → shipit_cli-0.16.0}/src/shipit/assets/wordpress/wp-config.php +69 -11
- {shipit_cli-0.15.2 → shipit_cli-0.16.0}/src/shipit/builders/docker.py +10 -3
- {shipit_cli-0.15.2 → shipit_cli-0.16.0}/src/shipit/cli.py +20 -3
- shipit_cli-0.16.0/src/shipit/providers/go.py +110 -0
- {shipit_cli-0.15.2 → shipit_cli-0.16.0}/src/shipit/providers/registry.py +2 -0
- {shipit_cli-0.15.2 → shipit_cli-0.16.0}/src/shipit/runners/base.py +2 -1
- {shipit_cli-0.15.2 → shipit_cli-0.16.0}/src/shipit/runners/local.py +7 -1
- {shipit_cli-0.15.2 → shipit_cli-0.16.0}/src/shipit/runners/wasmer.py +79 -12
- shipit_cli-0.16.0/src/shipit/version.py +5 -0
- shipit_cli-0.15.2/src/shipit/version.py +0 -5
- {shipit_cli-0.15.2 → shipit_cli-0.16.0}/.gitignore +0 -0
- {shipit_cli-0.15.2 → shipit_cli-0.16.0}/README.md +0 -0
- {shipit_cli-0.15.2 → shipit_cli-0.16.0}/src/shipit/__init__.py +0 -0
- {shipit_cli-0.15.2 → shipit_cli-0.16.0}/src/shipit/assets/php/php.ini +0 -0
- {shipit_cli-0.15.2 → shipit_cli-0.16.0}/src/shipit/assets/wordpress/install.sh +0 -0
- {shipit_cli-0.15.2 → shipit_cli-0.16.0}/src/shipit/builders/__init__.py +0 -0
- {shipit_cli-0.15.2 → shipit_cli-0.16.0}/src/shipit/builders/base.py +0 -0
- {shipit_cli-0.15.2 → shipit_cli-0.16.0}/src/shipit/builders/local.py +0 -0
- {shipit_cli-0.15.2 → shipit_cli-0.16.0}/src/shipit/generator.py +0 -0
- {shipit_cli-0.15.2 → shipit_cli-0.16.0}/src/shipit/procfile.py +0 -0
- {shipit_cli-0.15.2 → shipit_cli-0.16.0}/src/shipit/providers/base.py +0 -0
- {shipit_cli-0.15.2 → shipit_cli-0.16.0}/src/shipit/providers/hugo.py +0 -0
- {shipit_cli-0.15.2 → shipit_cli-0.16.0}/src/shipit/providers/jekyll.py +0 -0
- {shipit_cli-0.15.2 → shipit_cli-0.16.0}/src/shipit/providers/laravel.py +0 -0
- {shipit_cli-0.15.2 → shipit_cli-0.16.0}/src/shipit/providers/mkdocs.py +0 -0
- {shipit_cli-0.15.2 → shipit_cli-0.16.0}/src/shipit/providers/node_static.py +0 -0
- {shipit_cli-0.15.2 → shipit_cli-0.16.0}/src/shipit/providers/php.py +0 -0
- {shipit_cli-0.15.2 → shipit_cli-0.16.0}/src/shipit/providers/python.py +0 -0
- {shipit_cli-0.15.2 → shipit_cli-0.16.0}/src/shipit/providers/staticfile.py +0 -0
- {shipit_cli-0.15.2 → shipit_cli-0.16.0}/src/shipit/providers/wordpress.py +0 -0
- {shipit_cli-0.15.2 → shipit_cli-0.16.0}/src/shipit/runners/__init__.py +0 -0
- {shipit_cli-0.15.2 → shipit_cli-0.16.0}/src/shipit/shipit_types.py +0 -0
- {shipit_cli-0.15.2 → shipit_cli-0.16.0}/src/shipit/ui.py +0 -0
- {shipit_cli-0.15.2 → shipit_cli-0.16.0}/src/shipit/utils.py +0 -0
- {shipit_cli-0.15.2 → shipit_cli-0.16.0}/tests/test_e2e.py +0 -0
- {shipit_cli-0.15.2 → shipit_cli-0.16.0}/tests/test_generate_shipit_examples.py +0 -0
- {shipit_cli-0.15.2 → shipit_cli-0.16.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.
|
|
3
|
+
Version: 0.16.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
|
|
@@ -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
|
-
|
|
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',
|
|
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',
|
|
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 [],
|
|
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
|
+
'copy("{}/{}".format(temp.path, config.serve_binary), "{}/{}".format(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,
|
|
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,
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
309
|
-
if
|
|
310
|
-
arr = array([f"{k}={v}" for k, v in
|
|
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)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|