Development
Typical development process
- Pull the latest changes from the remote repository.
- Fetch the latest database dump from the production environment.
- Build the project.
- Start a new feature or bugfix branch:
- Create a new branch from
develop. - Implement the feature or fix the bug.
- Create a new branch from
- Run tests:
- Run automated tests locally.
- Fix any failing tests.
- Run code quality checks:
- Run static code analysis locally.
- Fix any issues reported.
- Commit changes to the branch and push it to the remote repository.
- Create a pull request:
- Create a pull request from the branch to
develop. - Assign reviewers.
- Wait for the continuous integration pipeline to pass.
- Create a pull request from the branch to
Common commands
The most common day-to-day commands. Each video is a live recording captured on a fresh Vortex project.
Build the project
ahoy build rebuilds the whole stack from scratch: it recreates the
containers, installs the Composer and front-end dependencies, compiles the
theme assets, and provisions the site from the database dump.
Re-provision the site
ahoy provision re-imports the database dump from .data/db.sql into the
running stack and applies the provisioning steps: database updates,
configuration import, cache rebuilds and deploy hooks.
Run linters
ahoy lint runs all the code quality checks: back-end (PHPCS, PHPStan,
Rector), front-end (Twig CS Fixer, ESLint, Stylelint) and test linting
(Gherkin Lint).
Run unit, kernel and functional tests
ahoy test runs all the PHPUnit test suites: unit, kernel, functional and
functional JavaScript.
Run BDD tests
ahoy test-bdd runs the Behat tests against the provisioned site, driving a
real browser inside the container stack.
Running CLI commands
You can run CLI commands inside the project containers.
- Ahoy
- Docker Compose
# Run a command in the CLI container
ahoy cli echo "Hello, World!"
# SSH into the CLI container
ahoy cli
# Run a command in the CLI container
docker compose exec cli echo "Hello, World!"
# SSH into the CLI container
docker compose exec cli bash
You can also use shortcuts for common commands:
- Ahoy
- Docker Compose
# Run Drush command
ahoy drush status
# Run Composer command
ahoy composer install
# Run Drush command
docker compose exec cli drush status
# Run Composer command
docker compose exec cli composer install
Switching branches
When switching to a new branch, there is no need to rebuild the entire project as it may take a long time. Instead, you can run these commands as needed based on what changed:
- Ahoy
- Docker Compose
# Update Composer dependencies (only if composer.json/composer.lock changed)
ahoy composer install
# Rebuild frontend assets (only if theme files changed)
ahoy fe
# Provision site (only if database or configuration changes expected)
ahoy provision
# Update Composer dependencies (only if composer.json/composer.lock changed)
docker compose exec cli composer install
# Rebuild frontend assets (only if theme files changed)
docker compose exec cli bash -c "cd \${WEBROOT}/themes/custom/\${DRUPAL_THEME} && yarn run build"
# Provision site (only if database or configuration changes expected)
docker compose exec cli ./vendor/bin/vortex-provision
Resetting the codebase
To reset the local environment, use the reset command. This will stop and remove
all containers and downloaded dependency packages (vendor, node_modules etc.).
- Ahoy
- Docker Compose
# Reset local environment
ahoy reset
# Fully reset repository to a state as if it was just cloned
ahoy reset --hard
# Reset local environment
docker compose down
./vendor/bin/vortex-reset
# Fully reset repository to a state as if it was just cloned
docker compose down
./vendor/bin/vortex-reset --hard
Environment variables
To update environment variables in your local development environment:
- Edit variables in
.env.localfile - Apply changes by re-creating the containers (a plain restart does not
re-read the
.envfiles):
- Ahoy
- Docker Compose
ahoy up
docker compose up -d
➡️ See Variables for the full variable reference.
Common issues and solutions
Site not loading
- Ahoy
- Docker Compose
ahoy doctor # Check for common issues
ahoy down && ahoy up # Restart containers
ahoy info # Verify URLs and ports
./vendor/bin/vortex-doctor # Check for common issues
docker compose down && docker compose up -d # Restart containers
docker compose exec cli ./vendor/bin/vortex-info # Verify URLs and ports
Database connection errors
- Ahoy
- Docker Compose
docker compose ps # Check if the database container is running
ahoy reset # Last resort: rebuild everything
docker compose ps # Check if the database container is running
docker compose down --volumes && docker compose up -d # Last resort
Permission issues
# Fix file permissions (Linux/Mac)
sudo chown -R $USER:$USER .
Reading logs
- Ahoy
- Docker Compose
# Show container logs
ahoy logs
# Check recent logs of a single container
ahoy logs -- --tail=50 cli
# View Drupal watchdog logs
ahoy drush watchdog:show --count=20
# Show container logs
docker compose logs
# Check recent logs of a single container
docker compose logs --tail=50 cli
# View Drupal watchdog logs
docker compose exec cli drush watchdog:show --count=20
Beyond local development
Expand to see the complete code lifecycle
Local Development
═════════════════════════════════════════════════════════════════════════════════════════
Developer writes code ──► Build and test locally ──► Commit changes
│
▼
Git Repository
═════════════════════════════════════════════════════════════════════════════════════════
Push to remote branch ──► Open/Update Pull Request
│
▼
┌─ CI Pipeline ────────────────────────────────────────────────────────────────────────────┐
│ │
│ ┌─ Database Job (Nightly) ───────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ Scheduled ──► Download production ──► Sanitize database ──► Store database cache │ │
│ │ trigger database Remove sensitive data │ │
│ │ │ │
│ └─────────────────────────────────────┬──────────────────────────────────────────────┘ │
│ │ Provides cached database │
│ ▼ │
│ ┌─ Lint Job ────────────┐ ┌─ Database Job ────────────────┐ ┌─ Audit Job ──────────┐ │
│ │ │ │ ◆ Nightly cache exists? │ │ Composer audit │ │
│ │ Build CLI container │ │ Yes ──► job succeeds │ │ (advisories) │ │
│ │ ▼ │ │ No ──► download, sanitize, │ │ ▼ │ │
│ │ Composer validate │ │ store cache │ │ Gitleaks │ │
│ │ ▼ │ └───────────────┬───────────────┘ │ (committed secrets) │ │
│ │ Composer normalize │ ▼ │ │ │
│ │ ▼ │ ┌─ Build Job ───────────────────┐ │ │ │
│ │ Hadolint │ │ Code assembly │ │ │ │
│ │ ▼ │ │ Docker, Composer deps, │ │ │ │
│ │ DCLint │ │ NPM deps, assets │ │ │ │
│ │ ▼ │ │ ▼ │ │ │ │
│ │ PHPCS │ │ Website setup │ │ │ │
│ │ ▼ │ │ Import cached DB, drush │ │ │ │
│ │ PHPStan │ │ deploy, custom scripts │ │ │ │
│ │ ▼ │ │ ▼ │ │ │ │
│ │ Rector │ │ Testing │ │ │ │
│ │ ▼ │ │ PHPUnit tests ──► Behat tests │ │ │ │
│ │ Twig CS Fixer │ └───────────────┬───────────────┘ │ │ │
│ │ ▼ │ │ │ │ │
│ │ Gherkin Lint │ │ │ │ │
│ │ ▼ │ │ │ │ │
│ │ ESLint / Stylelint │ │ │ │ │
│ │ │ │ │ │ │
│ └──────────┬────────────┘ │ │ │ │
│ │ │ │ │ │
│ ▼ ▼ │ │ │
│ ┌─ Deployment Job ─────────────────────────────────────────┐ │ │ │
│ │ │ │ │ │
│ │ Webhook Artifact Lagoon │ │ Does not gate │ │
│ │ Call URL Package artifact Run Lagoon CLI deploy │ │ deployment │ │
│ │ │ │ │ │
│ └──────────────────────────────────────────────────────────┘ └──────────────────────┘ │
│ │
└──────────────────────────────────────────────────────────────────────────────────────────┘
│
▼
Hosting Platform
═════════════════════════════════════════════════════════════════════════════════════════
◆ Environment ──No──► Sync DB from production ───┐
exists? │
│ Yes ▼
└──────────────────────────────────► drush deploy ──► Custom scripts ──► Notifications
Available Environments
═════════════════════════════════════════════════════════════════════════════════════════
┊ PR Environment ┊ Dev Staging Production
┊ (auto-removed) ┊ develop branch main branch production branch or tag
See also
| Topic | Description |
|---|---|
| Database | Fetching, refreshing, and exporting databases |
| Composer | Managing packages, patching, security auditing |
| Debugging | Xdebug, curl testing, container access |
| PHPUnit | Unit, kernel, and functional testing |
| Behat | Behavior-driven (BDD) testing |
| Jest | JavaScript unit testing |
| Visual regression | Diffy-powered visual regression on deployments |
| AI | The AI agent configuration files |
| FAQs | Answers to common operational questions |
| Variables | The full environment variable reference |