├── .github ├── release.yml └── workflows │ └── tests.yml ├── .gitignore ├── README.md ├── commands ├── host │ ├── xb-cypress │ ├── xb-fix │ ├── xb-setup │ └── xb-static └── web │ ├── xb-autosave │ ├── xb-core-set-version │ ├── xb-dev-extras │ ├── xb-eslint │ ├── xb-phpcs │ ├── xb-phpstan │ ├── xb-phpunit │ ├── xb-site-install │ ├── xb-stylelint │ ├── xb-ui-build │ ├── xb-ui-dev │ └── xb-workspaces-dev ├── config.drupal-xb-dev.yaml ├── install.yaml ├── resources └── xquartz-settings.png ├── tests ├── test.bats └── test.sh └── var └── .gitkeep /.github/release.yml: -------------------------------------------------------------------------------- 1 | changelog: 2 | exclude: 3 | labels: 4 | - ignore-for-release-notes 5 | categories: 6 | - title: Breaking Changes 7 | labels: 8 | - Semver-Major 9 | - breaking-change 10 | - title: New Features 11 | labels: 12 | - Semver-Minor 13 | - enhancement 14 | - title: Other Changes 15 | labels: 16 | - "*" 17 | -------------------------------------------------------------------------------- /.github/workflows/tests.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Tests 3 | 4 | on: 5 | pull_request: 6 | push: 7 | branches: [ main, wip ] 8 | 9 | schedule: 10 | # Daily at 00:00:00 UTC. 11 | # @see https://crontab.cronhub.io/ 12 | - cron: "0 0 * * *" 13 | 14 | workflow_dispatch: 15 | inputs: 16 | debug_enabled: 17 | type: boolean 18 | description: Debug with tmate 19 | required: false 20 | default: false 21 | 22 | concurrency: 23 | group: ${{ github.workflow }}-${{ github.ref }} 24 | cancel-in-progress: true 25 | 26 | # This is required for "gautamkrishnar/keepalive-workflow", see "ddev/github-action-add-on-test". 27 | permissions: 28 | actions: write 29 | 30 | jobs: 31 | tests: 32 | strategy: 33 | matrix: 34 | ddev_version: [ stable, HEAD ] 35 | fail-fast: false 36 | 37 | runs-on: ubuntu-latest 38 | 39 | steps: 40 | - uses: ddev/github-action-add-on-test@v2 # https://github.com/marketplace/actions/ddev-add-on-test 41 | with: 42 | ddev_version: ${{ matrix.ddev_version }} 43 | token: ${{ secrets.GITHUB_TOKEN }} 44 | debug_enabled: ${{ github.event.inputs.debug_enabled }} 45 | addon_repository: ${{ env.GITHUB_REPOSITORY }} 46 | addon_ref: ${{ env.GITHUB_REF }} 47 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea 2 | /var/* 3 | !/var/.gitkeep 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DDEV Drupal Experience Builder Development Environment 2 | 3 | This creates and configures a DDEV project for local Drupal [Experience Builder](https://www.drupal.org/project/experience_builder) (XB) module development. Specifically, it creates a Drupal site, clones and installs the module, sets up the front-end dependencies, and provides specialized development and testing tools. 4 | 5 | > **Notice:** This add-on is experimental. See [Support & community](#support--community) below. 6 | 7 | - [Requirements](#requirements) 8 | - [Installation](#installation) 9 | - [Usage](#usage) 10 | - [Updating](#updating) 11 | - [Cypress](#cypress) 12 | - [Setup](#setup) 13 | - [Usage](#usage-1) 14 | - [Support \& community](#support--community) 15 | - [FAQ \& known issues](#faq--known-issues) 16 | - [Can I use Cypress on Linux or Windows?](#can-i-use-cypress-on-linux-or-windows) 17 | - [What if Cypress fails to start?](#what-if-cypress-fails-to-start) 18 | - [What if I get an HTTPS error?](#what-if-i-get-an-https-error) 19 | 20 | ## Requirements 21 | 22 | Obviously, this requires a working [DDEV](https://ddev.com/) installation. It has been successfully tested with [Orbstack](https://orbstack.dev/), [Lima](https://lima-vm.io/), [Colima](https://github.com/abiosoft/colima), [Rancher Desktop](https://rancherdesktop.io/), and [Docker Desktop](https://www.docker.com/products/docker-desktop/). Others should work fine, as well. 23 | 24 | ## Installation 25 | 26 | ```shell 27 | # Create a new directory for your new DDEV project. 28 | # This can be any place you like. For example: 29 | mkdir ~/Sites/xb-dev 30 | cd ~/Sites/xb-dev 31 | 32 | # Configure the new DDEV project. 33 | ddev config --project-type=drupal11 --docroot=web 34 | 35 | # Create the Drupal project. 36 | ddev composer create drupal/recommended-project:11.x@dev --no-install 37 | 38 | # Install the add-on. 39 | ddev add-on get drupal-xb/ddev-drupal-xb-dev 40 | 41 | # Perform one-time setup operations. 42 | ddev xb-setup 43 | 44 | # Optionally add some convenience extras for development. 45 | ddev xb-dev-extras 46 | 47 | # Optionally configure the environment for Workspaces development. Note: This can be 48 | # a little volatile due to upstream Workspaces changes. Be aware that it can fail 49 | # and leave your site in a non-working state requiring you to set it up again from scratch. 50 | ddev xb-workspaces-dev 51 | ``` 52 | 53 | ## Usage 54 | 55 | 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. 56 | 57 | The installation process clones [the Experience Builder module](https://www.drupal.org/project/experience_builder) into `web/modules/contrib/experience_builder`. Develop and contribute from either location like you would any other Git repo for a normal Drupal project. 58 | 59 | Any time you update the Experience Builder module or modify its front-end code, be sure to rebuild the UI app assets: 60 | 61 | ```shell 62 | ddev xb-ui-build 63 | ``` 64 | 65 | When developing the React app, make sure to use the HTTPS URL of your DDEV project, then run: 66 | 67 | ```shell 68 | ddev xb-ui-dev 69 | ``` 70 | 71 | To completely reinstall Drupal and the Experience Builder module, run: 72 | 73 | ```shell 74 | ddev xb-site-install 75 | ``` 76 | 77 | For the full list of available Experience Builder commands, run this: 78 | 79 | ```shell 80 | ddev | grep xb- 81 | ``` 82 | 83 | ## Updating 84 | 85 | Update the Experience Builder module clone just like you would any other Git repo. No tools are currently provided for updating Core. 86 | 87 | ## Cypress 88 | 89 | Experience Builder uses [Cypress](https://www.cypress.io/) for front-end testing. It is currently only supported on macOS. 90 | 91 | ### Setup 92 | 93 | > Carefully follow the below XQuartz configuration steps after installing it. Failure to do so will result in frustrating, difficult to debug problems. 94 | 95 | Install XQuartz using Homebrew. See also https://www.xquartz.org/. 96 | 97 | ```shell 98 | brew install xquartz 99 | ``` 100 | 101 | Configure XQuartz to allow connections from the host: 102 | 103 | - Open XQuartz. 104 | - Open Preferences ("XQuartz" > "Settings..." from the menu or `⌘,`). 105 | - Go to the "Security" tab. 106 | - Check the "Allow connections from network clients" checkbox. 107 | - Log out and back in or restart your machine for the change to take effect. 108 | 109 | ![XQuartz Preferences dialog](resources/xquartz-settings.png) 110 | 111 | ### Usage 112 | 113 | Run Cypress tests interactively: 114 | 115 | ```shell 116 | ddev cypress open 117 | ``` 118 | 119 | Run them headlessly: 120 | 121 | ```shell 122 | ddev cypress run 123 | ``` 124 | 125 | Run component/unit tests: 126 | 127 | ```shell 128 | ddev cypress component 129 | ``` 130 | 131 | ## Support & community 132 | 133 | - [Experience Builder](https://www.drupal.org/project/experience_builder) module 134 | - [#experience-builder](https://drupal.slack.com/archives/C072JMEPUS1) Drupal Slack channel 135 | - Background on this add-on: [DDEV support for Cypress tests [#3458369] | Drupal.org](https://www.drupal.org/project/experience_builder/issues/3458369) 136 | 137 | ## FAQ & known issues 138 | 139 | ### Can I use Cypress on Linux or Windows? 140 | 141 | No, not currently; and there are no plans at present to support it. See [Support & community](#support--community) above if you want to make a case for it. 142 | 143 | ### What if Cypress fails to start? 144 | 145 | If you get an error like the below when attempting to run Cypress on macOS... 146 | 147 | - Confirm that you have carefully followed _all_ the instructions under [Cypress](#cypress). 148 | - See if your [Docker provider](#docker-provider) above requires any special configuration. 149 | 150 | If these don't resolve the issue, see [Support & community](#support--community) above. 151 | 152 | ``` 153 | Cypress failed to start. 154 | 155 | This may be due to a missing library or dependency. https://on.cypress.io/required-dependencies 156 | 157 | Please refer to the error below for more details. 158 | 159 | ---------- 160 | 161 | [2536:0808/191430.352014:ERROR:bus.cc(407)] Failed to connect to the bus: Failed to connect to socket /run/dbus/system_bus_socket: No such file or directory 162 | [2536:0808/191431.055343:ERROR:ozone_platform_x11.cc(240)] Missing X server or $DISPLAY 163 | [2536:0808/191431.055373:ERROR:env.cc(255)] The platform failed to initialize. Exiting. 164 | 165 | ---------- 166 | 167 | Platform: linux-arm64 (Debian - 12) 168 | Cypress Version: 13.12.0 169 | Failed to execute command node_modules/.bin/cypress open --browser electron --project .: exit status 1 170 | Failed to run xb-cypress-open ; error=exit status 1 171 | ``` 172 | 173 | ### What if I get an HTTPS error? 174 | 175 | If this is your first time using DDEV, you may get an error like the following when you try to visit your site. If so, you need to configure your OS and browser to trust the root certificate authority that DDEV uses. See [DDEV Installation](https://ddev.readthedocs.io/en/stable/users/install/ddev-installation/). 176 | 177 | ``` 178 | This site can't be reached 179 | 180 | The webpage at https://xb-dev.ddev.site/ might be temporarily down or it may have moved permanently to a new web address. 181 | 182 | ERR_SSL_UNRECOGNIZED_NAME_ALERT 183 | ``` 184 | -------------------------------------------------------------------------------- /commands/host/xb-cypress: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ## #ddev-generated 4 | ## Description: Run Cypress tests. 5 | ## Usage: xb-cypress open|run|component 6 | ## Example: ddev xb-cypress open # Run end-to-end tests in interactive mode.\nddev xb-cypress run # Run all tests headlessly.\nddev xb-cypress component # Run component/unit tests.\nddev xb-cypress open -- --env "VAR=value" # Pass arbitrary command arguments. 7 | ## Aliases: cypress,cy 8 | ## Flags: [] 9 | ## AutocompleteTerms: ["component","open","run"] 10 | ## OSTypes: darwin 11 | ## ExecRaw: true 12 | 13 | cd "$(dirname "$0")" || exit 1 14 | 15 | CYPRESS_BIN="$(dirname "$0")/../../../web/modules/contrib/experience_builder/ui/node_modules/.bin/cypress" 16 | 17 | # Check for the presence of Cypress. 18 | if ! command -v "$CYPRESS_BIN" &>/dev/null; then 19 | echo "Cypress is not installed. Run 'ddev xb-ui-build' and try again." 20 | exit 1 21 | fi 22 | 23 | # Check if XQuartz is installed and running. 24 | if ! open -Ra XQuartz; then 25 | echo "Cannot find XQuartz. Install it and try again." 26 | echo "Hint: https://github.com/drupal-xb/ddev-drupal-xb-dev#cypress" 27 | exit 1 28 | fi 29 | 30 | # Start XQuartz if it isn't running. 31 | if ! pgrep -x Xquartz &>/dev/null; then 32 | open -a XQuartz 33 | # Give it a moment to start up. 34 | sleep 2 35 | fi 36 | 37 | # Open up the allowed X11 hosts. 38 | xhost + 39 | 40 | # Runs a given Cypress command, e.g., `xb_cypress run --e2e`. 41 | function xb_cypress { 42 | ddev exec \ 43 | --dir /var/www/html/web/modules/contrib/experience_builder/ui \ 44 | "$CYPRESS_BIN $1" 45 | } 46 | 47 | # Remove "--", if present, or it gets treated as the command argument. 48 | if [[ "$1" == "--" ]]; then 49 | shift 50 | fi 51 | 52 | # Use the first argument as the command or default to "open". 53 | COMMAND="${1:-open}" 54 | 55 | # Shift to process remaining arguments. 56 | shift 57 | 58 | case "$COMMAND" in 59 | open) xb_cypress "open --browser electron $*" ;; 60 | run) xb_cypress "run --browser electron $*" ;; 61 | component) xb_cypress "run --component $*" ;; 62 | *) echo "Invalid argument: $1" >&2; exit 1 ;; 63 | esac 64 | -------------------------------------------------------------------------------- /commands/host/xb-fix: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ## #ddev-generated 4 | ## Description: Run all static analysis automatic fixer tools. 5 | ## Usage: xb-fix 6 | ## Example: ddev fix 7 | ## Aliases: fix 8 | ## Flags: [] 9 | ## ExecRaw: true 10 | 11 | echo Running PHPCBF... 12 | ddev phpcs fix 13 | 14 | echo 15 | echo Running ESLint fixer... 16 | ddev eslint fix 17 | 18 | echo 19 | echo Running Stylelint fixer... 20 | ddev stylelint fix 21 | -------------------------------------------------------------------------------- /commands/host/xb-setup: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ## #ddev-generated 4 | ## Description: Set up the Experience Builder development environment. 5 | ## Usage: xb-setup 6 | ## Example: ddev xb-setup\nddev xb-setup --force 7 | ## Flags: [{"Name":"force","Shorthand":"f","Usage":"Completely reset an existing environment if present and start over"}] 8 | ## ExecRaw: true 9 | 10 | cd "$(dirname "$0")" || exit 11 | cd ../../../ 12 | set -e 13 | 14 | # Flag-handling. 15 | while :; do 16 | case ${1:-} in 17 | -f | --force) 18 | FORCE=true ;; 19 | --) 20 | shift 21 | break ;; 22 | -?*) 23 | printf 'WARN: Unknown option (ignored): %s\n' "$1" >&2 ;; 24 | *) # Default case: No more options, so break out of the loop. 25 | break ;; 26 | esac 27 | shift 28 | done 29 | 30 | # Exit early if the environment is already set up. 31 | if [ -d web/modules/contrib/experience_builder/.git ] && [ ! "$FORCE" ]; then 32 | GREEN="\033[0;32m" 33 | NO_COLOR="\033[0m" 34 | printf "%bThe Experience Builder development environment is already set up.%b\n" "$GREEN" "$NO_COLOR" 35 | # shellcheck disable=SC2016 36 | echo 'Note: If the environment is broken, run `ddev xb-setup --force` to completely reset it and start over.' 37 | echo 'Warning: If you do this, you will lose any changes you have made to the Experience Builder module or your Drupal site. Back up anything you want to save.' 38 | echo Hint: ddev xb-setup --force 39 | exit 40 | fi 41 | 42 | # Remove the Experience Builder module if it's there. 43 | rm -rf web/modules/contrib/experience_builder 44 | mkdir -p web/modules/contrib 45 | 46 | # Place the Experience Builder module via Git for development. Require 47 | # it with Composer to test its composer.json and place dependencies. 48 | git clone \ 49 | git@git.drupal.org:project/experience_builder.git \ 50 | web/modules/contrib/experience_builder 51 | 52 | # Allow all Composer plugins. 53 | ddev composer config \ 54 | --no-plugins \ 55 | allow-plugins.\* \ 56 | true 57 | 58 | # Require Drush, but don't install yet for performance reasons. 59 | ddev composer require \ 60 | --no-install \ 61 | --update-with-all-dependencies \ 62 | --no-interaction \ 63 | drush/drush 64 | 65 | # Require the Experience Builder module. Still don't install. 66 | ddev composer config \ 67 | repositories.xb \ 68 | path \ 69 | web/modules/contrib/experience_builder 70 | ddev composer require \ 71 | --no-install \ 72 | --update-with-all-dependencies \ 73 | --no-interaction \ 74 | drupal/experience_builder 75 | 76 | # Require dev dependencies. NOW install. 77 | ddev composer require \ 78 | --dev \ 79 | --update-with-all-dependencies \ 80 | --no-interaction \ 81 | devizzent/cebe-php-openapi:^1.1.4 \ 82 | drupal/metatag:^2. \ 83 | jangregor/phpstan-prophecy:^2.2.0 \ 84 | league/openapi-psr7-validator:^0.22.0 \ 85 | webflo/drupal-finder:^1.3.1 86 | 87 | # Allow test modules and themes to be installed. 88 | # shellcheck disable=SC2016 89 | printf '\n# Allow test modules and themes to be installed.\n$settings["extension_discovery_scan_tests"] = TRUE;' \ 90 | >> web/sites/default/settings.ddev.php 91 | 92 | # Install Drupal and enable the Experience Builder module. 93 | ddev xb-site-install 94 | 95 | # Install Drupal core NPM packages. 96 | ddev exec --dir /var/www/html/web/core -- npm install 97 | 98 | # Build front-end assets. 99 | ddev xb-ui-build 100 | 101 | # Install DDEV Selenium Standalone Chrome 102 | ddev add-on get ddev/ddev-selenium-standalone-chrome 103 | -------------------------------------------------------------------------------- /commands/host/xb-static: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ## #ddev-generated 4 | ## Description: Run all static analysis tools. 5 | ## Usage: xb-static 6 | ## Example: ddev static 7 | ## Aliases: static 8 | ## Flags: [] 9 | ## ExecRaw: true 10 | 11 | echo Running PHPCS... 12 | ddev xb-phpcs 13 | 14 | echo 15 | echo Running ESLint... 16 | ddev xb-eslint 17 | 18 | echo 19 | echo Running Stylelint... 20 | ddev xb-stylelint 21 | 22 | echo 23 | echo Running PHPStan... 24 | ddev xb-phpstan 25 | -------------------------------------------------------------------------------- /commands/web/xb-autosave: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ## #ddev-generated 4 | ## Description: Enable, disable, or clear auto-save 5 | ## Usage: xb-autosave [on|off|enable|disable|true|false|toggle|status|clear] 6 | ## Example: ddev autosave # Enable auto-save.\nddev autosave on # Enable auto-save.\nddev autosave off # Disable auto-save.\nddev autosave toggle # Toggle auto-save status.\nddev autosave status # Get auto-save status.\nddev autosave clear # Clear all auto-saves. 7 | ## Aliases: autosave,as 8 | ## ExecRaw: false 9 | ## Flags: [] 10 | ## AutocompleteTerms: ["on","off","enable","disable","toggle","status","clear"] 11 | 12 | enable_autosave() { 13 | drush state:delete experience_builder.disable_auto-save 14 | } 15 | 16 | disable_autosave() { 17 | drush state:set experience_builder.disable_auto-save 1 18 | } 19 | 20 | get_autosave_status() { 21 | [[ "$(drush state:get experience_builder.disable_auto-save)" == "1" ]] && echo "0" || echo "1" 22 | } 23 | 24 | clear_autosave() { 25 | drush sql:query "delete from key_value_expire where collection='tempstore.shared.experience_builder.auto_save'" > /dev/null 26 | } 27 | 28 | # The default action is to enable auto-save. 29 | [[ $# -eq 0 ]] && enable_autosave && exit 30 | 31 | # Process command arguments. 32 | case "$1" in 33 | on|true|enable) enable_autosave ;; 34 | off|false|disable) disable_autosave ;; 35 | toggle) if [[ "$(get_autosave_status)" == "1" ]]; then disable_autosave; else enable_autosave; fi ;; 36 | status) if [[ "$(get_autosave_status)" == "1" ]]; then echo "autosave enabled"; else echo "autosave disabled"; fi ;; 37 | clear) clear_autosave ;; 38 | *) echo "Invalid argument: $1" >&2; exit 1 ;; 39 | esac 40 | -------------------------------------------------------------------------------- /commands/web/xb-core-set-version: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ## #ddev-generated 4 | ## Description: Change the version of Drupal core. 5 | ## Usage: xb-core-set-version 6 | ## Example: ddev core ^11 # Use the latest 11.x.\nddev core 11.0.7 # Use a specific version.\nddev core "^10 || ^11" # Use the latest 10.x or 11.x. 7 | ## Aliases: core 8 | ## Flags: [] 9 | ## ExecRaw: true 10 | 11 | cd "$DDEV_COMPOSER_ROOT" || exit 1 12 | 13 | if [ "$#" -ne 1 ]; then 14 | echo "Error: provide exactly one argument" 15 | echo "Usage: core " 16 | exit 1 17 | fi 18 | 19 | CORE_VERSION=$1 20 | 21 | composer require \ 22 | --dev \ 23 | --no-update \ 24 | "drupal/core-dev:$CORE_VERSION" 25 | composer require \ 26 | --no-update \ 27 | "drupal/core-recommended:$CORE_VERSION" \ 28 | "drupal/core-composer-scaffold:$CORE_VERSION" \ 29 | "drupal/core-project-message:$CORE_VERSION" 30 | composer update --with-all-dependencies 31 | -------------------------------------------------------------------------------- /commands/web/xb-dev-extras: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ## #ddev-generated 4 | ## Description: Add some convenience extras for development. 5 | ## Usage: xb-dev-extras 6 | ## Example: ddev xb-dev-extras\nddev xb-dev-extras --dry-run 7 | ## Aliases: extras 8 | ## Flags: [{"Name":"dry-run","Usage":"Show what the command will do if run"}] 9 | 10 | # If the '--dry-run' flag is passed, show what the command would do and then exit. 11 | if [[ "$1" == "--dry-run" ]]; then 12 | echo "This command will... 13 | 1. Install the following modules: 14 | - Admin Toolbar (admin_toolbar) 15 | - Admin Toolbar (admin_toolbar_tools) 16 | - Coffee (coffee) 17 | 2. Create a test page at '/test'." 18 | exit 0 19 | fi 20 | 21 | # Add the modules to the codebase. 22 | composer require \ 23 | --no-interaction \ 24 | drupal/admin_toolbar \ 25 | drupal/admin_toolbar_tools \ 26 | drupal/coffee 27 | 28 | # Install the modules in Drupal. 29 | drush en -y \ 30 | admin_toolbar \ 31 | admin_toolbar_tools \ 32 | coffee 33 | 34 | 35 | -------------------------------------------------------------------------------- /commands/web/xb-eslint: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ## #ddev-generated 4 | ## Description: Find problems in JavaScript code with ESLint. 5 | ## Usage: xb-eslint [fix] 6 | ## Example: ddev eslint # Check for errors.\nddev eslint fix # Fix errors where possible. 7 | ## Aliases: eslint,js 8 | ## ExecRaw: false 9 | ## Flags: [] 10 | ## AutocompleteTerms: ["fix"] 11 | 12 | cd "$DDEV_COMPOSER_ROOT/$DDEV_DOCROOT/modules/contrib/experience_builder/ui" || exit 1 13 | 14 | # @todo: Suppress "WARNING: You are currently running a version of TypeScript which is not officially supported by @typescript-eslint/typescript-estree." 15 | # @see https://www.drupal.org/project/experience_builder/issues/3485146 16 | 17 | case "$1" in 18 | "fix") npm run lint:fix ;; 19 | "") npm run lint:eslint ;; 20 | *) 21 | echo "Invalid argument: $1" 22 | exit 1 23 | ;; 24 | esac 25 | -------------------------------------------------------------------------------- /commands/web/xb-phpcs: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ## #ddev-generated 4 | ## Description: Check for standards compliance with PHPCS. 5 | ## Usage: xb-phpcs [fix] 6 | ## Example: ddev phpcs # Check for errors.\nddev phpcs fix # Fix errors where possible. 7 | ## Aliases: phpcs,cs 8 | ## ExecRaw: false 9 | ## Flags: [] 10 | ## AutocompleteTerms: ["fix"] 11 | 12 | cd "$DDEV_COMPOSER_ROOT/$DDEV_DOCROOT" || exit 1 13 | 14 | COMMAND="phpcs" 15 | if [[ $1 == "fix" ]]; then 16 | COMMAND="phpcbf" 17 | elif [[ -n $1 ]]; then 18 | echo "Invalid argument: $1" 19 | exit 1 20 | fi 21 | 22 | "../vendor/bin/$COMMAND" \ 23 | -s \ 24 | --standard=modules/contrib/experience_builder/phpcs.xml \ 25 | --basepath=modules/contrib/experience_builder \ 26 | modules/contrib/experience_builder 27 | -------------------------------------------------------------------------------- /commands/web/xb-phpstan: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ## #ddev-generated 4 | ## Description: Analyze code to find bugs with PHPStan. 5 | ## Example: ddev xb-phpstan 6 | ## Aliases: phpstan,stan 7 | 8 | cd "$DDEV_COMPOSER_ROOT/$DDEV_DOCROOT" || exit 1 9 | 10 | ../vendor/bin/phpstan \ 11 | analyze \ 12 | --configuration=modules/contrib/experience_builder/phpstan.neon \ 13 | --memory-limit=256M \ 14 | modules/contrib/experience_builder 15 | -------------------------------------------------------------------------------- /commands/web/xb-phpunit: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ## #ddev-generated 4 | ## Description: Run PHPUnit tests. 5 | ## Example: ddev xb-phpunit Run all tests.\nddev xb-phpunit tests/src/Unit/Example Specify a path to a specific test file or directory relative to the module root. 6 | ## Aliases: phpunit,test 7 | 8 | cd "$DDEV_COMPOSER_ROOT/$DDEV_DOCROOT" || exit 1 9 | 10 | ../vendor/bin/phpunit \ 11 | -c core/phpunit.xml.dist \ 12 | modules/contrib/experience_builder/"$*" 13 | -------------------------------------------------------------------------------- /commands/web/xb-site-install: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ## #ddev-generated 4 | ## Description: (Re)install Drupal and the Experience Builder module. 5 | ## Example: ddev xb-site-install 6 | ## Aliases: site-install,si 7 | 8 | # Install Drupal. 9 | drush site:install -y \ 10 | --account-name=admin \ 11 | --account-pass=admin \ 12 | --site-name="XB Local Dev" 13 | 14 | # Enable the Experience Builder module. 15 | drush pm:install -y \ 16 | experience_builder \ 17 | xb_dev_standard \ 18 | sdc_test_all_props 19 | 20 | # Without a cache rebuild, Drupal can't find test modules, leading to a WSOD. 21 | drush cache:rebuild 22 | 23 | # Create a default article. 24 | drush php:eval "(\Drupal\node\Entity\Node::create(['type' => 'article', 'title' => 'Test', 'uid' => 1]))->save();" 25 | 26 | # Create a test page. Note: If any more PHP code is added here, it should be 27 | # extracted to its own file. Writing it this way is clumsy, to say the least. 28 | drush php:eval " 29 | \$alias = '/test'; 30 | \$path_alias_repository = \Drupal::service('path_alias.repository'); 31 | 32 | // See if the test page already exists and exit if so. (Just checking for 33 | // the path alias is naive, but it will suffice for our purposes. 34 | if (\$path_alias_repository->lookupByAlias(\$alias, 'en')) { 35 | echo 'The test page already exists.' . PHP_EOL; 36 | return; 37 | } 38 | 39 | // Create the xb_page entity. 40 | \Drupal::service('entity_type.manager') 41 | ->getStorage('xb_page') 42 | ->create([ 43 | 'title' => 'XB 💫', 44 | 'description' => 'This is an XB page.', 45 | 'path' => ['alias' => \$alias], 46 | ])->save(); 47 | 48 | echo 'The test page has been created.' . PHP_EOL; 49 | " 50 | 51 | # Display a one time login link for user ID 1. 52 | drush uli 53 | -------------------------------------------------------------------------------- /commands/web/xb-stylelint: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ## #ddev-generated 4 | ## Description: Find errors and enforce conventions with Stylelint. 5 | ## Usage: xb-stylelint [fix] 6 | ## Example: ddev stylelint # Find errors.\nddev stylelint fix # Fix errors where possible. 7 | ## Aliases: stylelint,css 8 | ## ExecRaw: false 9 | ## Flags: [] 10 | ## AutocompleteTerms: ["fix"] 11 | 12 | UI_DIR="$DDEV_COMPOSER_ROOT/$DDEV_DOCROOT/modules/contrib/experience_builder/ui" 13 | cd "$UI_DIR" || exit 1 14 | 15 | FIX_OPTION="" 16 | if [[ $1 == "fix" ]]; then 17 | FIX_OPTION="--fix" 18 | elif [[ -n $1 ]]; then 19 | echo "Invalid argument: $1" 20 | exit 1 21 | fi 22 | 23 | npx stylelint \ 24 | --config "$DDEV_COMPOSER_ROOT/$DDEV_DOCROOT/core/.stylelintrc.json" \ 25 | --ignore-pattern "dist/**/*" \ 26 | "$UI_DIR/**/*.css" \ 27 | $FIX_OPTION 28 | -------------------------------------------------------------------------------- /commands/web/xb-ui-build: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ## #ddev-generated 4 | ## Description: Clean-install and build Experience Builder's UI app assets. 5 | ## Example: ddev xb-ui-build 6 | ## Aliases: ui-build,build 7 | 8 | cd "$DDEV_COMPOSER_ROOT/$DDEV_DOCROOT/modules/contrib/experience_builder/ui" || exit 1 9 | 10 | drush pm:uninstall xb_vite -y > /dev/null 2>&1 || : 11 | npm ci 12 | npm run build 13 | -------------------------------------------------------------------------------- /commands/web/xb-ui-dev: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ## #ddev-generated 4 | ## Description: Install dependencies and run Experience Builder's UI app development server. 5 | ## Example: ddev xb-ui-dev 6 | ## Aliases: ui-dev,dev 7 | 8 | cd "$DDEV_COMPOSER_ROOT/$DDEV_DOCROOT/modules/contrib/experience_builder/ui" || exit 1 9 | 10 | drush pm:install xb_vite -y > /dev/null 2>&1 || : 11 | npm install 12 | npm run drupaldev -- --host 13 | -------------------------------------------------------------------------------- /commands/web/xb-workspaces-dev: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ## #ddev-generated 4 | ## Description: Configure the environment for Workspaces development. 5 | ## Usage: xb-workspaces-dev 6 | ## Example: ddev xb-workspaces-dev\nddev xb-workspaces-dev --dry-run 7 | ## Aliases: workspaces,wse 8 | ## Flags: [{"Name":"dry-run","Usage":"Show what the command will do if run"}] 9 | 10 | # If the '--dry-run' flag is passed, show what the command would do and then exit. 11 | if [[ "$1" == "--dry-run" ]]; then 12 | echo "This command will... 13 | 1. Install the following modules: 14 | - Workspaces (workspaces) 15 | - Workspaces UI (workspaces_ui) (as of Drupal 11) 16 | - Workspaces Extras (wse) 17 | - Workspaces Config (wse_config) 18 | 2. Perform the following configuration: 19 | - Use the simplified workspace switcher in the toolbar 20 | - Disable sub workspaces" 21 | exit 0 22 | fi 23 | 24 | # Add the modules to the codebase. Use dev branches to always get 25 | # the latest commits and to facilitate upstream contribution. 26 | composer require \ 27 | --prefer-source \ 28 | --no-interaction \ 29 | drupal/wse:dev-2.0.x \ 30 | drupal/wse_config:dev-2.0.x 31 | 32 | # Install the modules in Drupal. 33 | modules=( 34 | workspaces 35 | wse 36 | wse_config 37 | ) 38 | # Workspaces UI is a separate module as of Drupal 11. Install it if it's available. 39 | WORKSPACES_UI="workspaces_ui" 40 | if drush pm:list --type=Module --status=disabled | grep -q "^$WORKSPACES_UI$"; then 41 | modules+=("$WORKSPACES_UI") 42 | fi 43 | drush pm:install -y "${modules[@]}" 44 | 45 | # Use the simplified workspace switcher in the toolbar. 46 | drush config:set -y \ 47 | wse.settings \ 48 | simplified_toolbar_switcher \ 49 | true 50 | 51 | # Disable sub workspaces. 52 | drush config:set -y \ 53 | wse.settings \ 54 | disable_sub_workspaces \ 55 | true 56 | -------------------------------------------------------------------------------- /config.drupal-xb-dev.yaml: -------------------------------------------------------------------------------- 1 | #ddev-generated 2 | web_environment: 3 | - BASE_URL=http://web 4 | - CYPRESS_CACHE_FOLDER=/var/www/html/.cache/cypress 5 | - DB_URL=sqlite://web/sites/default/files/db.sqlite 6 | - DISPLAY=host.docker.internal:0 7 | - DRUPAL_TEST_DB_URL=sqlite://web/sites/default/files/db.sqlite 8 | - VITE_SERVER_ORIGIN=https://${DDEV_HOSTNAME}:5174 9 | webimage_extra_packages: 10 | - libasound2 11 | - libgbm-dev 12 | - libgtk-3-0 13 | - libgtk2.0-0 14 | - libnotify-dev 15 | - libnss3 16 | - libxss1 17 | - libxtst6 18 | - xauth 19 | - xvfb 20 | web_extra_exposed_ports: 21 | - name: vite-dev-server 22 | container_port: 5173 23 | http_port: 5173 24 | https_port: 5174 25 | -------------------------------------------------------------------------------- /install.yaml: -------------------------------------------------------------------------------- 1 | # Details about the install.yaml file are at 2 | # https://ddev.readthedocs.io/en/latest/users/extend/additional-services/#sections-and-features-of-ddev-get-add-on-installyaml. 3 | # See also https://github.com/ddev/ddev-addon-template/blob/main/install.yaml. 4 | 5 | name: drupal-xb-dev 6 | 7 | project_files: 8 | - commands/host/xb-cypress 9 | - commands/host/xb-fix 10 | - commands/host/xb-setup 11 | - commands/host/xb-static 12 | - commands/web/xb-autosave 13 | - commands/web/xb-core-set-version 14 | - commands/web/xb-dev-extras 15 | - commands/web/xb-eslint 16 | - commands/web/xb-phpcs 17 | - commands/web/xb-phpstan 18 | - commands/web/xb-phpunit 19 | - commands/web/xb-site-install 20 | - commands/web/xb-stylelint 21 | - commands/web/xb-ui-build 22 | - commands/web/xb-ui-dev 23 | - commands/web/xb-workspaces-dev 24 | - config.drupal-xb-dev.yaml 25 | 26 | post_install_actions: 27 | - | 28 | echo "Deleting commands removed in v0.0.16 (unless they've been modified)..." 29 | FILES=( 30 | "commands/host/.xb-command-include" 31 | "commands/host/xb-cypress-component" 32 | "commands/host/xb-cypress-open" 33 | "commands/host/xb-cypress-run" 34 | "commands/web/xb-drush-si" 35 | "commands/web/xb-phpcbf" 36 | "commands/web/xb-stylelint-fix" 37 | ) 38 | for FILE in "${FILES[@]}"; do 39 | if [[ ! -f "$FILE" ]]; then 40 | continue 41 | fi 42 | # Skip the file if it has been modified. 43 | if ! grep -q '## #ddev-generated' "$FILE"; then 44 | echo "- Skipping $FILE - It has been modified" 45 | continue 46 | fi 47 | # Otherwise delete it. 48 | echo "- Deleting $FILE" 49 | rm -f "$FILE" 50 | done 51 | 52 | - | 53 | echo "‼️ If you're setting up this add-on for the first time on this project, finish installation by running 'ddev xb-setup'." 54 | echo "💡 To set up optional extras for development, run 'ddev xb-dev-extras'. Run 'ddev xb-dev-extras --help' to see what it will do first." 55 | -------------------------------------------------------------------------------- /resources/xquartz-settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drupal-xb/ddev-drupal-xb-dev/9747bf88eef3b5b4a0b34f71095b1a33338c310f/resources/xquartz-settings.png -------------------------------------------------------------------------------- /tests/test.bats: -------------------------------------------------------------------------------- 1 | setup() { 2 | set -eu -o pipefail 3 | DIR="$( cd "$( dirname "$BATS_TEST_FILENAME" )" >/dev/null 2>&1 && pwd )/.." 4 | export DIR 5 | export TESTDIR=~/tmp/drupal-xb-dev 6 | mkdir -p $TESTDIR 7 | export PROJNAME=drupal-xb-dev 8 | export DDEV_NONINTERACTIVE=true 9 | ddev delete -Oy ${PROJNAME} >/dev/null 2>&1 || true 10 | cd "${TESTDIR}" 11 | ddev config --project-name=${PROJNAME} 12 | ddev start -y >/dev/null 13 | } 14 | 15 | check_commands_installed() { 16 | # Get the available commands. 17 | ddev_help_output=$(ddev help) 18 | # Find command files in the add-on. 19 | cd "${TESTDIR}" 20 | tmp_file=$(mktemp) 21 | find "$GITHUB_WORKSPACE/commands" -name 'xb-*' -exec basename {} \; > "$tmp_file" 22 | # Check that all the command files got copied to the project upon installation. 23 | errors="" 24 | while read -r command_name; do 25 | # Skip xb-cypress since it's expected not to be installed on CI. 26 | if [ "$command_name" = "xb-cypress" ]; then 27 | continue 28 | fi 29 | if ! echo "$ddev_help_output" | grep -q "$command_name"; then 30 | errors="${errors}Error: ${command_name} is not installed.\n" 31 | fi 32 | done < "$tmp_file" 33 | rm -f "$tmp_file" 34 | # Display errors and fail, if any. 35 | if [ -n "$errors" ]; then 36 | printf "%b" "$errors" 37 | return 1 38 | fi 39 | echo "All commands were installed." 40 | } 41 | 42 | health_checks() { 43 | check_commands_installed 44 | ddev exec "curl -s https://localhost:443/" 45 | } 46 | 47 | teardown() { 48 | set -eu -o pipefail 49 | cd "${TESTDIR}" || ( printf "unable to cd to %s\n" "${TESTDIR}" && exit 1 ) 50 | ddev delete -Oy "${PROJNAME}" >/dev/null 2>&1 51 | [ "${TESTDIR}" != "" ] && rm -rf "${TESTDIR}" 52 | } 53 | 54 | @test "install from directory" { 55 | set -eu -o pipefail 56 | cd "${TESTDIR}" 57 | echo "# ddev add-on get ${DIR} with project ${PROJNAME} in ${TESTDIR} ($(pwd))" >&3 58 | ddev add-on get "${DIR}" 59 | ddev restart 60 | health_checks 61 | } 62 | 63 | # bats test_tags=release 64 | @test "install from release" { 65 | set -eu -o pipefail 66 | cd "${TESTDIR}" || ( printf "unable to cd to %s\n" "${TESTDIR}" && exit 1 ) 67 | echo "# ddev add-on get drupal-xb/ddev-drupal-xb-dev with project ${PROJNAME} in ${TESTDIR} ($(pwd))" >&3 68 | ddev add-on get drupal-xb/ddev-drupal-xb-dev 69 | ddev restart >/dev/null 70 | health_checks 71 | } 72 | -------------------------------------------------------------------------------- /tests/test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # This file is for self-testing this add-on during local development. 4 | # 5 | # First, install XQuartz (and ONLY XQuartz) according to the instructions at 6 | # https://github.com/drupal-xb/ddev-drupal-xb-dev#prerequisites-xquartz 7 | # (Stop after configuring XQuartz--do not continue with the steps in the README. 8 | # 9 | # Then run the following commands on your host machine to clone the 10 | # repository fresh and run the script: 11 | # 12 | # cd ~/Projects/temp # This can be anywhere you want. 13 | # git clone git@github.com:drupal-xb/ddev-drupal-xb-dev.git 14 | # cd ddev-drupal-xb-dev 15 | # ./tests/test.sh 16 | 17 | PROJECT_NAME="ddev-drupal-xb-dev" 18 | PROJECT_DIR="test-site" 19 | DRUPAL_VERSION="10.x@dev" 20 | 21 | cd "$(dirname "$0")/../var" && clear || exit 1 22 | clear; set -ev 23 | 24 | # Clean up from previous runs. 25 | PROJECT_EXISTS=$(ddev list | grep -q "$PROJECT_NAME.ddev.site") || true 26 | if [ -d $PROJECT_DIR ] || [ -n "$PROJECT_EXISTS" ]; then 27 | yes | ddev clean $PROJECT_NAME || true 28 | ddev remove --unlist $PROJECT_NAME || true 29 | rm -rf $PROJECT_DIR || true 30 | fi 31 | 32 | mkdir $PROJECT_DIR || true 33 | cd $PROJECT_DIR || exit 1 34 | 35 | # Create a new project. 36 | ddev config \ 37 | --project-name=$PROJECT_NAME \ 38 | --project-type=drupal \ 39 | --php-version=8.3 \ 40 | --docroot=web 41 | 42 | # Configure the new DDEV project. 43 | ddev config --project-type=drupal --php-version=8.3 --docroot=web 44 | 45 | # Create the Drupal project. 46 | ddev composer create drupal/recommended-project:$DRUPAL_VERSION --no-install 47 | 48 | # Get the add-on. 49 | ddev add-on get ../../ 50 | 51 | # Perform one-time setup operations. 52 | ddev xb-setup 53 | 54 | # Test an update. 55 | ddev add-on get ../../ 56 | 57 | # Try to perform one-time setup operations when they've already been done. 58 | ddev xb-setup 59 | 60 | # Make sure all the commands get installed. 61 | DDEV_HELP_OUTPUT=$(ddev help) 62 | find "commands" -name 'xb-*' -exec basename {} \; | while read -r COMMAND_NAME; do 63 | if ! echo "$DDEV_HELP_OUTPUT" | grep -q "$COMMAND_NAME"; then 64 | echo "Error: $COMMAND_NAME is not installed." 65 | exit 1 66 | fi 67 | done 68 | echo "All commands are installed." 69 | 70 | # Install dev extras. 71 | ddev xb-dev-extras 72 | 73 | # Configure environment for Workspaces development. 74 | ddev xb-workspaces-dev 75 | -------------------------------------------------------------------------------- /var/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drupal-xb/ddev-drupal-xb-dev/9747bf88eef3b5b4a0b34f71095b1a33338c310f/var/.gitkeep --------------------------------------------------------------------------------