shipit-cli 0.19.1__tar.gz → 0.19.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. {shipit_cli-0.19.1 → shipit_cli-0.19.3}/PKG-INFO +22 -11
  2. {shipit_cli-0.19.1 → shipit_cli-0.19.3}/README.md +21 -10
  3. {shipit_cli-0.19.1 → shipit_cli-0.19.3}/pyproject.toml +1 -1
  4. {shipit_cli-0.19.1 → shipit_cli-0.19.3}/src/shipit/cli.py +122 -68
  5. {shipit_cli-0.19.1 → shipit_cli-0.19.3}/src/shipit/providers/php.py +4 -0
  6. {shipit_cli-0.19.1 → shipit_cli-0.19.3}/src/shipit/runners/local.py +1 -2
  7. {shipit_cli-0.19.1 → shipit_cli-0.19.3}/src/shipit/runners/wasmer.py +36 -30
  8. {shipit_cli-0.19.1 → shipit_cli-0.19.3}/src/shipit/ui.py +1 -1
  9. shipit_cli-0.19.3/src/shipit/version.py +5 -0
  10. {shipit_cli-0.19.1 → shipit_cli-0.19.3}/src/shipit/volumes.py +38 -1
  11. shipit_cli-0.19.3/tests/test_cli_after_deploy.py +362 -0
  12. {shipit_cli-0.19.1 → shipit_cli-0.19.3}/tests/test_e2e.py +2 -2
  13. {shipit_cli-0.19.1 → shipit_cli-0.19.3}/tests/test_volumes.py +32 -3
  14. shipit_cli-0.19.1/src/shipit/version.py +0 -5
  15. shipit_cli-0.19.1/tests/test_cli_after_deploy.py +0 -159
  16. {shipit_cli-0.19.1 → shipit_cli-0.19.3}/.gitignore +0 -0
  17. {shipit_cli-0.19.1 → shipit_cli-0.19.3}/src/shipit/__init__.py +0 -0
  18. {shipit_cli-0.19.1 → shipit_cli-0.19.3}/src/shipit/assets/php/php.ini +0 -0
  19. {shipit_cli-0.19.1 → shipit_cli-0.19.3}/src/shipit/assets/wordpress/.htaccess +0 -0
  20. {shipit_cli-0.19.1 → shipit_cli-0.19.3}/src/shipit/assets/wordpress/install.sh +0 -0
  21. {shipit_cli-0.19.1 → shipit_cli-0.19.3}/src/shipit/assets/wordpress/start.php +0 -0
  22. {shipit_cli-0.19.1 → shipit_cli-0.19.3}/src/shipit/assets/wordpress/wp-config.php +0 -0
  23. {shipit_cli-0.19.1 → shipit_cli-0.19.3}/src/shipit/builders/__init__.py +0 -0
  24. {shipit_cli-0.19.1 → shipit_cli-0.19.3}/src/shipit/builders/base.py +0 -0
  25. {shipit_cli-0.19.1 → shipit_cli-0.19.3}/src/shipit/builders/docker.py +0 -0
  26. {shipit_cli-0.19.1 → shipit_cli-0.19.3}/src/shipit/builders/local.py +0 -0
  27. {shipit_cli-0.19.1 → shipit_cli-0.19.3}/src/shipit/generator.py +0 -0
  28. {shipit_cli-0.19.1 → shipit_cli-0.19.3}/src/shipit/procfile.py +0 -0
  29. {shipit_cli-0.19.1 → shipit_cli-0.19.3}/src/shipit/providers/base.py +0 -0
  30. {shipit_cli-0.19.1 → shipit_cli-0.19.3}/src/shipit/providers/go.py +0 -0
  31. {shipit_cli-0.19.1 → shipit_cli-0.19.3}/src/shipit/providers/hugo.py +0 -0
  32. {shipit_cli-0.19.1 → shipit_cli-0.19.3}/src/shipit/providers/jekyll.py +0 -0
  33. {shipit_cli-0.19.1 → shipit_cli-0.19.3}/src/shipit/providers/laravel.py +0 -0
  34. {shipit_cli-0.19.1 → shipit_cli-0.19.3}/src/shipit/providers/mkdocs.py +0 -0
  35. {shipit_cli-0.19.1 → shipit_cli-0.19.3}/src/shipit/providers/node_static.py +0 -0
  36. {shipit_cli-0.19.1 → shipit_cli-0.19.3}/src/shipit/providers/python.py +0 -0
  37. {shipit_cli-0.19.1 → shipit_cli-0.19.3}/src/shipit/providers/registry.py +0 -0
  38. {shipit_cli-0.19.1 → shipit_cli-0.19.3}/src/shipit/providers/staticfile.py +0 -0
  39. {shipit_cli-0.19.1 → shipit_cli-0.19.3}/src/shipit/providers/wordpress.py +0 -0
  40. {shipit_cli-0.19.1 → shipit_cli-0.19.3}/src/shipit/runners/__init__.py +0 -0
  41. {shipit_cli-0.19.1 → shipit_cli-0.19.3}/src/shipit/runners/base.py +0 -0
  42. {shipit_cli-0.19.1 → shipit_cli-0.19.3}/src/shipit/shipit_types.py +0 -0
  43. {shipit_cli-0.19.1 → shipit_cli-0.19.3}/src/shipit/utils.py +0 -0
  44. {shipit_cli-0.19.1 → shipit_cli-0.19.3}/tests/test_generate_shipit_examples.py +0 -0
  45. {shipit_cli-0.19.1 → shipit_cli-0.19.3}/tests/test_php_provider.py +0 -0
  46. {shipit_cli-0.19.1 → shipit_cli-0.19.3}/tests/test_staticfile_provider.py +0 -0
  47. {shipit_cli-0.19.1 → shipit_cli-0.19.3}/tests/test_version.py +0 -0
  48. {shipit_cli-0.19.1 → shipit_cli-0.19.3}/tests/test_wasmer_annotations.py +0 -0
  49. {shipit_cli-0.19.1 → shipit_cli-0.19.3}/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.19.1
3
+ Version: 0.19.3
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
@@ -37,12 +37,13 @@ Install nothing globally; use `uvx shipit-cli` to run Shipit from anywhere.
37
37
  uvx shipit-cli .
38
38
  ```
39
39
 
40
- Running in `auto` mode will generate the `Shipit` file when needed, build the project, and can
41
- also serve it. Shipit picks the safest builder automatically and falls back to
42
- Docker or Wasmer when requested:
40
+ Running in `auto` mode will generate the `Shipit` file when needed, build the
41
+ project, and can also run it. Shipit picks the safest builder automatically
42
+ and falls back to Docker or Wasmer when requested:
43
43
 
44
- - `uvx shipit-cli . --wasmer` builds locally and serves inside Wasmer.
45
- - `uvx shipit-cli . --docker` builds it with Docker (you can customize the docker client as well, eg: `--docker-client depot`).
44
+ - `uvx shipit-cli . --wasmer` builds locally and runs inside Wasmer.
45
+ - `uvx shipit-cli . --docker` builds it with Docker (you can customize the
46
+ docker client as well, eg: `--docker-client depot`).
46
47
  - `uvx shipit-cli . --start` launches the app after building.
47
48
 
48
49
  You can combine them as needed:
@@ -56,8 +57,7 @@ uvx shipit-cli . --start --wasmer --skip-prepare
56
57
  ### Default `auto` mode
57
58
 
58
59
  Full pipeline in one command. Combine flags such as `--regenerate` to rewrite
59
- the `Shipit` file. Use
60
- `--wasmer` to run with Wasmer, or `--wasmer-deploy` to deploy to Wasmer Edge.
60
+ the `Shipit` file. Use `--wasmer` to run with Wasmer.
61
61
 
62
62
  ### `generate`
63
63
 
@@ -87,13 +87,24 @@ uvx shipit-cli build
87
87
  Run the build steps defined in `Shipit`. Append `--wasmer` to execute inside
88
88
  Wasmer, `--docker` to use Docker builds.
89
89
 
90
- ### `serve`
90
+ ### `run`
91
91
 
92
92
  ```bash
93
- uvx shipit-cli serve
93
+ uvx shipit-cli run
94
94
  ```
95
95
 
96
- Execute the start command for the project. Combine with `--wasmer` for WebAssembly execution, or `--wasmer-deploy` to deploy to Wasmer Edge.
96
+ Run explicit commands for the project. Use `--start` to run the start
97
+ command, or pass one or more `--command` values. Combine with `--wasmer`
98
+ for WebAssembly execution.
99
+
100
+ ### `deploy`
101
+
102
+ ```bash
103
+ uvx shipit-cli deploy
104
+ ```
105
+
106
+ Deploy a Wasmer package generated by `shipit build --wasmer`. Use
107
+ `--wasmer-deploy-config` to write deployment metadata instead of publishing.
97
108
 
98
109
  ## Supported Technologies
99
110
 
@@ -14,12 +14,13 @@ Install nothing globally; use `uvx shipit-cli` to run Shipit from anywhere.
14
14
  uvx shipit-cli .
15
15
  ```
16
16
 
17
- Running in `auto` mode will generate the `Shipit` file when needed, build the project, and can
18
- also serve it. Shipit picks the safest builder automatically and falls back to
19
- Docker or Wasmer when requested:
17
+ Running in `auto` mode will generate the `Shipit` file when needed, build the
18
+ project, and can also run it. Shipit picks the safest builder automatically
19
+ and falls back to Docker or Wasmer when requested:
20
20
 
21
- - `uvx shipit-cli . --wasmer` builds locally and serves inside Wasmer.
22
- - `uvx shipit-cli . --docker` builds it with Docker (you can customize the docker client as well, eg: `--docker-client depot`).
21
+ - `uvx shipit-cli . --wasmer` builds locally and runs inside Wasmer.
22
+ - `uvx shipit-cli . --docker` builds it with Docker (you can customize the
23
+ docker client as well, eg: `--docker-client depot`).
23
24
  - `uvx shipit-cli . --start` launches the app after building.
24
25
 
25
26
  You can combine them as needed:
@@ -33,8 +34,7 @@ uvx shipit-cli . --start --wasmer --skip-prepare
33
34
  ### Default `auto` mode
34
35
 
35
36
  Full pipeline in one command. Combine flags such as `--regenerate` to rewrite
36
- the `Shipit` file. Use
37
- `--wasmer` to run with Wasmer, or `--wasmer-deploy` to deploy to Wasmer Edge.
37
+ the `Shipit` file. Use `--wasmer` to run with Wasmer.
38
38
 
39
39
  ### `generate`
40
40
 
@@ -64,13 +64,24 @@ uvx shipit-cli build
64
64
  Run the build steps defined in `Shipit`. Append `--wasmer` to execute inside
65
65
  Wasmer, `--docker` to use Docker builds.
66
66
 
67
- ### `serve`
67
+ ### `run`
68
68
 
69
69
  ```bash
70
- uvx shipit-cli serve
70
+ uvx shipit-cli run
71
71
  ```
72
72
 
73
- Execute the start command for the project. Combine with `--wasmer` for WebAssembly execution, or `--wasmer-deploy` to deploy to Wasmer Edge.
73
+ Run explicit commands for the project. Use `--start` to run the start
74
+ command, or pass one or more `--command` values. Combine with `--wasmer`
75
+ for WebAssembly execution.
76
+
77
+ ### `deploy`
78
+
79
+ ```bash
80
+ uvx shipit-cli deploy
81
+ ```
82
+
83
+ Deploy a Wasmer package generated by `shipit build --wasmer`. Use
84
+ `--wasmer-deploy-config` to write deployment metadata instead of publishing.
74
85
 
75
86
  ## Supported Technologies
76
87
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "shipit-cli"
3
- version = "0.19.1"
3
+ version = "0.19.3"
4
4
  description = "Shipit CLI is the best way to build, serve and deploy your projects anywhere."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
@@ -36,7 +36,12 @@ from shipit.shipit_types import (
36
36
  )
37
37
  from shipit.ui import console
38
38
  from shipit.version import version as shipit_version
39
- from shipit.volumes import build_volumes, load_volume_mappings
39
+ from shipit.volumes import (
40
+ build_volumes,
41
+ load_volume_mappings,
42
+ merge_volume_mappings,
43
+ parse_cli_volume_mappings,
44
+ )
40
45
 
41
46
  app = typer.Typer(invoke_without_command=True)
42
47
 
@@ -347,7 +352,7 @@ def auto(
347
352
  ),
348
353
  wasmer: bool = typer.Option(
349
354
  False,
350
- help="Use Wasmer to build and serve the project.",
355
+ help="Use Wasmer to build and run the project.",
351
356
  ),
352
357
  wasmer_bin: Optional[str] = typer.Option(
353
358
  None,
@@ -373,18 +378,26 @@ def auto(
373
378
  False,
374
379
  help="Run the prepare command after building (defaults to True).",
375
380
  ),
376
- run_commands: Optional[List[str]] = typer.Option(
381
+ command_names: Optional[List[str]] = typer.Option(
382
+ None,
383
+ "-c",
384
+ "--command",
385
+ help="Run one or more commands after building. Can be passed multiple times.",
386
+ ),
387
+ volume_specs: Optional[List[str]] = typer.Option(
377
388
  None,
378
- "--run",
379
- help="Run one or more serve commands after building. Can be passed multiple times.",
389
+ "--volume",
390
+ help="Attach one or more volumes as NAME:/guest/path. Can be passed multiple times.",
380
391
  ),
381
392
  start: bool = typer.Option(
382
393
  False,
383
- help="Equivalent to `--run=start`.",
394
+ "--start/--no-start",
395
+ help="Equivalent to `--command=start`.",
384
396
  ),
385
397
  after_deploy: bool = typer.Option(
386
398
  False,
387
- help="Equivalent to `--run=after_deploy`.",
399
+ "--after-deploy/--no-after-deploy",
400
+ help="Equivalent to `--command=after_deploy`.",
388
401
  ),
389
402
  regenerate: bool = typer.Option(
390
403
  None,
@@ -494,7 +507,6 @@ def auto(
494
507
  docker_opts=docker_opts,
495
508
  skip_docker_if_safe_build=skip_docker_if_safe_build,
496
509
  wasmer_registry=wasmer_registry,
497
- wasmer_token=wasmer_token,
498
510
  wasmer_bin=wasmer_bin,
499
511
  skip_prepare=skip_prepare,
500
512
  env_name=env_name,
@@ -502,24 +514,37 @@ def auto(
502
514
  provider=provider,
503
515
  config=config,
504
516
  )
505
- if run_commands or start or after_deploy or wasmer_deploy or wasmer_deploy_config:
506
- serve(
517
+ if (
518
+ command_names
519
+ or volume_specs
520
+ or start
521
+ or after_deploy
522
+ ):
523
+ run(
507
524
  path,
508
525
  wasmer=wasmer,
509
526
  wasmer_bin=wasmer_bin,
510
527
  docker=docker,
511
528
  docker_client=docker_client,
512
- run_commands=run_commands,
529
+ docker_opts=docker_opts,
530
+ command_names=command_names,
531
+ volume_specs=volume_specs,
513
532
  start=start,
514
533
  after_deploy=after_deploy,
515
- wasmer_token=wasmer_token,
516
534
  wasmer_registry=wasmer_registry,
535
+ )
536
+
537
+ if wasmer_deploy or wasmer_deploy_config:
538
+ deploy(
539
+ path,
517
540
  wasmer_deploy=wasmer_deploy,
541
+ wasmer_deploy_config=wasmer_deploy_config,
542
+ wasmer_bin=wasmer_bin,
543
+ wasmer_token=wasmer_token,
544
+ wasmer_registry=wasmer_registry,
518
545
  wasmer_app_owner=wasmer_app_owner,
519
546
  wasmer_app_name=wasmer_app_name,
520
- wasmer_deploy_config=wasmer_deploy_config,
521
547
  )
522
- # deploy(path)
523
548
 
524
549
 
525
550
  @app.command(name="generate")
@@ -602,7 +627,7 @@ def generate(
602
627
  context_settings={"allow_extra_args": True, "ignore_unknown_options": True},
603
628
  )
604
629
  def _default(ctx: typer.Context) -> None:
605
- if ctx.invoked_subcommand in ["auto", "generate", "build", "serve", "deploy", None]:
630
+ if ctx.invoked_subcommand in ["auto", "generate", "build", "run", "deploy", None]:
606
631
  print_help()
607
632
 
608
633
 
@@ -613,12 +638,55 @@ def deploy(
613
638
  help="Project path (defaults to current directory).",
614
639
  show_default=False,
615
640
  ),
641
+ wasmer_deploy: bool = typer.Option(
642
+ True,
643
+ help="Deploy the project to Wasmer.",
644
+ ),
645
+ wasmer_bin: Optional[str] = typer.Option(
646
+ None,
647
+ help="The path to the Wasmer binary.",
648
+ ),
649
+ wasmer_token: Optional[str] = typer.Option(
650
+ None,
651
+ help="Wasmer token.",
652
+ ),
653
+ wasmer_registry: Optional[str] = typer.Option(
654
+ None,
655
+ help="Wasmer registry.",
656
+ ),
657
+ wasmer_app_owner: Optional[str] = typer.Option(
658
+ None,
659
+ help="Owner of the Wasmer app.",
660
+ ),
661
+ wasmer_app_name: Optional[str] = typer.Option(
662
+ None,
663
+ help="Name of the Wasmer app.",
664
+ ),
665
+ wasmer_deploy_config: Optional[Path] = typer.Option(
666
+ None,
667
+ help="Save the output of the Wasmer build to a json file",
668
+ ),
616
669
  ) -> None:
617
- pass
670
+ if not path.exists():
671
+ raise Exception(f"The path {path} does not exist")
618
672
 
673
+ build_backend = LocalBuildBackend(path, ASSETS_PATH)
674
+ runner = WasmerRunner(
675
+ build_backend,
676
+ path,
677
+ registry=wasmer_registry,
678
+ token=wasmer_token,
679
+ bin=wasmer_bin,
680
+ )
619
681
 
620
- @app.command(name="serve")
621
- def serve(
682
+ if wasmer_deploy_config:
683
+ runner.deploy_config(wasmer_deploy_config)
684
+ elif wasmer_deploy:
685
+ runner.deploy(app_owner=wasmer_app_owner, app_name=wasmer_app_name)
686
+
687
+
688
+ @app.command(name="run")
689
+ def run(
622
690
  path: Path = typer.Argument(
623
691
  Path("."),
624
692
  help="Project path (defaults to current directory).",
@@ -626,7 +694,7 @@ def serve(
626
694
  ),
627
695
  wasmer: bool = typer.Option(
628
696
  False,
629
- help="Use Wasmer to build and serve the project.",
697
+ help="Use Wasmer to run the project.",
630
698
  ),
631
699
  wasmer_bin: Optional[str] = typer.Option(
632
700
  None,
@@ -644,47 +712,32 @@ def serve(
644
712
  None,
645
713
  help="Additional options to pass to the Docker client.",
646
714
  ),
647
- run_commands: Optional[List[str]] = typer.Option(
715
+ command_names: Optional[List[str]] = typer.Option(
648
716
  None,
649
- "--run",
650
- help="Run one or more serve commands. Can be passed multiple times.",
717
+ "-c",
718
+ "--command",
719
+ help="Run one or more commands. Can be passed multiple times.",
651
720
  ),
652
- start: Optional[bool] = typer.Option(
653
- True,
654
- help="Equivalent to `--run=start`.",
721
+ volume_specs: Optional[List[str]] = typer.Option(
722
+ None,
723
+ "--volume",
724
+ help="Attach one or more volumes as NAME:/guest/path. Can be passed multiple times.",
655
725
  ),
656
- after_deploy: bool = typer.Option(
726
+ start: bool = typer.Option(
657
727
  False,
658
- help="Equivalent to `--run=after_deploy`.",
728
+ "--start/--no-start",
729
+ help="Equivalent to `--command=start`.",
659
730
  ),
660
- wasmer_deploy: Optional[bool] = typer.Option(
731
+ after_deploy: bool = typer.Option(
661
732
  False,
662
- help="Deploy the project to Wasmer.",
663
- ),
664
- wasmer_token: Optional[str] = typer.Option(
665
- None,
666
- help="Wasmer token.",
733
+ "--after-deploy/--no-after-deploy",
734
+ help="Equivalent to `--command=after_deploy`.",
667
735
  ),
668
736
  wasmer_registry: Optional[str] = typer.Option(
669
737
  None,
670
738
  help="Wasmer registry.",
671
739
  ),
672
- wasmer_app_owner: Optional[str] = typer.Option(
673
- None,
674
- help="Owner of the Wasmer app.",
675
- ),
676
- wasmer_app_name: Optional[str] = typer.Option(
677
- None,
678
- help="Name of the Wasmer app.",
679
- ),
680
- wasmer_deploy_config: Optional[Path] = typer.Option(
681
- None,
682
- help="Save the output of the Wasmer build to a json file",
683
- ),
684
740
  ) -> None:
685
- # We assume wasmer as an active flag if we pass wasmer deploy or wasmer deploy config
686
- wasmer = wasmer or wasmer_deploy or (wasmer_deploy_config is not None)
687
-
688
741
  if not path.exists():
689
742
  raise Exception(f"The path {path} does not exist")
690
743
 
@@ -700,29 +753,21 @@ def serve(
700
753
  build_backend,
701
754
  path,
702
755
  registry=wasmer_registry,
703
- token=wasmer_token,
704
756
  bin=wasmer_bin,
705
757
  )
706
758
  else:
707
759
  runner = LocalRunner(build_backend, path)
708
760
 
709
761
  commands_to_run = resolve_run_commands(
710
- run_commands=run_commands,
711
- start=bool(start),
762
+ command_names=command_names,
763
+ start=start,
712
764
  after_deploy=after_deploy,
713
765
  )
714
766
 
715
- if wasmer_deploy_config:
716
- if not isinstance(runner, WasmerRunner):
717
- raise RuntimeError("--wasmer-deploy-config requires the Wasmer runner")
718
- runner.deploy_config(wasmer_deploy_config)
719
- elif wasmer_deploy:
720
- if not isinstance(runner, WasmerRunner):
721
- raise RuntimeError("--wasmer-deploy requires the Wasmer runner")
722
- runner.deploy(app_owner=wasmer_app_owner, app_name=wasmer_app_name)
723
- elif commands_to_run:
724
- run_serve_commands(path, runner, commands_to_run)
725
-
767
+ if commands_to_run:
768
+ run_serve_commands(path, runner, commands_to_run, volume_specs=volume_specs)
769
+ else:
770
+ console.print("[bold]No commands specified. Use `--command` to run a command.[/bold]")
726
771
 
727
772
  @app.command(name="plan")
728
773
  def plan(
@@ -928,7 +973,7 @@ def build(
928
973
  ),
929
974
  wasmer: bool = typer.Option(
930
975
  False,
931
- help="Use Wasmer to build and serve the project.",
976
+ help="Use Wasmer to build and package the project.",
932
977
  ),
933
978
  skip_prepare: bool = typer.Option(
934
979
  False,
@@ -1077,6 +1122,7 @@ def build(
1077
1122
  build_volumes(path, serve)
1078
1123
  runner.build(serve)
1079
1124
  if serve.prepare and not skip_prepare:
1125
+ console.print("\n[bold]Running prepare step[/bold]")
1080
1126
  runner.prepare(env, serve.prepare)
1081
1127
 
1082
1128
 
@@ -1095,11 +1141,11 @@ def get_shipit_path(path: Path, shipit_path: Optional[Path] = None) -> Path:
1095
1141
 
1096
1142
 
1097
1143
  def resolve_run_commands(
1098
- run_commands: Optional[List[str]],
1144
+ command_names: Optional[List[str]],
1099
1145
  start: bool,
1100
1146
  after_deploy: bool,
1101
1147
  ) -> List[str]:
1102
- commands = list(run_commands or [])
1148
+ commands = list(command_names or [])
1103
1149
  if after_deploy and "after_deploy" not in commands:
1104
1150
  commands.append("after_deploy")
1105
1151
  if start and "start" not in commands:
@@ -1107,14 +1153,22 @@ def resolve_run_commands(
1107
1153
  return commands
1108
1154
 
1109
1155
 
1110
- def run_serve_commands(path: Path, runner: Runner, commands: List[str]) -> None:
1111
- volume_mappings = load_volume_mappings(path)
1156
+ def run_serve_commands(
1157
+ path: Path,
1158
+ runner: Runner,
1159
+ commands: List[str],
1160
+ volume_specs: Optional[List[str]] = None,
1161
+ ) -> None:
1162
+ volume_mappings = merge_volume_mappings(
1163
+ load_volume_mappings(path),
1164
+ parse_cli_volume_mappings(volume_specs),
1165
+ )
1112
1166
  for command in commands:
1113
1167
  if command in OPTIONAL_RUN_COMMANDS and not runner.has_serve_command(command):
1114
1168
  continue
1169
+ console.print(f"\nRunning command [bold]{command}[/bold]")
1115
1170
  runner.run_serve_command(command, volume_mappings=volume_mappings)
1116
1171
 
1117
-
1118
1172
  def main() -> None:
1119
1173
  args = sys.argv[1:]
1120
1174
  # If no subcommand or first token looks like option/path → default to "build"
@@ -141,6 +141,10 @@ class PhpProvider:
141
141
  )
142
142
  if not config.framework:
143
143
  config.framework = cls.detect_framework(path, composer_config)
144
+ if config.framework == PhpFramework.Drupal:
145
+ # Drupal relies on Apache-style rewrite behavior that the built-in
146
+ # php server handles more predictably than phpix by default.
147
+ config.phpix = False
144
148
  return config
145
149
 
146
150
  @classmethod
@@ -21,7 +21,7 @@ class LocalRunner:
21
21
  self.build_backend = build_backend
22
22
  self.src_dir = src_dir
23
23
  self.runner_path = self.src_dir / ".shipit" / "runner" / "local"
24
- self.serve_bin_path = self.runner_path / "serve" / "bin"
24
+ self.serve_bin_path = self.runner_path / "bin"
25
25
  self.prepare_bash_script = self.runner_path / "prepare" / "prepare.sh"
26
26
 
27
27
  def prepare_config(self, provider_config: object) -> object:
@@ -113,6 +113,5 @@ class LocalRunner:
113
113
  command: str,
114
114
  volume_mappings: Optional[Dict[str, str]] = None,
115
115
  ) -> None:
116
- console.print(f"\n[bold]Running {command} command[/bold]")
117
116
  command_path = self.serve_bin_path / command
118
117
  sh.Command(str(command_path))(_out=write_stdout, _err=write_stderr)
@@ -36,7 +36,7 @@ def serialize_provider_config(provider_config: Any) -> Dict[str, Any]:
36
36
  if provider_config is None:
37
37
  return {}
38
38
  if hasattr(provider_config, "model_dump"):
39
- return provider_config.model_dump(mode="json", exclude_defaults=True)
39
+ return provider_config.model_dump(mode="json", exclude_none=True)
40
40
  if isinstance(provider_config, dict):
41
41
  return provider_config
42
42
  return {}
@@ -149,29 +149,29 @@ class WasmerRunner:
149
149
  },
150
150
  "phpix": {
151
151
  "dependencies": {
152
- "latest": "phpix/phpix-83-32bit@=0.2.0-alpha.3",
153
- "8.3": "phpix/phpix-83-32bit@=0.2.0-alpha.3",
154
- "8.3.29": "phpix/phpix-83-32bit@=0.2.0-alpha.3",
155
- "8.2": "phpix/phpix-82-32bit@=0.2.0-alpha.3",
156
- "8.1": "phpix/phpix-81-32bit@=0.2.0-alpha.3",
157
- "7.4": "wasmer/phpix-32@=0.1.13803",
152
+ "latest": "phpix/phpix-83-32bit@=0.2.0-alpha.4",
153
+ "8.3": "phpix/phpix-83-32bit@=0.2.0-alpha.4",
154
+ "8.3.29": "phpix/phpix-83-32bit@=0.2.0-alpha.4",
155
+ "8.2": "phpix/phpix-82-32bit@=0.2.0-alpha.4",
156
+ "8.1": "phpix/phpix-81-32bit@=0.2.0-alpha.4",
157
+ "7.4": "php/php-32@=7.4.3301", # Note, we don't have PHPix + PHP 7.4 yet
158
158
  },
159
159
  "architecture_dependencies": {
160
160
  "64-bit": {
161
- "latest": "phpix/phpix-83-64bit@=0.2.0-alpha.3",
162
- "8.3": "phpix/phpix-83-64bit@=0.2.0-alpha.3",
163
- "8.3.29": "phpix/phpix-83-64bit@=0.2.0-alpha.3",
164
- "8.2": "phpix/phpix-82-64bit@=0.2.0-alpha.3",
165
- "8.1": "phpix/phpix-81-64bit@=0.2.0-alpha.3",
166
- "7.4": "wasmer/phpix-64@=0.1.13803",
161
+ "latest": "phpix/phpix-83-64bit@=0.2.0-alpha.4",
162
+ "8.3": "phpix/phpix-83-64bit@=0.2.0-alpha.4",
163
+ "8.3.29": "phpix/phpix-83-64bit@=0.2.0-alpha.4",
164
+ "8.2": "phpix/phpix-82-64bit@=0.2.0-alpha.4",
165
+ "8.1": "phpix/phpix-81-64bit@=0.2.0-alpha.4",
166
+ "7.4": "php/php-64@=7.4.3301",
167
167
  },
168
168
  "32-bit": {
169
- "latest": "phpix/phpix-83-32bit@=0.2.0-alpha.3",
170
- "8.3": "phpix/phpix-83-32bit@=0.2.0-alpha.3",
171
- "8.3.29": "phpix/phpix-83-32bit@=0.2.0-alpha.3",
172
- "8.2": "phpix/phpix-82-32bit@=0.2.0-alpha.3",
173
- "8.1": "phpix/phpix-81-32bit@=0.2.0-alpha.3",
174
- "7.4": "wasmer/phpix-32@=0.1.13803",
169
+ "latest": "phpix/phpix-83-32bit@=0.2.0-alpha.4",
170
+ "8.3": "phpix/phpix-83-32bit@=0.2.0-alpha.4",
171
+ "8.3.29": "phpix/phpix-83-32bit@=0.2.0-alpha.4",
172
+ "8.2": "phpix/phpix-82-32bit@=0.2.0-alpha.4",
173
+ "8.1": "phpix/phpix-81-32bit@=0.2.0-alpha.4",
174
+ "7.4": "php/php-32@=7.4.3301",
175
175
  },
176
176
  },
177
177
  "scripts": {"php", "phpix"},
@@ -223,6 +223,7 @@ class WasmerRunner:
223
223
 
224
224
  def prepare_config(self, provider_config: Any) -> Any:
225
225
  from shipit.providers.python import PythonConfig
226
+ from shipit.providers.php import PhpConfig
226
227
 
227
228
  if isinstance(provider_config, PythonConfig):
228
229
  provider_config.python_extra_index_url = (
@@ -230,6 +231,8 @@ class WasmerRunner:
230
231
  )
231
232
  provider_config.cross_platform = "wasix_wasm32"
232
233
  provider_config.precompile_python = True
234
+ elif isinstance(provider_config, PhpConfig):
235
+ provider_config.phpix = True
233
236
  self.provider_config = provider_config
234
237
  return provider_config
235
238
 
@@ -315,13 +318,11 @@ class WasmerRunner:
315
318
  def prepare(self, env: Dict[str, str], prepare: List[PrepareStep]) -> None:
316
319
  prepare_dir = self.wasmer_dir_path / "prepare"
317
320
  self.run_serve_command(
318
- "bash",
319
- volume_mappings=load_volume_mappings(self.src_dir),
320
- extra_args=[
321
- f"--mapdir=/prepare:{prepare_dir}",
322
- "--",
323
- "/prepare/prepare.sh",
324
- ],
321
+ "bash /prepare/prepare.sh",
322
+ volume_mappings={
323
+ **load_volume_mappings(self.src_dir),
324
+ "/prepare": prepare_dir,
325
+ },
325
326
  )
326
327
 
327
328
  def find_file_in_mounts(self, serve: Serve, program: str) -> Optional[Path]:
@@ -606,10 +607,14 @@ class WasmerRunner:
606
607
  self,
607
608
  command: str,
608
609
  volume_mappings: Optional[Dict[str, str]] = None,
609
- extra_args: Optional[List[str]] = None,
610
610
  ) -> None:
611
- console.print(f"\n[bold]Serving site[/bold]: running {command} command")
612
- extra_args = extra_args or []
611
+ parsed_command = shlex.split(command)
612
+ if not parsed_command:
613
+ raise ValueError("Serve command cannot be empty")
614
+
615
+ command_name = parsed_command[0]
616
+ command_args = parsed_command[1:]
617
+ extra_args = []
613
618
 
614
619
  if self.wasmer_registry:
615
620
  extra_args = [f"--registry={self.wasmer_registry}"] + extra_args
@@ -620,12 +625,13 @@ class WasmerRunner:
620
625
  str(self.wasmer_dir_path.absolute()),
621
626
  "--net",
622
627
  "--forward-host-env",
623
- f"--command={command}",
628
+ f"--command={command_name}",
624
629
  *volume_mapdir_args(
625
630
  self.build_backend,
626
631
  volume_mappings or {},
627
632
  ),
628
633
  *extra_args,
634
+ *(["--", *command_args] if command_args else []),
629
635
  ],
630
636
  env=os.environ,
631
637
  )
@@ -1,7 +1,7 @@
1
1
  import sys
2
2
  from rich.console import Console
3
3
 
4
- console = Console()
4
+ console = Console(stderr=True)
5
5
 
6
6
 
7
7
  def write_stdout(line: str) -> None:
@@ -0,0 +1,5 @@
1
+ __all__ = ["version", "version_info"]
2
+
3
+
4
+ version = "0.19.3"
5
+ version_info = (0, 19, 3, "final", 0)