shipit-cli 0.3.2__tar.gz → 0.3.4__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.3.2 → shipit_cli-0.3.4}/PKG-INFO +1 -1
- {shipit_cli-0.3.2 → shipit_cli-0.3.4}/pyproject.toml +1 -1
- {shipit_cli-0.3.2 → shipit_cli-0.3.4}/src/shipit/cli.py +5 -1
- {shipit_cli-0.3.2 → shipit_cli-0.3.4}/src/shipit/generator.py +18 -21
- {shipit_cli-0.3.2 → shipit_cli-0.3.4}/src/shipit/providers/base.py +17 -14
- {shipit_cli-0.3.2 → shipit_cli-0.3.4}/src/shipit/providers/gatsby.py +19 -15
- {shipit_cli-0.3.2 → shipit_cli-0.3.4}/src/shipit/providers/hugo.py +12 -10
- {shipit_cli-0.3.2 → shipit_cli-0.3.4}/src/shipit/providers/laravel.py +19 -15
- {shipit_cli-0.3.2 → shipit_cli-0.3.4}/src/shipit/providers/mkdocs.py +20 -16
- {shipit_cli-0.3.2 → shipit_cli-0.3.4}/src/shipit/providers/node_static.py +21 -17
- {shipit_cli-0.3.2 → shipit_cli-0.3.4}/src/shipit/providers/php.py +26 -22
- {shipit_cli-0.3.2 → shipit_cli-0.3.4}/src/shipit/providers/python.py +32 -25
- {shipit_cli-0.3.2 → shipit_cli-0.3.4}/src/shipit/providers/registry.py +9 -10
- {shipit_cli-0.3.2 → shipit_cli-0.3.4}/src/shipit/providers/staticfile.py +22 -17
- shipit_cli-0.3.4/src/shipit/version.py +5 -0
- shipit_cli-0.3.2/src/shipit/version.py +0 -5
- {shipit_cli-0.3.2 → shipit_cli-0.3.4}/.gitignore +0 -0
- {shipit_cli-0.3.2 → shipit_cli-0.3.4}/README.md +0 -0
- {shipit_cli-0.3.2 → shipit_cli-0.3.4}/src/shipit/__init__.py +0 -0
- {shipit_cli-0.3.2 → shipit_cli-0.3.4}/src/shipit/assets/php/php.ini +0 -0
- {shipit_cli-0.3.2 → shipit_cli-0.3.4}/tests/test_examples_build.py +0 -0
- {shipit_cli-0.3.2 → shipit_cli-0.3.4}/tests/test_generate_shipit_examples.py +0 -0
- {shipit_cli-0.3.2 → shipit_cli-0.3.4}/tests/test_version.py +0 -0
|
@@ -584,6 +584,8 @@ class LocalBuilder:
|
|
|
584
584
|
for step in serve.prepare:
|
|
585
585
|
if isinstance(step, RunStep):
|
|
586
586
|
commands.append(step.command)
|
|
587
|
+
elif isinstance(step, WorkdirStep):
|
|
588
|
+
commands.append(f"cd {step.path}")
|
|
587
589
|
content = "#!/bin/bash\ncd {app_dir}\n{body}".format(
|
|
588
590
|
app_dir=app_dir, body="\n".join(commands)
|
|
589
591
|
)
|
|
@@ -741,9 +743,11 @@ class WasmerBuilder:
|
|
|
741
743
|
for step in serve.prepare:
|
|
742
744
|
if isinstance(step, RunStep):
|
|
743
745
|
commands.append(step.command)
|
|
746
|
+
elif isinstance(step, WorkdirStep):
|
|
747
|
+
commands.append(f"cd {step.path}")
|
|
744
748
|
body = "\n".join(filter(None, [env_lines, *commands]))
|
|
745
749
|
(prepare_dir / "prepare.sh").write_text(
|
|
746
|
-
f"#!/bin/bash\
|
|
750
|
+
f"#!/bin/bash\n\n{body}",
|
|
747
751
|
)
|
|
748
752
|
(prepare_dir / "prepare.sh").chmod(0o755)
|
|
749
753
|
|
|
@@ -7,22 +7,19 @@ from shipit.providers.base import DependencySpec, Provider, ProviderPlan, Detect
|
|
|
7
7
|
from shipit.providers.registry import providers as registry_providers
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
def _providers() -> list[Provider]:
|
|
11
|
-
# Load
|
|
10
|
+
def _providers() -> list[type[Provider]]:
|
|
11
|
+
# Load provider classes from modular registry
|
|
12
12
|
return registry_providers()
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
def detect_provider(path: Path) -> Provider:
|
|
16
|
-
matches: list[tuple[Provider, DetectResult]] = []
|
|
17
|
-
for
|
|
18
|
-
res =
|
|
16
|
+
matches: list[tuple[type[Provider], DetectResult]] = []
|
|
17
|
+
for provider_cls in _providers():
|
|
18
|
+
res = provider_cls.detect(path)
|
|
19
19
|
if res:
|
|
20
|
-
matches.append((
|
|
20
|
+
matches.append((provider_cls, res))
|
|
21
21
|
if not matches:
|
|
22
|
-
|
|
23
|
-
from shipit.providers.staticfile import StaticFileProvider
|
|
24
|
-
|
|
25
|
-
return StaticFileProvider()
|
|
22
|
+
raise Exception("Shipit could not detect a provider for this project")
|
|
26
23
|
# Highest score wins; tie-breaker by order
|
|
27
24
|
matches.sort(key=lambda x: x[1].score, reverse=True)
|
|
28
25
|
return matches[0][0]
|
|
@@ -80,20 +77,20 @@ def _render_assets(assets: Optional[Dict[str, str]]) -> Optional[str]:
|
|
|
80
77
|
|
|
81
78
|
|
|
82
79
|
def generate_shipit(path: Path) -> str:
|
|
83
|
-
|
|
84
|
-
provider
|
|
80
|
+
provider_cls = detect_provider(path)
|
|
81
|
+
provider = provider_cls(path)
|
|
85
82
|
|
|
86
83
|
# Collect parts
|
|
87
84
|
plan = ProviderPlan(
|
|
88
|
-
serve_name=provider.serve_name(
|
|
89
|
-
provider=provider.provider_kind(
|
|
90
|
-
mounts=provider.mounts(
|
|
91
|
-
declarations=provider.declarations(
|
|
92
|
-
dependencies=provider.dependencies(
|
|
93
|
-
build_steps=provider.build_steps(
|
|
94
|
-
prepare=provider.prepare_steps(
|
|
95
|
-
commands=provider.commands(
|
|
96
|
-
env=provider.env(
|
|
85
|
+
serve_name=provider.serve_name(),
|
|
86
|
+
provider=provider.provider_kind(),
|
|
87
|
+
mounts=provider.mounts(),
|
|
88
|
+
declarations=provider.declarations(),
|
|
89
|
+
dependencies=provider.dependencies(),
|
|
90
|
+
build_steps=provider.build_steps(),
|
|
91
|
+
prepare=provider.prepare_steps(),
|
|
92
|
+
commands=provider.commands(),
|
|
93
|
+
env=provider.env(),
|
|
97
94
|
)
|
|
98
95
|
|
|
99
96
|
# Declare dependency variables (combined) and collect serve deps
|
|
@@ -12,21 +12,24 @@ class DetectResult:
|
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
class Provider(Protocol):
|
|
15
|
-
def
|
|
16
|
-
|
|
17
|
-
def
|
|
18
|
-
|
|
19
|
-
def
|
|
20
|
-
def
|
|
21
|
-
|
|
22
|
-
def
|
|
23
|
-
def
|
|
15
|
+
def __init__(self, path: Path): ...
|
|
16
|
+
@classmethod
|
|
17
|
+
def name(cls) -> str: ...
|
|
18
|
+
@classmethod
|
|
19
|
+
def detect(cls, path: Path) -> Optional[DetectResult]: ...
|
|
20
|
+
def initialize(self) -> None: ...
|
|
21
|
+
# Structured plan steps (no path args; use self.path)
|
|
22
|
+
def serve_name(self) -> str: ...
|
|
23
|
+
def provider_kind(self) -> str: ...
|
|
24
|
+
def dependencies(self) -> list["DependencySpec"]: ...
|
|
25
|
+
def declarations(self) -> Optional[str]: ...
|
|
26
|
+
def build_steps(self) -> list[str]: ...
|
|
24
27
|
# Prepare: list of Starlark step calls (currently only run(...))
|
|
25
|
-
def prepare_steps(self
|
|
26
|
-
def commands(self
|
|
27
|
-
def assets(self
|
|
28
|
-
def mounts(self
|
|
29
|
-
def env(self
|
|
28
|
+
def prepare_steps(self) -> Optional[List[str]]: ...
|
|
29
|
+
def commands(self) -> Dict[str, str]: ...
|
|
30
|
+
def assets(self) -> Optional[Dict[str, str]]: ...
|
|
31
|
+
def mounts(self) -> List["MountSpec"]: ...
|
|
32
|
+
def env(self) -> Optional[Dict[str, str]]: ...
|
|
30
33
|
|
|
31
34
|
|
|
32
35
|
@dataclass
|
|
@@ -7,32 +7,36 @@ from .base import DetectResult, DependencySpec, Provider, _exists, _has_dependen
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
class GatsbyProvider:
|
|
10
|
-
def
|
|
10
|
+
def __init__(self, path: Path):
|
|
11
|
+
self.path = path
|
|
12
|
+
@classmethod
|
|
13
|
+
def name(cls) -> str:
|
|
11
14
|
return "gatsby"
|
|
12
15
|
|
|
13
|
-
|
|
16
|
+
@classmethod
|
|
17
|
+
def detect(cls, path: Path) -> Optional[DetectResult]:
|
|
14
18
|
pkg = path / "package.json"
|
|
15
19
|
if not pkg.exists():
|
|
16
20
|
return None
|
|
17
21
|
if _exists(path, "gatsby-config.js", "gatsby-config.ts") or _has_dependency(
|
|
18
22
|
pkg, "gatsby"
|
|
19
23
|
):
|
|
20
|
-
return DetectResult(
|
|
24
|
+
return DetectResult(cls.name(), 90)
|
|
21
25
|
return None
|
|
22
26
|
|
|
23
|
-
def initialize(self
|
|
27
|
+
def initialize(self) -> None:
|
|
24
28
|
pass
|
|
25
29
|
|
|
26
|
-
def serve_name(self
|
|
27
|
-
return path.name
|
|
30
|
+
def serve_name(self) -> str:
|
|
31
|
+
return self.path.name
|
|
28
32
|
|
|
29
|
-
def provider_kind(self
|
|
33
|
+
def provider_kind(self) -> str:
|
|
30
34
|
return "staticsite"
|
|
31
35
|
|
|
32
|
-
def declarations(self
|
|
36
|
+
def declarations(self) -> Optional[str]:
|
|
33
37
|
return None
|
|
34
38
|
|
|
35
|
-
def dependencies(self
|
|
39
|
+
def dependencies(self) -> list[DependencySpec]:
|
|
36
40
|
return [
|
|
37
41
|
DependencySpec(
|
|
38
42
|
"node",
|
|
@@ -44,7 +48,7 @@ class GatsbyProvider:
|
|
|
44
48
|
DependencySpec("static-web-server", env_var="SHIPIT_SWS_VERSION", use_in_serve=True),
|
|
45
49
|
]
|
|
46
50
|
|
|
47
|
-
def build_steps(self
|
|
51
|
+
def build_steps(self) -> list[str]:
|
|
48
52
|
return [
|
|
49
53
|
"run(\"npm install\", inputs=[\"package.json\", \"package-lock.json\"], group=\"install\")",
|
|
50
54
|
"copy(\".\", \".\", ignore=[\"node_modules\", \".git\"])",
|
|
@@ -52,17 +56,17 @@ class GatsbyProvider:
|
|
|
52
56
|
"run(\"cp -R public/* {}/\".format(app[\"build\"]))",
|
|
53
57
|
]
|
|
54
58
|
|
|
55
|
-
def prepare_steps(self
|
|
59
|
+
def prepare_steps(self) -> Optional[list[str]]:
|
|
56
60
|
return None
|
|
57
61
|
|
|
58
|
-
def commands(self
|
|
62
|
+
def commands(self) -> Dict[str, str]:
|
|
59
63
|
return {"start": '"static-web-server --root /app"'}
|
|
60
64
|
|
|
61
|
-
def assets(self
|
|
65
|
+
def assets(self) -> Optional[Dict[str, str]]:
|
|
62
66
|
return None
|
|
63
67
|
|
|
64
|
-
def mounts(self
|
|
68
|
+
def mounts(self) -> list[MountSpec]:
|
|
65
69
|
return [MountSpec("app")]
|
|
66
70
|
|
|
67
|
-
def env(self
|
|
71
|
+
def env(self) -> Optional[Dict[str, str]]:
|
|
68
72
|
return None
|
|
@@ -7,27 +7,29 @@ from .base import DetectResult, DependencySpec, Provider, _exists
|
|
|
7
7
|
from .staticfile import StaticFileProvider
|
|
8
8
|
|
|
9
9
|
class HugoProvider(StaticFileProvider):
|
|
10
|
-
|
|
10
|
+
@classmethod
|
|
11
|
+
def name(cls) -> str:
|
|
11
12
|
return "hugo"
|
|
12
13
|
|
|
13
|
-
|
|
14
|
+
@classmethod
|
|
15
|
+
def detect(cls, path: Path) -> Optional[DetectResult]:
|
|
14
16
|
if _exists(path, "hugo.toml", "hugo.json", "hugo.yaml", "hugo.yml"):
|
|
15
|
-
return DetectResult(
|
|
17
|
+
return DetectResult(cls.name(), 80)
|
|
16
18
|
if (
|
|
17
19
|
_exists(path, "config.toml", "config.json", "config.yaml", "config.yml")
|
|
18
20
|
and _exists(path, "content")
|
|
19
21
|
and (_exists(path, "static") or _exists(path, "themes"))
|
|
20
22
|
):
|
|
21
|
-
return DetectResult(
|
|
23
|
+
return DetectResult(cls.name(), 40)
|
|
22
24
|
return None
|
|
23
25
|
|
|
24
|
-
def serve_name(self
|
|
25
|
-
return path.name
|
|
26
|
+
def serve_name(self) -> str:
|
|
27
|
+
return self.path.name
|
|
26
28
|
|
|
27
|
-
def provider_kind(self
|
|
29
|
+
def provider_kind(self) -> str:
|
|
28
30
|
return "staticsite"
|
|
29
31
|
|
|
30
|
-
def dependencies(self
|
|
32
|
+
def dependencies(self) -> list[DependencySpec]:
|
|
31
33
|
return [
|
|
32
34
|
DependencySpec(
|
|
33
35
|
"hugo",
|
|
@@ -35,10 +37,10 @@ class HugoProvider(StaticFileProvider):
|
|
|
35
37
|
default_version="0.149.0",
|
|
36
38
|
use_in_build=True,
|
|
37
39
|
),
|
|
38
|
-
*super().dependencies(
|
|
40
|
+
*super().dependencies(),
|
|
39
41
|
]
|
|
40
42
|
|
|
41
|
-
def build_steps(self
|
|
43
|
+
def build_steps(self) -> list[str]:
|
|
42
44
|
return [
|
|
43
45
|
'copy(".", ".", ignore=[".git"])',
|
|
44
46
|
'run("hugo build --destination={}".format(app["build"]), group="build")',
|
|
@@ -7,24 +7,28 @@ from .base import DetectResult, DependencySpec, Provider, _exists, MountSpec
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
class LaravelProvider:
|
|
10
|
-
def
|
|
10
|
+
def __init__(self, path: Path):
|
|
11
|
+
self.path = path
|
|
12
|
+
@classmethod
|
|
13
|
+
def name(cls) -> str:
|
|
11
14
|
return "laravel"
|
|
12
15
|
|
|
13
|
-
|
|
16
|
+
@classmethod
|
|
17
|
+
def detect(cls, path: Path) -> Optional[DetectResult]:
|
|
14
18
|
if _exists(path, "artisan") and _exists(path, "composer.json"):
|
|
15
|
-
return DetectResult(
|
|
19
|
+
return DetectResult(cls.name(), 95)
|
|
16
20
|
return None
|
|
17
21
|
|
|
18
|
-
def initialize(self
|
|
22
|
+
def initialize(self) -> None:
|
|
19
23
|
pass
|
|
20
24
|
|
|
21
|
-
def serve_name(self
|
|
22
|
-
return path.name
|
|
25
|
+
def serve_name(self) -> str:
|
|
26
|
+
return self.path.name
|
|
23
27
|
|
|
24
|
-
def provider_kind(self
|
|
28
|
+
def provider_kind(self) -> str:
|
|
25
29
|
return "php"
|
|
26
30
|
|
|
27
|
-
def dependencies(self
|
|
31
|
+
def dependencies(self) -> list[DependencySpec]:
|
|
28
32
|
return [
|
|
29
33
|
DependencySpec(
|
|
30
34
|
"php",
|
|
@@ -39,10 +43,10 @@ class LaravelProvider:
|
|
|
39
43
|
DependencySpec("bash", use_in_serve=True),
|
|
40
44
|
]
|
|
41
45
|
|
|
42
|
-
def declarations(self
|
|
46
|
+
def declarations(self) -> Optional[str]:
|
|
43
47
|
return "HOME = getenv(\"HOME\")"
|
|
44
48
|
|
|
45
|
-
def build_steps(self
|
|
49
|
+
def build_steps(self) -> list[str]:
|
|
46
50
|
return [
|
|
47
51
|
"env(HOME=HOME, COMPOSER_FUND=\"0\")",
|
|
48
52
|
"workdir(app[\"build\"])",
|
|
@@ -53,7 +57,7 @@ class LaravelProvider:
|
|
|
53
57
|
"run(\"pnpm run build\", outputs=[\".\"], group=\"build\")",
|
|
54
58
|
]
|
|
55
59
|
|
|
56
|
-
def prepare_steps(self
|
|
60
|
+
def prepare_steps(self) -> Optional[list[str]]:
|
|
57
61
|
return [
|
|
58
62
|
'workdir(app["serve"])',
|
|
59
63
|
'run("mkdir -p storage/framework/{sessions,views,cache,testing} storage/logs bootstrap/cache")',
|
|
@@ -63,17 +67,17 @@ class LaravelProvider:
|
|
|
63
67
|
'run("php artisan view:cache")',
|
|
64
68
|
]
|
|
65
69
|
|
|
66
|
-
def commands(self
|
|
70
|
+
def commands(self) -> Dict[str, str]:
|
|
67
71
|
return {
|
|
68
72
|
"start": '"php -S localhost:8080 -t public"',
|
|
69
73
|
"after_deploy": '"php artisan migrate"',
|
|
70
74
|
}
|
|
71
75
|
|
|
72
|
-
def assets(self
|
|
76
|
+
def assets(self) -> Optional[Dict[str, str]]:
|
|
73
77
|
return None
|
|
74
78
|
|
|
75
|
-
def mounts(self
|
|
79
|
+
def mounts(self) -> list[MountSpec]:
|
|
76
80
|
return [MountSpec("app")]
|
|
77
81
|
|
|
78
|
-
def env(self
|
|
82
|
+
def env(self) -> Optional[Dict[str, str]]:
|
|
79
83
|
return None
|
|
@@ -7,24 +7,28 @@ from .base import DetectResult, DependencySpec, Provider, _exists, MountSpec
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
class MkdocsProvider:
|
|
10
|
-
def
|
|
10
|
+
def __init__(self, path: Path):
|
|
11
|
+
self.path = path
|
|
12
|
+
@classmethod
|
|
13
|
+
def name(cls) -> str:
|
|
11
14
|
return "mkdocs"
|
|
12
15
|
|
|
13
|
-
|
|
16
|
+
@classmethod
|
|
17
|
+
def detect(cls, path: Path) -> Optional[DetectResult]:
|
|
14
18
|
if _exists(path, "mkdocs.yml", "mkdocs.yaml"):
|
|
15
|
-
return DetectResult(
|
|
19
|
+
return DetectResult(cls.name(), 85)
|
|
16
20
|
return None
|
|
17
21
|
|
|
18
|
-
def initialize(self
|
|
22
|
+
def initialize(self) -> None:
|
|
19
23
|
pass
|
|
20
24
|
|
|
21
|
-
def serve_name(self
|
|
22
|
-
return path.name
|
|
25
|
+
def serve_name(self) -> str:
|
|
26
|
+
return self.path.name
|
|
23
27
|
|
|
24
|
-
def provider_kind(self
|
|
28
|
+
def provider_kind(self) -> str:
|
|
25
29
|
return "mkdocs-site"
|
|
26
30
|
|
|
27
|
-
def dependencies(self
|
|
31
|
+
def dependencies(self) -> list[DependencySpec]:
|
|
28
32
|
return [
|
|
29
33
|
DependencySpec(
|
|
30
34
|
"python",
|
|
@@ -46,11 +50,11 @@ class MkdocsProvider:
|
|
|
46
50
|
),
|
|
47
51
|
]
|
|
48
52
|
|
|
49
|
-
def declarations(self
|
|
53
|
+
def declarations(self) -> Optional[str]:
|
|
50
54
|
return None
|
|
51
55
|
|
|
52
|
-
def build_steps(self
|
|
53
|
-
has_requirements = _exists(path, "requirements.txt")
|
|
56
|
+
def build_steps(self) -> list[str]:
|
|
57
|
+
has_requirements = _exists(self.path, "requirements.txt")
|
|
54
58
|
if has_requirements:
|
|
55
59
|
install_lines = [
|
|
56
60
|
"run(\"uv init --no-managed-python\", inputs=[], outputs=[\".\"], group=\"install\")",
|
|
@@ -68,17 +72,17 @@ class MkdocsProvider:
|
|
|
68
72
|
"run(\"uv run mkdocs build --site-dir={}\".format(app[\"build\"]), outputs=[\".\"], group=\"build\")",
|
|
69
73
|
]
|
|
70
74
|
|
|
71
|
-
def prepare_steps(self
|
|
75
|
+
def prepare_steps(self) -> Optional[list[str]]:
|
|
72
76
|
return None
|
|
73
77
|
|
|
74
|
-
def commands(self
|
|
78
|
+
def commands(self) -> Dict[str, str]:
|
|
75
79
|
return {"start": '"static-web-server --root /app"'}
|
|
76
80
|
|
|
77
|
-
def assets(self
|
|
81
|
+
def assets(self) -> Optional[Dict[str, str]]:
|
|
78
82
|
return None
|
|
79
83
|
|
|
80
|
-
def mounts(self
|
|
84
|
+
def mounts(self) -> list[MountSpec]:
|
|
81
85
|
return [MountSpec("app")]
|
|
82
86
|
|
|
83
|
-
def env(self
|
|
87
|
+
def env(self) -> Optional[Dict[str, str]]:
|
|
84
88
|
return None
|
|
@@ -7,28 +7,32 @@ from .base import DetectResult, DependencySpec, Provider, _exists, _has_dependen
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
class NodeStaticProvider:
|
|
10
|
-
def
|
|
10
|
+
def __init__(self, path: Path):
|
|
11
|
+
self.path = path
|
|
12
|
+
@classmethod
|
|
13
|
+
def name(cls) -> str:
|
|
11
14
|
return "node-static"
|
|
12
15
|
|
|
13
|
-
|
|
16
|
+
@classmethod
|
|
17
|
+
def detect(cls, path: Path) -> Optional[DetectResult]:
|
|
14
18
|
pkg = path / "package.json"
|
|
15
19
|
if not pkg.exists():
|
|
16
20
|
return None
|
|
17
21
|
static_generators = ["astro", "vite", "next", "nuxt"]
|
|
18
22
|
if any(_has_dependency(pkg, dep) for dep in static_generators):
|
|
19
|
-
return DetectResult(
|
|
23
|
+
return DetectResult(cls.name(), 40)
|
|
20
24
|
return None
|
|
21
25
|
|
|
22
|
-
def initialize(self
|
|
26
|
+
def initialize(self) -> None:
|
|
23
27
|
pass
|
|
24
28
|
|
|
25
|
-
def serve_name(self
|
|
26
|
-
return path.name
|
|
29
|
+
def serve_name(self) -> str:
|
|
30
|
+
return self.path.name
|
|
27
31
|
|
|
28
|
-
def provider_kind(self
|
|
32
|
+
def provider_kind(self) -> str:
|
|
29
33
|
return "staticsite"
|
|
30
34
|
|
|
31
|
-
def dependencies(self
|
|
35
|
+
def dependencies(self) -> list[DependencySpec]:
|
|
32
36
|
return [
|
|
33
37
|
DependencySpec(
|
|
34
38
|
"node",
|
|
@@ -40,11 +44,11 @@ class NodeStaticProvider:
|
|
|
40
44
|
DependencySpec("static-web-server", use_in_serve=True),
|
|
41
45
|
]
|
|
42
46
|
|
|
43
|
-
def declarations(self
|
|
47
|
+
def declarations(self) -> Optional[str]:
|
|
44
48
|
return None
|
|
45
49
|
|
|
46
|
-
def build_steps(self
|
|
47
|
-
output_dir = "dist" if (path / "dist").exists() else "public"
|
|
50
|
+
def build_steps(self) -> list[str]:
|
|
51
|
+
output_dir = "dist" if (self.path / "dist").exists() else "public"
|
|
48
52
|
return [
|
|
49
53
|
"run(\"npm install\", inputs=[\"package.json\", \"package-lock.json\"], group=\"install\")",
|
|
50
54
|
"copy(\".\", \".\", ignore=[\"node_modules\", \".git\"])",
|
|
@@ -52,18 +56,18 @@ class NodeStaticProvider:
|
|
|
52
56
|
f"run(\"cp -R {output_dir}/* {{}}/\".format(app[\"build\"]))",
|
|
53
57
|
]
|
|
54
58
|
|
|
55
|
-
def prepare_steps(self
|
|
59
|
+
def prepare_steps(self) -> Optional[list[str]]:
|
|
56
60
|
return None
|
|
57
61
|
|
|
58
|
-
def commands(self
|
|
59
|
-
output_dir = "dist" if (path / "dist").exists() else "public"
|
|
62
|
+
def commands(self) -> Dict[str, str]:
|
|
63
|
+
output_dir = "dist" if (self.path / "dist").exists() else "public"
|
|
60
64
|
return {"start": f'"static-web-server --root /app/{output_dir}"'}
|
|
61
65
|
|
|
62
|
-
def assets(self
|
|
66
|
+
def assets(self) -> Optional[Dict[str, str]]:
|
|
63
67
|
return None
|
|
64
68
|
|
|
65
|
-
def mounts(self
|
|
69
|
+
def mounts(self) -> list[MountSpec]:
|
|
66
70
|
return [MountSpec("app")]
|
|
67
71
|
|
|
68
|
-
def env(self
|
|
72
|
+
def env(self) -> Optional[Dict[str, str]]:
|
|
69
73
|
return None
|
|
@@ -7,29 +7,33 @@ from .base import DetectResult, DependencySpec, Provider, _exists, MountSpec
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
class PhpProvider:
|
|
10
|
-
def
|
|
10
|
+
def __init__(self, path: Path):
|
|
11
|
+
self.path = path
|
|
12
|
+
@classmethod
|
|
13
|
+
def name(cls) -> str:
|
|
11
14
|
return "php"
|
|
12
15
|
|
|
13
|
-
|
|
16
|
+
@classmethod
|
|
17
|
+
def detect(cls, path: Path) -> Optional[DetectResult]:
|
|
14
18
|
if _exists(path, "composer.json") and _exists(path, "public/index.php"):
|
|
15
|
-
return DetectResult(
|
|
19
|
+
return DetectResult(cls.name(), 60)
|
|
16
20
|
if _exists(path, "index.php") and not _exists(path, "composer.json"):
|
|
17
|
-
return DetectResult(
|
|
21
|
+
return DetectResult(cls.name(), 10)
|
|
18
22
|
return None
|
|
19
23
|
|
|
20
|
-
def initialize(self
|
|
24
|
+
def initialize(self) -> None:
|
|
21
25
|
pass
|
|
22
26
|
|
|
23
|
-
def serve_name(self
|
|
24
|
-
return path.name
|
|
27
|
+
def serve_name(self) -> str:
|
|
28
|
+
return self.path.name
|
|
25
29
|
|
|
26
|
-
def provider_kind(self
|
|
30
|
+
def provider_kind(self) -> str:
|
|
27
31
|
return "php"
|
|
28
32
|
|
|
29
|
-
def has_composer(self
|
|
30
|
-
return _exists(path, "composer.json", "composer.lock")
|
|
33
|
+
def has_composer(self) -> bool:
|
|
34
|
+
return _exists(self.path, "composer.json", "composer.lock")
|
|
31
35
|
|
|
32
|
-
def dependencies(self
|
|
36
|
+
def dependencies(self) -> list[DependencySpec]:
|
|
33
37
|
deps = [
|
|
34
38
|
DependencySpec(
|
|
35
39
|
"php",
|
|
@@ -39,40 +43,40 @@ class PhpProvider:
|
|
|
39
43
|
use_in_serve=True,
|
|
40
44
|
),
|
|
41
45
|
]
|
|
42
|
-
if self.has_composer(
|
|
46
|
+
if self.has_composer():
|
|
43
47
|
deps.append(DependencySpec("composer", use_in_build=True))
|
|
44
48
|
deps.append(DependencySpec("bash", use_in_serve=True))
|
|
45
49
|
return deps
|
|
46
50
|
|
|
47
|
-
def declarations(self
|
|
51
|
+
def declarations(self) -> Optional[str]:
|
|
48
52
|
return "HOME = getenv(\"HOME\")"
|
|
49
53
|
|
|
50
|
-
def build_steps(self
|
|
54
|
+
def build_steps(self) -> list[str]:
|
|
51
55
|
steps = [
|
|
52
56
|
"workdir(app[\"build\"])",
|
|
53
57
|
]
|
|
54
58
|
|
|
55
|
-
if self.has_composer(
|
|
59
|
+
if self.has_composer():
|
|
56
60
|
steps.append("env(HOME=HOME, COMPOSER_FUND=\"0\")")
|
|
57
61
|
steps.append("run(\"composer install --optimize-autoloader --no-scripts --no-interaction\", inputs=[\"composer.json\", \"composer.lock\"], outputs=[\".\"], group=\"install\")")
|
|
58
62
|
|
|
59
63
|
steps.append("copy(\".\", \".\", ignore=[\".git\"])")
|
|
60
64
|
return steps
|
|
61
65
|
|
|
62
|
-
def prepare_steps(self
|
|
66
|
+
def prepare_steps(self) -> Optional[list[str]]:
|
|
63
67
|
return None
|
|
64
68
|
|
|
65
|
-
def commands(self
|
|
66
|
-
if _exists(path, "public/index.php"):
|
|
69
|
+
def commands(self) -> Dict[str, str]:
|
|
70
|
+
if _exists(self.path, "public/index.php"):
|
|
67
71
|
return {"start": '"php -S localhost:8080 -t public"'}
|
|
68
|
-
elif _exists(path, "index.php"):
|
|
72
|
+
elif _exists(self.path, "index.php"):
|
|
69
73
|
return {"start": '"php -S localhost:8080" -t .'}
|
|
70
74
|
|
|
71
|
-
def assets(self
|
|
75
|
+
def assets(self) -> Optional[Dict[str, str]]:
|
|
72
76
|
return {"php.ini": "get_asset(\"php/php.ini\")"}
|
|
73
77
|
|
|
74
|
-
def mounts(self
|
|
78
|
+
def mounts(self) -> list[MountSpec]:
|
|
75
79
|
return [MountSpec("app")]
|
|
76
80
|
|
|
77
|
-
def env(self
|
|
81
|
+
def env(self) -> Optional[Dict[str, str]]:
|
|
78
82
|
return None
|
|
@@ -13,28 +13,32 @@ from .base import (
|
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
class PythonProvider:
|
|
16
|
-
def
|
|
16
|
+
def __init__(self, path: Path):
|
|
17
|
+
self.path = path
|
|
18
|
+
@classmethod
|
|
19
|
+
def name(cls) -> str:
|
|
17
20
|
return "python"
|
|
18
21
|
|
|
19
|
-
|
|
22
|
+
@classmethod
|
|
23
|
+
def detect(cls, path: Path) -> Optional[DetectResult]:
|
|
20
24
|
if _exists(path, "pyproject.toml", "requirements.txt"):
|
|
21
25
|
if _exists(path, "manage.py"):
|
|
22
|
-
return DetectResult(
|
|
23
|
-
return DetectResult(
|
|
26
|
+
return DetectResult(cls.name(), 70)
|
|
27
|
+
return DetectResult(cls.name(), 50)
|
|
24
28
|
return None
|
|
25
29
|
|
|
26
|
-
def initialize(self
|
|
30
|
+
def initialize(self) -> None:
|
|
27
31
|
pass
|
|
28
32
|
|
|
29
|
-
def serve_name(self
|
|
30
|
-
return path.name
|
|
33
|
+
def serve_name(self) -> str:
|
|
34
|
+
return self.path.name
|
|
31
35
|
|
|
32
|
-
def provider_kind(self
|
|
36
|
+
def provider_kind(self) -> str:
|
|
33
37
|
return "python"
|
|
34
38
|
|
|
35
|
-
def dependencies(self
|
|
36
|
-
if _exists(path, ".python-version"):
|
|
37
|
-
python_version = (path / ".python-version").read_text().strip()
|
|
39
|
+
def dependencies(self) -> list[DependencySpec]:
|
|
40
|
+
if _exists(self.path, ".python-version"):
|
|
41
|
+
python_version = (self.path / ".python-version").read_text().strip()
|
|
38
42
|
else:
|
|
39
43
|
python_version = "3.13"
|
|
40
44
|
|
|
@@ -54,7 +58,7 @@ class PythonProvider:
|
|
|
54
58
|
),
|
|
55
59
|
]
|
|
56
60
|
|
|
57
|
-
def declarations(self
|
|
61
|
+
def declarations(self) -> Optional[str]:
|
|
58
62
|
return (
|
|
59
63
|
"cross_platform = getenv(\"SHIPIT_PYTHON_CROSS_PLATFORM\")\n"
|
|
60
64
|
"python_extra_index_url = getenv(\"SHIPIT_PYTHON_EXTRA_INDEX_URL\")\n"
|
|
@@ -62,24 +66,26 @@ class PythonProvider:
|
|
|
62
66
|
"python_cross_packages_path = venv[\"build\"] + f\"/lib/python{python_version}/site-packages\""
|
|
63
67
|
)
|
|
64
68
|
|
|
65
|
-
def build_steps(self
|
|
69
|
+
def build_steps(self) -> list[str]:
|
|
66
70
|
steps = [
|
|
67
71
|
"workdir(app[\"build\"])"
|
|
68
72
|
]
|
|
69
73
|
|
|
70
|
-
if _exists(path, "pyproject.toml"):
|
|
74
|
+
if _exists(self.path, "pyproject.toml"):
|
|
71
75
|
input_files = ["pyproject.toml"]
|
|
72
|
-
|
|
76
|
+
extra_args = ""
|
|
77
|
+
if _exists(self.path, "uv.lock"):
|
|
73
78
|
input_files.append("uv.lock")
|
|
79
|
+
extra_args = " --locked"
|
|
74
80
|
inputs = ", ".join([f"\"{input}\"" for input in input_files])
|
|
75
81
|
steps += [
|
|
76
82
|
"env(UV_PROJECT_ENVIRONMENT=local_venv[\"build\"] if cross_platform else venv[\"build\"])",
|
|
77
|
-
"run(f\"uv sync --compile --python python{python_version} --
|
|
83
|
+
"run(f\"uv sync --compile --python python{python_version} --no-managed-python" + extra_args + "\", inputs=[" + inputs + "], group=\"install\")",
|
|
78
84
|
"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 --only-binary :all: -o cross-requirements.txt\", inputs=[\"pyproject.toml\"], outputs=[\"cross-requirements.txt\"]) if cross_platform else None",
|
|
79
85
|
"run(f\"uvx pip install -r cross-requirements.txt --target {python_cross_packages_path} --platform {cross_platform} --only-binary=:all: --python-version={python_version} --compile\") if cross_platform else None",
|
|
80
86
|
"run(\"rm cross-requirements.txt\") if cross_platform else None",
|
|
81
87
|
]
|
|
82
|
-
if _exists(path, "requirements.txt"):
|
|
88
|
+
if _exists(self.path, "requirements.txt"):
|
|
83
89
|
steps += [
|
|
84
90
|
"env(UV_PROJECT_ENVIRONMENT=local_venv[\"build\"] if cross_platform else venv[\"build\"])",
|
|
85
91
|
"run(f\"uv init --no-managed-python --python python{python_version}\", inputs=[], outputs=[\"uv.lock\"], group=\"install\")",
|
|
@@ -95,38 +101,39 @@ class PythonProvider:
|
|
|
95
101
|
]
|
|
96
102
|
return steps
|
|
97
103
|
|
|
98
|
-
def prepare_steps(self
|
|
104
|
+
def prepare_steps(self) -> Optional[list[str]]:
|
|
99
105
|
return [
|
|
106
|
+
'workdir(app["serve"])',
|
|
100
107
|
'run("echo \\\"Precompiling Python code...\\\"") if precompile_python else None',
|
|
101
108
|
'run("python -m compileall -o 2 $PYTHONPATH") if precompile_python else None',
|
|
102
109
|
'run("echo \\\"Precompiling package code...\\\"") if precompile_python else None',
|
|
103
110
|
'run("python -m compileall -o 2 .") if precompile_python else None',
|
|
104
111
|
]
|
|
105
112
|
|
|
106
|
-
def commands(self
|
|
107
|
-
if _exists(path, "manage.py"):
|
|
113
|
+
def commands(self) -> Dict[str, str]:
|
|
114
|
+
if _exists(self.path, "manage.py"):
|
|
108
115
|
start_cmd = '"python manage.py runserver 0.0.0.0:8000"'
|
|
109
116
|
migrate_cmd = '"python manage.py migrate"'
|
|
110
117
|
return {"start": start_cmd, "after_deploy": migrate_cmd}
|
|
111
|
-
elif _exists(path, "main.py"):
|
|
118
|
+
elif _exists(self.path, "main.py"):
|
|
112
119
|
start_cmd = '"python main.py"'
|
|
113
|
-
elif _exists(path, "src/main.py"):
|
|
120
|
+
elif _exists(self.path, "src/main.py"):
|
|
114
121
|
start_cmd = '"python src/main.py"'
|
|
115
122
|
else:
|
|
116
123
|
start_cmd = '"python -c \'print(\\\"Hello, World!\\\")\'"'
|
|
117
124
|
return {"start": start_cmd}
|
|
118
125
|
|
|
119
|
-
def assets(self
|
|
126
|
+
def assets(self) -> Optional[Dict[str, str]]:
|
|
120
127
|
return None
|
|
121
128
|
|
|
122
|
-
def mounts(self
|
|
129
|
+
def mounts(self) -> list[MountSpec]:
|
|
123
130
|
return [
|
|
124
131
|
MountSpec("app"),
|
|
125
132
|
MountSpec("venv"),
|
|
126
133
|
MountSpec("local_venv", attach_to_serve=False),
|
|
127
134
|
]
|
|
128
135
|
|
|
129
|
-
def env(self
|
|
136
|
+
def env(self) -> Optional[Dict[str, str]]:
|
|
130
137
|
# For Django projects, generate an empty env dict to surface the field
|
|
131
138
|
# in the Shipit file. Other Python projects omit it by default.
|
|
132
139
|
return {
|
|
@@ -11,16 +11,15 @@ from .python import PythonProvider
|
|
|
11
11
|
from .staticfile import StaticFileProvider
|
|
12
12
|
|
|
13
13
|
|
|
14
|
-
def providers() -> list[Provider]:
|
|
14
|
+
def providers() -> list[type[Provider]]:
|
|
15
15
|
# Order matters: more specific providers first
|
|
16
16
|
return [
|
|
17
|
-
LaravelProvider
|
|
18
|
-
GatsbyProvider
|
|
19
|
-
HugoProvider
|
|
20
|
-
MkdocsProvider
|
|
21
|
-
PythonProvider
|
|
22
|
-
PhpProvider
|
|
23
|
-
NodeStaticProvider
|
|
24
|
-
StaticFileProvider
|
|
17
|
+
LaravelProvider,
|
|
18
|
+
GatsbyProvider,
|
|
19
|
+
HugoProvider,
|
|
20
|
+
MkdocsProvider,
|
|
21
|
+
PythonProvider,
|
|
22
|
+
PhpProvider,
|
|
23
|
+
NodeStaticProvider,
|
|
24
|
+
StaticFileProvider,
|
|
25
25
|
]
|
|
26
|
-
|
|
@@ -7,28 +7,33 @@ from .base import DetectResult, DependencySpec, Provider, _exists, MountSpec
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
class StaticFileProvider:
|
|
10
|
-
def
|
|
10
|
+
def __init__(self, path: Path):
|
|
11
|
+
self.path = path
|
|
12
|
+
|
|
13
|
+
@classmethod
|
|
14
|
+
def name(cls) -> str:
|
|
11
15
|
return "staticfile"
|
|
12
16
|
|
|
13
|
-
|
|
17
|
+
@classmethod
|
|
18
|
+
def detect(cls, path: Path) -> Optional[DetectResult]:
|
|
14
19
|
if _exists(path, "Staticfile"):
|
|
15
|
-
return DetectResult(
|
|
20
|
+
return DetectResult(cls.name(), 50)
|
|
16
21
|
if _exists(path, "index.html") and not _exists(
|
|
17
22
|
path, "package.json", "pyproject.toml", "composer.json"
|
|
18
23
|
):
|
|
19
|
-
return DetectResult(
|
|
24
|
+
return DetectResult(cls.name(), 10)
|
|
20
25
|
return None
|
|
21
26
|
|
|
22
|
-
def initialize(self
|
|
27
|
+
def initialize(self) -> None:
|
|
23
28
|
pass
|
|
24
29
|
|
|
25
|
-
def serve_name(self
|
|
26
|
-
return path.name
|
|
30
|
+
def serve_name(self) -> str:
|
|
31
|
+
return self.path.name
|
|
27
32
|
|
|
28
|
-
def provider_kind(self
|
|
33
|
+
def provider_kind(self) -> str:
|
|
29
34
|
return "staticfile"
|
|
30
35
|
|
|
31
|
-
def dependencies(self
|
|
36
|
+
def dependencies(self) -> list[DependencySpec]:
|
|
32
37
|
return [
|
|
33
38
|
DependencySpec(
|
|
34
39
|
"static-web-server",
|
|
@@ -38,28 +43,28 @@ class StaticFileProvider:
|
|
|
38
43
|
)
|
|
39
44
|
]
|
|
40
45
|
|
|
41
|
-
def build_steps(self
|
|
46
|
+
def build_steps(self) -> list[str]:
|
|
42
47
|
return [
|
|
43
48
|
'workdir(app["build"])',
|
|
44
49
|
'copy(".", ".", ignore=[".git"])'
|
|
45
50
|
]
|
|
46
51
|
|
|
47
|
-
def prepare_steps(self
|
|
52
|
+
def prepare_steps(self) -> Optional[list[str]]:
|
|
48
53
|
return None
|
|
49
54
|
|
|
50
|
-
def declarations(self
|
|
55
|
+
def declarations(self) -> Optional[str]:
|
|
51
56
|
return None
|
|
52
57
|
|
|
53
|
-
def commands(self
|
|
58
|
+
def commands(self) -> Dict[str, str]:
|
|
54
59
|
return {
|
|
55
|
-
"start": '"static-web-server --root
|
|
60
|
+
"start": '"static-web-server --root={} --log-level=info".format(app["serve"])'
|
|
56
61
|
}
|
|
57
62
|
|
|
58
|
-
def assets(self
|
|
63
|
+
def assets(self) -> Optional[Dict[str, str]]:
|
|
59
64
|
return None
|
|
60
65
|
|
|
61
|
-
def mounts(self
|
|
66
|
+
def mounts(self) -> list[MountSpec]:
|
|
62
67
|
return [MountSpec("app")]
|
|
63
68
|
|
|
64
|
-
def env(self
|
|
69
|
+
def env(self) -> Optional[Dict[str, str]]:
|
|
65
70
|
return None
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|