Wunder's template for Drupal projects designed to work automatically with DDEV, Cursor, CircleCI and Helm.
Wunder template for Drupal projects
This project is a tailored fork of the popular drupal-composer template. It is designed for deploying to Kubernetes clusters via CircleCI.
Getting started
- Create a new project repository
client-COUNTRYCODE-CLIENT-PROJECT.
- Set the repository to private (unless the project is public).
- Clone and customize the repository
README.md with the project details
- Update composer.json with the project name
- In real client projects, remove /composer.lock from .gitignore so the lockfile is committed and reproducible
- Modify the silta/silta* files values
- Adjust grumphp.yml tasks, including updating the project name in the gitcommitmessage regex
- Configure local development environment:
- For DDEV: Update project settings in .ddev/config.yaml
- For database synchronization, see ddev-wunderio-drupal
- Adjust web/sites/default/settings.php settings (stagefileproxy etc)
- Adjust config_split settings for silta (default), production, main, local environments
- Set up CircleCI
- Configure encryption keys and secrets
siltadev and siltafinland contexts in the CircleCI project settings and backup the keys in LastPass. Use the following naming convention: SEC{PROJECTNAME}{CONTEXT} where CONTEXT is the environment, such as siltadev or silta_finland.
- Update the .circleci/config.yml file with the corresponding secretkeyenv values.
- Define the secret environment variables in the silta/silta*.secrets YAML files for the siltadev and siltafinland contexts.
- Encrypt the silta/silta*.secrets files using the encryption keys and commit the encrypted files to the repository.
- See the relevant Silta's documentation for details.
- Enable JIRA integration
For additional instructions, please refer to the Silta documentation.
Production environment
- URL:
- Drush alias:
drush @production st - SSH:
ssh www-admin@production-shell.drupal-project -J www-admin@ssh.finland.wdr.io
Environment variables for silta_finland context
The following secret variables are defined in the silta/silta-prod.secrets file for the silta_finland context:
TESTKEYPROD- Secret key for testing purposes.
Main environment
- URL:
- Drush alias:
drush @main st - SSH:
ssh www-admin@main-shell.drupal-project -J www-admin@ssh.dev.wdr.io
drush @current st.
Environment variables for silta_dev context
The following secret variables are defined in the silta/silta.secrets file for the silta_dev context:
TEST_KEY- Secret key for testing purposes.
Local development
This project uses DDEV for local development.
DDEV environment
DDEV provides a containerized development environment with all necessary services preconfigured.
DDEV setup instructions
- Install DDEV
- Ensure Docker is running on your system
- Start the environment and set up your project:
# Start the DDEV environment
ddev start
# Authenticate SSH for database syncing ddev auth ssh
# Synchronize local database with a remote environment # Synchronization is provided by ddev-wunderio-drupal # drush deploy and drush uli are part of ddev syncdb command. ddev syncdb
Note: All commands in the DDEV section should be run within the DDEV environment using ddev prefix (e.g., ddev drush uli), or by using ddev ssh to access the container shell first.
DDEV services and access points
The project can be accessed at
For a complete list of all available services, URLs, and ports, use:
ddev describe
DDEV common commands
ddev- Display available commandsddev adminer- Launch Adminer database management interfaceddev copilot [args]- Run GitHub Copilot CLI inside the agents containerddev grumphp <commands>- Run code quality checks (command provided by ddev-wunderio-drupal)ddev mailpit- Open Mailpit email testing interfaceddev npm <commands>- Execute npm commandsddev phpunit <commands>- Run test suites (command provided by ddev-wunderio-drupal)ddev varnishadm <commands>- Manage Varnish cacheddev xdebug <mode>- Configure Xdebug debugging modesddev syncdb [environment]- Sync database from remote environment (requires VPN andddev auth ssh(command provided by ddev-wunderio-drupal)
DDEV Elasticsearch configuration
DDEV Elasticsearch configuration
This project includes Elasticsearch service for robust full-text search capabilities. It's automatically set up during DDEV initialization.
Plugins configuration
- Pre-configured with
analysis-icufor Unicode/multilingual text processing - Additional plugins can be defined in
.ddev/docker-compose.elasticsearch8.yaml
services:
elasticsearch:
environment:
- ELASTICSEARCH_PLUGINS=analysis-icu # Space-separated plugin list
Useful commands
# Check Elasticsearch status
ddev exec -s elasticsearch "curl -s localhost:9200"
List installed plugins
ddev exec -s elasticsearch "bin/elasticsearch-plugin list"
Web interface
Elasticvue is included for visualization and management at
DDEV WunderIO Drupal
DDEV WunderIO Drupal addon
The Drupal template includes the Wunder-specific ddev-wunderio-drupal addon. This addon provides additional functionality and tools specifically designed for Drupal development, including custom commands, configurations, and automation scripts to enhance your workflow.
For more information about the addon, configuration options, and available custom commands, see:
Automated installation
This addon is installed automatically when you run ddev start.
The automation is configured in .ddev/config.wunderio.yaml using a pre-start host hook:
hooks:
pre-start:
- exec-host: 'if [ ! -f "${DDEVGLOBALDIR}/wunderio/core/wdr-core.sh" ]; then ddev add-on get wunderio/ddev-wunderio-drupal; fi'
This means developers only need to clone the project and run ddev start; no manual addon installation step is required.
Common commands provided by the addon include:
ddev grumphpddev phpunitddev syncdb
Development tips
Code quality tools
Code quality tools
This project includes several tools to maintain code quality and consistency across the codebase.
Markdown Linting
Markdown files can be checked and automatically fixed using the following npm scripts:
# Check markdown files for linting issues
ddev npm run lint:md
Automatically fix markdown linting issues where possible
ddev npm run lint:md:fix
Markdown linting rules are configured in .markdownlint.json at the project root.
JavaScript and CSS Linting
The project also includes linting for JavaScript and CSS files:
# Check JavaScript files
ddev npm run lint:js
Check CSS/SCSS files
ddev npm run lint:css
Run all linting (JS, CSS, and Markdown)
ddev npm run lint
AI Workflow (ddev-agents + Copilot)
AI Workflow (ddev-agents + Copilot)
This project includes the ddev-agents addon for AI-assisted development in the local DDEV environment. It provides MCP tools and a dedicated agents container for running project-aware commands safely.
Quick start
- Start the project:
ddev start
- Open the project in the devcontainer.
- Open VS Code Copilot chat and start the local MCP server (
wdrmcp) from MCP server controls.
- Use project tools through Copilot chat, or run Copilot CLI directly:
ddev copilot
Project AI configuration
- Tool definitions:
.agents/tools-config/ - Addon metadata:
.ddev/addon-metadata/ddev-agents/manifest.yaml - Agents runtime config:
.ddev/config.agents.yaml - Copilot managed restrictions:
.ddev/copilot-managed-config.json
Security model
- Commands run via SSH with ephemeral keys generated at each
ddev start. - No Docker socket access is required in the agents workflow.
- Keys are distributed into containers during startup and are not persisted on host by default.
.agents/README.md.
Drupal core updates
Drupal core updates
- Updating Drupal core.
- Altering scaffold files (e.g.,
robots.txt,.htaccess).
Varnish and Purge configuration
Varnish and Purge configuration
This section describes how to set up Varnish caching and Purge functionality in your local development environment.
Note: Drush commands in this section should be run with the appropriate environment prefix (ddev).
Configuration Overview
The project includes ready-to-use Varnish configuration:
- Configuration Import (Recommended)
config/sync:
drush cim -y
- This applies all Purge and Varnish settings, including processors and purgers
- Manual Configuration (for new sites)
a. Install required modules:
drush en purge purgedrush purgeprocessorlateruntime purgequeuercoretags purgetokens purgeui varnishpurger varnishpurgetags -y
b. Configure Varnish Purger: - Set a value for Browser and proxy cache maximum age in admin/config/development/performance - Navigate to /admin/config/development/performance/purge - Click Add purger and select Varnish Purger: - Name: "Varnish Purger" - Type: "Tags" - Request method: "BAN" (important: use BAN instead of PURGE for compatibility with Silta) - Headers: Cache-Tags: [invalidation:expression] - Save the configuration
c. Configure processors: - Go to /admin/config/development/performance/purge/processors - Ensure these processors are enabled: - drushpurgeinvalidate (for manual invalidation via Drush) - lateruntime (for batching invalidations) - purgeuiblock_processor (for admin UI functionality)
d. Export the configuration:
drush cex -y
e. Update settings.php: - Find the purger ID in varnishpurger.settings.<PURGERID>.yml - Update web/sites/default/settings.php with the correct purger ID:
if (getenv('VARNISHADMINHOST')) {
$config['varnishpurger.settings.<PURGERID>']['hostname'] = trim(getenv('VARNISHADMINHOST'));
$config['varnishpurger.settings.<PURGERID>']['port'] = getenv('VARNISHADMINPORT') ? trim(getenv('VARNISHADMINPORT')) : '80';
}
Environment-Specific Setup
DDEV (Recommended)
- Varnish Configuration: DDEV comes pre-configured with Varnish in
.ddevfolder.
- Testing Configuration:
ddev drush cr
ddev exec curl -X BAN -H "Cache-Tags: config:system.performance" http://varnish
If working correctly, you should receive a "200 Ban added" response
- Viewing Varnish logs:
ddev exec -s varnish varnishlog -i BAN -i Cache
Important Notes
- BAN vs PURGE Method: Always use the "BAN" method in the Varnish purger configuration instead of "PURGE". The Silta Varnish configuration is set up to handle BAN requests but may reject PURGE requests with "405 Method Not Allowed" errors.
- Processors: The default Purge setup uses the
purgeprocessorlateruntimemodule, which empties the purge queue during page requests. This works well for most sites needing immediate cache clearing. Ensure all required processors are enabled.
- Cache Tags: The Varnish configuration is set up to handle cache tag invalidation with the
Cache-Tagsheader.
Testing
Testing
PHPUnit (unit & integration tests)
The PHPUnit test framework is predefined in this project. See phpunit.xml for details. A minified web/modules/custom/phpunitexample module from the examples module is included for learning purposes.
Note: Run these commands with the appropriate environment prefix (ddev phpunit).
- Run one test class:
phpunit path/to/your/class/file.php - List groups:
phpunit --list-groups - Run all tests in a particular group:
phpunit --group Groupname
Playwright (end-to-end tests)
Playwright is used for end-to-end browser testing. Tests are located in the tests/ directory and configured via playwright.config.ts.
Setup
Install Node dependencies if you haven't already:
ddev npm install
Playwright browsers are automatically installed inside the DDEV container on ddev start.
Running tests
The TESTBASEURL environment variable is preconfigured in DDEV (see .ddev/config.yaml).
To run all tests:
ddev npx playwright test
To view the HTML report after a run:
npx playwright show-report
Test structure
tests/helpers/drupal-test.ts— Custom Playwright test base providing adrupalhelper (via@drupal/playwright) for actions likedrupal.loginAsAdmin()tests/example.spec.ts— Example end-to-end test demonstrating basic page creation
Secrets handling
Silta CLI is a command-line tool to manage secrets and configurations for Silta projects. Use the following commands:
- Encrypt a file:
silta secrets encrypt --file silta/silta.secrets --secret-key=<secretkeyenv> - Decrypt a file:
silta secrets decrypt --file silta/silta.secrets --secret-key=<secretkeyenv> - Display help:
silta secrets --help
secretkeyenv values in the .circleci/config.yml file for the siltadev and siltafinland contexts. Refer to the Getting Started section for details.
Contributing
This project is maintained by Wunder. Contributions from the community are welcome.
Commit message validation and ticketing system integration
Commit message validation and ticketing system integration
Commit message validation is enforced by GrumPHP (gitcommitmessage) and requires a ticket ID in the subject. Use one of these formats:
TICKET-123: Capitalized subject
type(TICKET-123): Capitalized subject
Examples:
WNDR-446: Update composer dependencies
fix(WNDR-446): Add Drush 13 PRE_INITIALIZE hook
feat(GH-57): Add release automation command
Rules:
- Ticket format:
PROJECTKEY-123(for exampleWNDR-446,GH-57). - Subject must start with a capital letter after
:. - Allowed types in
type(...):feat,fix,chore,docs,style,refactor,perf,test,ci,build,revert. - Merge commits are excluded from this validation.
Recommended (not required by the matcher):
- Keep body lines as bullet points explaining what and why.
- Add a
Refs:footer with key files.
Git workflow
Refer to the WunderFlow repository for Git workflow details.
Deployments
Deployments are managed with CircleCI. Configurations are in .circleci/config.yml.
- Feature branches require manual approval for deployment by default.
- Other branches deploy automatically but can be configured for manual approval.
approve-deployment job in the CircleCI UI by clicking the "approve-deployment" job label when marked as "Needs Approval."