shipit-cli 0.22.2__tar.gz → 0.23.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.22.2 → shipit_cli-0.23.0}/PKG-INFO +1 -1
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/pyproject.toml +1 -1
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/src/shipit/providers/node.py +31 -9
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/src/shipit/providers/python.py +82 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/src/shipit/providers/staticfile.py +52 -1
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/src/shipit/runners/wasmer.py +1 -1
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/src/shipit/starlib/tools/python.shipit +9 -44
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/src/shipit/version.py +1 -1
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/test_node_provider.py +26 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/test_node_static_provider.py +8 -3
- shipit_cli-0.23.0/tests/test_python_detection.py +245 -0
- shipit_cli-0.23.0/tests/test_staticfile_provider.py +99 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/test_wasmer_annotations.py +1 -1
- shipit_cli-0.22.2/tests/test_python_detection.py +0 -96
- shipit_cli-0.22.2/tests/test_staticfile_provider.py +0 -46
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/.gitignore +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/README.md +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/src/shipit/__init__.py +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/src/shipit/assets/node/optimize-node-modules.sh +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/src/shipit/assets/php/php.ini +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/src/shipit/assets/wordpress/.htaccess +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/src/shipit/assets/wordpress/install.sh +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/src/shipit/assets/wordpress/start.php +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/src/shipit/assets/wordpress/wp-config.php +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/src/shipit/builders/__init__.py +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/src/shipit/builders/base.py +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/src/shipit/builders/docker.py +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/src/shipit/builders/local.py +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/src/shipit/cli.py +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/src/shipit/evaluator.py +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/src/shipit/generator.py +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/src/shipit/procfile.py +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/src/shipit/providers/base.py +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/src/shipit/providers/go.py +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/src/shipit/providers/hugo.py +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/src/shipit/providers/install_context.py +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/src/shipit/providers/jekyll.py +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/src/shipit/providers/laravel.py +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/src/shipit/providers/mkdocs.py +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/src/shipit/providers/node_static.py +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/src/shipit/providers/php.py +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/src/shipit/providers/registry.py +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/src/shipit/providers/wordpress.py +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/src/shipit/runners/__init__.py +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/src/shipit/runners/base.py +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/src/shipit/runners/local.py +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/src/shipit/shipit_types.py +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/src/shipit/starlark_loader.py +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/src/shipit/starlib/prelude.shipit +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/src/shipit/starlib/serve.shipit +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/src/shipit/starlib/tools/go.shipit +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/src/shipit/starlib/tools/hugo.shipit +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/src/shipit/starlib/tools/jekyll.shipit +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/src/shipit/starlib/tools/laravel.shipit +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/src/shipit/starlib/tools/mkdocs.shipit +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/src/shipit/starlib/tools/node.shipit +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/src/shipit/starlib/tools/node_static.shipit +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/src/shipit/starlib/tools/php.shipit +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/src/shipit/starlib/tools/staticfile.shipit +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/src/shipit/starlib/tools/wordpress.shipit +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/src/shipit/ui.py +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/src/shipit/utils.py +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/src/shipit/volumes.py +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_helpers.py +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/go-graphql.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/go-simple.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/hugo.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/mkdocs-with-plugins.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/mkdocs-with-plugins__cross.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/mkdocs.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/mkdocs__cross.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/node-astro.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/node-elysia.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/node-express.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/node-fastify.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/node-h3.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/node-hono.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/node-hydrogen.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/node-koa.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/node-mastra.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/node-mcp.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/node-nestjs.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/node-next.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/node-nitro.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/node-npm-file-subdir.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/node-pnpm-workspace-subdir.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/node-react-router.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/node-remix.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/node-solidstart.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/node-tanstack-start.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/node-xmcp.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/node.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/nodestatic-angular.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/nodestatic-assemble.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/nodestatic-astro.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/nodestatic-brunch.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/nodestatic-create-react-app.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/nodestatic-docusaurus-old.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/nodestatic-docusaurus.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/nodestatic-eleventy.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/nodestatic-ember.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/nodestatic-gatsby.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/nodestatic-harp.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/nodestatic-hexo.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/nodestatic-ionic-angular.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/nodestatic-ionic-react.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/nodestatic-metalsmith.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/nodestatic-next.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/nodestatic-nuxt.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/nodestatic-parcel.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/nodestatic-polymer.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/nodestatic-preact.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/nodestatic-remix.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/nodestatic-sanity.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/nodestatic-stencil.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/nodestatic-storybook.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/nodestatic-svelte.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/nodestatic-sveltekit.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/nodestatic-umijs.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/nodestatic-vite-react.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/nodestatic-vite.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/nodestatic-vitepress.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/nodestatic-vue.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/nodestatic-vuepress.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/php-api.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/php-laravel-react.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/php-nobuild.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/php-wordpress-empty.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/php-wordpress-plugin.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/php-wordpress-theme.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/php-wordpress.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/python-django.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/python-django__cross.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/python-fastapi.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/python-fastapi__cross.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/python-fasthtml.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/python-fasthtml__cross.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/python-ffmpeg.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/python-ffmpeg__cross.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/python-flask.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/python-flask__cross.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/python-mcp-chatgpt.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/python-mcp-chatgpt__cross.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/python-mcp.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/python-mcp__cross.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/python-pandoc.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/python-pandoc__cross.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/python-pillow.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/python-pillow__cross.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/python-procfile.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/python-procfile__cross.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/python-streamlit.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/python-streamlit__cross.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/static-htmlwithjs.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/static-nobuild.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/staticfile-redirects.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/staticfile.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/synthetic__go_subdir.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/synthetic__jekyll_bare.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/synthetic__jekyll_gemfile.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/synthetic__python_subdir.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/plan_snapshots/synthetic__static_subdir.json +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/test_cli_after_deploy.py +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/test_command_overrides.py +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/test_e2e.py +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/test_evaluator.py +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/test_generate_shipit_examples.py +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/test_install_context.py +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/test_php_provider.py +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/test_plan_snapshots.py +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/test_project_context.py +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/test_starlark_loader.py +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/test_subdir.py +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/test_version.py +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/test_volumes.py +0 -0
- {shipit_cli-0.22.2 → shipit_cli-0.23.0}/tests/test_wordpress_phpix.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: shipit-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.23.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
|
|
@@ -9,6 +9,8 @@ from pydantic import Field
|
|
|
9
9
|
from pydantic_settings import SettingsConfigDict
|
|
10
10
|
from semantic_version import NpmSpec, Version
|
|
11
11
|
|
|
12
|
+
from shipit.ui import console
|
|
13
|
+
|
|
12
14
|
from .base import Config, DetectResult
|
|
13
15
|
from .install_context import discover_js_install_context
|
|
14
16
|
|
|
@@ -536,6 +538,12 @@ class NodeProvider:
|
|
|
536
538
|
if config.commands.start and cls._is_node_command(config.commands.start):
|
|
537
539
|
return DetectResult(cls.name(), 35)
|
|
538
540
|
|
|
541
|
+
package_json = cls.parse_package_json(path)
|
|
542
|
+
package_start = (
|
|
543
|
+
cls.package_scripts(package_json).get("start", "").strip()
|
|
544
|
+
)
|
|
545
|
+
package_score = 30 if package_start else 10
|
|
546
|
+
|
|
539
547
|
if config.commands.install:
|
|
540
548
|
install_commands = {
|
|
541
549
|
"npm install",
|
|
@@ -552,17 +560,17 @@ class NodeProvider:
|
|
|
552
560
|
"bun i",
|
|
553
561
|
}
|
|
554
562
|
if config.commands.install in install_commands:
|
|
555
|
-
return DetectResult(cls.name(),
|
|
563
|
+
return DetectResult(cls.name(), package_score)
|
|
556
564
|
|
|
557
|
-
package_json = cls.parse_package_json(path)
|
|
558
565
|
found_deps = cls._check_package_json_deps(
|
|
559
566
|
package_json, *cls.FRAMEWORK_DEPENDENCIES
|
|
560
567
|
)
|
|
561
568
|
if cls.detect_framework(package_json, found_deps, path):
|
|
562
|
-
|
|
569
|
+
framework_score = 45 if package_start else 10
|
|
570
|
+
return DetectResult(cls.name(), framework_score)
|
|
563
571
|
|
|
564
572
|
if (path / "package.json").is_file():
|
|
565
|
-
return DetectResult(cls.name(),
|
|
573
|
+
return DetectResult(cls.name(), package_score)
|
|
566
574
|
|
|
567
575
|
if cls._common_entry_file(path, require_node_evidence=True):
|
|
568
576
|
return DetectResult(cls.name(), 30)
|
|
@@ -917,28 +925,42 @@ class NodeProvider:
|
|
|
917
925
|
|
|
918
926
|
@classmethod
|
|
919
927
|
def infer_start_command(
|
|
920
|
-
cls,
|
|
928
|
+
cls,
|
|
929
|
+
path: Path,
|
|
930
|
+
package_json: Optional[Dict[str, Any]],
|
|
931
|
+
*,
|
|
932
|
+
warn: bool = True,
|
|
921
933
|
) -> Optional[str]:
|
|
922
934
|
scripts = cls.package_scripts(package_json)
|
|
923
935
|
start_script = scripts.get("start")
|
|
924
|
-
if start_script:
|
|
925
|
-
return start_script.strip()
|
|
936
|
+
if start_script and start_script.strip():
|
|
937
|
+
return start_script.strip()
|
|
926
938
|
|
|
927
939
|
if package_json:
|
|
928
940
|
main = package_json.get("main")
|
|
929
941
|
if isinstance(main, str) and main.strip():
|
|
930
942
|
return cls._node_entry_command(main.strip())
|
|
931
943
|
|
|
944
|
+
if warn and (path / "package.json").is_file():
|
|
945
|
+
console.print(
|
|
946
|
+
"[bold yellow]Warning:[/bold yellow] "
|
|
947
|
+
"no start or main script found in package.json"
|
|
948
|
+
)
|
|
949
|
+
|
|
932
950
|
entry_file = cls._common_entry_file(
|
|
933
951
|
path,
|
|
934
952
|
require_node_evidence=not (path / "package.json").is_file(),
|
|
935
953
|
)
|
|
936
954
|
if entry_file:
|
|
937
955
|
return cls._node_entry_command(entry_file)
|
|
938
|
-
|
|
956
|
+
if warn:
|
|
957
|
+
tried = ", ".join(cls.COMMON_ENTRY_FILES)
|
|
958
|
+
console.print(
|
|
959
|
+
"[bold yellow]Warning:[/bold yellow] "
|
|
960
|
+
f"no entry file found for Node project (tried: {tried})"
|
|
961
|
+
)
|
|
939
962
|
return None
|
|
940
963
|
|
|
941
964
|
@classmethod
|
|
942
965
|
def _node_entry_command(cls, entry_file: str) -> str:
|
|
943
966
|
return f"node {shlex.quote(entry_file)}"
|
|
944
|
-
|
|
@@ -6,6 +6,8 @@ from typing import List, Optional, Set
|
|
|
6
6
|
from pydantic import Field
|
|
7
7
|
from pydantic_settings import SettingsConfigDict
|
|
8
8
|
|
|
9
|
+
from shipit.ui import console
|
|
10
|
+
|
|
9
11
|
from .install_context import discover_python_dependency_files, discover_python_install_context
|
|
10
12
|
from .base import DetectResult, _exists, Config
|
|
11
13
|
|
|
@@ -156,8 +158,88 @@ class PythonProvider:
|
|
|
156
158
|
path, config.framework, config.main_file
|
|
157
159
|
)
|
|
158
160
|
|
|
161
|
+
if not config.commands.start:
|
|
162
|
+
config.commands.start = cls.infer_start_command(config)
|
|
163
|
+
|
|
159
164
|
return config
|
|
160
165
|
|
|
166
|
+
@staticmethod
|
|
167
|
+
def infer_start_command(
|
|
168
|
+
config: PythonConfig,
|
|
169
|
+
*,
|
|
170
|
+
warn: bool = True,
|
|
171
|
+
) -> Optional[str]:
|
|
172
|
+
def cannot_infer(reason: str) -> Optional[str]:
|
|
173
|
+
if warn:
|
|
174
|
+
console.print(
|
|
175
|
+
f"[bold yellow]Warning:[/bold yellow] {reason}"
|
|
176
|
+
)
|
|
177
|
+
return None
|
|
178
|
+
|
|
179
|
+
def missing_main_file() -> Optional[str]:
|
|
180
|
+
if config.framework:
|
|
181
|
+
return cannot_infer(
|
|
182
|
+
"no main file was detected for the "
|
|
183
|
+
f"{config.framework.name} framework"
|
|
184
|
+
)
|
|
185
|
+
return cannot_infer(
|
|
186
|
+
"no main file was detected for Python project"
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
main_file = config.main_file
|
|
190
|
+
asgi = config.asgi_application
|
|
191
|
+
wsgi = config.wsgi_application
|
|
192
|
+
|
|
193
|
+
if config.server == PythonServer.Daphne:
|
|
194
|
+
if asgi:
|
|
195
|
+
return f"daphne {asgi} --bind 0.0.0.0 --port $PORT"
|
|
196
|
+
return cannot_infer(
|
|
197
|
+
"no ASGI application was detected for the Daphne server"
|
|
198
|
+
)
|
|
199
|
+
if config.server == PythonServer.Uvicorn:
|
|
200
|
+
if asgi:
|
|
201
|
+
return f"uvicorn {asgi} --host 0.0.0.0 --port $PORT"
|
|
202
|
+
if wsgi:
|
|
203
|
+
return (
|
|
204
|
+
f"uvicorn {wsgi} --interface=wsgi "
|
|
205
|
+
"--host 0.0.0.0 --port $PORT"
|
|
206
|
+
)
|
|
207
|
+
if not main_file:
|
|
208
|
+
if config.framework:
|
|
209
|
+
return missing_main_file()
|
|
210
|
+
return cannot_infer(
|
|
211
|
+
"no main file, ASGI application, or WSGI application "
|
|
212
|
+
"was detected for the Uvicorn server"
|
|
213
|
+
)
|
|
214
|
+
elif config.server == PythonServer.Hypercorn:
|
|
215
|
+
if asgi:
|
|
216
|
+
return f"hypercorn {asgi} --bind 0.0.0.0:$PORT"
|
|
217
|
+
return cannot_infer(
|
|
218
|
+
"no ASGI application was detected for the Hypercorn server"
|
|
219
|
+
)
|
|
220
|
+
elif config.framework == PythonFramework.Streamlit:
|
|
221
|
+
if main_file:
|
|
222
|
+
return (
|
|
223
|
+
f"streamlit run {main_file} --server.port $PORT "
|
|
224
|
+
"--server.address 0.0.0.0 --server.headless true"
|
|
225
|
+
)
|
|
226
|
+
return missing_main_file()
|
|
227
|
+
elif config.framework == PythonFramework.MCP:
|
|
228
|
+
if not main_file:
|
|
229
|
+
return missing_main_file()
|
|
230
|
+
if config.mcp_self_running:
|
|
231
|
+
return f"python {main_file}"
|
|
232
|
+
return (
|
|
233
|
+
f"python $VIRTUAL_ENV/bin/mcp run {main_file} "
|
|
234
|
+
"--transport=streamable-http"
|
|
235
|
+
)
|
|
236
|
+
elif config.framework == PythonFramework.Django:
|
|
237
|
+
return "python manage.py runserver 0.0.0.0:$PORT"
|
|
238
|
+
|
|
239
|
+
if main_file:
|
|
240
|
+
return f"python {main_file}"
|
|
241
|
+
return missing_main_file()
|
|
242
|
+
|
|
161
243
|
@classmethod
|
|
162
244
|
def check_deps(cls, path: Path, *deps: str) -> Set[str]:
|
|
163
245
|
pending_deps = {dep.lower() for dep in deps}
|
|
@@ -88,14 +88,65 @@ class StaticFileProvider:
|
|
|
88
88
|
if _exists(
|
|
89
89
|
path, "index.html", "index.htm", "public/index.htm", "public/index.html"
|
|
90
90
|
):
|
|
91
|
-
return DetectResult(cls.name(),
|
|
91
|
+
return DetectResult(cls.name(), 15)
|
|
92
92
|
return DetectResult(cls.name(), 10)
|
|
93
93
|
if config.commands.start and config.commands.start.startswith(
|
|
94
94
|
"static-web-server "
|
|
95
95
|
):
|
|
96
96
|
return DetectResult(cls.name(), 70)
|
|
97
|
+
if cls._is_unbuilt_node_static_site(path, config):
|
|
98
|
+
return DetectResult(cls.name(), 15)
|
|
97
99
|
return None
|
|
98
100
|
|
|
101
|
+
@classmethod
|
|
102
|
+
def _is_unbuilt_node_static_site(
|
|
103
|
+
cls,
|
|
104
|
+
path: Path,
|
|
105
|
+
config: Config,
|
|
106
|
+
) -> bool:
|
|
107
|
+
if not _exists(path, "index.html", "index.htm"):
|
|
108
|
+
return False
|
|
109
|
+
|
|
110
|
+
# Local imports avoid a module cycle: node-static composes this
|
|
111
|
+
# provider for its serving behavior.
|
|
112
|
+
from .node import NodeProvider
|
|
113
|
+
from .node_static import NodeStaticProvider
|
|
114
|
+
|
|
115
|
+
package_json = NodeProvider.parse_package_json(path)
|
|
116
|
+
if package_json is None:
|
|
117
|
+
return False
|
|
118
|
+
|
|
119
|
+
scripts = NodeProvider.package_scripts(package_json)
|
|
120
|
+
if scripts.get("start", "").strip():
|
|
121
|
+
return False
|
|
122
|
+
build_scripts = ("build", "generate", "export", "docs:build")
|
|
123
|
+
if config.commands.build or any(
|
|
124
|
+
scripts.get(name, "").strip() for name in build_scripts
|
|
125
|
+
):
|
|
126
|
+
return False
|
|
127
|
+
if NodeStaticProvider.detect(path, config):
|
|
128
|
+
return False
|
|
129
|
+
|
|
130
|
+
found_runtime_deps = NodeProvider._check_package_json_deps(
|
|
131
|
+
package_json,
|
|
132
|
+
*NodeProvider.FRAMEWORK_DEPENDENCIES,
|
|
133
|
+
)
|
|
134
|
+
if NodeProvider.detect_framework(
|
|
135
|
+
package_json,
|
|
136
|
+
found_runtime_deps,
|
|
137
|
+
path,
|
|
138
|
+
):
|
|
139
|
+
return False
|
|
140
|
+
|
|
141
|
+
return (
|
|
142
|
+
NodeProvider.infer_start_command(
|
|
143
|
+
path,
|
|
144
|
+
package_json,
|
|
145
|
+
warn=False,
|
|
146
|
+
)
|
|
147
|
+
is None
|
|
148
|
+
)
|
|
149
|
+
|
|
99
150
|
@classmethod
|
|
100
151
|
def _load_redirect_rules(cls, redirects_path: Path) -> list[RedirectRule]:
|
|
101
152
|
rules: list[RedirectRule] = []
|
|
@@ -32,7 +32,7 @@ WASMER_APP_KIND_ANNOTATION = "wasmer.io/app-kind"
|
|
|
32
32
|
WASMER_VERSION_ANNOTATION = "wasmer.io/version"
|
|
33
33
|
BUILD_ANNOTATIONS_FILENAME = "build-annotations.yaml"
|
|
34
34
|
EDGEJS_QUICKJS_DEPENDENCY = "wasmer/edgejs-quickjs@=0.1.0"
|
|
35
|
-
PHPIX_VERSION = "0.3.0-rc.
|
|
35
|
+
PHPIX_VERSION = "0.3.0-rc.3"
|
|
36
36
|
|
|
37
37
|
|
|
38
38
|
def _phpix_dependency(php_version: str, bits: int) -> str:
|
|
@@ -155,55 +155,18 @@ def python_build(config, source = None, app = None, venv = None, serving = True)
|
|
|
155
155
|
local_venv = local_venv,
|
|
156
156
|
)
|
|
157
157
|
|
|
158
|
-
def python_commands(config
|
|
159
|
-
"""
|
|
160
|
-
asgi = config.asgi_application
|
|
161
|
-
wsgi = config.wsgi_application
|
|
162
|
-
main_file = config.main_file
|
|
163
|
-
|
|
164
|
-
start = None
|
|
165
|
-
if config.server == "daphne":
|
|
166
|
-
if not asgi:
|
|
167
|
-
fail("No ASGI application found for Daphne")
|
|
168
|
-
start = f"daphne {asgi} --bind 0.0.0.0 --port {PORT}"
|
|
169
|
-
elif config.server == "uvicorn":
|
|
170
|
-
if not main_file and not asgi and not wsgi:
|
|
171
|
-
fail("No ASGI or WSGI application found for Uvicorn and no main file found")
|
|
172
|
-
if asgi:
|
|
173
|
-
start = f"uvicorn {asgi} --host 0.0.0.0 --port {PORT}"
|
|
174
|
-
elif wsgi:
|
|
175
|
-
start = f"uvicorn {wsgi} --interface=wsgi --host 0.0.0.0 --port {PORT}"
|
|
176
|
-
elif config.server == "hypercorn":
|
|
177
|
-
if not asgi:
|
|
178
|
-
fail("No ASGI application found for Hypercorn")
|
|
179
|
-
start = f"hypercorn {asgi} --bind 0.0.0.0:{PORT}"
|
|
180
|
-
elif config.framework == "streamlit":
|
|
181
|
-
if not main_file:
|
|
182
|
-
fail("No main file found for Streamlit")
|
|
183
|
-
start = f"streamlit run {main_file} --server.port {PORT} --server.address 0.0.0.0 --server.headless true"
|
|
184
|
-
elif config.framework == "mcp":
|
|
185
|
-
if not main_file:
|
|
186
|
-
fail("No main file found for MCP")
|
|
187
|
-
if config.mcp_self_running:
|
|
188
|
-
start = "python " + main_file
|
|
189
|
-
else:
|
|
190
|
-
start = "python {}/bin/mcp run {} --transport=streamable-http".format(venv.serve_path, main_file)
|
|
191
|
-
elif config.framework == "django":
|
|
192
|
-
start = f"python manage.py runserver 0.0.0.0:{PORT}"
|
|
193
|
-
|
|
194
|
-
if not start and main_file:
|
|
195
|
-
start = "python " + main_file
|
|
196
|
-
|
|
158
|
+
def python_commands(config):
|
|
159
|
+
"""Commands resolved from the Python provider configuration."""
|
|
197
160
|
commands = {}
|
|
198
|
-
if start:
|
|
199
|
-
commands["start"] = start
|
|
161
|
+
if config.commands.start:
|
|
162
|
+
commands["start"] = config.commands.start
|
|
200
163
|
if config.migration_strategy == "django":
|
|
201
164
|
commands["after_deploy"] = "python manage.py migrate"
|
|
202
165
|
elif config.migration_strategy == "alembic":
|
|
203
166
|
commands["after_deploy"] = "alembic upgrade head"
|
|
204
167
|
return commands
|
|
205
168
|
|
|
206
|
-
def python_env(config, app, site_packages):
|
|
169
|
+
def python_env(config, app, venv, site_packages):
|
|
207
170
|
app_path = app.serve_path
|
|
208
171
|
if config.main_file and config.main_file.startswith("src/"):
|
|
209
172
|
pythonpath = "{}:{}/src:{}".format(app_path, app_path, site_packages)
|
|
@@ -215,6 +178,8 @@ def python_env(config, app, site_packages):
|
|
|
215
178
|
elif config.framework == "mcp":
|
|
216
179
|
env_vars["FASTMCP_HOST"] = "0.0.0.0"
|
|
217
180
|
env_vars["FASTMCP_PORT"] = PORT
|
|
181
|
+
if not config.mcp_self_running:
|
|
182
|
+
env_vars["VIRTUAL_ENV"] = venv.serve_path
|
|
218
183
|
return env_vars
|
|
219
184
|
|
|
220
185
|
def python_prepare(config, site_packages, app_serve_path):
|
|
@@ -256,8 +221,8 @@ def python_serve(
|
|
|
256
221
|
name = name,
|
|
257
222
|
cwd = app.serve_path,
|
|
258
223
|
prepare = prepare if prepare != None else python_prepare(config, site_packages, app.serve_path),
|
|
259
|
-
env = python_env(config, app, site_packages),
|
|
260
|
-
commands = python_commands(config
|
|
224
|
+
env = python_env(config, app, venv, site_packages),
|
|
225
|
+
commands = python_commands(config),
|
|
261
226
|
services = services if services != None else python_services(config),
|
|
262
227
|
mounts = [app, venv],
|
|
263
228
|
**overrides
|
|
@@ -341,6 +341,18 @@ def test_node_start_command_uses_package_main(tmp_path: Path) -> None:
|
|
|
341
341
|
assert provider_config.commands.start == "node src/server.js"
|
|
342
342
|
|
|
343
343
|
|
|
344
|
+
def test_node_start_command_ignores_empty_script_and_uses_package_main(
|
|
345
|
+
tmp_path: Path,
|
|
346
|
+
) -> None:
|
|
347
|
+
(tmp_path / "package.json").write_text(
|
|
348
|
+
'{"scripts": {"start": " "}, "main": "src/server.js"}\n'
|
|
349
|
+
)
|
|
350
|
+
|
|
351
|
+
provider_config = NodeProvider.load_config(tmp_path, Config())
|
|
352
|
+
|
|
353
|
+
assert provider_config.commands.start == "node src/server.js"
|
|
354
|
+
|
|
355
|
+
|
|
344
356
|
def test_node_start_command_uses_common_entry_file(tmp_path: Path) -> None:
|
|
345
357
|
(tmp_path / "server.js").write_text(
|
|
346
358
|
"""const http = require("http");
|
|
@@ -356,6 +368,20 @@ http.createServer((_req, res) => {
|
|
|
356
368
|
assert provider_config.commands.start == "node server.js"
|
|
357
369
|
|
|
358
370
|
|
|
371
|
+
def test_node_provider_warns_when_start_command_is_missing(
|
|
372
|
+
tmp_path: Path,
|
|
373
|
+
capsys,
|
|
374
|
+
) -> None:
|
|
375
|
+
(tmp_path / "package.json").write_text('{"name": "missing-start"}\n')
|
|
376
|
+
|
|
377
|
+
provider_config = NodeProvider.load_config(tmp_path, Config())
|
|
378
|
+
|
|
379
|
+
assert provider_config.commands.start is None
|
|
380
|
+
warning = capsys.readouterr().err
|
|
381
|
+
assert "Warning: no start or main script found in package.json" in warning
|
|
382
|
+
assert "Warning: no entry file found for Node project" in warning
|
|
383
|
+
|
|
384
|
+
|
|
359
385
|
def test_node_build_steps_optimize_deps_prunes_then_node_modules(
|
|
360
386
|
tmp_path: Path,
|
|
361
387
|
) -> None:
|
|
@@ -6,7 +6,7 @@ from pydantic import ValidationError
|
|
|
6
6
|
|
|
7
7
|
from shipit.generator import load_provider, load_provider_config
|
|
8
8
|
from shipit.providers.base import Config
|
|
9
|
-
from shipit.providers.node import NodeFramework, PackageManager
|
|
9
|
+
from shipit.providers.node import NodeFramework, NodeProvider, PackageManager
|
|
10
10
|
from shipit.providers.node_static import (
|
|
11
11
|
NodeStaticConfig,
|
|
12
12
|
NodeStaticProvider,
|
|
@@ -245,7 +245,9 @@ def test_pure_static_dependency_keeps_priority_with_package_script_command() ->
|
|
|
245
245
|
assert detect_result.score == 60
|
|
246
246
|
|
|
247
247
|
|
|
248
|
-
def
|
|
248
|
+
def test_next_build_without_start_command_uses_node_static(
|
|
249
|
+
tmp_path: Path,
|
|
250
|
+
) -> None:
|
|
249
251
|
(tmp_path / "package.json").write_text(
|
|
250
252
|
"""{
|
|
251
253
|
"scripts": {
|
|
@@ -261,10 +263,13 @@ def test_explicit_next_build_command_uses_node_provider(tmp_path: Path) -> None:
|
|
|
261
263
|
base_config.commands.build = "next build"
|
|
262
264
|
|
|
263
265
|
detect_result = NodeStaticProvider.detect(tmp_path, base_config)
|
|
266
|
+
node_result = NodeProvider.detect(tmp_path, base_config)
|
|
264
267
|
|
|
265
268
|
assert detect_result is not None
|
|
266
269
|
assert detect_result.score == 20
|
|
267
|
-
assert
|
|
270
|
+
assert node_result is not None
|
|
271
|
+
assert node_result.score < detect_result.score
|
|
272
|
+
assert load_provider(tmp_path, base_config) is NodeStaticProvider
|
|
268
273
|
|
|
269
274
|
|
|
270
275
|
def test_explicit_next_export_command_stays_node_static(tmp_path: Path) -> None:
|