Skip to content
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
1479a5c
In some rare occasions calling yq from ddev alias does something to p…
zHelmet Feb 25, 2026
24ed28c
fix(GH-46): strip db-post-import hook to sanitization only
tormi Mar 5, 2026
ce33731
perf(GH-46): optimize syncdb with gzip, single yq call, new flags
tormi Mar 5, 2026
db865fd
chore(GH-46): update syncdb host command metadata
tormi Mar 5, 2026
7e09dca
docs(GH-46): update README for syncdb and hook changes
tormi Mar 5, 2026
30e3571
Merge #47
zHelmet Mar 5, 2026
fa08d07
Merge #43
zHelmet Mar 5, 2026
91f5081
Add --skip-hooks support and clean up syncdb script
zHelmet Mar 5, 2026
7ad3149
Merge branch GH-46 into bugfix/GH-46-syncdb
zHelmet Mar 9, 2026
47fd5a4
feat(GH-46): add --deploy flag to run drush deploy after syncdb
tormi Mar 10, 2026
edb2afd
refactor(GH-46): remove --force flag, replace confirmation with warning
tormi Mar 10, 2026
1748924
Merge branch GH-46 into bugfix/GH-46-syncdb
zHelmet Mar 17, 2026
90c2eb8
Restore syncdb
zHelmet Mar 17, 2026
84d3a6d
Make sure that sanitization is always ran
zHelmet Mar 24, 2026
45cfe3a
Prefix drush command
zHelmet Mar 24, 2026
d86be36
Remove private repo mention
zHelmet Apr 23, 2026
39f0e36
Merge pull request #50 from wunderio/bugfix/GH-46-syncdb
zHelmet May 18, 2026
ebb11a7
Update script accordingly agreed on the dev channels
zHelmet May 18, 2026
994821f
Fix copy paste fails
zHelmet May 18, 2026
39524b3
Permissions of the tmp file creation
zHelmet May 18, 2026
472a21f
GH-46: Clarify Drupal version in ddev config example
hkirsman May 21, 2026
80e107a
GH-46: Remove --skip-hooks reference from readme.
hkirsman May 21, 2026
bf3a86e
GH-46: Add --no-deploy example to readme.
hkirsman May 21, 2026
f3d7946
GH-46: More readme updates.
hkirsman May 21, 2026
508b424
GH-46: Export DDEV_APPROOT in wdr-core fallback path.
hkirsman May 21, 2026
77034be
GH-46: Use fixed-string grep for syncdb alias validation.
hkirsman May 21, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 60 additions & 53 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ scripts to enhance your Drupal development workflow.

### Steps

1. Initialize your Drupal 10 project. Project name parameter is optional, but
1. Initialize your Drupal project. Project name parameter is optional, but
it's advisable to use domain name as your project name as that's used for
the subdomain of ddev.site eg if project name is example.com, then localhost
URL will become example.com.ddev.site.

```bash
ddev config --project-type=drupal10 --docroot=web --project-name=example.com
ddev config --project-type=drupal --docroot=web --project-name=example.com
Comment thread
hkirsman marked this conversation as resolved.
Outdated
```

2. Install Wunderio DDEV Drupal as a DDEV add-on and restart DDEV:
Expand Down Expand Up @@ -59,66 +59,100 @@ URL will become example.com.ddev.site.

## Features

For a quick reference in your project's README, add:

```markdown
This project uses [ddev-wunderio-drupal](https://github.com/wunderio/ddev-wunderio-drupal) DDEV add-on. Run `ddev -h` to see all available commands.
```

### Custom DDEV Commands

- `pmu`: Runs drush pmu commands and creates dummy module folders if they don't exist.
This helps to uninstall module that has gone missing for example during branch
switching.

```bash
ddev pmu module1 module2 ...
```

- `twig-debug`: Toggles Drupal Twig debugging on/off. Useful for template development.

```bash
ddev twig-debug # Enable Twig debugging
ddev twig-debug off # Disable Twig debugging
```
- `grumphp`: Runs GrumPHP commands

- `grumphp`: Runs GrumPHP commands.

```bash
ddev grumphp
```
- `phpunit`: Runs PHPUnit commands

- `phpunit`: Runs PHPUnit commands.

```bash
ddev phpunit
```

- `regenerate-phpunit-config`: Regenerates fresh PHPUnit configuration. Run this if you don't have phpunit configured in your project.

```bash
ddev regenerate-phpunit-config
```

- `codecept`: Runs codeception commands.

```bash
ddev codecept
```
- `phpcbf`: Runs phpcbf commands

- `phpcbf`: Runs PHPCBF commands.

```bash
ddev phpcbf
```
- `phpcs`: Runs PHPcs commands

- `phpcs`: Runs PHPCS commands.

```bash
ddev phpcs
```

- `phpstan`: Runs PHPStan commands. Usually, the directory to be scanned is web/modules/custom or a module in the said directory.

```bash
ddev phpstan analyze <directory-or-module-to-be-scanned>
```
- `syncdb`: Synchronizes local database from desired environment.
You should have aliases set in drush/sites/self.site.yml

- `syncdb`: Synchronizes local database from a remote environment.
Requires aliases in `drush/sites/self.site.yml`.

```bash
ddev syncdb # Will give error as environment is not set
ddev syncdb prod # Will fetch database from production.
ddev syncdb <alias> # e.g. ddev syncdb prod
ddev syncdb prod --backup # Back up local DB before overwriting
ddev syncdb prod --deploy # Run drush deploy and drush uli after import
ddev syncdb prod --keep-dump # Keep the downloaded dump file
ddev syncdb prod --backup --deploy # Combine flags
```
- `yq`: Runs [yq](https://mikefarah.gitbook.io/yq) commands (YAML processor)

- `yq`: Runs [yq](https://mikefarah.gitbook.io/yq) commands (YAML processor).
It's available inside DDEV, but we expose it to host because why not :). It's required in syncdb script, but it could prove useful in day to day work.

```bash
ddev yq
```

- `commit`: Generates AI-powered commit messages from staged changes using the configured API.
The command analyzes your staged changes and branch name to generate commit messages following
the project's commit message format (ticket/issue ID prefix, present tense, imperative mood).
Requires `OPENAI_API_URL` and `OPENAI_API_KEY` environment variables to be configured via DDEV global config.

```bash
ddev commit
```

**Setup:** Configure the API credentials in DDEV global config (applies to all projects) and restart your DDEV project:

```bash
ddev config global --web-environment-add="OPENAI_API_URL=https://your-api-url"
ddev config global --web-environment-add="OPENAI_API_KEY=your-api-key"
Expand All @@ -130,25 +164,25 @@ URL will become example.com.ddev.site.
### Enhanced Configuration

1. **Custom DDEV Configuration**
- Post-start scripts for both host and web containers - by default it gives you uli link.
- Automatic update checks for this package
- Post-start scripts for both host and web containers by default it gives you a uli link.
- Automatic update checks for this package.

2. **Performance Optimizations**
- Special `database_dumps/` directory for Mac users not to mount db dumps
- Special `database_dumps/` directory for Mac users not to mount db dumps.

### Automated Workflows

The project includes several automated workflows:

1. **Database Management**
- Post-import database hooks (clears cache, sanitizes database)
- Post-restore snapshot hooks (clears cache, sanitizes database)
- Database synchronization from production
- Post-import and post-restore-snapshot hooks (sanitize database).
- Database synchronization from remote environments via `ddev syncdb`.
- Run `ddev drush deploy` after import to apply updates, import config, and rebuild caches.

2. **Development Environment Setup**
- Automatic composer installation on first start
- Post-start hook that run drush uli
- Integration with Wunderio's development tools eg grumphp, phpunit
- Automatic Composer installation on first start.
- Post-start hook that runs `drush uli`.
- Integration with Wunderio's development tools, e.g. GrumPHP, PHPUnit.

Both custom commands and hooks are scripts under `~/.ddev/wunderio/core/` folder
(note it's your host home folder) and you can extend them if you copy particular
Expand Down Expand Up @@ -184,48 +218,21 @@ Previously, this package was installed as a Composer plugin and deployed files i

## Performance Optimization

### Database Operations for Mac Users
### Database Dumps Directory (macOS)

**Important for Mac users:** When working with database imports and exports on macOS, you should store your database
dump files in the `database_dumps` directory at the project root. This directory is specially configured in this
template to provide specific performance benefits.
Store database dump files in the `database_dumps/` directory at the project root. On macOS this directory is excluded from Mutagen sync, avoiding slow DDEV startups and disk bloat.

```
project-root/
├── database_dumps/ <- Place your .sql or .sql.gz files here
├── web/
├── .ddev/
└── ...
```

**Key benefits:**

1. **Faster DDEV startup times:** When large database files are stored in the standard project directories,
they can significantly slow down DDEV startup as Mutagen indexes and syncs these files. Using the `database_dumps`
directory avoids this overhead.

2. **Reduced virtual disk usage:** By excluding database dumps from Mutagen synchronization, your virtual disk
requires less space, preventing potential disk space issues.

This optimization is configured via `upload_dirs` in `.ddev/config.wunderio.yaml`:
Configured via `upload_dirs` in `.ddev/config.wunderio.yaml`:

```yaml
upload_dirs:
- ../database_dumps
```

**Example usage:**
```bash
# Save your database dumps to the database_dumps directory
cp ~/Downloads/my-database-backup.sql.gz ./database_dumps/
`ddev syncdb` uses this directory automatically. For manual imports:

# Then import using the path relative to your project
```bash
ddev import-db --file=database_dumps/my-database-backup.sql.gz
```

This improvement is particularly noticeable in projects with multiple or large database dumps, where
startup times can be reduced from minutes to seconds.

**Note for Linux users:** While this configuration doesn't provide performance improvements on Linux
systems (which don't use Mutagen), it's still good practice to store database dumps in the
dedicated `database_dumps` folder for consistent organization across team environments.
**Note:** On Linux (no Mutagen) this has no performance effect, but keeps dumps organized consistently across teams.
4 changes: 2 additions & 2 deletions commands/host/wunderio-core-syncdb.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

#ddev-generated

## Description: Synchronise local database with production.
## Description: Synchronise local database with a remote environment.
## Usage: syncdb
## Example: "ddev syncdb"
## Example: "ddev syncdb prod" "ddev syncdb prod --backup --deploy"
## ExecRaw: true
## ProjectTypes: drupal9,drupal10,drupal11

Expand Down
21 changes: 12 additions & 9 deletions wunderio/core/hooks/db-post-import.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,16 @@
#
# Helper script to run post-import db hook.
#
# Only sanitizes the database after import. Full deployment steps
# (updatedb, config:import, cache:rebuild, deploy:hook) should be
# run deliberately via `ddev drush deploy`.
#
# Rationale: running cache:rebuild before config:import is dangerous
# when the imported DB has schema differences from the current codebase
# (see https://github.com/wunderio/charts/pull/514). Keeping this hook
# minimal also keeps `ddev import-db` fast for all use cases (restoring
# local backups, debugging specific DB states, etc.).
#

set -eu
if [[ -n "${WUNDERIO_DEBUG:-}" ]]; then
Expand All @@ -19,14 +29,7 @@ if [[ -n "${WUNDERIO_DEBUG:-}" ]]; then
exit 0
fi

# Every import is treated as deployment
# Unified based on https://www.drush.org/12.x/deploycommand/.
drush updatedb --no-cache-clear -y || { display_error_message "Database update failed"; exit 1; }
# Sanitize imported database (remove sensitive data).
drush sqlsan -y || { display_error_message "Database sanitization failed"; exit 1; }
drush cache:rebuild || { display_error_message "Cache rebuild failed"; exit 1; }
drush config:import -y || { display_error_message "Config import failed"; exit 1; }
drush cache:rebuild || { display_error_message "Final cache rebuild failed"; exit 1; }
drush deploy:hook || { display_error_message "Deploy hook failed"; exit 1; }

uli_link=$(drush uli)
display_status_message "Drupal is working, running drush uli: $uli_link"
display_status_message "Database imported and sanitized."
Loading