shipit-cli 0.19.0__tar.gz → 0.19.2__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.0 → shipit_cli-0.19.2}/PKG-INFO +22 -11
  2. {shipit_cli-0.19.0 → shipit_cli-0.19.2}/README.md +21 -10
  3. {shipit_cli-0.19.0 → shipit_cli-0.19.2}/pyproject.toml +1 -1
  4. {shipit_cli-0.19.0 → shipit_cli-0.19.2}/src/shipit/assets/wordpress/install.sh +3 -1
  5. {shipit_cli-0.19.0 → shipit_cli-0.19.2}/src/shipit/cli.py +117 -93
  6. {shipit_cli-0.19.0 → shipit_cli-0.19.2}/src/shipit/providers/php.py +4 -0
  7. {shipit_cli-0.19.0 → shipit_cli-0.19.2}/src/shipit/runners/base.py +6 -2
  8. {shipit_cli-0.19.0 → shipit_cli-0.19.2}/src/shipit/runners/local.py +7 -29
  9. {shipit_cli-0.19.0 → shipit_cli-0.19.2}/src/shipit/runners/wasmer.py +44 -49
  10. {shipit_cli-0.19.0 → shipit_cli-0.19.2}/src/shipit/ui.py +1 -1
  11. shipit_cli-0.19.2/src/shipit/version.py +5 -0
  12. shipit_cli-0.19.2/src/shipit/volumes.py +127 -0
  13. shipit_cli-0.19.2/tests/test_cli_after_deploy.py +362 -0
  14. {shipit_cli-0.19.0 → shipit_cli-0.19.2}/tests/test_e2e.py +2 -2
  15. {shipit_cli-0.19.0 → shipit_cli-0.19.2}/tests/test_volumes.py +41 -8
  16. shipit_cli-0.19.0/src/shipit/version.py +0 -5
  17. shipit_cli-0.19.0/tests/test_cli_after_deploy.py +0 -127
  18. {shipit_cli-0.19.0 → shipit_cli-0.19.2}/.gitignore +0 -0
  19. {shipit_cli-0.19.0 → shipit_cli-0.19.2}/src/shipit/__init__.py +0 -0
  20. {shipit_cli-0.19.0 → shipit_cli-0.19.2}/src/shipit/assets/php/php.ini +0 -0
  21. {shipit_cli-0.19.0 → shipit_cli-0.19.2}/src/shipit/assets/wordpress/.htaccess +0 -0
  22. {shipit_cli-0.19.0 → shipit_cli-0.19.2}/src/shipit/assets/wordpress/start.php +0 -0
  23. {shipit_cli-0.19.0 → shipit_cli-0.19.2}/src/shipit/assets/wordpress/wp-config.php +0 -0
  24. {shipit_cli-0.19.0 → shipit_cli-0.19.2}/src/shipit/builders/__init__.py +0 -0
  25. {shipit_cli-0.19.0 → shipit_cli-0.19.2}/src/shipit/builders/base.py +0 -0
  26. {shipit_cli-0.19.0 → shipit_cli-0.19.2}/src/shipit/builders/docker.py +0 -0
  27. {shipit_cli-0.19.0 → shipit_cli-0.19.2}/src/shipit/builders/local.py +0 -0
  28. {shipit_cli-0.19.0 → shipit_cli-0.19.2}/src/shipit/generator.py +0 -0
  29. {shipit_cli-0.19.0 → shipit_cli-0.19.2}/src/shipit/procfile.py +0 -0
  30. {shipit_cli-0.19.0 → shipit_cli-0.19.2}/src/shipit/providers/base.py +0 -0
  31. {shipit_cli-0.19.0 → shipit_cli-0.19.2}/src/shipit/providers/go.py +0 -0
  32. {shipit_cli-0.19.0 → shipit_cli-0.19.2}/src/shipit/providers/hugo.py +0 -0
  33. {shipit_cli-0.19.0 → shipit_cli-0.19.2}/src/shipit/providers/jekyll.py +0 -0
  34. {shipit_cli-0.19.0 → shipit_cli-0.19.2}/src/shipit/providers/laravel.py +0 -0
  35. {shipit_cli-0.19.0 → shipit_cli-0.19.2}/src/shipit/providers/mkdocs.py +0 -0
  36. {shipit_cli-0.19.0 → shipit_cli-0.19.2}/src/shipit/providers/node_static.py +0 -0
  37. {shipit_cli-0.19.0 → shipit_cli-0.19.2}/src/shipit/providers/python.py +0 -0
  38. {shipit_cli-0.19.0 → shipit_cli-0.19.2}/src/shipit/providers/registry.py +0 -0
  39. {shipit_cli-0.19.0 → shipit_cli-0.19.2}/src/shipit/providers/staticfile.py +0 -0
  40. {shipit_cli-0.19.0 → shipit_cli-0.19.2}/src/shipit/providers/wordpress.py +0 -0
  41. {shipit_cli-0.19.0 → shipit_cli-0.19.2}/src/shipit/runners/__init__.py +0 -0
  42. {shipit_cli-0.19.0 → shipit_cli-0.19.2}/src/shipit/shipit_types.py +0 -0
  43. {shipit_cli-0.19.0 → shipit_cli-0.19.2}/src/shipit/utils.py +0 -0
  44. {shipit_cli-0.19.0 → shipit_cli-0.19.2}/tests/test_generate_shipit_examples.py +0 -0
  45. {shipit_cli-0.19.0 → shipit_cli-0.19.2}/tests/test_php_provider.py +0 -0
  46. {shipit_cli-0.19.0 → shipit_cli-0.19.2}/tests/test_staticfile_provider.py +0 -0
  47. {shipit_cli-0.19.0 → shipit_cli-0.19.2}/tests/test_version.py +0 -0
  48. {shipit_cli-0.19.0 → shipit_cli-0.19.2}/tests/test_wasmer_annotations.py +0 -0
  49. {shipit_cli-0.19.0 → shipit_cli-0.19.2}/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.0
3
+ Version: 0.19.2
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.0"
3
+ version = "0.19.2"
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"
@@ -19,7 +19,9 @@ mkdir -p wp-content/plugins
19
19
  mkdir -p wp-content/upgrade
20
20
 
21
21
  if [ -n "${WPCONTENT_BASE_PATH:-}" ] && [ -d "${WPCONTENT_BASE_PATH}" ]; then
22
- cp -R "${WPCONTENT_BASE_PATH}/." /app/wp-content/
22
+ shopt -s dotglob nullglob
23
+ cp -R "${WPCONTENT_BASE_PATH}"/* /app/wp-content
24
+ shopt -u dotglob nullglob
23
25
  fi
24
26
 
25
27
  echo "Installing WordPress core"
@@ -36,6 +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 (
40
+ build_volumes,
41
+ load_volume_mappings,
42
+ merge_volume_mappings,
43
+ parse_cli_volume_mappings,
44
+ )
39
45
 
40
46
  app = typer.Typer(invoke_without_command=True)
41
47
 
@@ -346,7 +352,7 @@ def auto(
346
352
  ),
347
353
  wasmer: bool = typer.Option(
348
354
  False,
349
- help="Use Wasmer to build and serve the project.",
355
+ help="Use Wasmer to build and run the project.",
350
356
  ),
351
357
  wasmer_bin: Optional[str] = typer.Option(
352
358
  None,
@@ -372,18 +378,26 @@ def auto(
372
378
  False,
373
379
  help="Run the prepare command after building (defaults to True).",
374
380
  ),
375
- 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(
376
388
  None,
377
- "--run",
378
- 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.",
379
391
  ),
380
392
  start: bool = typer.Option(
381
393
  False,
382
- help="Equivalent to `--run=start`.",
394
+ "--start/--no-start",
395
+ help="Equivalent to `--command=start`.",
383
396
  ),
384
397
  after_deploy: bool = typer.Option(
385
398
  False,
386
- help="Equivalent to `--run=after_deploy`.",
399
+ "--after-deploy/--no-after-deploy",
400
+ help="Equivalent to `--command=after_deploy`.",
387
401
  ),
388
402
  regenerate: bool = typer.Option(
389
403
  None,
@@ -397,30 +411,10 @@ def auto(
397
411
  False,
398
412
  help="Use a temporary Shipit file in the system temporary directory.",
399
413
  ),
400
- wasmer_deploy: Optional[bool] = typer.Option(
401
- False,
402
- help="Deploy the project to Wasmer.",
403
- ),
404
- wasmer_deploy_config: Optional[Path] = typer.Option(
405
- None,
406
- help="Save the output of the Wasmer build to a json file",
407
- ),
408
- wasmer_token: Optional[str] = typer.Option(
409
- None,
410
- help="Wasmer token.",
411
- ),
412
414
  wasmer_registry: Optional[str] = typer.Option(
413
415
  None,
414
416
  help="Wasmer registry.",
415
417
  ),
416
- wasmer_app_owner: Optional[str] = typer.Option(
417
- None,
418
- help="Owner of the Wasmer app.",
419
- ),
420
- wasmer_app_name: Optional[str] = typer.Option(
421
- None,
422
- help="Name of the Wasmer app.",
423
- ),
424
418
  install_command: Optional[str] = typer.Option(
425
419
  None,
426
420
  help="The install command to use (overwrites the default)",
@@ -450,9 +444,6 @@ def auto(
450
444
  help="The port to use (defaults to 8080).",
451
445
  ),
452
446
  ):
453
- # We assume wasmer as an active flag if we pass wasmer deploy or wasmer deploy config
454
- wasmer = wasmer or wasmer_deploy or (wasmer_deploy_config is not None)
455
-
456
447
  if not path.exists():
457
448
  raise Exception(f"The path {path} does not exist")
458
449
 
@@ -493,7 +484,6 @@ def auto(
493
484
  docker_opts=docker_opts,
494
485
  skip_docker_if_safe_build=skip_docker_if_safe_build,
495
486
  wasmer_registry=wasmer_registry,
496
- wasmer_token=wasmer_token,
497
487
  wasmer_bin=wasmer_bin,
498
488
  skip_prepare=skip_prepare,
499
489
  env_name=env_name,
@@ -501,24 +491,25 @@ def auto(
501
491
  provider=provider,
502
492
  config=config,
503
493
  )
504
- if run_commands or start or after_deploy or wasmer_deploy or wasmer_deploy_config:
505
- serve(
494
+ if (
495
+ command_names
496
+ or volume_specs
497
+ or start
498
+ or after_deploy
499
+ ):
500
+ run(
506
501
  path,
507
502
  wasmer=wasmer,
508
503
  wasmer_bin=wasmer_bin,
509
504
  docker=docker,
510
505
  docker_client=docker_client,
511
- run_commands=run_commands,
506
+ docker_opts=docker_opts,
507
+ command_names=command_names,
508
+ volume_specs=volume_specs,
512
509
  start=start,
513
510
  after_deploy=after_deploy,
514
- wasmer_token=wasmer_token,
515
511
  wasmer_registry=wasmer_registry,
516
- wasmer_deploy=wasmer_deploy,
517
- wasmer_app_owner=wasmer_app_owner,
518
- wasmer_app_name=wasmer_app_name,
519
- wasmer_deploy_config=wasmer_deploy_config,
520
512
  )
521
- # deploy(path)
522
513
 
523
514
 
524
515
  @app.command(name="generate")
@@ -601,7 +592,7 @@ def generate(
601
592
  context_settings={"allow_extra_args": True, "ignore_unknown_options": True},
602
593
  )
603
594
  def _default(ctx: typer.Context) -> None:
604
- if ctx.invoked_subcommand in ["auto", "generate", "build", "serve", "deploy", None]:
595
+ if ctx.invoked_subcommand in ["auto", "generate", "build", "run", "deploy", None]:
605
596
  print_help()
606
597
 
607
598
 
@@ -612,12 +603,57 @@ def deploy(
612
603
  help="Project path (defaults to current directory).",
613
604
  show_default=False,
614
605
  ),
606
+ wasmer_deploy: bool = typer.Option(
607
+ True,
608
+ help="Deploy the project to Wasmer.",
609
+ ),
610
+ wasmer_bin: Optional[str] = typer.Option(
611
+ None,
612
+ help="The path to the Wasmer binary.",
613
+ ),
614
+ wasmer_token: Optional[str] = typer.Option(
615
+ None,
616
+ help="Wasmer token.",
617
+ ),
618
+ wasmer_registry: Optional[str] = typer.Option(
619
+ None,
620
+ help="Wasmer registry.",
621
+ ),
622
+ wasmer_app_owner: Optional[str] = typer.Option(
623
+ None,
624
+ help="Owner of the Wasmer app.",
625
+ ),
626
+ wasmer_app_name: Optional[str] = typer.Option(
627
+ None,
628
+ help="Name of the Wasmer app.",
629
+ ),
630
+ wasmer_deploy_config: Optional[Path] = typer.Option(
631
+ None,
632
+ help="Save the output of the Wasmer build to a json file",
633
+ ),
615
634
  ) -> None:
616
- pass
635
+ if not path.exists():
636
+ raise Exception(f"The path {path} does not exist")
637
+
638
+ build_backend = LocalBuildBackend(path, ASSETS_PATH)
639
+ runner = WasmerRunner(
640
+ build_backend,
641
+ path,
642
+ registry=wasmer_registry,
643
+ token=wasmer_token,
644
+ bin=wasmer_bin,
645
+ )
646
+
647
+ if wasmer_deploy_config:
648
+ runner.deploy_config(wasmer_deploy_config)
649
+ return
617
650
 
651
+ if wasmer_deploy:
652
+ runner.deploy(app_owner=wasmer_app_owner, app_name=wasmer_app_name)
618
653
 
619
- @app.command(name="serve")
620
- def serve(
654
+
655
+ @app.command(name="run")
656
+ def run(
621
657
  path: Path = typer.Argument(
622
658
  Path("."),
623
659
  help="Project path (defaults to current directory).",
@@ -625,7 +661,7 @@ def serve(
625
661
  ),
626
662
  wasmer: bool = typer.Option(
627
663
  False,
628
- help="Use Wasmer to build and serve the project.",
664
+ help="Use Wasmer to run the project.",
629
665
  ),
630
666
  wasmer_bin: Optional[str] = typer.Option(
631
667
  None,
@@ -643,47 +679,32 @@ def serve(
643
679
  None,
644
680
  help="Additional options to pass to the Docker client.",
645
681
  ),
646
- run_commands: Optional[List[str]] = typer.Option(
682
+ command_names: Optional[List[str]] = typer.Option(
647
683
  None,
648
- "--run",
649
- help="Run one or more serve commands. Can be passed multiple times.",
684
+ "-c",
685
+ "--command",
686
+ help="Run one or more commands. Can be passed multiple times.",
650
687
  ),
651
- start: Optional[bool] = typer.Option(
652
- True,
653
- help="Equivalent to `--run=start`.",
688
+ volume_specs: Optional[List[str]] = typer.Option(
689
+ None,
690
+ "--volume",
691
+ help="Attach one or more volumes as NAME:/guest/path. Can be passed multiple times.",
654
692
  ),
655
- after_deploy: bool = typer.Option(
693
+ start: bool = typer.Option(
656
694
  False,
657
- help="Equivalent to `--run=after_deploy`.",
695
+ "--start/--no-start",
696
+ help="Equivalent to `--command=start`.",
658
697
  ),
659
- wasmer_deploy: Optional[bool] = typer.Option(
698
+ after_deploy: bool = typer.Option(
660
699
  False,
661
- help="Deploy the project to Wasmer.",
662
- ),
663
- wasmer_token: Optional[str] = typer.Option(
664
- None,
665
- help="Wasmer token.",
700
+ "--after-deploy/--no-after-deploy",
701
+ help="Equivalent to `--command=after_deploy`.",
666
702
  ),
667
703
  wasmer_registry: Optional[str] = typer.Option(
668
704
  None,
669
705
  help="Wasmer registry.",
670
706
  ),
671
- wasmer_app_owner: Optional[str] = typer.Option(
672
- None,
673
- help="Owner of the Wasmer app.",
674
- ),
675
- wasmer_app_name: Optional[str] = typer.Option(
676
- None,
677
- help="Name of the Wasmer app.",
678
- ),
679
- wasmer_deploy_config: Optional[Path] = typer.Option(
680
- None,
681
- help="Save the output of the Wasmer build to a json file",
682
- ),
683
707
  ) -> None:
684
- # We assume wasmer as an active flag if we pass wasmer deploy or wasmer deploy config
685
- wasmer = wasmer or wasmer_deploy or (wasmer_deploy_config is not None)
686
-
687
708
  if not path.exists():
688
709
  raise Exception(f"The path {path} does not exist")
689
710
 
@@ -699,29 +720,21 @@ def serve(
699
720
  build_backend,
700
721
  path,
701
722
  registry=wasmer_registry,
702
- token=wasmer_token,
703
723
  bin=wasmer_bin,
704
724
  )
705
725
  else:
706
726
  runner = LocalRunner(build_backend, path)
707
727
 
708
728
  commands_to_run = resolve_run_commands(
709
- run_commands=run_commands,
710
- start=bool(start),
729
+ command_names=command_names,
730
+ start=start,
711
731
  after_deploy=after_deploy,
712
732
  )
713
733
 
714
- if wasmer_deploy_config:
715
- if not isinstance(runner, WasmerRunner):
716
- raise RuntimeError("--wasmer-deploy-config requires the Wasmer runner")
717
- runner.deploy_config(wasmer_deploy_config)
718
- elif wasmer_deploy:
719
- if not isinstance(runner, WasmerRunner):
720
- raise RuntimeError("--wasmer-deploy requires the Wasmer runner")
721
- runner.deploy(app_owner=wasmer_app_owner, app_name=wasmer_app_name)
722
- elif commands_to_run:
723
- run_serve_commands(runner, commands_to_run)
724
-
734
+ if commands_to_run:
735
+ run_serve_commands(path, runner, commands_to_run, volume_specs=volume_specs)
736
+ else:
737
+ console.print("[bold]No commands specified. Use `--command` to run a command.[/bold]")
725
738
 
726
739
  @app.command(name="plan")
727
740
  def plan(
@@ -927,7 +940,7 @@ def build(
927
940
  ),
928
941
  wasmer: bool = typer.Option(
929
942
  False,
930
- help="Use Wasmer to build and serve the project.",
943
+ help="Use Wasmer to build and package the project.",
931
944
  ),
932
945
  skip_prepare: bool = typer.Option(
933
946
  False,
@@ -1073,8 +1086,10 @@ def build(
1073
1086
 
1074
1087
  # Build and serve
1075
1088
  build_backend.build(serve.name, env, serve.mounts or [], build_steps)
1089
+ build_volumes(path, serve)
1076
1090
  runner.build(serve)
1077
1091
  if serve.prepare and not skip_prepare:
1092
+ console.print("\n[bold]Running prepare step[/bold]")
1078
1093
  runner.prepare(env, serve.prepare)
1079
1094
 
1080
1095
 
@@ -1093,11 +1108,11 @@ def get_shipit_path(path: Path, shipit_path: Optional[Path] = None) -> Path:
1093
1108
 
1094
1109
 
1095
1110
  def resolve_run_commands(
1096
- run_commands: Optional[List[str]],
1111
+ command_names: Optional[List[str]],
1097
1112
  start: bool,
1098
1113
  after_deploy: bool,
1099
1114
  ) -> List[str]:
1100
- commands = list(run_commands or [])
1115
+ commands = list(command_names or [])
1101
1116
  if after_deploy and "after_deploy" not in commands:
1102
1117
  commands.append("after_deploy")
1103
1118
  if start and "start" not in commands:
@@ -1105,12 +1120,21 @@ def resolve_run_commands(
1105
1120
  return commands
1106
1121
 
1107
1122
 
1108
- def run_serve_commands(runner: Runner, commands: List[str]) -> None:
1123
+ def run_serve_commands(
1124
+ path: Path,
1125
+ runner: Runner,
1126
+ commands: List[str],
1127
+ volume_specs: Optional[List[str]] = None,
1128
+ ) -> None:
1129
+ volume_mappings = merge_volume_mappings(
1130
+ load_volume_mappings(path),
1131
+ parse_cli_volume_mappings(volume_specs),
1132
+ )
1109
1133
  for command in commands:
1110
1134
  if command in OPTIONAL_RUN_COMMANDS and not runner.has_serve_command(command):
1111
1135
  continue
1112
- runner.run_serve_command(command)
1113
-
1136
+ console.print(f"\nRunning command [bold]{command}[/bold]")
1137
+ runner.run_serve_command(command, volume_mappings=volume_mappings)
1114
1138
 
1115
1139
  def main() -> None:
1116
1140
  args = sys.argv[1:]
@@ -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
@@ -1,5 +1,5 @@
1
1
  from pathlib import Path
2
- from typing import Dict, List, Protocol, TYPE_CHECKING
2
+ from typing import Dict, List, Optional, Protocol, TYPE_CHECKING
3
3
 
4
4
  from shipit.builders.base import BuildBackend
5
5
 
@@ -15,5 +15,9 @@ class Runner(Protocol):
15
15
  def build(self, serve: "Serve") -> None: ...
16
16
  def prepare(self, env: Dict[str, str], prepare: List["PrepareStep"]) -> None: ...
17
17
  def has_serve_command(self, command: str) -> bool: ...
18
- def run_serve_command(self, command: str) -> None: ...
18
+ def run_serve_command(
19
+ self,
20
+ command: str,
21
+ volume_mappings: Optional[Dict[str, str]] = None,
22
+ ) -> None: ...
19
23
  def get_serve_mount_path(self, name: str) -> Path: ...
@@ -1,6 +1,6 @@
1
1
  import shutil
2
2
  from pathlib import Path
3
- from typing import Dict, List, TYPE_CHECKING
3
+ from typing import Dict, List, Optional, TYPE_CHECKING
4
4
 
5
5
  import sh
6
6
  from rich import box
@@ -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:
@@ -37,30 +37,6 @@ class LocalRunner:
37
37
  self.build_prepare(serve)
38
38
  self.build_serve(serve)
39
39
 
40
- def _prepare_volumes(self, serve: Serve) -> None:
41
- for volume in serve.volumes or []:
42
- source = volume.path.absolute()
43
- target = volume.serve_path
44
-
45
- source.mkdir(parents=True, exist_ok=True)
46
-
47
- if target.is_symlink():
48
- if target.resolve(strict=False) == source.resolve():
49
- continue
50
- target.unlink()
51
- elif target.exists():
52
- if target.is_dir():
53
- if not any(source.iterdir()):
54
- shutil.copytree(target, source, dirs_exist_ok=True)
55
- shutil.rmtree(target)
56
- else:
57
- if not any(source.iterdir()):
58
- shutil.copy2(target, source / target.name)
59
- target.unlink()
60
-
61
- target.parent.mkdir(parents=True, exist_ok=True)
62
- target.symlink_to(source, target_is_directory=True)
63
-
64
40
  def build_prepare(self, serve: Serve) -> None:
65
41
  if not serve.prepare:
66
42
  return
@@ -93,7 +69,6 @@ class LocalRunner:
93
69
 
94
70
  def build_serve(self, serve: Serve) -> None:
95
71
  console.print("\n[bold]Building serve[/bold]")
96
- self._prepare_volumes(serve)
97
72
  shutil.rmtree(self.serve_bin_path.parent, ignore_errors=True)
98
73
  self.serve_bin_path.mkdir(parents=True, exist_ok=True)
99
74
  runtime_path = self.build_backend.get_runtime_path() or ""
@@ -133,7 +108,10 @@ class LocalRunner:
133
108
  def has_serve_command(self, command: str) -> bool:
134
109
  return (self.serve_bin_path / command).is_file()
135
110
 
136
- def run_serve_command(self, command: str) -> None:
137
- console.print(f"\n[bold]Running {command} command[/bold]")
111
+ def run_serve_command(
112
+ self,
113
+ command: str,
114
+ volume_mappings: Optional[Dict[str, str]] = None,
115
+ ) -> None:
138
116
  command_path = self.serve_bin_path / command
139
117
  sh.Command(str(command_path))(_out=write_stdout, _err=write_stderr)