shipit-cli 0.7.0__py3-none-any.whl → 0.8.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.
- shipit/assets/wordpress/install.sh +4 -9
- shipit/cli.py +57 -34
- shipit/generator.py +14 -2
- shipit/providers/hugo.py +6 -2
- shipit/providers/laravel.py +1 -1
- shipit/providers/mkdocs.py +2 -0
- shipit/providers/php.py +2 -2
- shipit/providers/python.py +16 -15
- shipit/providers/staticfile.py +12 -2
- shipit/providers/wordpress.py +1 -1
- shipit/version.py +2 -2
- {shipit_cli-0.7.0.dist-info → shipit_cli-0.8.0.dist-info}/METADATA +2 -1
- shipit_cli-0.8.0.dist-info/RECORD +23 -0
- shipit/env.py +0 -30
- shipit_cli-0.7.0.dist-info/RECORD +0 -24
- {shipit_cli-0.7.0.dist-info → shipit_cli-0.8.0.dist-info}/WHEEL +0 -0
- {shipit_cli-0.7.0.dist-info → shipit_cli-0.8.0.dist-info}/entry_points.txt +0 -0
|
@@ -12,7 +12,7 @@ echo "" > wp-content/upgrade/.keep
|
|
|
12
12
|
|
|
13
13
|
echo "Installing WordPress core..."
|
|
14
14
|
|
|
15
|
-
wp
|
|
15
|
+
wp core install \
|
|
16
16
|
--url="$WASMER_APP_URL" \
|
|
17
17
|
--title="$WP_SITE_TITLE" \
|
|
18
18
|
--admin_user="$WP_ADMIN_USERNAME" \
|
|
@@ -21,13 +21,8 @@ wp-cli core install \
|
|
|
21
21
|
--locale="$WP_LOCALE"
|
|
22
22
|
|
|
23
23
|
|
|
24
|
-
if [ -z "$
|
|
25
|
-
wp
|
|
26
|
-
fi
|
|
27
|
-
|
|
28
|
-
echo "Installing theme..."
|
|
29
|
-
wp-cli wasmer-aio-install install \
|
|
30
|
-
--locale="$WP_LOCALE" \
|
|
31
|
-
--theme=twentytwentyfive || true
|
|
24
|
+
if [ -z "$WP_UPDATE_DB" ]; then
|
|
25
|
+
wp core update-db
|
|
26
|
+
fi
|
|
32
27
|
|
|
33
28
|
echo "Installation complete"
|
shipit/cli.py
CHANGED
|
@@ -36,6 +36,7 @@ from shipit.version import version as shipit_version
|
|
|
36
36
|
from shipit.generator import generate_shipit
|
|
37
37
|
from shipit.providers.base import CustomCommands
|
|
38
38
|
from shipit.procfile import Procfile
|
|
39
|
+
from dotenv import dotenv_values
|
|
39
40
|
|
|
40
41
|
|
|
41
42
|
console = Console()
|
|
@@ -147,10 +148,12 @@ class Build:
|
|
|
147
148
|
|
|
148
149
|
def write_stdout(line: str) -> None:
|
|
149
150
|
sys.stdout.write(line) # print to console
|
|
151
|
+
sys.stdout.flush()
|
|
150
152
|
|
|
151
153
|
|
|
152
154
|
def write_stderr(line: str) -> None:
|
|
153
155
|
sys.stderr.write(line) # print to console
|
|
156
|
+
sys.stderr.flush()
|
|
154
157
|
|
|
155
158
|
|
|
156
159
|
class MapperItem(TypedDict):
|
|
@@ -178,6 +181,16 @@ class Builder(Protocol):
|
|
|
178
181
|
|
|
179
182
|
|
|
180
183
|
class DockerBuilder:
|
|
184
|
+
mise_mapper = {
|
|
185
|
+
"php": {
|
|
186
|
+
"source": "ubi:adwinying/php",
|
|
187
|
+
},
|
|
188
|
+
"composer": {
|
|
189
|
+
"source": "ubi:composer/composer",
|
|
190
|
+
"postinstall": """composer_dir=$(mise where ubi:composer/composer); ln -s "$composer_dir/composer.phar" /usr/local/bin/composer""",
|
|
191
|
+
},
|
|
192
|
+
}
|
|
193
|
+
|
|
181
194
|
def __init__(self, src_dir: Path, docker_client: Optional[str] = None) -> None:
|
|
182
195
|
self.src_dir = src_dir
|
|
183
196
|
self.docker_file_contents = ""
|
|
@@ -339,12 +352,17 @@ RUN chmod {oct(mode)[2:]} {path.absolute()}
|
|
|
339
352
|
)
|
|
340
353
|
self.docker_file_contents += f"RUN curl --proto '=https' --tlsv1.2 -sSfL https://get.static-web-server.net | sh\n"
|
|
341
354
|
return
|
|
355
|
+
|
|
356
|
+
mapped_dependency = self.mise_mapper.get(dependency.name, {})
|
|
357
|
+
package_name = mapped_dependency.get("source", dependency.name)
|
|
342
358
|
if dependency.version:
|
|
343
359
|
self.docker_file_contents += (
|
|
344
|
-
f"RUN mise use --global {
|
|
360
|
+
f"RUN mise use --global {package_name}@{dependency.version}\n"
|
|
345
361
|
)
|
|
346
362
|
else:
|
|
347
|
-
self.docker_file_contents += f"RUN mise use --global {
|
|
363
|
+
self.docker_file_contents += f"RUN mise use --global {package_name}\n"
|
|
364
|
+
if mapped_dependency.get("postinstall"):
|
|
365
|
+
self.docker_file_contents += f"RUN {mapped_dependency.get('postinstall')}\n"
|
|
348
366
|
|
|
349
367
|
def build(
|
|
350
368
|
self, env: Dict[str, str], mounts: List[Mount], steps: List[Step]
|
|
@@ -357,8 +375,8 @@ RUN chmod {oct(mode)[2:]} {path.absolute()}
|
|
|
357
375
|
self.docker_file_contents += """
|
|
358
376
|
RUN apt-get update \\
|
|
359
377
|
&& apt-get -y --no-install-recommends install \\
|
|
360
|
-
build-essential gcc make \\
|
|
361
|
-
dpkg-dev pkg-config \\
|
|
378
|
+
build-essential gcc make autoconf libtool bison \\
|
|
379
|
+
dpkg-dev pkg-config re2c locate \\
|
|
362
380
|
libmariadb-dev libmariadb-dev-compat libpq-dev \\
|
|
363
381
|
sudo curl ca-certificates \\
|
|
364
382
|
&& rm -rf /var/lib/apt/lists/*
|
|
@@ -406,7 +424,7 @@ RUN curl https://mise.run | sh
|
|
|
406
424
|
# Read the file content and write it to the target file
|
|
407
425
|
content_base64 = base64.b64encode(
|
|
408
426
|
(ASSETS_PATH / step.source).read_bytes()
|
|
409
|
-
)
|
|
427
|
+
).decode("utf-8")
|
|
410
428
|
self.docker_file_contents += (
|
|
411
429
|
f"RUN echo '{content_base64}' | base64 -d > {step.target}\n"
|
|
412
430
|
)
|
|
@@ -445,12 +463,6 @@ Shipit
|
|
|
445
463
|
def get_path(self) -> Path:
|
|
446
464
|
return Path("/")
|
|
447
465
|
|
|
448
|
-
def get_build_path(self) -> Path:
|
|
449
|
-
return self.get_path() / "app"
|
|
450
|
-
|
|
451
|
-
def get_serve_path(self) -> Path:
|
|
452
|
-
return self.get_path() / "serve"
|
|
453
|
-
|
|
454
466
|
def prepare(self, env: Dict[str, str], prepare: List[PrepareStep]) -> None:
|
|
455
467
|
raise NotImplementedError
|
|
456
468
|
|
|
@@ -460,13 +472,12 @@ Shipit
|
|
|
460
472
|
for dep in serve.deps:
|
|
461
473
|
self.add_dependency(dep)
|
|
462
474
|
|
|
463
|
-
build_path = self.get_build_path()
|
|
464
475
|
for command in serve.commands:
|
|
465
476
|
console.print(f"* {command}")
|
|
466
477
|
command_path = serve_command_path / command
|
|
467
478
|
self.create_file(
|
|
468
479
|
command_path,
|
|
469
|
-
f"#!/bin/bash\ncd {
|
|
480
|
+
f"#!/bin/bash\ncd {serve.cwd}\n{serve.commands[command]}",
|
|
470
481
|
mode=0o755,
|
|
471
482
|
)
|
|
472
483
|
|
|
@@ -479,6 +490,7 @@ class LocalBuilder:
|
|
|
479
490
|
def __init__(self, src_dir: Path) -> None:
|
|
480
491
|
self.src_dir = src_dir
|
|
481
492
|
self.local_path = self.src_dir / ".shipit" / "local"
|
|
493
|
+
self.serve_bin_path = self.local_path / "serve" / "bin"
|
|
482
494
|
self.prepare_bash_script = self.local_path / "prepare" / "prepare.sh"
|
|
483
495
|
self.build_path = self.local_path / "build"
|
|
484
496
|
self.workdir = self.build_path
|
|
@@ -502,6 +514,8 @@ class LocalBuilder:
|
|
|
502
514
|
elif isinstance(step, WorkdirStep):
|
|
503
515
|
console.print(f"[bold]Working in {step.path}[/bold]")
|
|
504
516
|
self.workdir = step.path
|
|
517
|
+
# We make sure the dir exists
|
|
518
|
+
step.path.mkdir(parents=True, exist_ok=True)
|
|
505
519
|
elif isinstance(step, RunStep):
|
|
506
520
|
extra = ""
|
|
507
521
|
if step.inputs:
|
|
@@ -627,12 +641,6 @@ class LocalBuilder:
|
|
|
627
641
|
def get_path(self) -> Path:
|
|
628
642
|
return self.local_path
|
|
629
643
|
|
|
630
|
-
def get_build_path(self) -> Path:
|
|
631
|
-
return self.get_path() / "build"
|
|
632
|
-
|
|
633
|
-
def get_serve_path(self) -> Path:
|
|
634
|
-
return self.get_path() / "serve"
|
|
635
|
-
|
|
636
644
|
def build_prepare(self, serve: Serve) -> None:
|
|
637
645
|
self.prepare_bash_script.parent.mkdir(parents=True, exist_ok=True)
|
|
638
646
|
commands: List[str] = []
|
|
@@ -675,14 +683,13 @@ class LocalBuilder:
|
|
|
675
683
|
def build_serve(self, serve: Serve) -> None:
|
|
676
684
|
# Remember serve configuration for run-time
|
|
677
685
|
console.print("\n[bold]Building serve[/bold]")
|
|
678
|
-
|
|
679
|
-
serve_command_path.mkdir(parents=True, exist_ok=False)
|
|
686
|
+
self.serve_bin_path.mkdir(parents=True, exist_ok=False)
|
|
680
687
|
path = self.get_path() / ".path"
|
|
681
688
|
path_text = path.read_text()
|
|
682
689
|
console.print(f"[bold]Serve Commands:[/bold]")
|
|
683
690
|
for command in serve.commands:
|
|
684
691
|
console.print(f"* {command}")
|
|
685
|
-
command_path =
|
|
692
|
+
command_path = self.serve_bin_path / command
|
|
686
693
|
env_vars = ""
|
|
687
694
|
if serve.env:
|
|
688
695
|
env_vars = " ".join([f"{k}={v}" for k, v in serve.env.items()])
|
|
@@ -706,8 +713,7 @@ class LocalBuilder:
|
|
|
706
713
|
|
|
707
714
|
def run_serve_command(self, command: str) -> None:
|
|
708
715
|
console.print(f"\n[bold]Running {command} command[/bold]")
|
|
709
|
-
|
|
710
|
-
command_path = base_path / command
|
|
716
|
+
command_path = self.serve_bin_path / command
|
|
711
717
|
sh.Command(str(command_path))(_out=write_stdout, _err=write_stderr)
|
|
712
718
|
|
|
713
719
|
|
|
@@ -807,9 +813,6 @@ class WasmerBuilder:
|
|
|
807
813
|
) -> None:
|
|
808
814
|
return self.inner_builder.build(env, mounts, build)
|
|
809
815
|
|
|
810
|
-
def get_build_path(self) -> Path:
|
|
811
|
-
return Path("/app")
|
|
812
|
-
|
|
813
816
|
def build_prepare(self, serve: Serve) -> None:
|
|
814
817
|
print("Building prepare")
|
|
815
818
|
prepare_dir = self.wasmer_dir_path / "prepare"
|
|
@@ -877,10 +880,10 @@ class WasmerBuilder:
|
|
|
877
880
|
)
|
|
878
881
|
|
|
879
882
|
def build_serve(self, serve: Serve) -> None:
|
|
880
|
-
from tomlkit import comment, document, nl, table, aot, string
|
|
883
|
+
from tomlkit import comment, document, nl, table, aot, string, array
|
|
881
884
|
|
|
882
885
|
doc = document()
|
|
883
|
-
doc.add(comment(f"
|
|
886
|
+
doc.add(comment(f"Wasmer manifest generated with Shipit v{shipit_version}"))
|
|
884
887
|
package = table()
|
|
885
888
|
doc.add("package", package)
|
|
886
889
|
package.add("entrypoint", "start")
|
|
@@ -953,14 +956,14 @@ class WasmerBuilder:
|
|
|
953
956
|
wasi_args = table()
|
|
954
957
|
if serve.cwd:
|
|
955
958
|
wasi_args.add("cwd", serve.cwd)
|
|
956
|
-
wasi_args.add("main-args", parts[1:])
|
|
959
|
+
wasi_args.add("main-args", array(parts[1:]).multiline(True))
|
|
957
960
|
env = program_binary.get("env") or {}
|
|
958
961
|
if serve.env:
|
|
959
962
|
env.update(serve.env)
|
|
960
963
|
if env:
|
|
964
|
+
arr = array([f"{k}={v}" for k, v in env.items()]).multiline(True)
|
|
961
965
|
wasi_args.add(
|
|
962
|
-
"env",
|
|
963
|
-
[f"{k}={v}" for k, v in env.items()],
|
|
966
|
+
"env", arr
|
|
964
967
|
)
|
|
965
968
|
title = string("annotations.wasi", literal=False)
|
|
966
969
|
command.add(title, wasi_args)
|
|
@@ -1038,7 +1041,7 @@ class WasmerBuilder:
|
|
|
1038
1041
|
)
|
|
1039
1042
|
yaml_config["jobs"] = jobs
|
|
1040
1043
|
|
|
1041
|
-
app_yaml = yaml.dump(yaml_config)
|
|
1044
|
+
app_yaml = yaml.dump(yaml_config,)
|
|
1042
1045
|
|
|
1043
1046
|
console.print(f"\n[bold]Created app.yaml manifest ✅[/bold]")
|
|
1044
1047
|
app_yaml_panel = Panel(
|
|
@@ -1385,6 +1388,10 @@ def auto(
|
|
|
1385
1388
|
None,
|
|
1386
1389
|
help="The start command to use (overwrites the default)",
|
|
1387
1390
|
),
|
|
1391
|
+
env_name: Optional[str] = typer.Option(
|
|
1392
|
+
None,
|
|
1393
|
+
help="The environment to use (defaults to `.env`, it will use .env.<env_name> if provided)",
|
|
1394
|
+
),
|
|
1388
1395
|
):
|
|
1389
1396
|
if not path.exists():
|
|
1390
1397
|
raise Exception(f"The path {path} does not exist")
|
|
@@ -1408,6 +1415,7 @@ def auto(
|
|
|
1408
1415
|
wasmer_token=wasmer_token,
|
|
1409
1416
|
wasmer_bin=wasmer_bin,
|
|
1410
1417
|
skip_prepare=skip_prepare,
|
|
1418
|
+
env_name=env_name,
|
|
1411
1419
|
)
|
|
1412
1420
|
if start or wasmer_deploy:
|
|
1413
1421
|
serve(
|
|
@@ -1612,6 +1620,10 @@ def build(
|
|
|
1612
1620
|
None,
|
|
1613
1621
|
help="Use a specific Docker client (such as depot, podman, etc.)",
|
|
1614
1622
|
),
|
|
1623
|
+
env_name: Optional[str] = typer.Option(
|
|
1624
|
+
None,
|
|
1625
|
+
help="The environment to use (defaults to `.env`, it will use .env.<env_name> if provided)",
|
|
1626
|
+
),
|
|
1615
1627
|
) -> None:
|
|
1616
1628
|
if not path.exists():
|
|
1617
1629
|
raise Exception(f"The path {path} does not exist")
|
|
@@ -1664,6 +1676,14 @@ def build(
|
|
|
1664
1676
|
"CLICOLOR": os.environ.get("CLICOLOR", "0"),
|
|
1665
1677
|
}
|
|
1666
1678
|
serve = next(iter(ctx.serves.values()))
|
|
1679
|
+
serve.env = serve.env or {}
|
|
1680
|
+
if (path / ".env").exists():
|
|
1681
|
+
env_vars = dotenv_values(path / ".env")
|
|
1682
|
+
serve.env.update(env_vars)
|
|
1683
|
+
|
|
1684
|
+
if (path / f".env.{env_name}").exists():
|
|
1685
|
+
env_vars = dotenv_values(path / f".env.{env_name}")
|
|
1686
|
+
serve.env.update(env_vars)
|
|
1667
1687
|
|
|
1668
1688
|
# Build and serve
|
|
1669
1689
|
builder.build(env, serve.mounts, serve.build)
|
|
@@ -1686,8 +1706,11 @@ def main() -> None:
|
|
|
1686
1706
|
app()
|
|
1687
1707
|
except Exception as e:
|
|
1688
1708
|
console.print(f"[bold red]{type(e).__name__}[/bold red]: {e}")
|
|
1689
|
-
raise e
|
|
1709
|
+
# raise e
|
|
1690
1710
|
|
|
1691
1711
|
|
|
1692
1712
|
if __name__ == "__main__":
|
|
1693
1713
|
main()
|
|
1714
|
+
|
|
1715
|
+
def flatten(xss):
|
|
1716
|
+
return [x for xs in xss for x in xs]
|
shipit/generator.py
CHANGED
|
@@ -109,7 +109,7 @@ def generate_shipit(path: Path, custom_commands: CustomCommands) -> str:
|
|
|
109
109
|
|
|
110
110
|
build_steps_block = ",\n".join([f" {s}" for s in build_steps])
|
|
111
111
|
deps_array = ", ".join(serve_dep_vars)
|
|
112
|
-
commands_lines = ",\n".join([f' "{k}": {v}' for k, v in plan.commands.items()])
|
|
112
|
+
commands_lines = ",\n".join([f' "{k}": {v}.replace("$PORT", PORT)' for k, v in plan.commands.items()])
|
|
113
113
|
env_lines = None
|
|
114
114
|
if plan.env is not None:
|
|
115
115
|
if len(plan.env) == 0:
|
|
@@ -119,31 +119,43 @@ def generate_shipit(path: Path, custom_commands: CustomCommands) -> str:
|
|
|
119
119
|
mounts_block = None
|
|
120
120
|
volumes_block = None
|
|
121
121
|
attach_serve_names: list[str] = []
|
|
122
|
+
|
|
122
123
|
if plan.mounts:
|
|
123
124
|
mounts = list(filter(lambda m: m.attach_to_serve, plan.mounts))
|
|
124
125
|
attach_serve_names = [m.name for m in mounts]
|
|
125
126
|
mounts_block = ",\n".join([f" {m.name}" for m in mounts])
|
|
127
|
+
|
|
126
128
|
if plan.volumes:
|
|
127
129
|
volumes_block = ",\n".join(
|
|
128
130
|
[f" {v.var_name or v.name}" for v in plan.volumes]
|
|
129
131
|
)
|
|
130
132
|
|
|
131
133
|
out: List[str] = []
|
|
134
|
+
|
|
132
135
|
if dep_block:
|
|
133
136
|
out.append(dep_block)
|
|
134
137
|
out.append("")
|
|
138
|
+
|
|
135
139
|
for m in plan.mounts:
|
|
136
140
|
out.append(f"{m.name} = mount(\"{m.name}\")")
|
|
141
|
+
out.append("")
|
|
142
|
+
|
|
137
143
|
if plan.volumes:
|
|
138
144
|
for v in plan.volumes:
|
|
139
145
|
out.append(f"{v.var_name or v.name} = volume(\"{v.name}\", {v.serve_path})")
|
|
146
|
+
out.append("")
|
|
147
|
+
|
|
140
148
|
if plan.services:
|
|
141
149
|
for s in plan.services:
|
|
142
150
|
out.append(f"{s.name} = service(\n name=\"{s.name}\",\n provider=\"{s.provider}\"\n)")
|
|
151
|
+
out.append("")
|
|
152
|
+
|
|
153
|
+
out.append("PORT = getenv(\"PORT\") or\"8080\"")
|
|
143
154
|
|
|
144
155
|
if plan.declarations:
|
|
145
156
|
out.append(plan.declarations)
|
|
146
|
-
|
|
157
|
+
|
|
158
|
+
out.append("")
|
|
147
159
|
out.append("serve(")
|
|
148
160
|
out.append(f' name="{plan.serve_name}",')
|
|
149
161
|
out.append(f' provider="{plan.provider}",')
|
shipit/providers/hugo.py
CHANGED
|
@@ -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, ServiceSpec, VolumeSpec, CustomCommands
|
|
6
|
+
from .base import DetectResult, DependencySpec, Provider, _exists, ServiceSpec, VolumeSpec, CustomCommands, MountSpec
|
|
7
7
|
from .staticfile import StaticFileProvider
|
|
8
8
|
|
|
9
9
|
class HugoProvider(StaticFileProvider):
|
|
@@ -43,10 +43,14 @@ class HugoProvider(StaticFileProvider):
|
|
|
43
43
|
|
|
44
44
|
def build_steps(self) -> list[str]:
|
|
45
45
|
return [
|
|
46
|
+
'workdir(temp["build"])',
|
|
46
47
|
'copy(".", ".", ignore=[".git"])',
|
|
47
48
|
'run("hugo build --destination={}".format(app["build"]), group="build")',
|
|
48
49
|
]
|
|
49
|
-
|
|
50
|
+
|
|
51
|
+
def mounts(self) -> list[MountSpec]:
|
|
52
|
+
return [MountSpec("temp", attach_to_serve=False), *super().mounts()]
|
|
53
|
+
|
|
50
54
|
def services(self) -> list[ServiceSpec]:
|
|
51
55
|
return []
|
|
52
56
|
|
shipit/providers/laravel.py
CHANGED
shipit/providers/mkdocs.py
CHANGED
|
@@ -30,6 +30,8 @@ class MkdocsProvider(StaticFileProvider):
|
|
|
30
30
|
def detect(cls, path: Path, custom_commands: CustomCommands) -> Optional[DetectResult]:
|
|
31
31
|
if _exists(path, "mkdocs.yml", "mkdocs.yaml"):
|
|
32
32
|
return DetectResult(cls.name(), 85)
|
|
33
|
+
if custom_commands.build and custom_commands.build.startswith("mkdocs "):
|
|
34
|
+
return DetectResult(cls.name(), 85)
|
|
33
35
|
return None
|
|
34
36
|
|
|
35
37
|
def initialize(self) -> None:
|
shipit/providers/php.py
CHANGED
|
@@ -92,9 +92,9 @@ class PhpProvider:
|
|
|
92
92
|
|
|
93
93
|
def base_commands(self) -> Dict[str, str]:
|
|
94
94
|
if _exists(self.path, "public/index.php"):
|
|
95
|
-
return {"start": '"php -S localhost:
|
|
95
|
+
return {"start": 'f"php -S localhost:{PORT} -t public"'}
|
|
96
96
|
elif _exists(self.path, "index.php"):
|
|
97
|
-
return {"start": '"php -S localhost:
|
|
97
|
+
return {"start": 'f"php -S localhost:{PORT} -t ."'}
|
|
98
98
|
|
|
99
99
|
def mounts(self) -> list[MountSpec]:
|
|
100
100
|
return [
|
shipit/providers/python.py
CHANGED
|
@@ -284,7 +284,7 @@ class PythonProvider:
|
|
|
284
284
|
if not self.only_build:
|
|
285
285
|
steps = ['workdir(app["build"])']
|
|
286
286
|
else:
|
|
287
|
-
steps = []
|
|
287
|
+
steps = ['workdir(temp["build"])']
|
|
288
288
|
|
|
289
289
|
extra_deps = ", ".join([f"{dep}" for dep in self.extra_dependencies])
|
|
290
290
|
has_requirements = _exists(self.path, "requirements.txt")
|
|
@@ -317,7 +317,7 @@ class PythonProvider:
|
|
|
317
317
|
]
|
|
318
318
|
if not self.only_build:
|
|
319
319
|
steps += [
|
|
320
|
-
'run(f"uv pip compile pyproject.toml --python-version={python_version} --universal --extra-index-url {python_extra_index_url} --index-url=https://pypi.org/simple --emit-index-url -o cross-requirements.txt", outputs=["cross-requirements.txt"]) if cross_platform else None',
|
|
320
|
+
'run(f"uv pip compile pyproject.toml --python-version={python_version} --universal --extra-index-url {python_extra_index_url} --index-url=https://pypi.org/simple --emit-index-url --no-deps -o cross-requirements.txt", outputs=["cross-requirements.txt"]) if cross_platform else None',
|
|
321
321
|
f'run(f"uvx pip install -r cross-requirements.txt {extra_deps} --target {{python_cross_packages_path}} --platform {{cross_platform}} --only-binary=:all: --python-version={{python_version}} --compile") if cross_platform else None',
|
|
322
322
|
'run("rm cross-requirements.txt") if cross_platform else None',
|
|
323
323
|
]
|
|
@@ -337,7 +337,7 @@ class PythonProvider:
|
|
|
337
337
|
]
|
|
338
338
|
if not self.only_build:
|
|
339
339
|
steps += [
|
|
340
|
-
'run(f"uv pip compile requirements.txt --python-version={python_version} --universal --extra-index-url {python_extra_index_url} --index-url=https://pypi.org/simple --emit-index-url -o cross-requirements.txt", inputs=["requirements.txt"], outputs=["cross-requirements.txt"]) if cross_platform else None',
|
|
340
|
+
'run(f"uv pip compile requirements.txt --python-version={python_version} --universal --extra-index-url {python_extra_index_url} --index-url=https://pypi.org/simple --emit-index-url --no-deps -o cross-requirements.txt", inputs=["requirements.txt"], outputs=["cross-requirements.txt"]) if cross_platform else None',
|
|
341
341
|
f'run(f"uvx pip install -r cross-requirements.txt {extra_deps} --target {{python_cross_packages_path}} --platform {{cross_platform}} --only-binary=:all: --python-version={{python_version}} --compile") if cross_platform else None',
|
|
342
342
|
'run("rm cross-requirements.txt") if cross_platform else None',
|
|
343
343
|
]
|
|
@@ -396,20 +396,20 @@ class PythonProvider:
|
|
|
396
396
|
if self.server == PythonServer.Daphne and self.asgi_application:
|
|
397
397
|
asgi_application = format_app_import(self.asgi_application)
|
|
398
398
|
start_cmd = (
|
|
399
|
-
f'"python -m daphne {asgi_application} --bind 0.0.0.0 --port
|
|
399
|
+
f'f"python -m daphne {asgi_application} --bind 0.0.0.0 --port {{PORT}}"'
|
|
400
400
|
)
|
|
401
401
|
elif self.server == PythonServer.Uvicorn:
|
|
402
402
|
if self.asgi_application:
|
|
403
403
|
asgi_application = format_app_import(self.asgi_application)
|
|
404
|
-
start_cmd = f'"python -m uvicorn {asgi_application} --host 0.0.0.0 --port
|
|
404
|
+
start_cmd = f'f"python -m uvicorn {asgi_application} --host 0.0.0.0 --port {{PORT}}"'
|
|
405
405
|
elif self.wsgi_application:
|
|
406
406
|
wsgi_application = format_app_import(self.wsgi_application)
|
|
407
|
-
start_cmd = f'"python -m uvicorn {wsgi_application} --interface=wsgi --host 0.0.0.0 --port
|
|
407
|
+
start_cmd = f'f"python -m uvicorn {wsgi_application} --interface=wsgi --host 0.0.0.0 --port {{PORT}}"'
|
|
408
408
|
# elif self.server == PythonServer.Gunicorn:
|
|
409
|
-
# start_cmd = f'"
|
|
409
|
+
# start_cmd = f'"fpython -m gunicorn {self.wsgi_application} --bind 0.0.0.0 --port {{PORT}}"'
|
|
410
410
|
if not start_cmd:
|
|
411
411
|
# We run the default runserver command if no server is specified
|
|
412
|
-
start_cmd = '"python manage.py runserver 0.0.0.0:
|
|
412
|
+
start_cmd = 'f"python manage.py runserver 0.0.0.0:{PORT}"'
|
|
413
413
|
migrate_cmd = '"python manage.py migrate"'
|
|
414
414
|
return {"start": start_cmd, "after_deploy": migrate_cmd}
|
|
415
415
|
|
|
@@ -423,21 +423,21 @@ class PythonProvider:
|
|
|
423
423
|
python_path = file_to_python_path(main_file)
|
|
424
424
|
path = f"{python_path}:app"
|
|
425
425
|
if self.server == PythonServer.Uvicorn:
|
|
426
|
-
start_cmd = f'"python -m uvicorn {path} --host 0.0.0.0 --port
|
|
426
|
+
start_cmd = f'f"python -m uvicorn {path} --host 0.0.0.0 --port {{PORT}}"'
|
|
427
427
|
elif self.server == PythonServer.Hypercorn:
|
|
428
|
-
start_cmd = f'"python -m hypercorn {path} --bind 0.0.0.0:
|
|
428
|
+
start_cmd = f'f"python -m hypercorn {path} --bind 0.0.0.0:{{PORT}}"'
|
|
429
429
|
else:
|
|
430
430
|
start_cmd = '"python -c \'print(\\"No start command detected, please provide a start command manually\\")\'"'
|
|
431
431
|
return {"start": start_cmd}
|
|
432
432
|
|
|
433
433
|
elif self.framework == PythonFramework.Streamlit:
|
|
434
|
-
start_cmd = f'"python -m streamlit run {main_file} --server.port
|
|
434
|
+
start_cmd = f'f"python -m streamlit run {main_file} --server.port {{PORT}} --server.address 0.0.0.0 --server.headless true"'
|
|
435
435
|
|
|
436
436
|
elif self.framework == PythonFramework.Flask:
|
|
437
437
|
python_path = file_to_python_path(main_file)
|
|
438
438
|
path = f"{python_path}:app"
|
|
439
|
-
# start_cmd = f'"python -m flask --app {path} run --debug --host 0.0.0.0 --port
|
|
440
|
-
start_cmd = f'"python -m uvicorn {path} --interface=wsgi --host 0.0.0.0 --port
|
|
439
|
+
# start_cmd = f'f"python -m flask --app {path} run --debug --host 0.0.0.0 --port {{PORT}}"'
|
|
440
|
+
start_cmd = f'f"python -m uvicorn {path} --interface=wsgi --host 0.0.0.0 --port {{PORT}}"'
|
|
441
441
|
|
|
442
442
|
elif self.framework == PythonFramework.MCP:
|
|
443
443
|
contents = (self.path / main_file).read_text()
|
|
@@ -449,7 +449,7 @@ class PythonProvider:
|
|
|
449
449
|
elif self.framework == PythonFramework.FastHTML:
|
|
450
450
|
python_path = file_to_python_path(main_file)
|
|
451
451
|
path = f"{python_path}:app"
|
|
452
|
-
start_cmd = f'"python -m uvicorn {path} --host 0.0.0.0 --port
|
|
452
|
+
start_cmd = f'f"python -m uvicorn {path} --host 0.0.0.0 --port {{PORT}}"'
|
|
453
453
|
|
|
454
454
|
else:
|
|
455
455
|
start_cmd = f'"python {main_file}"'
|
|
@@ -459,6 +459,7 @@ class PythonProvider:
|
|
|
459
459
|
def mounts(self) -> list[MountSpec]:
|
|
460
460
|
if self.only_build:
|
|
461
461
|
return [
|
|
462
|
+
MountSpec("temp", attach_to_serve=False),
|
|
462
463
|
MountSpec("local_venv", attach_to_serve=False),
|
|
463
464
|
]
|
|
464
465
|
return [
|
|
@@ -486,7 +487,7 @@ class PythonProvider:
|
|
|
486
487
|
env_vars["STREAMLIT_SERVER_HEADLESS"] = '"true"'
|
|
487
488
|
elif self.framework == PythonFramework.MCP:
|
|
488
489
|
env_vars["FASTMCP_HOST"] = '"0.0.0.0"'
|
|
489
|
-
env_vars["FASTMCP_PORT"] = '
|
|
490
|
+
env_vars["FASTMCP_PORT"] = 'PORT'
|
|
490
491
|
return env_vars
|
|
491
492
|
|
|
492
493
|
def services(self) -> list[ServiceSpec]:
|
shipit/providers/staticfile.py
CHANGED
|
@@ -2,6 +2,8 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
from pathlib import Path
|
|
4
4
|
from typing import Dict, Optional
|
|
5
|
+
import json
|
|
6
|
+
import yaml
|
|
5
7
|
|
|
6
8
|
from .base import (
|
|
7
9
|
DetectResult,
|
|
@@ -16,9 +18,17 @@ from .base import (
|
|
|
16
18
|
|
|
17
19
|
|
|
18
20
|
class StaticFileProvider:
|
|
21
|
+
config: Optional[dict] = None
|
|
22
|
+
|
|
19
23
|
def __init__(self, path: Path, custom_commands: CustomCommands):
|
|
20
24
|
self.path = path
|
|
21
25
|
self.custom_commands = custom_commands
|
|
26
|
+
if (self.path / "Staticfile").exists():
|
|
27
|
+
try:
|
|
28
|
+
self.config = yaml.safe_load((self.path / "Staticfile").read_text())
|
|
29
|
+
except yaml.YAMLError as e:
|
|
30
|
+
print(f"Error loading Staticfile: {e}")
|
|
31
|
+
pass
|
|
22
32
|
|
|
23
33
|
@classmethod
|
|
24
34
|
def name(cls) -> str:
|
|
@@ -58,7 +68,7 @@ class StaticFileProvider:
|
|
|
58
68
|
def build_steps(self) -> list[str]:
|
|
59
69
|
return [
|
|
60
70
|
'workdir(app["build"])',
|
|
61
|
-
'copy(
|
|
71
|
+
'copy({}, ".", ignore=[".git"])'.format(json.dumps(self.config and self.config.get("root") or "."))
|
|
62
72
|
]
|
|
63
73
|
|
|
64
74
|
def prepare_steps(self) -> Optional[list[str]]:
|
|
@@ -69,7 +79,7 @@ class StaticFileProvider:
|
|
|
69
79
|
|
|
70
80
|
def commands(self) -> Dict[str, str]:
|
|
71
81
|
return {
|
|
72
|
-
"start": '"static-web-server --root={} --log-level=info".format(app["serve"])'
|
|
82
|
+
"start": '"static-web-server --root={} --log-level=info --port={}".format(app["serve"], PORT)'
|
|
73
83
|
}
|
|
74
84
|
|
|
75
85
|
def mounts(self) -> list[MountSpec]:
|
shipit/providers/wordpress.py
CHANGED
|
@@ -70,7 +70,7 @@ class WordPressProvider(PhpProvider):
|
|
|
70
70
|
|
|
71
71
|
def commands(self) -> Dict[str, str]:
|
|
72
72
|
return {
|
|
73
|
-
"start": '"php -S localhost:
|
|
73
|
+
"start": 'f"php -S localhost:{PORT} -t ."',
|
|
74
74
|
"wp": '"php {}/wp-cli.phar --allow-root --path={}".format(assets[\"serve\"], app[\"serve\"])',
|
|
75
75
|
"after_deploy": '"bash {}/wordpress-install.sh".format(assets["serve"])',
|
|
76
76
|
}
|
shipit/version.py
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: shipit-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.8.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
|
|
7
7
|
Project-URL: Changelog, https://github.com/wasmerio/shipit/changelog
|
|
8
8
|
Requires-Python: >=3.10
|
|
9
|
+
Requires-Dist: dotenv>=0.9.9
|
|
9
10
|
Requires-Dist: pyyaml>=6.0.2
|
|
10
11
|
Requires-Dist: requests>=2.32.5
|
|
11
12
|
Requires-Dist: rich>=14.1.0
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
shipit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
shipit/cli.py,sha256=wfHNLe0Pe0uheeiFuWQi3DFlUA86oTN8-mojaKxru94,58696
|
|
3
|
+
shipit/generator.py,sha256=W4MynSFwId4PRWWrF0R3NsANye_Zv8TwXCUXai94pW0,6553
|
|
4
|
+
shipit/procfile.py,sha256=GlfdwzFUr0GWGKaaiXlLKNFInWaRNMy_wN14UEyU_5Q,2974
|
|
5
|
+
shipit/version.py,sha256=tLXsjc9rJ1_Aj9p3fPQjFAv5Eanmo1dQaEiaHbiBSwY,95
|
|
6
|
+
shipit/assets/php/php.ini,sha256=f4irndAjB4GuuouEImRkNV22Q-yw1KqR-43jAMDw730,2531
|
|
7
|
+
shipit/assets/wordpress/install.sh,sha256=fJkVeGAw_dj-ywmQipAWRjaz57sayD6F0OFvZKMIKug,669
|
|
8
|
+
shipit/assets/wordpress/wp-config.php,sha256=IdGQoeg8E89JiqwxO2i8WnGMzmhNWgRz80X6lbU5GXc,4134
|
|
9
|
+
shipit/providers/base.py,sha256=-lraLhnXtc2SfYNIUiyry7xD2NL4q0n6voNjr6qfRis,2994
|
|
10
|
+
shipit/providers/gatsby.py,sha256=kzfS-z040GaJ0a9u2_6S6K-ykGSX2yPG17VpjUWBOBA,2393
|
|
11
|
+
shipit/providers/hugo.py,sha256=l3IZ14LGYc3wQ7Uk0iQMDNN9Syd1G4HPzm0ePCGFyzE,1808
|
|
12
|
+
shipit/providers/laravel.py,sha256=2rCuOi2kC5OYQfAG7C0NMhG7KEgzfudwUT_CvVFz4hM,3031
|
|
13
|
+
shipit/providers/mkdocs.py,sha256=mDJpT3rzYAr5Vw-yt5fCpV0QgBZyksn9MrkPd4nzROU,2200
|
|
14
|
+
shipit/providers/node_static.py,sha256=QVUTTZbvUGtj2yT9WTbGmuM30rJzejnp76crIqSGA7o,2564
|
|
15
|
+
shipit/providers/php.py,sha256=BSOqS3UhABoe_ued8aXtyn0KdqWbOCq6VV2ehtoBlmk,3547
|
|
16
|
+
shipit/providers/python.py,sha256=kQpaaQi8ajHM_SFk2xI5lRIeOc6PXSKumb-Tv_5n6m0,20954
|
|
17
|
+
shipit/providers/registry.py,sha256=lHUViVuPJf1OIZD8I_NTX4LP7E3Uo5-MmLfarmAA_cM,729
|
|
18
|
+
shipit/providers/staticfile.py,sha256=BxZ7Z8dN0tAd-s8_m-NPgqJrVSvKwxCd-us-hCanL1E,2626
|
|
19
|
+
shipit/providers/wordpress.py,sha256=Wjc1fgFburewlf4hQ2ZmxTQko_SHQW-8jrDukzKx0Gs,3019
|
|
20
|
+
shipit_cli-0.8.0.dist-info/METADATA,sha256=p_XVn3jE5BNj2JQm_5-xBqszHGjdZYb2me6Ur0BOgTk,523
|
|
21
|
+
shipit_cli-0.8.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
22
|
+
shipit_cli-0.8.0.dist-info/entry_points.txt,sha256=7AE1NjSrHaSDfbfsRRO50KKnHFTbB0Imsccd1WynzAQ,72
|
|
23
|
+
shipit_cli-0.8.0.dist-info/RECORD,,
|
shipit/env.py
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import shlex
|
|
2
|
-
import re
|
|
3
|
-
|
|
4
|
-
def parse(content):
|
|
5
|
-
"""
|
|
6
|
-
Parse the content of a .env file (a line-delimited KEY=value format) into a
|
|
7
|
-
dictionary mapping keys to values.
|
|
8
|
-
"""
|
|
9
|
-
values = {}
|
|
10
|
-
for line in content.splitlines():
|
|
11
|
-
lexer = shlex.shlex(line, posix=True)
|
|
12
|
-
tokens = list(lexer)
|
|
13
|
-
|
|
14
|
-
# parses the assignment statement
|
|
15
|
-
if len(tokens) < 3:
|
|
16
|
-
continue
|
|
17
|
-
|
|
18
|
-
name, op = tokens[:2]
|
|
19
|
-
value = ''.join(tokens[2:])
|
|
20
|
-
|
|
21
|
-
if op != '=':
|
|
22
|
-
continue
|
|
23
|
-
if not re.match(r'[A-Za-z_][A-Za-z_0-9]*', name):
|
|
24
|
-
continue
|
|
25
|
-
|
|
26
|
-
value = value.replace(r'\n', '\n')
|
|
27
|
-
value = value.replace(r'\t', '\t')
|
|
28
|
-
values[name] = value
|
|
29
|
-
|
|
30
|
-
return values
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
shipit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
-
shipit/cli.py,sha256=cLWFBrY24w--GQj_YtRo7U7jnGITEG_TWo4D9W6XH1Q,57549
|
|
3
|
-
shipit/env.py,sha256=Bede00-iFI67RZ0bx92JyX49XL7Q91HK-QoKRpwPaGQ,725
|
|
4
|
-
shipit/generator.py,sha256=GFsuqZG83gn7yxphE4GHwZjEB3sToJn24yNDE-zrTtM,6400
|
|
5
|
-
shipit/procfile.py,sha256=GlfdwzFUr0GWGKaaiXlLKNFInWaRNMy_wN14UEyU_5Q,2974
|
|
6
|
-
shipit/version.py,sha256=myhj6JcZUHlBRvAyfRYaJ_bv3PrzoXvUd5ppXAZh014,95
|
|
7
|
-
shipit/assets/php/php.ini,sha256=f4irndAjB4GuuouEImRkNV22Q-yw1KqR-43jAMDw730,2531
|
|
8
|
-
shipit/assets/wordpress/install.sh,sha256=GOIwJX3qPp7VuZXjkKVFFY6Mo9k7VFWfobS6aZYitPg,817
|
|
9
|
-
shipit/assets/wordpress/wp-config.php,sha256=IdGQoeg8E89JiqwxO2i8WnGMzmhNWgRz80X6lbU5GXc,4134
|
|
10
|
-
shipit/providers/base.py,sha256=-lraLhnXtc2SfYNIUiyry7xD2NL4q0n6voNjr6qfRis,2994
|
|
11
|
-
shipit/providers/gatsby.py,sha256=kzfS-z040GaJ0a9u2_6S6K-ykGSX2yPG17VpjUWBOBA,2393
|
|
12
|
-
shipit/providers/hugo.py,sha256=BvSYTDTVxHz6FW2mA4sqIsNayFRo5BK6Z4tWFRRimmY,1644
|
|
13
|
-
shipit/providers/laravel.py,sha256=yhOnaaXZ2US8EO5ZD5pBTerSOBi9IWBBIqeQrbW7YoM,3028
|
|
14
|
-
shipit/providers/mkdocs.py,sha256=pWTeIUEnSyB653s7Cw_OSllgiSGcDymRTEHgV5ChDLM,2070
|
|
15
|
-
shipit/providers/node_static.py,sha256=QVUTTZbvUGtj2yT9WTbGmuM30rJzejnp76crIqSGA7o,2564
|
|
16
|
-
shipit/providers/php.py,sha256=JIWl5CdVEdf9DAr9O9rR8NucucYCj_M5PbJRw_SnmYU,3541
|
|
17
|
-
shipit/providers/python.py,sha256=n0748miZ5RpQyQUCmkq3_G2Nnub8SaogZoJTNNFalZc,20801
|
|
18
|
-
shipit/providers/registry.py,sha256=lHUViVuPJf1OIZD8I_NTX4LP7E3Uo5-MmLfarmAA_cM,729
|
|
19
|
-
shipit/providers/staticfile.py,sha256=O1D0cXa_cFZH4OXRFLjBG3e-LbjMDo7ZBC2D3CvrPo4,2218
|
|
20
|
-
shipit/providers/wordpress.py,sha256=wMIcBpICqcEpbOgJCufrnM-r76AVI7_xC-NUlh9XMmE,3016
|
|
21
|
-
shipit_cli-0.7.0.dist-info/METADATA,sha256=Ang6CnPqUUcKRovpIAMHMsnccw640bQUYlpPOZ3MNoA,494
|
|
22
|
-
shipit_cli-0.7.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
23
|
-
shipit_cli-0.7.0.dist-info/entry_points.txt,sha256=7AE1NjSrHaSDfbfsRRO50KKnHFTbB0Imsccd1WynzAQ,72
|
|
24
|
-
shipit_cli-0.7.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|