Development Setup
Prerequisites
Section titled “Prerequisites”- PHP 8.5+
- Composer
- Docker (for E2E tests)
- make
Getting Started
Section titled “Getting Started”git clone git@github.com:whatwedo/dde.gitcd ddecomposer installbin/console list # Verify it worksTo use your local development version instead of the installed binary, override the dde command via an alias. Two variants:
Run from sources directly (fastest iteration — every code change is picked up on the next invocation, no build step):
alias dde='~/projects/dde/bin/console'Run the built binary (matches what users get from a release; useful for verifying PHAR-specific behaviour like the pre-warmed cache dir):
make build-binaryalias dde='~/projects/dde/bin/dde'Adjust the path to wherever you cloned the repository. Add the alias to your shell rc (.bashrc, .zshrc, …) to make it permanent.
Quality Assurance
Section titled “Quality Assurance”Run the full QA suite:
make qaThis executes, in order:
- ECS — coding standard check and auto-fix (
make ecs) - PHPStan — static analysis at level 8 (
make phpstan) - Rector — automated refactoring, dry-run mode (
make rector) - Tests — PHPUnit, excluding E2E tests (
make test)
Individual Tools
Section titled “Individual Tools”make ecs # Fix coding standard (whatwedo/php-coding-standard)make phpstan # Run PHPStan level 8 (auto-warms cache)make rector # Run Rector (PHP 8.5 + Symfony 8 rule sets)make test # Run all tests (excludes E2E)make test-e2e # Run E2E tests (requires Docker)make test-unit # Run unit tests onlyBuilding
Section titled “Building”PHAR Binary
Section titled “PHAR Binary”make buildThis produces bin/dde.phar using humbug/box. The actual box compile is wrapped by scripts/compile-phar.sh, the single source of truth for a byte-identical, reproducible PHAR (used by build.sh, the Makefile, and CI) — see Reproducible Builds for the how and why.
PHAR-specific runtime behaviour:
bin/consoledetects the PHAR context viastr_starts_with(__DIR__, 'phar://')and disables Dotenv.KerneloverridesgetCacheDir()/getLogDir()in the PHAR (pre-warmed cache, temp log dir).
Standalone Binary
Section titled “Standalone Binary”make build-binaryThis combines the PHAR with micro.sfx from static-php-cli into a standalone executable. The build script (scripts/build.sh) automates the micro.sfx download and reads the target PHP version from composer.json — the php constraint under require there is the single source of truth for the PHP version, propagated to build.sh and the CI workflows.
Continuous Integration
Section titled “Continuous Integration”.github/workflows/ci.yml runs on every push and pull request: ECS, PHPStan, Rector (dry-run), and tests.
Pitfalls worth knowing:
- CI runs
ecs checkwithout--fix, whilemake ecslocally rewrites files in place. A green localmake qawith a dirty working tree means CI will fail — commit the auto-fixed files. - PHPStan requires a Symfony cache warmup (dev env) before it can analyse the container XML; the
make phpstantarget handles this. - Tests tagged
#[Group('e2e')]require Docker and are excluded from CI (--exclude-group=e2e).
Project Structure
Section titled “Project Structure”src/ Command/ # CLI commands (Project/*, System/*) Manager/ # Business logic orchestration Service/ # System service implementations Config/ # Configuration DTOs and TreeBuilder definitions Model/ # Data models Parser/ # Docker Compose and Dockerfile parsers Modifier/ # Docker Compose persistent modifications Adapter/ # Container entrypoint adapters Database/ # Database adapter implementations Doctor/ # Health check system Event/ # Project lifecycle events Hook/ # Hook execution system Plugin/ # Plugin loading and proxy commands Output/ # Output formatters (Text, JSON) Util/ # Utility classes
tests/ Unit/ # Unit tests (mirrors src/ structure) Integration/ # Integration tests E2E/ # End-to-end tests (require Docker)
resources/ adapters/ # Built-in adapter scripts (nginx, php-fpm, apache) entrypoint.sh # Container entrypoint script docker/ # Dockerfiles for system services