From 0e89486a220c776d1b97fdb9eaa308c63a7ed97c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Hojtsy?= Date: Wed, 19 Aug 2026 08:51:42 +0200 Subject: [PATCH 1/3] fix: Make canvas paths docroot-aware in host commands Derive the canvas module location from composer installer-paths so xb-setup, xb-cypress, and xb-playwright work with both docroot=web and docroot="" projects (including Drupal core-style checkouts with drupal-dev). Also update README setup/usage wording to reflect docroot-agnostic behavior. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- README.md | 6 +++--- commands/host/xb-cypress | 22 +++++++++++++++++++--- commands/host/xb-playwright | 19 +++++++++++++++++-- commands/host/xb-setup | 36 +++++++++++++++++++++++++++++------- 4 files changed, 68 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 5077c55..ba0fd60 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ mkdir ~/Sites/xb-dev cd ~/Sites/xb-dev # Configure the new DDEV project. -ddev config --project-type=drupal11 --docroot=web +ddev config --project-type=drupal11 # Create the Drupal project. ddev composer create-project drupal/recommended-project:11.x@dev --no-install @@ -40,7 +40,7 @@ ddev composer create-project drupal/recommended-project:11.x@dev --no-install # Install the add-on. ddev add-on get drupal-canvas/ddev-drupal-xb-dev -# Perform one-time setup operations. +# Perform one-time setup operations, including composer installing Drupal Canvas itself. ddev xb-setup # Optionally add some convenience extras for development. @@ -56,7 +56,7 @@ ddev xb-workspaces-dev The resulting DDEV project is just like any other one. Interact with it using the [the built-in commands](https://ddev.readthedocs.io/en/stable/users/usage/commands/), e.g., `ddev launch` to browse the site. -The installation process clones [the Drupal Canvas module](https://www.drupal.org/project/canvas) into `web/modules/contrib/canvas`. Develop and contribute from either location like you would any other Git repo for a normal Drupal project. +The installation process clones [the Drupal Canvas module](https://www.drupal.org/project/canvas) into the project installer path for contrib modules (typically `web/modules/contrib/canvas` for `docroot: web`, or `modules/contrib/canvas` for `docroot: ""`). Develop and contribute from there like you would any other Git repo for a normal Drupal project. Any time you update the Drupal Canvas module or modify its front-end code, be sure to rebuild the UI app assets: diff --git a/commands/host/xb-cypress b/commands/host/xb-cypress index 59e24c1..59f5ab4 100755 --- a/commands/host/xb-cypress +++ b/commands/host/xb-cypress @@ -12,8 +12,24 @@ cd "$(dirname "$0")" || exit 1 -CYPRESS_BIN="$(dirname "$0")/../../../web/modules/contrib/canvas/node_modules/cypress/bin/cypress" -CYPRESS_BIN_INSIDE_CONTAINER="/var/www/html/web/modules/contrib/canvas/node_modules/cypress/bin/cypress" +resolve_canvas_dir() { + ddev exec -- php -r ' +$composer = json_decode((string) file_get_contents("composer.json"), true); +$paths = $composer["extra"]["installer-paths"] ?? []; +foreach ($paths as $path => $conditions) { + if (in_array("type:drupal-module", $conditions, true)) { + echo str_replace("{\$name}", "canvas", $path); + exit(0); + } +} +echo "modules/contrib/canvas"; +' +} + +CANVAS_DIR="$(resolve_canvas_dir)" +CYPRESS_BIN="$(dirname "$0")/../../../$CANVAS_DIR/node_modules/cypress/bin/cypress" +CYPRESS_BIN_INSIDE_CONTAINER="/var/www/html/$CANVAS_DIR/node_modules/cypress/bin/cypress" +CANVAS_UI_DIR_INSIDE_CONTAINER="/var/www/html/$CANVAS_DIR/ui" # Check for the presence of Cypress. if ! command -v "$CYPRESS_BIN" &>/dev/null; then @@ -62,7 +78,7 @@ xhost + function xb_cypress { # This needs to be the binary path inside the container. ddev exec \ - --dir /var/www/html/web/modules/contrib/canvas/ui \ + --dir "$CANVAS_UI_DIR_INSIDE_CONTAINER" \ "$CYPRESS_BIN_INSIDE_CONTAINER $1" } diff --git a/commands/host/xb-playwright b/commands/host/xb-playwright index 27b094e..99c1216 100755 --- a/commands/host/xb-playwright +++ b/commands/host/xb-playwright @@ -10,8 +10,23 @@ ## OSTypes: darwin,linux ## ExecRaw: true -CANVAS_DIR_INSIDE_CONTAINER="/var/www/html/web/modules/contrib/canvas" -CANVAS_DIR_ON_HOST="$(dirname "$0")/../../../web/modules/contrib/canvas" +resolve_canvas_dir() { + ddev exec -- php -r ' +$composer = json_decode((string) file_get_contents("composer.json"), true); +$paths = $composer["extra"]["installer-paths"] ?? []; +foreach ($paths as $path => $conditions) { + if (in_array("type:drupal-module", $conditions, true)) { + echo str_replace("{\$name}", "canvas", $path); + exit(0); + } +} +echo "modules/contrib/canvas"; +' +} + +CANVAS_DIR_RELATIVE="$(resolve_canvas_dir)" +CANVAS_DIR_INSIDE_CONTAINER="/var/www/html/$CANVAS_DIR_RELATIVE" +CANVAS_DIR_ON_HOST="$(dirname "$0")/../../../$CANVAS_DIR_RELATIVE" # Check that Playwright is installed (npm install has run). if [[ ! -x "$CANVAS_DIR_ON_HOST/node_modules/.bin/playwright" ]]; then diff --git a/commands/host/xb-setup b/commands/host/xb-setup index 593866e..0d71def 100755 --- a/commands/host/xb-setup +++ b/commands/host/xb-setup @@ -11,6 +11,28 @@ cd "$(dirname "$0")" || exit cd ../../../ set -e +resolve_canvas_dir() { + ddev exec -- php -r ' +$composer = json_decode((string) file_get_contents("composer.json"), true); +$paths = $composer["extra"]["installer-paths"] ?? []; +foreach ($paths as $path => $conditions) { + if (in_array("type:drupal-module", $conditions, true)) { + echo str_replace("{\$name}", "canvas", $path); + exit(0); + } +} +echo "modules/contrib/canvas"; +' +} + +CANVAS_DIR="$(resolve_canvas_dir)" +DOCROOT_PREFIX="${CANVAS_DIR%/modules/contrib/canvas}" +if [ "$DOCROOT_PREFIX" = "$CANVAS_DIR" ]; then + DOCROOT_PREFIX="" +fi +SETTINGS_DDEV_PATH="${DOCROOT_PREFIX:+$DOCROOT_PREFIX/}sites/default/settings.ddev.php" +CORE_DIR_IN_CONTAINER="/var/www/html/${DOCROOT_PREFIX:+$DOCROOT_PREFIX/}core" + # Flag-handling. while :; do case ${1:-} in @@ -28,7 +50,7 @@ while :; do done # Exit early if the environment is already set up. -if [ -d web/modules/contrib/canvas/.git ] && [ ! "$FORCE" ]; then +if [ -d "$CANVAS_DIR/.git" ] && [ ! "$FORCE" ]; then GREEN="\033[0;32m" NO_COLOR="\033[0m" printf "%bThe Drupal Canvas development environment is already set up.%b\n" "$GREEN" "$NO_COLOR" @@ -40,14 +62,14 @@ if [ -d web/modules/contrib/canvas/.git ] && [ ! "$FORCE" ]; then fi # Remove the Drupal Canvas module if it's there. -rm -rf web/modules/contrib/canvas -mkdir -p web/modules/contrib +rm -rf "$CANVAS_DIR" +mkdir -p "$(dirname "$CANVAS_DIR")" # Place the Drupal Canvas module via Git for development. Require # it with Composer to test its composer.json and place dependencies. git clone \ git@git.drupal.org:project/canvas.git \ - web/modules/contrib/canvas + "$CANVAS_DIR" # Allow all Composer plugins. ddev composer config \ @@ -66,7 +88,7 @@ ddev composer require \ ddev composer config \ repositories.xb \ path \ - web/modules/contrib/canvas + "$CANVAS_DIR" ddev composer require \ --no-install \ --update-with-all-dependencies \ @@ -87,13 +109,13 @@ ddev composer require \ # Allow test modules and themes to be installed. # shellcheck disable=SC2016 printf '\n# Allow test modules and themes to be installed.\n$settings["extension_discovery_scan_tests"] = TRUE;' \ - >> web/sites/default/settings.ddev.php + >> "$SETTINGS_DDEV_PATH" # Install Drupal and enable the Drupal Canvas module. ddev xb-site-install # Install Drupal core NPM packages. -ddev exec --dir /var/www/html/web/core -- npm install +ddev exec --dir "$CORE_DIR_IN_CONTAINER" -- npm install # Build front-end assets. ddev xb-ui-build From 96eafef3031cbdeb47cda1de66da082a129b3fde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Hojtsy?= Date: Wed, 19 Aug 2026 12:48:07 +0200 Subject: [PATCH 2/3] refactor: Extract shared host canvas path helpers Move docroot-aware canvas path resolution into a shared host helper script and reuse it from xb-setup, xb-cypress, and xb-playwright. This removes duplicated logic and keeps path derivation consistent across commands. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- commands/host/.xb-command-helpers.sh | 34 ++++++++++++++++++++++++++++ commands/host/xb-cypress | 24 ++++---------------- commands/host/xb-playwright | 20 +++------------- commands/host/xb-setup | 29 +++++------------------- install.yaml | 1 + 5 files changed, 49 insertions(+), 59 deletions(-) create mode 100644 commands/host/.xb-command-helpers.sh diff --git a/commands/host/.xb-command-helpers.sh b/commands/host/.xb-command-helpers.sh new file mode 100644 index 0000000..06379ce --- /dev/null +++ b/commands/host/.xb-command-helpers.sh @@ -0,0 +1,34 @@ +#!/bin/bash + +# Shared helpers for host-side xb commands. + +resolve_canvas_dir() { + ddev exec -- php -r ' +$composer = json_decode((string) file_get_contents("composer.json"), true); +$paths = $composer["extra"]["installer-paths"] ?? []; +foreach ($paths as $path => $conditions) { + if (in_array("type:drupal-module", $conditions, true)) { + echo str_replace("{\$name}", "canvas", $path); + exit(0); + } +} +echo "modules/contrib/canvas"; +' +} + +init_canvas_paths() { + local script_dir="$1" + local docroot_prefix + + CANVAS_DIR_RELATIVE="$(resolve_canvas_dir)" + CANVAS_DIR_ON_HOST="$script_dir/../../../$CANVAS_DIR_RELATIVE" + CANVAS_DIR_INSIDE_CONTAINER="/var/www/html/$CANVAS_DIR_RELATIVE" + CANVAS_UI_DIR_INSIDE_CONTAINER="$CANVAS_DIR_INSIDE_CONTAINER/ui" + + docroot_prefix="${CANVAS_DIR_RELATIVE%/modules/contrib/canvas}" + if [ "$docroot_prefix" = "$CANVAS_DIR_RELATIVE" ]; then + docroot_prefix="" + fi + SETTINGS_DDEV_PATH="${docroot_prefix:+$docroot_prefix/}sites/default/settings.ddev.php" + CORE_DIR_IN_CONTAINER="/var/www/html/${docroot_prefix:+$docroot_prefix/}core" +} diff --git a/commands/host/xb-cypress b/commands/host/xb-cypress index 59f5ab4..0025700 100755 --- a/commands/host/xb-cypress +++ b/commands/host/xb-cypress @@ -10,26 +10,12 @@ ## OSTypes: darwin,linux ## ExecRaw: true -cd "$(dirname "$0")" || exit 1 +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +. "$SCRIPT_DIR/.xb-command-helpers.sh" +init_canvas_paths "$SCRIPT_DIR" -resolve_canvas_dir() { - ddev exec -- php -r ' -$composer = json_decode((string) file_get_contents("composer.json"), true); -$paths = $composer["extra"]["installer-paths"] ?? []; -foreach ($paths as $path => $conditions) { - if (in_array("type:drupal-module", $conditions, true)) { - echo str_replace("{\$name}", "canvas", $path); - exit(0); - } -} -echo "modules/contrib/canvas"; -' -} - -CANVAS_DIR="$(resolve_canvas_dir)" -CYPRESS_BIN="$(dirname "$0")/../../../$CANVAS_DIR/node_modules/cypress/bin/cypress" -CYPRESS_BIN_INSIDE_CONTAINER="/var/www/html/$CANVAS_DIR/node_modules/cypress/bin/cypress" -CANVAS_UI_DIR_INSIDE_CONTAINER="/var/www/html/$CANVAS_DIR/ui" +CYPRESS_BIN="$CANVAS_DIR_ON_HOST/node_modules/cypress/bin/cypress" +CYPRESS_BIN_INSIDE_CONTAINER="$CANVAS_DIR_INSIDE_CONTAINER/node_modules/cypress/bin/cypress" # Check for the presence of Cypress. if ! command -v "$CYPRESS_BIN" &>/dev/null; then diff --git a/commands/host/xb-playwright b/commands/host/xb-playwright index 99c1216..a3d7b30 100755 --- a/commands/host/xb-playwright +++ b/commands/host/xb-playwright @@ -10,23 +10,9 @@ ## OSTypes: darwin,linux ## ExecRaw: true -resolve_canvas_dir() { - ddev exec -- php -r ' -$composer = json_decode((string) file_get_contents("composer.json"), true); -$paths = $composer["extra"]["installer-paths"] ?? []; -foreach ($paths as $path => $conditions) { - if (in_array("type:drupal-module", $conditions, true)) { - echo str_replace("{\$name}", "canvas", $path); - exit(0); - } -} -echo "modules/contrib/canvas"; -' -} - -CANVAS_DIR_RELATIVE="$(resolve_canvas_dir)" -CANVAS_DIR_INSIDE_CONTAINER="/var/www/html/$CANVAS_DIR_RELATIVE" -CANVAS_DIR_ON_HOST="$(dirname "$0")/../../../$CANVAS_DIR_RELATIVE" +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +. "$SCRIPT_DIR/.xb-command-helpers.sh" +init_canvas_paths "$SCRIPT_DIR" # Check that Playwright is installed (npm install has run). if [[ ! -x "$CANVAS_DIR_ON_HOST/node_modules/.bin/playwright" ]]; then diff --git a/commands/host/xb-setup b/commands/host/xb-setup index 0d71def..763f7d5 100755 --- a/commands/host/xb-setup +++ b/commands/host/xb-setup @@ -7,31 +7,14 @@ ## Flags: [{"Name":"force","Shorthand":"f","Usage":"Completely reset an existing environment if present and start over"}] ## ExecRaw: true -cd "$(dirname "$0")" || exit -cd ../../../ +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +. "$SCRIPT_DIR/.xb-command-helpers.sh" + +cd "$SCRIPT_DIR/../../../" || exit set -e -resolve_canvas_dir() { - ddev exec -- php -r ' -$composer = json_decode((string) file_get_contents("composer.json"), true); -$paths = $composer["extra"]["installer-paths"] ?? []; -foreach ($paths as $path => $conditions) { - if (in_array("type:drupal-module", $conditions, true)) { - echo str_replace("{\$name}", "canvas", $path); - exit(0); - } -} -echo "modules/contrib/canvas"; -' -} - -CANVAS_DIR="$(resolve_canvas_dir)" -DOCROOT_PREFIX="${CANVAS_DIR%/modules/contrib/canvas}" -if [ "$DOCROOT_PREFIX" = "$CANVAS_DIR" ]; then - DOCROOT_PREFIX="" -fi -SETTINGS_DDEV_PATH="${DOCROOT_PREFIX:+$DOCROOT_PREFIX/}sites/default/settings.ddev.php" -CORE_DIR_IN_CONTAINER="/var/www/html/${DOCROOT_PREFIX:+$DOCROOT_PREFIX/}core" +init_canvas_paths "$SCRIPT_DIR" +CANVAS_DIR="$CANVAS_DIR_RELATIVE" # Flag-handling. while :; do diff --git a/install.yaml b/install.yaml index c479567..80cd745 100644 --- a/install.yaml +++ b/install.yaml @@ -5,6 +5,7 @@ name: drupal-xb-dev project_files: + - commands/host/.xb-command-helpers.sh - commands/host/xb-cypress - commands/host/xb-fix - commands/host/xb-playwright From f6becf17de744192f83b86fe1f0b5f20a9b72997 Mon Sep 17 00:00:00 2001 From: Christian Lopez Espinola Date: Mon, 31 Aug 2026 09:59:16 +0200 Subject: [PATCH 3/3] chore: Add #ddev-generated marker to .xb-command-helpers.sh Keeps the shared helper in sync on add-on upgrades, matching the marker convention DDEV's upgrade path and post_install_actions cleanup key off. Co-Authored-By: Claude Opus 4.8 --- commands/host/.xb-command-helpers.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/commands/host/.xb-command-helpers.sh b/commands/host/.xb-command-helpers.sh index 06379ce..3706674 100644 --- a/commands/host/.xb-command-helpers.sh +++ b/commands/host/.xb-command-helpers.sh @@ -1,5 +1,7 @@ #!/bin/bash +## #ddev-generated + # Shared helpers for host-side xb commands. resolve_canvas_dir() {